From: Nikita Popov Date: Fri, 13 Nov 2020 21:17:26 +0000 (+0100) Subject: [KnownBits] Combine abs() implementations X-Git-Tag: llvmorg-13-init~6112 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9a85643cd357e412cff69067bb5c4840e228c2ab;p=platform%2Fupstream%2Fllvm.git [KnownBits] Combine abs() implementations ValueTracking was using a more powerful abs() implementation. Roll it into KnownBits::abs(). Also add an exhaustive test for abs(), in both the poisoning and non-poisoning variants. --- diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index b43fde0..4c4cd35 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -326,7 +326,7 @@ public: KnownBits &operator^=(const KnownBits &RHS); /// Compute known bits for the absolute value. - KnownBits abs() const; + KnownBits abs(bool IntMinIsPoison = false) const; KnownBits byteSwap() { return KnownBits(Zero.byteSwap(), One.byteSwap()); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index e6d3727..a3c139d 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1511,28 +1511,12 @@ static void computeKnownBitsFromOperator(const Operator *I, if (const IntrinsicInst *II = dyn_cast(I)) { switch (II->getIntrinsicID()) { default: break; - case Intrinsic::abs: + case Intrinsic::abs: { computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q); - - // If the source's MSB is zero then we know the rest of the bits. - if (Known2.isNonNegative()) { - Known.Zero |= Known2.Zero; - Known.One |= Known2.One; - break; - } - - // Absolute value preserves trailing zero count. - Known.Zero.setLowBits(Known2.Zero.countTrailingOnes()); - - // If this call is undefined for INT_MIN, the result is positive. We - // also know it can't be INT_MIN if there is a set bit that isn't the - // sign bit. - Known2.One.clearSignBit(); - if (match(II->getArgOperand(1), m_One()) || Known2.One.getBoolValue()) - Known.Zero.setSignBit(); - // FIXME: Handle known negative input? - // FIXME: Calculate the negated Known bits and combine them? + bool IntMinIsPoison = match(II->getArgOperand(1), m_One()); + Known = Known2.abs(IntMinIsPoison); break; + } case Intrinsic::bitreverse: computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q); Known.Zero |= Known2.Zero.reverseBits(); diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index 7b94e7b..748abf8 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -233,21 +233,23 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS) { return Known; } -KnownBits KnownBits::abs() const { +KnownBits KnownBits::abs(bool IntMinIsPoison) const { // If the source's MSB is zero then we know the rest of the bits already. if (isNonNegative()) return *this; - // Assume we know nothing. + // Absolute value preserves trailing zero count. KnownBits KnownAbs(getBitWidth()); + KnownAbs.Zero.setLowBits(countMinTrailingZeros()); - // We only know that the absolute values's MSB will be zero iff there is - // a set bit that isn't the sign bit (otherwise it could be INT_MIN). - APInt Val = One; - Val.clearSignBit(); - if (!Val.isNullValue()) + // We only know that the absolute values's MSB will be zero if INT_MIN is + // poison, or there is a set bit that isn't the sign bit (otherwise it could + // be INT_MIN). + if (IntMinIsPoison || (!One.isNullValue() && !One.isMinSignedValue())) KnownAbs.Zero.setSignBit(); + // FIXME: Handle known negative input? + // FIXME: Calculate the negated Known bits and combine them? return KnownAbs; } diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 709a3fc..c5eb96e 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -251,6 +251,36 @@ TEST(KnownBitsTest, BinaryExhaustive) { }); } +TEST(KnownBitsTest, UnaryExhaustive) { + unsigned Bits = 4; + ForeachKnownBits(Bits, [&](const KnownBits &Known) { + KnownBits KnownAbs(Bits); + KnownAbs.Zero.setAllBits(); + KnownAbs.One.setAllBits(); + KnownBits KnownAbsPoison(KnownAbs); + + ForeachNumInKnownBits(Known, [&](const APInt &N) { + APInt Res = N.abs(); + KnownAbs.One &= Res; + KnownAbs.Zero &= ~Res; + + if (!N.isMinSignedValue()) { + KnownAbsPoison.One &= Res; + KnownAbsPoison.Zero &= ~Res; + } + }); + + // abs() is conservatively correct, but not guaranteed to be precise. + KnownBits ComputedAbs = Known.abs(); + EXPECT_TRUE(ComputedAbs.Zero.isSubsetOf(KnownAbs.Zero)); + EXPECT_TRUE(ComputedAbs.One.isSubsetOf(KnownAbs.One)); + + KnownBits ComputedAbsPoison = Known.abs(true); + EXPECT_TRUE(ComputedAbsPoison.Zero.isSubsetOf(KnownAbsPoison.Zero)); + EXPECT_TRUE(ComputedAbsPoison.One.isSubsetOf(KnownAbsPoison.One)); + }); +} + TEST(KnownBitsTest, GetMinMaxVal) { unsigned Bits = 4; ForeachKnownBits(Bits, [&](const KnownBits &Known) {