1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Instcombine should recognize that this code can be adjusted to fit the canonical max/min pattern.
8 define i32 @smax1(i32 %n) {
10 ; CHECK-NEXT: [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0)
11 ; CHECK-NEXT: ret i32 [[M]]
13 %t = icmp sgt i32 %n, 0
14 %m = select i1 %t, i32 %n, i32 0
20 define 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]]
25 %t = icmp slt i32 %n, 0
26 %m = select i1 %t, i32 %n, i32 0
30 ; Canonicalize min/max.
32 define 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]]
37 %t = icmp sge i32 %n, 1
38 %m = select i1 %t, i32 %n, i32 0
42 ; Canonicalize min/max.
44 define 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]]
49 %t = icmp sle i32 %n, -1
50 %m = select i1 %t, i32 %n, i32 0
54 ; Canonicalize min/max.
56 define 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]]
61 %t = icmp sgt i32 %n, -1
62 %m = select i1 %t, i32 %n, i32 0
66 ; Canonicalize min/max.
68 define <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]]
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
78 ; Canonicalize min/max.
80 define 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]]
85 %t = icmp slt i32 %n, 1
86 %m = select i1 %t, i32 %n, i32 0
90 ; Canonicalize min/max.
92 define <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]]
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
102 ; Canonicalize min/max.
104 define 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]]
109 %t = icmp ugt i32 %n, 4
110 %m = select i1 %t, i32 %n, i32 5
114 ; Canonicalize min/max.
116 define <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]]
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>
126 ; Canonicalize min/max.
128 define 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]]
133 %t = icmp ult i32 %n, 7
134 %m = select i1 %t, i32 %n, i32 6
138 ; Canonicalize min/max.
140 define <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]]
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>
150 ; Canonicalize min/max.
152 define 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]]
157 %t = icmp sge i32 %n, 0
158 %m = select i1 %t, i32 %n, i32 0
162 ; Canonicalize min/max.
164 define <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]]
169 %t = icmp sge <2 x i32> %n, zeroinitializer
170 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
174 ; Canonicalize min/max.
176 define 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]]
181 %t = icmp sle i32 %n, 0
182 %m = select i1 %t, i32 %n, i32 0
186 ; Canonicalize min/max.
188 define <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]]
193 %t = icmp sle <2 x i32> %n, zeroinitializer
194 %m = select <2 x i1> %t, <2 x i32> %n, <2 x i32> zeroinitializer
198 ; Canonicalize min/max.
200 define 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]]
205 %t = icmp uge i32 %n, 8
206 %m = select i1 %t, i32 %n, i32 8
210 ; Canonicalize min/max.
212 define <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]]
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>
222 ; Canonicalize min/max.
224 define 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]]
229 %t = icmp ule i32 %n, 9
230 %m = select i1 %t, i32 %n, i32 9
234 ; Canonicalize min/max.
236 define <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]]
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>
246 define 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]]
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
258 define <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]]
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
270 define 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]]
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
282 define <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]]
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
294 define 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]]
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
306 define <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]]
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>
318 define 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]]
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
330 define <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]]
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>
342 define 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]]
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
354 define <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]]
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
366 define 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]]
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
378 define <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]]
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
390 define 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]]
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
402 define <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]]
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>
414 define 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]]
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
426 define <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]]
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>
438 ; Don't crash mishandling a pattern that can't be transformed.
440 define <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]]
446 %cmp = icmp slt i8 %x, 0
447 %sel = select i1 %cmp, <2 x i16> %a, <2 x i16> %b