Skip to content

Commit ca00cec

Browse files
authored
[ConstantRange] Infer nonnegative for mul nuw nsw (#100554)
Alive2: https://alive2.llvm.org/ce/z/byzmsV
1 parent fd17064 commit ca00cec

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

llvm/lib/IR/ConstantRange.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,17 @@ ConstantRange::multiplyWithNoWrap(const ConstantRange &Other,
12421242
if (NoWrapKind & OverflowingBinaryOperator::NoUnsignedWrap)
12431243
Result = Result.intersectWith(umul_sat(Other), RangeType);
12441244

1245+
// mul nsw nuw X, Y s>= 0 if X s> 1 or Y s> 1
1246+
if ((NoWrapKind == (OverflowingBinaryOperator::NoSignedWrap |
1247+
OverflowingBinaryOperator::NoUnsignedWrap)) &&
1248+
!Result.isAllNonNegative()) {
1249+
if (getSignedMin().sgt(1) || Other.getSignedMin().sgt(1))
1250+
Result = Result.intersectWith(
1251+
getNonEmpty(APInt::getZero(getBitWidth()),
1252+
APInt::getSignedMinValue(getBitWidth())),
1253+
RangeType);
1254+
}
1255+
12451256
return Result;
12461257
}
12471258

llvm/test/Transforms/CorrelatedValuePropagation/mul.ll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,35 @@ define i1 @one_bit(i1 %a, i1 %b) {
224224
%mul = mul i1 %a, %b
225225
ret i1 %mul
226226
}
227+
228+
define i1 @test_mul_nuw_nsw_nneg(i32 %x, i32 range(i32 3, 2147483648) %y) {
229+
; CHECK-LABEL: @test_mul_nuw_nsw_nneg(
230+
; CHECK-NEXT: entry:
231+
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X:%.*]], [[Y:%.*]]
232+
; CHECK-NEXT: ret i1 true
233+
;
234+
entry:
235+
%mul = mul nuw nsw i32 %x, %y
236+
%cmp = icmp sgt i32 %mul, -1
237+
ret i1 %cmp
238+
}
239+
240+
define i1 @test_mul_nuw_nsw_nneg_complex(i32 %x, i32 noundef %y, i32 %z) {
241+
; CHECK-LABEL: @test_mul_nuw_nsw_nneg_complex(
242+
; CHECK-NEXT: entry:
243+
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[Y:%.*]], 2
244+
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], 0
245+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP2]], i32 3, i32 4
246+
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP1]], i32 [[Y]], i32 [[SEL1]]
247+
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X]], [[SEL2]]
248+
; CHECK-NEXT: ret i1 true
249+
;
250+
entry:
251+
%cmp1 = icmp sgt i32 %y, 2
252+
%cmp2 = icmp eq i32 %x, 0
253+
%sel1 = select i1 %cmp2, i32 3, i32 4
254+
%sel2 = select i1 %cmp1, i32 %y, i32 %sel1
255+
%mul = mul nuw nsw i32 %x, %sel2
256+
%cmp3 = icmp sgt i32 %mul, -1
257+
ret i1 %cmp3
258+
}

llvm/unittests/IR/ConstantRangeTest.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,24 @@ TEST_F(ConstantRangeTest, MultiplyWithNoWrap) {
10701070
.multiplyWithNoWrap(ConstantRange(APInt(8, 100), APInt(8, 121)),
10711071
OBO::NoSignedWrap),
10721072
ConstantRange::getEmpty(8));
1073+
EXPECT_TRUE(ConstantRange::getFull(8)
1074+
.multiplyWithNoWrap(ConstantRange(APInt(8, 2), APInt(8, 128)),
1075+
OBO::NoUnsignedWrap | OBO::NoSignedWrap)
1076+
.isAllNonNegative());
1077+
EXPECT_TRUE(ConstantRange(APInt(8, 2), APInt(8, 128))
1078+
.multiplyWithNoWrap(ConstantRange::getFull(8),
1079+
OBO::NoUnsignedWrap | OBO::NoSignedWrap)
1080+
.isAllNonNegative());
1081+
EXPECT_FALSE(
1082+
ConstantRange::getFull(8)
1083+
.multiplyWithNoWrap(ConstantRange(APInt(8, 1), APInt(8, 128)),
1084+
OBO::NoUnsignedWrap | OBO::NoSignedWrap)
1085+
.isAllNonNegative());
1086+
EXPECT_FALSE(
1087+
ConstantRange::getFull(8)
1088+
.multiplyWithNoWrap(ConstantRange(APInt(8, 2), APInt(8, 128)),
1089+
OBO::NoSignedWrap)
1090+
.isAllNonNegative());
10731091

10741092
TestBinaryOpExhaustive(
10751093
[](const ConstantRange &CR1, const ConstantRange &CR2) {

0 commit comments

Comments
 (0)