diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index 07fd94e29a1fb..df0b02c1335d4 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -107,6 +107,18 @@ struct KnownBits { Zero.setSignBit(); } + /// Return the minimal value possible given these KnownBits. + APInt getMinValue() const { + // Assume that all bits that aren't known-ones are zeros. + return One; + } + + /// Return the maximal value possible given these KnownBits. + APInt getMaxValue() const { + // Assume that all bits that aren't known-zeros are ones. + return ~Zero; + } + /// Truncate the underlying known Zero and One bits. This is equivalent /// to truncating the value we're tracking. KnownBits trunc(unsigned BitWidth) const { diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 483159bef987f..d635afb0a299c 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5717,10 +5717,11 @@ ScalarEvolution::getRangeRef(const SCEV *S, if (SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED) { // For a SCEVUnknown, ask ValueTracking. KnownBits Known = computeKnownBits(U->getValue(), DL, 0, &AC, nullptr, &DT); - if (Known.One != ~Known.Zero + 1) - ConservativeResult = - ConservativeResult.intersectWith( - ConstantRange(Known.One, ~Known.Zero + 1), RangeType); + // If Known does not result in full-set, intersect with it. + if (Known.getMinValue() != Known.getMaxValue() + 1) + ConservativeResult = ConservativeResult.intersectWith( + ConstantRange(Known.getMinValue(), Known.getMaxValue() + 1), + RangeType); } else { assert(SignHint == ScalarEvolution::HINT_RANGE_SIGNED && "generalize as needed!"); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 51d92cca214ba..f46bae77ba269 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -915,7 +915,7 @@ static void computeKnownBitsFromShiftOperator( // If the shift amount could be greater than or equal to the bit-width of the // LHS, the value could be poison, but bail out because the check below is // expensive. TODO: Should we just carry on? - if ((~Known.Zero).uge(BitWidth)) { + if (Known.getMaxValue().uge(BitWidth)) { Known.resetAll(); return; } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a20e43462f707..5dbdde5d8ea9b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3350,20 +3350,20 @@ SelectionDAG::OverflowKind SelectionDAG::computeOverflowKind(SDValue N0, KnownBits N0Known = computeKnownBits(N0); bool overflow; - (void)(~N0Known.Zero).uadd_ov(~N1Known.Zero, overflow); + (void)N0Known.getMaxValue().uadd_ov(N1Known.getMaxValue(), overflow); if (!overflow) return OFK_Never; } // mulhi + 1 never overflow if (N0.getOpcode() == ISD::UMUL_LOHI && N0.getResNo() == 1 && - (~N1Known.Zero & 0x01) == ~N1Known.Zero) + (N1Known.getMaxValue() & 0x01) == N1Known.getMaxValue()) return OFK_Never; if (N1.getOpcode() == ISD::UMUL_LOHI && N1.getResNo() == 1) { KnownBits N0Known = computeKnownBits(N0); - if ((~N0Known.Zero & 0x01) == ~N0Known.Zero) + if ((N0Known.getMaxValue() & 0x01) == N0Known.getMaxValue()) return OFK_Never; } diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 68c3c7ad90dab..2a8ea0657dbb6 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -64,11 +64,11 @@ ConstantRange ConstantRange::fromKnownBits(const KnownBits &Known, // For unsigned ranges, or signed ranges with known sign bit, create a simple // range between the smallest and largest possible value. if (!IsSigned || Known.isNegative() || Known.isNonNegative()) - return ConstantRange(Known.One, ~Known.Zero + 1); + return ConstantRange(Known.getMinValue(), Known.getMaxValue() + 1); // If we don't know the sign bit, pick the lower bound as a negative number // and the upper bound as a non-negative one. - APInt Lower = Known.One, Upper = ~Known.Zero; + APInt Lower = Known.getMinValue(), Upper = Known.getMaxValue(); Lower.setSignBit(); Upper.clearSignBit(); return ConstantRange(Lower, Upper + 1); diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index a6c591fca3121..8f3f4aa8caeaf 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -21,8 +21,8 @@ static KnownBits computeForAddCarry( assert(!(CarryZero && CarryOne) && "Carry can't be zero and one at the same time"); - APInt PossibleSumZero = ~LHS.Zero + ~RHS.Zero + !CarryZero; - APInt PossibleSumOne = LHS.One + RHS.One + CarryOne; + APInt PossibleSumZero = LHS.getMaxValue() + RHS.getMaxValue() + !CarryZero; + APInt PossibleSumOne = LHS.getMinValue() + RHS.getMinValue() + CarryOne; // Compute known bits of the carry. APInt CarryKnownZero = ~(PossibleSumZero ^ LHS.Zero ^ RHS.Zero); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index f8adca740a681..7994176c4c265 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -3609,7 +3609,7 @@ SDValue SystemZTargetLowering::lowerCTPOP(SDValue Op, // Get the known-zero mask for the operand. KnownBits Known = DAG.computeKnownBits(Op); - unsigned NumSignificantBits = (~Known.Zero).getActiveBits(); + unsigned NumSignificantBits = Known.getMaxValue().getActiveBits(); if (NumSignificantBits == 0) return DAG.getConstant(0, DL, VT); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index c2b3b127cf178..372521dc5c923 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -127,4 +127,18 @@ TEST(KnownBitsTest, AddSubExhaustive) { TestAddSubExhaustive(false); } +TEST(KnownBitsTest, GetMinMaxVal) { + unsigned Bits = 4; + ForeachKnownBits(Bits, [&](const KnownBits &Known) { + APInt Min = APInt::getMaxValue(Bits); + APInt Max = APInt::getMinValue(Bits); + ForeachNumInKnownBits(Known, [&](const APInt &N) { + Min = APIntOps::umin(Min, N); + Max = APIntOps::umax(Max, N); + }); + EXPECT_EQ(Min, Known.getMinValue()); + EXPECT_EQ(Max, Known.getMaxValue()); + }); +} + } // end anonymous namespace