xref: /llvm-project/llvm/test/CodeGen/AArch64/vecreduce-umax-legalization.ll (revision 7ece560a50d09686bb384b309b8b05d8f63111e5)
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-prefixes=CHECK,CHECK-SD
3; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
4
5declare i1 @llvm.vector.reduce.umax.v1i1(<1 x i1> %a)
6declare i8 @llvm.vector.reduce.umax.v1i8(<1 x i8> %a)
7declare i16 @llvm.vector.reduce.umax.v1i16(<1 x i16> %a)
8declare i24 @llvm.vector.reduce.umax.v1i24(<1 x i24> %a)
9declare i32 @llvm.vector.reduce.umax.v1i32(<1 x i32> %a)
10declare i64 @llvm.vector.reduce.umax.v1i64(<1 x i64> %a)
11declare i128 @llvm.vector.reduce.umax.v1i128(<1 x i128> %a)
12
13declare i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> %a)
14declare i8 @llvm.vector.reduce.umax.v3i8(<3 x i8> %a)
15declare i8 @llvm.vector.reduce.umax.v9i8(<9 x i8> %a)
16declare i32 @llvm.vector.reduce.umax.v3i32(<3 x i32> %a)
17declare i1 @llvm.vector.reduce.umax.v4i1(<4 x i1> %a)
18declare i24 @llvm.vector.reduce.umax.v4i24(<4 x i24> %a)
19declare i128 @llvm.vector.reduce.umax.v2i128(<2 x i128> %a)
20declare i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> %a)
21
22define i1 @test_v1i1(<1 x i1> %a) nounwind {
23; CHECK-LABEL: test_v1i1:
24; CHECK:       // %bb.0:
25; CHECK-NEXT:    and w0, w0, #0x1
26; CHECK-NEXT:    ret
27  %b = call i1 @llvm.vector.reduce.umax.v1i1(<1 x i1> %a)
28  ret i1 %b
29}
30
31define i8 @test_v1i8(<1 x i8> %a) nounwind {
32; CHECK-LABEL: test_v1i8:
33; CHECK:       // %bb.0:
34; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
35; CHECK-NEXT:    umov w0, v0.b[0]
36; CHECK-NEXT:    ret
37  %b = call i8 @llvm.vector.reduce.umax.v1i8(<1 x i8> %a)
38  ret i8 %b
39}
40
41define i16 @test_v1i16(<1 x i16> %a) nounwind {
42; CHECK-LABEL: test_v1i16:
43; CHECK:       // %bb.0:
44; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
45; CHECK-NEXT:    umov w0, v0.h[0]
46; CHECK-NEXT:    ret
47  %b = call i16 @llvm.vector.reduce.umax.v1i16(<1 x i16> %a)
48  ret i16 %b
49}
50
51define i24 @test_v1i24(<1 x i24> %a) nounwind {
52; CHECK-LABEL: test_v1i24:
53; CHECK:       // %bb.0:
54; CHECK-NEXT:    ret
55  %b = call i24 @llvm.vector.reduce.umax.v1i24(<1 x i24> %a)
56  ret i24 %b
57}
58
59define i32 @test_v1i32(<1 x i32> %a) nounwind {
60; CHECK-SD-LABEL: test_v1i32:
61; CHECK-SD:       // %bb.0:
62; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
63; CHECK-SD-NEXT:    fmov w0, s0
64; CHECK-SD-NEXT:    ret
65;
66; CHECK-GI-LABEL: test_v1i32:
67; CHECK-GI:       // %bb.0:
68; CHECK-GI-NEXT:    fmov w0, s0
69; CHECK-GI-NEXT:    ret
70  %b = call i32 @llvm.vector.reduce.umax.v1i32(<1 x i32> %a)
71  ret i32 %b
72}
73
74define i64 @test_v1i64(<1 x i64> %a) nounwind {
75; CHECK-SD-LABEL: test_v1i64:
76; CHECK-SD:       // %bb.0:
77; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
78; CHECK-SD-NEXT:    fmov x0, d0
79; CHECK-SD-NEXT:    ret
80;
81; CHECK-GI-LABEL: test_v1i64:
82; CHECK-GI:       // %bb.0:
83; CHECK-GI-NEXT:    fmov x0, d0
84; CHECK-GI-NEXT:    ret
85  %b = call i64 @llvm.vector.reduce.umax.v1i64(<1 x i64> %a)
86  ret i64 %b
87}
88
89define i128 @test_v1i128(<1 x i128> %a) nounwind {
90; CHECK-LABEL: test_v1i128:
91; CHECK:       // %bb.0:
92; CHECK-NEXT:    ret
93  %b = call i128 @llvm.vector.reduce.umax.v1i128(<1 x i128> %a)
94  ret i128 %b
95}
96
97; No i64 vector support for UMAX.
98define i64 @test_v2i64(<2 x i64> %a) nounwind {
99; CHECK-SD-LABEL: test_v2i64:
100; CHECK-SD:       // %bb.0:
101; CHECK-SD-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
102; CHECK-SD-NEXT:    cmhi d2, d0, d1
103; CHECK-SD-NEXT:    bif v0.8b, v1.8b, v2.8b
104; CHECK-SD-NEXT:    fmov x0, d0
105; CHECK-SD-NEXT:    ret
106;
107; CHECK-GI-LABEL: test_v2i64:
108; CHECK-GI:       // %bb.0:
109; CHECK-GI-NEXT:    mov d1, v0.d[1]
110; CHECK-GI-NEXT:    fmov x8, d0
111; CHECK-GI-NEXT:    fmov x9, d1
112; CHECK-GI-NEXT:    cmp x8, x9
113; CHECK-GI-NEXT:    fcsel d0, d0, d1, hi
114; CHECK-GI-NEXT:    fmov x0, d0
115; CHECK-GI-NEXT:    ret
116  %b = call i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> %a)
117  ret i64 %b
118}
119
120define i8 @test_v3i8(<3 x i8> %a) nounwind {
121; CHECK-SD-LABEL: test_v3i8:
122; CHECK-SD:       // %bb.0:
123; CHECK-SD-NEXT:    movi v0.2d, #0000000000000000
124; CHECK-SD-NEXT:    mov v0.h[0], w0
125; CHECK-SD-NEXT:    mov v0.h[1], w1
126; CHECK-SD-NEXT:    mov v0.h[2], w2
127; CHECK-SD-NEXT:    bic v0.4h, #255, lsl #8
128; CHECK-SD-NEXT:    umaxv h0, v0.4h
129; CHECK-SD-NEXT:    fmov w0, s0
130; CHECK-SD-NEXT:    ret
131;
132; CHECK-GI-LABEL: test_v3i8:
133; CHECK-GI:       // %bb.0:
134; CHECK-GI-NEXT:    and w8, w0, #0xff
135; CHECK-GI-NEXT:    cmp w8, w1, uxtb
136; CHECK-GI-NEXT:    csel w8, w0, w1, hi
137; CHECK-GI-NEXT:    and w9, w8, #0xff
138; CHECK-GI-NEXT:    cmp w9, w2, uxtb
139; CHECK-GI-NEXT:    csel w0, w8, w2, hi
140; CHECK-GI-NEXT:    ret
141  %b = call i8 @llvm.vector.reduce.umax.v3i8(<3 x i8> %a)
142  ret i8 %b
143}
144
145define i8 @test_v9i8(<9 x i8> %a) nounwind {
146; CHECK-SD-LABEL: test_v9i8:
147; CHECK-SD:       // %bb.0:
148; CHECK-SD-NEXT:    adrp x8, .LCPI9_0
149; CHECK-SD-NEXT:    ldr q1, [x8, :lo12:.LCPI9_0]
150; CHECK-SD-NEXT:    and v0.16b, v0.16b, v1.16b
151; CHECK-SD-NEXT:    umaxv b0, v0.16b
152; CHECK-SD-NEXT:    fmov w0, s0
153; CHECK-SD-NEXT:    ret
154;
155; CHECK-GI-LABEL: test_v9i8:
156; CHECK-GI:       // %bb.0:
157; CHECK-GI-NEXT:    mov b1, v0.b[1]
158; CHECK-GI-NEXT:    umov w8, v0.b[0]
159; CHECK-GI-NEXT:    umov w9, v0.b[1]
160; CHECK-GI-NEXT:    umov w10, v0.b[2]
161; CHECK-GI-NEXT:    fmov w11, s1
162; CHECK-GI-NEXT:    cmp w8, w11, uxtb
163; CHECK-GI-NEXT:    umov w11, v0.b[3]
164; CHECK-GI-NEXT:    csel w8, w8, w9, hi
165; CHECK-GI-NEXT:    umov w9, v0.b[4]
166; CHECK-GI-NEXT:    cmp w10, w8, uxtb
167; CHECK-GI-NEXT:    csel w8, w8, w10, lo
168; CHECK-GI-NEXT:    umov w10, v0.b[5]
169; CHECK-GI-NEXT:    cmp w11, w8, uxtb
170; CHECK-GI-NEXT:    csel w8, w8, w11, lo
171; CHECK-GI-NEXT:    umov w11, v0.b[6]
172; CHECK-GI-NEXT:    cmp w9, w8, uxtb
173; CHECK-GI-NEXT:    csel w8, w8, w9, lo
174; CHECK-GI-NEXT:    umov w9, v0.b[7]
175; CHECK-GI-NEXT:    cmp w10, w8, uxtb
176; CHECK-GI-NEXT:    csel w8, w8, w10, lo
177; CHECK-GI-NEXT:    umov w10, v0.b[8]
178; CHECK-GI-NEXT:    cmp w11, w8, uxtb
179; CHECK-GI-NEXT:    csel w8, w8, w11, lo
180; CHECK-GI-NEXT:    cmp w9, w8, uxtb
181; CHECK-GI-NEXT:    csel w8, w8, w9, lo
182; CHECK-GI-NEXT:    cmp w10, w8, uxtb
183; CHECK-GI-NEXT:    csel w0, w8, w10, lo
184; CHECK-GI-NEXT:    ret
185  %b = call i8 @llvm.vector.reduce.umax.v9i8(<9 x i8> %a)
186  ret i8 %b
187}
188
189define i32 @test_v3i32(<3 x i32> %a) nounwind {
190; CHECK-LABEL: test_v3i32:
191; CHECK:       // %bb.0:
192; CHECK-NEXT:    mov v0.s[3], wzr
193; CHECK-NEXT:    umaxv s0, v0.4s
194; CHECK-NEXT:    fmov w0, s0
195; CHECK-NEXT:    ret
196  %b = call i32 @llvm.vector.reduce.umax.v3i32(<3 x i32> %a)
197  ret i32 %b
198}
199
200define i1 @test_v4i1(<4 x i1> %a) nounwind {
201; CHECK-SD-LABEL: test_v4i1:
202; CHECK-SD:       // %bb.0:
203; CHECK-SD-NEXT:    shl v0.4h, v0.4h, #15
204; CHECK-SD-NEXT:    cmlt v0.4h, v0.4h, #0
205; CHECK-SD-NEXT:    umaxv h0, v0.4h
206; CHECK-SD-NEXT:    fmov w8, s0
207; CHECK-SD-NEXT:    and w0, w8, #0x1
208; CHECK-SD-NEXT:    ret
209;
210; CHECK-GI-LABEL: test_v4i1:
211; CHECK-GI:       // %bb.0:
212; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
213; CHECK-GI-NEXT:    umov w8, v0.h[0]
214; CHECK-GI-NEXT:    umov w9, v0.h[1]
215; CHECK-GI-NEXT:    umov w10, v0.h[2]
216; CHECK-GI-NEXT:    umov w11, v0.h[3]
217; CHECK-GI-NEXT:    and w12, w8, #0x1
218; CHECK-GI-NEXT:    and w13, w9, #0x1
219; CHECK-GI-NEXT:    cmp w12, w13
220; CHECK-GI-NEXT:    and w12, w10, #0x1
221; CHECK-GI-NEXT:    and w13, w11, #0x1
222; CHECK-GI-NEXT:    csel w8, w8, w9, hi
223; CHECK-GI-NEXT:    cmp w12, w13
224; CHECK-GI-NEXT:    csel w9, w10, w11, hi
225; CHECK-GI-NEXT:    and w10, w8, #0x1
226; CHECK-GI-NEXT:    and w11, w9, #0x1
227; CHECK-GI-NEXT:    cmp w10, w11
228; CHECK-GI-NEXT:    csel w8, w8, w9, hi
229; CHECK-GI-NEXT:    and w0, w8, #0x1
230; CHECK-GI-NEXT:    ret
231  %b = call i1 @llvm.vector.reduce.umax.v4i1(<4 x i1> %a)
232  ret i1 %b
233}
234
235define i24 @test_v4i24(<4 x i24> %a) nounwind {
236; CHECK-SD-LABEL: test_v4i24:
237; CHECK-SD:       // %bb.0:
238; CHECK-SD-NEXT:    bic v0.4s, #255, lsl #24
239; CHECK-SD-NEXT:    umaxv s0, v0.4s
240; CHECK-SD-NEXT:    fmov w0, s0
241; CHECK-SD-NEXT:    ret
242;
243; CHECK-GI-LABEL: test_v4i24:
244; CHECK-GI:       // %bb.0:
245; CHECK-GI-NEXT:    mov s1, v0.s[1]
246; CHECK-GI-NEXT:    mov s2, v0.s[2]
247; CHECK-GI-NEXT:    mov s3, v0.s[3]
248; CHECK-GI-NEXT:    fmov w8, s0
249; CHECK-GI-NEXT:    fmov w9, s1
250; CHECK-GI-NEXT:    fmov w10, s2
251; CHECK-GI-NEXT:    fmov w11, s3
252; CHECK-GI-NEXT:    and w8, w8, #0xffffff
253; CHECK-GI-NEXT:    and w9, w9, #0xffffff
254; CHECK-GI-NEXT:    cmp w8, w9
255; CHECK-GI-NEXT:    and w8, w10, #0xffffff
256; CHECK-GI-NEXT:    and w9, w11, #0xffffff
257; CHECK-GI-NEXT:    fcsel s0, s0, s1, hi
258; CHECK-GI-NEXT:    cmp w8, w9
259; CHECK-GI-NEXT:    fcsel s1, s2, s3, hi
260; CHECK-GI-NEXT:    fmov w8, s0
261; CHECK-GI-NEXT:    fmov w9, s1
262; CHECK-GI-NEXT:    and w8, w8, #0xffffff
263; CHECK-GI-NEXT:    and w9, w9, #0xffffff
264; CHECK-GI-NEXT:    cmp w8, w9
265; CHECK-GI-NEXT:    fcsel s0, s0, s1, hi
266; CHECK-GI-NEXT:    fmov w0, s0
267; CHECK-GI-NEXT:    ret
268  %b = call i24 @llvm.vector.reduce.umax.v4i24(<4 x i24> %a)
269  ret i24 %b
270}
271
272define i128 @test_v2i128(<2 x i128> %a) nounwind {
273; CHECK-SD-LABEL: test_v2i128:
274; CHECK-SD:       // %bb.0:
275; CHECK-SD-NEXT:    cmp x2, x0
276; CHECK-SD-NEXT:    sbcs xzr, x3, x1
277; CHECK-SD-NEXT:    csel x0, x0, x2, lo
278; CHECK-SD-NEXT:    csel x1, x1, x3, lo
279; CHECK-SD-NEXT:    ret
280;
281; CHECK-GI-LABEL: test_v2i128:
282; CHECK-GI:       // %bb.0:
283; CHECK-GI-NEXT:    cmp x0, x2
284; CHECK-GI-NEXT:    cset w8, hi
285; CHECK-GI-NEXT:    cmp x1, x3
286; CHECK-GI-NEXT:    cset w9, hi
287; CHECK-GI-NEXT:    csel w8, w8, w9, eq
288; CHECK-GI-NEXT:    tst w8, #0x1
289; CHECK-GI-NEXT:    csel x0, x0, x2, ne
290; CHECK-GI-NEXT:    csel x1, x1, x3, ne
291; CHECK-GI-NEXT:    ret
292  %b = call i128 @llvm.vector.reduce.umax.v2i128(<2 x i128> %a)
293  ret i128 %b
294}
295
296define i32 @test_v16i32(<16 x i32> %a) nounwind {
297; CHECK-SD-LABEL: test_v16i32:
298; CHECK-SD:       // %bb.0:
299; CHECK-SD-NEXT:    umax v1.4s, v1.4s, v3.4s
300; CHECK-SD-NEXT:    umax v0.4s, v0.4s, v2.4s
301; CHECK-SD-NEXT:    umax v0.4s, v0.4s, v1.4s
302; CHECK-SD-NEXT:    umaxv s0, v0.4s
303; CHECK-SD-NEXT:    fmov w0, s0
304; CHECK-SD-NEXT:    ret
305;
306; CHECK-GI-LABEL: test_v16i32:
307; CHECK-GI:       // %bb.0:
308; CHECK-GI-NEXT:    umax v0.4s, v0.4s, v1.4s
309; CHECK-GI-NEXT:    umax v1.4s, v2.4s, v3.4s
310; CHECK-GI-NEXT:    umax v0.4s, v0.4s, v1.4s
311; CHECK-GI-NEXT:    umaxv s0, v0.4s
312; CHECK-GI-NEXT:    fmov w0, s0
313; CHECK-GI-NEXT:    ret
314  %b = call i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> %a)
315  ret i32 %b
316}
317