public Interval(SlotIndex start, SlotIndex end) { Debug.Assert(start <= end); this.Start = start; this.End = end; }
public MoveHint(SlotIndex slot, VirtualRegister from, VirtualRegister to, int bonus) { Slot = slot; From = from; To = to; Bonus = bonus; }
private LiveInterval(VirtualRegister virtualRegister, SlotIndex start, SlotIndex end, IList<SlotIndex> uses, IList<SlotIndex> defs) { LiveRange = new LiveRange(start, end, uses, defs); VirtualRegister = virtualRegister; SpillValue = 0; Stage = AllocationStage.Initial; ForceSpilled = false; NeverSpill = false; }
public LiveRange(SlotIndex start, SlotIndex end, IList<SlotIndex> uses, IList<SlotIndex> defs) : base(start, end) { // live intervals can not start/end at the same location Debug.Assert(start != end); SlotIndex max = null; SlotIndex min = null; foreach (var use in uses) { if (use != Start && (End == use || Contains(use))) { usePositions.Add(use, use); if (max == null || use > max) max = use; if (min == null || use < min) min = use; } } foreach (var def in defs) { if (Contains(def)) { defPositions.Add(def, def); if (max == null || def > max) max = def; if (min == null || def < min) min = def; } } Minimum = min; Maximum = max; if (FirstDef == null) IsDefFirst = false; else if (FirstUse == null) IsDefFirst = true; else if (FirstDef < FirstUse) IsDefFirst = true; }
private LiveInterval(VirtualRegister virtualRegister, SlotIndex start, SlotIndex end, IList<SlotIndex> uses, IList<SlotIndex> defs) : base(start, end) { this.VirtualRegister = virtualRegister; this.SpillValue = 0; this.Stage = AllocationStage.Initial; this.ForceSpilled = false; this.NeverSpill = false; SlotIndex max = null; SlotIndex min = null; foreach (var use in uses) { if (Contains(use)) { usePositions.Add(use, use); if (max == null || use > max) max = use; if (min == null || use < min) min = use; } } foreach (var def in defs) { if (Contains(def)) { defPositions.Add(def, def); if (max == null || def > max) max = def; if (min == null || def < min) min = def; } } this.Minimum = min; this.Maximum = max; }
private void NumberInstructions() { var number = new CompilerTrace(trace, "InstructionNumber"); int index = SlotIncrement; foreach (BasicBlock block in basicBlocks) { for (Context context = new Context(instructionSet, block); ; context.GotoNext()) { if (!context.IsEmpty) { context.SlotNumber = index; index = index + SlotIncrement; if (number.Active) { if (context.IsBlockStartInstruction) { number.Log(context.SlotNumber.ToString() + " = " + context.ToString() + " # " + block.ToString()); } else { number.Log(context.SlotNumber.ToString() + " = " + context.ToString()); } } } if (context.IsBlockEndInstruction) break; } SlotIndex start = new SlotIndex(instructionSet, block.StartIndex); SlotIndex end = new SlotIndex(instructionSet, block.EndIndex); extendedBlocks[block.Sequence].Interval = new Interval(start, end); } }
private SlotIndex GetHighOptimalSplitLocation(LiveInterval liveInterval, SlotIndex after, bool check) { Debug.Assert(liveInterval.End != after); if (trace.Active) trace.Log("--High Splitting: " + liveInterval.ToString() + " move: " + after.ToString()); SlotIndex blockEnd = GetBlockEnd(after); if (trace.Active) trace.Log(" Block End : " + blockEnd.ToString()); SlotIndex higherBound = blockEnd < liveInterval.End ? blockEnd : liveInterval.End.Previous; if (trace.Active) trace.Log(" Higher Bound: " + higherBound.ToString()); SlotIndex nextUse = liveInterval.GetNextDefOrUsePosition(after); if (trace.Active) trace.Log(" Next Use : " + (nextUse != null ? nextUse.ToString() : "null")); if (nextUse != null && nextUse <= higherBound) { if (trace.Active) trace.Log(" High Optimal: " + nextUse.Previous.ToString()); return nextUse; } if (trace.Active) trace.Log(" High Optimal: " + higherBound.ToString()); return higherBound; }
private SlotIndex GetLowOptimalSplitLocation(LiveInterval liveInterval, SlotIndex from, bool check) { Debug.Assert(liveInterval.Start != from); if (trace.Active) trace.Log("--Low Splitting: " + liveInterval.ToString() + " move: " + from.ToString()); if (check) { if (liveInterval.UsePositions.Contains(from) || liveInterval.DefPositions.Contains(from)) { if (trace.Active) trace.Log(" No optimal. Split move: " + from.ToString()); return from; } } SlotIndex blockStart = GetBlockStart(from); if (trace.Active) trace.Log(" Block Start : " + blockStart.ToString()); SlotIndex lowerBound = blockStart > liveInterval.Start ? blockStart : liveInterval.Start.Next; if (trace.Active) trace.Log(" Lower Bound : " + lowerBound.ToString()); SlotIndex previousUse = liveInterval.GetPreviousDefOrUsePosition(from); if (trace.Active) trace.Log(" Previous Use: " + (previousUse != null ? previousUse.ToString() : "null")); if (previousUse != null && previousUse >= lowerBound) { if (trace.Active) trace.Log(" Low Optimal : " + previousUse.Next.ToString()); return previousUse.Next; } if (trace.Active) trace.Log(" Low Optimal : " + lowerBound.ToString()); return lowerBound; }
private void CollectMoveHints() { foreach (var block in basicBlocks) { for (Context context = new Context(instructionSet, block); !context.IsBlockEndInstruction; context.GotoNext()) { if (context.IsEmpty || context.IsBlockStartInstruction || context.IsBlockEndInstruction) continue; if (!architecture.IsInstructionMove(context.Instruction)) continue; var from = virtualRegisters[GetIndex(context.Operand1)]; var to = virtualRegisters[GetIndex(context.Result)]; if (from.IsPhysicalRegister && to.IsPhysicalRegister) continue; var slot = new SlotIndex(context); int factor = (from.IsPhysicalRegister || to.IsPhysicalRegister) ? 150 : 125; int bonus = GetLoopDepth(slot); moveHints.Add(slot, new MoveHint(slot, from, to, bonus)); } } }
private SlotIndex GetBlockStart(SlotIndex slotIndex) { return GetContainingBlock(slotIndex).Start; }
private bool PreferBlockBoundaryIntervalSplit(LiveInterval liveInterval, SlotIndex at, bool addToQueue) { var low = GetLowerOptimalSplitLocation(liveInterval, at); var high = GetUpperOptimalSplitLocation(liveInterval, at); IList<LiveInterval> intervals; if (liveInterval.Start == low) { if (!liveInterval.LiveRange.CanSplitAt(high)) return false; intervals = liveInterval.SplitAt(high); } else if (high == liveInterval.End) { if (!liveInterval.LiveRange.CanSplitAt(low)) return false; intervals = liveInterval.SplitAt(low); } else { if (!liveInterval.LiveRange.CanSplitAt(low, high)) { return false; } intervals = liveInterval.SplitAt(low, high); } ReplaceIntervals(liveInterval, intervals, addToQueue); return true; }
private int GetSpillCost(SlotIndex use, int factor) { return factor * GetLoopDepth(use) * 100; }
public SlotIndex GetPreviousDefPosition(SlotIndex at) { return(GetPrevious(DefPositions, at)); }
protected virtual void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite) { }
public bool Contains(SlotIndex start) { return(LiveRange.Contains(start)); }
public LiveInterval(VirtualRegister virtualRegister, SlotIndex start, SlotIndex end) : this(virtualRegister, start, end, virtualRegister.UsePositions, virtualRegister.DefPositions) { }
public bool Intersects(SlotIndex start, SlotIndex end) { return(LiveRange.Intersects(start, end)); }
public bool IsAdjacent(SlotIndex start, SlotIndex end) { return(LiveRange.IsAdjacent(start, end)); }
private int GetSpillCost(SlotIndex use, int factor) { return(factor * GetLoopDepth(use) * 100); }
private bool TrySimplePartialFreeIntervalSplit(LiveInterval liveInterval) { SlotIndex furthestUsed = null; foreach (var track in LiveIntervalTracks) { if (track.IsReserved) { continue; } if (track.IsFloatingPoint != liveInterval.VirtualRegister.IsFloatingPoint) { continue; } var next = track.GetNextLiveRange(liveInterval.Start); if (next == null) { continue; } Debug.Assert(next > liveInterval.Start); if (Trace.Active) { Trace.Log(" Register " + track + " free up to " + next); } if (furthestUsed == null || furthestUsed < next) { furthestUsed = next; } } if (furthestUsed == null) { if (Trace.Active) { Trace.Log(" No partial free space available"); } return(false); } if (furthestUsed < liveInterval.Minimum) { if (Trace.Active) { Trace.Log(" No partial free space available"); } return(false); } if (furthestUsed.IsBlockStartInstruction) { return(false); } if (furthestUsed <= liveInterval.Start) { if (Trace.Active) { Trace.Log(" No partial free space available"); } return(false); } if (Trace.Active) { Trace.Log(" Partial free up destination: " + furthestUsed); } if (liveInterval.UsePositions.Contains(furthestUsed) && liveInterval.Contains(furthestUsed.HalfStepBack)) { furthestUsed = furthestUsed.HalfStepBack; } return(PreferBlockBoundaryIntervalSplit(liveInterval, furthestUsed, true)); }
protected override void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite) { PreferBlockBoundaryIntervalSplit(liveInterval, callSite, false); }
public IList<LiveInterval> SplitAt(SlotIndex low, SlotIndex high) { var liveRanges = LiveRange.SplitAt(low, high); var intervals = new List<LiveInterval>(liveRanges.Count); foreach (var liveRange in liveRanges) { intervals.Add(CreateSplit(liveRange)); } return intervals; }
public bool Contains(SlotIndex at) { return(at >= Start && at < End); }
private SlotIndex GetUpperOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { if (Trace.Active) Trace.Log("--High Splitting: " + liveInterval.ToString() + " move: " + at.ToString()); var a = liveInterval.End; var blockEnd = GetBlockEnd(at); var b = blockEnd > liveInterval.End ? blockEnd : null; if (Trace.Active) Trace.Log(" Block End : " + (b != null ? b.ToString() : "null")); var c = liveInterval.LiveRange.GetNextUsePosition(at); if (c != null && c.HalfStepBack > at) c = c.HalfStepBack; if (Trace.Active) Trace.Log(" Next Use : " + (c != null ? c.ToString() : "null")); var d = liveInterval.LiveRange.GetNextDefPosition(at); if (Trace.Active) Trace.Log(" Next Def : " + (d != null ? d.ToString() : "null")); var min = GetMinimum(a, b, c, d); if (Trace.Active) Trace.Log(" High Optimal : " + min.ToString()); return min; }
public bool IsAdjacent(SlotIndex start, SlotIndex end) { return(start == End || end == Start); }
public bool Intersects(SlotIndex start, SlotIndex end) { return((Start <= start && End > start) || (start <= Start && end > Start)); }
private void BuildLiveIntervals() { var intervalTrace = new CompilerTrace(trace, "BuildLiveIntervals"); for (int b = basicBlocks.Count - 1; b >= 0; b--) { var block = extendedBlocks[b]; for (int r = 0; r < registerCount; r++) { if (!block.LiveOut.Get(r)) continue; var register = virtualRegisters[r]; if (b + 1 != basicBlocks.Count && extendedBlocks[b + 1].LiveIn.Get(r)) { if (intervalTrace.Active) intervalTrace.Log("Add (LiveOut) " + register.ToString() + " : " + block.Start + " to " + extendedBlocks[b + 1].Start); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Start, extendedBlocks[b + 1].Start); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } else { if (intervalTrace.Active) intervalTrace.Log("Add (!LiveOut) " + register.ToString() + " : " + block.Interval.Start + " to " + block.Interval.End); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Interval); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } Context context = new Context(instructionSet, block.BasicBlock, block.BasicBlock.EndIndex); while (!context.IsBlockStartInstruction) { if (!context.IsEmpty) { SlotIndex slotIndex = new SlotIndex(context); OperandVisitor visitor = new OperandVisitor(context); if (context.Instruction.FlowControl == FlowControl.Call) { SlotIndex nextSlotIndex = slotIndex.Next; for (int s = 0; s < physicalRegisterCount; s++) { var register = virtualRegisters[s]; if (intervalTrace.Active) intervalTrace.Log("Add (Call) " + register.ToString() + " : " + slotIndex + " to " + nextSlotIndex); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(slotIndex, nextSlotIndex); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } callSlots.Add(slotIndex); } foreach (var result in visitor.Output) { var register = virtualRegisters[GetIndex(result)]; if (register.IsReserved) continue; var first = register.FirstRange; if (!register.IsPhysicalRegister) { register.AddDefPosition(slotIndex); } if (first != null) { if (intervalTrace.Active) intervalTrace.Log("Replace First " + register.ToString() + " : " + slotIndex + " to " + first.End); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.FirstRange = new LiveInterval(register, slotIndex, first.End); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } else { // This is necesary to handled a result that is never used! // Common with instructions which more than one result if (intervalTrace.Active) intervalTrace.Log("Add (Unused) " + register.ToString() + " : " + slotIndex + " to " + slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(slotIndex, slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } foreach (var result in visitor.Input) { var register = virtualRegisters[GetIndex(result)]; if (register.IsReserved) continue; if (!register.IsPhysicalRegister) { register.AddUsePosition(slotIndex); } if (intervalTrace.Active) intervalTrace.Log("Add (normal) " + register.ToString() + " : " + block.Start + " to " + slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Start, slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } context.GotoPrevious(); } } }
public SlotIndex GetNextUsePosition(SlotIndex at) { return(GetNext(UsePositions, at)); }
private SlotIndex GetBlockEnd(SlotIndex slotIndex) { return GetContainingBlock(slotIndex).End; }
public SlotIndex GetNextDefPosition(SlotIndex at) { return(GetNext(DefPositions, at)); }
private ExtendedBlock GetContainingBlock(SlotIndex slotIndex) { foreach (var block in extendedBlocks) { if (block.Contains(slotIndex)) { return block; } } Debug.Assert(false, "GetContainingBlock"); return null; }
public bool Contains(SlotIndex slotIndex) { return(slotIndex >= Start && slotIndex < End); }
private int GetLoopDepth(SlotIndex slotIndex) { return GetContainingBlock(slotIndex).LoopDepth + 1; }
private int GetSpillCost(SlotIndex use, int factor) { return (factor * SlotIncrement) * GetLoopDepth(use) * 100; }
public LiveInterval CreateExpandedLiveRange(SlotIndex start, SlotIndex end) { var mergedStart = Start < start ? Start : start; var mergedEnd = End > end ? End : end; return new LiveInterval(VirtualRegister, mergedStart, mergedEnd); }
public bool IsAdjacent(SlotIndex start, SlotIndex end) { return LiveRange.IsAdjacent(start, end); }
public SlotIndex GetPreviousUsePosition(SlotIndex at) { return(GetPrevious(UsePositions, at)); }
public bool Contains(SlotIndex start) { return LiveRange.Contains(start); }
public bool Intersects(SlotIndex start, SlotIndex end) { return LiveRange.Intersects(start, end); }
private SlotIndex GetLowerOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { if (Trace.Active) Trace.Log("--Low Splitting: " + liveInterval.ToString() + " move: " + at.ToString()); //a = liveInterval.Start.IsOnHalfStep ? liveInterval.Start : liveInterval.Start.HalfStepForward; var a = liveInterval.Start; var blockStart = GetBlockStart(at); var b = blockStart > liveInterval.Start ? blockStart : null; if (Trace.Active) Trace.Log(" Block Start : " + (b != null ? b.ToString() : "null")); var c = liveInterval.LiveRange.GetPreviousUsePosition(at); if (c != null && c.HalfStepForward <= at) c = c.HalfStepForward; if (Trace.Active) Trace.Log(" Previous Use : " + (c != null ? c.ToString() : "null")); var d = liveInterval.LiveRange.GetPreviousDefPosition(at); if (d != null && d.HalfStepForward <= at) d = d.HalfStepForward; if (Trace.Active) Trace.Log(" Previous Def : " + (d != null ? d.ToString() : "null")); var max = GetMaximum(a, b, c, d); if (Trace.Active) Trace.Log(" Low Optimal : " + max.ToString()); return max; }
private SlotIndex GetMaximum(SlotIndex a, SlotIndex b, SlotIndex c, SlotIndex d) { var max = a; if (max == null || (b != null && b > max)) max = b; if (max == null || (c != null && c > max)) max = c; if (max == null || (d != null && d > max)) max = d; return max; }
private SlotIndex GetMinimum(SlotIndex a, SlotIndex b, SlotIndex c, SlotIndex d) { var min = a; if (min == null || (b != null && b < min)) min = b; if (min == null || (c != null && c < min)) min = c; if (min == null || (d != null && d < min)) min = d; return min; }
public bool Contains(SlotIndex slotIndex) { return Interval.Contains(slotIndex) || slotIndex == Interval.End; }
public LiveRange(SlotIndex start, SlotIndex end, VirtualRegister virtualRegister, int startIndex = 0, int endIndex = Int32.MaxValue) { VirtualRegister = virtualRegister; Start = start; End = end; if (virtualRegister.IsPhysicalRegister) { return; } int lastUseIndex = -1; int firstUseIndex = -1; int lastDefIndex = -1; int firstDefIndex = -1; int useCount = 0; int defCount = 0; for (int i = startIndex; i < virtualRegister.UsePositions.Count && i <= endIndex; i++) { var use = virtualRegister.UsePositions[i]; if (use > end) { break; } if (use > start) // && (use <= end) { if (firstUseIndex < 0) { firstUseIndex = i; } useCount++; lastUseIndex = i; } } for (int i = startIndex; i < virtualRegister.DefPositions.Count && i <= endIndex; i++) { var def = virtualRegister.DefPositions[i]; if (def >= end) { break; } if (def >= start) // && (def < end) { if (firstDefIndex < 0) { firstDefIndex = i; } defCount++; lastDefIndex = i; } } StartIndex = LowestGreaterThanZero(firstUseIndex, firstDefIndex); EndIndex = Math.Max(lastUseIndex, lastDefIndex); FirstUseIndex = firstUseIndex; LastUseIndex = lastUseIndex; FirstDefIndex = firstDefIndex; LastDefIndex = lastDefIndex; UseCount = useCount; DefCount = defCount; IsEmpty = useCount + defCount == 0; FirstUse = useCount == 0 ? SlotIndex.NullSlot : VirtualRegister.UsePositions[firstUseIndex]; FirstDef = defCount == 0 ? SlotIndex.NullSlot : VirtualRegister.DefPositions[firstDefIndex]; LastUse = useCount == 0 ? SlotIndex.NullSlot : VirtualRegister.UsePositions[lastUseIndex]; LastDef = defCount == 0 ? SlotIndex.NullSlot : VirtualRegister.DefPositions[lastDefIndex]; First = (useCount == 0 || firstDefIndex < firstUseIndex) ? FirstDef : FirstUse; Last = (useCount == 0 || lastDefIndex > lastUseIndex) ? LastDef : LastUse; IsDefFirst = defCount != 0 && (useCount == 0 || FirstDefIndex < FirstUseIndex); //Debug.Assert(InternalValidation()); }