aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/IR/ConstantRangeTest.cpp
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2022-07-18 15:13:12 +0200
committerNikita Popov <npopov@redhat.com>2022-07-18 15:14:17 +0200
commitb57d61384c9938e3dfa54b55bf8b2a0a05e67e28 (patch)
tree40a13ff3e0e5c671edb261f79213e8652cc73700 /llvm/unittests/IR/ConstantRangeTest.cpp
parentc287bc4841074b834137c1098ff3bd11fb93dd51 (diff)
downloadllvm-b57d61384c9938e3dfa54b55bf8b2a0a05e67e28.zip
llvm-b57d61384c9938e3dfa54b55bf8b2a0a05e67e28.tar.gz
llvm-b57d61384c9938e3dfa54b55bf8b2a0a05e67e28.tar.bz2
[ConstantRangeTest] Move nowrap binop tests to generic infrastructure (NFC)
Move testing for add/sub with nowrap flags to TestBinaryOpExhaustive, rather than separate homegrown exhaustive testing functions.
Diffstat (limited to 'llvm/unittests/IR/ConstantRangeTest.cpp')
-rw-r--r--llvm/unittests/IR/ConstantRangeTest.cpp210
1 files changed, 78 insertions, 132 deletions
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index edea097..e3fefe7 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -206,6 +206,22 @@ static bool CheckSingleElementsOnly(const ConstantRange &CR1,
return CR1.isSingleElement() && CR2.isSingleElement();
}
+static bool CheckNonWrappedOnly(const ConstantRange &CR1,
+ const ConstantRange &CR2) {
+ return !CR1.isWrappedSet() && !CR2.isWrappedSet();
+}
+
+static bool CheckNonSignWrappedOnly(const ConstantRange &CR1,
+ const ConstantRange &CR2) {
+ return !CR1.isSignWrappedSet() && !CR2.isSignWrappedSet();
+}
+
+static bool CheckNonWrappedOrSignWrappedOnly(const ConstantRange &CR1,
+ const ConstantRange &CR2) {
+ return !CR1.isWrappedSet() && !CR1.isSignWrappedSet() &&
+ !CR2.isWrappedSet() && !CR2.isSignWrappedSet();
+}
+
// CheckFn determines whether optimality is checked for a given range pair.
// Correctness is always checked.
static void TestBinaryOpExhaustive(BinaryRangeFn RangeFn, BinaryIntFn IntFn,
@@ -752,110 +768,6 @@ TEST_F(ConstantRangeTest, Add) {
});
}
-template <typename Fn1, typename Fn2>
-static void TestAddWithNoSignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
- unsigned Bits = 4;
- EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
- const ConstantRange &CR2) {
- ConstantRange CR = RangeFn(CR1, CR2);
- SignedOpRangeGatherer R(CR.getBitWidth());
- bool AllOverflow = true;
- ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
- ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
- bool IsOverflow = false;
- APInt N = IntFn(IsOverflow, N1, N2);
- if (!IsOverflow) {
- AllOverflow = false;
- R.account(N);
- EXPECT_TRUE(CR.contains(N));
- }
- });
- });
-
- EXPECT_EQ(CR.isEmptySet(), AllOverflow);
-
- if (CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
- return;
-
- ConstantRange Exact = R.getRange();
- EXPECT_EQ(Exact, CR);
- });
-}
-
-template <typename Fn1, typename Fn2>
-static void TestAddWithNoUnsignedWrapExhaustive(Fn1 RangeFn, Fn2 IntFn) {
- unsigned Bits = 4;
- EnumerateTwoConstantRanges(Bits, [&](const ConstantRange &CR1,
- const ConstantRange &CR2) {
- ConstantRange CR = RangeFn(CR1, CR2);
- UnsignedOpRangeGatherer R(CR.getBitWidth());
- bool AllOverflow = true;
- ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
- ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
- bool IsOverflow = false;
- APInt N = IntFn(IsOverflow, N1, N2);
- if (!IsOverflow) {
- AllOverflow = false;
- R.account(N);
- EXPECT_TRUE(CR.contains(N));
- }
- });
- });
-
- EXPECT_EQ(CR.isEmptySet(), AllOverflow);
-
- if (CR1.isWrappedSet() || CR2.isWrappedSet())
- return;
-
- ConstantRange Exact = R.getRange();
- EXPECT_EQ(Exact, CR);
- });
-}
-
-template <typename Fn1, typename Fn2, typename Fn3>
-static void TestAddWithNoSignedUnsignedWrapExhaustive(Fn1 RangeFn,
- Fn2 IntFnSigned,
- Fn3 IntFnUnsigned) {
- unsigned Bits = 4;
- EnumerateTwoConstantRanges(
- Bits, [&](const ConstantRange &CR1, const ConstantRange &CR2) {
- ConstantRange CR = RangeFn(CR1, CR2);
- UnsignedOpRangeGatherer UR(CR.getBitWidth());
- SignedOpRangeGatherer SR(CR.getBitWidth());
- bool AllOverflow = true;
- ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
- ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
- bool IsOverflow = false, IsSignedOverflow = false;
- APInt N = IntFnSigned(IsSignedOverflow, N1, N2);
- (void) IntFnUnsigned(IsOverflow, N1, N2);
- if (!IsSignedOverflow && !IsOverflow) {
- AllOverflow = false;
- UR.account(N);
- SR.account(N);
- EXPECT_TRUE(CR.contains(N));
- }
- });
- });
-
- EXPECT_EQ(CR.isEmptySet(), AllOverflow);
-
- if (CR1.isWrappedSet() || CR2.isWrappedSet() ||
- CR1.isSignWrappedSet() || CR2.isSignWrappedSet())
- return;
-
- ConstantRange ExactUnsignedCR = UR.getRange();
- ConstantRange ExactSignedCR = SR.getRange();
-
- if (ExactUnsignedCR.isEmptySet() || ExactSignedCR.isEmptySet()) {
- EXPECT_TRUE(CR.isEmptySet());
- return;
- }
-
- ConstantRange Exact = ExactSignedCR.intersectWith(ExactUnsignedCR);
- EXPECT_EQ(Exact, CR);
- });
-}
-
TEST_F(ConstantRangeTest, AddWithNoWrap) {
typedef OverflowingBinaryOperator OBO;
EXPECT_EQ(Empty.addWithNoWrap(Some, OBO::NoSignedWrap), Empty);
@@ -905,13 +817,19 @@ TEST_F(ConstantRangeTest, AddWithNoWrap) {
OBO::NoSignedWrap),
ConstantRange(APInt(8, 125), APInt(8, 9)));
- TestAddWithNoSignedWrapExhaustive(
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.addWithNoWrap(CR2, OBO::NoSignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.sadd_ov(N2, IsOverflow);
- });
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow;
+ APInt Res = N1.sadd_ov(N2, IsOverflow);
+ if (IsOverflow)
+ return None;
+ return Res;
+ },
+ PreferSmallest,
+ CheckNonSignWrappedOnly);
EXPECT_EQ(Empty.addWithNoWrap(Some, OBO::NoUnsignedWrap), Empty);
EXPECT_EQ(Some.addWithNoWrap(Empty, OBO::NoUnsignedWrap), Empty);
@@ -953,13 +871,19 @@ TEST_F(ConstantRangeTest, AddWithNoWrap) {
OBO::NoUnsignedWrap),
ConstantRange(APInt(8, 25), APInt(8, -11)));
- TestAddWithNoUnsignedWrapExhaustive(
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.addWithNoWrap(CR2, OBO::NoUnsignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.uadd_ov(N2, IsOverflow);
- });
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow;
+ APInt Res = N1.uadd_ov(N2, IsOverflow);
+ if (IsOverflow)
+ return None;
+ return Res;
+ },
+ PreferSmallest,
+ CheckNonWrappedOnly);
EXPECT_EQ(ConstantRange(APInt(8, 50), APInt(8, 100))
.addWithNoWrap(ConstantRange(APInt(8, 20), APInt(8, 70)),
@@ -987,16 +911,21 @@ TEST_F(ConstantRangeTest, AddWithNoWrap) {
OBO::NoUnsignedWrap | OBO::NoSignedWrap),
ConstantRange(APInt(8, 176), APInt(8, 235)));
- TestAddWithNoSignedUnsignedWrapExhaustive(
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.addWithNoWrap(CR2, OBO::NoUnsignedWrap | OBO::NoSignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.sadd_ov(N2, IsOverflow);
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow1, IsOverflow2;
+ APInt Res1 = N1.uadd_ov(N2, IsOverflow1);
+ APInt Res2 = N1.sadd_ov(N2, IsOverflow2);
+ if (IsOverflow1 || IsOverflow2)
+ return None;
+ assert(Res1 == Res2 && "Addition results differ?");
+ return Res1;
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.uadd_ov(N2, IsOverflow);
- });
+ PreferSmallest,
+ CheckNonWrappedOrSignWrappedOnly);
}
TEST_F(ConstantRangeTest, Sub) {
@@ -1031,30 +960,47 @@ TEST_F(ConstantRangeTest, Sub) {
TEST_F(ConstantRangeTest, SubWithNoWrap) {
typedef OverflowingBinaryOperator OBO;
- TestAddWithNoSignedWrapExhaustive(
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.subWithNoWrap(CR2, OBO::NoSignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.ssub_ov(N2, IsOverflow);
- });
- TestAddWithNoUnsignedWrapExhaustive(
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow;
+ APInt Res = N1.ssub_ov(N2, IsOverflow);
+ if (IsOverflow)
+ return None;
+ return Res;
+ },
+ PreferSmallest,
+ CheckNonSignWrappedOnly);
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.subWithNoWrap(CR2, OBO::NoUnsignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.usub_ov(N2, IsOverflow);
- });
- TestAddWithNoSignedUnsignedWrapExhaustive(
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow;
+ APInt Res = N1.usub_ov(N2, IsOverflow);
+ if (IsOverflow)
+ return None;
+ return Res;
+ },
+ PreferSmallest,
+ CheckNonWrappedOnly);
+ TestBinaryOpExhaustive(
[](const ConstantRange &CR1, const ConstantRange &CR2) {
return CR1.subWithNoWrap(CR2, OBO::NoUnsignedWrap | OBO::NoSignedWrap);
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.ssub_ov(N2, IsOverflow);
+ [](const APInt &N1, const APInt &N2) -> Optional<APInt> {
+ bool IsOverflow1, IsOverflow2;
+ APInt Res1 = N1.usub_ov(N2, IsOverflow1);
+ APInt Res2 = N1.ssub_ov(N2, IsOverflow2);
+ if (IsOverflow1 || IsOverflow2)
+ return None;
+ assert(Res1 == Res2 && "Subtraction results differ?");
+ return Res1;
},
- [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
- return N1.usub_ov(N2, IsOverflow);
- });
+ PreferSmallest,
+ CheckNonWrappedOrSignWrappedOnly);
}
TEST_F(ConstantRangeTest, Multiply) {