Skip to content

Commit 1da116b

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

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,29 @@ 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+
const APInt *C0;
1855+
auto matchShiftOrMul = [&](Value *I) {
1856+
return ((match(I, m_OneUse(m_NUWShl(m_Value(X), m_APInt(C0))))) ||
1857+
(match(I, m_OneUse(m_NUWMul(m_Value(X), m_APInt(C0)))) &&
1858+
!C0->isOne())) &&
1859+
!C0->isZero();
1860+
};
1861+
bool matchI0 = false;
1862+
if (IID == Intrinsic::umax &&
1863+
(((matchI0 = matchShiftOrMul(I0)) &&
1864+
match(I1, m_OneUse(m_Add(m_Specific(X), m_One())))) ||
1865+
(matchShiftOrMul(I1) &&
1866+
match(I0, m_OneUse(m_Add(m_Specific(X), m_One())))))) {
1867+
Value *Op = matchI0 ? I0 : I1;
1868+
Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
1869+
Value *NewSelect =
1870+
Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), Op);
1871+
return replaceInstUsesWith(*II, NewSelect);
1872+
}
18501873
// If both operands of unsigned min/max are sign-extended, it is still ok
18511874
// to narrow the operation.
18521875
[[fallthrough]];

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

Lines changed: 20 additions & 20 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
@@ -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
@@ -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)