xref: /llvm-project/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll (revision 9c7e02d579db7ba81a414cd2212ce2b48b927941)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2
3; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4
5; When C0 is neither 0 nor 1:
6;   umax(nuw_mul(x, C0), x + 1) is optimized to:
7;   x == 0 ? 1 : nuw_mul(x, C0)
8; When C0 is not 0:
9;   umax(nuw_shl(x, C0), x + 1) is optimized to:
10;   x == 0 ? 1 : nuw_shl(x, C0)
11
12; Positive Test Cases for `shl`
13
14define i64 @test_shl_by_2(i64 %x) {
15; CHECK-LABEL: define i64 @test_shl_by_2(
16; CHECK-SAME: i64 [[X:%.*]]) {
17; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 2
18; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
19; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
20; CHECK-NEXT:    ret i64 [[MAX]]
21;
22  %x1 = add i64 %x, 1
23  %shl = shl nuw i64 %x, 2
24  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
25  ret i64 %max
26}
27
28define i64 @test_shl_by_5(i64 %x) {
29; CHECK-LABEL: define i64 @test_shl_by_5(
30; CHECK-SAME: i64 [[X:%.*]]) {
31; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 5
32; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
33; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[TMP2]]
34; CHECK-NEXT:    ret i64 [[MAX]]
35;
36  %x1 = add i64 %x, 1
37  %shl = shl nuw i64 %x, 5
38  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
39  ret i64 %max
40}
41
42define i64 @test_shl_with_nsw(i64 %x) {
43; CHECK-LABEL: define i64 @test_shl_with_nsw(
44; CHECK-SAME: i64 [[X:%.*]]) {
45; CHECK-NEXT:    [[SHL:%.*]] = shl nuw nsw i64 [[X]], 2
46; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
47; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
48; CHECK-NEXT:    ret i64 [[MAX]]
49;
50  %x1 = add i64 %x, 1
51  %shl = shl nuw nsw i64 %x, 2
52  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
53  ret i64 %max
54}
55
56define <2 x i64> @test_shl_vector_by_2(<2 x i64> %x) {
57; CHECK-LABEL: define <2 x i64> @test_shl_vector_by_2(
58; CHECK-SAME: <2 x i64> [[X:%.*]]) {
59; CHECK-NEXT:    [[SHL:%.*]] = shl nuw <2 x i64> [[X]], splat (i64 2)
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]]
62; CHECK-NEXT:    ret <2 x i64> [[MAX]]
63;
64  %x1 = add <2 x i64> %x, <i64 1, i64 1>
65  %shl = shl nuw <2 x i64> %x, <i64 2, i64 2>
66  %max = call <2 x i64> @llvm.umax.v2i64(<2 x i64> %shl, <2 x i64> %x1)
67  ret <2 x i64> %max
68}
69
70; Commuted Test Cases for `shl`
71
72define i64 @test_shl_umax_commuted(i64 %x) {
73; CHECK-LABEL: define i64 @test_shl_umax_commuted(
74; CHECK-SAME: i64 [[X:%.*]]) {
75; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
76; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
77; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
78; CHECK-NEXT:    ret i64 [[MAX]]
79;
80  %x1 = add i64 %x, 1
81  %shl = shl nuw i64 %x, 2
82  %max = call i64 @llvm.umax.i64(i64 %x1, i64 %shl)
83  ret i64 %max
84}
85
86; Negative Test Cases for `shl`
87
88define i64 @test_shl_by_zero(i64 %x) {
89; CHECK-LABEL: define i64 @test_shl_by_zero(
90; CHECK-SAME: i64 [[X:%.*]]) {
91; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
92; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]])
93; CHECK-NEXT:    ret i64 [[MAX]]
94;
95  %x1 = add i64 %x, 1
96  %shl = shl nuw i64 %x, 0
97  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
98  ret i64 %max
99}
100
101define i64 @test_shl_add_by_2(i64 %x) {
102; CHECK-LABEL: define i64 @test_shl_add_by_2(
103; CHECK-SAME: i64 [[X:%.*]]) {
104; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 2
105; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
106; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
107; CHECK-NEXT:    ret i64 [[MAX]]
108;
109  %x1 = add i64 %x, 2
110  %shl = shl nuw i64 %x, 2
111  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
112  ret i64 %max
113}
114
115define i64 @test_shl_without_nuw(i64 %x) {
116; CHECK-LABEL: define i64 @test_shl_without_nuw(
117; CHECK-SAME: i64 [[X:%.*]]) {
118; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
119; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X]], 2
120; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
121; CHECK-NEXT:    ret i64 [[MAX]]
122;
123  %x1 = add i64 %x, 1
124  %shl = shl i64 %x, 2
125  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
126  ret i64 %max
127}
128
129define i64 @test_shl_umin(i64 %x) {
130; CHECK-LABEL: define i64 @test_shl_umin(
131; CHECK-SAME: i64 [[X:%.*]]) {
132; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
133; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
134; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umin.i64(i64 [[SHL]], i64 [[X1]])
135; CHECK-NEXT:    ret i64 [[MAX]]
136;
137  %x1 = add i64 %x, 1
138  %shl = shl nuw i64 %x, 2
139  %max = call i64 @llvm.umin.i64(i64 %shl, i64 %x1)
140  ret i64 %max
141}
142
143; Multi-use Test Cases for `shl`
144declare void @use(i64)
145
146define i64 @test_shl_multi_use_add(i64 %x) {
147; CHECK-LABEL: define i64 @test_shl_multi_use_add(
148; CHECK-SAME: i64 [[X:%.*]]) {
149; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
150; CHECK-NEXT:    call void @use(i64 [[X1]])
151; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 3
152; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
153; CHECK-NEXT:    ret i64 [[MAX]]
154;
155  %x1 = add i64 %x, 1
156  call void @use(i64 %x1)
157  %shl = shl nuw i64 %x, 3
158  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
159  ret i64 %max
160}
161
162define i64 @test_shl_multi_use_shl(i64 %x) {
163; CHECK-LABEL: define i64 @test_shl_multi_use_shl(
164; CHECK-SAME: i64 [[X:%.*]]) {
165; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
166; CHECK-NEXT:    call void @use(i64 [[SHL]])
167; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
168; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[SHL]]
169; CHECK-NEXT:    ret i64 [[MAX]]
170;
171  %x1 = add i64 %x, 1
172  %shl = shl nuw i64 %x, 2
173  call void @use(i64 %shl)
174  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
175  ret i64 %max
176}
177
178; Positive Test Cases for `mul`
179
180define i64 @test_mul_by_3(i64 %x) {
181; CHECK-LABEL: define i64 @test_mul_by_3(
182; CHECK-SAME: i64 [[X:%.*]]) {
183; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 3
184; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
185; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
186; CHECK-NEXT:    ret i64 [[MAX]]
187;
188  %x1 = add i64 %x, 1
189  %mul = mul nuw i64 %x, 3
190  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
191  ret i64 %max
192}
193
194define i64 @test_mul_by_5(i64 %x) {
195; CHECK-LABEL: define i64 @test_mul_by_5(
196; CHECK-SAME: i64 [[X:%.*]]) {
197; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 5
198; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
199; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
200; CHECK-NEXT:    ret i64 [[MAX]]
201;
202  %x1 = add i64 %x, 1
203  %mul = mul nuw i64 %x, 5
204  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
205  ret i64 %max
206}
207
208define i64 @test_mul_with_nsw(i64 %x) {
209; CHECK-LABEL: define i64 @test_mul_with_nsw(
210; CHECK-SAME: i64 [[X:%.*]]) {
211; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i64 [[X]], 3
212; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
213; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
214; CHECK-NEXT:    ret i64 [[MAX]]
215;
216  %x1 = add i64 %x, 1
217  %mul = mul nuw nsw i64 %x, 3
218  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
219  ret i64 %max
220}
221
222define <2 x i64> @test_mul_vector_by_3(<2 x i64> %x) {
223; CHECK-LABEL: define <2 x i64> @test_mul_vector_by_3(
224; CHECK-SAME: <2 x i64> [[X:%.*]]) {
225; CHECK-NEXT:    [[MUL:%.*]] = mul nuw <2 x i64> [[X]], splat (i64 3)
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]]
228; CHECK-NEXT:    ret <2 x i64> [[MAX]]
229;
230  %x1 = add <2 x i64> %x, <i64 1, i64 1>
231  %mul = mul nuw <2 x i64> %x, <i64 3, i64 3>
232  %max = call <2 x i64> @llvm.umax.v2i64(<2 x i64> %mul, <2 x i64> %x1)
233  ret <2 x i64> %max
234}
235
236; Commuted Test Cases for `mul`
237
238define i64 @test_mul_max_commuted(i64 %x) {
239; CHECK-LABEL: define i64 @test_mul_max_commuted(
240; CHECK-SAME: i64 [[X:%.*]]) {
241; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 3
242; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
243; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
244; CHECK-NEXT:    ret i64 [[MAX]]
245;
246  %x1 = add i64 %x, 1
247  %mul = mul nuw i64 %x, 3
248  %max = call i64 @llvm.umax.i64(i64 %x1, i64 %mul)
249  ret i64 %max
250}
251
252; Negative Test Cases for `mul`
253
254define i64 @test_mul_by_zero(i64 %x) {
255; CHECK-LABEL: define i64 @test_mul_by_zero(
256; CHECK-SAME: i64 [[X:%.*]]) {
257; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
258; CHECK-NEXT:    ret i64 [[X1]]
259;
260  %x1 = add i64 %x, 1
261  %mul = mul nuw i64 %x, 0
262  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
263  ret i64 %max
264}
265
266define i64 @test_mul_by_1(i64 %x) {
267; CHECK-LABEL: define i64 @test_mul_by_1(
268; CHECK-SAME: i64 [[X:%.*]]) {
269; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
270; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]])
271; CHECK-NEXT:    ret i64 [[MAX]]
272;
273  %x1 = add i64 %x, 1
274  %mul = mul nuw i64 %x, 1
275  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
276  ret i64 %max
277}
278
279define i64 @test_mul_add_by_2(i64 %x) {
280; CHECK-LABEL: define i64 @test_mul_add_by_2(
281; CHECK-SAME: i64 [[X:%.*]]) {
282; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 2
283; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 3
284; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
285; CHECK-NEXT:    ret i64 [[MAX]]
286;
287  %x1 = add i64 %x, 2
288  %mul = mul nuw i64 %x, 3
289  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
290  ret i64 %max
291}
292
293define i64 @test_mul_without_nuw(i64 %x) {
294; CHECK-LABEL: define i64 @test_mul_without_nuw(
295; CHECK-SAME: i64 [[X:%.*]]) {
296; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
297; CHECK-NEXT:    [[MUL:%.*]] = mul i64 [[X]], 3
298; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
299; CHECK-NEXT:    ret i64 [[MAX]]
300;
301  %x1 = add i64 %x, 1
302  %mul = mul i64 %x, 3
303  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
304  ret i64 %max
305}
306
307define i64 @test_mul_umin(i64 %x) {
308; CHECK-LABEL: define i64 @test_mul_umin(
309; CHECK-SAME: i64 [[X:%.*]]) {
310; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
311; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 3
312; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umin.i64(i64 [[MUL]], i64 [[X1]])
313; CHECK-NEXT:    ret i64 [[MAX]]
314;
315  %x1 = add i64 %x, 1
316  %mul = mul nuw i64 %x, 3
317  %max = call i64 @llvm.umin.i64(i64 %mul, i64 %x1)
318  ret i64 %max
319}
320
321; Multi-use Test Cases for `mul`
322
323define i64 @test_mul_multi_use_add(i64 %x) {
324; CHECK-LABEL: define i64 @test_mul_multi_use_add(
325; CHECK-SAME: i64 [[X:%.*]]) {
326; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
327; CHECK-NEXT:    call void @use(i64 [[X1]])
328; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw i64 [[X]], 3
329; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
330; CHECK-NEXT:    ret i64 [[MAX]]
331;
332  %x1 = add i64 %x, 1
333  call void @use(i64 %x1)
334  %mul = mul nuw i64 %x, 3
335  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
336  ret i64 %max
337}
338
339define i64 @test_mul_multi_use_mul(i64 %x) {
340; CHECK-LABEL: define i64 @test_mul_multi_use_mul(
341; CHECK-SAME: i64 [[X:%.*]]) {
342; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 3
343; CHECK-NEXT:    call void @use(i64 [[MUL]])
344; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[X]], 0
345; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP1]], i64 1, i64 [[MUL]]
346; CHECK-NEXT:    ret i64 [[MAX]]
347;
348  %x1 = add i64 %x, 1
349  %mul = mul nuw i64 %x, 3
350  call void @use(i64 %mul)
351  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
352  ret i64 %max
353}
354