aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/KnownBitsTest.cpp
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2024-02-28 21:59:38 -0600
committerNoah Goldstein <goldstein.w.n@gmail.com>2024-03-05 12:59:58 -0600
commit17162b61c2e6968482fab928f89bdca8b4ac06d9 (patch)
treeab4d537ec5aeeb763ee4448190c87212f7741994 /llvm/unittests/Support/KnownBitsTest.cpp
parent61c06775c96a93bf2b6ac0145b78b4ecb1a858b6 (diff)
downloadllvm-17162b61c2e6968482fab928f89bdca8b4ac06d9.zip
llvm-17162b61c2e6968482fab928f89bdca8b4ac06d9.tar.gz
llvm-17162b61c2e6968482fab928f89bdca8b4ac06d9.tar.bz2
[KnownBits] Make `nuw` and `nsw` support in `computeForAddSub` optimal
Just some improvements that should hopefully strengthen analysis. Closes #83580
Diffstat (limited to 'llvm/unittests/Support/KnownBitsTest.cpp')
-rw-r--r--llvm/unittests/Support/KnownBitsTest.cpp74
1 files changed, 62 insertions, 12 deletions
diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index d0ea1095..658f379 100644
--- a/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/llvm/unittests/Support/KnownBitsTest.cpp
@@ -169,41 +169,69 @@ static void TestAddSubExhaustive(bool IsAdd) {
unsigned Bits = 4;
ForeachKnownBits(Bits, [&](const KnownBits &Known1) {
ForeachKnownBits(Bits, [&](const KnownBits &Known2) {
- KnownBits Known(Bits), KnownNSW(Bits);
+ KnownBits Known(Bits), KnownNSW(Bits), KnownNUW(Bits),
+ KnownNSWAndNUW(Bits);
Known.Zero.setAllBits();
Known.One.setAllBits();
KnownNSW.Zero.setAllBits();
KnownNSW.One.setAllBits();
+ KnownNUW.Zero.setAllBits();
+ KnownNUW.One.setAllBits();
+ KnownNSWAndNUW.Zero.setAllBits();
+ KnownNSWAndNUW.One.setAllBits();
ForeachNumInKnownBits(Known1, [&](const APInt &N1) {
ForeachNumInKnownBits(Known2, [&](const APInt &N2) {
- bool Overflow;
+ bool SignedOverflow;
+ bool UnsignedOverflow;
APInt Res;
- if (IsAdd)
- Res = N1.sadd_ov(N2, Overflow);
- else
- Res = N1.ssub_ov(N2, Overflow);
+ if (IsAdd) {
+ Res = N1.uadd_ov(N2, UnsignedOverflow);
+ Res = N1.sadd_ov(N2, SignedOverflow);
+ } else {
+ Res = N1.usub_ov(N2, UnsignedOverflow);
+ Res = N1.ssub_ov(N2, SignedOverflow);
+ }
Known.One &= Res;
Known.Zero &= ~Res;
- if (!Overflow) {
+ if (!SignedOverflow) {
KnownNSW.One &= Res;
KnownNSW.Zero &= ~Res;
}
+
+ if (!UnsignedOverflow) {
+ KnownNUW.One &= Res;
+ KnownNUW.Zero &= ~Res;
+ }
+
+ if (!UnsignedOverflow && !SignedOverflow) {
+ KnownNSWAndNUW.One &= Res;
+ KnownNSWAndNUW.Zero &= ~Res;
+ }
});
});
KnownBits KnownComputed = KnownBits::computeForAddSub(
IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2);
- EXPECT_EQ(Known, KnownComputed);
+ EXPECT_TRUE(isOptimal(Known, KnownComputed, {Known1, Known2}));
- // The NSW calculation is not precise, only check that it's
- // conservatively correct.
KnownBits KnownNSWComputed = KnownBits::computeForAddSub(
IsAdd, /*NSW=*/true, /*NUW=*/false, Known1, Known2);
- EXPECT_TRUE(KnownNSWComputed.Zero.isSubsetOf(KnownNSW.Zero));
- EXPECT_TRUE(KnownNSWComputed.One.isSubsetOf(KnownNSW.One));
+ if (!KnownNSW.hasConflict())
+ EXPECT_TRUE(isOptimal(KnownNSW, KnownNSWComputed, {Known1, Known2}));
+
+ KnownBits KnownNUWComputed = KnownBits::computeForAddSub(
+ IsAdd, /*NSW=*/false, /*NUW=*/true, Known1, Known2);
+ if (!KnownNUW.hasConflict())
+ EXPECT_TRUE(isOptimal(KnownNUW, KnownNUWComputed, {Known1, Known2}));
+
+ KnownBits KnownNSWAndNUWComputed = KnownBits::computeForAddSub(
+ IsAdd, /*NSW=*/true, /*NUW=*/true, Known1, Known2);
+ if (!KnownNSWAndNUW.hasConflict())
+ EXPECT_TRUE(isOptimal(KnownNSWAndNUW, KnownNSWAndNUWComputed,
+ {Known1, Known2}));
});
});
}
@@ -244,6 +272,28 @@ TEST(KnownBitsTest, SubBorrowExhaustive) {
});
}
+TEST(KnownBitsTest, SignBitUnknown) {
+ KnownBits Known(2);
+ EXPECT_TRUE(Known.isSignUnknown());
+ Known.Zero.setBit(0);
+ EXPECT_TRUE(Known.isSignUnknown());
+ Known.Zero.setBit(1);
+ EXPECT_FALSE(Known.isSignUnknown());
+ Known.Zero.clearBit(0);
+ EXPECT_FALSE(Known.isSignUnknown());
+ Known.Zero.clearBit(1);
+ EXPECT_TRUE(Known.isSignUnknown());
+
+ Known.One.setBit(0);
+ EXPECT_TRUE(Known.isSignUnknown());
+ Known.One.setBit(1);
+ EXPECT_FALSE(Known.isSignUnknown());
+ Known.One.clearBit(0);
+ EXPECT_FALSE(Known.isSignUnknown());
+ Known.One.clearBit(1);
+ EXPECT_TRUE(Known.isSignUnknown());
+}
+
TEST(KnownBitsTest, AbsDiffSpecialCase) {
// There are 2 implementation of absdiff - both are currently needed to cover
// extra cases.