[llvm] [KnownBitsTest] Print name of function when exhaustive tests fail (PR #89588)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 22 03:31:33 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Jay Foad (jayfoad)

<details>
<summary>Changes</summary>

When exhaustive unary/binary tests fail, print the name of the function
being tested as well as the values of the inputs and outputs.

Example of a simulated failure in testing "udiv exact":

    unittests/Support/KnownBitsTest.cpp:99: Failure
    Value of: checkResult(Name, Exact, Computed, {Known1, Known2}, CheckOptimality)
      Actual: false (udiv exact: Inputs = ???1, ????, Computed = ???1, Exact = 0???)
    Expected: true


---
Full diff: https://github.com/llvm/llvm-project/pull/89588.diff


1 Files Affected:

- (modified) llvm/unittests/Support/KnownBitsTest.cpp (+67-77) 


``````````diff
diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index feb0231300f1fd..8946444c222dc1 100644
--- a/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/llvm/unittests/Support/KnownBitsTest.cpp
@@ -11,6 +11,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/KnownBits.h"
 #include "KnownBitsTest.h"
 #include "gtest/gtest.h"
@@ -25,28 +27,24 @@ using BinaryBitsFn =
 using BinaryIntFn =
     llvm::function_ref<std::optional<APInt>(const APInt &, const APInt &)>;
 
-static testing::AssertionResult isCorrect(const KnownBits &Exact,
-                                          const KnownBits &Computed,
-                                          ArrayRef<KnownBits> Inputs) {
-  if (Computed.Zero.isSubsetOf(Exact.Zero) &&
-      Computed.One.isSubsetOf(Exact.One))
-    return testing::AssertionSuccess();
-
-  testing::AssertionResult Result = testing::AssertionFailure();
-  Result << "Inputs = ";
-  for (const KnownBits &Input : Inputs)
-    Result << Input << ", ";
-  Result << "Computed = " << Computed << ", Exact = " << Exact;
-  return Result;
-}
-
-static testing::AssertionResult isOptimal(const KnownBits &Exact,
-                                          const KnownBits &Computed,
-                                          ArrayRef<KnownBits> Inputs) {
-  if (Computed == Exact)
-    return testing::AssertionSuccess();
+static testing::AssertionResult checkResult(Twine Name,
+                                            const KnownBits &Exact,
+                                            const KnownBits &Computed,
+                                            ArrayRef<KnownBits> Inputs,
+                                            bool CheckOptimality) {
+  if (CheckOptimality) {
+    // We generally don't want to return conflicting known bits, even if it is
+    // legal for always poison results.
+    if (Exact.hasConflict() || Computed == Exact)
+      return testing::AssertionSuccess();
+  } else {
+    if (Computed.Zero.isSubsetOf(Exact.Zero) &&
+        Computed.One.isSubsetOf(Exact.One))
+      return testing::AssertionSuccess();
+  }
 
   testing::AssertionResult Result = testing::AssertionFailure();
+  Result << Name << ": ";
   Result << "Inputs = ";
   for (const KnownBits &Input : Inputs)
     Result << Input << ", ";
@@ -54,7 +52,7 @@ static testing::AssertionResult isOptimal(const KnownBits &Exact,
   return Result;
 }
 
-static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn,
+static void testUnaryOpExhaustive(StringRef Name, UnaryBitsFn BitsFn, UnaryIntFn IntFn,
                                   bool CheckOptimality = true) {
   for (unsigned Bits : {1, 4}) {
     ForeachKnownBits(Bits, [&](const KnownBits &Known) {
@@ -71,17 +69,12 @@ static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn,
       });
 
       EXPECT_TRUE(!Computed.hasConflict());
-      EXPECT_TRUE(isCorrect(Exact, Computed, Known));
-      // We generally don't want to return conflicting known bits, even if it is
-      // legal for always poison results.
-      if (CheckOptimality && !Exact.hasConflict()) {
-        EXPECT_TRUE(isOptimal(Exact, Computed, Known));
-      }
+      EXPECT_TRUE(checkResult(Name, Exact, Computed, Known, CheckOptimality));
     });
   }
 }
 
-static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn,
+static void testBinaryOpExhaustive(StringRef Name, BinaryBitsFn BitsFn, BinaryIntFn IntFn,
                                    bool CheckOptimality = true,
                                    bool RefinePoisonToZero = false) {
   for (unsigned Bits : {1, 4}) {
@@ -102,12 +95,8 @@ static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn,
         });
 
         EXPECT_TRUE(!Computed.hasConflict());
-        EXPECT_TRUE(isCorrect(Exact, Computed, {Known1, Known2}));
-        // We generally don't want to return conflicting known bits, even if it
-        // is legal for always poison results.
-        if (CheckOptimality && !Exact.hasConflict()) {
-          EXPECT_TRUE(isOptimal(Exact, Computed, {Known1, Known2}));
-        }
+        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()) {
@@ -152,6 +141,7 @@ TEST(KnownBitsTest, AddCarryExhaustive) {
 }
 
 static void TestAddSubExhaustive(bool IsAdd) {
+  Twine Name = IsAdd ? "add" : "sub";
   unsigned Bits = 4;
   ForeachKnownBits(Bits, [&](const KnownBits &Known1) {
     ForeachKnownBits(Bits, [&](const KnownBits &Known2) {
@@ -201,23 +191,23 @@ static void TestAddSubExhaustive(bool IsAdd) {
 
       KnownBits KnownComputed = KnownBits::computeForAddSub(
           IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2);
-      EXPECT_TRUE(isOptimal(Known, KnownComputed, {Known1, Known2}));
+      EXPECT_TRUE(checkResult(Name, Known, KnownComputed, {Known1, Known2},
+                              /*CheckOptimality=*/true));
 
       KnownBits KnownNSWComputed = KnownBits::computeForAddSub(
           IsAdd, /*NSW=*/true, /*NUW=*/false, Known1, Known2);
-      if (!KnownNSW.hasConflict())
-        EXPECT_TRUE(isOptimal(KnownNSW, KnownNSWComputed, {Known1, Known2}));
+      EXPECT_TRUE(checkResult(Name + " nsw", KnownNSW, KnownNSWComputed, {Known1, Known2},
+                              /*CheckOptimality=*/true));
 
       KnownBits KnownNUWComputed = KnownBits::computeForAddSub(
           IsAdd, /*NSW=*/false, /*NUW=*/true, Known1, Known2);
-      if (!KnownNUW.hasConflict())
-        EXPECT_TRUE(isOptimal(KnownNUW, KnownNUWComputed, {Known1, Known2}));
+      EXPECT_TRUE(checkResult(Name + " nuw", KnownNUW, KnownNUWComputed, {Known1, Known2},
+                              /*CheckOptimality=*/true));
 
       KnownBits KnownNSWAndNUWComputed = KnownBits::computeForAddSub(
           IsAdd, /*NSW=*/true, /*NUW=*/true, Known1, Known2);
-      if (!KnownNSWAndNUW.hasConflict())
-        EXPECT_TRUE(isOptimal(KnownNSWAndNUW, KnownNSWAndNUWComputed,
-                              {Known1, Known2}));
+      EXPECT_TRUE(checkResult(Name + " nsw nuw", KnownNSWAndNUW, KnownNSWAndNUWComputed,
+                              {Known1, Known2}, /*CheckOptimality=*/true));
     });
   });
 }
@@ -281,28 +271,28 @@ TEST(KnownBitsTest, SignBitUnknown) {
 }
 
 TEST(KnownBitsTest, BinaryExhaustive) {
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("and",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return Known1 & Known2;
       },
       [](const APInt &N1, const APInt &N2) { return N1 & N2; });
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("or",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return Known1 | Known2;
       },
       [](const APInt &N1, const APInt &N2) { return N1 | N2; });
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("xor",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return Known1 ^ Known2;
       },
       [](const APInt &N1, const APInt &N2) { return N1 ^ N2; });
