Skip to content

Commit 2872987

Browse files
committed
[InstCombine] Fix InstCombinerImpl::foldICmpMulConstant for nsw and nuw mul with unsigned compare.
If we have both an nsw and nuw flag, we would see the nsw flag first and only handle signed comparisons. This patch ignores the nsw flag if the comparison isn't signed. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D143766
1 parent 41628d0 commit 2872987

File tree

2 files changed

+21
-25
lines changed

2 files changed

+21
-25
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,35 +2061,37 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
20612061
}
20622062
}
20632063

2064-
if (!Mul->hasNoSignedWrap() && !Mul->hasNoUnsignedWrap())
2065-
return nullptr;
2066-
20672064
// With a matching no-overflow guarantee, fold the constants:
20682065
// (X * MulC) < C --> X < (C / MulC)
20692066
// (X * MulC) > C --> X > (C / MulC)
20702067
// TODO: Assert that Pred is not equal to SGE, SLE, UGE, ULE?
20712068
Constant *NewC = nullptr;
2072-
if (Mul->hasNoSignedWrap()) {
2069+
if (Mul->hasNoSignedWrap() && ICmpInst::isSigned(Pred)) {
20732070
// MININT / -1 --> overflow.
20742071
if (C.isMinSignedValue() && MulC->isAllOnes())
20752072
return nullptr;
20762073
if (MulC->isNegative())
20772074
Pred = ICmpInst::getSwappedPredicate(Pred);
20782075

2079-
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE)
2076+
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) {
20802077
NewC = ConstantInt::get(
20812078
MulTy, APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::UP));
2082-
if (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_SGT)
2079+
} else {
2080+
assert((Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_SGT) &&
2081+
"Unexpected predicate");
20832082
NewC = ConstantInt::get(
20842083
MulTy, APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::DOWN));
2085-
} else {
2086-
assert(Mul->hasNoUnsignedWrap() && "Expected mul nuw");
2087-
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)
2084+
}
2085+
} else if (Mul->hasNoUnsignedWrap() && ICmpInst::isUnsigned(Pred)) {
2086+
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE) {
20882087
NewC = ConstantInt::get(
20892088
MulTy, APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::UP));
2090-
if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT)
2089+
} else {
2090+
assert((Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT) &&
2091+
"Unexpected predicate");
20912092
NewC = ConstantInt::get(
20922093
MulTy, APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::DOWN));
2094+
}
20932095
}
20942096

20952097
return NewC ? new ICmpInst(Pred, X, NewC) : nullptr;

llvm/test/Transforms/InstCombine/icmp-mul.ll

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,10 @@ define i1 @ult_rem_zero(i8 %x) {
134134
}
135135

136136
; Same as above, but with nsw flag too.
137-
; FIXME: This should be optimized like above.
137+
; This used to not optimize due to nsw being prioritized too much.
138138
define i1 @ult_rem_zero_nsw(i8 %x) {
139139
; CHECK-LABEL: @ult_rem_zero_nsw(
140-
; CHECK-NEXT: [[A:%.*]] = mul nuw nsw i8 [[X:%.*]], 7
141-
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[A]], 21
140+
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 3
142141
; CHECK-NEXT: ret i1 [[B]]
143142
;
144143
%a = mul nuw nsw i8 %x, 7
@@ -157,11 +156,10 @@ define i1 @ult_rem_nz(i8 %x) {
157156
}
158157

159158
; Same as above, but with nsw flag too.
160-
; FIXME: This should be optimized like above.
159+
; This used to not optimize due to nsw being prioritized too much.
161160
define i1 @ult_rem_nz_nsw(i8 %x) {
162161
; CHECK-LABEL: @ult_rem_nz_nsw(
163-
; CHECK-NEXT: [[A:%.*]] = mul nuw nsw i8 [[X:%.*]], 5
164-
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[A]], 21
162+
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 5
165163
; CHECK-NEXT: ret i1 [[B]]
166164
;
167165
%a = mul nuw nsw i8 %x, 5
@@ -212,11 +210,10 @@ define i1 @ugt_rem_zero(i8 %x) {
212210
}
213211

214212
; Same as above, but with nsw flag too.
215-
; FIXME: This should be optimized like above.
213+
; This used to not optimize due to nsw being prioritized too much.
216214
define i1 @ugt_rem_zero_nsw(i8 %x) {
217215
; CHECK-LABEL: @ugt_rem_zero_nsw(
218-
; CHECK-NEXT: [[A:%.*]] = mul nuw nsw i8 [[X:%.*]], 7
219-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], 21
216+
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3
220217
; CHECK-NEXT: ret i1 [[B]]
221218
;
222219
%a = mul nuw nsw i8 %x, 7
@@ -235,11 +232,10 @@ define i1 @ugt_rem_nz(i8 %x) {
235232
}
236233

237234
; Same as above, but with nsw flag too.
238-
; FIXME: This should be optimized like above.
235+
; This used to not optimize due to nsw being prioritized too much.
239236
define i1 @ugt_rem_nz_nsw(i8 %x) {
240237
; CHECK-LABEL: @ugt_rem_nz_nsw(
241-
; CHECK-NEXT: [[A:%.*]] = mul nuw nsw i8 [[X:%.*]], 5
242-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], 21
238+
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4
243239
; CHECK-NEXT: ret i1 [[B]]
244240
;
245241
%a = mul nuw nsw i8 %x, 5
@@ -998,9 +994,7 @@ define i1 @splat_mul_known_lz(i32 %x) {
998994

999995
define i1 @splat_mul_unknown_lz(i32 %x) {
1000996
; CHECK-LABEL: @splat_mul_unknown_lz(
1001-
; CHECK-NEXT: [[Z:%.*]] = zext i32 [[X:%.*]] to i128
1002-
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i128 [[Z]], 18446744078004518913
1003-
; CHECK-NEXT: [[R:%.*]] = icmp ult i128 [[M]], 39614081257132168796771975168
997+
; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[X:%.*]], -1
1004998
; CHECK-NEXT: ret i1 [[R]]
1005999
;
10061000
%z = zext i32 %x to i128

0 commit comments

Comments
 (0)