diff options
| author | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-11 21:10:33 +0000 |
|---|---|---|
| committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-11 21:10:33 +0000 |
| commit | e319eafb20815d3773c78655819fc2355b2b9123 (patch) | |
| tree | 803ff2a5648d68a60df3444161aa7f6ade1f9740 | |
| parent | db615bb313bf639693fac295843f06739bca459c (diff) | |
| download | bcm5719-llvm-e319eafb20815d3773c78655819fc2355b2b9123.tar.gz bcm5719-llvm-e319eafb20815d3773c78655819fc2355b2b9123.zip | |
[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
llvm-svn: 358228
| -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) { |

