Index: llvm/trunk/include/llvm/IR/ConstantRange.h =================================================================== --- llvm/trunk/include/llvm/IR/ConstantRange.h +++ llvm/trunk/include/llvm/IR/ConstantRange.h @@ -399,6 +399,9 @@ /// 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; Index: llvm/trunk/lib/IR/ConstantRange.cpp =================================================================== --- llvm/trunk/lib/IR/ConstantRange.cpp +++ llvm/trunk/lib/IR/ConstantRange.cpp @@ -1252,6 +1252,26 @@ 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"; Index: llvm/trunk/unittests/IR/ConstantRangeTest.cpp =================================================================== --- llvm/trunk/unittests/IR/ConstantRangeTest.cpp +++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp @@ -1578,6 +1578,18 @@ }); } +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) {