Skip to content

Commit 2916622

Browse files
alexander-shaposhnikovmemfrob
authored and
memfrob
committed
[InstCombine] Improve folding of mul + icmp
This diff adds folds for patterns like X * A < B where A, B are constants and "mul" has either "nsw" or "nuw". (to address llvm/llvm-project#56563). Test plan: 1/ ninja check-llvm check-clang 2/ Bootstrapped LLVM/Clang pass tests Differential revision: https://reviews.llvm.org/D130039
1 parent cd5573b commit 2916622

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,9 +2002,12 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
20022002
Constant::getNullValue(Mul->getType()));
20032003
}
20042004

2005+
if (MulC->isZero() || !(Mul->hasNoSignedWrap() || Mul->hasNoUnsignedWrap()))
2006+
return nullptr;
2007+
20052008
// If the multiply does not wrap, try to divide the compare constant by the
20062009
// multiplication factor.
2007-
if (Cmp.isEquality() && !MulC->isZero()) {
2010+
if (Cmp.isEquality()) {
20082011
// (mul nsw X, MulC) == C --> X == C /s MulC
20092012
if (Mul->hasNoSignedWrap() && C.srem(*MulC).isZero()) {
20102013
Constant *NewC = ConstantInt::get(Mul->getType(), C.sdiv(*MulC));
@@ -2017,7 +2020,40 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp,
20172020
}
20182021
}
20192022

2020-
return nullptr;
2023+
Constant *NewC = nullptr;
2024+
2025+
// FIXME: Add assert that Pred is not equal to ICMP_SGE, ICMP_SLE,
2026+
// ICMP_UGE, ICMP_ULE.
2027+
2028+
if (Mul->hasNoSignedWrap()) {
2029+
if (MulC->isNegative()) {
2030+
// MININT / -1 --> overflow.
2031+
if (C.isMinSignedValue() && MulC->isAllOnes())
2032+
return nullptr;
2033+
Pred = ICmpInst::getSwappedPredicate(Pred);
2034+
}
2035+
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE)
2036+
NewC = ConstantInt::get(
2037+
Mul->getType(),
2038+
APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::UP));
2039+
if (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_SGT)
2040+
NewC = ConstantInt::get(
2041+
Mul->getType(),
2042+
APIntOps::RoundingSDiv(C, *MulC, APInt::Rounding::DOWN));
2043+
}
2044+
2045+
if (Mul->hasNoUnsignedWrap()) {
2046+
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)
2047+
NewC = ConstantInt::get(
2048+
Mul->getType(),
2049+
APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::UP));
2050+
if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT)
2051+
NewC = ConstantInt::get(
2052+
Mul->getType(),
2053+
APIntOps::RoundingUDiv(C, *MulC, APInt::Rounding::DOWN));
2054+
}
2055+
2056+
return NewC ? new ICmpInst(Pred, Mul->getOperand(0), NewC) : nullptr;
20212057
}
20222058

20232059
/// Fold icmp (shl 1, Y), C.

