Skip to content

Commit 7cf567d

Browse files
committed
[ConstantRange] Calculate precise range for multiply by -1
These are pretty common in SCEV, so make sure we get a precise result by mapping to the sub() operation.
1 parent 04a8070 commit 7cf567d

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

llvm/lib/IR/ConstantRange.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,20 @@ ConstantRange::multiply(const ConstantRange &Other) const {
10951095
if (isEmptySet() || Other.isEmptySet())
10961096
return getEmpty();
10971097

1098+
if (const APInt *C = getSingleElement()) {
1099+
if (C->isOne())
1100+
return Other;
1101+
if (C->isAllOnes())
1102+
return ConstantRange(APInt::getZero(getBitWidth())).sub(Other);
1103+
}
1104+
1105+
if (const APInt *C = Other.getSingleElement()) {
1106+
if (C->isOne())
1107+
return *this;
1108+
if (C->isAllOnes())
1109+
return ConstantRange(APInt::getZero(getBitWidth())).sub(*this);
1110+
}
1111+
10981112
// Multiplication is signedness-independent. However different ranges can be
10991113
// obtained depending on how the input ranges are treated. These different
11001114
// ranges are all conservatively correct, but one might be better than the

llvm/unittests/IR/ConstantRangeTest.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,26 @@ TEST_F(ConstantRangeTest, Multiply) {
997997
EXPECT_EQ(ConstantRange(APInt(8, -2)).multiply(
998998
ConstantRange(APInt(8, 0), APInt(8, 2))),
999999
ConstantRange(APInt(8, -2), APInt(8, 1)));
1000+
1001+
// Multiplication by -1 should give precise results.
1002+
EXPECT_EQ(ConstantRange(APInt(8, 3), APInt(8, -11))
1003+
.multiply(ConstantRange(APInt(8, -1))),
1004+
ConstantRange(APInt(8, 12), APInt(8, -2)));
1005+
EXPECT_EQ(ConstantRange(APInt(8, -1))
1006+
.multiply(ConstantRange(APInt(8, 3), APInt(8, -11))),
1007+
ConstantRange(APInt(8, 12), APInt(8, -2)));
1008+
1009+
TestBinaryOpExhaustive(
1010+
[](const ConstantRange &CR1, const ConstantRange &CR2) {
1011+
return CR1.multiply(CR2);
1012+
},
1013+
[](const APInt &N1, const APInt &N2) {
1014+
return N1 * N2;
1015+
},
1016+
PreferSmallest,
1017+
[](const ConstantRange &, const ConstantRange &) {
1018+
return false; // Check correctness only.
1019+
});
10001020
}
10011021

10021022
TEST_F(ConstantRangeTest, smul_fast) {

0 commit comments

Comments
 (0)