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

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 22 04:43:40 PDT 2024


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

>From 38cba53901c9792dc6e8219e7a876f1e001a145a Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Mon, 22 Apr 2024 11:27:05 +0100
Subject: [PATCH] [KnownBitsTest] Print name of function when exhaustive tests
 fail

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
---
 llvm/unittests/Support/KnownBitsTest.cpp | 106 +++++++++++++++--------
 1 file changed, 68 insertions(+), 38 deletions(-)

diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index 2fa650c2c3bf0e..b970137e63b715 100644
--- a/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/llvm/unittests/Support/KnownBitsTest.cpp
@@ -10,9 +10,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/KnownBits.h"
 #include "KnownBitsTest.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -25,7 +27,7 @@ using BinaryBitsFn =
 using BinaryIntFn =
     llvm::function_ref<std::optional<APInt>(const APInt &, const APInt &)>;
 
-static testing::AssertionResult checkResult(const KnownBits &Exact,
+static testing::AssertionResult checkResult(Twine Name, const KnownBits &Exact,
                                             const KnownBits &Computed,
                                             ArrayRef<KnownBits> Inputs,
                                             bool CheckOptimality) {
@@ -41,6 +43,7 @@ static testing::AssertionResult checkResult(const KnownBits &Exact,
   }
 
   testing::AssertionResult Result = testing::AssertionFailure();
+  Result << Name << ": ";
   Result << "Inputs = ";
   for (const KnownBits &Input : Inputs)
     Result << Input << ", ";
@@ -48,7 +51,8 @@ static testing::AssertionResult checkResult(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) {
@@ -65,12 +69,13 @@ static void testUnaryOpExhaustive(UnaryBitsFn BitsFn, UnaryIntFn IntFn,
       });
 
       EXPECT_TRUE(!Computed.hasConflict());
-      EXPECT_TRUE(checkResult(Exact, Computed, Known, CheckOptimality));
+      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}) {
@@ -91,8 +96,8 @@ static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn,
         });
 
         EXPECT_TRUE(!Computed.hasConflict());
-        EXPECT_TRUE(
-            checkResult(Exact, Computed, {Known1, Known2}, CheckOptimality));
+        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()) {
@@ -137,6 +142,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) {
@@ -186,23 +192,26 @@ static void TestAddSubExhaustive(bool IsAdd) {
 
       KnownBits KnownComputed = KnownBits::computeForAddSub(
           IsAdd, /*NSW=*/false, /*NUW=*/false, Known1, Known2);
-      EXPECT_TRUE(checkResult(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);
-      EXPECT_TRUE(checkResult(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);
-      EXPECT_TRUE(checkResult(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);
-      EXPECT_TRUE(checkResult(KnownNSWAndNUW, KnownNSWAndNUWComputed,
-                              {Known1, Known2}, /*CheckOptimality=*/true));
+      EXPECT_TRUE(checkResult(Name + " nsw nuw", KnownNSWAndNUW,
+                              KnownNSWAndNUWComputed, {Known1, Known2},
+                              /*CheckOptimality=*/true));
     });
   });
 }
@@ -267,27 +276,31 @@ TEST(KnownBitsTest, SignBitUnknown) {
 
 TEST(KnownBitsTest, BinaryExhaustive) {
   testBinaryOpExhaustive(
+      "and",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return Known1 & Known2;
       },
       [](const APInt &N1, const APInt &N2) { return N1 & N2; });
   testBinaryOpExhaustive(
+      "or",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return Known1 | Known2;
       },
       [](const APInt &N1, const APInt &N2) { return N1 | N2; });
   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("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);
       },
@@ -298,6 +311,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
+      "udiv exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::udiv(Known1, Known2, /*Exact*/ true);
       },
@@ -308,6 +322,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
+      "sdiv",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::sdiv(Known1, Known2);
       },
@@ -318,6 +333,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
+      "sdiv exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::sdiv(Known1, Known2, /*Exact*/ true);
       },
@@ -329,7 +345,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::urem,
+      "urem", KnownBits::urem,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         if (N2.isZero())
           return std::nullopt;
@@ -337,7 +353,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::srem,
+      "srem", KnownBits::srem,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         if (N2.isZero())
           return std::nullopt;
@@ -345,30 +361,31 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::sadd_sat,
+      "sadd_sat", KnownBits::sadd_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.sadd_sat(N2);
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::uadd_sat,
+      "uadd_sat", KnownBits::uadd_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.uadd_sat(N2);
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::ssub_sat,
+      "ssub_sat", KnownBits::ssub_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.ssub_sat(N2);
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::usub_sat,
+      "usub_sat", KnownBits::usub_sat,
       [](const APInt &N1, const APInt &N2) -> std::optional<APInt> {
         return N1.usub_sat(N2);
       },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
+      "shl",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2);
       },
@@ -379,6 +396,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "ushl_ov",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ true);
       },
@@ -391,6 +409,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "shl nsw",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ false, /* NSW */ true);
       },
@@ -403,6 +422,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "shl nuw",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::shl(Known1, Known2, /* NUW */ true, /* NSW */ true);
       },
@@ -417,6 +437,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
 
   testBinaryOpExhaustive(
+      "lshr",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::lshr(Known1, Known2);
       },
@@ -427,6 +448,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "lshr exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::lshr(Known1, Known2, /*ShAmtNonZero=*/false,
                                /*Exact=*/true);
@@ -440,6 +462,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "ashr",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::ashr(Known1, Known2);
       },
@@ -450,6 +473,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   testBinaryOpExhaustive(
+      "ashr exact",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::ashr(Known1, Known2, /*ShAmtNonZero=*/false,
                                /*Exact=*/true);
@@ -463,38 +487,44 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
   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(
-      KnownBits::mulhs,
+      "mulhs", KnownBits::mulhs,
       [](const APInt &N1, const APInt &N2) { return APIntOps::mulhs(N1, N2); },
       /*CheckOptimality=*/false);
   testBinaryOpExhaustive(
-      KnownBits::mulhu,
+      "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(); },
-                        [](const APInt &N) { return N.abs(); });
+  testUnaryOpExhaustive(
+      "abs", [](const KnownBits &Known) { return Known.abs(); },
+      [](const APInt &N) { return N.abs(); });
 
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.abs(true); },
-                        [](const APInt &N) -> std::optional<APInt> {
-                          if (N.isMinSignedValue())
-                            return std::nullopt;
-                          return N.abs();
-                        });
+  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(); },
-                        [](const APInt &N) { return N & -N; });
-  testUnaryOpExhaustive([](const KnownBits &Known) { return Known.blsmsk(); },
-                        [](const APInt &N) { return N ^ (N - 1); });
+  testUnaryOpExhaustive(
+      "blsi", [](const KnownBits &Known) { return Known.blsi(); },
+      [](const APInt &N) { return N & -N; });
+  testUnaryOpExhaustive(
+      "blsmsk", [](const KnownBits &Known) { return Known.blsmsk(); },
+      [](const APInt &N) { return N ^ (N - 1); });
 
   testUnaryOpExhaustive(
+      "mul self",
       [](const KnownBits &Known) {
         return KnownBits::mul(Known, Known, /*SelfMultiply*/ true);
       },



More information about the llvm-commits mailing list