From: Nikita Popov Date: Thu, 11 Apr 2019 21:10:33 +0000 (+0000) Subject: [ConstantRange] Add unsignedMulMayOverflow() X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d6ce6ef4db6a90e79bfcf3af82599a29cf07c859;p=llvm [ConstantRange] Add unsignedMulMayOverflow() Same as the other ConstantRange overflow checking methods, but for unsigned mul. In this case there is no cheap overflow criterion, so using umul_ov for the implementation. Differential Revision: https://reviews.llvm.org/D60574 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358228 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index a8d51b37957..d98bf96a21c 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/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/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp index 391d9653db5..35c2b0e2e2c 100644 --- a/lib/IR/ConstantRange.cpp +++ b/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/unittests/IR/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp index 55e71a1f29b..6d1b512d229 100644 --- a/unittests/IR/ConstantRangeTest.cpp +++ b/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) {