Skip to content

Commit d528f78

Browse files
committed
[InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x == 0 ? 1 : nuw_mul(x, C0))
1 parent 6c4aa1d commit d528f78

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 C0 is not 0:
1851+
// umax(nuw_shl(x, C0), x + 1) -> x == 0 ? 1 : nuw_shl(x, C0)
1852+
// If C0 is not 0 or 1:
1853+
// umax(nuw_mul(x, C0), x + 1) -> x == 0 ? 1 : nuw_mul(x, C0)
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
@@ -58,9 +58,9 @@ define i64 @test_shl_with_nsw(i64 %x) {
5858
define i64 @test_shl_umax_commuted(i64 %x) {
5959
; CHECK-LABEL: define i64 @test_shl_umax_commuted(
6060
; CHECK-SAME: i64 [[X:%.*]]) {
61-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
6261
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2
63-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[SHL]])
62+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
63+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
6464
; CHECK-NEXT: ret i64 [[MAX]]
6565
;
6666
%x1 = add i64 %x, 1
@@ -148,10 +148,10 @@ define i64 @test_shl_multi_use_add(i64 %x) {
148148
define i64 @test_shl_multi_use_shl(i64 %x) {
149149
; CHECK-LABEL: define i64 @test_shl_multi_use_shl(
150150
; CHECK-SAME: i64 [[X:%.*]]) {
151-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
152151
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2
153152
; CHECK-NEXT: call void @use(i64 [[SHL]])
154-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
153+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
154+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
155155
; CHECK-NEXT: ret i64 [[MAX]]
156156
;
157157
%x1 = add i64 %x, 1
@@ -164,9 +164,9 @@ define i64 @test_shl_multi_use_shl(i64 %x) {
164164
define i64 @test_shl_multi_use_max(i64 %x) {
165165
; CHECK-LABEL: define i64 @test_shl_multi_use_max(
166166
; CHECK-SAME: i64 [[X:%.*]]) {
167-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
168167
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 3
169-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
168+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
169+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
170170
; CHECK-NEXT: call void @use(i64 [[MAX]])
171171
; CHECK-NEXT: ret i64 [[MAX]]
172172
;
@@ -182,9 +182,9 @@ define i64 @test_shl_multi_use_max(i64 %x) {
182182
define i64 @test_mul_by_3(i64 %x) {
183183
; CHECK-LABEL: define i64 @test_mul_by_3(
184184
; CHECK-SAME: i64 [[X:%.*]]) {
185-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
186185
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
187-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
186+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
187+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
188188
; CHECK-NEXT: ret i64 [[MAX]]
189189
;
190190
%x1 = add i64 %x, 1
@@ -196,9 +196,9 @@ define i64 @test_mul_by_3(i64 %x) {
196196
define i64 @test_mul_by_5(i64 %x) {
197197
; CHECK-LABEL: define i64 @test_mul_by_5(
198198
; CHECK-SAME: i64 [[X:%.*]]) {
199-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
200199
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 5
201-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
200+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
201+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
202202
; CHECK-NEXT: ret i64 [[MAX]]
203203
;
204204
%x1 = add i64 %x, 1
@@ -210,9 +210,9 @@ define i64 @test_mul_by_5(i64 %x) {
210210
define i64 @test_mul_with_nsw(i64 %x) {
211211
; CHECK-LABEL: define i64 @test_mul_with_nsw(
212212
; CHECK-SAME: i64 [[X:%.*]]) {
213-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
214213
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i64 [[X]], 3
215-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
214+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
215+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
216216
; CHECK-NEXT: ret i64 [[MAX]]
217217
;
218218
%x1 = add i64 %x, 1
@@ -226,9 +226,9 @@ define i64 @test_mul_with_nsw(i64 %x) {
226226
define i64 @test_mul_max_commuted(i64 %x) {
227227
; CHECK-LABEL: define i64 @test_mul_max_commuted(
228228
; CHECK-SAME: i64 [[X:%.*]]) {
229-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
230229
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
231-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[MUL]])
230+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
231+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
232232
; CHECK-NEXT: ret i64 [[MAX]]
233233
;
234234
%x1 = add i64 %x, 1
@@ -327,10 +327,10 @@ define i64 @test_mul_multi_use_add(i64 %x) {
327327
define i64 @test_mul_multi_use_mul(i64 %x) {
328328
; CHECK-LABEL: define i64 @test_mul_multi_use_mul(
329329
; CHECK-SAME: i64 [[X:%.*]]) {
330-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
331330
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 3
332331
; CHECK-NEXT: call void @use(i64 [[MUL]])
333-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
332+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
333+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
334334
; CHECK-NEXT: ret i64 [[MAX]]
335335
;
336336
%x1 = add i64 %x, 1
@@ -343,9 +343,9 @@ define i64 @test_mul_multi_use_mul(i64 %x) {
343343
define i64 @test_mul_multi_use_max(i64 %x) {
344344
; CHECK-LABEL: define i64 @test_mul_multi_use_max(
345345
; CHECK-SAME: i64 [[X:%.*]]) {
346-
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
347346
; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[X]], 3
348-
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
347+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[X]], 0
348+
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
349349
; CHECK-NEXT: call void @use(i64 [[MAX]])
350350
; CHECK-NEXT: ret i64 [[MAX]]
351351
;

0 commit comments

Comments
 (0)