-  testBinaryOpExhaustive(KnownBits::umax, APIntOps::umax);
-  testBinaryOpExhaustive(KnownBits::umin, APIntOps::umin);
-  testBinaryOpExhaustive(KnownBits::smax, APIntOps::smax);
-  testBinaryOpExhaustive(KnownBits::smin, APIntOps::smin);
-  testBinaryOpExhaustive(KnownBits::abdu, APIntOps::abdu);
-  testBinaryOpExhaustive(KnownBits::abds, APIntOps::abds);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("umax", KnownBits::umax, APIntOps::umax);
+  testBinaryOpExhaustive("umin", KnownBits::umin, APIntOps::umin);
+  testBinaryOpExhaustive("smax", KnownBits::smax, APIntOps::smax);
+  testBinaryOpExhaustive("smin", KnownBits::smin, APIntOps::smin);
+  testBinaryOpExhaustive("abdu", KnownBits::abdu, APIntOps::abdu);
+  testBinaryOpExhaustive("abds", KnownBits::abds, APIntOps::abds);
+  testBinaryOpExhaustive("udiv",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::udiv(Known1, Known2);
       },
@@ -312,7 +302,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.udiv(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("udiv exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::udiv(Known1, Known2, /*Exact*/ true);
       },
@@ -322,7 +312,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.udiv(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("sdiv",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::sdiv(Known1, Known2);
       },
@@ -332,7 +322,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.sdiv(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("sdiv exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::sdiv(Known1, Known2, /*Exact*/ true);
       },
@@ -343,7 +333,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.sdiv(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("urem",
       KnownBits::urem,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         if (N2.isZero())
@@ -351,7 +341,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.urem(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("srem",
       KnownBits::srem,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         if (N2.isZero())
@@ -359,31 +349,31 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.srem(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("sadd_sat",
       KnownBits::sadd_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.sadd_sat(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("uadd_sat",
       KnownBits::uadd_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.uadd_sat(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("ssub_sat",
       KnownBits::ssub_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.ssub_sat(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("usub_sat",
       KnownBits::usub_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.usub_sat(N2);
       },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("shl",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2);
       },
@@ -393,7 +383,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.shl(N2);
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("ushl_ov",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ true);
       },
@@ -405,7 +395,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return Res;
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("shl nsw",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ false, /* NSW */ true);
       },
@@ -417,7 +407,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return Res;
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("shl nuw",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ true, /* NSW */ true);
       },
@@ -431,7 +421,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
 
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("lshr",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::lshr(Known1, Known2);
       },
@@ -441,7 +431,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.lshr(N2);
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("lshr exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::lshr(Known1, Known2, /*ShAmtNonZero=*/false,
                                /*Exact=*/true);
@@ -454,7 +444,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.lshr(N2);
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("ashr",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::ashr(Known1, Known2);
       },
@@ -464,7 +454,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.ashr(N2);
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("ashr exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::ashr(Known1, Known2, /*ShAmtNonZero=*/false,
                                /*Exact=*/true);
@@ -477,39 +467,39 @@ TEST(KnownBitsTest, BinaryExhaustive) {
         return N1.ashr(N2);
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("mul",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::mul(Known1, Known2);
       },
       [](const APInt &N1, const APInt &N2) { return N1 * N2; },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("mulhs",
       KnownBits::mulhs,
       [](const APInt &N1, const APInt &N2) { return APIntOps::mulhs(N1, N2); },
       /*CheckOptimality=*/false);
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("mulhu",
       KnownBits::mulhu,
       [](const APInt &N1, const APInt &N2) { return APIntOps::mulhu(N1, N2); },
       /*CheckOptimality=*/false);
 }
 
 TEST(KnownBitsTest, UnaryExhaustive) {
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.abs(); },
+  testUnaryOpExhaustive("abs", [](const KnownBits &Known) { return Known.abs(); },
                         [](const APInt &N) { return N.abs(); });
 
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.abs(true); },
+  testUnaryOpExhaustive("abs(true)", [](const KnownBits &Known) { return Known.abs(true); },
                         [](const APInt &N) -> std::optional<APInt> {
                           if (N.isMinSignedValue())
                             return std::nullopt;
                           return N.abs();
                         });
 
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.blsi(); },
+  testUnaryOpExhaustive("blsi", [](const KnownBits &Known) { return Known.blsi(); },
                         [](const APInt &N) { return N & -N; });
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.blsmsk(); },
+  testUnaryOpExhaustive("blsmsk", [](const KnownBits &Known) { return Known.blsmsk(); },
                         [](const APInt &N) { return N ^ (N - 1); });
 
-  testUnaryOpExhaustive(
+  testUnaryOpExhaustive("mul self",
       [](const KnownBits &Known) {
         return KnownBits::mul(Known, Known, /*SelfMultiply*/ true);
       },

``````````

</details>


https://github.com/llvm/llvm-project/pull/89588


More information about the llvm-commits mailing list