Inheritance: IComparable
コード例 #1
0
ファイル: Interval.cs プロジェクト: yonglehou/MOSA-Project
		public Interval(SlotIndex start, SlotIndex end)
		{
			Debug.Assert(start <= end);

			this.Start = start;
			this.End = end;
		}
コード例 #2
0
ファイル: MoveHint.cs プロジェクト: tea/MOSA-Project
 public MoveHint(SlotIndex slot, VirtualRegister from, VirtualRegister to, int bonus)
 {
     Slot = slot;
     From = from;
     To = to;
     Bonus = bonus;
 }
コード例 #3
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
        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;
        }
コード例 #4
0
ファイル: LiveRange.cs プロジェクト: Zahovay/MOSA-Project
        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;
        }
コード例 #5
0
ファイル: LiveInterval.cs プロジェクト: tea/MOSA-Project
        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;
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
        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;
        }
コード例 #8
0
        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;
        }
コード例 #9
0
        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));
                }
            }
        }
コード例 #10
0
 private SlotIndex GetBlockStart(SlotIndex slotIndex)
 {
     return GetContainingBlock(slotIndex).Start;
 }
コード例 #11
0
        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;
        }
コード例 #12
0
 private int GetSpillCost(SlotIndex use, int factor)
 {
     return factor * GetLoopDepth(use) * 100;
 }
コード例 #13
0
ファイル: LiveRange.cs プロジェクト: mlintell/MOSA-Project
 public SlotIndex GetPreviousDefPosition(SlotIndex at)
 {
     return(GetPrevious(DefPositions, at));
 }
コード例 #14
0
 protected virtual void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite)
 {
 }
コード例 #15
0
 public bool Contains(SlotIndex start)
 {
     return(LiveRange.Contains(start));
 }
コード例 #16
0
 public LiveInterval(VirtualRegister virtualRegister, SlotIndex start, SlotIndex end)
     : this(virtualRegister, start, end, virtualRegister.UsePositions, virtualRegister.DefPositions)
 {
 }
コード例 #17
0
 public bool Intersects(SlotIndex start, SlotIndex end)
 {
     return(LiveRange.Intersects(start, end));
 }
コード例 #18
0
 public bool IsAdjacent(SlotIndex start, SlotIndex end)
 {
     return(LiveRange.IsAdjacent(start, end));
 }
コード例 #19
0
 private int GetSpillCost(SlotIndex use, int factor)
 {
     return(factor * GetLoopDepth(use) * 100);
 }
コード例 #20
0
        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));
        }
コード例 #21
0
 protected override void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite)
 {
     PreferBlockBoundaryIntervalSplit(liveInterval, callSite, false);
 }
コード例 #22
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
        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;
        }
コード例 #23
0
 public bool Contains(SlotIndex at)
 {
     return(at >= Start && at < End);
 }
コード例 #24
0
        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;
        }
コード例 #25
0
 public bool IsAdjacent(SlotIndex start, SlotIndex end)
 {
     return(start == End || end == Start);
 }
コード例 #26
0
 protected virtual void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite)
 {
 }
コード例 #27
0
 public bool Intersects(SlotIndex start, SlotIndex end)
 {
     return((Start <= start && End > start) || (start <= Start && end > Start));
 }
コード例 #28
0
        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();
                }
            }
        }
コード例 #29
0
 public SlotIndex GetNextUsePosition(SlotIndex at)
 {
     return(GetNext(UsePositions, at));
 }
コード例 #30
0
 private SlotIndex GetBlockEnd(SlotIndex slotIndex)
 {
     return GetContainingBlock(slotIndex).End;
 }
コード例 #31
0
 public SlotIndex GetNextDefPosition(SlotIndex at)
 {
     return(GetNext(DefPositions, at));
 }
コード例 #32
0
        private ExtendedBlock GetContainingBlock(SlotIndex slotIndex)
        {
            foreach (var block in extendedBlocks)
            {
                if (block.Contains(slotIndex))
                {
                    return block;
                }
            }

            Debug.Assert(false, "GetContainingBlock");
            return null;
        }
コード例 #33
0
 public bool Contains(SlotIndex slotIndex)
 {
     return(slotIndex >= Start && slotIndex < End);
 }
コード例 #34
0
 private int GetLoopDepth(SlotIndex slotIndex)
 {
     return GetContainingBlock(slotIndex).LoopDepth + 1;
 }
コード例 #35
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
 public LiveInterval(VirtualRegister virtualRegister, SlotIndex start, SlotIndex end)
     : this(virtualRegister, start, end, virtualRegister.UsePositions, virtualRegister.DefPositions)
 {
 }
コード例 #36
0
 private int GetSpillCost(SlotIndex use, int factor)
 {
     return (factor * SlotIncrement) * GetLoopDepth(use) * 100;
 }
コード例 #37
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
        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);
        }
コード例 #38
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
 public bool IsAdjacent(SlotIndex start, SlotIndex end)
 {
     return LiveRange.IsAdjacent(start, end);
 }
コード例 #39
0
ファイル: LiveRange.cs プロジェクト: mlintell/MOSA-Project
 public SlotIndex GetPreviousUsePosition(SlotIndex at)
 {
     return(GetPrevious(UsePositions, at));
 }
コード例 #40
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
 public bool Contains(SlotIndex start)
 {
     return LiveRange.Contains(start);
 }
コード例 #41
0
 protected override void SplitIntervalAtCallSite(LiveInterval liveInterval, SlotIndex callSite)
 {
     PreferBlockBoundaryIntervalSplit(liveInterval, callSite, false);
 }
コード例 #42
0
ファイル: LiveInterval.cs プロジェクト: Zahovay/MOSA-Project
 public bool Intersects(SlotIndex start, SlotIndex end)
 {
     return LiveRange.Intersects(start, end);
 }
コード例 #43
0
        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;
        }
コード例 #44
0
        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;
        }
コード例 #45
0
        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;
        }
コード例 #46
0
 public bool Contains(SlotIndex slotIndex)
 {
     return Interval.Contains(slotIndex) || slotIndex == Interval.End;
 }
コード例 #47
0
ファイル: LiveRange.cs プロジェクト: arakis/MOSA-Project
        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());
        }