[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 03:31:03 PDT 2024


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

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


>From f07ee1947454ac60169659a31b80a16f95da17ce Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Mon, 22 Apr 2024 11:00:56 +0100
Subject: [PATCH 1/2] [KnownBitsTest] Common up isCorrect and isOptimal. NFC.

This de-duplicates the code that prints useful information when a test
fails.
---
 llvm/unittests/Support/KnownBitsTest.cpp | 65 +++++++++---------------
 1 file changed, 25 insertions(+), 40 deletions(-)

diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index feb0231300f1fd..2fa650c2c3bf0e 100644
--- a/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/llvm/unittests/Support/KnownBitsTest.cpp
@@ -25,26 +25,20 @@ 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(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 << "Inputs = ";
@@ -71,12 +65,7 @@ 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(Exact, Computed, Known, CheckOptimality));
     });
   }
 }
@@ -102,12 +91,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(Exact, Computed, {Known1, Known2}, CheckOptimality));
         // In some cases we choose to return zero if the result is always
         // poison.
         if (RefinePoisonToZero && Exact.hasConflict()) {
@@ -201,23 +186,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(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(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(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(KnownNSWAndNUW, KnownNSWAndNUWComputed,
+                              {Known1, Known2}, /*CheckOptimality=*/true));
     });
   });
 }

>From 5b936af2ee94a8e76b0cae0a72d990e5b49bba00 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 2/2] [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 | 93 +++++++++++++-----------
 1 file changed, 49 insertions(+), 44 deletions(-)

diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index 2fa650c2c3bf0e..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,7 +27,8 @@ 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 +44,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 +52,7 @@ 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,12 @@ 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}) {
@@ -92,7 +96,7 @@ static void testBinaryOpExhaustive(BinaryBitsFn BitsFn, BinaryIntFn IntFn,
 
         EXPECT_TRUE(!Computed.hasConflict());
         EXPECT_TRUE(
-            checkResult(Exact, Computed, {Known1, Known2}, CheckOptimality));
+            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 +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) {
@@ -186,22 +191,22 @@ 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,
+      EXPECT_TRUE(checkResult(Name + " nsw nuw", KnownNSWAndNUW, KnownNSWAndNUWComputed,
                               {Known1, Known2}, /*CheckOptimality=*/true));
     });
   });
@@ -266,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);
       },
@@ -297,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);
       },
@@ -307,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);
       },
@@ -317,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);
       },
@@ -328,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())
@@ -336,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())
@@ -344,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);
       },
@@ -378,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);
       },
@@ -390,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);
       },
@@ -402,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);
       },
@@ -416,7 +421,7 @@ TEST(KnownBitsTest, BinaryExhaustive) {
       },
       /*CheckOptimality=*/true, /* RefinePoisonToZero */ true);
 
-  testBinaryOpExhaustive(
+  testBinaryOpExhaustive("lshr",
       [](const KnownBits &Known1, const KnownBits &Known2) {
         return KnownBits::lshr(Known1, Known2);
       },
@@ -426,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);
@@ -439,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);
       },
@@ -449,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);
@@ -462,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);
       },



More information about the llvm-commits mailing list