[PATCH] D125933: [ConstantRange] Improve the implementation of binaryOr
Alexander Shaposhnikov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed May 18 15:32:39 PDT 2022
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: nikic, spatel.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a subscriber: hiraditya.
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: LLVM.
This diff is a continuation of the effort stared in D125603 <https://reviews.llvm.org/D125603> and makes ConstantRange::binaryOr return a more precise result.
Test plan:
1/ ninja check-llvm-unit
2/ ninja check-llvm
3/ ninja check-clang
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D125933
Files:
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
@@ -2560,6 +2560,43 @@
CheckSingleElementsOnly);
}
+TEST_F(ConstantRangeTest, binaryOr) {
+ // Single element ranges.
+ ConstantRange R16(APInt(8, 16));
+ ConstantRange R20(APInt(8, 20));
+ EXPECT_EQ(*R16.binaryOr(R16).getSingleElement(), APInt(8, 16));
+ EXPECT_EQ(*R16.binaryOr(R20).getSingleElement(), APInt(8, 16 | 20));
+
+ ConstantRange R16_32(APInt(8, 16), APInt(8, 32));
+ // 'Or' with a high bits mask.
+ // KnownBits estimate is important, otherwise the maximum included element
+ // would be 2^8 - 1.
+ ConstantRange R32(APInt(8, 32));
+ ConstantRange R48_64(APInt(8, 48), APInt(8, 64));
+ EXPECT_EQ(R16_32.binaryOr(R32), R48_64);
+ EXPECT_EQ(R32.binaryOr(R16_32), R48_64);
+ // 'Or' with a low bits mask.
+ ConstantRange R4(APInt(8, 4));
+ ConstantRange R0_16(APInt(8, 0), APInt(8, 16));
+ ConstantRange R4_16(APInt(8, 4), APInt(8, 16));
+ EXPECT_EQ(R0_16.binaryOr(R4), R4_16);
+ EXPECT_EQ(R4.binaryOr(R0_16), R4_16);
+
+ // Ranges with more than one element. Handled conservatively for now.
+ // UMaxUMin estimate is important, otherwise the lower bound would be zero.
+ ConstantRange R0_64(APInt(8, 0), APInt(8, 64));
+ ConstantRange R5_32(APInt(8, 5), APInt(8, 32));
+ ConstantRange R5_64(APInt(8, 5), APInt(8, 64));
+ EXPECT_EQ(R0_64.binaryOr(R5_32), R5_64);
+
+ TestBinaryOpExhaustive(
+ [](const ConstantRange &CR1, const ConstantRange &CR2) {
+ return CR1.binaryOr(CR2);
+ },
+ [](const APInt &N1, const APInt &N2) { return N1 | N2; }, PreferSmallest,
+ CheckSingleElementsOnly);
+}
+
TEST_F(ConstantRangeTest, binaryXor) {
// Single element ranges.
ConstantRange R16(APInt(8, 16));
Index: llvm/lib/IR/ConstantRange.cpp
===================================================================
--- llvm/lib/IR/ConstantRange.cpp
+++ llvm/lib/IR/ConstantRange.cpp
@@ -1402,14 +1402,13 @@
if (isEmptySet() || Other.isEmptySet())
return getEmpty();
- // Use APInt's implementation of OR for single element ranges.
- if (isSingleElement() && Other.isSingleElement())
- return {*getSingleElement() | *Other.getSingleElement()};
-
- // TODO: replace this with something less conservative
-
- APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
- return getNonEmpty(std::move(umax), APInt::getZero(getBitWidth()));
+ ConstantRange KnownBitsRange =
+ fromKnownBits(toKnownBits() | Other.toKnownBits(), false);
+ // Upper wrapped range.
+ ConstantRange UMaxUMinRange =
+ getNonEmpty(APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()),
+ APInt::getZero(getBitWidth()));
+ return KnownBitsRange.intersectWith(UMaxUMinRange);
}
ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D125933.430517.patch
Type: text/x-patch
Size: 2954 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220518/71fefeb0/attachment.bin>
More information about the llvm-commits
mailing list