[llvm] [KnownBits] Make nuw and nsw support in computeForAddSub optimal (PR #83382)
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 29 03:34:12 PST 2024
================
@@ -166,44 +166,82 @@ TEST(KnownBitsTest, AddCarryExhaustive) {
}
static void TestAddSubExhaustive(bool IsAdd) {
- unsigned Bits = 4;
+ unsigned Bits = 6;
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, Known1, Known2);
- EXPECT_EQ(Known, KnownComputed);
+ KnownBits KnownComputed = KnownBits::computeForAddSub(
+ IsAdd, /*NSW*/ false, /*NUW*/ false, Known1, Known2);
+ EXPECT_TRUE(isOptimal(Known, KnownComputed, {Known1, Known2}));
+ EXPECT_TRUE(isCorrect(Known, KnownComputed, {Known1, Known2}));
- // The NSW calculation is not precise, only check that it's
- // conservatively correct.
KnownBits KnownNSWComputed = KnownBits::computeForAddSub(
- IsAdd, /*NSW*/true, Known1, Known2);
- EXPECT_TRUE(KnownNSWComputed.Zero.isSubsetOf(KnownNSW.Zero));
- EXPECT_TRUE(KnownNSWComputed.One.isSubsetOf(KnownNSW.One));
+ IsAdd, /*NSW*/ true, /*NUW*/ false, Known1, Known2);
+ if (!KnownNSW.hasConflict()) {
+ EXPECT_TRUE(isOptimal(KnownNSW, KnownNSWComputed, {Known1, Known2}));
+ }
+ EXPECT_TRUE(isCorrect(KnownNSW, KnownNSWComputed, {Known1, Known2}));
----------------
jayfoad wrote:
Just remove this. It's not testing anything useful. The only way `Known` can have a conflict is if every possible input value causes overflow, in which Known.One and Known.Zero will both be all-ones, so isCorrect is trivially true.
https://github.com/llvm/llvm-project/pull/83382
More information about the llvm-commits
mailing list