[llvm] 3117794 - [NFCI][IR] ConstantRangeTest: refactor operation range gatherers

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 14:37:12 PDT 2020


Author: Roman Lebedev
Date: 2020-09-25T00:36:41+03:00
New Revision: 31177949cb1d88d7dd32078d09a265b828d40826

URL: https://github.com/llvm/llvm-project/commit/31177949cb1d88d7dd32078d09a265b828d40826
DIFF: https://github.com/llvm/llvm-project/commit/31177949cb1d88d7dd32078d09a265b828d40826.diff

LOG: [NFCI][IR] ConstantRangeTest: refactor operation range gatherers

We do the same dance to acquire the "exact" range of an op via
an exhaustive approach in many places.
Let's not invent the wheel each time.

Added: 
    

Modified: 
    llvm/unittests/IR/ConstantRangeTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 19474eea0167..5e8a98e61f85 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -59,107 +59,130 @@ static void ForeachNumInConstantRange(const ConstantRange &CR, Fn TestFn) {
   }
 }
 
-template<typename Fn1, typename Fn2>
-static void TestUnsignedUnaryOpExhaustive(
-    Fn1 RangeFn, Fn2 IntFn, bool SkipSignedIntMin = false) {
+struct OpRangeGathererBase {
+  void account(const APInt &N);
+  ConstantRange getRange();
+};
+
+struct UnsignedOpRangeGatherer : public OpRangeGathererBase {
+  APInt Min;
+  APInt Max;
+
+  UnsignedOpRangeGatherer(unsigned Bits)
+      : Min(APInt::getMaxValue(Bits)), Max(APInt::getMinValue(Bits)) {}
+
+  void account(const APInt &N) {
+    if (N.ult(Min))
+      Min = N;
+    if (N.ugt(Max))
+      Max = N;
+  }
+
+  ConstantRange getRange() {
+    if (Min.ugt(Max))
+      return ConstantRange::getEmpty(Min.getBitWidth());
+    return ConstantRange::getNonEmpty(Min, Max + 1);
+  }
+};
+
+struct SignedOpRangeGatherer : public OpRangeGathererBase {
+  APInt Min;
+  APInt Max;
+
+  SignedOpRangeGatherer(unsigned Bits)
+      : Min(APInt::getSignedMaxValue(Bits)),
+        Max(APInt::getSignedMinValue(Bits)) {}
+
+  void account(const APInt &N) {
+    if (N.slt(Min))
+      Min = N;
+    if (N.sgt(Max))
+      Max = N;
+  }
+
+  ConstantRange getRange() {
+    if (Min.sgt(Max))
+      return ConstantRange::getEmpty(Min.getBitWidth());
+    return ConstantRange::getNonEmpty(Min, Max + 1);
+  }
+};
+
+template <typename Fn1, typename Fn2>
+static void TestUnsignedUnaryOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
+                                          bool SkipSignedIntMin = false) {
   unsigned Bits = 4;
   EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) {
-    APInt Min = APInt::getMaxValue(Bits);
-    APInt Max = APInt::getMinValue(Bits);
+    UnsignedOpRangeGatherer R(CR.getBitWidth());
     ForeachNumInConstantRange(CR, [&](const APInt &N) {
       if (SkipSignedIntMin && N.isMinSignedValue())
         return;
-
-      APInt AbsN = IntFn(N);
-      if (AbsN.ult(Min))
-        Min = AbsN;
-      if (AbsN.ugt(Max))
-        Max = AbsN;
+      R.account(IntFn(N));
     });
 
-    ConstantRange ResultCR = RangeFn(CR);
-    if (Min.ugt(Max)) {
-      EXPECT_TRUE(ResultCR.isEmptySet());
-      return;
-    }
+    ConstantRange ExactCR = R.getRange();
+    ConstantRange ActualCR = RangeFn(CR);
 
-    ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
-    EXPECT_EQ(Exact, ResultCR);
+    EXPECT_EQ(ExactCR, ActualCR);
   });
 }
 
-template<typename Fn1, typename Fn2>
-static void TestUnsignedBinOpExhaustive(
-    Fn1 RangeFn, Fn2 IntFn,
-    bool SkipZeroRHS = false, bool CorrectnessOnly = false) {
+template <typename Fn1, typename Fn2>
+static void TestUnsignedBinOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
+                                        bool SkipZeroRHS = false,
+                                        bool CorrectnessOnly = false) {
   unsigned Bits = 4;
-  EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
-                                       const ConstantRange &CR2) {
-    APInt Min = APInt::getMaxValue(Bits);
-    APInt Max = APInt::getMinValue(Bits);
-    ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
-      ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
-        if (SkipZeroRHS && N2 == 0)
-          return;
+  EnumerateTwoConstantRanges(
+      Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+        UnsignedOpRangeGatherer R(CR1.getBitWidth());
+        ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
+          ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
+            if (SkipZeroRHS && N2 == 0)
+              return;
+            R.account(IntFn(N1, N2));
+          });
+        });
 