llvm/test/Analysis/ValueTracking/known-power-of-two-urem.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ define i64 @known_power_of_two_urem_loop_mul_negative(i64 %size, i64 %a) {
159159
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[SIZE:%.*]], [[PHI]]
160160
; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]]
161161
; CHECK-NEXT: [[I]] = mul nuw i64 [[PHI]], 3
162-
; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[I]], 100000000
162+
; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], 33333334
163163
; CHECK-NEXT: br i1 [[ICMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
164164
; CHECK: for.end:
165165
; CHECK-NEXT: ret i64 [[SUM]]

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

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ declare void @use(i8)
77

88
define i1 @slt_positive_multip_rem_zero(i8 %x) {
99
; CHECK-LABEL: @slt_positive_multip_rem_zero(
10-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 7
11-
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[A]], 21
10+
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], 3
1211
; CHECK-NEXT: ret i1 [[B]]
1312
;
1413
%a = mul nsw i8 %x, 7
@@ -18,8 +17,7 @@ define i1 @slt_positive_multip_rem_zero(i8 %x) {
1817

1918
define i1 @slt_negative_multip_rem_zero(i8 %x) {
2019
; CHECK-LABEL: @slt_negative_multip_rem_zero(
21-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], -7
22-
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[A]], 21
20+
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], -3
2321
; CHECK-NEXT: ret i1 [[B]]
2422
;
2523
%a = mul nsw i8 %x, -7
@@ -29,8 +27,7 @@ define i1 @slt_negative_multip_rem_zero(i8 %x) {
2927

3028
define i1 @slt_positive_multip_rem_nz(i8 %x) {
3129
; CHECK-LABEL: @slt_positive_multip_rem_nz(
32-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 5
33-
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[A]], 21
30+
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], 5
3431
; CHECK-NEXT: ret i1 [[B]]
3532
;
3633
%a = mul nsw i8 %x, 5
@@ -40,8 +37,7 @@ define i1 @slt_positive_multip_rem_nz(i8 %x) {
4037

4138
define i1 @ult_rem_zero(i8 %x) {
4239
; CHECK-LABEL: @ult_rem_zero(
43-
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 7
44-
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[A]], 21
40+
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 3
4541
; CHECK-NEXT: ret i1 [[B]]
4642
;
4743
%a = mul nuw i8 %x, 7
@@ -51,8 +47,7 @@ define i1 @ult_rem_zero(i8 %x) {
5147

5248
define i1 @ult_rem_nz(i8 %x) {
5349
; CHECK-LABEL: @ult_rem_nz(
54-
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 5
55-
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[A]], 21
50+
; CHECK-NEXT: [[B:%.*]] = icmp ult i8 [[X:%.*]], 5
5651
; CHECK-NEXT: ret i1 [[B]]
5752
;
5853
%a = mul nuw i8 %x, 5
@@ -64,8 +59,7 @@ define i1 @ult_rem_nz(i8 %x) {
6459

6560
define i1 @sgt_positive_multip_rem_zero(i8 %x) {
6661
; CHECK-LABEL: @sgt_positive_multip_rem_zero(
67-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 7
68-
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[A]], 21
62+
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], 3
6963
; CHECK-NEXT: ret i1 [[B]]
7064
;
7165
%a = mul nsw i8 %x, 7
@@ -75,8 +69,7 @@ define i1 @sgt_positive_multip_rem_zero(i8 %x) {
7569

7670
define i1 @sgt_negative_multip_rem_zero(i8 %x) {
7771
; CHECK-LABEL: @sgt_negative_multip_rem_zero(
78-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], -7
79-
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[A]], 21
72+
; CHECK-NEXT: [[B:%.*]] = icmp slt i8 [[X:%.*]], -3
8073
; CHECK-NEXT: ret i1 [[B]]
8174
;
8275
%a = mul nsw i8 %x, -7
@@ -86,8 +79,7 @@ define i1 @sgt_negative_multip_rem_zero(i8 %x) {
8679

8780
define i1 @sgt_positive_multip_rem_nz(i8 %x) {
8881
; CHECK-LABEL: @sgt_positive_multip_rem_nz(
89-
; CHECK-NEXT: [[A:%.*]] = mul nsw i8 [[X:%.*]], 5
90-
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[A]], 21
82+
; CHECK-NEXT: [[B:%.*]] = icmp sgt i8 [[X:%.*]], 4
9183
; CHECK-NEXT: ret i1 [[B]]
9284
;
9385
%a = mul nsw i8 %x, 5
@@ -97,8 +89,7 @@ define i1 @sgt_positive_multip_rem_nz(i8 %x) {
9789

9890
define i1 @ugt_rem_zero(i8 %x) {
9991
; CHECK-LABEL: @ugt_rem_zero(
100-
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 7
101-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], 21
92+
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3
10293
; CHECK-NEXT: ret i1 [[B]]
10394
;
10495
%a = mul nuw i8 %x, 7
@@ -108,8 +99,7 @@ define i1 @ugt_rem_zero(i8 %x) {
10899

109100
define i1 @ugt_rem_nz(i8 %x) {
110101
; CHECK-LABEL: @ugt_rem_nz(
111-
; CHECK-NEXT: [[A:%.*]] = mul nuw i8 [[X:%.*]], 5
112-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[A]], 21
102+
; CHECK-NEXT: [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4
113103
; CHECK-NEXT: ret i1 [[B]]
114104
;
115105
%a = mul nuw i8 %x, 5
@@ -866,13 +856,11 @@ define i1 @splat_mul_known_lz(i32 %x) {
866856
ret i1 %r
867857
}
868858

869-
; Negative test - the 33rd bit could be set.
859+
; The 33rd bit can only be set when MSB of x is set.
870860

871861
define i1 @splat_mul_unknown_lz(i32 %x) {
872862
; CHECK-LABEL: @splat_mul_unknown_lz(
873-
; CHECK-NEXT: [[Z:%.*]] = zext i32 [[X:%.*]] to i128
874-
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i128 [[Z]], 18446744078004518913
875-
; CHECK-NEXT: [[R:%.*]] = icmp ult i128 [[M]], 39614081257132168796771975168
863+
; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[X:%.*]], -1
876864
; CHECK-NEXT: ret i1 [[R]]
877865
;
878866
%z = zext i32 %x to i128

0 commit comments

Comments
 (0)