Index: llvm/lib/IR/ConstantRange.cpp =================================================================== --- llvm/lib/IR/ConstantRange.cpp +++ llvm/lib/IR/ConstantRange.cpp @@ -1256,12 +1256,6 @@ } ConstantRange ConstantRange::binaryNot() const { - if (isEmptySet()) - return getEmpty(); - - if (isWrappedSet()) - return getFull(); - return ConstantRange(APInt::getAllOnesValue(getBitWidth())).sub(*this); } Index: llvm/unittests/IR/ConstantRangeTest.cpp =================================================================== --- llvm/unittests/IR/ConstantRangeTest.cpp +++ llvm/unittests/IR/ConstantRangeTest.cpp @@ -70,11 +70,11 @@ if (SkipSignedIntMin && N.isMinSignedValue()) return; - APInt AbsN = IntFn(N); - if (AbsN.ult(Min)) - Min = AbsN; - if (AbsN.ugt(Max)) - Max = AbsN; + APInt ResultN = IntFn(N); + if (ResultN.ult(Min)) + Min = ResultN; + if (ResultN.ugt(Max)) + Max = ResultN; }); ConstantRange ResultCR = RangeFn(CR); @@ -88,6 +88,45 @@ }); } +// Test unary operator without a sign preference. This checks that the +// computed range is exact, rather than being exact up to the unsigned/signed +// envelope. +template +static void TestSignlessUnaryOpExhaustive(Fn1 RangeFn, Fn2 IntFn) { + unsigned Bits = 4; + EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) { + bool Empty = true; + APInt Min, Max; + ForeachNumInConstantRange(CR, [&](const APInt &N) { + APInt ResultN = IntFn(N); + if (Empty) { + Empty = false; + Min = Max = ResultN; + return; + } + + APInt DistFromMin = ResultN - Min; + if (DistFromMin.ult(Max - Min)) + return; // Already in the range. + + APInt DistFromMax = ResultN - Max; + if (DistFromMax.ult(-DistFromMin)) + Max = ResultN; + else + Min = ResultN; + }); + + ConstantRange ResultCR = RangeFn(CR); + if (Empty) { + EXPECT_TRUE(ResultCR.isEmptySet()); + return; + } + + ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1); + EXPECT_EQ(Exact, ResultCR); + }); +} + template static void TestUnsignedBinOpExhaustive( Fn1 RangeFn, Fn2 IntFn, @@ -2403,16 +2442,16 @@ } TEST_F(ConstantRangeTest, binaryNot) { - TestUnsignedUnaryOpExhaustive( + TestSignlessUnaryOpExhaustive( [](const ConstantRange &CR) { return CR.binaryNot(); }, [](const APInt &N) { return ~N; }); - TestUnsignedUnaryOpExhaustive( + TestSignlessUnaryOpExhaustive( [](const ConstantRange &CR) { return CR.binaryXor( ConstantRange(APInt::getAllOnesValue(CR.getBitWidth()))); }, [](const APInt &N) { return ~N; }); - TestUnsignedUnaryOpExhaustive( + TestSignlessUnaryOpExhaustive( [](const ConstantRange &CR) { return ConstantRange(APInt::getAllOnesValue(CR.getBitWidth())) .binaryXor(CR);