diff options
-rw-r--r-- | llvm/include/llvm/Analysis/ValueTracking.h | 6 | ||||
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 41 | ||||
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 33 |
4 files changed, 52 insertions, 60 deletions
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index a92ba8e374f..7c2e9a65ac2 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -610,6 +610,12 @@ class Value; Optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL, bool LHSIsTrue = true, unsigned Depth = 0); + + /// Return the boolean condition value in the context of the given instruction + /// if it is known based on dominating conditions. + Optional<bool> isImpliedByDomCondition(const Value *Cond, + const Instruction *ContextI, + const DataLayout &DL); } // end namespace llvm #endif // LLVM_ANALYSIS_VALUETRACKING_H diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index ddebcfaad06..120a024ed60 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3924,42 +3924,6 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F) { return nullptr; } -/// Try to determine the result of a select based on a dominating condition. -static Value *foldSelectWithDominatingCond(Value *Cond, Value *TV, Value *FV, - const SimplifyQuery &Q) { - // First, make sure that we have a select in a basic block. - // We don't know if we are called from some incomplete state. - if (!Q.CxtI || !Q.CxtI->getParent()) - return nullptr; - - // TODO: This is a poor/cheap way to determine dominance. Should we use the - // dominator tree in the SimplifyQuery instead? - const BasicBlock *SelectBB = Q.CxtI->getParent(); - const BasicBlock *PredBB = SelectBB->getSinglePredecessor(); - if (!PredBB) - return nullptr; - - // We need a conditional branch in the predecessor. - Value *PredCond; - BasicBlock *TrueBB, *FalseBB; - if (!match(PredBB->getTerminator(), m_Br(m_Value(PredCond), TrueBB, FalseBB))) - return nullptr; - - // The branch should get simplified. Don't bother simplifying the select. - if (TrueBB == FalseBB) - return nullptr; - - assert((TrueBB == SelectBB || FalseBB == SelectBB) && - "Predecessor block does not point to successor?"); - - // Is the select condition implied by the predecessor condition? - bool CondIsTrue = TrueBB == SelectBB; - Optional<bool> Implied = isImpliedCondition(PredCond, Cond, Q.DL, CondIsTrue); - if (!Implied) - return nullptr; - return *Implied ? TV : FV; -} - /// Given operands for a SelectInst, see if we can fold the result. /// If not, this returns null. static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, @@ -4002,8 +3966,9 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal)) return V; - if (Value *V = foldSelectWithDominatingCond(Cond, TrueVal, FalseVal, Q)) - return V; + Optional<bool> Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL); + if (Imp) + return *Imp ? TrueVal : FalseVal; return nullptr; } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 3c01d979560..a6ad6bf8cae 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5378,3 +5378,35 @@ Optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS, } return None; } + +Optional<bool> llvm::isImpliedByDomCondition(const Value *Cond, + const Instruction *ContextI, + const DataLayout &DL) { + assert(Cond->getType()->isIntOrIntVectorTy(1) && "Condition must be bool"); + if (!ContextI || !ContextI->getParent()) + return None; + + // TODO: This is a poor/cheap way to determine dominance. Should we use a + // dominator tree (eg, from a SimplifyQuery) instead? + const BasicBlock *ContextBB = ContextI->getParent(); + const BasicBlock *PredBB = ContextBB->getSinglePredecessor(); + if (!PredBB) + return None; + + // We need a conditional branch in the predecessor. + Value *PredCond; + BasicBlock *TrueBB, *FalseBB; + if (!match(PredBB->getTerminator(), m_Br(m_Value(PredCond), TrueBB, FalseBB))) + return None; + + // The branch should get simplified. Don't bother simplifying this condition. + if (TrueBB == FalseBB) + return None; + + assert((TrueBB == ContextBB || FalseBB == ContextBB) && + "Predecessor block does not point to successor?"); + + // Is this condition implied by the predecessor condition? + bool CondIsTrue = TrueBB == ContextBB; + return isImpliedCondition(PredCond, Cond, DL, CondIsTrue); +} diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index ef5f750df1e..b98f2fff65e 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5854,28 +5854,17 @@ bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) { if (SimplifyBranchOnICmpChain(BI, Builder, DL)) return true; - // If this basic block has a single dominating predecessor block and the - // dominating block's condition implies BI's condition, we know the direction - // of the BI branch. - if (BasicBlock *Dom = BB->getSinglePredecessor()) { - auto *PBI = dyn_cast_or_null<BranchInst>(Dom->getTerminator()); - if (PBI && PBI->isConditional() && - PBI->getSuccessor(0) != PBI->getSuccessor(1)) { - assert(PBI->getSuccessor(0) == BB || PBI->getSuccessor(1) == BB); - bool CondIsTrue = PBI->getSuccessor(0) == BB; - Optional<bool> Implication = isImpliedCondition( - PBI->getCondition(), BI->getCondition(), DL, CondIsTrue); - if (Implication) { - // Turn this into a branch on constant. - auto *OldCond = BI->getCondition(); - ConstantInt *CI = *Implication - ? ConstantInt::getTrue(BB->getContext()) - : ConstantInt::getFalse(BB->getContext()); - BI->setCondition(CI); - RecursivelyDeleteTriviallyDeadInstructions(OldCond); - return requestResimplify(); - } - } + // If this basic block has dominating predecessor blocks and the dominating + // blocks' conditions imply BI's condition, we know the direction of BI. + Optional<bool> Imp = isImpliedByDomCondition(BI->getCondition(), BI, DL); + if (Imp) { + // Turn this into a branch on constant. + auto *OldCond = BI->getCondition(); + ConstantInt *TorF = *Imp ? ConstantInt::getTrue(BB->getContext()) + : ConstantInt::getFalse(BB->getContext()); + BI->setCondition(TorF); + RecursivelyDeleteTriviallyDeadInstructions(OldCond); + return requestResimplify(); } // If this basic block is ONLY a compare and a branch, and if a predecessor |