/// <summary> /// Spills the register. /// </summary> /// <param name="active">The active.</param> /// <param name="current">The current.</param> /// <returns></returns> private Register SpillRegister(List <LiveRange> active, LiveRange current) { foreach (LiveRange lr in active) { // Does it make sense to spill this register? if (lr.Reg.IsValidSigType(current.Op.Type)) { // Yes, spill it back to its operand RegisterOperand rop = new RegisterOperand(lr.Op.Type, lr.Reg); // MoveInstruction mi = CreateMoveInstruction(lr.Op, rop); // FIXME PG - hack to allow compile // current.Block.Instructions.Insert(current.Start++, mi); // FIXME PG - hack to allow compile // Load the new value // mi = CreateMoveInstruction(rop, current.Op); // FIXME PG - hack to allow compile // current.Block.Instructions.Insert(current.Start++, mi); // FIXME PG - hack to allow compile // Remove this live range from the active list active.Remove(lr); lr.Start = PickNextUse(lr.Op, current.Start, lr.End); if (lr.Start != -1) { ReinsertSpilledRange(lr); } return(lr.Reg); } } throw new InvalidOperationException(@"Failed to spill a register."); }
/// <summary> /// Assigns the registers. /// </summary> private void AssignRegisters() { List <LiveRange> active = new List <LiveRange>(); _registers = FillRegisterList(); for (int i = 0; i < _liveRanges.Count; i++) { LiveRange lr = _liveRanges[i]; ExpireOldRanges(lr.Start, active); Register reg = AllocateRegister(lr.Op); if (reg == null) { reg = SpillRegister(active, lr); } Debug.Assert(reg != null, @"Failed to allocate a register type."); RegisterOperand rop = new RegisterOperand(lr.Op.Type, reg); ReplaceOperand(lr, rop);; lr.Reg = reg; int insIdx = active.FindIndex(delegate(LiveRange match) { return((lr.End - match.End) > 0); }); active.Insert(insIdx + 1, lr); } }
/// <summary> /// Replaces the operand. /// </summary> /// <param name="lr">The lr.</param> /// <param name="replacement">The replacement.</param> private void ReplaceOperand(LiveRange lr, RegisterOperand replacement) { int opIdx; // Iterate all definition sites first foreach (int index in lr.Op.Definitions.ToArray()) { Context def = new Context(InstructionSet, index); if (def.Offset == lr.Start) { opIdx = 0; foreach (Operand r in def.Results) { // Is this the operand? if (object.ReferenceEquals(r, lr.Op)) { def.SetResult(opIdx, replacement); } opIdx++; } break; } } // Iterate all use sites foreach (int index in lr.Op.Uses.ToArray()) { Context instr = new Context(InstructionSet, index); if (instr.Offset <= lr.Start) { // A use on instr.Offset == lr.Start is one from a previous definition!! } else if (instr.Offset <= lr.End) { opIdx = 0; foreach (Operand r in instr.Operands) { // Is this the operand? if (object.ReferenceEquals(r, lr.Op)) { instr.SetOperand(opIdx, replacement); } opIdx++; } } else { break; } } }
/// <summary> /// Reinserts the spilled range. /// </summary> /// <param name="lr">The lr.</param> private void ReinsertSpilledRange(LiveRange lr) { int index = 0; foreach (LiveRange item in _liveRanges) { if (item.Start > lr.Start) { _liveRanges.Insert(index, lr); break; } index++; } }
/// <summary> /// Expires the old ranges. /// </summary> /// <param name="position">The position.</param> /// <param name="active">The active.</param> private void ExpireOldRanges(int position, List <LiveRange> active) { for (int i = 0; i < active.Count; i++) { LiveRange lr = active[i]; if (lr.End > position) { break; } _registers.Add(lr.Reg); active.RemoveAt(i); i--; } }
public void LiveRangeTest() { var basicBlocks = CreateBasicBlockInstructionSet(); GreedyRegisterAllocator.NumberInstructions(basicBlocks); var liveRange = new LiveRange( new SlotIndex(basicBlocks[0].First), new SlotIndex(basicBlocks[0].Last), new List <SlotIndex>(), new List <SlotIndex>() ); Assert.True(liveRange.IsEmpty); //liveRange.SplitAt(basicBlocks.) }
/// <summary> /// Spills the register. /// </summary> /// <param name="active">The active.</param> /// <param name="current">The current.</param> /// <returns></returns> private Register SpillRegister(List<LiveRange> active, LiveRange current) { foreach (LiveRange lr in active) { // Does it make sense to spill this register? if (lr.Reg.IsValidSigType(current.Op.Type)) { // Yes, spill it back to its operand RegisterOperand rop = new RegisterOperand(lr.Op.Type, lr.Reg); // MoveInstruction mi = CreateMoveInstruction(lr.Op, rop); // FIXME PG - hack to allow compile // current.Block.Instructions.Insert(current.Start++, mi); // FIXME PG - hack to allow compile // Load the new value // mi = CreateMoveInstruction(rop, current.Op); // FIXME PG - hack to allow compile // current.Block.Instructions.Insert(current.Start++, mi); // FIXME PG - hack to allow compile // Remove this live range from the active list active.Remove(lr); lr.Start = PickNextUse(lr.Op, current.Start, lr.End); if (lr.Start != -1) ReinsertSpilledRange(lr); return lr.Reg; } } throw new InvalidOperationException(@"Failed to spill a register."); }
/// <summary> /// Replaces the operand. /// </summary> /// <param name="lr">The lr.</param> /// <param name="replacement">The replacement.</param> private void ReplaceOperand(LiveRange lr, RegisterOperand replacement) { int opIdx; // Iterate all definition sites first foreach (int index in lr.Op.Definitions.ToArray()) { Context def = new Context(instructionSet, index); if (def.Offset == lr.Start) { opIdx = 0; foreach (Operand r in def.Results) { // Is this the operand? if (object.ReferenceEquals(r, lr.Op)) def.SetResult(opIdx, replacement); opIdx++; } break; } } // Iterate all use sites foreach (int index in lr.Op.Uses.ToArray()) { Context instr = new Context(instructionSet, index); if (instr.Offset <= lr.Start) { // A use on instr.Offset == lr.Start is one from a previous definition!! } else if (instr.Offset <= lr.End) { opIdx = 0; foreach (Operand r in instr.Operands) { // Is this the operand? if (object.ReferenceEquals(r, lr.Op)) instr.SetOperand(opIdx, replacement); opIdx++; } } else { break; } } }
public void AddRange(LiveRange liveRange) { liveRanges.Add(liveRange); }