diff options
| -rw-r--r-- | llvm/include/llvm/IR/ConstantRange.h | 3 | ||||
| -rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 20 | ||||
| -rw-r--r-- | llvm/unittests/IR/ConstantRangeTest.cpp | 12 | 
3 files changed, 35 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index a8d51b37957..d98bf96a21c 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -399,6 +399,9 @@ public:    /// Return whether signed sub of the two ranges always/never overflows.    OverflowResult signedSubMayOverflow(const ConstantRange &Other) const; +  /// Return whether unsigned mul of the two ranges always/never overflows. +  OverflowResult unsignedMulMayOverflow(const ConstantRange &Other) const; +    /// Print out the bounds to a stream.    void print(raw_ostream &OS) const; diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 391d9653db5..35c2b0e2e2c 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1252,6 +1252,26 @@ ConstantRange::OverflowResult ConstantRange::signedSubMayOverflow(    return OverflowResult::NeverOverflows;  } +ConstantRange::OverflowResult ConstantRange::unsignedMulMayOverflow( +    const ConstantRange &Other) const { +  if (isEmptySet() || Other.isEmptySet()) +    return OverflowResult::MayOverflow; + +  APInt Min = getUnsignedMin(), Max = getUnsignedMax(); +  APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax(); +  bool Overflow; + +  (void) Min.umul_ov(OtherMin, Overflow); +  if (Overflow) +    return OverflowResult::AlwaysOverflows; + +  (void) Max.umul_ov(OtherMax, Overflow); +  if (Overflow) +    return OverflowResult::MayOverflow; + +  return OverflowResult::NeverOverflows; +} +  void ConstantRange::print(raw_ostream &OS) const {    if (isFullSet())      OS << "full-set"; diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index 55e71a1f29b..6d1b512d229 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -1578,6 +1578,18 @@ TEST_F(ConstantRangeTest, UnsignedSubOverflowExhaustive) {        });  } +TEST_F(ConstantRangeTest, UnsignedMulOverflowExhaustive) { +  TestOverflowExhaustive( +      [](const APInt &N1, const APInt &N2) { +        bool Overflow; +        (void) N1.umul_ov(N2, Overflow); +        return Overflow; +      }, +      [](const ConstantRange &CR1, const ConstantRange &CR2) { +        return CR1.unsignedMulMayOverflow(CR2); +      }); +} +  TEST_F(ConstantRangeTest, SignedAddOverflowExhaustive) {    TestOverflowExhaustive(        [](const APInt &N1, const APInt &N2) {  | 

