[llvm] r335646 - [ConstantRange] Add support of mul in makeGuaranteedNoWrapRegion.

Tim Shen via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 26 11:54:10 PDT 2018


Author: timshen
Date: Tue Jun 26 11:54:10 2018
New Revision: 335646

URL: http://llvm.org/viewvc/llvm-project?rev=335646&view=rev
Log:
[ConstantRange] Add support of mul in makeGuaranteedNoWrapRegion.

Summary: This is trying to add support for r334428.

Reviewers: sanjoy

Subscribers: jlebar, hiraditya, bixia, llvm-commits

Differential Revision: https://reviews.llvm.org/D48399

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

Modified: llvm/trunk/lib/IR/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantRange.cpp?rev=335646&r1=335645&r2=335646&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantRange.cpp (original)
+++ llvm/trunk/lib/IR/ConstantRange.cpp Tue Jun 26 11:54:10 2018
@@ -255,6 +255,64 @@ ConstantRange::makeGuaranteedNoWrapRegio
                           APInt::getSignedMinValue(BitWidth) + SignedMin));
     }
     return Result;
+  case Instruction::Mul: {
+    if (NoWrapKind == (OBO::NoSignedWrap | OBO::NoUnsignedWrap)) {
+      return SubsetIntersect(
+          makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoSignedWrap),
+          makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoUnsignedWrap));
+    }
+
+    // Equivalent to calling makeGuaranteedNoWrapRegion() on [V, V+1).
+    const bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
+    const auto makeSingleValueRegion = [Unsigned,
+                                        BitWidth](APInt V) -> ConstantRange {
+      // Handle special case for 0, -1 and 1. See the last for reason why we
+      // specialize -1 and 1.
+      if (V == 0 || V.isOneValue())
+        return ConstantRange(BitWidth, true);
+
+      APInt MinValue, MaxValue;
+      if (Unsigned) {
+        MinValue = APInt::getMinValue(BitWidth);
+        MaxValue = APInt::getMaxValue(BitWidth);
+      } else {
+        MinValue = APInt::getSignedMinValue(BitWidth);
+        MaxValue = APInt::getSignedMaxValue(BitWidth);
+      }
+      // e.g. Returning [-127, 127], represented as [-127, -128).
+      if (!Unsigned && V.isAllOnesValue())
+        return ConstantRange(-MaxValue, MinValue);
+
+      APInt Lower, Upper;
+      if (!Unsigned && V.isNegative()) {
+        Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
+        Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
+      } else if (Unsigned) {
+        Lower = APIntOps::RoundingUDiv(MinValue, V, APInt::Rounding::UP);
+        Upper = APIntOps::RoundingUDiv(MaxValue, V, APInt::Rounding::DOWN);
+      } else {
+        Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
+        Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
+      }
+      if (Unsigned) {
+        Lower = Lower.zextOrSelf(BitWidth);
+        Upper = Upper.zextOrSelf(BitWidth);
+      } else {
+        Lower = Lower.sextOrSelf(BitWidth);
+        Upper = Upper.sextOrSelf(BitWidth);
+      }
+      // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
+      // Upper + 1 is guanranteed not to overflow, because |divisor| > 1. 0, -1,
+      // and 1 are already handled as special cases.
+      return ConstantRange(Lower, Upper + 1);
+    };
+
+    if (Unsigned)
+      return makeSingleValueRegion(Other.getUnsignedMax());
+
+    return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()),
+                           makeSingleValueRegion(Other.getSignedMax()));
+  }
   }
 }
 

Modified: llvm/trunk/unittests/IR/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantRangeTest.cpp?rev=335646&r1=335645&r2=335646&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantRangeTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp Tue Jun 26 11:54:10 2018
@@ -1021,4 +1021,103 @@ TEST(ConstantRange, GetEquivalentICmp) {
   EXPECT_EQ(RHS, APInt(32, -1));
 }
 
+TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedSingleValue) {
+  typedef OverflowingBinaryOperator OBO;
+
+  for (uint64_t I = std::numeric_limits<uint8_t>::min();
+       I <= std::numeric_limits<uint8_t>::max(); I++) {
+    auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
+        Instruction::Mul, ConstantRange(APInt(8, I), APInt(8, I + 1)),
+        OBO::NoUnsignedWrap);
+
+    for (uint64_t V = std::numeric_limits<uint8_t>::min();
+         V <= std::numeric_limits<uint8_t>::max(); V++) {
+      bool Overflow;
+      (void)APInt(8, I).umul_ov(APInt(8, V), Overflow);
+      EXPECT_EQ(!Overflow, Range.contains(APInt(8, V)));
+    }
+  }
+}
+
+TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulSignedSingleValue) {
+  typedef OverflowingBinaryOperator OBO;
+
+  for (int64_t I = std::numeric_limits<int8_t>::min();
+       I <= std::numeric_limits<int8_t>::max(); I++) {
+    auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
+        Instruction::Mul,
+        ConstantRange(APInt(8, I, /*isSigned=*/true),
+                      APInt(8, I + 1, /*isSigned=*/true)),
+        OBO::NoSignedWrap);
+
+    for (int64_t V = std::numeric_limits<int8_t>::min();
+         V <= std::numeric_limits<int8_t>::max(); V++) {
+      bool Overflow;
+      (void)APInt(8, I, /*isSigned=*/true)
+          .smul_ov(APInt(8, V, /*isSigned=*/true), Overflow);
+      EXPECT_EQ(!Overflow, Range.contains(APInt(8, V, /*isSigned=*/true)));
+    }
+  }
+}
+
+TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedAndSignedSingleValue) {
+  typedef OverflowingBinaryOperator OBO;
+
+  for (uint64_t I = std::numeric_limits<uint8_t>::min();
+       I <= std::numeric_limits<uint8_t>::max(); I++) {
+    auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
+        Instruction::Mul, ConstantRange(APInt(8, I), APInt(8, I + 1)),
+        OBO::NoUnsignedWrap | OBO::NoSignedWrap);
+
+    for (uint64_t V = std::numeric_limits<uint8_t>::min();
+         V <= std::numeric_limits<uint8_t>::max(); V++) {
+      bool UOverflow;
+      (void)APInt(8, I).umul_ov(APInt(8, V), UOverflow);
+      bool SOverflow;
+      (void)APInt(8, I).smul_ov(APInt(8, V), SOverflow);
+      EXPECT_EQ(!(UOverflow || SOverflow), Range.contains(APInt(8, V)));
+    }
+  }
+}
+
+TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulUnsignedRange) {
+  typedef OverflowingBinaryOperator OBO;
+
+  for (uint64_t Lo = std::numeric_limits<uint8_t>::min();
+       Lo <= std::numeric_limits<uint8_t>::max(); Lo++) {
+    for (uint64_t Hi = Lo; Hi <= std::numeric_limits<uint8_t>::max(); Hi++) {
+      EXPECT_EQ(
+          ConstantRange::makeGuaranteedNoWrapRegion(
+              Instruction::Mul, ConstantRange(APInt(8, Lo), APInt(8, Hi + 1)),
+              OBO::NoUnsignedWrap),
+          ConstantRange::makeGuaranteedNoWrapRegion(
+              Instruction::Mul, ConstantRange(APInt(8, Hi), APInt(8, Hi + 1)),
+              OBO::NoUnsignedWrap));
+    }
+  }
+}
+
+TEST(ConstantRange, MakeGuaranteedNoWrapRegionMulSignedRange) {
+  typedef OverflowingBinaryOperator OBO;
+
+  int Lo = -12, Hi = 16;
+  auto Range = ConstantRange::makeGuaranteedNoWrapRegion(
+      Instruction::Mul,
+      ConstantRange(APInt(8, Lo, /*isSigned=*/true),
+                    APInt(8, Hi + 1, /*isSigned=*/true)),
+      OBO::NoSignedWrap);
+
+  for (int64_t V = std::numeric_limits<int8_t>::min();
+       V <= std::numeric_limits<int8_t>::max(); V++) {
+    bool AnyOverflow = false;
+    for (int64_t I = Lo; I <= Hi; I++) {
+      bool Overflow;
+      (void)APInt(8, I, /*isSigned=*/true)
+          .smul_ov(APInt(8, V, /*isSigned=*/true), Overflow);
+      AnyOverflow |= Overflow;
+    }
+    EXPECT_EQ(!AnyOverflow, Range.contains(APInt(8, V, /*isSigned=*/true)));
+  }
+}
+
 }  // anonymous namespace




More information about the llvm-commits mailing list