diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index e766d729e1b..1dc5a960e04 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -116,8 +116,8 @@ bool 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 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. +/// will not invalidate either of them. This returns the new block if the edge +/// was split, null otherwise. /// /// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the /// specified successor will be merged into the same critical edge block. @@ -126,10 +126,16 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, /// dest go to one block instead of each going to a different block, but isn't /// the standard definition of a "critical edge". /// +/// It is invalid to call this function on a critical edge that starts at an +/// IndirectBrInst. Splitting these edges will almost always create an invalid +/// program because the addr of the new block won't be the one that is jumped +/// to. +/// BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0, bool MergeIdenticalEdges = false); -inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) { +inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, + Pass *P = 0) { return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); } diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp index d683a2c5aae..813119d5d56 100644 --- a/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -69,7 +69,7 @@ bool BreakCriticalEdges::runOnFunction(Function &F) { bool Changed = false; for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { TerminatorInst *TI = I->getTerminator(); - if (TI->getNumSuccessors() > 1) + if (TI->getNumSuccessors() > 1 && !isa(TI)) for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (SplitCriticalEdge(TI, i, this)) { ++NumBroken; @@ -150,14 +150,29 @@ static void CreatePHIsForSplitLoopExit(SmallVectorImpl &Preds, /// SplitCriticalEdge - If this edge is a critical edge, insert a new node to /// split the critical edge. This will update DominatorTree and -/// DominatorFrontier information if it is available, thus 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. -// +/// DominatorFrontier information if it is available, thus calling this pass +/// will not invalidate either of them. This returns the new block if the edge +/// was split, null otherwise. +/// +/// If MergeIdenticalEdges is true (not 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". +/// +/// It is invalid to call this function on a critical edge that starts at an +/// IndirectBrInst. Splitting these edges will almost always create an invalid +/// program because the addr of the new block won't be the one that is jumped +/// to. +/// BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P, bool MergeIdenticalEdges) { if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0; + + assert(!isa(TI) && + "Cannot split critical edge from IndirectBrInst"); + BasicBlock *TIBB = TI->getParent(); BasicBlock *DestBB = TI->getSuccessor(SuccNum);