aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorMax Kazantsev <max.kazantsev@azul.com>2018-08-06 06:11:36 +0000
committerMax Kazantsev <max.kazantsev@azul.com>2018-08-06 06:11:36 +0000
commit34b0666be9e62b328c6c2adb7c649ea0656c8a7a (patch)
tree54ac7b7f001d8f7979b74f20e02d46b17607422d /llvm/lib/Analysis/ValueTracking.cpp
parent3bec3abf3877c2187582b18cdd0c4a88415139ed (diff)
downloadllvm-34b0666be9e62b328c6c2adb7c649ea0656c8a7a.zip
llvm-34b0666be9e62b328c6c2adb7c649ea0656c8a7a.tar.gz
llvm-34b0666be9e62b328c6c2adb7c649ea0656c8a7a.tar.bz2
[ValueTracking] Teach isKnownNonNullFromDominatingCondition about AND
`isKnownNonNullFromDominatingCondition` is able to prove non-null basing on `br` or `guard` by `%p != null` condition, but is unable to do so basing on `(%p != null) && %other_cond`. This patch allows it to do so. Differential Revision: https://reviews.llvm.org/D50172 Reviewed By: reames llvm-svn: 338990
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp38
1 files changed, 28 insertions, 10 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index edd46c5..65c5d0e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1861,18 +1861,36 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
continue;
for (auto *CmpU : U->users()) {
- if (const BranchInst *BI = dyn_cast<BranchInst>(CmpU)) {
- assert(BI->isConditional() && "uses a comparison!");
+ SmallVector<const User *, 4> WorkList;
+ SmallPtrSet<const User *, 4> Visited;
+ Visited.insert(CmpU);
+ WorkList.push_back(CmpU);
+
+ while (!WorkList.empty()) {
+ auto *Curr = WorkList.pop_back_val();
+
+ // If a user is an AND, add all its users to the work list.
+ if (auto *BO = dyn_cast<BinaryOperator>(Curr))
+ if (BO->getOpcode() == Instruction::And) {
+ for (auto *BOU : BO->users())
+ if (Visited.insert(BOU).second)
+ WorkList.push_back(BOU);
+ continue;
+ }
+
+ if (const BranchInst *BI = dyn_cast<BranchInst>(Curr)) {
+ assert(BI->isConditional() && "uses a comparison!");
- BasicBlock *NonNullSuccessor =
- BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
- BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
- if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
+ BasicBlock *NonNullSuccessor =
+ BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
+ BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
+ if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
+ return true;
+ } else if (Pred == ICmpInst::ICMP_NE &&
+ match(Curr, m_Intrinsic<Intrinsic::experimental_guard>()) &&
+ DT->dominates(cast<Instruction>(Curr), CtxI)) {
return true;
- } else if (Pred == ICmpInst::ICMP_NE &&
- match(CmpU, m_Intrinsic<Intrinsic::experimental_guard>()) &&
- DT->dominates(cast<Instruction>(CmpU), CtxI)) {
- return true;
+ }
}
}
}