1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+unimplemented-simd128 | FileCheck %s
2
3; Test loads and stores with custom alignment values.
4
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"
7
8; ==============================================================================
9; 16 x i8
10; ==============================================================================
11
12; CHECK-LABEL: load_v16i8_a1:
13; CHECK-NEXT: .functype load_v16i8_a1 (i32) -> (v128){{$}}
14; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
15; CHECK-NEXT: return $pop[[R]]{{$}}
16define <16 x i8> @load_v16i8_a1(<16 x i8> *%p) {
17  %v = load <16 x i8>, <16 x i8>* %p, align 1
18  ret <16 x i8> %v
19}
20
21; CHECK-LABEL: load_v16i8_a4:
22; CHECK-NEXT: .functype load_v16i8_a4 (i32) -> (v128){{$}}
23; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
24; CHECK-NEXT: return $pop[[R]]{{$}}
25define <16 x i8> @load_v16i8_a4(<16 x i8> *%p) {
26  %v = load <16 x i8>, <16 x i8>* %p, align 4
27  ret <16 x i8> %v
28}
29
30; 16 is the default alignment for v128 so no attribute is needed.
31
32; CHECK-LABEL: load_v16i8_a16:
33; CHECK-NEXT: .functype load_v16i8_a16 (i32) -> (v128){{$}}
34; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
35; CHECK-NEXT: return $pop[[R]]{{$}}
36define <16 x i8> @load_v16i8_a16(<16 x i8> *%p) {
37  %v = load <16 x i8>, <16 x i8>* %p, align 16
38  ret <16 x i8> %v
39}
40
41; 32 is greater than the default alignment so it is ignored.
42
43; CHECK-LABEL: load_v16i8_a32:
44; CHECK-NEXT: .functype load_v16i8_a32 (i32) -> (v128){{$}}
45; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
46; CHECK-NEXT: return $pop[[R]]{{$}}
47define <16 x i8> @load_v16i8_a32(<16 x i8> *%p) {
48  %v = load <16 x i8>, <16 x i8>* %p, align 32
49  ret <16 x i8> %v
50}
51
52; CHECK-LABEL: store_v16i8_a1:
53; CHECK-NEXT: .functype store_v16i8_a1 (i32, v128) -> (){{$}}
54; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
55; CHECK-NEXT: return{{$}}
56define void @store_v16i8_a1(<16 x i8> *%p, <16 x i8> %v) {
57  store <16 x i8> %v, <16 x i8>* %p, align 1
58  ret void
59}
60
61; CHECK-LABEL: store_v16i8_a4:
62; CHECK-NEXT: .functype store_v16i8_a4 (i32, v128) -> (){{$}}
63; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
64; CHECK-NEXT: return{{$}}
65define void @store_v16i8_a4(<16 x i8> *%p, <16 x i8> %v) {
66  store <16 x i8> %v, <16 x i8>* %p, align 4
67  ret void
68}
69
70; 16 is the default alignment for v128 so no attribute is needed.
71
72; CHECK-LABEL: store_v16i8_a16:
73; CHECK-NEXT: .functype store_v16i8_a16 (i32, v128) -> (){{$}}
74; CHECK-NEXT: v128.store 0($0), $1{{$}}
75; CHECK-NEXT: return{{$}}
76define void @store_v16i8_a16(<16 x i8> *%p, <16 x i8> %v) {
77  store <16 x i8> %v, <16 x i8>* %p, align 16
78  ret void
79}
80
81; 32 is greater than the default alignment so it is ignored.
82
83; CHECK-LABEL: store_v16i8_a32:
84; CHECK-NEXT: .functype store_v16i8_a32 (i32, v128) -> (){{$}}
85; CHECK-NEXT: v128.store 0($0), $1{{$}}
86; CHECK-NEXT: return{{$}}
87define void @store_v16i8_a32(<16 x i8> *%p, <16 x i8> %v) {
88  store <16 x i8> %v, <16 x i8>* %p, align 32
89  ret void
90}
91
92; 1 is the default alignment for v8x16.load_splat so no attribute is needed.
93
94; CHECK-LABEL: load_splat_v16i8_a1:
95; CHECK-NEXT: .functype load_splat_v16i8_a1 (i32) -> (v128){{$}}
96; CHECK-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
97; CHECK-NEXT: return $pop[[R]]{{$}}
98define <16 x i8> @load_splat_v16i8_a1(i8* %p) {
99  %e = load i8, i8* %p, align 1
100  %v1 = insertelement <16 x i8> undef, i8 %e, i32 0
101  %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer
102  ret <16 x i8> %v2
103}
104
105; 2 is greater than the default alignment so it is ignored.
106
107; CHECK-LABEL: load_splat_v16i8_a2:
108; CHECK-NEXT: .functype load_splat_v16i8_a2 (i32) -> (v128){{$}}
109; CHECK-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
110; CHECK-NEXT: return $pop[[R]]{{$}}
111define <16 x i8> @load_splat_v16i8_a2(i8* %p) {
112  %e = load i8, i8* %p, align 2
113  %v1 = insertelement <16 x i8> undef, i8 %e, i32 0
114  %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer
115  ret <16 x i8> %v2
116}
117
118; ==============================================================================
119; 8 x i16
120; ==============================================================================
121
122; CHECK-LABEL: load_v8i16_a1:
123; CHECK-NEXT: .functype load_v8i16_a1 (i32) -> (v128){{$}}
124; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
125; CHECK-NEXT: return $pop[[R]]{{$}}
126define <8 x i16> @load_v8i16_a1(<8 x i16> *%p) {
127  %v = load <8 x i16>, <8 x i16>* %p, align 1
128  ret <8 x i16> %v
129}
130
131; CHECK-LABEL: load_v8i16_a4:
132; CHECK-NEXT: .functype load_v8i16_a4 (i32) -> (v128){{$}}
133; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
134; CHECK-NEXT: return $pop[[R]]{{$}}
135define <8 x i16> @load_v8i16_a4(<8 x i16> *%p) {
136  %v = load <8 x i16>, <8 x i16>* %p, align 4
137  ret <8 x i16> %v
138}
139
140; 8 is the default alignment for v128 so no attribute is needed.
141
142; CHECK-LABEL: load_v8i16_a16:
143; CHECK-NEXT: .functype load_v8i16_a16 (i32) -> (v128){{$}}
144; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
145; CHECK-NEXT: return $pop[[R]]{{$}}
146define <8 x i16> @load_v8i16_a16(<8 x i16> *%p) {
147  %v = load <8 x i16>, <8 x i16>* %p, align 16
148  ret <8 x i16> %v
149}
150
151; 32 is greater than the default alignment so it is ignored.
152
153; CHECK-LABEL: load_v8i16_a32:
154; CHECK-NEXT: .functype load_v8i16_a32 (i32) -> (v128){{$}}
155; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
156; CHECK-NEXT: return $pop[[R]]{{$}}
157define <8 x i16> @load_v8i16_a32(<8 x i16> *%p) {
158  %v = load <8 x i16>, <8 x i16>* %p, align 32
159  ret <8 x i16> %v
160}
161
162; CHECK-LABEL: store_v8i16_a1:
163; CHECK-NEXT: .functype store_v8i16_a1 (i32, v128) -> (){{$}}
164; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
165; CHECK-NEXT: return{{$}}
166define void @store_v8i16_a1(<8 x i16> *%p, <8 x i16> %v) {
167  store <8 x i16> %v, <8 x i16>* %p, align 1
168  ret void
169}
170
171; CHECK-LABEL: store_v8i16_a4:
172; CHECK-NEXT: .functype store_v8i16_a4 (i32, v128) -> (){{$}}
173; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
174; CHECK-NEXT: return{{$}}
175define void @store_v8i16_a4(<8 x i16> *%p, <8 x i16> %v) {
176  store <8 x i16> %v, <8 x i16>* %p, align 4
177  ret void
178}
179
180; 16 is the default alignment for v128 so no attribute is needed.
181
182; CHECK-LABEL: store_v8i16_a16:
183; CHECK-NEXT: .functype store_v8i16_a16 (i32, v128) -> (){{$}}
184; CHECK-NEXT: v128.store 0($0), $1{{$}}
185; CHECK-NEXT: return{{$}}
186define void @store_v8i16_a16(<8 x i16> *%p, <8 x i16> %v) {
187  store <8 x i16> %v, <8 x i16>* %p, align 16
188  ret void
189}
190
191; 32 is greater than the default alignment so it is ignored.
192
193; CHECK-LABEL: store_v8i16_a32:
194; CHECK-NEXT: .functype store_v8i16_a32 (i32, v128) -> (){{$}}
195; CHECK-NEXT: v128.store 0($0), $1{{$}}
196; CHECK-NEXT: return{{$}}
197define void @store_v8i16_a32(<8 x i16> *%p, <8 x i16> %v) {
198  store <8 x i16> %v, <8 x i16>* %p, align 32
199  ret void
200}
201
202; CHECK-LABEL: load_ext_v8i16_a1:
203; CHECK-NEXT: .functype load_ext_v8i16_a1 (i32) -> (v128){{$}}
204; CHECK-NEXT: i16x8.load8x8_u $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
205; CHECK-NEXT: return $pop[[R]]{{$}}
206define <8 x i8> @load_ext_v8i16_a1(<8 x i8>* %p) {
207  %v = load <8 x i8>, <8 x i8>* %p, align 1
208  ret <8 x i8> %v
209}
210
211; CHECK-LABEL: load_ext_v8i16_a2:
212; CHECK-NEXT: .functype load_ext_v8i16_a2 (i32) -> (v128){{$}}
213; CHECK-NEXT: i16x8.load8x8_u $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
214; CHECK-NEXT: return $pop[[R]]{{$}}
215define <8 x i8> @load_ext_v8i16_a2(<8 x i8>* %p) {
216  %v = load <8 x i8>, <8 x i8>* %p, align 2
217  ret <8 x i8> %v
218}
219
220; CHECK-LABEL: load_ext_v8i16_a4:
221; CHECK-NEXT: .functype load_ext_v8i16_a4 (i32) -> (v128){{$}}
222; CHECK-NEXT: i16x8.load8x8_u $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
223; CHECK-NEXT: return $pop[[R]]{{$}}
224define <8 x i8> @load_ext_v8i16_a4(<8 x i8>* %p) {
225  %v = load <8 x i8>, <8 x i8>* %p, align 4
226  ret <8 x i8> %v
227}
228
229; 8 is the default alignment for v128 extending load so no attribute is needed.
230
231; CHECK-LABEL: load_ext_v8i16_a8:
232; CHECK-NEXT: .functype load_ext_v8i16_a8 (i32) -> (v128){{$}}
233; CHECK-NEXT: i16x8.load8x8_u $push[[R:[0-9]+]]=, 0($0){{$}}
234; CHECK-NEXT: return $pop[[R]]{{$}}
235define <8 x i8> @load_ext_v8i16_a8(<8 x i8>* %p) {
236  %v = load <8 x i8>, <8 x i8>* %p, align 8
237  ret <8 x i8> %v
238}
239
240; 16 is greater than the default alignment so it is ignored.
241
242; CHECK-LABEL: load_ext_v8i16_a16:
243; CHECK-NEXT: .functype load_ext_v8i16_a16 (i32) -> (v128){{$}}
244; CHECK-NEXT: i16x8.load8x8_u $push[[R:[0-9]+]]=, 0($0){{$}}
245; CHECK-NEXT: return $pop[[R]]{{$}}
246define <8 x i8> @load_ext_v8i16_a16(<8 x i8>* %p) {
247  %v = load <8 x i8>, <8 x i8>* %p, align 16
248  ret <8 x i8> %v
249}
250
251; CHECK-LABEL: load_sext_v8i16_a1:
252; CHECK-NEXT: .functype load_sext_v8i16_a1 (i32) -> (v128){{$}}
253; CHECK-NEXT: i16x8.load8x8_s $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
254; CHECK-NEXT: return $pop[[R]]{{$}}
255define <8 x i16> @load_sext_v8i16_a1(<8 x i8>* %p) {
256  %v = load <8 x i8>, <8 x i8>* %p, align 1
257  %v2 = sext <8 x i8> %v to <8 x i16>
258  ret <8 x i16> %v2
259}
260
261; CHECK-LABEL: load_sext_v8i16_a2:
262; CHECK-NEXT: .functype load_sext_v8i16_a2 (i32) -> (v128){{$}}
263; CHECK-NEXT: i16x8.load8x8_s $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
264; CHECK-NEXT: return $pop[[R]]{{$}}
265define <8 x i16> @load_sext_v8i16_a2(<8 x i8>* %p) {
266  %v = load <8 x i8>, <8 x i8>* %p, align 2
267  %v2 = sext <8 x i8> %v to <8 x i16>
268  ret <8 x i16> %v2
269}
270
271; CHECK-LABEL: load_sext_v8i16_a4:
272; CHECK-NEXT: .functype load_sext_v8i16_a4 (i32) -> (v128){{$}}
273; CHECK-NEXT: i16x8.load8x8_s $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
274; CHECK-NEXT: return $pop[[R]]{{$}}
275define <8 x i16> @load_sext_v8i16_a4(<8 x i8>* %p) {
276  %v = load <8 x i8>, <8 x i8>* %p, align 4
277  %v2 = sext <8 x i8> %v to <8 x i16>
278  ret <8 x i16> %v2
279}
280
281; 8 is the default alignment for v128 extending load so no attribute is needed.
282
283; CHECK-LABEL: load_sext_v8i16_a8:
284; CHECK-NEXT: .functype load_sext_v8i16_a8 (i32) -> (v128){{$}}
285; CHECK-NEXT: i16x8.load8x8_s $push[[R:[0-9]+]]=, 0($0){{$}}
286; CHECK-NEXT: return $pop[[R]]{{$}}
287define <8 x i16> @load_sext_v8i16_a8(<8 x i8>* %p) {
288  %v = load <8 x i8>, <8 x i8>* %p, align 8
289  %v2 = sext <8 x i8> %v to <8 x i16>
290  ret <8 x i16> %v2
291}
292
293; 16 is greater than the default alignment so it is ignored.
294
295; CHECK-LABEL: load_sext_v8i16_a16:
296; CHECK-NEXT: .functype load_sext_v8i16_a16 (i32) -> (v128){{$}}
297; CHECK-NEXT: i16x8.load8x8_s $push[[R:[0-9]+]]=, 0($0){{$}}
298; CHECK-NEXT: return $pop[[R]]{{$}}
299define <8 x i16> @load_sext_v8i16_a16(<8 x i8>* %p) {
300  %v = load <8 x i8>, <8 x i8>* %p, align 16
301  %v2 = sext <8 x i8> %v to <8 x i16>
302  ret <8 x i16> %v2
303}
304
305; CHECK-LABEL: load_splat_v8i16_a1:
306; CHECK-NEXT: .functype load_splat_v8i16_a1 (i32) -> (v128){{$}}
307; CHECK-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
308; CHECK-NEXT: return $pop[[R]]{{$}}
309define <8 x i16> @load_splat_v8i16_a1(i16* %p) {
310  %e = load i16, i16* %p, align 1
311  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
312  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
313  ret <8 x i16> %v2
314}
315
316; 2 is the default alignment for v16x8.load_splat so no attribute is needed.
317
318; CHECK-LABEL: load_splat_v8i16_a2:
319; CHECK-NEXT: .functype load_splat_v8i16_a2 (i32) -> (v128){{$}}
320; CHECK-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
321; CHECK-NEXT: return $pop[[R]]{{$}}
322define <8 x i16> @load_splat_v8i16_a2(i16* %p) {
323  %e = load i16, i16* %p, align 2
324  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
325  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
326  ret <8 x i16> %v2
327}
328
329; 4 is greater than the default alignment so it is ignored.
330
331; CHECK-LABEL: load_splat_v8i16_a4:
332; CHECK-NEXT: .functype load_splat_v8i16_a4 (i32) -> (v128){{$}}
333; CHECK-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
334; CHECK-NEXT: return $pop[[R]]{{$}}
335define <8 x i16> @load_splat_v8i16_a4(i16* %p) {
336  %e = load i16, i16* %p, align 4
337  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
338  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
339  ret <8 x i16> %v2
340}
341
342; ==============================================================================
343; 4 x i32
344; ==============================================================================
345
346; CHECK-LABEL: load_v4i32_a1:
347; CHECK-NEXT: .functype load_v4i32_a1 (i32) -> (v128){{$}}
348; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
349; CHECK-NEXT: return $pop[[R]]{{$}}
350define <4 x i32> @load_v4i32_a1(<4 x i32> *%p) {
351  %v = load <4 x i32>, <4 x i32>* %p, align 1
352  ret <4 x i32> %v
353}
354
355; CHECK-LABEL: load_v4i32_a4:
356; CHECK-NEXT: .functype load_v4i32_a4 (i32) -> (v128){{$}}
357; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
358; CHECK-NEXT: return $pop[[R]]{{$}}
359define <4 x i32> @load_v4i32_a4(<4 x i32> *%p) {
360  %v = load <4 x i32>, <4 x i32>* %p, align 4
361  ret <4 x i32> %v
362}
363
364; 4 is the default alignment for v128 so no attribute is needed.
365
366; CHECK-LABEL: load_v4i32_a16:
367; CHECK-NEXT: .functype load_v4i32_a16 (i32) -> (v128){{$}}
368; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
369; CHECK-NEXT: return $pop[[R]]{{$}}
370define <4 x i32> @load_v4i32_a16(<4 x i32> *%p) {
371  %v = load <4 x i32>, <4 x i32>* %p, align 16
372  ret <4 x i32> %v
373}
374
375; 32 is greater than the default alignment so it is ignored.
376
377; CHECK-LABEL: load_v4i32_a32:
378; CHECK-NEXT: .functype load_v4i32_a32 (i32) -> (v128){{$}}
379; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
380; CHECK-NEXT: return $pop[[R]]{{$}}
381define <4 x i32> @load_v4i32_a32(<4 x i32> *%p) {
382  %v = load <4 x i32>, <4 x i32>* %p, align 32
383  ret <4 x i32> %v
384}
385
386; CHECK-LABEL: store_v4i32_a1:
387; CHECK-NEXT: .functype store_v4i32_a1 (i32, v128) -> (){{$}}
388; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
389; CHECK-NEXT: return{{$}}
390define void @store_v4i32_a1(<4 x i32> *%p, <4 x i32> %v) {
391  store <4 x i32> %v, <4 x i32>* %p, align 1
392  ret void
393}
394
395; CHECK-LABEL: store_v4i32_a4:
396; CHECK-NEXT: .functype store_v4i32_a4 (i32, v128) -> (){{$}}
397; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
398; CHECK-NEXT: return{{$}}
399define void @store_v4i32_a4(<4 x i32> *%p, <4 x i32> %v) {
400  store <4 x i32> %v, <4 x i32>* %p, align 4
401  ret void
402}
403
404; 16 is the default alignment for v128 so no attribute is needed.
405
406; CHECK-LABEL: store_v4i32_a16:
407; CHECK-NEXT: .functype store_v4i32_a16 (i32, v128) -> (){{$}}
408; CHECK-NEXT: v128.store 0($0), $1{{$}}
409; CHECK-NEXT: return{{$}}
410define void @store_v4i32_a16(<4 x i32> *%p, <4 x i32> %v) {
411  store <4 x i32> %v, <4 x i32>* %p, align 16
412  ret void
413}
414
415; 32 is greater than the default alignment so it is ignored.
416
417; CHECK-LABEL: store_v4i32_a32:
418; CHECK-NEXT: .functype store_v4i32_a32 (i32, v128) -> (){{$}}
419; CHECK-NEXT: v128.store 0($0), $1{{$}}
420; CHECK-NEXT: return{{$}}
421define void @store_v4i32_a32(<4 x i32> *%p, <4 x i32> %v) {
422  store <4 x i32> %v, <4 x i32>* %p, align 32
423  ret void
424}
425
426; CHECK-LABEL: load_ext_v4i32_a1:
427; CHECK-NEXT: .functype load_ext_v4i32_a1 (i32) -> (v128){{$}}
428; CHECK-NEXT: i32x4.load16x4_u $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
429; CHECK-NEXT: return $pop[[R]]{{$}}
430define <4 x i16> @load_ext_v4i32_a1(<4 x i16>* %p) {
431  %v = load <4 x i16>, <4 x i16>* %p, align 1
432  ret <4 x i16> %v
433}
434
435; CHECK-LABEL: load_ext_v4i32_a2:
436; CHECK-NEXT: .functype load_ext_v4i32_a2 (i32) -> (v128){{$}}
437; CHECK-NEXT: i32x4.load16x4_u $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
438; CHECK-NEXT: return $pop[[R]]{{$}}
439define <4 x i16> @load_ext_v4i32_a2(<4 x i16>* %p) {
440  %v = load <4 x i16>, <4 x i16>* %p, align 2
441  ret <4 x i16> %v
442}
443
444; CHECK-LABEL: load_ext_v4i32_a4:
445; CHECK-NEXT: .functype load_ext_v4i32_a4 (i32) -> (v128){{$}}
446; CHECK-NEXT: i32x4.load16x4_u $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
447; CHECK-NEXT: return $pop[[R]]{{$}}
448define <4 x i16> @load_ext_v4i32_a4(<4 x i16>* %p) {
449  %v = load <4 x i16>, <4 x i16>* %p, align 4
450  ret <4 x i16> %v
451}
452
453; 8 is the default alignment for v128 extending load so no attribute is needed.
454
455; CHECK-LABEL: load_ext_v4i32_a8:
456; CHECK-NEXT: .functype load_ext_v4i32_a8 (i32) -> (v128){{$}}
457; CHECK-NEXT: i32x4.load16x4_u $push[[R:[0-9]+]]=, 0($0){{$}}
458; CHECK-NEXT: return $pop[[R]]{{$}}
459define <4 x i16> @load_ext_v4i32_a8(<4 x i16>* %p) {
460  %v = load <4 x i16>, <4 x i16>* %p, align 8
461  ret <4 x i16> %v
462}
463
464; 16 is greater than the default alignment so it is ignored.
465
466; CHECK-LABEL: load_ext_v4i32_a16:
467; CHECK-NEXT: .functype load_ext_v4i32_a16 (i32) -> (v128){{$}}
468; CHECK-NEXT: i32x4.load16x4_u $push[[R:[0-9]+]]=, 0($0){{$}}
469; CHECK-NEXT: return $pop[[R]]{{$}}
470define <4 x i16> @load_ext_v4i32_a16(<4 x i16>* %p) {
471  %v = load <4 x i16>, <4 x i16>* %p, align 16
472  ret <4 x i16> %v
473}
474
475; CHECK-LABEL: load_sext_v4i32_a1:
476; CHECK-NEXT: .functype load_sext_v4i32_a1 (i32) -> (v128){{$}}
477; CHECK-NEXT: i32x4.load16x4_s $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
478; CHECK-NEXT: return $pop[[R]]{{$}}
479define <4 x i32> @load_sext_v4i32_a1(<4 x i16>* %p) {
480  %v = load <4 x i16>, <4 x i16>* %p, align 1
481  %v2 = sext <4 x i16> %v to <4 x i32>
482  ret <4 x i32> %v2
483}
484
485; CHECK-LABEL: load_sext_v4i32_a2:
486; CHECK-NEXT: .functype load_sext_v4i32_a2 (i32) -> (v128){{$}}
487; CHECK-NEXT: i32x4.load16x4_s $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
488; CHECK-NEXT: return $pop[[R]]{{$}}
489define <4 x i32> @load_sext_v4i32_a2(<4 x i16>* %p) {
490  %v = load <4 x i16>, <4 x i16>* %p, align 2
491  %v2 = sext <4 x i16> %v to <4 x i32>
492  ret <4 x i32> %v2
493}
494
495; CHECK-LABEL: load_sext_v4i32_a4:
496; CHECK-NEXT: .functype load_sext_v4i32_a4 (i32) -> (v128){{$}}
497; CHECK-NEXT: i32x4.load16x4_s $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
498; CHECK-NEXT: return $pop[[R]]{{$}}
499define <4 x i32> @load_sext_v4i32_a4(<4 x i16>* %p) {
500  %v = load <4 x i16>, <4 x i16>* %p, align 4
501  %v2 = sext <4 x i16> %v to <4 x i32>
502  ret <4 x i32> %v2
503}
504
505; 8 is the default alignment for v128 extending load so no attribute is needed.
506
507; CHECK-LABEL: load_sext_v4i32_a8:
508; CHECK-NEXT: .functype load_sext_v4i32_a8 (i32) -> (v128){{$}}
509; CHECK-NEXT: i32x4.load16x4_s $push[[R:[0-9]+]]=, 0($0){{$}}
510; CHECK-NEXT: return $pop[[R]]{{$}}
511define <4 x i32> @load_sext_v4i32_a8(<4 x i16>* %p) {
512  %v = load <4 x i16>, <4 x i16>* %p, align 8
513  %v2 = sext <4 x i16> %v to <4 x i32>
514  ret <4 x i32> %v2
515}
516
517; 16 is greater than the default alignment so it is ignored.
518
519; CHECK-LABEL: load_sext_v4i32_a16:
520; CHECK-NEXT: .functype load_sext_v4i32_a16 (i32) -> (v128){{$}}
521; CHECK-NEXT: i32x4.load16x4_s $push[[R:[0-9]+]]=, 0($0){{$}}
522; CHECK-NEXT: return $pop[[R]]{{$}}
523define <4 x i32> @load_sext_v4i32_a16(<4 x i16>* %p) {
524  %v = load <4 x i16>, <4 x i16>* %p, align 16
525  %v2 = sext <4 x i16> %v to <4 x i32>
526  ret <4 x i32> %v2
527}
528
529; CHECK-LABEL: load_splat_v4i32_a1:
530; CHECK-NEXT: .functype load_splat_v4i32_a1 (i32) -> (v128){{$}}
531; CHECK-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
532; CHECK-NEXT: return $pop[[R]]{{$}}
533define <4 x i32> @load_splat_v4i32_a1(i32* %addr) {
534  %e = load i32, i32* %addr, align 1
535  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
536  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
537  ret <4 x i32> %v2
538}
539
540; CHECK-LABEL: load_splat_v4i32_a2:
541; CHECK-NEXT: .functype load_splat_v4i32_a2 (i32) -> (v128){{$}}
542; CHECK-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
543; CHECK-NEXT: return $pop[[R]]{{$}}
544define <4 x i32> @load_splat_v4i32_a2(i32* %addr) {
545  %e = load i32, i32* %addr, align 2
546  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
547  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
548  ret <4 x i32> %v2
549}
550
551; 4 is the default alignment for v32x4.load_splat so no attribute is needed.
552
553; CHECK-LABEL: load_splat_v4i32_a4:
554; CHECK-NEXT: .functype load_splat_v4i32_a4 (i32) -> (v128){{$}}
555; CHECK-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
556; CHECK-NEXT: return $pop[[R]]{{$}}
557define <4 x i32> @load_splat_v4i32_a4(i32* %addr) {
558  %e = load i32, i32* %addr, align 4
559  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
560  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
561  ret <4 x i32> %v2
562}
563
564; 8 is greater than the default alignment so it is ignored.
565
566; CHECK-LABEL: load_splat_v4i32_a8:
567; CHECK-NEXT: .functype load_splat_v4i32_a8 (i32) -> (v128){{$}}
568; CHECK-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
569; CHECK-NEXT: return $pop[[R]]{{$}}
570define <4 x i32> @load_splat_v4i32_a8(i32* %addr) {
571  %e = load i32, i32* %addr, align 8
572  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
573  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
574  ret <4 x i32> %v2
575}
576
577; ==============================================================================
578; 2 x i64
579; ==============================================================================
580
581; CHECK-LABEL: load_v2i64_a1:
582; CHECK-NEXT: .functype load_v2i64_a1 (i32) -> (v128){{$}}
583; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
584; CHECK-NEXT: return $pop[[R]]{{$}}
585define <2 x i64> @load_v2i64_a1(<2 x i64> *%p) {
586  %v = load <2 x i64>, <2 x i64>* %p, align 1
587  ret <2 x i64> %v
588}
589
590; CHECK-LABEL: load_v2i64_a4:
591; CHECK-NEXT: .functype load_v2i64_a4 (i32) -> (v128){{$}}
592; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
593; CHECK-NEXT: return $pop[[R]]{{$}}
594define <2 x i64> @load_v2i64_a4(<2 x i64> *%p) {
595  %v = load <2 x i64>, <2 x i64>* %p, align 4
596  ret <2 x i64> %v
597}
598
599; 2 is the default alignment for v128 so no attribute is needed.
600
601; CHECK-LABEL: load_v2i64_a16:
602; CHECK-NEXT: .functype load_v2i64_a16 (i32) -> (v128){{$}}
603; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
604; CHECK-NEXT: return $pop[[R]]{{$}}
605define <2 x i64> @load_v2i64_a16(<2 x i64> *%p) {
606  %v = load <2 x i64>, <2 x i64>* %p, align 16
607  ret <2 x i64> %v
608}
609
610; 32 is greater than the default alignment so it is ignored.
611
612; CHECK-LABEL: load_v2i64_a32:
613; CHECK-NEXT: .functype load_v2i64_a32 (i32) -> (v128){{$}}
614; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
615; CHECK-NEXT: return $pop[[R]]{{$}}
616define <2 x i64> @load_v2i64_a32(<2 x i64> *%p) {
617  %v = load <2 x i64>, <2 x i64>* %p, align 32
618  ret <2 x i64> %v
619}
620
621; CHECK-LABEL: store_v2i64_a1:
622; CHECK-NEXT: .functype store_v2i64_a1 (i32, v128) -> (){{$}}
623; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
624; CHECK-NEXT: return{{$}}
625define void @store_v2i64_a1(<2 x i64> *%p, <2 x i64> %v) {
626  store <2 x i64> %v, <2 x i64>* %p, align 1
627  ret void
628}
629
630; CHECK-LABEL: store_v2i64_a4:
631; CHECK-NEXT: .functype store_v2i64_a4 (i32, v128) -> (){{$}}
632; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
633; CHECK-NEXT: return{{$}}
634define void @store_v2i64_a4(<2 x i64> *%p, <2 x i64> %v) {
635  store <2 x i64> %v, <2 x i64>* %p, align 4
636  ret void
637}
638
639; 16 is the default alignment for v128 so no attribute is needed.
640
641; CHECK-LABEL: store_v2i64_a16:
642; CHECK-NEXT: .functype store_v2i64_a16 (i32, v128) -> (){{$}}
643; CHECK-NEXT: v128.store 0($0), $1{{$}}
644; CHECK-NEXT: return{{$}}
645define void @store_v2i64_a16(<2 x i64> *%p, <2 x i64> %v) {
646  store <2 x i64> %v, <2 x i64>* %p, align 16
647  ret void
648}
649
650; 32 is greater than the default alignment so it is ignored.
651
652; CHECK-LABEL: store_v2i64_a32:
653; CHECK-NEXT: .functype store_v2i64_a32 (i32, v128) -> (){{$}}
654; CHECK-NEXT: v128.store 0($0), $1{{$}}
655; CHECK-NEXT: return{{$}}
656define void @store_v2i64_a32(<2 x i64> *%p, <2 x i64> %v) {
657  store <2 x i64> %v, <2 x i64>* %p, align 32
658  ret void
659}
660
661; CHECK-LABEL: load_splat_v2i64_a1:
662; CHECK-NEXT: .functype load_splat_v2i64_a1 (i32) -> (v128){{$}}
663; CHECK-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
664; CHECK-NEXT: return $pop[[R]]{{$}}
665define <2 x i64> @load_splat_v2i64_a1(i64* %p) {
666  %e = load i64, i64* %p, align 1
667  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
668  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
669  ret <2 x i64> %v2
670}
671
672; CHECK-LABEL: load_splat_v2i64_a2:
673; CHECK-NEXT: .functype load_splat_v2i64_a2 (i32) -> (v128){{$}}
674; CHECK-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=1{{$}}
675; CHECK-NEXT: return $pop[[R]]{{$}}
676define <2 x i64> @load_splat_v2i64_a2(i64* %p) {
677  %e = load i64, i64* %p, align 2
678  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
679  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
680  ret <2 x i64> %v2
681}
682
683; CHECK-LABEL: load_splat_v2i64_a4:
684; CHECK-NEXT: .functype load_splat_v2i64_a4 (i32) -> (v128){{$}}
685; CHECK-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
686; CHECK-NEXT: return $pop[[R]]{{$}}
687define <2 x i64> @load_splat_v2i64_a4(i64* %p) {
688  %e = load i64, i64* %p, align 4
689  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
690  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
691  ret <2 x i64> %v2
692}
693
694; 8 is the default alignment for v64x2.load_splat so no attribute is needed.
695
696; CHECK-LABEL: load_splat_v2i64_a8:
697; CHECK-NEXT: .functype load_splat_v2i64_a8 (i32) -> (v128){{$}}
698; CHECK-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
699; CHECK-NEXT: return $pop[[R]]{{$}}
700define <2 x i64> @load_splat_v2i64_a8(i64* %p) {
701  %e = load i64, i64* %p, align 8
702  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
703  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
704  ret <2 x i64> %v2
705}
706
707; 16 is greater than the default alignment so it is ignored.
708
709; CHECK-LABEL: load_splat_v2i64_a16:
710; CHECK-NEXT: .functype load_splat_v2i64_a16 (i32) -> (v128){{$}}
711; CHECK-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0){{$}}
712; CHECK-NEXT: return $pop[[R]]{{$}}
713define <2 x i64> @load_splat_v2i64_a16(i64* %p) {
714  %e = load i64, i64* %p, align 16
715  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
716  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
717  ret <2 x i64> %v2
718}
719
720; ==============================================================================
721; 4 x float
722; ==============================================================================
723
724; CHECK-LABEL: load_v4f32_a1:
725; CHECK-NEXT: .functype load_v4f32_a1 (i32) -> (v128){{$}}
726; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
727; CHECK-NEXT: return $pop[[R]]{{$}}
728define <4 x float> @load_v4f32_a1(<4 x float> *%p) {
729  %v = load <4 x float>, <4 x float>* %p, align 1
730  ret <4 x float> %v
731}
732
733; CHECK-LABEL: load_v4f32_a4:
734; CHECK-NEXT: .functype load_v4f32_a4 (i32) -> (v128){{$}}
735; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
736; CHECK-NEXT: return $pop[[R]]{{$}}
737define <4 x float> @load_v4f32_a4(<4 x float> *%p) {
738  %v = load <4 x float>, <4 x float>* %p, align 4
739  ret <4 x float> %v
740}
741
742; 4 is the default alignment for v128 so no attribute is needed.
743
744; CHECK-LABEL: load_v4f32_a16:
745; CHECK-NEXT: .functype load_v4f32_a16 (i32) -> (v128){{$}}
746; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
747; CHECK-NEXT: return $pop[[R]]{{$}}
748define <4 x float> @load_v4f32_a16(<4 x float> *%p) {
749  %v = load <4 x float>, <4 x float>* %p, align 16
750  ret <4 x float> %v
751}
752
753; 32 is greater than the default alignment so it is ignored.
754
755; CHECK-LABEL: load_v4f32_a32:
756; CHECK-NEXT: .functype load_v4f32_a32 (i32) -> (v128){{$}}
757; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
758; CHECK-NEXT: return $pop[[R]]{{$}}
759define <4 x float> @load_v4f32_a32(<4 x float> *%p) {
760  %v = load <4 x float>, <4 x float>* %p, align 32
761  ret <4 x float> %v
762}
763
764; CHECK-LABEL: store_v4f32_a1:
765; CHECK-NEXT: .functype store_v4f32_a1 (i32, v128) -> (){{$}}
766; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
767; CHECK-NEXT: return{{$}}
768define void @store_v4f32_a1(<4 x float> *%p, <4 x float> %v) {
769  store <4 x float> %v, <4 x float>* %p, align 1
770  ret void
771}
772
773; CHECK-LABEL: store_v4f32_a4:
774; CHECK-NEXT: .functype store_v4f32_a4 (i32, v128) -> (){{$}}
775; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
776; CHECK-NEXT: return{{$}}
777define void @store_v4f32_a4(<4 x float> *%p, <4 x float> %v) {
778  store <4 x float> %v, <4 x float>* %p, align 4
779  ret void
780}
781
782; 16 is the default alignment for v128 so no attribute is needed.
783
784; CHECK-LABEL: store_v4f32_a16:
785; CHECK-NEXT: .functype store_v4f32_a16 (i32, v128) -> (){{$}}
786; CHECK-NEXT: v128.store 0($0), $1{{$}}
787; CHECK-NEXT: return{{$}}
788define void @store_v4f32_a16(<4 x float> *%p, <4 x float> %v) {
789  store <4 x float> %v, <4 x float>* %p, align 16
790  ret void
791}
792
793; 32 is greater than the default alignment so it is ignored.
794
795; CHECK-LABEL: store_v4f32_a32:
796; CHECK-NEXT: .functype store_v4f32_a32 (i32, v128) -> (){{$}}
797; CHECK-NEXT: v128.store 0($0), $1{{$}}
798; CHECK-NEXT: return{{$}}
799define void @store_v4f32_a32(<4 x float> *%p, <4 x float> %v) {
800  store <4 x float> %v, <4 x float>* %p, align 32
801  ret void
802}
803
804; ==============================================================================
805; 2 x double
806; ==============================================================================
807
808; CHECK-LABEL: load_v2f64_a1:
809; CHECK-NEXT: .functype load_v2f64_a1 (i32) -> (v128){{$}}
810; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=0{{$}}
811; CHECK-NEXT: return $pop[[R]]{{$}}
812define <2 x double> @load_v2f64_a1(<2 x double> *%p) {
813  %v = load <2 x double>, <2 x double>* %p, align 1
814  ret <2 x double> %v
815}
816
817; CHECK-LABEL: load_v2f64_a4:
818; CHECK-NEXT: .functype load_v2f64_a4 (i32) -> (v128){{$}}
819; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0):p2align=2{{$}}
820; CHECK-NEXT: return $pop[[R]]{{$}}
821define <2 x double> @load_v2f64_a4(<2 x double> *%p) {
822  %v = load <2 x double>, <2 x double>* %p, align 4
823  ret <2 x double> %v
824}
825
826; 2 is the default alignment for v128 so no attribute is needed.
827
828; CHECK-LABEL: load_v2f64_a16:
829; CHECK-NEXT: .functype load_v2f64_a16 (i32) -> (v128){{$}}
830; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
831; CHECK-NEXT: return $pop[[R]]{{$}}
832define <2 x double> @load_v2f64_a16(<2 x double> *%p) {
833  %v = load <2 x double>, <2 x double>* %p, align 16
834  ret <2 x double> %v
835}
836
837; 32 is greater than the default alignment so it is ignored.
838
839; CHECK-LABEL: load_v2f64_a32:
840; CHECK-NEXT: .functype load_v2f64_a32 (i32) -> (v128){{$}}
841; CHECK-NEXT: v128.load $push[[R:[0-9]+]]=, 0($0){{$}}
842; CHECK-NEXT: return $pop[[R]]{{$}}
843define <2 x double> @load_v2f64_a32(<2 x double> *%p) {
844  %v = load <2 x double>, <2 x double>* %p, align 32
845  ret <2 x double> %v
846}
847
848; CHECK-LABEL: store_v2f64_a1:
849; CHECK-NEXT: .functype store_v2f64_a1 (i32, v128) -> (){{$}}
850; CHECK-NEXT: v128.store 0($0):p2align=0, $1{{$}}
851; CHECK-NEXT: return{{$}}
852define void @store_v2f64_a1(<2 x double> *%p, <2 x double> %v) {
853  store <2 x double> %v, <2 x double>* %p, align 1
854  ret void
855}
856
857; CHECK-LABEL: store_v2f64_a4:
858; CHECK-NEXT: .functype store_v2f64_a4 (i32, v128) -> (){{$}}
859; CHECK-NEXT: v128.store 0($0):p2align=2, $1{{$}}
860; CHECK-NEXT: return{{$}}
861define void @store_v2f64_a4(<2 x double> *%p, <2 x double> %v) {
862  store <2 x double> %v, <2 x double>* %p, align 4
863  ret void
864}
865
866; 16 is the default alignment for v128 so no attribute is needed.
867
868; CHECK-LABEL: store_v2f64_a16:
869; CHECK-NEXT: .functype store_v2f64_a16 (i32, v128) -> (){{$}}
870; CHECK-NEXT: v128.store 0($0), $1{{$}}
871; CHECK-NEXT: return{{$}}
872define void @store_v2f64_a16(<2 x double> *%p, <2 x double> %v) {
873  store <2 x double> %v, <2 x double>* %p, align 16
874  ret void
875}
876
877; 32 is greater than the default alignment so it is ignored.
878
879; CHECK-LABEL: store_v2f64_a32:
880; CHECK-NEXT: .functype store_v2f64_a32 (i32, v128) -> (){{$}}
881; CHECK-NEXT: v128.store 0($0), $1{{$}}
882; CHECK-NEXT: return{{$}}
883define void @store_v2f64_a32(<2 x double> *%p, <2 x double> %v) {
884  store <2 x double> %v, <2 x double>* %p, align 32
885  ret void
886}
887