diff options
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 4bb480d840..78454645b3 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -797,7 +797,35 @@ bool llvm::SimplifyCFG(BasicBlock *BB) { (&*I == cast<Instruction>(BI->getCondition()) && &*++I == BI)) if (FoldValueComparisonIntoPredecessors(BI)) - return SimplifyCFG(BB) || 1; + return SimplifyCFG(BB) | true; + } + + if (BI->isConditional()) { + // If this block ends with a branch instruction, and if there is one + // predecessor, see if the previous block ended with a branch on the same + // condition, which makes this conditional branch redundant. + pred_iterator PI(pred_begin(BB)), PE(pred_end(BB)); + BasicBlock *OnlyPred = *PI++; + for (; PI != PE; ++PI)// Search all predecessors, see if they are all same + if (*PI != OnlyPred) { + OnlyPred = 0; // There are multiple different predecessors... + break; + } + + if (OnlyPred) + if (BranchInst *PBI = dyn_cast<BranchInst>(OnlyPred->getTerminator())) + if (PBI->isConditional() && + PBI->getCondition() == BI->getCondition() && + PBI->getSuccessor(0) != BB || PBI->getSuccessor(1) != BB) { + // Okay, the outcome of this conditional branch is statically + // knowable. Delete the outgoing CFG edge that is impossible to + // execute. + bool CondIsTrue = PBI->getSuccessor(0) == BB; + BI->getSuccessor(CondIsTrue)->removePredecessor(BB); + new BranchInst(BI->getSuccessor(!CondIsTrue), BB); + BB->getInstList().erase(BI); + return SimplifyCFG(BB) | true; + } } } @@ -812,7 +840,7 @@ bool llvm::SimplifyCFG(BasicBlock *BB) { OnlyPred = 0; // There are multiple different predecessors... break; } - + BasicBlock *OnlySucc = 0; if (OnlyPred && OnlyPred != BB && // Don't break self loops OnlyPred->getTerminator()->getOpcode() != Instruction::Invoke) { |