summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/InstructionSimplify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 9fc10af9668..ddebcfaad06 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3924,6 +3924,42 @@ 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,
@@ -3966,6 +4002,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;
+
return nullptr;
}
OpenPOWER on IntegriCloud