[llvm] 7cf567d - [ConstantRange] Calculate precise range for multiply by -1

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 23 03:17:55 PDT 2023


Author: Nikita Popov
Date: 2023-06-23T12:17:48+02:00
New Revision: 7cf567d46121f4aa8f659554b5e8584cd0fac056

URL: https://github.com/llvm/llvm-project/commit/7cf567d46121f4aa8f659554b5e8584cd0fac056
DIFF: https://github.com/llvm/llvm-project/commit/7cf567d46121f4aa8f659554b5e8584cd0fac056.diff

LOG: [ConstantRange] Calculate precise range for multiply by -1

These are pretty common in SCEV, so make sure we get a precise
result by mapping to the sub() operation.

Added: 
    

Modified: 
    llvm/lib/IR/ConstantRange.cpp
    llvm/unittests/IR/ConstantRangeTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 74cc09705f883..e9344a8815c08 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -1095,6 +1095,20 @@ ConstantRange::multiply(const ConstantRange &Other) const {
   if (isEmptySet() || Other.isEmptySet())
     return getEmpty();
 
+  if (const APInt *C = getSingleElement()) {
+    if (C->isOne())
+      return Other;
+    if (C->isAllOnes())
+      return ConstantRange(APInt::getZero(getBitWidth())).sub(Other);
+  }
+
+  if (const APInt *C = Other.getSingleElement()) {
+    if (C->isOne())
+      return *this;
+    if (C->isAllOnes())
+      return ConstantRange(APInt::getZero(getBitWidth())).sub(*this);
+  }
+
   // Multiplication is signedness-independent. However 
diff erent ranges can be
   // obtained depending on how the input ranges are treated. These 
diff erent
   // ranges are all conservatively correct, but one might be better than the

diff  --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index f4052838c434c..38d1119e7f85b 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -997,6 +997,26 @@ TEST_F(ConstantRangeTest, Multiply) {
   EXPECT_EQ(ConstantRange(APInt(8, -2)).multiply(
               ConstantRange(APInt(8, 0), APInt(8, 2))),
             ConstantRange(APInt(8, -2), APInt(8, 1)));
+
+  // Multiplication by -1 should give precise results.
+  EXPECT_EQ(ConstantRange(APInt(8, 3), APInt(8, -11))
+                .multiply(ConstantRange(APInt(8, -1))),
+            ConstantRange(APInt(8, 12), APInt(8, -2)));
+  EXPECT_EQ(ConstantRange(APInt(8, -1))
+                .multiply(ConstantRange(APInt(8, 3), APInt(8, -11))),
+            ConstantRange(APInt(8, 12), APInt(8, -2)));
+
+  TestBinaryOpExhaustive(
+      [](const ConstantRange &CR1, const ConstantRange &CR2) {
+        return CR1.multiply(CR2);
+      },
+      [](const APInt &N1, const APInt &N2) {
+        return N1 * N2;
+      },
+      PreferSmallest,
+      [](const ConstantRange &, const ConstantRange &) {
+        return false; // Check correctness only.
+      });
 }
 
 TEST_F(ConstantRangeTest, smul_fast) {


        


More information about the llvm-commits mailing list