Beispiel #1
0
        // Split critical edges in the graph. A critical edge is an edge which
        // is neither its successor's only predecessor, nor its predecessor's
        // only successor. Critical edges must be split to prevent copy-insertion
        // and code motion from affecting other edges. It is probably not strictly
        // needed here.
        public static void SplitCriticalEdges(LBlock[] blocks)
        {
            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                if (block.numSuccessors < 2)
                {
                    continue;
                }
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    LBlock target = block.getSuccessor(j);
                    if (target.numPredecessors < 2)
                    {
                        continue;
                    }

                    // Create a new block inheriting from the predecessor.
                    LBlock         split        = new LBlock(block.pc);
                    LGoto          ins          = new LGoto(target);
                    LInstruction[] instructions = { ins };
                    split.setInstructions(instructions);
                    block.replaceSuccessor(j, split);
                    target.replacePredecessor(block, split);
                    split.addPredecessor(block);
                }
            }
        }
Beispiel #2
0
        public static void FindLoops(LBlock[] blocks)
        {
            // Mark backedges and headers.
            for (int i = 1; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    LBlock successor = block.getSuccessor(j);
                    if (successor.id < block.id)
                    {
                        successor.setLoopHeader(block);
                        block.setInLoop(successor);
                        break;
                    }
                }
            }

            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block = blocks[i];
                if (block.backedge != null)
                {
                    MarkLoop(block.backedge);
                }
            }
        }
Beispiel #3
0
        // Return a reverse post-order listing of reachable blocks.
        public static LBlock[] Order(LBlock entry)
        {
            // Postorder traversal without recursion.
            Stack <LBlock> pending    = new Stack <LBlock>();
            Stack <int>    successors = new Stack <int>();
            Stack <LBlock> done       = new Stack <LBlock>();

            LBlock current       = entry;
            int    nextSuccessor = 0;

            for (; ;)
            {
                if (!current.marked)
                {
                    current.mark();
                    if (nextSuccessor < current.numSuccessors)
                    {
                        pending.Push(current);
                        successors.Push(nextSuccessor);
                        current       = current.getSuccessor(nextSuccessor);
                        nextSuccessor = 0;
                        continue;
                    }

                    done.Push(current);
                }

                if (pending.Count == 0)
                {
                    break;
                }

                current = pending.Pop();
                current.unmark();
                nextSuccessor = successors.Pop() + 1;
            }

            List <LBlock> blocks = new List <LBlock>();

            while (done.Count > 0)
            {
                current = done.Pop();
                current.unmark();
                current.setId(blocks.Count);
                blocks.Add(current);
            }

            return(blocks.ToArray());
        }
Beispiel #4
0
        private ControlType findLoopJoinAndBody(NodeBlock header, NodeBlock effectiveHeader,
                                                out NodeBlock join, out NodeBlock body, out NodeBlock cond)
        {
            //Debug.Assert(effectiveHeader.lir.numSuccessors == 2);

            LBlock succ1 = effectiveHeader.lir.getSuccessor(0);
            LBlock succ2 = effectiveHeader.lir.getSuccessor(1);

            if (succ1.loop != header.lir || succ2.loop != header.lir)
            {
                //Debug.Assert(succ1.loop == header.lir || succ2.loop == header.lir);
                if (succ1.loop != header.lir)
                {
                    join = graph_[succ1.id];
                    body = graph_[succ2.id];
                }
                else
                {
                    join = graph_[succ2.id];
                    body = graph_[succ1.id];
                }
                cond = header;

                // If this is a self-loop, it is more correct to decompose it
                // to a do-while loop. This may not be source accurate in the
                // case of something like |while (x);| but it catches many more
                // source-accurate cases.
                if (header == effectiveHeader &&
                    BlockAnalysis.GetEmptyTarget(body) == header)
                {
                    body = null;
                    return(ControlType.DoWhileLoop);
                }

                return(ControlType.WhileLoop);
            }
            else
            {
                // Neither successor of the header exits the loop, so this is
                // probably a do-while loop. For now, assume it's simple.
                //Debug.Assert(header == effectiveHeader);
                LBlock backedge = header.lir.backedge;
                if (BlockAnalysis.GetEmptyTarget(graph_[backedge.id]) == header)
                {
                    // Skip an empty block sitting in between the backedge and
                    // the condition.
                    //Debug.Assert(backedge.numPredecessors == 1);
                    backedge = backedge.getPredecessor(0);
                }

                //Debug.Assert(backedge.numSuccessors == 2);
                succ1 = backedge.getSuccessor(0);
                succ2 = backedge.getSuccessor(1);

                body = header;
                cond = graph_[backedge.id];
                if (succ1.loop != header.lir)
                {
                    join = graph_[succ1.id];
                }
                else
                {
                    //Debug.Assert(succ2.loop != header.lir);
                    join = graph_[succ2.id];
                }
                return(ControlType.DoWhileLoop);
            }
        }
Beispiel #5
0
        // From Engineering a Compiler (Cooper, Torczon)
        public static bool IsReducible(LBlock[] blocks)
        {
            // Copy the graph into a temporary mutable structure.
            RBlock[] rblocks = new RBlock[blocks.Length];
            for (int i = 0; i < blocks.Length; i++)
            {
                rblocks[i] = new RBlock(i);
            }

            for (int i = 0; i < blocks.Length; i++)
            {
                LBlock block  = blocks[i];
                RBlock rblock = rblocks[i];
                for (int j = 0; j < block.numPredecessors; j++)
                {
                    rblock.predecessors.Add(rblocks[block.getPredecessor(j).id]);
                }
                for (int j = 0; j < block.numSuccessors; j++)
                {
                    rblock.successors.Add(rblocks[block.getSuccessor(j).id]);
                }
            }

            // Okay, start reducing.
            LinkedList <RBlock> queue = new LinkedList <RBlock>(rblocks);

            for (;;)
            {
                List <RBlock> deleteQueue = new List <RBlock>();
                foreach (RBlock rblock in queue)
                {
                    // Transformation T1, remove self-edges.
                    if (rblock.predecessors.Contains(rblock))
                    {
                        rblock.predecessors.Remove(rblock);
                    }
                    if (rblock.successors.Contains(rblock))
                    {
                        rblock.successors.Remove(rblock);
                    }

                    // Transformation T2, remove blocks with one predecessor,
                    // reroute successors' predecessors.
                    if (rblock.predecessors.Count == 1)
                    {
                        // Mark this node for removal since C# sucks and can't delete during iteration.
                        deleteQueue.Add(rblock);

                        RBlock predecessor = rblock.predecessors[0];

                        // Delete the edge from pred -> me
                        predecessor.successors.Remove(rblock);

                        for (int i = 0; i < rblock.successors.Count; i++)
                        {
                            RBlock successor = rblock.successors[i];
                            //Debug.Assert(successor.predecessors.Contains(rblock));
                            successor.predecessors.Remove(rblock);
                            if (!successor.predecessors.Contains(predecessor))
                            {
                                successor.predecessors.Add(predecessor);
                            }

                            if (!predecessor.successors.Contains(successor))
                            {
                                predecessor.successors.Add(successor);
                            }
                        }
                    }
                }

                if (deleteQueue.Count == 0)
                {
                    break;
                }

                foreach (RBlock rblock in deleteQueue)
                {
                    queue.Remove(rblock);
                }
            }

            // If the graph reduced to one node, it was reducible.
            return(queue.Count == 1);
        }