-        APInt N = IntFn(N1, N2);
-        if (N.ult(Min))
-          Min = N;
-        if (N.ugt(Max))
-          Max = N;
-      });
-    });
+        ConstantRange CR = RangeFn(CR1, CR2);
 
-    ConstantRange CR = RangeFn(CR1, CR2);
-    if (Min.ugt(Max)) {
-      EXPECT_TRUE(CR.isEmptySet());
-      return;
-    }
+        ConstantRange Exact = R.getRange();
 
-    ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
-    if (CorrectnessOnly) {
-      EXPECT_TRUE(CR.contains(Exact));
-    } else {
-      EXPECT_EQ(Exact, CR);
-    }
-  });
+        if (!CorrectnessOnly) {
+          EXPECT_EQ(Exact, CR);
+          return;
+        }
+
+        EXPECT_TRUE(CR.contains(Exact));
+        if (Exact.isEmptySet())
+          EXPECT_TRUE(CR.isEmptySet());
+      });
 }
 
-template<typename Fn1, typename Fn2>
-static void TestSignedBinOpExhaustive(
-    Fn1 RangeFn, Fn2 IntFn,
-    bool SkipZeroRHS = false, bool CorrectnessOnly = false) {
+template <typename Fn1, typename Fn2>
+static void TestSignedBinOpExhaustive(Fn1 RangeFn, Fn2 IntFn,
+                                      bool SkipZeroRHS = false,
+                                      bool CorrectnessOnly = false) {
   unsigned Bits = 4;
-  EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
-                                       const ConstantRange &CR2) {
-    APInt Min = APInt::getSignedMaxValue(Bits);
-    APInt Max = APInt::getSignedMinValue(Bits);
-    ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
-      ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
-        if (SkipZeroRHS && N2 == 0)
-          return;
+  EnumerateTwoConstantRanges(
+      Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+        SignedOpRangeGatherer R(CR1.getBitWidth());
+        ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
+          ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
+            if (SkipZeroRHS && N2 == 0)
+              return;
 
-        APInt N = IntFn(N1, N2);
-        if (N.slt(Min))
-          Min = N;
-        if (N.sgt(Max))
-          Max = N;
-      });
-    });
+            R.account(IntFn(N1, N2));
+          });
+        });
 
-    ConstantRange CR = RangeFn(CR1, CR2);
-    if (Min.sgt(Max)) {
-      EXPECT_TRUE(CR.isEmptySet());
-      return;
-    }
+        ConstantRange CR = RangeFn(CR1, CR2);
 
-    ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
-    if (CorrectnessOnly) {
-      EXPECT_TRUE(CR.contains(Exact));
-    } else {
-      EXPECT_EQ(Exact, CR);
-    }
-  });
+        ConstantRange Exact = R.getRange();
+        if (CorrectnessOnly) {
+          EXPECT_TRUE(CR.contains(Exact));
+        } else {
+          EXPECT_EQ(Exact, CR);
+        }
+      });
 }
 
 ConstantRange ConstantRangeTest::Full(16, true);
@@ -731,8 +754,7 @@ static void TestAddWithNoSignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
   EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
                                        const ConstantRange &CR2) {
     ConstantRange CR = RangeFn(CR1, CR2);
-    APInt Min = APInt::getSignedMaxValue(Bits);
-    APInt Max = APInt::getSignedMinValue(Bits);
+    SignedOpRangeGatherer R(CR.getBitWidth());
     bool AllOverflow = true;
     ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
       ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -740,10 +762,7 @@ static void TestAddWithNoSignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
         APInt N = IntFn(IsOverflow, N1, N2);
         if (!IsOverflow) {
           AllOverflow = false;
-          if (N.slt(Min))
-            Min = N;
-          if (N.sgt(Max))
-            Max = N;
+          R.account(N);
           EXPECT_TRUE(CR.contains(N));
         }
       });
@@ -751,15 +770,11 @@ static void TestAddWithNoSignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
 
     EXPECT_EQ(CR.isEmptySet(), AllOverflow);
 
-    if (!CR1.isSignWrappedSet() && !CR2.isSignWrappedSet()) {
-      if (Min.sgt(Max)) {
-        EXPECT_TRUE(CR.isEmptySet());
-        return;
-      }
+    if (CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
+      return;
 
-      ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
-      EXPECT_EQ(Exact, CR);
-    }
+    ConstantRange Exact = R.getRange();
+    EXPECT_EQ(Exact, CR);
   });
 }
 
@@ -769,8 +784,7 @@ static void TestAddWithNoUnsignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
   EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
                                        const ConstantRange &CR2) {
     ConstantRange CR = RangeFn(CR1, CR2);
-    APInt Min = APInt::getMaxValue(Bits);
-    APInt Max = APInt::getMinValue(Bits);
+    UnsignedOpRangeGatherer R(CR.getBitWidth());
     bool AllOverflow = true;
     ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
       ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -778,10 +792,7 @@ static void TestAddWithNoUnsignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
         APInt N = IntFn(IsOverflow, N1, N2);
         if (!IsOverflow) {
           AllOverflow = false;
-          if (N.ult(Min))
-            Min = N;
-          if (N.ugt(Max))
-            Max = N;
+          R.account(N);
           EXPECT_TRUE(CR.contains(N));
         }
       });
