-
Notifications
You must be signed in to change notification settings - Fork 10.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[KnownBitsTest] Print name of function when exhaustive tests fail #89588
Conversation
Please only review the top commit. |
@llvm/pr-subscribers-llvm-support Author: Jay Foad (jayfoad) ChangesWhen exhaustive unary/binary tests fail, print the name of the function Example of a simulated failure in testing "udiv exact":
Full diff: https://github.com/llvm/llvm-project/pull/89588.diff 1 Files Affected:
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);
},
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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
5b936af
to
38cba53
Compare
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":