summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/IR/ConstantRangeTest.cpp
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-04-12 19:36:47 +0000
committerNikita Popov <nikita.ppv@gmail.com>2019-04-12 19:36:47 +0000
commit3dc7c7ca3115ba9294f72074fdea0bf9bf6f6b60 (patch)
treef48a378bc632c0c0d61b0a91f904602b3c0cb19b /llvm/unittests/IR/ConstantRangeTest.cpp
parent2312a06c87207d28c83707db019b4053ceea9bae (diff)
downloadbcm5719-llvm-3dc7c7ca3115ba9294f72074fdea0bf9bf6f6b60.tar.gz
bcm5719-llvm-3dc7c7ca3115ba9294f72074fdea0bf9bf6f6b60.zip
[ConstantRange] Clarify makeGuaranteedNoWrapRegion() guarantees; NFC
makeGuaranteedNoWrapRegion() is actually makeExactNoWrapRegion() as long as only one of NUW or NSW is specified. This is not obvious from the current documentation, and some code seems to think that it is only exact for single-element ranges. Clarify docs and add tests to be more confident this really holds. There are currently no users of makeGuaranteedNoWrapRegion() that pass both NUW and NSW. I think it would be best to drop support for this entirely and then rename the function to makeExactNoWrapRegion(). Knowing that the no-wrap region is exact is useful, because we can backwards-constrain values. What I have in mind in particular is that LVI should be able to constrain values on edges where the with.overflow overflow flag is false. Differential Revision: https://reviews.llvm.org/D60598 llvm-svn: 358305
Diffstat (limited to 'llvm/unittests/IR/ConstantRangeTest.cpp')
-rw-r--r--llvm/unittests/IR/ConstantRangeTest.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 6d1b512d229..322be45bb28 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -1151,6 +1151,76 @@ TEST(ConstantRange, MakeGuaranteedNoWrapRegion) {
ConstantRange(APInt::getMinValue(32) + 1, APInt::getSignedMinValue(32)));
}
+template<typename Fn>
+void TestNoWrapRegionExhaustive(Instruction::BinaryOps BinOp,
+ unsigned NoWrapKind, Fn OverflowFn) {
+ // When using 4 bits this test needs ~3s on a debug build.
+ unsigned Bits = 3;
+ EnumerateTwoConstantRanges(Bits,
+ [&](const ConstantRange &CR1, const ConstantRange &CR2) {
+ if (CR2.isEmptySet())
+ return;
+
+ ConstantRange NoWrap =
+ ConstantRange::makeGuaranteedNoWrapRegion(BinOp, CR2, NoWrapKind);
+ ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
+ bool NoOverflow = true;
+ ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
+ if (OverflowFn(N1, N2))
+ NoOverflow = false;
+ });
+ EXPECT_EQ(NoOverflow, NoWrap.contains(N1));
+ });
+ });
+}
+
+// Show that makeGuaranteedNoWrapRegion is precise if only one of
+// NoUnsignedWrap or NoSignedWrap is used.
+TEST(ConstantRange, NoWrapRegionExhaustive) {
+ TestNoWrapRegionExhaustive(
+ Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.uadd_ov(N2, Overflow);
+ return Overflow;
+ });
+ TestNoWrapRegionExhaustive(
+ Instruction::Add, OverflowingBinaryOperator::NoSignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.sadd_ov(N2, Overflow);
+ return Overflow;
+ });
+ TestNoWrapRegionExhaustive(
+ Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.usub_ov(N2, Overflow);
+ return Overflow;
+ });
+ TestNoWrapRegionExhaustive(
+ Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.ssub_ov(N2, Overflow);
+ return Overflow;
+ });
+ TestNoWrapRegionExhaustive(
+ Instruction::Mul, OverflowingBinaryOperator::NoUnsignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.umul_ov(N2, Overflow);
+ return Overflow;
+ });
+ TestNoWrapRegionExhaustive(
+ Instruction::Mul, OverflowingBinaryOperator::NoSignedWrap,
+ [](const APInt &N1, const APInt &N2) {
+ bool Overflow;
+ (void) N1.smul_ov(N2, Overflow);
+ return Overflow;
+ });
+}
+
TEST(ConstantRange, GetEquivalentICmp) {
APInt RHS;
CmpInst::Predicate Pred;
OpenPOWER on IntegriCloud