diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 551c1a8107494..b16368de17648 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -815,4 +815,38 @@ TEST(KnownBitsTest, ConcatBits) { } } +TEST(KnownBitsTest, MulExhaustive) { + for (unsigned Bits : {1, 4}) { + ForeachKnownBits(Bits, [&](const KnownBits &Known1) { + ForeachKnownBits(Bits, [&](const KnownBits &Known2) { + KnownBits Computed = KnownBits::mul(Known1, Known2); + KnownBits Exact(Bits); + Exact.Zero.setAllBits(); + Exact.One.setAllBits(); + + ForeachNumInKnownBits(Known1, [&](const APInt &N1) { + ForeachNumInKnownBits(Known2, [&](const APInt &N2) { + APInt Res = N1 * N2; + Exact.One &= Res; + Exact.Zero &= ~Res; + }); + }); + + if (!Exact.hasConflict()) { + // Check that the result is optimal for the contiguous known low order + // bits. + APInt Mask = APInt::getLowBitsSet( + Bits, (Exact.Zero | Exact.One).countTrailingOnes()); + Exact.Zero &= Mask; + Exact.One &= Mask; + Computed.Zero &= Mask; + Computed.One &= Mask; + EXPECT_TRUE(checkResult("mul", Exact, Computed, {Known1, Known2}, + /*CheckOptimality=*/true)); + } + }); + }); + } +} + } // end anonymous namespace