xref: /llvm-project/llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll (revision 61510b51c33464a6bc15e4cf5b1ee07e2e0ec1c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOFP --check-prefix=CHECK-NOFP-SD
3; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon,+fullfp16 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-FP --check-prefix=CHECK-FP-SD
4; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOFP --check-prefix=CHECK-NOFP-GI
5; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon,+fullfp16 -global-isel -global-isel-abort=2 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-FP --check-prefix=CHECK-FP-GI
6
7; CHECK-NOFP-GI:       warning: Instruction selection used fallback path for test_v11f16
8; CHECK-NOFP-GI-NEXT:  warning: Instruction selection used fallback path for test_v11f16_ninf
9; CHECK-NOFP-GI-NEXT:  warning: Instruction selection used fallback path for test_v3f32
10; CHECK-NOFP-GI-NEXT:  warning: Instruction selection used fallback path for test_v3f32_ninf
11; CHECK-NOFP-GI-NEXT:  warning: Instruction selection used fallback path for test_v2f128
12;
13; CHECK-FP-GI:       warning: Instruction selection used fallback path for test_v11f16
14; CHECK-FP-GI-NEXT:  warning: Instruction selection used fallback path for test_v11f16_ninf
15; CHECK-FP-GI-NEXT:  warning: Instruction selection used fallback path for test_v3f32
16; CHECK-FP-GI-NEXT:  warning: Instruction selection used fallback path for test_v3f32_ninf
17; CHECK-FP-GI-NEXT:  warning: Instruction selection used fallback path for test_v2f128
18
19declare half @llvm.vector.reduce.fmax.v1f16(<1 x half> %a)
20declare float @llvm.vector.reduce.fmax.v1f32(<1 x float> %a)
21declare double @llvm.vector.reduce.fmax.v1f64(<1 x double> %a)
22declare fp128 @llvm.vector.reduce.fmax.v1f128(<1 x fp128> %a)
23
24declare half @llvm.vector.reduce.fmax.v4f16(<4 x half> %a)
25declare half @llvm.vector.reduce.fmax.v8f16(<8 x half> %a)
26declare half @llvm.vector.reduce.fmax.v16f16(<16 x half> %a)
27declare float @llvm.vector.reduce.fmax.v2f32(<2 x float> %a)
28declare float @llvm.vector.reduce.fmax.v4f32(<4 x float> %a)
29declare float @llvm.vector.reduce.fmax.v8f32(<8 x float> %a)
30declare float @llvm.vector.reduce.fmax.v16f32(<16 x float> %a)
31declare double @llvm.vector.reduce.fmax.v2f64(<2 x double> %a)
32declare double @llvm.vector.reduce.fmax.v4f64(<4 x double> %a)
33
34declare half @llvm.vector.reduce.fmax.v11f16(<11 x half> %a)
35declare float @llvm.vector.reduce.fmax.v3f32(<3 x float> %a)
36declare fp128 @llvm.vector.reduce.fmax.v2f128(<2 x fp128> %a)
37
38define half @test_v1f16(<1 x half> %a) nounwind {
39; CHECK-LABEL: test_v1f16:
40; CHECK:       // %bb.0:
41; CHECK-NEXT:    ret
42  %b = call nnan half @llvm.vector.reduce.fmax.v1f16(<1 x half> %a)
43  ret half %b
44}
45
46define float @test_v1f32(<1 x float> %a) nounwind {
47; CHECK-NOFP-SD-LABEL: test_v1f32:
48; CHECK-NOFP-SD:       // %bb.0:
49; CHECK-NOFP-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
50; CHECK-NOFP-SD-NEXT:    // kill: def $s0 killed $s0 killed $q0
51; CHECK-NOFP-SD-NEXT:    ret
52;
53; CHECK-FP-SD-LABEL: test_v1f32:
54; CHECK-FP-SD:       // %bb.0:
55; CHECK-FP-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
56; CHECK-FP-SD-NEXT:    // kill: def $s0 killed $s0 killed $q0
57; CHECK-FP-SD-NEXT:    ret
58;
59; CHECK-NOFP-GI-LABEL: test_v1f32:
60; CHECK-NOFP-GI:       // %bb.0:
61; CHECK-NOFP-GI-NEXT:    // kill: def $s0 killed $s0 killed $d0
62; CHECK-NOFP-GI-NEXT:    ret
63;
64; CHECK-FP-GI-LABEL: test_v1f32:
65; CHECK-FP-GI:       // %bb.0:
66; CHECK-FP-GI-NEXT:    // kill: def $s0 killed $s0 killed $d0
67; CHECK-FP-GI-NEXT:    ret
68  %b = call nnan float @llvm.vector.reduce.fmax.v1f32(<1 x float> %a)
69  ret float %b
70}
71
72define double @test_v1f64(<1 x double> %a) nounwind {
73; CHECK-LABEL: test_v1f64:
74; CHECK:       // %bb.0:
75; CHECK-NEXT:    ret
76  %b = call nnan double @llvm.vector.reduce.fmax.v1f64(<1 x double> %a)
77  ret double %b
78}
79
80define fp128 @test_v1f128(<1 x fp128> %a) nounwind {
81; CHECK-LABEL: test_v1f128:
82; CHECK:       // %bb.0:
83; CHECK-NEXT:    ret
84  %b = call nnan fp128 @llvm.vector.reduce.fmax.v1f128(<1 x fp128> %a)
85  ret fp128 %b
86}
87
88define half @test_v4f16(<4 x half> %a) nounwind {
89; CHECK-NOFP-SD-LABEL: test_v4f16:
90; CHECK-NOFP-SD:       // %bb.0:
91; CHECK-NOFP-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
92; CHECK-NOFP-SD-NEXT:    mov h1, v0.h[1]
93; CHECK-NOFP-SD-NEXT:    fcvt s2, h0
94; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
95; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s2, s1
96; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[2]
97; CHECK-NOFP-SD-NEXT:    mov h0, v0.h[3]
98; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
99; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
100; CHECK-NOFP-SD-NEXT:    fcvt s0, h0
101; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
102; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
103; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
104; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
105; CHECK-NOFP-SD-NEXT:    fmaxnm s0, s1, s0
106; CHECK-NOFP-SD-NEXT:    fcvt h0, s0
107; CHECK-NOFP-SD-NEXT:    ret
108;
109; CHECK-FP-LABEL: test_v4f16:
110; CHECK-FP:       // %bb.0:
111; CHECK-FP-NEXT:    fmaxnmv h0, v0.4h
112; CHECK-FP-NEXT:    ret
113;
114; CHECK-NOFP-GI-LABEL: test_v4f16:
115; CHECK-NOFP-GI:       // %bb.0:
116; CHECK-NOFP-GI-NEXT:    fcvtl v0.4s, v0.4h
117; CHECK-NOFP-GI-NEXT:    fmaxnmv s0, v0.4s
118; CHECK-NOFP-GI-NEXT:    fcvt h0, s0
119; CHECK-NOFP-GI-NEXT:    ret
120  %b = call nnan half @llvm.vector.reduce.fmax.v4f16(<4 x half> %a)
121  ret half %b
122}
123
124define half @test_v4f16_ninf(<4 x half> %a) nounwind {
125; CHECK-NOFP-SD-LABEL: test_v4f16_ninf:
126; CHECK-NOFP-SD:       // %bb.0:
127; CHECK-NOFP-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
128; CHECK-NOFP-SD-NEXT:    mov h1, v0.h[1]
129; CHECK-NOFP-SD-NEXT:    fcvt s2, h0
130; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
131; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s2, s1
132; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[2]
133; CHECK-NOFP-SD-NEXT:    mov h0, v0.h[3]
134; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
135; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
136; CHECK-NOFP-SD-NEXT:    fcvt s0, h0
137; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
138; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
139; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
140; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
141; CHECK-NOFP-SD-NEXT:    fmaxnm s0, s1, s0
142; CHECK-NOFP-SD-NEXT:    fcvt h0, s0
143; CHECK-NOFP-SD-NEXT:    ret
144;
145; CHECK-FP-LABEL: test_v4f16_ninf:
146; CHECK-FP:       // %bb.0:
147; CHECK-FP-NEXT:    fmaxnmv h0, v0.4h
148; CHECK-FP-NEXT:    ret
149;
150; CHECK-NOFP-GI-LABEL: test_v4f16_ninf:
151; CHECK-NOFP-GI:       // %bb.0:
152; CHECK-NOFP-GI-NEXT:    fcvtl v0.4s, v0.4h
153; CHECK-NOFP-GI-NEXT:    fmaxnmv s0, v0.4s
154; CHECK-NOFP-GI-NEXT:    fcvt h0, s0
155; CHECK-NOFP-GI-NEXT:    ret
156  %b = call nnan ninf half @llvm.vector.reduce.fmax.v4f16(<4 x half> %a)
157  ret half %b
158}
159
160define half @test_v8f16(<8 x half> %a) nounwind {
161; CHECK-NOFP-SD-LABEL: test_v8f16:
162; CHECK-NOFP-SD:       // %bb.0:
163; CHECK-NOFP-SD-NEXT:    mov h1, v0.h[1]
164; CHECK-NOFP-SD-NEXT:    fcvt s2, h0
165; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
166; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s2, s1
167; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[2]
168; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
169; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
170; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
171; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
172; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[3]
173; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
174; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
175; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
176; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
177; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[4]
178; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
179; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
180; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
181; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
182; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[5]
183; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
184; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
185; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
186; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
187; CHECK-NOFP-SD-NEXT:    mov h2, v0.h[6]
188; CHECK-NOFP-SD-NEXT:    mov h0, v0.h[7]
189; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
190; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
191; CHECK-NOFP-SD-NEXT:    fcvt s0, h0
192; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
193; CHECK-NOFP-SD-NEXT:    fmaxnm s1, s1, s2
194; CHECK-NOFP-SD-NEXT:    fcvt h1, s1
195; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
196; CHECK-NOFP-SD-NEXT:    fmaxnm s0, s1, s0
197; CHECK-NOFP-SD-NEXT:    fcvt h0, s0
198; CHECK-NOFP-SD-NEXT:    ret
199;
200; CHECK-FP-LABEL: test_v8f16:
201; CHECK-FP:       // %bb.0:
202; CHECK-FP-NEXT:    fmaxnmv h0, v0.8h
203; CHECK-FP-NEXT:    ret
204;
205; CHECK-NOFP-GI-LABEL: test_v8f16:
206; CHECK-NOFP-GI:       // %bb.0:
207; CHECK-NOFP-GI-NEXT:    fcvtl v1.4s, v0.4h
208; CHECK-NOFP-GI-NEXT:    fcvtl2 v0.4s, v0.8h
209; CHECK-NOFP-GI-NEXT:    fmaxnm v0.4s, v1.4s, v0.4s
210; CHECK-NOFP-GI-NEXT:    fmaxnmv s0, v0.4s
211; CHECK-NOFP-GI-NEXT:    fcvt h0, s0
212; CHECK-NOFP-GI-NEXT:    ret
213  %b = call nnan half @llvm.vector.reduce.fmax.v8f16(<8 x half> %a)
214  ret half %b
215}
216
217define half @test_v16f16(<16 x half> %a) nounwind {
218; CHECK-NOFP-SD-LABEL: test_v16f16:
219; CHECK-NOFP-SD:       // %bb.0:
220; CHECK-NOFP-SD-NEXT:    mov h2, v1.h[1]
221; CHECK-NOFP-SD-NEXT:    mov h3, v0.h[1]
222; CHECK-NOFP-SD-NEXT:    fcvt s4, h1
223; CHECK-NOFP-SD-NEXT:    fcvt s5, h0
224; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
225; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
226; CHECK-NOFP-SD-NEXT:    fmaxnm s4, s5, s4
227; CHECK-NOFP-SD-NEXT:    mov h5, v0.h[2]
228; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s3, s2
229; CHECK-NOFP-SD-NEXT:    mov h3, v1.h[2]
230; CHECK-NOFP-SD-NEXT:    fcvt h4, s4
231; CHECK-NOFP-SD-NEXT:    fcvt s5, h5
232; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
233; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
234; CHECK-NOFP-SD-NEXT:    fcvt s4, h4
235; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
236; CHECK-NOFP-SD-NEXT:    fmaxnm s3, s5, s3
237; CHECK-NOFP-SD-NEXT:    mov h5, v0.h[3]
238; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s4, s2
239; CHECK-NOFP-SD-NEXT:    mov h4, v1.h[3]
240; CHECK-NOFP-SD-NEXT:    fcvt h3, s3
241; CHECK-NOFP-SD-NEXT:    fcvt s5, h5
242; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
243; CHECK-NOFP-SD-NEXT:    fcvt s4, h4
244; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
245; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
246; CHECK-NOFP-SD-NEXT:    fmaxnm s4, s5, s4
247; CHECK-NOFP-SD-NEXT:    mov h5, v0.h[4]
248; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s2, s3
249; CHECK-NOFP-SD-NEXT:    mov h3, v1.h[4]
250; CHECK-NOFP-SD-NEXT:    fcvt h4, s4
251; CHECK-NOFP-SD-NEXT:    fcvt s5, h5
252; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
253; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
254; CHECK-NOFP-SD-NEXT:    fcvt s4, h4
255; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
256; CHECK-NOFP-SD-NEXT:    fmaxnm s3, s5, s3
257; CHECK-NOFP-SD-NEXT:    mov h5, v0.h[5]
258; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s2, s4
259; CHECK-NOFP-SD-NEXT:    mov h4, v1.h[5]
260; CHECK-NOFP-SD-NEXT:    fcvt h3, s3
261; CHECK-NOFP-SD-NEXT:    fcvt s5, h5
262; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
263; CHECK-NOFP-SD-NEXT:    fcvt s4, h4
264; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
265; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
266; CHECK-NOFP-SD-NEXT:    fmaxnm s4, s5, s4
267; CHECK-NOFP-SD-NEXT:    mov h5, v0.h[6]
268; CHECK-NOFP-SD-NEXT:    mov h0, v0.h[7]
269; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s2, s3
270; CHECK-NOFP-SD-NEXT:    fcvt h3, s4
271; CHECK-NOFP-SD-NEXT:    mov h4, v1.h[6]
272; CHECK-NOFP-SD-NEXT:    fcvt s5, h5
273; CHECK-NOFP-SD-NEXT:    mov h1, v1.h[7]
274; CHECK-NOFP-SD-NEXT:    fcvt s0, h0
275; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
276; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
277; CHECK-NOFP-SD-NEXT:    fcvt s4, h4
278; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
279; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
280; CHECK-NOFP-SD-NEXT:    fmaxnm s0, s0, s1
281; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s2, s3
282; CHECK-NOFP-SD-NEXT:    fmaxnm s3, s5, s4
283; CHECK-NOFP-SD-NEXT:    fcvt h0, s0
284; CHECK-NOFP-SD-NEXT:    fcvt h2, s2
285; CHECK-NOFP-SD-NEXT:    fcvt h3, s3
286; CHECK-NOFP-SD-NEXT:    fcvt s0, h0
287; CHECK-NOFP-SD-NEXT:    fcvt s2, h2
288; CHECK-NOFP-SD-NEXT:    fcvt s3, h3
289; CHECK-NOFP-SD-NEXT:    fmaxnm s2, s2, s3
290; CHECK-NOFP-SD-NEXT:    fcvt h1, s2
291; CHECK-NOFP-SD-NEXT:    fcvt s1, h1
292; CHECK-NOFP-SD-NEXT:    fmaxnm s0, s1, s0
293; CHECK-NOFP-SD-NEXT:    fcvt h0, s0
294; CHECK-NOFP-SD-NEXT:    ret
295;
296; CHECK-FP-LABEL: test_v16f16:
297; CHECK-FP:       // %bb.0:
298; CHECK-FP-NEXT:    fmaxnm v0.8h, v0.8h, v1.8h
299; CHECK-FP-NEXT:    fmaxnmv h0, v0.8h
300; CHECK-FP-NEXT:    ret
301;
302; CHECK-NOFP-GI-LABEL: test_v16f16:
303; CHECK-NOFP-GI:       // %bb.0:
304; CHECK-NOFP-GI-NEXT:    fcvtl v2.4s, v0.4h
305; CHECK-NOFP-GI-NEXT:    fcvtl2 v0.4s, v0.8h
306; CHECK-NOFP-GI-NEXT:    fcvtl v3.4s, v1.4h
307; CHECK-NOFP-GI-NEXT:    fcvtl2 v1.4s, v1.8h
308; CHECK-NOFP-GI-NEXT:    fmaxnm v0.4s, v2.4s, v0.4s
309; CHECK-NOFP-GI-NEXT:    fmaxnm v1.4s, v3.4s, v1.4s
310; CHECK-NOFP-GI-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
311; CHECK-NOFP-GI-NEXT:    fmaxnmv s0, v0.4s
312; CHECK-NOFP-GI-NEXT:    fcvt h0, s0
313; CHECK-NOFP-GI-NEXT:    ret
314  %b = call nnan half @llvm.vector.reduce.fmax.v16f16(<16 x half> %a)
315  ret half %b
316}
317
318define float @test_v2f32(<2 x float> %a) nounwind {
319; CHECK-LABEL: test_v2f32:
320; CHECK:       // %bb.0:
321; CHECK-NEXT:    fmaxnmp s0, v0.2s
322; CHECK-NEXT:    ret
323  %b = call nnan float @llvm.vector.reduce.fmax.v2f32(<2 x float> %a)
324  ret float %b
325}
326
327define float @test_v4f32(<4 x float> %a) nounwind {
328; CHECK-LABEL: test_v4f32:
329; CHECK:       // %bb.0:
330; CHECK-NEXT:    fmaxnmv s0, v0.4s
331; CHECK-NEXT:    ret
332  %b = call nnan float @llvm.vector.reduce.fmax.v4f32(<4 x float> %a)
333  ret float %b
334}
335
336define float @test_v8f32(<8 x float> %a) nounwind {
337; CHECK-LABEL: test_v8f32:
338; CHECK:       // %bb.0:
339; CHECK-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
340; CHECK-NEXT:    fmaxnmv s0, v0.4s
341; CHECK-NEXT:    ret
342  %b = call nnan float @llvm.vector.reduce.fmax.v8f32(<8 x float> %a)
343  ret float %b
344}
345
346define float @test_v16f32(<16 x float> %a) nounwind {
347; CHECK-NOFP-SD-LABEL: test_v16f32:
348; CHECK-NOFP-SD:       // %bb.0:
349; CHECK-NOFP-SD-NEXT:    fmaxnm v1.4s, v1.4s, v3.4s
350; CHECK-NOFP-SD-NEXT:    fmaxnm v0.4s, v0.4s, v2.4s
351; CHECK-NOFP-SD-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
352; CHECK-NOFP-SD-NEXT:    fmaxnmv s0, v0.4s
353; CHECK-NOFP-SD-NEXT:    ret
354;
355; CHECK-FP-SD-LABEL: test_v16f32:
356; CHECK-FP-SD:       // %bb.0:
357; CHECK-FP-SD-NEXT:    fmaxnm v1.4s, v1.4s, v3.4s
358; CHECK-FP-SD-NEXT:    fmaxnm v0.4s, v0.4s, v2.4s
359; CHECK-FP-SD-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
360; CHECK-FP-SD-NEXT:    fmaxnmv s0, v0.4s
361; CHECK-FP-SD-NEXT:    ret
362;
363; CHECK-NOFP-GI-LABEL: test_v16f32:
364; CHECK-NOFP-GI:       // %bb.0:
365; CHECK-NOFP-GI-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
366; CHECK-NOFP-GI-NEXT:    fmaxnm v1.4s, v2.4s, v3.4s
367; CHECK-NOFP-GI-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
368; CHECK-NOFP-GI-NEXT:    fmaxnmv s0, v0.4s
369; CHECK-NOFP-GI-NEXT:    ret
370;
371; CHECK-FP-GI-LABEL: test_v16f32:
372; CHECK-FP-GI:       // %bb.0:
373; CHECK-FP-GI-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
374; CHECK-FP-GI-NEXT:    fmaxnm v1.4s, v2.4s, v3.4s
375; CHECK-FP-GI-NEXT:    fmaxnm v0.4s, v0.4s, v1.4s
376; CHECK-FP-GI-NEXT:    fmaxnmv s0, v0.4s
377; CHECK-FP-GI-NEXT:    ret
378  %b = call nnan float @llvm.vector.reduce.fmax.v16f32(<16 x float> %a)
379  ret float %b
380}
381
382define double @test_v2f64(<2 x double> %a) nounwind {
383; CHECK-LABEL: test_v2f64:
384; CHECK:       // %bb.0:
385; CHECK-NEXT:    fmaxnmp d0, v0.2d
386; CHECK-NEXT:    ret
387  %b = call double @llvm.vector.reduce.fmax.v2f64(<2 x double> %a)
388  ret double %b
389}
390
391define double @test_v4f64(<4 x double> %a) nounwind {
392; CHECK-LABEL: test_v4f64:
393; CHECK:       // %bb.0:
394; CHECK-NEXT:    fmaxnm v0.2d, v0.2d, v1.2d
395; CHECK-NEXT:    fmaxnmp d0, v0.2d
396; CHECK-NEXT:    ret
397  %b = call double @llvm.vector.reduce.fmax.v4f64(<4 x double> %a)
398  ret double %b
399}
400
401define half @test_v11f16(<11 x half> %a) nounwind {
402; CHECK-NOFP-LABEL: test_v11f16:
403; CHECK-NOFP:       // %bb.0:
404; CHECK-NOFP-NEXT:    ldr h16, [sp, #8]
405; CHECK-NOFP-NEXT:    ldr h17, [sp]
406; CHECK-NOFP-NEXT:    fcvt s1, h1
407; CHECK-NOFP-NEXT:    fcvt s0, h0
408; CHECK-NOFP-NEXT:    fcvt s2, h2
409; CHECK-NOFP-NEXT:    fcvt s16, h16
410; CHECK-NOFP-NEXT:    fcvt s17, h17
411; CHECK-NOFP-NEXT:    fmaxnm s1, s1, s16
412; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s17
413; CHECK-NOFP-NEXT:    ldr h16, [sp, #16]
414; CHECK-NOFP-NEXT:    fcvt s16, h16
415; CHECK-NOFP-NEXT:    fcvt h1, s1
416; CHECK-NOFP-NEXT:    fcvt h0, s0
417; CHECK-NOFP-NEXT:    fcvt s1, h1
418; CHECK-NOFP-NEXT:    fcvt s0, h0
419; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
420; CHECK-NOFP-NEXT:    fmaxnm s1, s2, s16
421; CHECK-NOFP-NEXT:    fcvt h0, s0
422; CHECK-NOFP-NEXT:    fcvt h1, s1
423; CHECK-NOFP-NEXT:    fcvt s0, h0
424; CHECK-NOFP-NEXT:    fcvt s1, h1
425; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
426; CHECK-NOFP-NEXT:    fcvt s1, h3
427; CHECK-NOFP-NEXT:    fcvt h0, s0
428; CHECK-NOFP-NEXT:    fcvt s0, h0
429; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
430; CHECK-NOFP-NEXT:    fcvt s1, h4
431; CHECK-NOFP-NEXT:    fcvt h0, s0
432; CHECK-NOFP-NEXT:    fcvt s0, h0
433; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
434; CHECK-NOFP-NEXT:    fcvt s1, h5
435; CHECK-NOFP-NEXT:    fcvt h0, s0
436; CHECK-NOFP-NEXT:    fcvt s0, h0
437; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
438; CHECK-NOFP-NEXT:    fcvt s1, h6
439; CHECK-NOFP-NEXT:    fcvt h0, s0
440; CHECK-NOFP-NEXT:    fcvt s0, h0
441; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
442; CHECK-NOFP-NEXT:    fcvt s1, h7
443; CHECK-NOFP-NEXT:    fcvt h0, s0
444; CHECK-NOFP-NEXT:    fcvt s0, h0
445; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
446; CHECK-NOFP-NEXT:    fcvt h0, s0
447; CHECK-NOFP-NEXT:    ret
448;
449; CHECK-FP-LABEL: test_v11f16:
450; CHECK-FP:       // %bb.0:
451; CHECK-FP-NEXT:    // kill: def $h0 killed $h0 def $q0
452; CHECK-FP-NEXT:    // kill: def $h1 killed $h1 def $q1
453; CHECK-FP-NEXT:    // kill: def $h2 killed $h2 def $q2
454; CHECK-FP-NEXT:    // kill: def $h3 killed $h3 def $q3
455; CHECK-FP-NEXT:    // kill: def $h4 killed $h4 def $q4
456; CHECK-FP-NEXT:    // kill: def $h5 killed $h5 def $q5
457; CHECK-FP-NEXT:    mov x8, sp
458; CHECK-FP-NEXT:    // kill: def $h6 killed $h6 def $q6
459; CHECK-FP-NEXT:    // kill: def $h7 killed $h7 def $q7
460; CHECK-FP-NEXT:    mov v0.h[1], v1.h[0]
461; CHECK-FP-NEXT:    movi v1.8h, #252, lsl #8
462; CHECK-FP-NEXT:    mov v0.h[2], v2.h[0]
463; CHECK-FP-NEXT:    ld1 { v1.h }[0], [x8]
464; CHECK-FP-NEXT:    add x8, sp, #8
465; CHECK-FP-NEXT:    ld1 { v1.h }[1], [x8]
466; CHECK-FP-NEXT:    add x8, sp, #16
467; CHECK-FP-NEXT:    mov v0.h[3], v3.h[0]
468; CHECK-FP-NEXT:    ld1 { v1.h }[2], [x8]
469; CHECK-FP-NEXT:    mov v0.h[4], v4.h[0]
470; CHECK-FP-NEXT:    mov v0.h[5], v5.h[0]
471; CHECK-FP-NEXT:    mov v0.h[6], v6.h[0]
472; CHECK-FP-NEXT:    mov v0.h[7], v7.h[0]
473; CHECK-FP-NEXT:    fmaxnm v0.8h, v0.8h, v1.8h
474; CHECK-FP-NEXT:    fmaxnmv h0, v0.8h
475; CHECK-FP-NEXT:    ret
476  %b = call nnan half @llvm.vector.reduce.fmax.v11f16(<11 x half> %a)
477  ret half %b
478}
479
480define half @test_v11f16_ninf(<11 x half> %a) nounwind {
481; CHECK-NOFP-LABEL: test_v11f16_ninf:
482; CHECK-NOFP:       // %bb.0:
483; CHECK-NOFP-NEXT:    ldr h16, [sp, #8]
484; CHECK-NOFP-NEXT:    ldr h17, [sp]
485; CHECK-NOFP-NEXT:    fcvt s1, h1
486; CHECK-NOFP-NEXT:    fcvt s0, h0
487; CHECK-NOFP-NEXT:    fcvt s2, h2
488; CHECK-NOFP-NEXT:    fcvt s16, h16
489; CHECK-NOFP-NEXT:    fcvt s17, h17
490; CHECK-NOFP-NEXT:    fmaxnm s1, s1, s16
491; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s17
492; CHECK-NOFP-NEXT:    ldr h16, [sp, #16]
493; CHECK-NOFP-NEXT:    fcvt s16, h16
494; CHECK-NOFP-NEXT:    fcvt h1, s1
495; CHECK-NOFP-NEXT:    fcvt h0, s0
496; CHECK-NOFP-NEXT:    fcvt s1, h1
497; CHECK-NOFP-NEXT:    fcvt s0, h0
498; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
499; CHECK-NOFP-NEXT:    fmaxnm s1, s2, s16
500; CHECK-NOFP-NEXT:    fcvt h0, s0
501; CHECK-NOFP-NEXT:    fcvt h1, s1
502; CHECK-NOFP-NEXT:    fcvt s0, h0
503; CHECK-NOFP-NEXT:    fcvt s1, h1
504; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
505; CHECK-NOFP-NEXT:    fcvt s1, h3
506; CHECK-NOFP-NEXT:    fcvt h0, s0
507; CHECK-NOFP-NEXT:    fcvt s0, h0
508; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
509; CHECK-NOFP-NEXT:    fcvt s1, h4
510; CHECK-NOFP-NEXT:    fcvt h0, s0
511; CHECK-NOFP-NEXT:    fcvt s0, h0
512; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
513; CHECK-NOFP-NEXT:    fcvt s1, h5
514; CHECK-NOFP-NEXT:    fcvt h0, s0
515; CHECK-NOFP-NEXT:    fcvt s0, h0
516; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
517; CHECK-NOFP-NEXT:    fcvt s1, h6
518; CHECK-NOFP-NEXT:    fcvt h0, s0
519; CHECK-NOFP-NEXT:    fcvt s0, h0
520; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
521; CHECK-NOFP-NEXT:    fcvt s1, h7
522; CHECK-NOFP-NEXT:    fcvt h0, s0
523; CHECK-NOFP-NEXT:    fcvt s0, h0
524; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
525; CHECK-NOFP-NEXT:    fcvt h0, s0
526; CHECK-NOFP-NEXT:    ret
527;
528; CHECK-FP-LABEL: test_v11f16_ninf:
529; CHECK-FP:       // %bb.0:
530; CHECK-FP-NEXT:    // kill: def $h0 killed $h0 def $q0
531; CHECK-FP-NEXT:    // kill: def $h1 killed $h1 def $q1
532; CHECK-FP-NEXT:    // kill: def $h2 killed $h2 def $q2
533; CHECK-FP-NEXT:    // kill: def $h3 killed $h3 def $q3
534; CHECK-FP-NEXT:    // kill: def $h4 killed $h4 def $q4
535; CHECK-FP-NEXT:    // kill: def $h5 killed $h5 def $q5
536; CHECK-FP-NEXT:    mov x8, sp
537; CHECK-FP-NEXT:    // kill: def $h6 killed $h6 def $q6
538; CHECK-FP-NEXT:    // kill: def $h7 killed $h7 def $q7
539; CHECK-FP-NEXT:    mov v0.h[1], v1.h[0]
540; CHECK-FP-NEXT:    mvni v1.8h, #4, lsl #8
541; CHECK-FP-NEXT:    ld1 { v1.h }[0], [x8]
542; CHECK-FP-NEXT:    add x8, sp, #8
543; CHECK-FP-NEXT:    mov v0.h[2], v2.h[0]
544; CHECK-FP-NEXT:    ld1 { v1.h }[1], [x8]
545; CHECK-FP-NEXT:    add x8, sp, #16
546; CHECK-FP-NEXT:    mov v0.h[3], v3.h[0]
547; CHECK-FP-NEXT:    ld1 { v1.h }[2], [x8]
548; CHECK-FP-NEXT:    mov v0.h[4], v4.h[0]
549; CHECK-FP-NEXT:    mov v0.h[5], v5.h[0]
550; CHECK-FP-NEXT:    mov v0.h[6], v6.h[0]
551; CHECK-FP-NEXT:    mov v0.h[7], v7.h[0]
552; CHECK-FP-NEXT:    fmaxnm v0.8h, v0.8h, v1.8h
553; CHECK-FP-NEXT:    fmaxnmv h0, v0.8h
554; CHECK-FP-NEXT:    ret
555  %b = call nnan ninf half @llvm.vector.reduce.fmax.v11f16(<11 x half> %a)
556  ret half %b
557}
558
559define float @test_v3f32(<3 x float> %a) nounwind {
560; CHECK-LABEL: test_v3f32:
561; CHECK:       // %bb.0:
562; CHECK-NEXT:    mov w8, #-8388608 // =0xff800000
563; CHECK-NEXT:    fmov s1, w8
564; CHECK-NEXT:    mov v0.s[3], v1.s[0]
565; CHECK-NEXT:    fmaxnmv s0, v0.4s
566; CHECK-NEXT:    ret
567  %b = call nnan float @llvm.vector.reduce.fmax.v3f32(<3 x float> %a)
568  ret float %b
569}
570
571define float @test_v3f32_ninf(<3 x float> %a) nounwind {
572; CHECK-LABEL: test_v3f32_ninf:
573; CHECK:       // %bb.0:
574; CHECK-NEXT:    mov w8, #-8388609 // =0xff7fffff
575; CHECK-NEXT:    fmov s1, w8
576; CHECK-NEXT:    mov v0.s[3], v1.s[0]
577; CHECK-NEXT:    fmaxnmv s0, v0.4s
578; CHECK-NEXT:    ret
579  %b = call nnan ninf float @llvm.vector.reduce.fmax.v3f32(<3 x float> %a)
580  ret float %b
581}
582
583define fp128 @test_v2f128(<2 x fp128> %a) nounwind {
584; CHECK-LABEL: test_v2f128:
585; CHECK:       // %bb.0:
586; CHECK-NEXT:    sub sp, sp, #48
587; CHECK-NEXT:    str x30, [sp, #32] // 8-byte Folded Spill
588; CHECK-NEXT:    stp q0, q1, [sp] // 32-byte Folded Spill
589; CHECK-NEXT:    bl __gttf2
590; CHECK-NEXT:    ldr q0, [sp, #16] // 16-byte Folded Reload
591; CHECK-NEXT:    cmp w0, #0
592; CHECK-NEXT:    b.le .LBB18_2
593; CHECK-NEXT:  // %bb.1:
594; CHECK-NEXT:    ldr q0, [sp] // 16-byte Folded Reload
595; CHECK-NEXT:  .LBB18_2:
596; CHECK-NEXT:    ldr x30, [sp, #32] // 8-byte Folded Reload
597; CHECK-NEXT:    add sp, sp, #48
598; CHECK-NEXT:    ret
599  %b = call nnan fp128 @llvm.vector.reduce.fmax.v2f128(<2 x fp128> %a)
600  ret fp128 %b
601}
602