aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp37
1 files changed, 33 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 05b802c..536d880 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1077,6 +1077,22 @@ static void computeKnownBitsFromOperator(const Operator *I,
computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q);
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
+ Value *X = nullptr, *Y = nullptr;
+ // and(x, -x) is a common idiom for clearing all but lowest set bit. If we
+ // have a single known bit in x, we can clear all bits above it.
+ // TODO: instcombine often reassociates independent `and` which can hide
+ // this pattern. Try to match and(x, and(-x, y)) / and(and(x, y), -x).
+ if (!Known.One.isZero() || !Known2.One.isZero()) {
+ if (match(I, m_c_BinOp(m_Value(X), m_Neg(m_Deferred(X))))) {
+ // -(-x) == x so pick whichever we can get a better result with.
+ if (Known.countMaxTrailingZeros() <= Known2.countMaxTrailingZeros())
+ Known = Known.blsi();
+ else
+ Known = Known2.blsi();
+
+ break;
+ }
+ }
Known &= Known2;
// and(x, add (x, -1)) is a common idiom that always clears the low bit;
@@ -1084,7 +1100,6 @@ static void computeKnownBitsFromOperator(const Operator *I,
// matching the form add(x, add(x, y)) where y is odd.
// TODO: This could be generalized to clearing any bit set in y where the
// following bit is known to be unset in y.
- Value *X = nullptr, *Y = nullptr;
if (!Known.Zero[0] && !Known.One[0] &&
match(I, m_c_BinOp(m_Value(X), m_Add(m_Deferred(X), m_Value(Y))))) {
Known2.resetAll();
@@ -1100,12 +1115,26 @@ static void computeKnownBitsFromOperator(const Operator *I,
Known |= Known2;
break;
- case Instruction::Xor:
+ case Instruction::Xor: {
computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q);
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
- Known ^= Known2;
- break;
+ Value *X = nullptr;
+ // xor(x, x + -1) is a common idiom that will clear all bits above
+ // the lowest set bit. We can safely say any bit past the lowest
+ // known one must be zero.
+ // TODO: `x + -1` is often shrunk `x + C` which `C` is minimum bits needed
+ // for demanded. This can cause us to miss this pattern. Expand to account
+ // for `x + -1` in the context of demanded bits.
+ if ((!Known.One.isZero() || !Known2.One.isZero()) &&
+ match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_AllOnes())))) {
+ // Known2 is confusingly LHS.
+ const KnownBits &XBits = I->getOperand(0) == X ? Known2 : Known;
+ Known = XBits.blsmsk();
+ } else {
+ Known ^= Known2;
+ }
+ } break;
case Instruction::Mul: {
bool NSW = Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(I));
computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, DemandedElts,