예제 #1
0
        private void RemoveBlock(BasicBlock block, CompilerTrace trace)
        {
            Debug.Assert(block.NextBlocks.Count == 1);

            BasicBlock target = block.NextBlocks[0];

            if (trace.Active)
            {
                trace.Log("====== Removing: " + block.ToString() + " # " + block.Sequence);
                trace.Log("     New Target: " + target.ToString());
                foreach (var from in block.PreviousBlocks)
                {
                    trace.Log("Previous Blocks: " + from.ToString());
                }
            }

            target.PreviousBlocks.Remove(block);

            foreach (var from in block.PreviousBlocks)
            {
                from.NextBlocks.Remove(block);
                from.NextBlocks.AddIfNew(target);

                if (trace.Active)
                {
                    trace.Log("  Add target to NextBlock of " + from.ToString());
                }

                target.PreviousBlocks.AddIfNew(from);

                if (trace.Active)
                {
                    trace.Log("  Add " + from.ToString() + " to PreviousBlock of " + target.ToString());
                }

                ReplaceBranchTargets(from, block, target);
            }

            block.NextBlocks.Clear();
            block.PreviousBlocks.Clear();

            EmptyBlockOfAllInstructions(block);
        }
예제 #2
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);
            }
        }
예제 #3
0
        private void InsertRegisterMoves()
        {
            var insertTrace = new CompilerTrace(trace, "InsertRegisterMoves");

            // collect edge slot indexes
            Dictionary<SlotIndex, ExtendedBlock> blockEdges = new Dictionary<SlotIndex, ExtendedBlock>();

            foreach (var block in extendedBlocks)
            {
                blockEdges.Add(block.Start, block);
                blockEdges.Add(block.End, block);
            }

            foreach (var virtualRegister in virtualRegisters)
            {
                if (virtualRegister.IsPhysicalRegister)
                    continue;

                if (virtualRegister.LiveIntervals.Count <= 1)
                    continue;

                foreach (var currentInterval in virtualRegister.LiveIntervals)
                {
                    if (blockEdges.ContainsKey(currentInterval.End))
                        continue;

                    // List is not sorted, so scan thru each one
                    foreach (var nextInterval in virtualRegister.LiveIntervals)
                    {
                        if (nextInterval.Start == currentInterval.End)
                        {
                            // next interval is stack - stores to stack are done elsewhere
                            if (nextInterval.AssignedPhysicalOperand == null)
                                break;

                            // check if source and destination operands of the move are the same
                            if (nextInterval.AssignedOperand == currentInterval.AssignedOperand ||
                                nextInterval.AssignedOperand.Register == currentInterval.AssignedOperand.Register)
                                break;

                            Context context = new Context(instructionSet, currentInterval.End.Index);
                            context.GotoPrevious();

                            while (context.IsEmpty || context.Instruction.FlowControl == FlowControl.UnconditionalBranch || context.Instruction.FlowControl == FlowControl.ConditionalBranch || context.Instruction.FlowControl == FlowControl.Return)
                            {
                                context.GotoPrevious();
                            }

                            architecture.InsertMoveInstruction(context,
                                nextInterval.AssignedOperand,
                                currentInterval.AssignedOperand
                            );

                            context.Marked = true;

                            if (insertTrace.Active)
                            {
                                insertTrace.Log("REGISTER: " + virtualRegister.ToString());
                                insertTrace.Log("POSITION: " + currentInterval.End.ToString());
                                insertTrace.Log("    FROM: " + currentInterval.AssignedOperand.ToString());
                                insertTrace.Log("      TO: " + nextInterval.AssignedOperand.ToString());

                                insertTrace.Log("");
                            }

                            break;
                        }
                    }
                }
            }
        }
