[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / minmax_reduction.ll
blob2f67b72ee4010190f68787c379715d075fa79821
1 ; RUN: opt -S -loop-vectorize -dce -force-vector-width=2 -force-vector-interleave=1  < %s | FileCheck %s
3 target 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"
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
9 ; Signed tests.
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, i32 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
21 define i32 @max_red(i32 %max) {
22 entry:
23   br label %for.body
25 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
29   %0 = load i32, i32* %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
37 for.end:
38   ret i32 %max.red.0
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
49 define i32 @max_red_inverse_select(i32 %max) {
50 entry:
51   br label %for.body
53 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
57   %0 = load i32, i32* %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
65 for.end:
66   ret i32 %max.red.0
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
76 define i32 @min_red(i32 %max) {
77 entry:
78   br label %for.body
80 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
84   %0 = load i32, i32* %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
92 for.end:
93   ret i32 %max.red.0
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
104 define i32 @min_red_inverse_select(i32 %max) {
105 entry:
106   br label %for.body
108 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
112   %0 = load i32, i32* %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
120 for.end:
121   ret i32 %max.red.0
124 ; Unsigned tests.
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
133 define i32 @umax_red(i32 %max) {
134 entry:
135   br label %for.body
137 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
141   %0 = load i32, i32* %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
149 for.end:
150   ret i32 %max.red.0
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
161 define i32 @umax_red_inverse_select(i32 %max) {
162 entry:
163   br label %for.body
165 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
169   %0 = load i32, i32* %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
177 for.end:
178   ret i32 %max.red.0
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
188 define i32 @umin_red(i32 %max) {
189 entry:
190   br label %for.body
192 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
196   %0 = load i32, i32* %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
204 for.end:
205   ret i32 %max.red.0
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
216 define i32 @umin_red_inverse_select(i32 %max) {
217 entry:
218   br label %for.body
220 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
224   %0 = load i32, i32* %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
232 for.end:
233   ret i32 %max.red.0
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
244 define i32 @sge_min_red(i32 %max) {
245 entry:
246   br label %for.body
248 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
252   %0 = load i32, i32* %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
260 for.end:
261   ret i32 %max.red.0
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
272 define i32 @sle_min_red(i32 %max) {
273 entry:
274   br label %for.body
276 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
280   %0 = load i32, i32* %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
288 for.end:
289   ret i32 %max.red.0
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
300 define i32 @uge_min_red(i32 %max) {
301 entry:
302   br label %for.body
304 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
308   %0 = load i32, i32* %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
316 for.end:
317   ret i32 %max.red.0
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
328 define i32 @ule_min_red(i32 %max) {
329 entry:
330   br label %for.body
332 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
336   %0 = load i32, i32* %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
344 for.end:
345   ret i32 %max.red.0
348 ; No reduction.
349 ; CHECK-LABEL: @no_red_1(
350 ; CHECK-NOT: icmp <2 x i32>
351 define i32 @no_red_1(i32 %max) {
352 entry:
353   br label %for.body
355 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
359   %arrayidx1 = getelementptr inbounds [1024 x i32], [1024 x i32]* @A, i64 1, i64 %indvars.iv
360   %0 = load i32, i32* %arrayidx, align 4
361   %1 = load i32, i32* %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
369 for.end:
370   ret i32 %max.red.0
373 ; CHECK-LABEL: @no_red_2(
374 ; CHECK-NOT: icmp <2 x i32>
375 define i32 @no_red_2(i32 %max) {
376 entry:
377   br label %for.body
379 for.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], [1024 x i32]* @A, i64 0, i64 %indvars.iv
383   %arrayidx1 = getelementptr inbounds [1024 x i32], [1024 x i32]* @A, i64 1, i64 %indvars.iv
384   %0 = load i32, i32* %arrayidx, align 4
385   %1 = load i32, i32* %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
393 for.end:
394   ret i32 %max.red.0
397 ; Float tests.
399 ; Maximum.
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
408 define float @max_red_float(float %max) #0 {
409 entry:
410   br label %for.body
412 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
416   %0 = load float, float* %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
423 for.end:
424   ret float %max.red.0
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
433 define float @max_red_float_ge(float %max) #0 {
434 entry:
435   br label %for.body
437 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
441   %0 = load float, float* %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
448 for.end:
449   ret float %max.red.0
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
458 define float @inverted_max_red_float(float %max) #0 {
459 entry:
460   br label %for.body
462 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
466   %0 = load float, float* %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
473 for.end:
474   ret float %max.red.0
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
483 define float @inverted_max_red_float_le(float %max) #0 {
484 entry:
485   br label %for.body
487 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
491   %0 = load float, float* %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
498 for.end:
499   ret float %max.red.0
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
508 define float @unordered_max_red_float(float %max) #0 {
509 entry:
510   br label %for.body
512 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
516   %0 = load float, float* %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
523 for.end:
524   ret float %max.red.0
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
533 define float @unordered_max_red_float_ge(float %max) #0 {
534 entry:
535   br label %for.body
537 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
541   %0 = load float, float* %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
548 for.end:
549   ret float %max.red.0
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
558 define float @inverted_unordered_max_red_float(float %max) #0 {
559 entry:
560   br label %for.body
562 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
566   %0 = load float, float* %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
573 for.end:
574   ret float %max.red.0
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
583 define float @inverted_unordered_max_red_float_le(float %max) #0 {
584 entry:
585   br label %for.body
587 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
591   %0 = load float, float* %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
598 for.end:
599   ret float %max.red.0
602 ; Minimum.
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
611 define float @min_red_float(float %min) #0 {
612 entry:
613   br label %for.body
615 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
619   %0 = load float, float* %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
626 for.end:
627   ret float %min.red.0
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
636 define float @min_red_float_le(float %min) #0 {
637 entry:
638   br label %for.body
640 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
644   %0 = load float, float* %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
651 for.end:
652   ret float %min.red.0
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
661 define float @inverted_min_red_float(float %min) #0 {
662 entry:
663   br label %for.body
665 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
669   %0 = load float, float* %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
676 for.end:
677   ret float %min.red.0
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
686 define float @inverted_min_red_float_ge(float %min) #0 {
687 entry:
688   br label %for.body
690 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
694   %0 = load float, float* %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
701 for.end:
702   ret float %min.red.0
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
711 define float @unordered_min_red_float(float %min) #0 {
712 entry:
713   br label %for.body
715 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
719   %0 = load float, float* %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
726 for.end:
727   ret float %min.red.0
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
736 define float @unordered_min_red_float_le(float %min) #0 {
737 entry:
738   br label %for.body
740 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
744   %0 = load float, float* %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
751 for.end:
752   ret float %min.red.0
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
761 define float @inverted_unordered_min_red_float(float %min) #0 {
762 entry:
763   br label %for.body
765 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
769   %0 = load float, float* %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
776 for.end:
777   ret float %min.red.0
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
786 define float @inverted_unordered_min_red_float_ge(float %min) #0 {
787 entry:
788   br label %for.body
790 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
794   %0 = load float, float* %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
801 for.end:
802   ret float %min.red.0
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
812 define double @min_red_double(double %min) #0 {
813 entry:
814   br label %for.body
816 for.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], [1024 x double]* @dA, i64 0, i64 %indvars.iv
820   %0 = load double, double* %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
827 for.end:
828   ret double %min.red.0
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>
836 define float @max_red_float_nans(float %max) {
837 entry:
838   br label %for.body
840 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
844   %0 = load float, float* %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
851 for.end:
852   ret float %max.red.0
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>
859 define float @max_red_float_nsz(float %max) #1 {
860 entry:
861   br label %for.body
863 for.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], [1024 x float]* @fA, i64 0, i64 %indvars.iv
867   %0 = load float, float* %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
874 for.end:
875   ret float %max.red.0
878 ; Make sure any check-not directives are not triggered by function declarations.
879 ; CHECK: declare
881 attributes #0 = { "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" }
882 attributes #1 = { "no-nans-fp-math"="true" }