diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 51e780c42af27..84882550117d8 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -77,7 +77,8 @@ static void testUnaryOpExhaustive(StringRef Name, UnaryBitsFn BitsFn, static void testBinaryOpExhaustive(StringRef Name, BinaryBitsFn BitsFn, BinaryIntFn IntFn, - bool CheckOptimality = true) { + bool CheckOptimality = true, + bool RefinePoisonToZero = false) { for (unsigned Bits : {1, 4}) { ForeachKnownBits(Bits, [&](const KnownBits &Known1) { ForeachKnownBits(Bits, [&](const KnownBits &Known2) { @@ -99,6 +100,12 @@ static void testBinaryOpExhaustive(StringRef Name, BinaryBitsFn BitsFn, EXPECT_TRUE(checkResult(Name, Exact, Computed, {Known1, Known2}, CheckOptimality)); } + // In some cases we choose to return zero if the result is always + // poison. + if (RefinePoisonToZero && Exact.hasConflict() && + !Known1.hasConflict() && !Known2.hasConflict()) { + EXPECT_TRUE(Computed.isZero()); + } }); }); } @@ -313,7 +320,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { testBinaryOpExhaustive( "udiv exact", [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::udiv(Known1, Known2, /*Exact*/ true); + return KnownBits::udiv(Known1, Known2, /*Exact=*/true); }, [](const APInt &N1, const APInt &N2) -> std::optional { if (N2.isZero() || !N1.urem(N2).isZero()) @@ -335,7 +342,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { testBinaryOpExhaustive( "sdiv exact", [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::sdiv(Known1, Known2, /*Exact*/ true); + return KnownBits::sdiv(Known1, Known2, /*Exact=*/true); }, [](const APInt &N1, const APInt &N2) -> std::optional { if (N2.isZero() || (N1.isMinSignedValue() && N2.isAllOnes()) || @@ -394,11 +401,11 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return N1.shl(N2); }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "ushl_ov", [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::shl(Known1, Known2, /* NUW */ true); + return KnownBits::shl(Known1, Known2, /*NUW=*/true); }, [](const APInt &N1, const APInt &N2) -> std::optional { bool Overflow; @@ -407,11 +414,11 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return Res; }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "shl nsw", [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::shl(Known1, Known2, /* NUW */ false, /* NSW */ true); + return KnownBits::shl(Known1, Known2, /*NUW=*/false, /*NSW=*/true); }, [](const APInt &N1, const APInt &N2) -> std::optional { bool Overflow; @@ -420,11 +427,11 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return Res; }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "shl nuw", [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::shl(Known1, Known2, /* NUW */ true, /* NSW */ true); + return KnownBits::shl(Known1, Known2, /*NUW=*/true, /*NSW=*/true); }, [](const APInt &N1, const APInt &N2) -> std::optional { bool OverflowUnsigned, OverflowSigned; @@ -434,7 +441,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return Res; }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "lshr", @@ -446,7 +453,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return N1.lshr(N2); }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "lshr exact", [](const KnownBits &Known1, const KnownBits &Known2) { @@ -460,7 +467,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return N1.lshr(N2); }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "ashr", [](const KnownBits &Known1, const KnownBits &Known2) { @@ -471,7 +478,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return N1.ashr(N2); }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "ashr exact", [](const KnownBits &Known1, const KnownBits &Known2) { @@ -485,7 +492,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { return std::nullopt; return N1.ashr(N2); }, - /*CheckOptimality=*/true); + /*CheckOptimality=*/true, /*RefinePoisonToZero=*/true); testBinaryOpExhaustive( "mul", [](const KnownBits &Known1, const KnownBits &Known2) { @@ -538,7 +545,7 @@ TEST(KnownBitsTest, UnaryExhaustive) { testUnaryOpExhaustive( "mul self", [](const KnownBits &Known) { - return KnownBits::mul(Known, Known, /*SelfMultiply*/ true); + return KnownBits::mul(Known, Known, /*SelfMultiply=*/true); }, [](const APInt &N) { return N * N; }, /*CheckOptimality=*/false); } @@ -709,8 +716,8 @@ TEST(KnownBitsTest, SExtOrTrunc) { const unsigned NarrowerSize = 4; const unsigned BaseSize = 6; const unsigned WiderSize = 8; - APInt NegativeFitsNarrower(BaseSize, -4, /*isSigned*/ true); - APInt NegativeDoesntFitNarrower(BaseSize, -28, /*isSigned*/ true); + APInt NegativeFitsNarrower(BaseSize, -4, /*isSigned=*/true); + APInt NegativeDoesntFitNarrower(BaseSize, -28, /*isSigned=*/true); APInt PositiveFitsNarrower(BaseSize, 14); APInt PositiveDoesntFitNarrower(BaseSize, 36); auto InitKnownBits = [&](KnownBits &Res, const APInt &Input) {