예제 #4
0
        private void ComputeLocalLiveSets()
        {
            var liveSetTrace = new CompilerTrace(trace, "ComputeLocalLiveSets");

            foreach (var block in extendedBlocks)
            {
                if (liveSetTrace.Active)
                    liveSetTrace.Log("Block # " + block.BasicBlock.Sequence.ToString());

                BitArray liveGen = new BitArray(registerCount, false);
                BitArray liveKill = new BitArray(registerCount, false);

                liveGen.Set(stackFrameRegister.Index, true);
                liveGen.Set(stackPointerRegister.Index, true);

                if (programCounter != null)
                    liveGen.Set(programCounter.Index, true);

                for (Context context = new Context(instructionSet, block.BasicBlock); !context.IsBlockEndInstruction; context.GotoNext())
                {
                    if (context.IsEmpty)
                        continue;

                    if (liveSetTrace.Active)
                        liveSetTrace.Log(context.ToString());

                    OperandVisitor visitor = new OperandVisitor(context);

                    foreach (var ops in visitor.Input)
                    {
                        if (liveSetTrace.Active)
                            liveSetTrace.Log("INPUT:  " + ops.ToString());

                        int index = GetIndex(ops);
                        if (!liveKill.Get(index))
                        {
                            liveGen.Set(index, true);

                            if (liveSetTrace.Active)
                                liveSetTrace.Log("GEN:  " + index.ToString() + " " + ops.ToString());
                        }
                    }

                    if (context.Instruction.FlowControl == FlowControl.Call)
                    {
                        for (int s = 0; s < physicalRegisterCount; s++)
                        {
                            liveKill.Set(s, true);
                        }

                        if (liveSetTrace.Active)
                            liveSetTrace.Log("KILL ALL PHYSICAL");
                    }

                    foreach (var ops in visitor.Output)
                    {
                        if (liveSetTrace.Active)
                            liveSetTrace.Log("OUTPUT: " + ops.ToString());

                        int index = GetIndex(ops);
                        liveKill.Set(index, true);

                        if (liveSetTrace.Active)
                            liveSetTrace.Log("KILL: " + index.ToString() + " " + ops.ToString());
                    }
                }

                block.LiveGen = liveGen;
                block.LiveKill = liveKill;
                block.LiveKillNot = ((BitArray)liveKill.Clone()).Not();

                if (liveSetTrace.Active)
                {
                    liveSetTrace.Log("GEN:     " + ToString(block.LiveGen));
                    liveSetTrace.Log("KILL:    " + ToString(block.LiveKill));
                    liveSetTrace.Log("KILLNOT: " + ToString(block.LiveKillNot));
                    liveSetTrace.Log(string.Empty);
                }
            }
        }
예제 #5
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();
                }
            }
        }
예제 #6
0
        private void TraceMoveHints()
        {
            if (!trace.Active)
                return;

            var moveHintTrace = new CompilerTrace(trace, "Move Hints");

            foreach (var moveHint in moveHints)
            {
                moveHintTrace.Log(moveHint.Value.ToString());
            }
        }
예제 #7
0
        private void TraceLiveIntervals(string stage, bool operand)
        {
            if (!trace.Active)
                return;

            var registerTrace = new CompilerTrace(trace, stage);

            foreach (var virtualRegister in virtualRegisters)
            {
                if (virtualRegister.IsPhysicalRegister)
                {
                    registerTrace.Log("Physical Register # " + virtualRegister.PhysicalRegister.ToString());
                }
                else
                {
                    registerTrace.Log("Virtual Register # " + virtualRegister.VirtualRegisterOperand.Index.ToString());
                }

                registerTrace.Log("Live Intervals (" + virtualRegister.LiveIntervals.Count.ToString() + "): " + LiveIntervalsToString(virtualRegister.LiveIntervals, operand));

                registerTrace.Log("Def Positions (" + virtualRegister.DefPositions.Count.ToString() + "): " + SlotsToString(virtualRegister.DefPositions));
                registerTrace.Log("Use Positions (" + virtualRegister.UsePositions.Count.ToString() + "): " + SlotsToString(virtualRegister.UsePositions));
            }
        }
