Skip to content

Commit c4d173b

Browse files
committed
[InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x == 0 ? 1 : nuw_mul(x, C0))
1 parent 65216b6 commit c4d173b

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,33 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
18471847
return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
18481848
}
18491849
}
1850+
// If C is not 0:
1851+
// umax(nuw_shl(x, C), x + 1) -> x == 0 ? 1 : nuw_shl(x, C)
1852+
// If C is not 0 or 1:
1853+
// umax(nuw_mul(x, C), x + 1) -> x == 0 ? 1 : nuw_mul(x, C)
1854+
auto foldMaxMulShift = [&](Value *A, Value *B) -> Instruction * {
1855+
const APInt *C;
1856+
Value *X;
1857+
if (!match(A, m_NUWShl(m_Value(X), m_APInt(C))) &&
1858+
!(match(A, m_NUWMul(m_Value(X), m_APInt(C))) && !C->isOne()))
1859+
return nullptr;
1860+
if (C->isZero())
1861+
return nullptr;
1862+
if (!match(B, m_OneUse(m_Add(m_Specific(X), m_One()))))
1863+
return nullptr;
1864+
1865+
Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
1866+
Value *NewSelect =
1867+
Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), A);
1868+
return replaceInstUsesWith(*II, NewSelect);
1869+
};
1870+
1871+
if (IID == Intrinsic::umax) {
1872+
if (Instruction *I = foldMaxMulShift(I0, I1))
1873+
return I;
1874+
if (Instruction *I = foldMaxMulShift(I1, I0))
1875+
return I;
1876+
}
18501877
// If both operands of unsigned min/max are sign-extended, it is still ok
18511878
// to narrow the operation.
18521879
[[fallthrough]];

llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
define i64 @test_shl_by_2(i64 %x) {
1515
; CHECK-LABEL: define i64 @test_shl_by_2(
1616
; CHECK-SAME: i64 [[X:%.*]]) {
17-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
1817
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 2
19-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
18+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
19+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
2020
; CHECK-NEXT: ret i64 [[MAX]]
2121
;
2222
%x1 = add i64 %x, 1
@@ -28,9 +28,9 @@ define i64 @test_shl_by_2(i64 %x) {
2828
define i64 @test_shl_by_5(i64 %x) {
2929
; CHECK-LABEL: define i64 @test_shl_by_5(
3030
; CHECK-SAME: i64 [[X:%.*]]) {
31-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
3231
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 5
33-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
32+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
33+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
3434
; CHECK-NEXT: ret i64 [[MAX]]
3535
;
3636
%x1 = add i64 %x, 1
@@ -42,9 +42,9 @@ define i64 @test_shl_by_5(i64 %x) {
4242
define i64 @test_shl_with_nsw(i64 %x) {
4343
; CHECK-LABEL: define i64 @test_shl_with_nsw(
4444
; CHECK-SAME: i64 [[X:%.*]]) {
45-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
4645
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i64 [[X]], 2
47-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
46+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
47+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
4848
; CHECK-NEXT: ret i64 [[MAX]]
4949
;
5050
%x1 = add i64 %x, 1
@@ -56,9 +56,9 @@ define i64 @test_shl_with_nsw(i64 %x) {
5656
define <2 x i64> @test_shl_vector_by_2(<2 x i64> %x) {
5757
; CHECK-LABEL: define <2 x i64> @test_shl_vector_by_2(
5858
; CHECK-SAME: <2 x i64> [[X:%.*]]) {
59-
; CHECK-NEXT: [[X1:%.*]] = add <2 x i64> [[X]], splat (i64 1)
6059
; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i64> [[X]], splat (i64 2)
61-
; CHECK-NEXT: [[MAX:%.*]] = call <2 x i64> @llvm.umax.v2i64(<2 x i64> [[SHL]], <2 x i64> [[X1]])
60+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> [[X]], zeroinitializer
61+
; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[TMP1]], <2 x i64> splat (i64 1), <2 x i64> [[SHL]]
6262
; CHECK-NEXT: ret <2 x i64> [[MAX]]
6363
;
6464
%x1 = add <2 x i64> %x, <i64 1, i64 1>
@@ -72,9 +72,9 @@ define <2 x i64> @test_shl_vector_by_2(<2 x i64> %x) {
7272
define i64 @test_shl_umax_commuted(i64 %x) {
7373
; CHECK-LABEL: define i64 @test_shl_umax_commuted(
7474
; CHECK-SAME: i64 [[X:%.*]]) {
75-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
7675
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2
77-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[SHL]])
76+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
77+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
7878
; CHECK-NEXT: ret i64 [[MAX]]
7979
;
8080
%x1 = add i64 %x, 1
@@ -162,10 +162,10 @@ define i64 @test_shl_multi_use_add(i64 %x) {
162162
define i64 @test_shl_multi_use_shl(i64 %x) {
163163
; CHECK-LABEL: define i64 @test_shl_multi_use_shl(
164164
; CHECK-SAME: i64 [[X:%.*]]) {
165-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
166165
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2
167166
; CHECK-NEXT: call void @use(i64 [[SHL]])
168-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
167+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
168+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
169169
; CHECK-NEXT: ret i64 [[MAX]]
170170
;
171171
%x1 = add i64 %x, 1
@@ -180,9 +180,9 @@ define i64 @test_shl_multi_use_shl(i64 %x) {
180180
define i64 @test_mul_by_3(i64 %x) {
181181
; CHECK-LABEL: define i64 @test_mul_by_3(
182182
; CHECK-SAME: i64 [[X:%.*]]) {
183-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
184183
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
185-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
184+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
185+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
186186
; CHECK-NEXT: ret i64 [[MAX]]
187187
;
188188
%x1 = add i64 %x, 1
@@ -194,9 +194,9 @@ define i64 @test_mul_by_3(i64 %x) {
194194
define i64 @test_mul_by_5(i64 %x) {
195195
; CHECK-LABEL: define i64 @test_mul_by_5(
196196
; CHECK-SAME: i64 [[X:%.*]]) {
197-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
198197
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 5
199-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
198+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
199+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
200200
; CHECK-NEXT: ret i64 [[MAX]]
201201
;
202202
%x1 = add i64 %x, 1
@@ -208,9 +208,9 @@ define i64 @test_mul_by_5(i64 %x) {
208208
define i64 @test_mul_with_nsw(i64 %x) {
209209
; CHECK-LABEL: define i64 @test_mul_with_nsw(
210210
; CHECK-SAME: i64 [[X:%.*]]) {
211-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
212211
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[X]], 3
213-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
212+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
213+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
214214
; CHECK-NEXT: ret i64 [[MAX]]
215215
;
216216
%x1 = add i64 %x, 1
@@ -222,9 +222,9 @@ define i64 @test_mul_with_nsw(i64 %x) {
222222
define <2 x i64> @test_mul_vector_by_3(<2 x i64> %x) {
223223
; CHECK-LABEL: define <2 x i64> @test_mul_vector_by_3(
224224
; CHECK-SAME: <2 x i64> [[X:%.*]]) {
225-
; CHECK-NEXT: [[X1:%.*]] = add <2 x i64> [[X]], splat (i64 1)
226225
; CHECK-NEXT: [[MUL:%.*]] = mul nuw <2 x i64> [[X]], splat (i64 3)
227-
; CHECK-NEXT: [[MAX:%.*]] = call <2 x i64> @llvm.umax.v2i64(<2 x i64> [[MUL]], <2 x i64> [[X1]])
226+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i64> [[X]], zeroinitializer
227+
; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[TMP1]], <2 x i64> splat (i64 1), <2 x i64> [[MUL]]
228228
; CHECK-NEXT: ret <2 x i64> [[MAX]]
229229
;
230230
%x1 = add <2 x i64> %x, <i64 1, i64 1>
@@ -238,9 +238,9 @@ define <2 x i64> @test_mul_vector_by_3(<2 x i64> %x) {
238238
define i64 @test_mul_max_commuted(i64 %x) {
239239
; CHECK-LABEL: define i64 @test_mul_max_commuted(
240240
; CHECK-SAME: i64 [[X:%.*]]) {
241-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
242241
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
243-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[MUL]])
242+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
243+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
244244
; CHECK-NEXT: ret i64 [[MAX]]
245245
;
246246
%x1 = add i64 %x, 1
@@ -339,10 +339,10 @@ define i64 @test_mul_multi_use_add(i64 %x) {
339339
define i64 @test_mul_multi_use_mul(i64 %x) {
340340
; CHECK-LABEL: define i64 @test_mul_multi_use_mul(
341341
; CHECK-SAME: i64 [[X:%.*]]) {
342-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
343342
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
344343
; CHECK-NEXT: call void @use(i64 [[MUL]])
345-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
344+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
345+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
346346
; CHECK-NEXT: ret i64 [[MAX]]
347347
;
348348
%x1 = add i64 %x, 1

0 commit comments

Comments
 (0)