diff options
author | Nikita Popov <npopov@redhat.com> | 2023-11-27 16:50:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-27 16:50:05 +0100 |
commit | 28a5e6b069ee7540cd0965a0ad6cf0475db8d68c (patch) | |
tree | bc3c50003f2fcd9f6a40fa6d55dd1f04a9248b12 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 936180a5e8816b2d02393b8faa535bcd37ac9b42 (diff) | |
download | llvm-28a5e6b069ee7540cd0965a0ad6cf0475db8d68c.zip llvm-28a5e6b069ee7540cd0965a0ad6cf0475db8d68c.tar.gz llvm-28a5e6b069ee7540cd0965a0ad6cf0475db8d68c.tar.bz2 |
[InstCombine] Remove over-generalization from computeKnownBitsFromCmp() (#72637)
For most practical purposes, the only KnownBits patterns we care about are
those involving a constant comparison RHS and constant mask. However,
the actual implementation is written in a very general way -- and of
course, with basically no test coverage of those generalizations.
This patch reduces the implementation to only handle cases with constant
operands. The test changes are all in "make sure we don't crash" tests.
The motivation for this change is an upcoming patch to handling dominating
conditions in computeKnownBits(). Handling non-constant RHS would add
significant additional compile-time overhead in that case, without any
significant impact on optimization quality.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 134 |
1 files changed, 61 insertions, 73 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index baf9f488..cda9c12 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -633,101 +633,89 @@ static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) { static void computeKnownBitsFromCmp(const Value *V, const ICmpInst *Cmp, KnownBits &Known, unsigned Depth, const SimplifyQuery &Q) { + if (Cmp->getOperand(1)->getType()->isPointerTy()) { + // Handle comparison of pointer to null explicitly, as it will not be + // covered by the m_APInt() logic below. + if (match(Cmp->getOperand(1), m_Zero())) { + switch (Cmp->getPredicate()) { + case ICmpInst::ICMP_EQ: + Known.setAllZero(); + break; + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_SGT: + Known.makeNonNegative(); + break; + case ICmpInst::ICMP_SLT: + Known.makeNegative(); + break; + default: + break; + } + } + return; + } + unsigned BitWidth = Known.getBitWidth(); - // We are attempting to compute known bits for the operands of an assume. - // Do not try to use other assumptions for those recursive calls because - // that can lead to mutual recursion and a compile-time explosion. - // An example of the mutual recursion: computeKnownBits can call - // isKnownNonZero which calls computeKnownBitsFromAssume (this function) - // and so on. - SimplifyQuery QueryNoAC = Q; - QueryNoAC.AC = nullptr; - - // Note that ptrtoint may change the bitwidth. - Value *A, *B; auto m_V = m_CombineOr(m_Specific(V), m_PtrToIntSameSize(Q.DL, m_Specific(V))); CmpInst::Predicate Pred; - uint64_t C; + const APInt *Mask, *C; + uint64_t ShAmt; switch (Cmp->getPredicate()) { case ICmpInst::ICMP_EQ: - // assume(v = a) - if (match(Cmp, m_c_ICmp(Pred, m_V, m_Value(A)))) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - Known = Known.unionWith(RHSKnown); - // assume(v & b = a) - } else if (match(Cmp, - m_c_ICmp(Pred, m_c_And(m_V, m_Value(B)), m_Value(A)))) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - KnownBits MaskKnown = computeKnownBits(B, Depth + 1, QueryNoAC); - - // For those bits in the mask that are known to be one, we can propagate - // known bits from the RHS to V. - Known.Zero |= RHSKnown.Zero & MaskKnown.One; - Known.One |= RHSKnown.One & MaskKnown.One; - // assume(v | b = a) + // assume(V = C) + if (match(Cmp, m_ICmp(Pred, m_V, m_APInt(C)))) { + Known = Known.unionWith(KnownBits::makeConstant(*C)); + // assume(V & Mask = C) } else if (match(Cmp, - m_c_ICmp(Pred, m_c_Or(m_V, m_Value(B)), m_Value(A)))) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - KnownBits BKnown = computeKnownBits(B, Depth + 1, QueryNoAC); - - // For those bits in B that are known to be zero, we can propagate known - // bits from the RHS to V. - Known.Zero |= RHSKnown.Zero & BKnown.Zero; - Known.One |= RHSKnown.One & BKnown.Zero; - // assume(v ^ b = a) + m_ICmp(Pred, m_And(m_V, m_APInt(Mask)), m_APInt(C)))) { + // For one bits in Mask, we can propagate bits from C to V. + Known.Zero |= ~*C & *Mask; + Known.One |= *C & *Mask; + // assume(V | Mask = C) + } else if (match(Cmp, m_ICmp(Pred, m_Or(m_V, m_APInt(Mask)), m_APInt(C)))) { + // For zero bits in Mask, we can propagate bits from C to V. + Known.Zero |= ~*C & ~*Mask; + Known.One |= *C & ~*Mask; + // assume(V ^ Mask = C) } else if (match(Cmp, - m_c_ICmp(Pred, m_c_Xor(m_V, m_Value(B)), m_Value(A)))) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - KnownBits BKnown = computeKnownBits(B, Depth + 1, QueryNoAC); - - // For those bits in B that are known to be zero, we can propagate known - // bits from the RHS to V. For those bits in B that are known to be one, - // we can propagate inverted known bits from the RHS to V. - Known.Zero |= RHSKnown.Zero & BKnown.Zero; - Known.One |= RHSKnown.One & BKnown.Zero; - Known.Zero |= RHSKnown.One & BKnown.One; - Known.One |= RHSKnown.Zero & BKnown.One; - // assume(v << c = a) - } else if (match(Cmp, m_c_ICmp(Pred, m_Shl(m_V, m_ConstantInt(C)), - m_Value(A))) && - C < BitWidth) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - - // For those bits in RHS that are known, we can propagate them to known - // bits in V shifted to the right by C. - RHSKnown.Zero.lshrInPlace(C); - RHSKnown.One.lshrInPlace(C); + m_ICmp(Pred, m_Xor(m_V, m_APInt(Mask)), m_APInt(C)))) { + // Equivalent to assume(V == Mask ^ C) + Known = Known.unionWith(KnownBits::makeConstant(*C ^ *Mask)); + // assume(V << ShAmt = C) + } else if (match(Cmp, m_ICmp(Pred, m_Shl(m_V, m_ConstantInt(ShAmt)), + m_APInt(C))) && + ShAmt < BitWidth) { + // For those bits in C that are known, we can propagate them to known + // bits in V shifted to the right by ShAmt. + KnownBits RHSKnown = KnownBits::makeConstant(*C); + RHSKnown.Zero.lshrInPlace(ShAmt); + RHSKnown.One.lshrInPlace(ShAmt); Known = Known.unionWith(RHSKnown); - // assume(v >> c = a) - } else if (match(Cmp, m_c_ICmp(Pred, m_Shr(m_V, m_ConstantInt(C)), - m_Value(A))) && - C < BitWidth) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); + // assume(V >> ShAmt = C) + } else if (match(Cmp, m_ICmp(Pred, m_Shr(m_V, m_ConstantInt(ShAmt)), + m_APInt(C))) && + ShAmt < BitWidth) { + KnownBits RHSKnown = KnownBits::makeConstant(*C); // For those bits in RHS that are known, we can propagate them to known // bits in V shifted to the right by C. - Known.Zero |= RHSKnown.Zero << C; - Known.One |= RHSKnown.One << C; + Known.Zero |= RHSKnown.Zero << ShAmt; + Known.One |= RHSKnown.One << ShAmt; } break; case ICmpInst::ICMP_NE: { - // assume (v & b != 0) where b is a power of 2 + // assume (V & B != 0) where B is a power of 2 const APInt *BPow2; - if (match(Cmp, m_ICmp(Pred, m_c_And(m_V, m_Power2(BPow2)), m_Zero()))) { + if (match(Cmp, m_ICmp(Pred, m_And(m_V, m_Power2(BPow2)), m_Zero()))) Known.One |= *BPow2; - } break; } default: const APInt *Offset = nullptr; if (match(Cmp, m_ICmp(Pred, m_CombineOr(m_V, m_Add(m_V, m_APInt(Offset))), - m_Value(A)))) { - KnownBits RHSKnown = computeKnownBits(A, Depth + 1, QueryNoAC); - ConstantRange RHSRange = - ConstantRange::fromKnownBits(RHSKnown, Cmp->isSigned()); - ConstantRange LHSRange = - ConstantRange::makeAllowedICmpRegion(Pred, RHSRange); + m_APInt(C)))) { + ConstantRange LHSRange = ConstantRange::makeAllowedICmpRegion(Pred, *C); if (Offset) LHSRange = LHSRange.sub(*Offset); Known = Known.unionWith(LHSRange.toKnownBits()); |