From 93ca12299f3210e300c9ac4f0fd8d6ce5b7d7d60 Mon Sep 17 00:00:00 2001 From: Pete Cooper Date: Sat, 17 Dec 2011 06:32:38 +0000 Subject: 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146822 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'lib/Transforms/Utils') diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index bf2cb49..d20e5a5 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/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(PBI->getCondition())) { + if (ICmpInst *RHS = dyn_cast(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. -- cgit v1.1