From: Chris Lattner Date: Sat, 28 Oct 2006 06:44:56 +0000 (+0000) Subject: Expose a smarter way to break critical edges. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=27e1f90d8551b84db910c93ab21c941031c18b60;p=oota-llvm.git Expose a smarter way to break critical edges. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31256 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 3853901b30c..0bfb6f750aa 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -63,9 +63,15 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum); /// split the critical edge. This will update DominatorSet, ImmediateDominator, /// DominatorTree, and DominatorFrontier information if it is available, thus /// calling this pass will not invalidate either of them. This returns true if -/// the edge was split, false otherwise. +/// the edge was split, false otherwise. If MergeIdenticalEdges is true (the +/// default), *all* edges from TI to the specified successor will be merged into +/// the same critical edge block. This is most commonly interesting with switch +/// instructions, which may have many edges to any one destination. This +/// ensures that all edges to that dest go to one block instead of each going to +/// a different block, but isn't the standard definition of a "critical edge". /// -bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0); +bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0, + bool MergeIdenticalEdges = false); inline bool SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) { return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); @@ -89,13 +95,14 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { /// and return true, otherwise return false. This method requires that there be /// an edge between the two blocks. If P is specified, it updates the analyses /// described above. -inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0) { +inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0, + bool MergeIdenticalEdges = false) { TerminatorInst *TI = Src->getTerminator(); unsigned i = 0; while (1) { assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); if (TI->getSuccessor(i) == Dst) - return SplitCriticalEdge(TI, i, P); + return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges); ++i; } } diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp index d4e186cabb2..5bb513fc3bd 100644 --- a/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -100,10 +100,12 @@ bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum) { // SplitCriticalEdge - If this edge is a critical edge, insert a new node to // split the critical edge. This will update DominatorSet, ImmediateDominator, // DominatorTree, and DominatorFrontier information if it is available, thus -// calling this pass will not invalidate either of them. This returns true if -// the edge was split, false otherwise. +// calling this pass will not invalidate any of them. This returns true if +// the edge was split, false otherwise. This ensures that all edges to that +// dest go to one block instead of each going to a different block. // -bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) { +bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P, + bool MergeIdenticalEdges) { if (!isCriticalEdge(TI, SuccNum)) return false; BasicBlock *TIBB = TI->getParent(); BasicBlock *DestBB = TI->getSuccessor(SuccNum); @@ -114,13 +116,13 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) { // Create our unconditional branch... new BranchInst(DestBB, NewBB); - // Branch to the new block, breaking the edge... + // Branch to the new block, breaking the edge. TI->setSuccessor(SuccNum, NewBB); // Insert the block into the function... right after the block TI lives in. Function &F = *TIBB->getParent(); F.getBasicBlockList().insert(TIBB->getNext(), NewBB); - + // If there are any PHI nodes in DestBB, we need to update them so that they // merge incoming values from NewBB instead of from TIBB. // @@ -132,6 +134,23 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) { int BBIdx = PN->getBasicBlockIndex(TIBB); PN->setIncomingBlock(BBIdx, NewBB); } + + // If there are any other edges from TIBB to DestBB, update those to go + // through the split block, making those edges non-critical as well (and + // reducing the number of phi entries in the DestBB if relevant). + if (MergeIdenticalEdges) { + for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) { + if (TI->getSuccessor(i) != DestBB) continue; + + // Remove an entry for TIBB from DestBB phi nodes. + DestBB->removePredecessor(TIBB); + + // We found another edge to DestBB, go to NewBB instead. + TI->setSuccessor(i, NewBB); + } + } + + // If we don't have a pass object, we can't update anything... if (P == 0) return true;