xref: /llvm-project/llvm/test/CodeGen/AArch64/complex-deinterleaving-uniform-cases.ll (revision 61510b51c33464a6bc15e4cf5b1ee07e2e0ec1c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16 -o - | FileCheck %s
3
4target triple = "aarch64"
5
6; Expected to transform
7define <4 x float> @simple_mul(<4 x float> %a, <4 x float> %b) {
8; CHECK-LABEL: simple_mul:
9; CHECK:       // %bb.0: // %entry
10; CHECK-NEXT:    movi v2.2d, #0000000000000000
11; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #0
12; CHECK-NEXT:    fcmla v2.4s, v1.4s, v0.4s, #90
13; CHECK-NEXT:    mov v0.16b, v2.16b
14; CHECK-NEXT:    ret
15entry:
16  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
17  %strided.vec17 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
18  %strided.vec19 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
19  %strided.vec20 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
20  %0 = fmul fast <2 x float> %strided.vec20, %strided.vec
21  %1 = fmul fast <2 x float> %strided.vec19, %strided.vec17
22  %2 = fadd fast <2 x float> %1, %0
23  %3 = fmul fast <2 x float> %strided.vec19, %strided.vec
24  %4 = fmul fast <2 x float> %strided.vec17, %strided.vec20
25  %5 = fsub fast <2 x float> %3, %4
26  %interleaved.vec = shufflevector <2 x float> %5, <2 x float> %2, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
27  ret <4 x float> %interleaved.vec
28}
29
30; Expected to not transform
31define <4 x float> @simple_mul_no_contract(<4 x float> %a, <4 x float> %b) {
32; CHECK-LABEL: simple_mul_no_contract:
33; CHECK:       // %bb.0: // %entry
34; CHECK-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
35; CHECK-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
36; CHECK-NEXT:    zip1 v4.2s, v0.2s, v2.2s
37; CHECK-NEXT:    zip2 v0.2s, v0.2s, v2.2s
38; CHECK-NEXT:    zip1 v2.2s, v1.2s, v3.2s
39; CHECK-NEXT:    zip2 v1.2s, v1.2s, v3.2s
40; CHECK-NEXT:    fmul v3.2s, v1.2s, v4.2s
41; CHECK-NEXT:    fmul v4.2s, v2.2s, v4.2s
42; CHECK-NEXT:    fmul v1.2s, v0.2s, v1.2s
43; CHECK-NEXT:    fmla v3.2s, v0.2s, v2.2s
44; CHECK-NEXT:    fsub v0.2s, v4.2s, v1.2s
45; CHECK-NEXT:    zip1 v0.4s, v0.4s, v3.4s
46; CHECK-NEXT:    ret
47entry:
48  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
49  %strided.vec17 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
50  %strided.vec19 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
51  %strided.vec20 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
52  %0 = fmul fast <2 x float> %strided.vec20, %strided.vec
53  %1 = fmul fast <2 x float> %strided.vec19, %strided.vec17
54  %2 = fadd fast <2 x float> %1, %0
55  %3 = fmul fast <2 x float> %strided.vec19, %strided.vec
56  %4 = fmul fast <2 x float> %strided.vec17, %strided.vec20
57  %5 = fsub <2 x float> %3, %4
58  %interleaved.vec = shufflevector <2 x float> %5, <2 x float> %2, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
59  ret <4 x float> %interleaved.vec
60}
61
62; Expected to transform
63define <4 x float> @three_way_mul(<4 x float> %a, <4 x float> %b, <4 x float> %c) {
64; CHECK-LABEL: three_way_mul:
65; CHECK:       // %bb.0: // %entry
66; CHECK-NEXT:    movi v4.2d, #0000000000000000
67; CHECK-NEXT:    movi v3.2d, #0000000000000000
68; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #0
69; CHECK-NEXT:    fcmla v4.4s, v0.4s, v1.4s, #90
70; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #0
71; CHECK-NEXT:    fcmla v3.4s, v4.4s, v2.4s, #90
72; CHECK-NEXT:    mov v0.16b, v3.16b
73; CHECK-NEXT:    ret
74entry:
75  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
76  %strided.vec39 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
77  %strided.vec41 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
78  %strided.vec42 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
79  %strided.vec44 = shufflevector <4 x float> %c, <4 x float> poison, <2 x i32> <i32 0, i32 2>
80  %strided.vec45 = shufflevector <4 x float> %c, <4 x float> poison, <2 x i32> <i32 1, i32 3>
81  %0 = fmul fast <2 x float> %strided.vec41, %strided.vec
82  %1 = fmul fast <2 x float> %strided.vec42, %strided.vec39
83  %2 = fsub fast <2 x float> %0, %1
84  %3 = fmul fast <2 x float> %2, %strided.vec45
85  %4 = fmul fast <2 x float> %strided.vec42, %strided.vec
86  %5 = fmul fast <2 x float> %strided.vec39, %strided.vec41
87  %6 = fadd fast <2 x float> %4, %5
88  %7 = fmul fast <2 x float> %6, %strided.vec44
89  %8 = fadd fast <2 x float> %3, %7
90  %9 = fmul fast <2 x float> %2, %strided.vec44
91  %10 = fmul fast <2 x float> %6, %strided.vec45
92  %11 = fsub fast <2 x float> %9, %10
93  %interleaved.vec = shufflevector <2 x float> %11, <2 x float> %8, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
94  ret <4 x float> %interleaved.vec
95}
96
97; Expected to transform
98define <4 x float> @simple_add_90(<4 x float> %a, <4 x float> %b) {
99; CHECK-LABEL: simple_add_90:
100; CHECK:       // %bb.0: // %entry
101; CHECK-NEXT:    fcadd v0.4s, v1.4s, v0.4s, #90
102; CHECK-NEXT:    ret
103entry:
104  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
105  %strided.vec17 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
106  %strided.vec19 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
107  %strided.vec20 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
108  %0 = fsub fast <2 x float> %strided.vec19, %strided.vec17
109  %1 = fadd fast <2 x float> %strided.vec20, %strided.vec
110  %interleaved.vec = shufflevector <2 x float> %0, <2 x float> %1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
111  ret <4 x float> %interleaved.vec
112}
113
114; Expected to not transform, fadd commutativity is not yet implemented
115define <4 x float> @simple_add_270_false(<4 x float> %a, <4 x float> %b) {
116; CHECK-LABEL: simple_add_270_false:
117; CHECK:       // %bb.0: // %entry
118; CHECK-NEXT:    fcadd v0.4s, v0.4s, v1.4s, #270
119; CHECK-NEXT:    ret
120entry:
121  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
122  %strided.vec17 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
123  %strided.vec19 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
124  %strided.vec20 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
125  %0 = fadd fast <2 x float> %strided.vec20, %strided.vec
126  %1 = fsub fast <2 x float> %strided.vec17, %strided.vec19
127  %interleaved.vec = shufflevector <2 x float> %0, <2 x float> %1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
128  ret <4 x float> %interleaved.vec
129}
130
131; Expected to transform
132define <4 x float> @simple_add_270_true(<4 x float> %a, <4 x float> %b) {
133; CHECK-LABEL: simple_add_270_true:
134; CHECK:       // %bb.0: // %entry
135; CHECK-NEXT:    fcadd v0.4s, v0.4s, v1.4s, #270
136; CHECK-NEXT:    ret
137entry:
138  %strided.vec = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
139  %strided.vec17 = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
140  %strided.vec19 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
141  %strided.vec20 = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
142  %0 = fadd fast <2 x float> %strided.vec, %strided.vec20
143  %1 = fsub fast <2 x float> %strided.vec17, %strided.vec19
144  %interleaved.vec = shufflevector <2 x float> %0, <2 x float> %1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
145  ret <4 x float> %interleaved.vec
146}
147
148; Expected to not transform
149define <4 x float> @add_external_use(<4 x float> %a, <4 x float> %b) {
150; CHECK-LABEL: add_external_use:
151; CHECK:       // %bb.0: // %entry
152; CHECK-NEXT:    ext v2.16b, v0.16b, v0.16b, #8
153; CHECK-NEXT:    ext v3.16b, v1.16b, v1.16b, #8
154; CHECK-NEXT:    zip1 v4.2s, v0.2s, v2.2s
155; CHECK-NEXT:    zip2 v0.2s, v0.2s, v2.2s
156; CHECK-NEXT:    zip1 v2.2s, v1.2s, v3.2s
157; CHECK-NEXT:    zip2 v1.2s, v1.2s, v3.2s
158; CHECK-NEXT:    fadd v0.2s, v0.2s, v2.2s
159; CHECK-NEXT:    fsub v1.2s, v4.2s, v1.2s
160; CHECK-NEXT:    zip1 v0.4s, v1.4s, v0.4s
161; CHECK-NEXT:    ret
162entry:
163  %a.real = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
164  %a.imag = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
165  %b.real = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
166  %b.imag = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
167  %0 = fsub fast <2 x float> %a.real, %b.imag
168  %1 = fadd fast <2 x float> %a.imag, %b.real
169  %interleaved.vec = shufflevector <2 x float> %0, <2 x float> %1, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
170  %dup = shufflevector <2 x float> %0, <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
171  %interleaved.vec2 = shufflevector <4 x float> %interleaved.vec, <4 x float> %dup, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
172  ret <4 x float> %interleaved.vec2
173}
174
175; Expected to transform
176define <4 x float> @mul_mul_with_fneg(<4 x float> %a, <4 x float> %b) {
177; CHECK-LABEL: mul_mul_with_fneg:
178; CHECK:       // %bb.0: // %entry
179; CHECK-NEXT:    movi v2.2d, #0000000000000000
180; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #270
181; CHECK-NEXT:    fcmla v2.4s, v0.4s, v1.4s, #180
182; CHECK-NEXT:    mov v0.16b, v2.16b
183; CHECK-NEXT:    ret
184entry:
185  %a.real = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 0, i32 2>
186  %a.imag = shufflevector <4 x float> %a, <4 x float> poison, <2 x i32> <i32 1, i32 3>
187  %b.real = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 0, i32 2>
188  %b.imag = shufflevector <4 x float> %b, <4 x float> poison, <2 x i32> <i32 1, i32 3>
189  %0 = fneg fast <2 x float> %a.imag
190  %1 = fmul fast <2 x float> %b.real, %0
191  %2 = fmul fast <2 x float> %a.real, %b.imag
192  %3 = fsub fast <2 x float> %1, %2
193  %4 = fmul fast <2 x float> %b.imag, %a.imag
194  %5 = fmul fast <2 x float> %a.real, %b.real
195  %6 = fsub fast <2 x float> %4, %5
196  %interleaved.vec = shufflevector <2 x float> %6, <2 x float> %3, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
197  ret <4 x float> %interleaved.vec
198}
199
200; Expected to not transform
201define <12 x float> @abp90c12(<12 x float> %a, <12 x float> %b, <12 x float> %c) {
202; CHECK-LABEL: abp90c12:
203; CHECK:       // %bb.0: // %entry
204; CHECK-NEXT:    // kill: def $s1 killed $s1 def $q1
205; CHECK-NEXT:    // kill: def $s3 killed $s3 def $q3
206; CHECK-NEXT:    ldr s17, [sp, #40]
207; CHECK-NEXT:    add x10, sp, #56
208; CHECK-NEXT:    // kill: def $s0 killed $s0 def $q0
209; CHECK-NEXT:    add x9, sp, #48
210; CHECK-NEXT:    mov v1.s[1], v3.s[0]
211; CHECK-NEXT:    ldr s3, [sp, #32]
212; CHECK-NEXT:    // kill: def $s2 killed $s2 def $q2
213; CHECK-NEXT:    mov v0.s[1], v2.s[0]
214; CHECK-NEXT:    ld1 { v17.s }[1], [x10]
215; CHECK-NEXT:    // kill: def $s5 killed $s5 def $q5
216; CHECK-NEXT:    ldr s16, [sp, #8]
217; CHECK-NEXT:    // kill: def $s4 killed $s4 def $q4
218; CHECK-NEXT:    add x10, sp, #24
219; CHECK-NEXT:    ld1 { v3.s }[1], [x9]
220; CHECK-NEXT:    add x9, sp, #72
221; CHECK-NEXT:    // kill: def $s7 killed $s7 def $q7
222; CHECK-NEXT:    // kill: def $s6 killed $s6 def $q6
223; CHECK-NEXT:    ldr s2, [sp]
224; CHECK-NEXT:    ld1 { v16.s }[1], [x10]
225; CHECK-NEXT:    add x10, sp, #112
226; CHECK-NEXT:    ldr s20, [sp, #136]
227; CHECK-NEXT:    mov v1.s[2], v5.s[0]
228; CHECK-NEXT:    ld1 { v17.s }[2], [x9]
229; CHECK-NEXT:    add x9, sp, #64
230; CHECK-NEXT:    ldr s5, [sp, #96]
231; CHECK-NEXT:    ld1 { v3.s }[2], [x9]
232; CHECK-NEXT:    mov v0.s[2], v4.s[0]
233; CHECK-NEXT:    add x9, sp, #88
234; CHECK-NEXT:    ldr s4, [sp, #104]
235; CHECK-NEXT:    ldr s19, [sp, #192]
236; CHECK-NEXT:    ld1 { v5.s }[1], [x10]
237; CHECK-NEXT:    add x10, sp, #80
238; CHECK-NEXT:    ld1 { v17.s }[3], [x9]
239; CHECK-NEXT:    mov v1.s[3], v7.s[0]
240; CHECK-NEXT:    add x9, sp, #120
241; CHECK-NEXT:    ld1 { v3.s }[3], [x10]
242; CHECK-NEXT:    ld1 { v4.s }[1], [x9]
243; CHECK-NEXT:    ldr s7, [sp, #128]
244; CHECK-NEXT:    add x10, sp, #144
245; CHECK-NEXT:    mov v0.s[3], v6.s[0]
246; CHECK-NEXT:    add x9, sp, #16
247; CHECK-NEXT:    ld1 { v7.s }[1], [x10]
248; CHECK-NEXT:    ld1 { v2.s }[1], [x9]
249; CHECK-NEXT:    add x9, sp, #160
250; CHECK-NEXT:    fmul v6.4s, v17.4s, v1.4s
251; CHECK-NEXT:    fmul v18.4s, v4.4s, v16.4s
252; CHECK-NEXT:    fmul v16.4s, v5.4s, v16.4s
253; CHECK-NEXT:    fmul v1.4s, v3.4s, v1.4s
254; CHECK-NEXT:    add x10, sp, #208
255; CHECK-NEXT:    ld1 { v7.s }[2], [x9]
256; CHECK-NEXT:    add x9, sp, #152
257; CHECK-NEXT:    ld1 { v19.s }[1], [x10]
258; CHECK-NEXT:    ld1 { v20.s }[1], [x9]
259; CHECK-NEXT:    add x9, sp, #176
260; CHECK-NEXT:    add x10, sp, #184
261; CHECK-NEXT:    fneg v6.4s, v6.4s
262; CHECK-NEXT:    fneg v18.4s, v18.4s
263; CHECK-NEXT:    fmla v16.4s, v2.4s, v4.4s
264; CHECK-NEXT:    fmla v1.4s, v0.4s, v17.4s
265; CHECK-NEXT:    ld1 { v7.s }[3], [x9]
266; CHECK-NEXT:    add x9, sp, #168
267; CHECK-NEXT:    ld1 { v20.s }[2], [x9]
268; CHECK-NEXT:    ldr s4, [sp, #200]
269; CHECK-NEXT:    add x9, sp, #216
270; CHECK-NEXT:    fmla v6.4s, v0.4s, v3.4s
271; CHECK-NEXT:    fmla v18.4s, v2.4s, v5.4s
272; CHECK-NEXT:    ld1 { v4.s }[1], [x9]
273; CHECK-NEXT:    fsub v0.4s, v7.4s, v1.4s
274; CHECK-NEXT:    fsub v1.4s, v19.4s, v16.4s
275; CHECK-NEXT:    ld1 { v20.s }[3], [x10]
276; CHECK-NEXT:    fadd v2.4s, v4.4s, v18.4s
277; CHECK-NEXT:    fadd v3.4s, v20.4s, v6.4s
278; CHECK-NEXT:    ext v4.16b, v0.16b, v1.16b, #12
279; CHECK-NEXT:    ext v5.16b, v3.16b, v2.16b, #12
280; CHECK-NEXT:    trn2 v1.4s, v1.4s, v2.4s
281; CHECK-NEXT:    ext v4.16b, v0.16b, v4.16b, #12
282; CHECK-NEXT:    ext v5.16b, v3.16b, v5.16b, #8
283; CHECK-NEXT:    rev64 v4.4s, v4.4s
284; CHECK-NEXT:    trn2 v2.4s, v4.4s, v5.4s
285; CHECK-NEXT:    zip2 v4.4s, v0.4s, v3.4s
286; CHECK-NEXT:    zip1 v0.4s, v0.4s, v3.4s
287; CHECK-NEXT:    ext v1.16b, v2.16b, v1.16b, #8
288; CHECK-NEXT:    mov v4.d[1], v2.d[0]
289; CHECK-NEXT:    str q0, [x8]
290; CHECK-NEXT:    stp q4, q1, [x8, #16]
291; CHECK-NEXT:    ret
292entry:
293  %ar = shufflevector <12 x float> %a, <12 x float> poison, <6 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10>
294  %ai = shufflevector <12 x float> %a, <12 x float> poison, <6 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11>
295  %br = shufflevector <12 x float> %b, <12 x float> poison, <6 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10>
296  %bi = shufflevector <12 x float> %b, <12 x float> poison, <6 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11>
297  %cr = shufflevector <12 x float> %c, <12 x float> poison, <6 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10>
298  %ci = shufflevector <12 x float> %c, <12 x float> poison, <6 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11>
299
300  %i6 = fmul fast <6 x float> %br, %ar
301  %i7 = fmul fast <6 x float> %bi, %ai
302  %xr = fsub fast <6 x float> %i6, %i7
303  %i9 = fmul fast <6 x float> %bi, %ar
304  %i10 = fmul fast <6 x float> %br, %ai
305  %xi = fadd fast <6 x float> %i9, %i10
306
307  %zr = fsub fast <6 x float> %cr, %xi
308  %zi = fadd fast <6 x float> %ci, %xr
309  %interleaved.vec = shufflevector <6 x float> %zr, <6 x float> %zi, <12 x i32> <i32 0, i32 6, i32 1, i32 7, i32 2, i32 8, i32 3, i32 9, i32 4, i32 10, i32 5, i32 11>
310  ret <12 x float> %interleaved.vec
311}
312