xref: /llvm-project/llvm/test/CodeGen/AArch64/sve-fixed-length-bitcast.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -aarch64-sve-vector-bits-min=256  < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_256
3; RUN: llc -aarch64-sve-vector-bits-min=512  < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
4; RUN: llc -aarch64-sve-vector-bits-min=2048 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
5
6target triple = "aarch64-unknown-linux-gnu"
7
8; Don't use SVE for 64-bit vectors.
9define void @bitcast_v4i16(ptr %a, ptr %b) vscale_range(2,0) #0 {
10; CHECK-LABEL: bitcast_v4i16:
11; CHECK:       // %bb.0:
12; CHECK-NEXT:    ldr d0, [x0]
13; CHECK-NEXT:    str d0, [x1]
14; CHECK-NEXT:    ret
15  %load = load volatile <4 x i16>, ptr %a
16  %cast = bitcast <4 x i16> %load to <4 x half>
17  store volatile <4 x half> %cast, ptr %b
18  ret void
19}
20
21; Don't use SVE for 128-bit vectors.
22define void @bitcast_v8i16(ptr %a, ptr %b) vscale_range(2,0) #0 {
23; CHECK-LABEL: bitcast_v8i16:
24; CHECK:       // %bb.0:
25; CHECK-NEXT:    ldr q0, [x0]
26; CHECK-NEXT:    str q0, [x1]
27; CHECK-NEXT:    ret
28  %load = load volatile <8 x i16>, ptr %a
29  %cast = bitcast <8 x i16> %load to <8 x half>
30  store volatile <8 x half> %cast, ptr %b
31  ret void
32}
33
34define void @bitcast_v16i16(ptr %a, ptr %b) vscale_range(2,0) #0 {
35; CHECK-LABEL: bitcast_v16i16:
36; CHECK:       // %bb.0:
37; CHECK-NEXT:    ptrue p0.h, vl16
38; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
39; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
40; CHECK-NEXT:    ret
41  %load = load volatile <16 x i16>, ptr %a
42  %cast = bitcast <16 x i16> %load to <16 x half>
43  store volatile <16 x half> %cast, ptr %b
44  ret void
45}
46
47define void @bitcast_v32i16(ptr %a, ptr %b) #0 {
48; VBITS_GE_256-LABEL: bitcast_v32i16:
49; VBITS_GE_256:       // %bb.0:
50; VBITS_GE_256-NEXT:    ptrue p0.h, vl16
51; VBITS_GE_256-NEXT:    mov x8, #16 // =0x10
52; VBITS_GE_256-NEXT:    ld1h { z0.h }, p0/z, [x0, x8, lsl #1]
53; VBITS_GE_256-NEXT:    ld1h { z1.h }, p0/z, [x0]
54; VBITS_GE_256-NEXT:    st1h { z0.h }, p0, [x1, x8, lsl #1]
55; VBITS_GE_256-NEXT:    st1h { z1.h }, p0, [x1]
56; VBITS_GE_256-NEXT:    ret
57;
58; VBITS_GE_512-LABEL: bitcast_v32i16:
59; VBITS_GE_512:       // %bb.0:
60; VBITS_GE_512-NEXT:    ptrue p0.h, vl32
61; VBITS_GE_512-NEXT:    ld1h { z0.h }, p0/z, [x0]
62; VBITS_GE_512-NEXT:    st1h { z0.h }, p0, [x1]
63; VBITS_GE_512-NEXT:    ret
64  %load = load volatile <32 x i16>, ptr %a
65  %cast = bitcast <32 x i16> %load to <32 x half>
66  store volatile <32 x half> %cast, ptr %b
67  ret void
68}
69
70define void @bitcast_v64i16(ptr %a, ptr %b) vscale_range(8,0) #0 {
71; CHECK-LABEL: bitcast_v64i16:
72; CHECK:       // %bb.0:
73; CHECK-NEXT:    ptrue p0.h, vl64
74; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
75; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
76; CHECK-NEXT:    ret
77  %load = load volatile <64 x i16>, ptr %a
78  %cast = bitcast <64 x i16> %load to <64 x half>
79  store volatile <64 x half> %cast, ptr %b
80  ret void
81}
82
83define void @bitcast_v128i16(ptr %a, ptr %b) vscale_range(16,0) #0 {
84; CHECK-LABEL: bitcast_v128i16:
85; CHECK:       // %bb.0:
86; CHECK-NEXT:    ptrue p0.h, vl128
87; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
88; CHECK-NEXT:    st1h { z0.h }, p0, [x1]
89; CHECK-NEXT:    ret
90  %load = load volatile <128 x i16>, ptr %a
91  %cast = bitcast <128 x i16> %load to <128 x half>
92  store volatile <128 x half> %cast, ptr %b
93  ret void
94}
95
96; Don't use SVE for 64-bit vectors.
97define void @bitcast_v2i32(ptr %a, ptr %b) vscale_range(2,0) #0 {
98; CHECK-LABEL: bitcast_v2i32:
99; CHECK:       // %bb.0:
100; CHECK-NEXT:    ldr d0, [x0]
101; CHECK-NEXT:    str d0, [x1]
102; CHECK-NEXT:    ret
103  %load = load volatile <2 x i32>, ptr %a
104  %cast = bitcast <2 x i32> %load to <2 x float>
105  store volatile <2 x float> %cast, ptr %b
106  ret void
107}
108
109; Don't use SVE for 128-bit vectors.
110define void @bitcast_v4i32(ptr %a, ptr %b) vscale_range(2,0) #0 {
111; CHECK-LABEL: bitcast_v4i32:
112; CHECK:       // %bb.0:
113; CHECK-NEXT:    ldr q0, [x0]
114; CHECK-NEXT:    str q0, [x1]
115; CHECK-NEXT:    ret
116  %load = load volatile <4 x i32>, ptr %a
117  %cast = bitcast <4 x i32> %load to <4 x float>
118  store volatile <4 x float> %cast, ptr %b
119  ret void
120}
121
122define void @bitcast_v8i32(ptr %a, ptr %b) vscale_range(2,0) #0 {
123; CHECK-LABEL: bitcast_v8i32:
124; CHECK:       // %bb.0:
125; CHECK-NEXT:    ptrue p0.s, vl8
126; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
127; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
128; CHECK-NEXT:    ret
129  %load = load volatile <8 x i32>, ptr %a
130  %cast = bitcast <8 x i32> %load to <8 x float>
131  store volatile <8 x float> %cast, ptr %b
132  ret void
133}
134
135define void @bitcast_v16i32(ptr %a, ptr %b) #0 {
136; VBITS_GE_256-LABEL: bitcast_v16i32:
137; VBITS_GE_256:       // %bb.0:
138; VBITS_GE_256-NEXT:    ptrue p0.s, vl8
139; VBITS_GE_256-NEXT:    mov x8, #8 // =0x8
140; VBITS_GE_256-NEXT:    ld1w { z0.s }, p0/z, [x0, x8, lsl #2]
141; VBITS_GE_256-NEXT:    ld1w { z1.s }, p0/z, [x0]
142; VBITS_GE_256-NEXT:    st1w { z0.s }, p0, [x1, x8, lsl #2]
143; VBITS_GE_256-NEXT:    st1w { z1.s }, p0, [x1]
144; VBITS_GE_256-NEXT:    ret
145;
146; VBITS_GE_512-LABEL: bitcast_v16i32:
147; VBITS_GE_512:       // %bb.0:
148; VBITS_GE_512-NEXT:    ptrue p0.s, vl16
149; VBITS_GE_512-NEXT:    ld1w { z0.s }, p0/z, [x0]
150; VBITS_GE_512-NEXT:    st1w { z0.s }, p0, [x1]
151; VBITS_GE_512-NEXT:    ret
152  %load = load volatile <16 x i32>, ptr %a
153  %cast = bitcast <16 x i32> %load to <16 x float>
154  store volatile <16 x float> %cast, ptr %b
155  ret void
156}
157
158define void @bitcast_v32i32(ptr %a, ptr %b) vscale_range(8,0) #0 {
159; CHECK-LABEL: bitcast_v32i32:
160; CHECK:       // %bb.0:
161; CHECK-NEXT:    ptrue p0.s, vl32
162; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
163; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
164; CHECK-NEXT:    ret
165  %load = load volatile <32 x i32>, ptr %a
166  %cast = bitcast <32 x i32> %load to <32 x float>
167  store volatile <32 x float> %cast, ptr %b
168  ret void
169}
170
171define void @bitcast_v64i32(ptr %a, ptr %b) vscale_range(16,0) #0 {
172; CHECK-LABEL: bitcast_v64i32:
173; CHECK:       // %bb.0:
174; CHECK-NEXT:    ptrue p0.s, vl64
175; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
176; CHECK-NEXT:    st1w { z0.s }, p0, [x1]
177; CHECK-NEXT:    ret
178  %load = load volatile <64 x i32>, ptr %a
179  %cast = bitcast <64 x i32> %load to <64 x float>
180  store volatile <64 x float> %cast, ptr %b
181  ret void
182}
183
184; Don't use SVE for 64-bit vectors.
185define void @bitcast_v1i64(ptr %a, ptr %b) vscale_range(2,0) #0 {
186; CHECK-LABEL: bitcast_v1i64:
187; CHECK:       // %bb.0:
188; CHECK-NEXT:    ldr d0, [x0]
189; CHECK-NEXT:    str d0, [x1]
190; CHECK-NEXT:    ret
191  %load = load volatile <1 x i64>, ptr %a
192  %cast = bitcast <1 x i64> %load to <1 x double>
193  store volatile <1 x double> %cast, ptr %b
194  ret void
195}
196
197; Don't use SVE for 128-bit vectors.
198define void @bitcast_v2i64(ptr %a, ptr %b) vscale_range(2,0) #0 {
199; CHECK-LABEL: bitcast_v2i64:
200; CHECK:       // %bb.0:
201; CHECK-NEXT:    ldr q0, [x0]
202; CHECK-NEXT:    str q0, [x1]
203; CHECK-NEXT:    ret
204  %load = load volatile <2 x i64>, ptr %a
205  %cast = bitcast <2 x i64> %load to <2 x double>
206  store volatile <2 x double> %cast, ptr %b
207  ret void
208}
209
210define void @bitcast_v4i64(ptr %a, ptr %b) vscale_range(2,0) #0 {
211; CHECK-LABEL: bitcast_v4i64:
212; CHECK:       // %bb.0:
213; CHECK-NEXT:    ptrue p0.d, vl4
214; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
215; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
216; CHECK-NEXT:    ret
217  %load = load volatile <4 x i64>, ptr %a
218  %cast = bitcast <4 x i64> %load to <4 x double>
219  store volatile <4 x double> %cast, ptr %b
220  ret void
221}
222
223define void @bitcast_v8i64(ptr %a, ptr %b) #0 {
224; VBITS_GE_256-LABEL: bitcast_v8i64:
225; VBITS_GE_256:       // %bb.0:
226; VBITS_GE_256-NEXT:    ptrue p0.d, vl4
227; VBITS_GE_256-NEXT:    mov x8, #4 // =0x4
228; VBITS_GE_256-NEXT:    ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
229; VBITS_GE_256-NEXT:    ld1d { z1.d }, p0/z, [x0]
230; VBITS_GE_256-NEXT:    st1d { z0.d }, p0, [x1, x8, lsl #3]
231; VBITS_GE_256-NEXT:    st1d { z1.d }, p0, [x1]
232; VBITS_GE_256-NEXT:    ret
233;
234; VBITS_GE_512-LABEL: bitcast_v8i64:
235; VBITS_GE_512:       // %bb.0:
236; VBITS_GE_512-NEXT:    ptrue p0.d, vl8
237; VBITS_GE_512-NEXT:    ld1d { z0.d }, p0/z, [x0]
238; VBITS_GE_512-NEXT:    st1d { z0.d }, p0, [x1]
239; VBITS_GE_512-NEXT:    ret
240  %load = load volatile <8 x i64>, ptr %a
241  %cast = bitcast <8 x i64> %load to <8 x double>
242  store volatile <8 x double> %cast, ptr %b
243  ret void
244}
245
246define void @bitcast_v16i64(ptr %a, ptr %b) vscale_range(8,0) #0 {
247; CHECK-LABEL: bitcast_v16i64:
248; CHECK:       // %bb.0:
249; CHECK-NEXT:    ptrue p0.d, vl16
250; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
251; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
252; CHECK-NEXT:    ret
253  %load = load volatile <16 x i64>, ptr %a
254  %cast = bitcast <16 x i64> %load to <16 x double>
255  store volatile <16 x double> %cast, ptr %b
256  ret void
257}
258
259define void @bitcast_v32i64(ptr %a, ptr %b) vscale_range(16,0) #0 {
260; CHECK-LABEL: bitcast_v32i64:
261; CHECK:       // %bb.0:
262; CHECK-NEXT:    ptrue p0.d, vl32
263; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
264; CHECK-NEXT:    st1d { z0.d }, p0, [x1]
265; CHECK-NEXT:    ret
266  %load = load volatile <32 x i64>, ptr %a
267  %cast = bitcast <32 x i64> %load to <32 x double>
268  store volatile <32 x double> %cast, ptr %b
269  ret void
270}
271
272attributes #0 = { "target-features"="+sve" }
273