[PATCH] D69918: [CR][WIP] Add `subWithNoWrap()` method
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 6 14:31:50 PST 2019
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7fbe5d4b2ab9: [ConstantRange] Add `subWithNoWrap()` method (authored by lebedev.ri).
Changed prior to commit:
https://reviews.llvm.org/D69918?vs=228140&id=228152#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69918/new/
https://reviews.llvm.org/D69918
Files:
llvm/include/llvm/IR/ConstantRange.h
llvm/lib/IR/ConstantRange.cpp
llvm/unittests/IR/ConstantRangeTest.cpp
Index: llvm/unittests/IR/ConstantRangeTest.cpp
===================================================================
--- llvm/unittests/IR/ConstantRangeTest.cpp
+++ llvm/unittests/IR/ConstantRangeTest.cpp
@@ -934,6 +934,34 @@
ConstantRange(APInt(16, 0x6)));
}
+TEST_F(ConstantRangeTest, SubWithNoWrap) {
+ typedef OverflowingBinaryOperator OBO;
+ TestAddWithNoSignedWrapExhaustive(
+ [](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 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 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);
+ },
+ [](bool &IsOverflow, const APInt &N1, const APInt &N2) {
+ return N1.usub_ov(N2, IsOverflow);
+ });
+}
+
TEST_F(ConstantRangeTest, Multiply) {
EXPECT_EQ(Full.multiply(Full), Full);
EXPECT_EQ(Full.multiply(Empty), Empty);
Index: llvm/lib/IR/ConstantRange.cpp
===================================================================
--- llvm/lib/IR/ConstantRange.cpp
+++ llvm/lib/IR/ConstantRange.cpp
@@ -898,6 +898,36 @@
return X;
}
+ConstantRange ConstantRange::subWithNoWrap(const ConstantRange &Other,
+ unsigned NoWrapKind,
+ PreferredRangeType RangeType) const {
+ // Calculate the range for "X - Y" which is guaranteed not to wrap(overflow).
+ // (X is from this, and Y is from Other)
+ if (isEmptySet() || Other.isEmptySet())
+ return getEmpty();
+ if (isFullSet() && Other.isFullSet())
+ return getFull();
+
+ using OBO = OverflowingBinaryOperator;
+ ConstantRange Result = sub(Other);
+
+ // If an overflow happens for every value pair in these two constant ranges,
+ // we must return Empty set. In signed case, we get that for free, because we
+ // get lucky that intersection of add() with ssub_sat() results in an
+ // empty set. But for unsigned we must perform the overflow check manually.
+
+ if (NoWrapKind & OBO::NoSignedWrap)
+ Result = Result.intersectWith(ssub_sat(Other), RangeType);
+
+ if (NoWrapKind & OBO::NoUnsignedWrap) {
+ if (getUnsignedMax().ult(Other.getUnsignedMin()))
+ return getEmpty(); // Always overflows.
+ Result = Result.intersectWith(usub_sat(Other), RangeType);
+ }
+
+ return Result;
+}
+
ConstantRange
ConstantRange::multiply(const ConstantRange &Other) const {
// TODO: If either operand is a single element and the multiply is known to
Index: llvm/include/llvm/IR/ConstantRange.h
===================================================================
--- llvm/include/llvm/IR/ConstantRange.h
+++ llvm/include/llvm/IR/ConstantRange.h
@@ -351,6 +351,14 @@
ConstantRange sub(const ConstantRange &Other) const;
/// Return a new range representing the possible values resulting
+ /// from an subtraction with wrap type \p NoWrapKind of a value in this
+ /// range and a value in \p Other.
+ /// If the result range is disjoint, the preferred range is determined by the
+ /// \p PreferredRangeType.
+ ConstantRange subWithNoWrap(const ConstantRange &Other, unsigned NoWrapKind,
+ PreferredRangeType RangeType = Smallest) const;
+
+ /// Return a new range representing the possible values resulting
/// from a multiplication of a value in this range and a value in \p Other,
/// treating both this and \p Other as unsigned ranges.
ConstantRange multiply(const ConstantRange &Other) const;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69918.228152.patch
Type: text/x-patch
Size: 4090 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191106/75465355/attachment.bin>
More information about the llvm-commits
mailing list