예제 #8
0
        private void TraceBlocks()
        {
            if (!trace.Active)
                return;

            var sectionTrace = new CompilerTrace(trace, "Extended Blocks");

            foreach (var block in extendedBlocks)
            {
                sectionTrace.Log("Block # " + block.BasicBlock.Sequence.ToString() + " (" + block.Start + " to " + block.End + ")");
                sectionTrace.Log(" LiveIn:   " + ToString(block.LiveIn));
                sectionTrace.Log(" LiveGen:  " + ToString(block.LiveGen));
                sectionTrace.Log(" LiveKill: " + ToString(block.LiveKill));
                sectionTrace.Log(" LiveOut:  " + ToString(block.LiveOut));
            }
        }
예제 #9
0
        private void ResolveDataFlow()
        {
            var resolverTrace = new CompilerTrace(trace, "ResolveDataFlow");

            MoveResolver[,] moveResolvers = new MoveResolver[2, basicBlocks.Count];

            foreach (var from in extendedBlocks)
            {
                foreach (var nextBlock in from.BasicBlock.NextBlocks)
                {
                    var to = extendedBlocks[nextBlock.Sequence];

                    // determine where to insert resolving moves
                    bool fromAnchorFlag = (from.BasicBlock.NextBlocks.Count == 1);

                    ExtendedBlock anchor = fromAnchorFlag ? from : to;

                    MoveResolver moveResolver = moveResolvers[fromAnchorFlag ? 0 : 1, anchor.Sequence];

                    if (moveResolver == null)
                    {
                        moveResolver = new MoveResolver(anchor.BasicBlock, from.BasicBlock, to.BasicBlock);
                        moveResolvers[fromAnchorFlag ? 0 : 1, anchor.Sequence] = moveResolver;
                    }

                    foreach (var virtualRegister in GetVirtualRegisters(to.LiveIn))
                    {
                        //if (virtualRegister.IsPhysicalRegister)
                        //continue;

                        var fromLiveInterval = virtualRegister.GetIntervalAtOrEndsAt(from.End);
                        var toLiveInterval = virtualRegister.GetIntervalAt(to.Start);

                        Debug.Assert(fromLiveInterval != null);
                        Debug.Assert(toLiveInterval != null);

                        if (fromLiveInterval.AssignedPhysicalRegister != toLiveInterval.AssignedPhysicalRegister)
                        {
                            if (resolverTrace.Active)
                            {
                                resolverTrace.Log("REGISTER: " + fromLiveInterval.VirtualRegister.ToString());
                                resolverTrace.Log("    FROM: " + from.ToString().PadRight(7) + " " + fromLiveInterval.AssignedOperand.ToString());
                                resolverTrace.Log("      TO: " + to.ToString().PadRight(7) + " " + toLiveInterval.AssignedOperand.ToString());

                                resolverTrace.Log("  INSERT: " + (fromAnchorFlag ? "FROM (bottom)" : "TO (top)") + ((toLiveInterval.AssignedPhysicalOperand == null) ? "  ****SKIPPED***" : string.Empty));
                                resolverTrace.Log("");
                            }

                            // interval was spilled (spill moves are inserted elsewhere)
                            if (toLiveInterval.AssignedPhysicalOperand == null)
                                continue;

                            Debug.Assert(from.BasicBlock.NextBlocks.Count == 1 || to.BasicBlock.PreviousBlocks.Count == 1);

                            moveResolver.AddMove(fromLiveInterval.AssignedOperand, toLiveInterval.AssignedOperand);
                        }
                    }
                }
            }

            for (int b = 0; b < basicBlocks.Count; b++)
            {
                for (int fromTag = 0; fromTag < 2; fromTag++)
                {
                    MoveResolver moveResolver = moveResolvers[fromTag, b];

                    if (moveResolver == null)
                        continue;

                    moveResolver.InsertResolvingMoves(architecture, instructionSet);
                }
            }
        }