xref: /llvm-project/llvm/test/Transforms/InstCombine/adjust-for-minmax.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; Instcombine should recognize that this code can be adjusted to fit the canonical max/min pattern.
5
6; No change
7
8define i32 @smax1(i32 %n) {
9; CHECK-LABEL: @smax1(
10; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
11; CHECK-NEXT:    ret i32 [[M]]
12;
13  %t = icmp sgt i32 %n, 0
14  %m = select i1 %t, i32 %n, i32 0
15  ret i32 %m
16}
17
18; No change
19
20define i32 @smin1(i32 %n) {
21; CHECK-LABEL: @smin1(
22; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0)
23; CHECK-NEXT:    ret i32 [[M]]
24;
25  %t = icmp slt i32 %n, 0
26  %m = select i1 %t, i32 %n, i32 0
27  ret i32 %m
28}
29
30; Canonicalize min/max.
31
32define i32 @smax2(i32 %n) {
33; CHECK-LABEL: @smax2(
34; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
35; CHECK-NEXT:    ret i32 [[M]]
36;
37  %t = icmp sge i32 %n, 1
38  %m = select i1 %t, i32 %n, i32 0
39  ret i32 %m
40}
41
42; Canonicalize min/max.
43
44define i32 @smin2(i32 %n) {
45; CHECK-LABEL: @smin2(
46; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0)
47; CHECK-NEXT:    ret i32 [[M]]
48;
49  %t = icmp sle i32 %n, -1
50  %m = select i1 %t, i32 %n, i32 0
51  ret i32 %m
52}
53
54; Canonicalize min/max.
55
56define i32 @smax3(i32 %n) {
57; CHECK-LABEL: @smax3(
58; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
59; CHECK-NEXT:    ret i32 [[M]]
60;
61  %t = icmp sgt i32 %n, -1
62  %m = select i1 %t, i32 %n, i32 0
63  ret i32 %m
64}
65
66; Canonicalize min/max.
67
68define <2 x i32> @smax3_vec(<2 x i32> %n) {
69; CHECK-LABEL: @smax3_vec(
70; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer)
71; CHECK-NEXT:    ret <2 x i32> [[M]]
72;
73  %t = icmp sgt <2 x i32> %n, <i32 -1, i32 -1>
74  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
75  ret <2 x i32> %m
76}
77
78; Canonicalize min/max.
79
80define i32 @smin3(i32 %n) {
81; CHECK-LABEL: @smin3(
82; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0)
83; CHECK-NEXT:    ret i32 [[M]]
84;
85  %t = icmp slt i32 %n, 1
86  %m = select i1 %t, i32 %n, i32 0
87  ret i32 %m
88}
89
90; Canonicalize min/max.
91
92define <2 x i32> @smin3_vec(<2 x i32> %n) {
93; CHECK-LABEL: @smin3_vec(
94; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer)
95; CHECK-NEXT:    ret <2 x i32> [[M]]
96;
97  %t = icmp slt <2 x i32> %n, <i32 1, i32 1>
98  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
99  ret <2 x i32> %m
100}
101
102; Canonicalize min/max.
103
104define i32 @umax3(i32 %n) {
105; CHECK-LABEL: @umax3(
106; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 5)
107; CHECK-NEXT:    ret i32 [[M]]
108;
109  %t = icmp ugt i32 %n, 4
110  %m = select i1 %t, i32 %n, i32 5
111  ret i32 %m
112}
113
114; Canonicalize min/max.
115
116define <2 x i32> @umax3_vec(<2 x i32> %n) {
117; CHECK-LABEL: @umax3_vec(
118; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 5))
119; CHECK-NEXT:    ret <2 x i32> [[M]]
120;
121  %t = icmp ugt <2 x i32> %n, <i32 4, i32 4>
122  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 5, i32 5>
123  ret <2 x i32> %m
124}
125
126; Canonicalize min/max.
127
128define i32 @umin3(i32 %n) {
129; CHECK-LABEL: @umin3(
130; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[N:%.*]], i32 6)
131; CHECK-NEXT:    ret i32 [[M]]
132;
133  %t = icmp ult i32 %n, 7
134  %m = select i1 %t, i32 %n, i32 6
135  ret i32 %m
136}
137
138; Canonicalize min/max.
139
140define <2 x i32> @umin3_vec(<2 x i32> %n) {
141; CHECK-LABEL: @umin3_vec(
142; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 6))
143; CHECK-NEXT:    ret <2 x i32> [[M]]
144;
145  %t = icmp ult <2 x i32> %n, <i32 7, i32 7>
146  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 6, i32 6>
147  ret <2 x i32> %m
148}
149
150; Canonicalize min/max.
151
152define i32 @smax4(i32 %n) {
153; CHECK-LABEL: @smax4(
154; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
155; CHECK-NEXT:    ret i32 [[M]]
156;
157  %t = icmp sge i32 %n, 0
158  %m = select i1 %t, i32 %n, i32 0
159  ret i32 %m
160}
161
162; Canonicalize min/max.
163
164define <2 x i32> @smax4_vec(<2 x i32> %n) {
165; CHECK-LABEL: @smax4_vec(
166; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer)
167; CHECK-NEXT:    ret <2 x i32> [[M]]
168;
169  %t = icmp sge <2 x i32> %n, zeroinitializer
170  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
171  ret <2 x i32> %m
172}
173
174; Canonicalize min/max.
175
176define i32 @smin4(i32 %n) {
177; CHECK-LABEL: @smin4(
178; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smin.i32(i32 [[N:%.*]], i32 0)
179; CHECK-NEXT:    ret i32 [[M]]
180;
181  %t = icmp sle i32 %n, 0
182  %m = select i1 %t, i32 %n, i32 0
183  ret i32 %m
184}
185
186; Canonicalize min/max.
187
188define <2 x i32> @smin4_vec(<2 x i32> %n) {
189; CHECK-LABEL: @smin4_vec(
190; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> zeroinitializer)
191; CHECK-NEXT:    ret <2 x i32> [[M]]
192;
193  %t = icmp sle <2 x i32> %n, zeroinitializer
194  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
195  ret <2 x i32> %m
196}
197
198; Canonicalize min/max.
199
200define i32 @umax4(i32 %n) {
201; CHECK-LABEL: @umax4(
202; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 8)
203; CHECK-NEXT:    ret i32 [[M]]
204;
205  %t = icmp uge i32 %n, 8
206  %m = select i1 %t, i32 %n, i32 8
207  ret i32 %m
208}
209
210; Canonicalize min/max.
211
212define <2 x i32> @umax4_vec(<2 x i32> %n) {
213; CHECK-LABEL: @umax4_vec(
214; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 8))
215; CHECK-NEXT:    ret <2 x i32> [[M]]
216;
217  %t = icmp uge <2 x i32> %n, <i32 8, i32 8>
218  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 8, i32 8>
219  ret <2 x i32> %m
220}
221
222; Canonicalize min/max.
223
224define i32 @umin4(i32 %n) {
225; CHECK-LABEL: @umin4(
226; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.umin.i32(i32 [[N:%.*]], i32 9)
227; CHECK-NEXT:    ret i32 [[M]]
228;
229  %t = icmp ule i32 %n, 9
230  %m = select i1 %t, i32 %n, i32 9
231  ret i32 %m
232}
233
234; Canonicalize min/max.
235
236define <2 x i32> @umin4_vec(<2 x i32> %n) {
237; CHECK-LABEL: @umin4_vec(
238; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[N:%.*]], <2 x i32> splat (i32 9))
239; CHECK-NEXT:    ret <2 x i32> [[M]]
240;
241  %t = icmp ule <2 x i32> %n, <i32 9, i32 9>
242  %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> <i32 9, i32 9>
243  ret <2 x i32> %m
244}
245
246define i64 @smax_sext(i32 %a) {
247; CHECK-LABEL: @smax_sext(
248; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 0)
249; CHECK-NEXT:    [[MAX:%.*]] = zext nneg i32 [[NARROW]] to i64
250; CHECK-NEXT:    ret i64 [[MAX]]
251;
252  %a_ext = sext i32 %a to i64
253  %cmp = icmp sgt i32 %a, -1
254  %max = select i1 %cmp, i64 %a_ext, i64 0
255  ret i64 %max
256}
257
258define <2 x i64> @smax_sext_vec(<2 x i32> %a) {
259; CHECK-LABEL: @smax_sext_vec(
260; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> zeroinitializer)
261; CHECK-NEXT:    [[MAX:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64>
262; CHECK-NEXT:    ret <2 x i64> [[MAX]]
263;
264  %a_ext = sext <2 x i32> %a to <2 x i64>
265  %cmp = icmp sgt <2 x i32> %a, <i32 -1, i32 -1>
266  %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> zeroinitializer
267  ret <2 x i64> %max
268}
269
270define i64 @smin_sext(i32 %a) {
271; CHECK-LABEL: @smin_sext(
272; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.smin.i32(i32 [[A:%.*]], i32 0)
273; CHECK-NEXT:    [[MIN:%.*]] = sext i32 [[NARROW]] to i64
274; CHECK-NEXT:    ret i64 [[MIN]]
275;
276  %a_ext = sext i32 %a to i64
277  %cmp = icmp slt i32 %a, 1
278  %min = select i1 %cmp, i64 %a_ext, i64 0
279  ret i64 %min
280}
281
282define <2 x i64>@smin_sext_vec(<2 x i32> %a) {
283; CHECK-LABEL: @smin_sext_vec(
284; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> zeroinitializer)
285; CHECK-NEXT:    [[MIN:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
286; CHECK-NEXT:    ret <2 x i64> [[MIN]]
287;
288  %a_ext = sext <2 x i32> %a to <2 x i64>
289  %cmp = icmp slt <2 x i32> %a, <i32 1, i32 1>
290  %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> zeroinitializer
291  ret <2 x i64> %min
292}
293
294define i64 @umax_sext(i32 %a) {
295; CHECK-LABEL: @umax_sext(
296; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 3)
297; CHECK-NEXT:    [[MAX:%.*]] = sext i32 [[NARROW]] to i64
298; CHECK-NEXT:    ret i64 [[MAX]]
299;
300  %a_ext = sext i32 %a to i64
301  %cmp = icmp ugt i32 %a, 2
302  %max = select i1 %cmp, i64 %a_ext, i64 3
303  ret i64 %max
304}
305
306define <2 x i64> @umax_sext_vec(<2 x i32> %a) {
307; CHECK-LABEL: @umax_sext_vec(
308; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3))
309; CHECK-NEXT:    [[MAX:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
310; CHECK-NEXT:    ret <2 x i64> [[MAX]]
311;
312  %a_ext = sext <2 x i32> %a to <2 x i64>
313  %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2>
314  %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 3, i64 3>
315  ret <2 x i64> %max
316}
317
318define i64 @umin_sext(i32 %a) {
319; CHECK-LABEL: @umin_sext(
320; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2)
321; CHECK-NEXT:    [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64
322; CHECK-NEXT:    ret i64 [[MIN]]
323;
324  %a_ext = sext i32 %a to i64
325  %cmp = icmp ult i32 %a, 3
326  %min = select i1 %cmp, i64 %a_ext, i64 2
327  ret i64 %min
328}
329
330define <2 x i64> @umin_sext_vec(<2 x i32> %a) {
331; CHECK-LABEL: @umin_sext_vec(
332; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2))
333; CHECK-NEXT:    [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64>
334; CHECK-NEXT:    ret <2 x i64> [[MIN]]
335;
336  %a_ext = sext <2 x i32> %a to <2 x i64>
337  %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3>
338  %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 2, i64 2>
339  ret <2 x i64> %min
340}
341
342define i64 @umax_sext2(i32 %a) {
343; CHECK-LABEL: @umax_sext2(
344; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 2)
345; CHECK-NEXT:    [[MIN:%.*]] = sext i32 [[NARROW]] to i64
346; CHECK-NEXT:    ret i64 [[MIN]]
347;
348  %a_ext = sext i32 %a to i64
349  %cmp = icmp ult i32 %a, 3
350  %min = select i1 %cmp, i64 2, i64 %a_ext
351  ret i64 %min
352}
353
354define <2 x i64> @umax_sext2_vec(<2 x i32> %a) {
355; CHECK-LABEL: @umax_sext2_vec(
356; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2))
357; CHECK-NEXT:    [[MIN:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>
358; CHECK-NEXT:    ret <2 x i64> [[MIN]]
359;
360  %a_ext = sext <2 x i32> %a to <2 x i64>
361  %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3>
362  %min = select <2 x i1> %cmp, <2 x i64> <i64 2, i64 2>, <2 x i64> %a_ext
363  ret <2 x i64> %min
364}
365
366define i64 @umin_sext2(i32 %a) {
367; CHECK-LABEL: @umin_sext2(
368; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 3)
369; CHECK-NEXT:    [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64
370; CHECK-NEXT:    ret i64 [[MIN]]
371;
372  %a_ext = sext i32 %a to i64
373  %cmp = icmp ugt i32 %a, 2
374  %min = select i1 %cmp, i64 3, i64 %a_ext
375  ret i64 %min
376}
377
378define <2 x i64> @umin_sext2_vec(<2 x i32> %a) {
379; CHECK-LABEL: @umin_sext2_vec(
380; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3))
381; CHECK-NEXT:    [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64>
382; CHECK-NEXT:    ret <2 x i64> [[MIN]]
383;
384  %a_ext = sext <2 x i32> %a to <2 x i64>
385  %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2>
386  %min = select <2 x i1> %cmp, <2 x i64> <i64 3, i64 3>, <2 x i64> %a_ext
387  ret <2 x i64> %min
388}
389
390define i64 @umax_zext(i32 %a) {
391; CHECK-LABEL: @umax_zext(
392; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 3)
393; CHECK-NEXT:    [[MAX:%.*]] = zext i32 [[NARROW]] to i64
394; CHECK-NEXT:    ret i64 [[MAX]]
395;
396  %a_ext = zext i32 %a to i64
397  %cmp = icmp ugt i32 %a, 2
398  %max = select i1 %cmp, i64 %a_ext, i64 3
399  ret i64 %max
400}
401
402define <2 x i64> @umax_zext_vec(<2 x i32> %a) {
403; CHECK-LABEL: @umax_zext_vec(
404; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 3))
405; CHECK-NEXT:    [[MAX:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>
406; CHECK-NEXT:    ret <2 x i64> [[MAX]]
407;
408  %a_ext = zext <2 x i32> %a to <2 x i64>
409  %cmp = icmp ugt <2 x i32> %a, <i32 2, i32 2>
410  %max = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 3, i64 3>
411  ret <2 x i64> %max
412}
413
414define i64 @umin_zext(i32 %a) {
415; CHECK-LABEL: @umin_zext(
416; CHECK-NEXT:    [[NARROW:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2)
417; CHECK-NEXT:    [[MIN:%.*]] = zext nneg i32 [[NARROW]] to i64
418; CHECK-NEXT:    ret i64 [[MIN]]
419;
420  %a_ext = zext i32 %a to i64
421  %cmp = icmp ult i32 %a, 3
422  %min = select i1 %cmp, i64 %a_ext, i64 2
423  ret i64 %min
424}
425
426define <2 x i64> @umin_zext_vec(<2 x i32> %a) {
427; CHECK-LABEL: @umin_zext_vec(
428; CHECK-NEXT:    [[NARROW:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[A:%.*]], <2 x i32> splat (i32 2))
429; CHECK-NEXT:    [[MIN:%.*]] = zext nneg <2 x i32> [[NARROW]] to <2 x i64>
430; CHECK-NEXT:    ret <2 x i64> [[MIN]]
431;
432  %a_ext = zext <2 x i32> %a to <2 x i64>
433  %cmp = icmp ult <2 x i32> %a, <i32 3, i32 3>
434  %min = select <2 x i1> %cmp, <2 x i64> %a_ext, <2 x i64> <i64 2, i64 2>
435  ret <2 x i64> %min
436}
437
438; Don't crash mishandling a pattern that can't be transformed.
439
440define <2 x i16> @scalar_select_of_vectors(<2 x i16> %a, <2 x i16> %b, i8 %x) {
441; CHECK-LABEL: @scalar_select_of_vectors(
442; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
443; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], <2 x i16> [[A:%.*]], <2 x i16> [[B:%.*]]
444; CHECK-NEXT:    ret <2 x i16> [[SEL]]
445;
446  %cmp = icmp slt i8 %x, 0
447  %sel = select i1 %cmp, <2 x i16> %a, <2 x i16> %b
448  ret <2 x i16> %sel
449}
450
451