xref: /llvm-project/llvm/test/Transforms/LoopVectorize/minmax_reduction.ll (revision ec146cb7c0b4a162ee73463e6c7bb306b99e013b)
1; RUN: opt -S -passes=loop-vectorize,dce -force-vector-width=2 -force-vector-interleave=2  < %s | FileCheck %s
2
3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
4
5@A = common global [1024 x i32] zeroinitializer, align 16
6@fA = common global [1024 x float] zeroinitializer, align 16
7@dA = common global [1024 x double] zeroinitializer, align 16
8
9; Signed tests.
10
11; Turn this into a max reduction. Make sure we use a splat to initialize the
12; vector for the reduction.
13; CHECK-LABEL: @max_red(
14; CHECK: %[[VAR:.*]] = insertelement <2 x i32> poison, i32 %max, i64 0
15; CHECK: {{.*}} = shufflevector <2 x i32> %[[VAR]], <2 x i32> poison, <2 x i32> zeroinitializer
16; CHECK: icmp sgt <2 x i32>
17; CHECK: select <2 x i1>
18; CHECK: middle.block
19; CHECK: call i32 @llvm.vector.reduce.smax.v2i32
20
21define i32 @max_red(i32 %max) {
22entry:
23  br label %for.body
24
25for.body:
26  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
27  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
28  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
29  %0 = load i32, ptr %arrayidx, align 4
30  %cmp3 = icmp sgt i32 %0, %max.red.08
31  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
32  %indvars.iv.next = add i64 %indvars.iv, 1
33  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
34  %exitcond = icmp eq i32 %lftr.wideiv, 1024
35  br i1 %exitcond, label %for.end, label %for.body
36
37for.end:
38  ret i32 %max.red.0
39}
40
41; Turn this into a max reduction. The select has its inputs reversed therefore
42; this is a max reduction.
43; CHECK-LABEL: @max_red_inverse_select(
44; CHECK: icmp slt <2 x i32>
45; CHECK: select <2 x i1>
46; CHECK: middle.block
47; CHECK: call i32 @llvm.vector.reduce.smax.v2i32
48
49define i32 @max_red_inverse_select(i32 %max) {
50entry:
51  br label %for.body
52
53for.body:
54  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
55  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
56  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
57  %0 = load i32, ptr %arrayidx, align 4
58  %cmp3 = icmp slt i32 %max.red.08, %0
59  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
60  %indvars.iv.next = add i64 %indvars.iv, 1
61  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
62  %exitcond = icmp eq i32 %lftr.wideiv, 1024
63  br i1 %exitcond, label %for.end, label %for.body
64
65for.end:
66  ret i32 %max.red.0
67}
68
69; Turn this into a min reduction.
70; CHECK-LABEL: @min_red(
71; CHECK: icmp slt <2 x i32>
72; CHECK: select <2 x i1>
73; CHECK: middle.block
74; CHECK: call i32 @llvm.vector.reduce.smin.v2i32
75
76define i32 @min_red(i32 %max) {
77entry:
78  br label %for.body
79
80for.body:
81  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
82  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
83  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
84  %0 = load i32, ptr %arrayidx, align 4
85  %cmp3 = icmp slt i32 %0, %max.red.08
86  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
87  %indvars.iv.next = add i64 %indvars.iv, 1
88  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
89  %exitcond = icmp eq i32 %lftr.wideiv, 1024
90  br i1 %exitcond, label %for.end, label %for.body
91
92for.end:
93  ret i32 %max.red.0
94}
95
96; Turn this into a min reduction. The select has its inputs reversed therefore
97; this is a min reduction.
98; CHECK-LABEL: @min_red_inverse_select(
99; CHECK: icmp sgt <2 x i32>
100; CHECK: select <2 x i1>
101; CHECK: middle.block
102; CHECK: call i32 @llvm.vector.reduce.smin.v2i32
103
104define i32 @min_red_inverse_select(i32 %max) {
105entry:
106  br label %for.body
107
108for.body:
109  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
110  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
111  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
112  %0 = load i32, ptr %arrayidx, align 4
113  %cmp3 = icmp sgt i32 %max.red.08, %0
114  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
115  %indvars.iv.next = add i64 %indvars.iv, 1
116  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
117  %exitcond = icmp eq i32 %lftr.wideiv, 1024
118  br i1 %exitcond, label %for.end, label %for.body
119
120for.end:
121  ret i32 %max.red.0
122}
123
124; Unsigned tests.
125
126; Turn this into a max reduction.
127; CHECK-LABEL: @umax_red(
128; CHECK: icmp ugt <2 x i32>
129; CHECK: select <2 x i1>
130; CHECK: middle.block
131; CHECK: call i32 @llvm.vector.reduce.umax.v2i32
132
133define i32 @umax_red(i32 %max) {
134entry:
135  br label %for.body
136
137for.body:
138  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
139  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
140  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
141  %0 = load i32, ptr %arrayidx, align 4
142  %cmp3 = icmp ugt i32 %0, %max.red.08
143  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
144  %indvars.iv.next = add i64 %indvars.iv, 1
145  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
146  %exitcond = icmp eq i32 %lftr.wideiv, 1024
147  br i1 %exitcond, label %for.end, label %for.body
148
149for.end:
150  ret i32 %max.red.0
151}
152
153; Turn this into a max reduction. The select has its inputs reversed therefore
154; this is a max reduction.
155; CHECK-LABEL: @umax_red_inverse_select(
156; CHECK: icmp ult <2 x i32>
157; CHECK: select <2 x i1>
158; CHECK: middle.block
159; CHECK: call i32 @llvm.vector.reduce.umax.v2i32
160
161define i32 @umax_red_inverse_select(i32 %max) {
162entry:
163  br label %for.body
164
165for.body:
166  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
167  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
168  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
169  %0 = load i32, ptr %arrayidx, align 4
170  %cmp3 = icmp ult i32 %max.red.08, %0
171  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
172  %indvars.iv.next = add i64 %indvars.iv, 1
173  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
174  %exitcond = icmp eq i32 %lftr.wideiv, 1024
175  br i1 %exitcond, label %for.end, label %for.body
176
177for.end:
178  ret i32 %max.red.0
179}
180
181; Turn this into a min reduction.
182; CHECK-LABEL: @umin_red(
183; CHECK: icmp ult <2 x i32>
184; CHECK: select <2 x i1>
185; CHECK: middle.block
186; CHECK: call i32 @llvm.vector.reduce.umin.v2i32
187
188define i32 @umin_red(i32 %max) {
189entry:
190  br label %for.body
191
192for.body:
193  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
194  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
195  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
196  %0 = load i32, ptr %arrayidx, align 4
197  %cmp3 = icmp ult i32 %0, %max.red.08
198  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
199  %indvars.iv.next = add i64 %indvars.iv, 1
200  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
201  %exitcond = icmp eq i32 %lftr.wideiv, 1024
202  br i1 %exitcond, label %for.end, label %for.body
203
204for.end:
205  ret i32 %max.red.0
206}
207
208; Turn this into a min reduction. The select has its inputs reversed therefore
209; this is a min reduction.
210; CHECK-LABEL: @umin_red_inverse_select(
211; CHECK: icmp ugt <2 x i32>
212; CHECK: select <2 x i1>
213; CHECK: middle.block
214; CHECK: call i32 @llvm.vector.reduce.umin.v2i32
215
216define i32 @umin_red_inverse_select(i32 %max) {
217entry:
218  br label %for.body
219
220for.body:
221  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
222  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
223  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
224  %0 = load i32, ptr %arrayidx, align 4
225  %cmp3 = icmp ugt i32 %max.red.08, %0
226  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
227  %indvars.iv.next = add i64 %indvars.iv, 1
228  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
229  %exitcond = icmp eq i32 %lftr.wideiv, 1024
230  br i1 %exitcond, label %for.end, label %for.body
231
232for.end:
233  ret i32 %max.red.0
234}
235
236; SGE -> SLT
237; Turn this into a min reduction (select inputs are reversed).
238; CHECK-LABEL: @sge_min_red(
239; CHECK: icmp sge <2 x i32>
240; CHECK: select <2 x i1>
241; CHECK: middle.block
242; CHECK: call i32 @llvm.vector.reduce.smin.v2i32
243
244define i32 @sge_min_red(i32 %max) {
245entry:
246  br label %for.body
247
248for.body:
249  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
250  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
251  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
252  %0 = load i32, ptr %arrayidx, align 4
253  %cmp3 = icmp sge i32 %0, %max.red.08
254  %max.red.0 = select i1 %cmp3, i32 %max.red.08, i32 %0
255  %indvars.iv.next = add i64 %indvars.iv, 1
256  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
257  %exitcond = icmp eq i32 %lftr.wideiv, 1024
258  br i1 %exitcond, label %for.end, label %for.body
259
260for.end:
261  ret i32 %max.red.0
262}
263
264; SLE -> SGT
265; Turn this into a max reduction (select inputs are reversed).
266; CHECK-LABEL: @sle_min_red(
267; CHECK: icmp sle <2 x i32>
268; CHECK: select <2 x i1>
269; CHECK: middle.block
270; CHECK: call i32 @llvm.vector.reduce.smax.v2i32
271
272define i32 @sle_min_red(i32 %max) {
273entry:
274  br label %for.body
275
276for.body:
277  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
278  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
279  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
280  %0 = load i32, ptr %arrayidx, align 4
281  %cmp3 = icmp sle i32 %0, %max.red.08
282  %max.red.0 = select i1 %cmp3, i32 %max.red.08, i32 %0
283  %indvars.iv.next = add i64 %indvars.iv, 1
284  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
285  %exitcond = icmp eq i32 %lftr.wideiv, 1024
286  br i1 %exitcond, label %for.end, label %for.body
287
288for.end:
289  ret i32 %max.red.0
290}
291
292; UGE -> ULT
293; Turn this into a min reduction (select inputs are reversed).
294; CHECK-LABEL: @uge_min_red(
295; CHECK: icmp uge <2 x i32>
296; CHECK: select <2 x i1>
297; CHECK: middle.block
298; CHECK: call i32 @llvm.vector.reduce.umin.v2i32
299
300define i32 @uge_min_red(i32 %max) {
301entry:
302  br label %for.body
303
304for.body:
305  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
306  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
307  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
308  %0 = load i32, ptr %arrayidx, align 4
309  %cmp3 = icmp uge i32 %0, %max.red.08
310  %max.red.0 = select i1 %cmp3, i32 %max.red.08, i32 %0
311  %indvars.iv.next = add i64 %indvars.iv, 1
312  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
313  %exitcond = icmp eq i32 %lftr.wideiv, 1024
314  br i1 %exitcond, label %for.end, label %for.body
315
316for.end:
317  ret i32 %max.red.0
318}
319
320; ULE -> UGT
321; Turn this into a max reduction (select inputs are reversed).
322; CHECK-LABEL: @ule_min_red(
323; CHECK: icmp ule <2 x i32>
324; CHECK: select <2 x i1>
325; CHECK: middle.block
326; CHECK: call i32 @llvm.vector.reduce.umax.v2i32
327
328define i32 @ule_min_red(i32 %max) {
329entry:
330  br label %for.body
331
332for.body:
333  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
334  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
335  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
336  %0 = load i32, ptr %arrayidx, align 4
337  %cmp3 = icmp ule i32 %0, %max.red.08
338  %max.red.0 = select i1 %cmp3, i32 %max.red.08, i32 %0
339  %indvars.iv.next = add i64 %indvars.iv, 1
340  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
341  %exitcond = icmp eq i32 %lftr.wideiv, 1024
342  br i1 %exitcond, label %for.end, label %for.body
343
344for.end:
345  ret i32 %max.red.0
346}
347
348; No reduction.
349; CHECK-LABEL: @no_red_1(
350; CHECK-NOT: icmp <2 x i32>
351define i32 @no_red_1(i32 %max) {
352entry:
353  br label %for.body
354
355for.body:
356  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
357  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
358  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
359  %arrayidx1 = getelementptr inbounds [1024 x i32], ptr @A, i64 1, i64 %indvars.iv
360  %0 = load i32, ptr %arrayidx, align 4
361  %1 = load i32, ptr %arrayidx1, align 4
362  %cmp3 = icmp sgt i32 %0, %1
363  %max.red.0 = select i1 %cmp3, i32 %0, i32 %max.red.08
364  %indvars.iv.next = add i64 %indvars.iv, 1
365  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
366  %exitcond = icmp eq i32 %lftr.wideiv, 1024
367  br i1 %exitcond, label %for.end, label %for.body
368
369for.end:
370  ret i32 %max.red.0
371}
372
373; CHECK-LABEL: @no_red_2(
374; CHECK-NOT: icmp <2 x i32>
375define i32 @no_red_2(i32 %max) {
376entry:
377  br label %for.body
378
379for.body:
380  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
381  %max.red.08 = phi i32 [ %max, %entry ], [ %max.red.0, %for.body ]
382  %arrayidx = getelementptr inbounds [1024 x i32], ptr @A, i64 0, i64 %indvars.iv
383  %arrayidx1 = getelementptr inbounds [1024 x i32], ptr @A, i64 1, i64 %indvars.iv
384  %0 = load i32, ptr %arrayidx, align 4
385  %1 = load i32, ptr %arrayidx1, align 4
386  %cmp3 = icmp sgt i32 %0, %max.red.08
387  %max.red.0 = select i1 %cmp3, i32 %0, i32 %1
388  %indvars.iv.next = add i64 %indvars.iv, 1
389  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
390  %exitcond = icmp eq i32 %lftr.wideiv, 1024
391  br i1 %exitcond, label %for.end, label %for.body
392
393for.end:
394  ret i32 %max.red.0
395}
396
397; Float tests.
398
399; Maximum.
400
401; Turn this into a max reduction in the presence of a no-nans-fp-math attribute.
402; CHECK-LABEL: @max_red_float(
403; CHECK: fcmp fast ogt <2 x float>
404; CHECK: select <2 x i1>
405; CHECK: middle.block
406; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
407
408define float @max_red_float(float %max) #0 {
409entry:
410  br label %for.body
411
412for.body:
413  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
414  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
415  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
416  %0 = load float, ptr %arrayidx, align 4
417  %cmp3 = fcmp fast ogt float %0, %max.red.08
418  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
419  %indvars.iv.next = add i64 %indvars.iv, 1
420  %exitcond = icmp eq i64 %indvars.iv.next, 1024
421  br i1 %exitcond, label %for.end, label %for.body
422
423for.end:
424  ret float %max.red.0
425}
426
427; CHECK-LABEL: @max_red_float_ge(
428; CHECK: fcmp fast oge <2 x float>
429; CHECK: select <2 x i1>
430; CHECK: middle.block
431; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
432
433define float @max_red_float_ge(float %max) #0 {
434entry:
435  br label %for.body
436
437for.body:
438  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
439  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
440  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
441  %0 = load float, ptr %arrayidx, align 4
442  %cmp3 = fcmp fast oge float %0, %max.red.08
443  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
444  %indvars.iv.next = add i64 %indvars.iv, 1
445  %exitcond = icmp eq i64 %indvars.iv.next, 1024
446  br i1 %exitcond, label %for.end, label %for.body
447
448for.end:
449  ret float %max.red.0
450}
451
452; CHECK-LABEL: @inverted_max_red_float(
453; CHECK: fcmp fast olt <2 x float>
454; CHECK: select <2 x i1>
455; CHECK: middle.block
456; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
457
458define float @inverted_max_red_float(float %max) #0 {
459entry:
460  br label %for.body
461
462for.body:
463  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
464  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
465  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
466  %0 = load float, ptr %arrayidx, align 4
467  %cmp3 = fcmp fast olt float %0, %max.red.08
468  %max.red.0 = select i1 %cmp3, float %max.red.08, float %0
469  %indvars.iv.next = add i64 %indvars.iv, 1
470  %exitcond = icmp eq i64 %indvars.iv.next, 1024
471  br i1 %exitcond, label %for.end, label %for.body
472
473for.end:
474  ret float %max.red.0
475}
476
477; CHECK-LABEL: @inverted_max_red_float_le(
478; CHECK: fcmp fast ole <2 x float>
479; CHECK: select <2 x i1>
480; CHECK: middle.block
481; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
482
483define float @inverted_max_red_float_le(float %max) #0 {
484entry:
485  br label %for.body
486
487for.body:
488  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
489  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
490  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
491  %0 = load float, ptr %arrayidx, align 4
492  %cmp3 = fcmp fast ole float %0, %max.red.08
493  %max.red.0 = select i1 %cmp3, float %max.red.08, float %0
494  %indvars.iv.next = add i64 %indvars.iv, 1
495  %exitcond = icmp eq i64 %indvars.iv.next, 1024
496  br i1 %exitcond, label %for.end, label %for.body
497
498for.end:
499  ret float %max.red.0
500}
501
502; CHECK-LABEL: @unordered_max_red_float(
503; CHECK: fcmp fast ugt <2 x float>
504; CHECK: select <2 x i1>
505; CHECK: middle.block
506; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
507
508define float @unordered_max_red_float(float %max) #0 {
509entry:
510  br label %for.body
511
512for.body:
513  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
514  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
515  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
516  %0 = load float, ptr %arrayidx, align 4
517  %cmp3 = fcmp fast ugt float %0, %max.red.08
518  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
519  %indvars.iv.next = add i64 %indvars.iv, 1
520  %exitcond = icmp eq i64 %indvars.iv.next, 1024
521  br i1 %exitcond, label %for.end, label %for.body
522
523for.end:
524  ret float %max.red.0
525}
526
527; CHECK-LABEL: @unordered_max_red_float_ge(
528; CHECK: fcmp fast uge <2 x float>
529; CHECK: select <2 x i1>
530; CHECK: middle.block
531; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
532
533define float @unordered_max_red_float_ge(float %max) #0 {
534entry:
535  br label %for.body
536
537for.body:
538  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
539  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
540  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
541  %0 = load float, ptr %arrayidx, align 4
542  %cmp3 = fcmp fast uge float %0, %max.red.08
543  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
544  %indvars.iv.next = add i64 %indvars.iv, 1
545  %exitcond = icmp eq i64 %indvars.iv.next, 1024
546  br i1 %exitcond, label %for.end, label %for.body
547
548for.end:
549  ret float %max.red.0
550}
551
552; CHECK-LABEL: @inverted_unordered_max_red_float(
553; CHECK: fcmp fast ult <2 x float>
554; CHECK: select <2 x i1>
555; CHECK: middle.block
556; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
557
558define float @inverted_unordered_max_red_float(float %max) #0 {
559entry:
560  br label %for.body
561
562for.body:
563  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
564  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
565  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
566  %0 = load float, ptr %arrayidx, align 4
567  %cmp3 = fcmp fast ult float %0, %max.red.08
568  %max.red.0 = select i1 %cmp3, float %max.red.08, float %0
569  %indvars.iv.next = add i64 %indvars.iv, 1
570  %exitcond = icmp eq i64 %indvars.iv.next, 1024
571  br i1 %exitcond, label %for.end, label %for.body
572
573for.end:
574  ret float %max.red.0
575}
576
577; CHECK-LABEL: @inverted_unordered_max_red_float_le(
578; CHECK: fcmp fast ule <2 x float>
579; CHECK: select <2 x i1>
580; CHECK: middle.block
581; CHECK: call fast float @llvm.vector.reduce.fmax.v2f32
582
583define float @inverted_unordered_max_red_float_le(float %max) #0 {
584entry:
585  br label %for.body
586
587for.body:
588  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
589  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
590  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
591  %0 = load float, ptr %arrayidx, align 4
592  %cmp3 = fcmp fast ule float %0, %max.red.08
593  %max.red.0 = select i1 %cmp3, float %max.red.08, float %0
594  %indvars.iv.next = add i64 %indvars.iv, 1
595  %exitcond = icmp eq i64 %indvars.iv.next, 1024
596  br i1 %exitcond, label %for.end, label %for.body
597
598for.end:
599  ret float %max.red.0
600}
601
602; Minimum.
603
604; Turn this into a min reduction in the presence of a no-nans-fp-math attribute.
605; CHECK-LABEL: @min_red_float(
606; CHECK: fcmp fast olt <2 x float>
607; CHECK: select <2 x i1>
608; CHECK: middle.block
609; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
610
611define float @min_red_float(float %min) #0 {
612entry:
613  br label %for.body
614
615for.body:
616  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
617  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
618  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
619  %0 = load float, ptr %arrayidx, align 4
620  %cmp3 = fcmp fast olt float %0, %min.red.08
621  %min.red.0 = select i1 %cmp3, float %0, float %min.red.08
622  %indvars.iv.next = add i64 %indvars.iv, 1
623  %exitcond = icmp eq i64 %indvars.iv.next, 1024
624  br i1 %exitcond, label %for.end, label %for.body
625
626for.end:
627  ret float %min.red.0
628}
629
630; CHECK-LABEL: @min_red_float_le(
631; CHECK: fcmp fast ole <2 x float>
632; CHECK: select <2 x i1>
633; CHECK: middle.block
634; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
635
636define float @min_red_float_le(float %min) #0 {
637entry:
638  br label %for.body
639
640for.body:
641  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
642  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
643  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
644  %0 = load float, ptr %arrayidx, align 4
645  %cmp3 = fcmp fast ole float %0, %min.red.08
646  %min.red.0 = select i1 %cmp3, float %0, float %min.red.08
647  %indvars.iv.next = add i64 %indvars.iv, 1
648  %exitcond = icmp eq i64 %indvars.iv.next, 1024
649  br i1 %exitcond, label %for.end, label %for.body
650
651for.end:
652  ret float %min.red.0
653}
654
655; CHECK-LABEL: @inverted_min_red_float(
656; CHECK: fcmp fast ogt <2 x float>
657; CHECK: select <2 x i1>
658; CHECK: middle.block
659; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
660
661define float @inverted_min_red_float(float %min) #0 {
662entry:
663  br label %for.body
664
665for.body:
666  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
667  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
668  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
669  %0 = load float, ptr %arrayidx, align 4
670  %cmp3 = fcmp fast ogt float %0, %min.red.08
671  %min.red.0 = select i1 %cmp3, float %min.red.08, float %0
672  %indvars.iv.next = add i64 %indvars.iv, 1
673  %exitcond = icmp eq i64 %indvars.iv.next, 1024
674  br i1 %exitcond, label %for.end, label %for.body
675
676for.end:
677  ret float %min.red.0
678}
679
680; CHECK-LABEL: @inverted_min_red_float_ge(
681; CHECK: fcmp fast oge <2 x float>
682; CHECK: select <2 x i1>
683; CHECK: middle.block
684; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
685
686define float @inverted_min_red_float_ge(float %min) #0 {
687entry:
688  br label %for.body
689
690for.body:
691  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
692  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
693  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
694  %0 = load float, ptr %arrayidx, align 4
695  %cmp3 = fcmp fast oge float %0, %min.red.08
696  %min.red.0 = select i1 %cmp3, float %min.red.08, float %0
697  %indvars.iv.next = add i64 %indvars.iv, 1
698  %exitcond = icmp eq i64 %indvars.iv.next, 1024
699  br i1 %exitcond, label %for.end, label %for.body
700
701for.end:
702  ret float %min.red.0
703}
704
705; CHECK-LABEL: @unordered_min_red_float(
706; CHECK: fcmp fast ult <2 x float>
707; CHECK: select <2 x i1>
708; CHECK: middle.block
709; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
710
711define float @unordered_min_red_float(float %min) #0 {
712entry:
713  br label %for.body
714
715for.body:
716  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
717  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
718  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
719  %0 = load float, ptr %arrayidx, align 4
720  %cmp3 = fcmp fast ult float %0, %min.red.08
721  %min.red.0 = select i1 %cmp3, float %0, float %min.red.08
722  %indvars.iv.next = add i64 %indvars.iv, 1
723  %exitcond = icmp eq i64 %indvars.iv.next, 1024
724  br i1 %exitcond, label %for.end, label %for.body
725
726for.end:
727  ret float %min.red.0
728}
729
730; CHECK-LABEL: @unordered_min_red_float_le(
731; CHECK: fcmp fast ule <2 x float>
732; CHECK: select <2 x i1>
733; CHECK: middle.block
734; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
735
736define float @unordered_min_red_float_le(float %min) #0 {
737entry:
738  br label %for.body
739
740for.body:
741  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
742  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
743  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
744  %0 = load float, ptr %arrayidx, align 4
745  %cmp3 = fcmp fast ule float %0, %min.red.08
746  %min.red.0 = select i1 %cmp3, float %0, float %min.red.08
747  %indvars.iv.next = add i64 %indvars.iv, 1
748  %exitcond = icmp eq i64 %indvars.iv.next, 1024
749  br i1 %exitcond, label %for.end, label %for.body
750
751for.end:
752  ret float %min.red.0
753}
754
755; CHECK-LABEL: @inverted_unordered_min_red_float(
756; CHECK: fcmp fast ugt <2 x float>
757; CHECK: select <2 x i1>
758; CHECK: middle.block
759; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
760
761define float @inverted_unordered_min_red_float(float %min) #0 {
762entry:
763  br label %for.body
764
765for.body:
766  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
767  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
768  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
769  %0 = load float, ptr %arrayidx, align 4
770  %cmp3 = fcmp fast ugt float %0, %min.red.08
771  %min.red.0 = select i1 %cmp3, float %min.red.08, float %0
772  %indvars.iv.next = add i64 %indvars.iv, 1
773  %exitcond = icmp eq i64 %indvars.iv.next, 1024
774  br i1 %exitcond, label %for.end, label %for.body
775
776for.end:
777  ret float %min.red.0
778}
779
780; CHECK-LABEL: @inverted_unordered_min_red_float_ge(
781; CHECK: fcmp fast uge <2 x float>
782; CHECK: select <2 x i1>
783; CHECK: middle.block
784; CHECK: call fast float @llvm.vector.reduce.fmin.v2f32
785
786define float @inverted_unordered_min_red_float_ge(float %min) #0 {
787entry:
788  br label %for.body
789
790for.body:
791  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
792  %min.red.08 = phi float [ %min, %entry ], [ %min.red.0, %for.body ]
793  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
794  %0 = load float, ptr %arrayidx, align 4
795  %cmp3 = fcmp fast uge float %0, %min.red.08
796  %min.red.0 = select i1 %cmp3, float %min.red.08, float %0
797  %indvars.iv.next = add i64 %indvars.iv, 1
798  %exitcond = icmp eq i64 %indvars.iv.next, 1024
799  br i1 %exitcond, label %for.end, label %for.body
800
801for.end:
802  ret float %min.red.0
803}
804
805; Make sure we handle doubles, too.
806; CHECK-LABEL: @min_red_double(
807; CHECK: fcmp fast olt <2 x double>
808; CHECK: select <2 x i1>
809; CHECK: middle.block
810; CHECK: call fast double @llvm.vector.reduce.fmin.v2f64
811
812define double @min_red_double(double %min) #0 {
813entry:
814  br label %for.body
815
816for.body:
817  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
818  %min.red.08 = phi double [ %min, %entry ], [ %min.red.0, %for.body ]
819  %arrayidx = getelementptr inbounds [1024 x double], ptr @dA, i64 0, i64 %indvars.iv
820  %0 = load double, ptr %arrayidx, align 4
821  %cmp3 = fcmp fast olt double %0, %min.red.08
822  %min.red.0 = select i1 %cmp3, double %0, double %min.red.08
823  %indvars.iv.next = add i64 %indvars.iv, 1
824  %exitcond = icmp eq i64 %indvars.iv.next, 1024
825  br i1 %exitcond, label %for.end, label %for.body
826
827for.end:
828  ret double %min.red.0
829}
830
831
832; Don't this into a max reduction. The no-nans-fp-math attribute is missing
833; CHECK-LABEL: @max_red_float_nans(
834; CHECK-NOT: <2 x float>
835
836define float @max_red_float_nans(float %max) {
837entry:
838  br label %for.body
839
840for.body:
841  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
842  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
843  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
844  %0 = load float, ptr %arrayidx, align 4
845  %cmp3 = fcmp fast ogt float %0, %max.red.08
846  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
847  %indvars.iv.next = add i64 %indvars.iv, 1
848  %exitcond = icmp eq i64 %indvars.iv.next, 1024
849  br i1 %exitcond, label %for.end, label %for.body
850
851for.end:
852  ret float %max.red.0
853}
854
855; As above, with the no-signed-zeros-fp-math attribute missing
856; CHECK-LABEL: @max_red_float_nsz(
857; CHECK-NOT: <2 x float>
858
859define float @max_red_float_nsz(float %max) #1 {
860entry:
861  br label %for.body
862
863for.body:
864  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
865  %max.red.08 = phi float [ %max, %entry ], [ %max.red.0, %for.body ]
866  %arrayidx = getelementptr inbounds [1024 x float], ptr @fA, i64 0, i64 %indvars.iv
867  %0 = load float, ptr %arrayidx, align 4
868  %cmp3 = fcmp fast ogt float %0, %max.red.08
869  %max.red.0 = select i1 %cmp3, float %0, float %max.red.08
870  %indvars.iv.next = add i64 %indvars.iv, 1
871  %exitcond = icmp eq i64 %indvars.iv.next, 1024
872  br i1 %exitcond, label %for.end, label %for.body
873
874for.end:
875  ret float %max.red.0
876}
877
878; CHECK-LABEL: @smin_intrinsic(
879; CHECK: <2 x i32> @llvm.smin.v2i32
880; CHECK: i32 @llvm.vector.reduce.smin.v2i32
881define i32 @smin_intrinsic(ptr nocapture readonly %x) {
882entry:
883  br label %for.body
884
885for.body:                                         ; preds = %entry, %for.body
886  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
887  %s.011 = phi i32 [ 100, %entry ], [ %1, %for.body ]
888  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.012
889  %0 = load i32, ptr %arrayidx, align 4
890  %1 = tail call i32 @llvm.smin.i32(i32 %s.011, i32 %0)
891  %inc = add nuw nsw i32 %i.012, 1
892  %exitcond.not = icmp eq i32 %inc, 1024
893  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
894
895for.cond.cleanup:                                 ; preds = %for.body
896  ret i32 %1
897}
898
899; CHECK-LABEL: @smax_intrinsic(
900; CHECK: <2 x i32> @llvm.smax.v2i32
901; CHECK: i32 @llvm.vector.reduce.smax.v2i32
902define i32 @smax_intrinsic(ptr nocapture readonly %x) {
903entry:
904  br label %for.body
905
906for.body:                                         ; preds = %entry, %for.body
907  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
908  %s.011 = phi i32 [ 100, %entry ], [ %1, %for.body ]
909  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.012
910  %0 = load i32, ptr %arrayidx, align 4
911  %1 = tail call i32 @llvm.smax.i32(i32 %s.011, i32 %0)
912  %inc = add nuw nsw i32 %i.012, 1
913  %exitcond.not = icmp eq i32 %inc, 1024
914  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
915
916for.cond.cleanup:                                 ; preds = %for.body
917  ret i32 %1
918}
919
920; CHECK-LABEL: @umin_intrinsic(
921; CHECK: <2 x i32> @llvm.umin.v2i32
922; CHECK: i32 @llvm.vector.reduce.umin.v2i32
923define i32 @umin_intrinsic(ptr nocapture readonly %x) {
924entry:
925  br label %for.body
926
927for.body:                                         ; preds = %entry, %for.body
928  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
929  %s.011 = phi i32 [ 100, %entry ], [ %1, %for.body ]
930  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.012
931  %0 = load i32, ptr %arrayidx, align 4
932  %1 = tail call i32 @llvm.umin.i32(i32 %s.011, i32 %0)
933  %inc = add nuw nsw i32 %i.012, 1
934  %exitcond.not = icmp eq i32 %inc, 1024
935  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
936
937for.cond.cleanup:                                 ; preds = %for.body
938  ret i32 %1
939}
940
941; CHECK-LABEL: @umax_intrinsic(
942; CHECK: <2 x i32> @llvm.umax.v2i32
943; CHECK: i32 @llvm.vector.reduce.umax.v2i32
944define i32 @umax_intrinsic(ptr nocapture readonly %x) {
945entry:
946  br label %for.body
947
948for.body:                                         ; preds = %entry, %for.body
949  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
950  %s.011 = phi i32 [ 100, %entry ], [ %1, %for.body ]
951  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.012
952  %0 = load i32, ptr %arrayidx, align 4
953  %1 = tail call i32 @llvm.umax.i32(i32 %s.011, i32 %0)
954  %inc = add nuw nsw i32 %i.012, 1
955  %exitcond.not = icmp eq i32 %inc, 1024
956  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
957
958for.cond.cleanup:                                 ; preds = %for.body
959  ret i32 %1
960}
961
962; CHECK-LABEL: @fmin_intrinsic(
963; CHECK: nnan nsz <2 x float> @llvm.minnum.v2f32
964; CHECK: nnan nsz float @llvm.vector.reduce.fmin.v2f32
965define float @fmin_intrinsic(ptr nocapture readonly %x) {
966entry:
967  br label %for.body
968
969for.cond.cleanup:                                 ; preds = %for.body
970  ret float %1
971
972for.body:                                         ; preds = %entry, %for.body
973  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
974  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
975  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
976  %0 = load float, ptr %arrayidx, align 4
977  %1 = tail call nnan nsz float @llvm.minnum.f32(float %s.011, float %0)
978  %inc = add nuw nsw i32 %i.012, 1
979  %exitcond.not = icmp eq i32 %inc, 1024
980  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
981}
982
983; CHECK-LABEL: @fmax_intrinsic(
984; CHECK: fast <2 x float> @llvm.maxnum.v2f32
985; CHECK: fast float @llvm.vector.reduce.fmax.v2f32
986define float @fmax_intrinsic(ptr nocapture readonly %x) {
987entry:
988  br label %for.body
989
990for.cond.cleanup:                                 ; preds = %for.body
991  ret float %1
992
993for.body:                                         ; preds = %entry, %for.body
994  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
995  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
996  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
997  %0 = load float, ptr %arrayidx, align 4
998  %1 = tail call fast float @llvm.maxnum.f32(float %s.011, float %0)
999  %inc = add nuw nsw i32 %i.012, 1
1000  %exitcond.not = icmp eq i32 %inc, 1024
1001  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1002}
1003
1004; CHECK-LABEL: @fmin_intrinsic_nofast(
1005; CHECK-NOT: <2 x float> @llvm.minnum.v2f32
1006define float @fmin_intrinsic_nofast(ptr nocapture readonly %x) {
1007entry:
1008  br label %for.body
1009
1010for.cond.cleanup:                                 ; preds = %for.body
1011  ret float %1
1012
1013for.body:                                         ; preds = %entry, %for.body
1014  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1015  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
1016  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
1017  %0 = load float, ptr %arrayidx, align 4
1018  %1 = tail call float @llvm.minnum.f32(float %s.011, float %0)
1019  %inc = add nuw nsw i32 %i.012, 1
1020  %exitcond.not = icmp eq i32 %inc, 1024
1021  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1022}
1023
1024; CHECK-LABEL: @fmax_intrinsic_nofast(
1025; CHECK-NOT: <2 x float> @llvm.maxnum.v2f32
1026define float @fmax_intrinsic_nofast(ptr nocapture readonly %x) {
1027entry:
1028  br label %for.body
1029
1030for.cond.cleanup:                                 ; preds = %for.body
1031  ret float %1
1032
1033for.body:                                         ; preds = %entry, %for.body
1034  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1035  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
1036  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
1037  %0 = load float, ptr %arrayidx, align 4
1038  %1 = tail call float @llvm.maxnum.f32(float %s.011, float %0)
1039  %inc = add nuw nsw i32 %i.012, 1
1040  %exitcond.not = icmp eq i32 %inc, 1024
1041  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1042}
1043
1044; CHECK-LABEL: @sminmax(
1045; Min and max intrinsics - don't vectorize
1046; CHECK-NOT: <2 x i32>
1047define i32 @sminmax(ptr nocapture readonly %x, ptr nocapture readonly %y) {
1048entry:
1049  br label %for.body
1050
1051for.cond.cleanup:                                 ; preds = %for.body
1052  ret i32 %cond9
1053
1054for.body:                                         ; preds = %entry, %for.body
1055  %i.025 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1056  %s.024 = phi i32 [ 0, %entry ], [ %cond9, %for.body ]
1057  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.025
1058  %0 = load i32, ptr %arrayidx, align 4
1059  %s.0. = tail call i32 @llvm.smin.i32(i32 %s.024, i32 %0)
1060  %arrayidx3 = getelementptr inbounds i32, ptr %y, i32 %i.025
1061  %1 = load i32, ptr %arrayidx3, align 4
1062  %cond9 = tail call i32 @llvm.smax.i32(i32 %s.0., i32 %1)
1063  %inc = add nuw nsw i32 %i.025, 1
1064  %exitcond.not = icmp eq i32 %inc, 1024
1065  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1066}
1067
1068; CHECK-LABEL: @sminmin(
1069; CHECK: <2 x i32> @llvm.smin.v2i32
1070; CHECK: <2 x i32> @llvm.smin.v2i32
1071; CHECK: i32 @llvm.vector.reduce.smin.v2i32
1072define i32 @sminmin(ptr nocapture readonly %x, ptr nocapture readonly %y) {
1073entry:
1074  br label %for.body
1075
1076for.cond.cleanup:                                 ; preds = %for.body
1077  ret i32 %cond9
1078
1079for.body:                                         ; preds = %entry, %for.body
1080  %i.025 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1081  %s.024 = phi i32 [ 0, %entry ], [ %cond9, %for.body ]
1082  %arrayidx = getelementptr inbounds i32, ptr %x, i32 %i.025
1083  %0 = load i32, ptr %arrayidx, align 4
1084  %s.0. = tail call i32 @llvm.smin.i32(i32 %s.024, i32 %0)
1085  %arrayidx3 = getelementptr inbounds i32, ptr %y, i32 %i.025
1086  %1 = load i32, ptr %arrayidx3, align 4
1087  %cond9 = tail call i32 @llvm.smin.i32(i32 %s.0., i32 %1)
1088  %inc = add nuw nsw i32 %i.025, 1
1089  %exitcond.not = icmp eq i32 %inc, 1024
1090  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1091}
1092
1093; CHECK-LABEL: fmaximum_intrinsic
1094; CHECK-LABEL: vector.body:
1095; CHECK: call <2 x float> @llvm.maximum.v2f32
1096; CHECK: call <2 x float> @llvm.maximum.v2f32
1097
1098; CHECK-LABEL: middle.block:
1099; CHECK: call <2 x float> @llvm.maximum.v2f32
1100; CHECK: call float @llvm.vector.reduce.fmaximum.v2f32
1101define float @fmaximum_intrinsic(ptr nocapture readonly %x) {
1102entry:
1103  br label %for.body
1104
1105for.cond.cleanup:                                 ; preds = %for.body
1106  ret float %1
1107
1108for.body:                                         ; preds = %entry, %for.body
1109  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1110  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
1111  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
1112  %0 = load float, ptr %arrayidx, align 4
1113  %1 = tail call float @llvm.maximum.f32(float %s.011, float %0)
1114  %inc = add nuw nsw i32 %i.012, 1
1115  %exitcond.not = icmp eq i32 %inc, 1024
1116  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1117}
1118
1119; CHECK-LABEL: fminimum_intrinsic
1120; CHECK-LABEL: vector.body:
1121; CHECK: call <2 x float> @llvm.minimum.v2f32
1122; CHECK: call <2 x float> @llvm.minimum.v2f32
1123
1124; CHECK-LABEL: middle.block:
1125; CHECK: call <2 x float> @llvm.minimum.v2f32
1126; CHECK: call float @llvm.vector.reduce.fminimum.v2f32
1127define float @fminimum_intrinsic(ptr nocapture readonly %x) {
1128entry:
1129  br label %for.body
1130
1131for.cond.cleanup:                                 ; preds = %for.body
1132  ret float %1
1133
1134for.body:                                         ; preds = %entry, %for.body
1135  %i.012 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1136  %s.011 = phi float [ 0.000000e+00, %entry ], [ %1, %for.body ]
1137  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.012
1138  %0 = load float, ptr %arrayidx, align 4
1139  %1 = tail call float @llvm.minimum.f32(float %s.011, float %0)
1140  %inc = add nuw nsw i32 %i.012, 1
1141  %exitcond.not = icmp eq i32 %inc, 1024
1142  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1143}
1144
1145; CHECK-LABEL: fminimum_fminimum
1146; CHECK-LABEL: vector.body:
1147; CHECK: call <2 x float> @llvm.minimum.v2f32
1148; CHECK: call <2 x float> @llvm.minimum.v2f32
1149; CHECK: call <2 x float> @llvm.minimum.v2f32
1150; CHECK: call <2 x float> @llvm.minimum.v2f32
1151
1152; CHECK-LABEL: middle.block:
1153; CHECK: call <2 x float> @llvm.minimum.v2f32
1154; CHECK: call float @llvm.vector.reduce.fminimum.v2f32
1155define float @fminimum_fminimum(ptr nocapture readonly %x, ptr nocapture readonly %y) {
1156entry:
1157  br label %for.body
1158
1159for.cond.cleanup:                                 ; preds = %for.body
1160  ret float %cond9
1161
1162for.body:                                         ; preds = %entry, %for.body
1163  %i.025 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1164  %s.011 = phi float [ 0.000000e+00, %entry ], [ %cond9, %for.body ]
1165  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.025
1166  %0 = load float, ptr %arrayidx, align 4
1167  %s.0. = tail call float @llvm.minimum.f32(float %s.011, float %0)
1168  %arrayidx3 = getelementptr inbounds float, ptr %y, i32 %i.025
1169  %1 = load float, ptr %arrayidx3, align 4
1170  %cond9 = tail call float @llvm.minimum.f32(float %s.0., float %1)
1171  %inc = add nuw nsw i32 %i.025, 1
1172  %exitcond.not = icmp eq i32 %inc, 1024
1173  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1174}
1175
1176; CHECK-LABEL: fminimum_fminimum_one_with_flags
1177; CHECK-LABEL: vector.body:
1178; CHECK: call nnan nsz <2 x float> @llvm.minimum.v2f32
1179; CHECK: call nnan nsz <2 x float> @llvm.minimum.v2f32
1180; CHECK: call <2 x float> @llvm.minimum.v2f32
1181; CHECK: call <2 x float> @llvm.minimum.v2f32
1182
1183; CHECK-LABEL: middle.block:
1184; CHECK: call <2 x float> @llvm.minimum.v2f32
1185; CHECK: call float @llvm.vector.reduce.fminimum.v2f32
1186define float @fminimum_fminimum_one_with_flags(ptr nocapture readonly %x, ptr nocapture readonly %y) {
1187entry:
1188  br label %for.body
1189
1190for.cond.cleanup:                                 ; preds = %for.body
1191  ret float %cond9
1192
1193for.body:                                         ; preds = %entry, %for.body
1194  %i.025 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
1195  %s.011 = phi float [ 0.000000e+00, %entry ], [ %cond9, %for.body ]
1196  %arrayidx = getelementptr inbounds float, ptr %x, i32 %i.025
1197  %0 = load float, ptr %arrayidx, align 4
1198  %s.0. = tail call nnan nsz float @llvm.minimum.f32(float %s.011, float %0)
1199  %arrayidx3 = getelementptr inbounds float, ptr %y, i32 %i.025
1200  %1 = load float, ptr %arrayidx3, align 4
1201  %cond9 = tail call float @llvm.minimum.f32(float %s.0., float %1)
1202  %inc = add nuw nsw i32 %i.025, 1
1203  %exitcond.not = icmp eq i32 %inc, 1024
1204  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1205}
1206
1207; Make sure any check-not directives are not triggered by function declarations.
1208; CHECK: declare
1209
1210declare i32 @llvm.smin.i32(i32, i32)
1211declare i32 @llvm.smax.i32(i32, i32)
1212declare i32 @llvm.umin.i32(i32, i32)
1213declare i32 @llvm.umax.i32(i32, i32)
1214declare float @llvm.minnum.f32(float, float)
1215declare float @llvm.maxnum.f32(float, float)
1216declare float @llvm.minimum.f32(float, float)
1217declare float @llvm.maximum.f32(float, float)
1218
1219attributes #0 = { "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" }
1220attributes #1 = { "no-nans-fp-math"="true" }
1221