private bool PlaceLiveIntervalOnTrack(LiveInterval liveInterval, MoveHint[] hints) { if (hints == null) { return(false); } foreach (var moveHint in hints) { var register = (liveInterval.Start == moveHint.Slot) ? moveHint.FromRegister : moveHint.ToRegister; if (register == null) { continue; // no usable hint } Trace?.Log($" Trying move hint: {register} [ {moveHint} ]"); if (PlaceLiveIntervalOnTrack(liveInterval, LiveIntervalTracks[register.Index])) { return(true); } } return(false); }
private bool PlaceLiveIntervalOnTrack(LiveInterval liveInterval, MoveHint[] hints) { if (hints == null) { return(false); } foreach (var moveHint in hints) { LiveIntervalTrack track = null; var register = (liveInterval.Start == moveHint.Slot) ? moveHint.FromRegister : moveHint.ToRegister; if (register == null) { continue; // no usable hint } if (Trace.Active) { Trace.Log(" Trying move hint: " + register + " [ " + moveHint + " ]"); } if (PlaceLiveIntervalOnTrack(liveInterval, LiveIntervalTracks[register.Index])) { return(true); } } return(false); }
protected override bool TrySplitInterval(LiveInterval liveInterval, int level) { //if (level <= 1) // return false; if (liveInterval.IsEmpty) { return(false); } if (TrySimplePartialFreeIntervalSplit(liveInterval)) { return(true); } if (level <= 1) { return(false); } //if (IntervalSplitAtFirstUseOrDef(liveInterval)) // return true; return(false); }
public void Add(LiveInterval liveInterval) { Debug.Assert(!Intersects(liveInterval)); liveIntervals.Add(liveInterval); liveInterval.LiveIntervalTrack = this; }
public void Evict(LiveInterval liveInterval) { intervals.Remove(liveInterval.StartValue, liveInterval.EndValue); Debug.Assert(!intervals.Contains(liveInterval.StartValue, liveInterval.EndValue)); liveInterval.LiveIntervalTrack = null; }
public void Add(LiveInterval liveInterval) { Debug.Assert(!intervals.Contains(liveInterval.StartValue, liveInterval.EndValue)); intervals.Add(liveInterval.StartValue, liveInterval.EndValue, liveInterval); liveInterval.LiveIntervalTrack = this; }
public void Add(LiveInterval liveInterval) { Debug.Assert(!Intersects(liveInterval)); liveIntervals.Add(liveInterval); liveInterval.LiveIntervalTrack = this; }
public LiveInterval CreateExpandedLiveInterval(LiveInterval interval) { Debug.Assert(VirtualRegister == interval.VirtualRegister); var start = Start < interval.Start ? Start : interval.Start; var end = End > interval.End ? End : interval.End; return(new LiveInterval(VirtualRegister, start, end)); }
public void ReplaceWithSplit(LiveInterval source, IList <LiveInterval> liveIntervals) { Remove(source); foreach (var liveInterval in liveIntervals) { Add(liveInterval); } }
private void UpdateMoveHints(LiveInterval liveInterval) { if (moveHints.TryGetValue(liveInterval.Start, out MoveHint MoveHint)) { MoveHint.Update(liveInterval); } if (moveHints.TryGetValue(liveInterval.End, out MoveHint)) { MoveHint.Update(liveInterval); } }
public bool Intersects(LiveInterval liveInterval) { foreach (var interval in liveIntervals) { if (interval.Intersects(liveInterval)) { return(true); } } return(false); }
private SlotIndex GetLowerOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { if (Trace.Active) { Trace.Log("--Low Splitting: " + liveInterval + " move: " + at); } //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); } return(max); }
/// <summary> /// Gets the intersections. /// </summary> /// <param name="liveInterval">The live interval.</param> /// <returns></returns> public List <LiveInterval> GetIntersections(LiveInterval liveInterval) { List <LiveInterval> intersections = null; foreach (var interval in liveIntervals) { if (interval.Intersects(liveInterval)) { (intersections ?? (intersections = new List <LiveInterval>())).Add(interval); } } return(intersections); }
public void Update(LiveInterval interval) { var updateInterval = interval.AssignedPhysicalRegister == null ? null : interval; if (interval.VirtualRegister == From) { FromInterval = updateInterval; } if (interval.VirtualRegister == To) { ToInterval = updateInterval; } }
private MoveHint[] GetMoveHints(LiveInterval liveInterval) { MoveHint startMoveHint = null; MoveHint endMoveHint = null; moveHints.TryGetValue(liveInterval.Start, out startMoveHint); if (!liveInterval.End.IsBlockStartInstruction) { moveHints.TryGetValue(liveInterval.End, out endMoveHint); } int cnt = (startMoveHint == null ? 0 : 1) + (endMoveHint == null ? 0 : 1); if (cnt == 0) { return(null); } var hints = new MoveHint[cnt]; if (startMoveHint != null && endMoveHint != null) { // sorted by bonus if (startMoveHint.Bonus > endMoveHint.Bonus) { hints[0] = startMoveHint; hints[1] = endMoveHint; } else { hints[0] = endMoveHint; hints[1] = startMoveHint; } } else { if (startMoveHint != null) { hints[0] = startMoveHint; } else { hints[0] = endMoveHint; } } return(hints); }
protected override bool PlaceLiveInterval(LiveInterval liveInterval) { // For now, empty intervals will stay spilled if (liveInterval.IsEmpty) { if (Trace.Active) { Trace.Log(" Spilled"); } liveInterval.VirtualRegister.IsSpilled = true; AddSpilledInterval(liveInterval); return(true); } var moveHints = GetMoveHints(liveInterval); // Try to place using move hints first if (PlaceLiveIntervalOnTrack(liveInterval, moveHints)) { UpdateMoveHints(liveInterval, moveHints); return(true); } // TODO - try move hints first, allow evictions // Find any available track and place interval there if (PlaceLiveIntervalOnAnyAvailableTrack(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return(true); } if (Trace.Active) { Trace.Log(" No free register available"); } // No place for live interval; find live interval(s) to evict based on spill costs if (PlaceLiveIntervalOnTrackAllowEvictions(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return(true); } return(false); }
private void UpdateMoveHints(LiveInterval liveInterval, MoveHint[] moveHints) { if (moveHints == null) { return; } if (moveHints.Length >= 1) { moveHints[0].Update(liveInterval); } else if (moveHints.Length >= 2) { moveHints[1].Update(liveInterval); } }
protected override void CalculateSpillCost(LiveInterval liveInterval) { int spillvalue = 0; foreach (var use in liveInterval.UsePositions) { spillvalue += GetSpillCost(use, 100); } foreach (var use in liveInterval.DefPositions) { spillvalue += GetSpillCost(use, 115); } liveInterval.SpillValue = spillvalue; }
protected override void CalculateSpillCost(LiveInterval liveInterval) { int spillvalue = 0; foreach (var use in liveInterval.UsePositions) { spillvalue += GetSpillCost(use, 100); } foreach (var use in liveInterval.DefPositions) { spillvalue += GetSpillCost(use, 115); } liveInterval.SpillValue = spillvalue; }
/// <summary> /// Gets the intersections. /// </summary> /// <param name="liveInterval">The live interval.</param> /// <returns></returns> public List<LiveInterval> GetIntersections(LiveInterval liveInterval) { List<LiveInterval> intersections = null; foreach (var interval in liveIntervals) { if (interval.Intersects(liveInterval)) { if (intersections == null) intersections = new List<LiveInterval>(); intersections.Add(interval); } } return intersections; }
private SlotIndex GetUpperOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { if (Trace.Active) { Trace.Log("--High Splitting: " + liveInterval + " move: " + at); } 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); } return(min); }
private bool PreferBlockBoundaryIntervalSplit(LiveInterval liveInterval, SlotIndex at, bool addToQueue) { var low = GetLowerOptimalSplitLocation(liveInterval, at); var high = GetUpperOptimalSplitLocation(liveInterval, at); List <LiveInterval> intervals; if (low.IsNull && high.IsNotNull) { if (!liveInterval.LiveRange.CanSplitAt(high)) { return(false); } intervals = liveInterval.SplitAt(high); } else if (high.IsNull && low.IsNotNull) { if (!liveInterval.LiveRange.CanSplitAt(low)) { return(false); } intervals = liveInterval.SplitAt(low); } else if (low.IsNotNull && high.IsNotNull) { if (!liveInterval.LiveRange.CanSplitAt(low, high)) { return(false); } intervals = liveInterval.SplitAt(low, high); } else { return(false); } ReplaceIntervals(liveInterval, intervals, addToQueue); return(true); }
protected override bool PlaceLiveInterval(LiveInterval liveInterval) { // For now, empty intervals will stay spilled if (liveInterval.IsEmpty) { if (Trace.Active) Trace.Log(" Spilled"); liveInterval.VirtualRegister.IsSpilled = true; AddSpilledInterval(liveInterval); return true; } var moveHints = GetMoveHints(liveInterval); // Try to place using move hints first if (PlaceLiveIntervalOnTrack(liveInterval, moveHints)) { UpdateMoveHints(liveInterval, moveHints); return true; } // TODO - try move hints first, allow evictions // Find any available track and place interval there if (PlaceLiveIntervalOnAnyAvailableTrack(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return true; } if (Trace.Active) Trace.Log(" No free register available"); // No place for live interval; find live interval(s) to evict based on spill costs if (PlaceLiveIntervalOnTrackAllowEvictions(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return true; } return false; }
private bool IntervalSplitAtFirstUseOrDef(LiveInterval liveInterval) { if (liveInterval.IsEmpty) { return(false); } SlotIndex at = null; var firstUse = liveInterval.UsePositions.Count != 0 ? liveInterval.UsePositions[0] : null; var firstDef = liveInterval.DefPositions.Count != 0 ? liveInterval.DefPositions[0] : null; if (at == null) { at = firstUse; } if (at != null && firstDef != null && firstDef < at) { at = firstDef; } if (at >= liveInterval.End) { return(false); } if (at <= liveInterval.Start) { return(false); } if (Trace.Active) { Trace.Log(" Splitting around first use/def"); } return(PreferBlockBoundaryIntervalSplit(liveInterval, at, true)); }
private SlotIndex GetLowerOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { Trace?.Log($"--Low Splitting: {liveInterval} at: {at}"); var max = SlotIndex.NullSlot; var blockStart = GetBlockStart(at); Trace?.Log($" Block Start : {blockStart}"); if (blockStart < at && blockStart > liveInterval.Start) { max = blockStart; } var prevUse = liveInterval.LiveRange.GetPreviousUsePosition(at); Trace?.Log($" Previous Use : {prevUse}"); if (prevUse.IsNotNull && prevUse.After < at && (max.IsNull || prevUse.After > max)) { max = prevUse.After; } var prevDef = liveInterval.LiveRange.GetPreviousDefPosition(at); Trace?.Log($" Previous Def : {prevDef}"); if (prevDef.IsNotNull && prevDef.After < at && (max.IsNull || prevDef.After > max)) { max = prevDef.After; } Trace?.Log($" Low Optimal : {max}"); return(max); }
private SlotIndex GetUpperOptimalSplitLocation(LiveInterval liveInterval, SlotIndex at) { Trace?.Log($"--High Splitting: {liveInterval} at: {at}"); var min = SlotIndex.NullSlot; var blockEnd = GetBlockEnd(at); Trace?.Log($" Block End : {blockEnd}"); if (blockEnd > at && blockEnd < liveInterval.End) { min = blockEnd; } var nextUse = liveInterval.LiveRange.GetNextUsePosition(at); Trace?.Log($" Next Use : {nextUse}"); if (nextUse.IsNotNull && nextUse.Before > at && (min.IsNull || nextUse.Before < min)) { min = nextUse.Before; } var nextDef = liveInterval.LiveRange.GetNextDefPosition(at); Trace?.Log($" Next Def : {nextDef}"); if (nextDef.IsNotNull && nextDef > at && (min.IsNull || nextDef < min)) { min = nextDef; } Trace?.Log($" High Optimal : {min}"); return(min); }
private bool IntervalSplitAtFirstUseOrDef(LiveInterval liveInterval) { if (liveInterval.IsEmpty) { return(false); } var at = SlotIndex.NullSlot; var firstUse = liveInterval.LiveRange.FirstUse; var firstDef = liveInterval.LiveRange.FirstDef; if (at.IsNull) { at = firstUse; } if (at.IsNotNull && firstDef.IsNotNull && firstDef < at) { at = firstDef; } if (at >= liveInterval.End) { return(false); } if (at <= liveInterval.Start) { return(false); } Trace?.Log(" Splitting around first use/def"); return(PreferBlockBoundaryIntervalSplit(liveInterval, at, true)); }
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.ToString() + " free up to " + next.ToString()); 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; } //Debug.Assert(!furthestUsed.IsBlockStartInstruction); if (furthestUsed.IsBlockStartInstruction) { return false; } var lastFree = furthestUsed.Previous; if (lastFree <= liveInterval.Start) { if (trace.Active) trace.Log(" No partial free space available"); return false; } if (trace.Active) trace.Log(" Partial free up to: " + furthestUsed.ToString()); var low = GetLowOptimalSplitLocation(liveInterval, lastFree, true); var high = GetHighOptimalSplitLocation(liveInterval, lastFree, true); var first = liveInterval.Split(liveInterval.Start, low); var last = liveInterval.Split(high, liveInterval.End); var middle = (low != high) ? liveInterval.Split(low, high) : null; if (trace.Active) trace.Log(" Low Split : " + first.ToString()); if (trace.Active) trace.Log(" Middle Split: " + (middle == null ? "n/a" : middle.ToString())); if (trace.Active) trace.Log(" High Split : " + last.ToString()); var virtualRegister = liveInterval.VirtualRegister; CalculateSpillCost(first); CalculateSpillCost(last); virtualRegister.Remove(liveInterval); virtualRegister.Add(first); virtualRegister.Add(last); AddPriorityQueue(first); AddPriorityQueue(last); if (middle != null) { //middle.ForceSpilled = true; CalculateSpillCost(middle); virtualRegister.Add(middle); AddPriorityQueue(middle); } return true; }
public void Remove(LiveInterval liveInterval) { LiveIntervals.Remove(liveInterval); }
public bool IsAdjacent(LiveInterval other) { return LiveRange.IsAdjacent(other.LiveRange); }
public LiveInterval CreateExpandedLiveInterval(LiveInterval interval) { Debug.Assert(VirtualRegister == interval.VirtualRegister); var start = Start < interval.Start ? Start : interval.Start; var end = End > interval.End ? End : interval.End; return new LiveInterval(VirtualRegister, start, end); }
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 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.ToString() + " free up to " + next.ToString()); 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.ToString()); if (liveInterval.UsePositions.Contains(furthestUsed) && liveInterval.Contains(furthestUsed.HalfStepBack)) furthestUsed = furthestUsed.HalfStepBack; return PreferBlockBoundaryIntervalSplit(liveInterval, furthestUsed, true); }
private void UpdateMoveHints(LiveInterval liveInterval, MoveHint[] moveHints) { if (moveHints == null) return; if (moveHints.Length >= 1) moveHints[0].Update(liveInterval); else if (moveHints.Length >= 2) moveHints[1].Update(liveInterval); }
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 MoveHint[] GetMoveHints(LiveInterval liveInterval) { MoveHint startMoveHint = null; MoveHint endMoveHint = null; moveHints.TryGetValue(liveInterval.Start, out startMoveHint); if (!liveInterval.End.IsBlockStartInstruction) moveHints.TryGetValue(liveInterval.End.Previous, out endMoveHint); int cnt = (startMoveHint == null ? 0 : 1) + (endMoveHint == null ? 0 : 1); if (cnt == 0) return null; MoveHint[] hints = new MoveHint[cnt]; if (startMoveHint != null && endMoveHint != null) { // sorted by bonus if (startMoveHint.Bonus > endMoveHint.Bonus) { hints[0] = startMoveHint; hints[1] = endMoveHint; } else { hints[0] = endMoveHint; hints[1] = startMoveHint; } } else { if (startMoveHint != null) { hints[0] = startMoveHint; } else { hints[0] = endMoveHint; } } return hints; }
protected override bool TrySplitInterval(LiveInterval liveInterval, int level) { return false; }
private bool IntervalSplitAtFirstUseOrDef(LiveInterval liveInterval) { // last resort if (liveInterval.IsEmpty) return false; SlotIndex at; var firstUse = liveInterval.UsePositions.Count != 0 ? liveInterval.UsePositions[0] : null; var firstDef = liveInterval.DefPositions.Count != 0 ? liveInterval.DefPositions[0] : null; at = firstDef; if (at == null) at = firstUse; else if (firstUse != null && firstUse < at) at = firstUse; var atNext = at.Next; if (liveInterval.Start == at && liveInterval.End == atNext) { if (trace.Active) trace.Log(" Interval already smallest"); return false; } if (trace.Active) trace.Log(" Splitting around first use/def"); var virtualRegister = liveInterval.VirtualRegister; virtualRegister.Remove(liveInterval); if (liveInterval.Start != at) { var first = liveInterval.Split(liveInterval.Start, at); CalculateSpillCost(first); virtualRegister.Add(first); AddPriorityQueue(first); if (trace.Active) trace.Log(" First Split : " + first.ToString()); } var middle = liveInterval.Split(at, atNext); CalculateSpillCost(middle); virtualRegister.Add(middle); AddPriorityQueue(middle); if (trace.Active) trace.Log(" Middle Split: " + middle.ToString()); if (liveInterval.End != atNext) { var last = liveInterval.Split(atNext, liveInterval.End); CalculateSpillCost(last); virtualRegister.Add(last); AddPriorityQueue(last); if (trace.Active) trace.Log(" Last Split : " + last.ToString()); } return true; }
private bool PlaceLiveIntervalOnTrackAllowEvictions(LiveInterval liveInterval) { // find live interval(s) to evict based on spill costs foreach (var track in liveIntervalTracks) { if (track.IsReserved) continue; if (track.IsFloatingPoint != liveInterval.VirtualRegister.IsFloatingPoint) continue; var intersections = track.GetIntersections(liveInterval); bool evict = true; foreach (var intersection in intersections) { if (intersection.SpillCost >= liveInterval.SpillCost || intersection.SpillCost == Int32.MaxValue || intersection.VirtualRegister.IsPhysicalRegister || intersection.IsPhysicalRegister) { evict = false; break; } } if (evict) { if (intersections.Count != 0) { if (trace.Active) trace.Log(" Evicting live intervals"); track.Evict(intersections); foreach (var intersection in intersections) { if (trace.Active) trace.Log(" Evicted: " + intersection.ToString()); liveInterval.Stage = LiveInterval.AllocationStage.Initial; AddPriorityQueue(intersection); }; } track.Add(liveInterval); if (trace.Active) trace.Log(" Assigned live interval to: " + track.ToString()); return true; } } return false; }
private bool PlaceLiveIntervalOnTrack(LiveInterval liveInterval, MoveHint[] hints) { if (hints == null) return false; foreach (var moveHint in hints) { LiveIntervalTrack track = null; var register = (liveInterval.Start == moveHint.Slot) ? moveHint.FromRegister : moveHint.ToRegister; if (register == null) continue; // no usable hint if (trace.Active) trace.Log(" Trying move hint: " + register.ToString() + " [ " + moveHint.ToString() + " ]"); if (PlaceLiveIntervalOnTrack(liveInterval, liveIntervalTracks[register.Index])) { return true; } } return false; }
private bool PlaceLiveIntervalOnTrack(LiveInterval liveInterval, LiveIntervalTrack track) { if (track.IsReserved) return false; if (track.IsFloatingPoint != liveInterval.VirtualRegister.IsFloatingPoint) return false; if (track.Intersects(liveInterval)) return false; if (trace.Active) trace.Log(" Assigned live interval to: " + track.ToString()); track.Add(liveInterval); return true; }
protected virtual void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite) { }
protected override int CalculatePriorityValue(LiveInterval liveInterval) { return liveInterval.Length | ((int)(((int)LiveInterval.AllocationStage.Max - liveInterval.Stage)) << 28); }
protected override bool TrySplitInterval(LiveInterval liveInterval, int level) { return(false); }
private bool TrySplitInterval(LiveInterval liveInterval, int level) { if (liveInterval.IsEmpty) return false; if (TrySimplePartialFreeIntervalSplit(liveInterval)) return true; if (level <= 1) return false; if (IntervalSplitAtFirstUseOrDef(liveInterval)) return true; return false; }
private void AddPriorityQueue(LiveInterval liveInterval) { // priority is based on allocation stage (primary, lower first) and interval size (secondary, higher first) priorityQueue.Enqueue(liveInterval.Length | ((int)(((int)LiveInterval.AllocationStage.Max - liveInterval.Stage)) << 28), liveInterval); }
public void Evict(LiveInterval liveInterval) { liveIntervals.Remove(liveInterval); liveInterval.LiveIntervalTrack = null; }
public void Update(LiveInterval interval) { LiveInterval updateInterval = interval.AssignedPhysicalRegister == null ? null : interval; if (interval.VirtualRegister == From) { FromInterval = updateInterval; } if (interval.VirtualRegister == To) { ToInterval = updateInterval; } }
private bool IntervalSplitAtFirstUseOrDef(LiveInterval liveInterval) { if (liveInterval.IsEmpty) return false; SlotIndex at = null; var firstUse = liveInterval.UsePositions.Count != 0 ? liveInterval.UsePositions[0] : null; var firstDef = liveInterval.DefPositions.Count != 0 ? liveInterval.DefPositions[0] : null; if (at == null) { at = firstUse; } if (at != null && firstDef != null && firstDef < at) { at = firstDef; } if (at >= liveInterval.End) return false; if (at <= liveInterval.Start) return false; if (Trace.Active) Trace.Log(" Splitting around first use/def"); return PreferBlockBoundaryIntervalSplit(liveInterval, at, true); }
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; }
public bool Intersects(LiveInterval other) { return LiveRange.Intersects(other.LiveRange); }
private SlotIndex FindCallSiteInInterval(LiveInterval liveInterval) { foreach (SlotIndex slot in callSlots) { if (liveInterval.Contains(slot)) return slot; } return null; }
public void Add(LiveInterval liveInterval) { LiveIntervals.Add(liveInterval); }
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)); }
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; }
private void UpdateMoveHints(LiveInterval liveInterval) { MoveHint MoveHint = null; if (moveHints.TryGetValue(liveInterval.Start, out MoveHint)) { MoveHint.Update(liveInterval); } if (moveHints.TryGetValue(liveInterval.End, out MoveHint)) { MoveHint.Update(liveInterval); } }
protected override int CalculatePriorityValue(LiveInterval liveInterval) { return(liveInterval.Length | ((int)(((int)LiveInterval.AllocationStage.Max - liveInterval.Stage)) << 28)); }
private bool PlaceLiveIntervalOnAnyAvailableTrack(LiveInterval liveInterval) { foreach (var track in liveIntervalTracks) { if (PlaceLiveIntervalOnTrack(liveInterval, track)) { return true; } } return false; }
protected virtual void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite) { }
private void ProcessLiveInterval(LiveInterval liveInterval) { if (trace.Active) { trace.Log("Processing Interval: " + liveInterval.ToString() + " / Length: " + liveInterval.Length.ToString() + " / Spill Cost: " + liveInterval.SpillCost.ToString() + " / Stage: " + liveInterval.Stage.ToString()); trace.Log(" Defs (" + liveInterval.DefPositions.Count.ToString() + "): " + SlotsToString(liveInterval.DefPositions)); trace.Log(" Uses (" + liveInterval.UsePositions.Count.ToString() + "): " + SlotsToString(liveInterval.UsePositions)); } if (liveInterval.ForceSpilled) { if (trace.Active) trace.Log(" Forced spilled interval"); liveInterval.VirtualRegister.IsSpilled = true; spilledIntervals.Add(liveInterval); return; } // For now, empty intervals will stay spilled if (liveInterval.IsEmpty) { if (trace.Active) trace.Log(" Spilled"); liveInterval.VirtualRegister.IsSpilled = true; spilledIntervals.Add(liveInterval); return; } var moveHints = GetMoveHints(liveInterval); // Try to place using move hints first if (PlaceLiveIntervalOnTrack(liveInterval, moveHints)) { UpdateMoveHints(liveInterval, moveHints); return; } // TODO - try move hints first, allow evictions // Find any available track and place interval there if (PlaceLiveIntervalOnAnyAvailableTrack(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return; } if (trace.Active) trace.Log(" No free register available"); // No place for live interval; find live interval(s) to evict based on spill costs if (PlaceLiveIntervalOnTrackAllowEvictions(liveInterval)) { UpdateMoveHints(liveInterval, moveHints); return; } if (trace.Active) trace.Log(" No live intervals to evicts"); // No live intervals to evict! // prepare to split live interval if (liveInterval.Stage == LiveInterval.AllocationStage.Initial) { if (trace.Active) trace.Log(" Re-queued for split level 1 stage"); liveInterval.Stage = LiveInterval.AllocationStage.SplitLevel1; AddPriorityQueue(liveInterval); return; } // split live interval - level 1 if (liveInterval.Stage == LiveInterval.AllocationStage.SplitLevel1) { if (trace.Active) trace.Log(" Attempting to split interval - level 1"); if (TrySplitInterval(liveInterval, 1)) { return; } // Move to split level 2 stage if (trace.Active) trace.Log(" Re-queued for split interval - level 2"); liveInterval.Stage = LiveInterval.AllocationStage.SplitLevel2; AddPriorityQueue(liveInterval); return; } // split live interval - level 2 if (liveInterval.Stage == LiveInterval.AllocationStage.SplitLevel2) { if (trace.Active) trace.Log(" Attempting to split interval - level 2"); if (TrySplitInterval(liveInterval, 2)) { return; } // Move to spill stage if (trace.Active) trace.Log(" Re-queued for spillable stage"); liveInterval.Stage = LiveInterval.AllocationStage.Spillable; AddPriorityQueue(liveInterval); return; } // spill interval to stack slot if (liveInterval.Stage == LiveInterval.AllocationStage.Spillable) { if (trace.Active) trace.Log(" Spilled interval"); //liveInterval.Stage = LiveInterval.AllocationStage.Spilled liveInterval.VirtualRegister.IsSpilled = true; spilledIntervals.Add(liveInterval); return; } // TODO return; }