diff options
author | Pete Cooper <peter_cooper@apple.com> | 2011-12-17 06:32:38 +0000 |
---|---|---|
committer | Pete Cooper <peter_cooper@apple.com> | 2011-12-17 06:32:38 +0000 |
commit | eadf124d2b15cef353b211cbc0bf793caf70ead1 (patch) | |
tree | 2c83d205d9c2ff69518d6c90722e4c62b5ca855b /llvm/lib/Transforms | |
parent | 3c2848ea310e80dd7587558725cad34c5cefafff (diff) | |
download | bcm5719-llvm-eadf124d2b15cef353b211cbc0bf793caf70ead1.tar.gz bcm5719-llvm-eadf124d2b15cef353b211cbc0bf793caf70ead1.zip |
SimplifyCFG now predicts some conditional branches to true or false depending on previous branch on same comparison operands.
For example,
if (a == b) {
if (a > b) // this is false
Fixes some of the issues on <rdar://problem/10554090>
llvm-svn: 146822
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index bf2cb49bdcd..d20e5a54762 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "simplifycfg" +#include "llvm/Transforms/Utils/CmpInstAnalysis.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" @@ -1702,6 +1703,47 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI) { } } + // Treat "if (cond1) { if (cond2) {} }" as "cond1 & cond2" and fold. + // This gives us the value of what cond2 is given cond1 is already known to + // be true. + if (ICmpInst *LHS = dyn_cast<ICmpInst>(PBI->getCondition())) { + if (ICmpInst *RHS = dyn_cast<ICmpInst>(BI->getCondition())) { + ICmpInst::Predicate LHSCC = LHS->getPredicate(), + RHSCC = RHS->getPredicate(); + if (PredicatesFoldable(LHSCC, RHSCC)) { + if (LHS->getOperand(0) == RHS->getOperand(1) && + LHS->getOperand(1) == RHS->getOperand(0)) + LHS->swapOperands(); + if (LHS->getOperand(0) == RHS->getOperand(0) && + LHS->getOperand(1) == RHS->getOperand(1) && + BB->getSinglePredecessor()) { + Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1); + bool CondIsTrue = PBI->getSuccessor(0) == BB; + unsigned LHSCode = getICmpCode(LHS, !CondIsTrue); + unsigned RHSCode = getICmpCode(RHS); + unsigned Code = LHSCode & RHSCode; + + Value *ConstantCondition = NULL; + // If the resultant code is the same as the LHS code then as that + // code is known to be true we can make RHS now be true. + if (Code == LHSCode) + ConstantCondition = ConstantInt::get( + CmpInst::makeCmpResultType(LHS->getType()), 1); + else { + bool isSigned = LHS->isSigned() || RHS->isSigned(); + CmpInst::Predicate IgnoredNewPred; + ConstantCondition = getICmpValue(isSigned, Code, Op0, Op1, + IgnoredNewPred); + } + if (ConstantCondition) { + RHS->replaceAllUsesWith(ConstantCondition); + return true; + } + } + } + } + } + // If this is a conditional branch in an empty block, and if any // predecessors is a conditional branch to one of our destinations, // fold the conditions into logical ops and one cond br. |