@@ -789,15 +800,11 @@ static void TestAddWithNoUnsignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
 
     EXPECT_EQ(CR.isEmptySet(), AllOverflow);
 
-    if (!CR1.isWrappedSet() && !CR2.isWrappedSet()) {
-      if (Min.ugt(Max)) {
-        EXPECT_TRUE(CR.isEmptySet());
-        return;
-      }
+    if (CR1.isWrappedSet() || CR2.isWrappedSet())
+      return;
 
-      ConstantRange Exact = ConstantRange::getNonEmpty(Min, Max + 1);
-      EXPECT_EQ(Exact, CR);
-    }
+    ConstantRange Exact = R.getRange();
+    EXPECT_EQ(Exact, CR);
   });
 }
 
@@ -809,10 +816,8 @@ static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
   EnumerateTwoConstantRanges(
       Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
         ConstantRange CR = RangeFn(CR1, CR2);
-        APInt UMin = APInt::getMaxValue(Bits);
-        APInt UMax = APInt::getMinValue(Bits);
-        APInt SMin = APInt::getSignedMaxValue(Bits);
-        APInt SMax = APInt::getSignedMinValue(Bits);
+        UnsignedOpRangeGatherer UR(CR.getBitWidth());
+        SignedOpRangeGatherer SR(CR.getBitWidth());
         bool AllOverflow = true;
         ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
           ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
@@ -821,14 +826,8 @@ static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
             (void) IntFnUnsigned(IsOverflow, N1, N2);
             if (!IsSignedOverflow && !IsOverflow) {
               AllOverflow = false;
-              if (N.slt(SMin))
-                SMin = N;
-              if (N.sgt(SMax))
-                SMax = N;
-              if (N.ult(UMin))
-                UMin = N;
-              if (N.ugt(UMax))
-                UMax = N;
+              UR.account(N);
+              SR.account(N);
               EXPECT_TRUE(CR.contains(N));
             }
           });
@@ -836,18 +835,20 @@ static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
 
         EXPECT_EQ(CR.isEmptySet(), AllOverflow);
 
-        if (!CR1.isWrappedSet() && !CR2.isWrappedSet() &&
-            !CR1.isSignWrappedSet() && !CR2.isSignWrappedSet()) {
-          if (UMin.ugt(UMax) || SMin.sgt(SMax)) {
-            EXPECT_TRUE(CR.isEmptySet());
-            return;
-          }
+        if (CR1.isWrappedSet() || CR2.isWrappedSet() ||
+            CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
+          return;
 
-          ConstantRange Exact =
-              ConstantRange::getNonEmpty(SMin, SMax + 1)
-                  .intersectWith(ConstantRange::getNonEmpty(UMin, UMax + 1));
-          EXPECT_EQ(Exact, CR);
+        ConstantRange ExactUnsignedCR = UR.getRange();
+        ConstantRange ExactSignedCR = SR.getRange();
+
+        if (ExactUnsignedCR.isEmptySet() || ExactSignedCR.isEmptySet()) {
+          EXPECT_TRUE(CR.isEmptySet());
+          return;
         }
+
+        ConstantRange Exact = ExactSignedCR.intersectWith(ExactUnsignedCR);
+        EXPECT_EQ(Exact, CR);
       });
 }
 
@@ -2229,23 +2230,19 @@ TEST_F(ConstantRangeTest, FromKnownBitsExhaustive) {
       if (Known.hasConflict() || Known.isUnknown())
         continue;
 
-      APInt MinUnsigned = APInt::getMaxValue(Bits);
-      APInt MaxUnsigned = APInt::getMinValue(Bits);
-      APInt MinSigned = APInt::getSignedMaxValue(Bits);
-      APInt MaxSigned = APInt::getSignedMinValue(Bits);
+      UnsignedOpRangeGatherer UR(Bits);
+      SignedOpRangeGatherer SR(Bits);
       for (unsigned N = 0; N < Max; ++N) {
         APInt Num(Bits, N);
         if ((Num & Known.Zero) != 0 || (~Num & Known.One) != 0)
           continue;
 
-        if (Num.ult(MinUnsigned)) MinUnsigned = Num;
-        if (Num.ugt(MaxUnsigned)) MaxUnsigned = Num;
-        if (Num.slt(MinSigned)) MinSigned = Num;
-        if (Num.sgt(MaxSigned)) MaxSigned = Num;
+        UR.account(Num);
+        SR.account(Num);
       }
 
-      ConstantRange UnsignedCR(MinUnsigned, MaxUnsigned + 1);
-      ConstantRange SignedCR(MinSigned, MaxSigned + 1);
+      ConstantRange UnsignedCR = UR.getRange();
+      ConstantRange SignedCR = SR.getRange();
       EXPECT_EQ(UnsignedCR, ConstantRange::fromKnownBits(Known, false));
       EXPECT_EQ(SignedCR, ConstantRange::fromKnownBits(Known, true));
     }


        


More information about the llvm-commits mailing list