summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2019-12-18 20:24:38 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2019-12-20 01:47:57 +0300
commit047186cc986f5bb53ce716dfe363ba517b7d0ed8 (patch)
treee021c5b0ab7f82e971753e1665a37bc8597924bc /llvm/lib/Analysis/ValueTracking.cpp
parent92083a295a02f46ecd168438d2145a0ca3c9b6ec (diff)
downloadbcm5719-llvm-047186cc986f5bb53ce716dfe363ba517b7d0ed8.tar.gz
bcm5719-llvm-047186cc986f5bb53ce716dfe363ba517b7d0ed8.zip
[ValueTracking] isKnownNonZero() should take non-null-ness assumptions into consideration (PR43267)
Summary: It is pretty common to assume that something is not zero. Even optimizer itself sometimes emits such assumptions (e.g. `addAssumeNonNull()` in `PromoteMemoryToRegister.cpp`). But we currently don't deal with such assumptions :) The only way `isKnownNonZero()` handles assumptions is by calling `computeKnownBits()` which calls `computeKnownBitsFromAssume()`. But `x != 0` does not tell us anything about set bits, it only says that there are *some* set bits. So naturally, `KnownBits` does not get populated, and we fail to make use of this assumption. I propose to deal with this special case by special-casing it via adding a `isKnownNonZeroFromAssume()` that returns boolean when there is an applicable assumption. While there, we also deal with other predicates, mainly if the comparison is with constant. Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=43267 | PR43267 ]]. Differential Revision: https://reviews.llvm.org/D71660
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c98140e2e93..ad6765e2514 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -576,6 +576,73 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv,
return !isEphemeralValueOf(Inv, CxtI);
}
+static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) {
+ // Use of assumptions is context-sensitive. If we don't have a context, we
+ // cannot use them!
+ if (!Q.AC || !Q.CxtI)
+ return false;
+
+ // Note that the patterns below need to be kept in sync with the code
+ // in AssumptionCache::updateAffectedValues.
+
+ auto CmpExcludesZero = [V](ICmpInst *Cmp) {
+ auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V)));
+
+ Value *RHS;
+ CmpInst::Predicate Pred;
+ if (!match(Cmp, m_c_ICmp(Pred, m_V, m_Value(RHS))))
+ return false;
+ // Canonicalize 'v' to be on the LHS of the comparison.
+ if (Cmp->getOperand(1) != RHS)
+ Pred = CmpInst::getSwappedPredicate(Pred);
+
+ // assume(v u> y) -> assume(v != 0)
+ if (Pred == ICmpInst::ICMP_UGT)
+ return true;
+
+ // assume(v != 0)
+ // We special-case this one to ensure that we handle `assume(v != null)`.
+ if (Pred == ICmpInst::ICMP_NE)
+ return match(RHS, m_Zero());
+
+ // All other predicates - rely on generic ConstantRange handling.
+ ConstantInt *CI;
+ if (!match(RHS, m_ConstantInt(CI)))
+ return false;
+ ConstantRange RHSRange(CI->getValue());
+ ConstantRange TrueValues =
+ ConstantRange::makeAllowedICmpRegion(Pred, RHSRange);
+ return !TrueValues.contains(APInt::getNullValue(CI->getBitWidth()));
+ };
+
+ for (auto &AssumeVH : Q.AC->assumptionsFor(V)) {
+ if (!AssumeVH)
+ continue;
+ CallInst *I = cast<CallInst>(AssumeVH);
+ assert(I->getFunction() == Q.CxtI->getFunction() &&
+ "Got assumption for the wrong function!");
+ if (Q.isExcluded(I))
+ continue;
+
+ // Warning: This loop can end up being somewhat performance sensitive.
+ // We're running this loop for once for each value queried resulting in a
+ // runtime of ~O(#assumes * #values).
+
+ assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
+ "must be an assume intrinsic");
+
+ Value *Arg = I->getArgOperand(0);
+ ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
+ if (!Cmp)
+ continue;
+
+ if (CmpExcludesZero(Cmp) && isValidAssumeForContext(I, Q.CxtI, Q.DT))
+ return true;
+ }
+
+ return false;
+}
+
static void computeKnownBitsFromAssume(const Value *V, KnownBits &Known,
unsigned Depth, const Query &Q) {
// Use of assumptions is context-sensitive. If we don't have a context, we
@@ -2079,6 +2146,9 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
}
}
+ if (isKnownNonZeroFromAssume(V, Q))
+ return true;
+
// Some of the tests below are recursive, so bail out if we hit the limit.
if (Depth++ >= MaxDepth)
return false;
OpenPOWER on IntegriCloud