1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -verify-machineinstrs -mattr=+simd128 | FileCheck %s
3
4; Test loads and stores with custom alignment values.
5
6target triple = "wasm32-unknown-unknown"
7
8; ==============================================================================
9; 16 x i8
10; ==============================================================================
11
12define <16 x i8> @load_v16i8_a1(<16 x i8> *%p) {
13; CHECK-LABEL: load_v16i8_a1:
14; CHECK:         .functype load_v16i8_a1 (i32) -> (v128)
15; CHECK-NEXT:  # %bb.0:
16; CHECK-NEXT:    local.get 0
17; CHECK-NEXT:    v128.load 0:p2align=0
18; CHECK-NEXT:    # fallthrough-return
19  %v = load <16 x i8>, <16 x i8>* %p, align 1
20  ret <16 x i8> %v
21}
22
23define <16 x i8> @load_v16i8_a4(<16 x i8> *%p) {
24; CHECK-LABEL: load_v16i8_a4:
25; CHECK:         .functype load_v16i8_a4 (i32) -> (v128)
26; CHECK-NEXT:  # %bb.0:
27; CHECK-NEXT:    local.get 0
28; CHECK-NEXT:    v128.load 0:p2align=2
29; CHECK-NEXT:    # fallthrough-return
30  %v = load <16 x i8>, <16 x i8>* %p, align 4
31  ret <16 x i8> %v
32}
33
34; 16 is the default alignment for v128 so no attribute is needed.
35define <16 x i8> @load_v16i8_a16(<16 x i8> *%p) {
36; CHECK-LABEL: load_v16i8_a16:
37; CHECK:         .functype load_v16i8_a16 (i32) -> (v128)
38; CHECK-NEXT:  # %bb.0:
39; CHECK-NEXT:    local.get 0
40; CHECK-NEXT:    v128.load 0
41; CHECK-NEXT:    # fallthrough-return
42  %v = load <16 x i8>, <16 x i8>* %p, align 16
43  ret <16 x i8> %v
44}
45
46; 32 is greater than the default alignment so it is ignored.
47define <16 x i8> @load_v16i8_a32(<16 x i8> *%p) {
48; CHECK-LABEL: load_v16i8_a32:
49; CHECK:         .functype load_v16i8_a32 (i32) -> (v128)
50; CHECK-NEXT:  # %bb.0:
51; CHECK-NEXT:    local.get 0
52; CHECK-NEXT:    v128.load 0
53; CHECK-NEXT:    # fallthrough-return
54  %v = load <16 x i8>, <16 x i8>* %p, align 32
55  ret <16 x i8> %v
56}
57
58define void @store_v16i8_a1(<16 x i8> *%p, <16 x i8> %v) {
59; CHECK-LABEL: store_v16i8_a1:
60; CHECK:         .functype store_v16i8_a1 (i32, v128) -> ()
61; CHECK-NEXT:  # %bb.0:
62; CHECK-NEXT:    local.get 0
63; CHECK-NEXT:    local.get 1
64; CHECK-NEXT:    v128.store 0:p2align=0
65; CHECK-NEXT:    # fallthrough-return
66  store <16 x i8> %v, <16 x i8>* %p, align 1
67  ret void
68}
69
70define void @store_v16i8_a4(<16 x i8> *%p, <16 x i8> %v) {
71; CHECK-LABEL: store_v16i8_a4:
72; CHECK:         .functype store_v16i8_a4 (i32, v128) -> ()
73; CHECK-NEXT:  # %bb.0:
74; CHECK-NEXT:    local.get 0
75; CHECK-NEXT:    local.get 1
76; CHECK-NEXT:    v128.store 0:p2align=2
77; CHECK-NEXT:    # fallthrough-return
78  store <16 x i8> %v, <16 x i8>* %p, align 4
79  ret void
80}
81
82; 16 is the default alignment for v128 so no attribute is needed.
83define void @store_v16i8_a16(<16 x i8> *%p, <16 x i8> %v) {
84; CHECK-LABEL: store_v16i8_a16:
85; CHECK:         .functype store_v16i8_a16 (i32, v128) -> ()
86; CHECK-NEXT:  # %bb.0:
87; CHECK-NEXT:    local.get 0
88; CHECK-NEXT:    local.get 1
89; CHECK-NEXT:    v128.store 0
90; CHECK-NEXT:    # fallthrough-return
91  store <16 x i8> %v, <16 x i8>* %p, align 16
92  ret void
93}
94
95; 32 is greater than the default alignment so it is ignored.
96define void @store_v16i8_a32(<16 x i8> *%p, <16 x i8> %v) {
97; CHECK-LABEL: store_v16i8_a32:
98; CHECK:         .functype store_v16i8_a32 (i32, v128) -> ()
99; CHECK-NEXT:  # %bb.0:
100; CHECK-NEXT:    local.get 0
101; CHECK-NEXT:    local.get 1
102; CHECK-NEXT:    v128.store 0
103; CHECK-NEXT:    # fallthrough-return
104  store <16 x i8> %v, <16 x i8>* %p, align 32
105  ret void
106}
107
108; 1 is the default alignment for v128.load8_splat so no attribute is needed.
109define <16 x i8> @load_splat_v16i8_a1(i8* %p) {
110; CHECK-LABEL: load_splat_v16i8_a1:
111; CHECK:         .functype load_splat_v16i8_a1 (i32) -> (v128)
112; CHECK-NEXT:  # %bb.0:
113; CHECK-NEXT:    local.get 0
114; CHECK-NEXT:    v128.load8_splat 0
115; CHECK-NEXT:    # fallthrough-return
116  %e = load i8, i8* %p, align 1
117  %v1 = insertelement <16 x i8> undef, i8 %e, i32 0
118  %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer
119  ret <16 x i8> %v2
120}
121
122; 2 is greater than the default alignment so it is ignored.
123define <16 x i8> @load_splat_v16i8_a2(i8* %p) {
124; CHECK-LABEL: load_splat_v16i8_a2:
125; CHECK:         .functype load_splat_v16i8_a2 (i32) -> (v128)
126; CHECK-NEXT:  # %bb.0:
127; CHECK-NEXT:    local.get 0
128; CHECK-NEXT:    v128.load8_splat 0
129; CHECK-NEXT:    # fallthrough-return
130  %e = load i8, i8* %p, align 2
131  %v1 = insertelement <16 x i8> undef, i8 %e, i32 0
132  %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer
133  ret <16 x i8> %v2
134}
135
136; 1 is the default alignment for v128.load8_lane so no attribute is needed.
137define <16 x i8> @load_lane_i8_a1(i8* %p, <16 x i8> %v) {
138; CHECK-LABEL: load_lane_i8_a1:
139; CHECK:         .functype load_lane_i8_a1 (i32, v128) -> (v128)
140; CHECK-NEXT:  # %bb.0:
141; CHECK-NEXT:    local.get 0
142; CHECK-NEXT:    local.get 1
143; CHECK-NEXT:    v128.load8_lane 0, 0
144; CHECK-NEXT:    # fallthrough-return
145  %e = load i8, i8* %p, align 1
146  %v1 = insertelement <16 x i8> %v, i8 %e, i32 0
147  ret <16 x i8> %v1
148}
149
150; 2 is greater than the default alignment so it is ignored.
151define <16 x i8> @load_lane_i8_a2(i8* %p, <16 x i8> %v) {
152; CHECK-LABEL: load_lane_i8_a2:
153; CHECK:         .functype load_lane_i8_a2 (i32, v128) -> (v128)
154; CHECK-NEXT:  # %bb.0:
155; CHECK-NEXT:    local.get 0
156; CHECK-NEXT:    local.get 1
157; CHECK-NEXT:    v128.load8_lane 0, 0
158; CHECK-NEXT:    # fallthrough-return
159  %e = load i8, i8* %p, align 2
160  %v1 = insertelement <16 x i8> %v, i8 %e, i32 0
161  ret <16 x i8> %v1
162}
163
164; 1 is the default alignment for v128.store8_lane so no attribute is needed.
165define void @store_lane_i8_a1(<16 x i8> %v, i8* %p) {
166; CHECK-LABEL: store_lane_i8_a1:
167; CHECK:         .functype store_lane_i8_a1 (v128, i32) -> ()
168; CHECK-NEXT:  # %bb.0:
169; CHECK-NEXT:    local.get 1
170; CHECK-NEXT:    local.get 0
171; CHECK-NEXT:    v128.store8_lane 0, 0
172; CHECK-NEXT:    # fallthrough-return
173  %x = extractelement <16 x i8> %v, i32 0
174  store i8 %x, i8* %p, align 1
175  ret void
176}
177
178; 2 is greater than the default alignment so it is ignored.
179define void @store_lane_i8_a2(<16 x i8> %v, i8* %p) {
180; CHECK-LABEL: store_lane_i8_a2:
181; CHECK:         .functype store_lane_i8_a2 (v128, i32) -> ()
182; CHECK-NEXT:  # %bb.0:
183; CHECK-NEXT:    local.get 1
184; CHECK-NEXT:    local.get 0
185; CHECK-NEXT:    v128.store8_lane 0, 0
186; CHECK-NEXT:    # fallthrough-return
187  %x = extractelement <16 x i8> %v, i32 0
188  store i8 %x, i8* %p, align 2
189  ret void
190}
191
192; ==============================================================================
193; 8 x i16
194; ==============================================================================
195
196define <8 x i16> @load_v8i16_a1(<8 x i16> *%p) {
197; CHECK-LABEL: load_v8i16_a1:
198; CHECK:         .functype load_v8i16_a1 (i32) -> (v128)
199; CHECK-NEXT:  # %bb.0:
200; CHECK-NEXT:    local.get 0
201; CHECK-NEXT:    v128.load 0:p2align=0
202; CHECK-NEXT:    # fallthrough-return
203  %v = load <8 x i16>, <8 x i16>* %p, align 1
204  ret <8 x i16> %v
205}
206
207define <8 x i16> @load_v8i16_a4(<8 x i16> *%p) {
208; CHECK-LABEL: load_v8i16_a4:
209; CHECK:         .functype load_v8i16_a4 (i32) -> (v128)
210; CHECK-NEXT:  # %bb.0:
211; CHECK-NEXT:    local.get 0
212; CHECK-NEXT:    v128.load 0:p2align=2
213; CHECK-NEXT:    # fallthrough-return
214  %v = load <8 x i16>, <8 x i16>* %p, align 4
215  ret <8 x i16> %v
216}
217
218; 8 is the default alignment for v128 so no attribute is needed.
219define <8 x i16> @load_v8i16_a16(<8 x i16> *%p) {
220; CHECK-LABEL: load_v8i16_a16:
221; CHECK:         .functype load_v8i16_a16 (i32) -> (v128)
222; CHECK-NEXT:  # %bb.0:
223; CHECK-NEXT:    local.get 0
224; CHECK-NEXT:    v128.load 0
225; CHECK-NEXT:    # fallthrough-return
226  %v = load <8 x i16>, <8 x i16>* %p, align 16
227  ret <8 x i16> %v
228}
229
230; 32 is greater than the default alignment so it is ignored.
231define <8 x i16> @load_v8i16_a32(<8 x i16> *%p) {
232; CHECK-LABEL: load_v8i16_a32:
233; CHECK:         .functype load_v8i16_a32 (i32) -> (v128)
234; CHECK-NEXT:  # %bb.0:
235; CHECK-NEXT:    local.get 0
236; CHECK-NEXT:    v128.load 0
237; CHECK-NEXT:    # fallthrough-return
238  %v = load <8 x i16>, <8 x i16>* %p, align 32
239  ret <8 x i16> %v
240}
241
242define void @store_v8i16_a1(<8 x i16> *%p, <8 x i16> %v) {
243; CHECK-LABEL: store_v8i16_a1:
244; CHECK:         .functype store_v8i16_a1 (i32, v128) -> ()
245; CHECK-NEXT:  # %bb.0:
246; CHECK-NEXT:    local.get 0
247; CHECK-NEXT:    local.get 1
248; CHECK-NEXT:    v128.store 0:p2align=0
249; CHECK-NEXT:    # fallthrough-return
250  store <8 x i16> %v, <8 x i16>* %p, align 1
251  ret void
252}
253
254define void @store_v8i16_a4(<8 x i16> *%p, <8 x i16> %v) {
255; CHECK-LABEL: store_v8i16_a4:
256; CHECK:         .functype store_v8i16_a4 (i32, v128) -> ()
257; CHECK-NEXT:  # %bb.0:
258; CHECK-NEXT:    local.get 0
259; CHECK-NEXT:    local.get 1
260; CHECK-NEXT:    v128.store 0:p2align=2
261; CHECK-NEXT:    # fallthrough-return
262  store <8 x i16> %v, <8 x i16>* %p, align 4
263  ret void
264}
265
266; 16 is the default alignment for v128 so no attribute is needed.
267define void @store_v8i16_a16(<8 x i16> *%p, <8 x i16> %v) {
268; CHECK-LABEL: store_v8i16_a16:
269; CHECK:         .functype store_v8i16_a16 (i32, v128) -> ()
270; CHECK-NEXT:  # %bb.0:
271; CHECK-NEXT:    local.get 0
272; CHECK-NEXT:    local.get 1
273; CHECK-NEXT:    v128.store 0
274; CHECK-NEXT:    # fallthrough-return
275  store <8 x i16> %v, <8 x i16>* %p, align 16
276  ret void
277}
278
279; 32 is greater than the default alignment so it is ignored.
280define void @store_v8i16_a32(<8 x i16> *%p, <8 x i16> %v) {
281; CHECK-LABEL: store_v8i16_a32:
282; CHECK:         .functype store_v8i16_a32 (i32, v128) -> ()
283; CHECK-NEXT:  # %bb.0:
284; CHECK-NEXT:    local.get 0
285; CHECK-NEXT:    local.get 1
286; CHECK-NEXT:    v128.store 0
287; CHECK-NEXT:    # fallthrough-return
288  store <8 x i16> %v, <8 x i16>* %p, align 32
289  ret void
290}
291
292define <8 x i8> @load_ext_v8i16_a1(<8 x i8>* %p) {
293; CHECK-LABEL: load_ext_v8i16_a1:
294; CHECK:         .functype load_ext_v8i16_a1 (i32) -> (v128)
295; CHECK-NEXT:  # %bb.0:
296; CHECK-NEXT:    local.get 0
297; CHECK-NEXT:    i16x8.load8x8_u 0:p2align=0
298; CHECK-NEXT:    # fallthrough-return
299  %v = load <8 x i8>, <8 x i8>* %p, align 1
300  ret <8 x i8> %v
301}
302
303define <8 x i8> @load_ext_v8i16_a2(<8 x i8>* %p) {
304; CHECK-LABEL: load_ext_v8i16_a2:
305; CHECK:         .functype load_ext_v8i16_a2 (i32) -> (v128)
306; CHECK-NEXT:  # %bb.0:
307; CHECK-NEXT:    local.get 0
308; CHECK-NEXT:    i16x8.load8x8_u 0:p2align=1
309; CHECK-NEXT:    # fallthrough-return
310  %v = load <8 x i8>, <8 x i8>* %p, align 2
311  ret <8 x i8> %v
312}
313
314define <8 x i8> @load_ext_v8i16_a4(<8 x i8>* %p) {
315; CHECK-LABEL: load_ext_v8i16_a4:
316; CHECK:         .functype load_ext_v8i16_a4 (i32) -> (v128)
317; CHECK-NEXT:  # %bb.0:
318; CHECK-NEXT:    local.get 0
319; CHECK-NEXT:    i16x8.load8x8_u 0:p2align=2
320; CHECK-NEXT:    # fallthrough-return
321  %v = load <8 x i8>, <8 x i8>* %p, align 4
322  ret <8 x i8> %v
323}
324
325; 8 is the default alignment for v128 extending load so no attribute is needed.
326define <8 x i8> @load_ext_v8i16_a8(<8 x i8>* %p) {
327; CHECK-LABEL: load_ext_v8i16_a8:
328; CHECK:         .functype load_ext_v8i16_a8 (i32) -> (v128)
329; CHECK-NEXT:  # %bb.0:
330; CHECK-NEXT:    local.get 0
331; CHECK-NEXT:    i16x8.load8x8_u 0
332; CHECK-NEXT:    # fallthrough-return
333  %v = load <8 x i8>, <8 x i8>* %p, align 8
334  ret <8 x i8> %v
335}
336
337; 16 is greater than the default alignment so it is ignored.
338define <8 x i8> @load_ext_v8i16_a16(<8 x i8>* %p) {
339; CHECK-LABEL: load_ext_v8i16_a16:
340; CHECK:         .functype load_ext_v8i16_a16 (i32) -> (v128)
341; CHECK-NEXT:  # %bb.0:
342; CHECK-NEXT:    local.get 0
343; CHECK-NEXT:    i16x8.load8x8_u 0
344; CHECK-NEXT:    # fallthrough-return
345  %v = load <8 x i8>, <8 x i8>* %p, align 16
346  ret <8 x i8> %v
347}
348
349define <8 x i16> @load_sext_v8i16_a1(<8 x i8>* %p) {
350; CHECK-LABEL: load_sext_v8i16_a1:
351; CHECK:         .functype load_sext_v8i16_a1 (i32) -> (v128)
352; CHECK-NEXT:  # %bb.0:
353; CHECK-NEXT:    local.get 0
354; CHECK-NEXT:    i16x8.load8x8_s 0:p2align=0
355; CHECK-NEXT:    # fallthrough-return
356  %v = load <8 x i8>, <8 x i8>* %p, align 1
357  %v2 = sext <8 x i8> %v to <8 x i16>
358  ret <8 x i16> %v2
359}
360
361define <8 x i16> @load_sext_v8i16_a2(<8 x i8>* %p) {
362; CHECK-LABEL: load_sext_v8i16_a2:
363; CHECK:         .functype load_sext_v8i16_a2 (i32) -> (v128)
364; CHECK-NEXT:  # %bb.0:
365; CHECK-NEXT:    local.get 0
366; CHECK-NEXT:    i16x8.load8x8_s 0:p2align=1
367; CHECK-NEXT:    # fallthrough-return
368  %v = load <8 x i8>, <8 x i8>* %p, align 2
369  %v2 = sext <8 x i8> %v to <8 x i16>
370  ret <8 x i16> %v2
371}
372
373define <8 x i16> @load_sext_v8i16_a4(<8 x i8>* %p) {
374; CHECK-LABEL: load_sext_v8i16_a4:
375; CHECK:         .functype load_sext_v8i16_a4 (i32) -> (v128)
376; CHECK-NEXT:  # %bb.0:
377; CHECK-NEXT:    local.get 0
378; CHECK-NEXT:    i16x8.load8x8_s 0:p2align=2
379; CHECK-NEXT:    # fallthrough-return
380  %v = load <8 x i8>, <8 x i8>* %p, align 4
381  %v2 = sext <8 x i8> %v to <8 x i16>
382  ret <8 x i16> %v2
383}
384
385; 8 is the default alignment for v128 extending load so no attribute is needed.
386define <8 x i16> @load_sext_v8i16_a8(<8 x i8>* %p) {
387; CHECK-LABEL: load_sext_v8i16_a8:
388; CHECK:         .functype load_sext_v8i16_a8 (i32) -> (v128)
389; CHECK-NEXT:  # %bb.0:
390; CHECK-NEXT:    local.get 0
391; CHECK-NEXT:    i16x8.load8x8_s 0
392; CHECK-NEXT:    # fallthrough-return
393  %v = load <8 x i8>, <8 x i8>* %p, align 8
394  %v2 = sext <8 x i8> %v to <8 x i16>
395  ret <8 x i16> %v2
396}
397
398; 16 is greater than the default alignment so it is ignored.
399define <8 x i16> @load_sext_v8i16_a16(<8 x i8>* %p) {
400; CHECK-LABEL: load_sext_v8i16_a16:
401; CHECK:         .functype load_sext_v8i16_a16 (i32) -> (v128)
402; CHECK-NEXT:  # %bb.0:
403; CHECK-NEXT:    local.get 0
404; CHECK-NEXT:    i16x8.load8x8_s 0
405; CHECK-NEXT:    # fallthrough-return
406  %v = load <8 x i8>, <8 x i8>* %p, align 16
407  %v2 = sext <8 x i8> %v to <8 x i16>
408  ret <8 x i16> %v2
409}
410
411define <8 x i16> @load_splat_v8i16_a1(i16* %p) {
412; CHECK-LABEL: load_splat_v8i16_a1:
413; CHECK:         .functype load_splat_v8i16_a1 (i32) -> (v128)
414; CHECK-NEXT:  # %bb.0:
415; CHECK-NEXT:    local.get 0
416; CHECK-NEXT:    v128.load16_splat 0:p2align=0
417; CHECK-NEXT:    # fallthrough-return
418  %e = load i16, i16* %p, align 1
419  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
420  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
421  ret <8 x i16> %v2
422}
423
424; 2 is the default alignment for v128.load16_splat so no attribute is needed.
425define <8 x i16> @load_splat_v8i16_a2(i16* %p) {
426; CHECK-LABEL: load_splat_v8i16_a2:
427; CHECK:         .functype load_splat_v8i16_a2 (i32) -> (v128)
428; CHECK-NEXT:  # %bb.0:
429; CHECK-NEXT:    local.get 0
430; CHECK-NEXT:    v128.load16_splat 0
431; CHECK-NEXT:    # fallthrough-return
432  %e = load i16, i16* %p, align 2
433  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
434  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
435  ret <8 x i16> %v2
436}
437
438; 4 is greater than the default alignment so it is ignored.
439define <8 x i16> @load_splat_v8i16_a4(i16* %p) {
440; CHECK-LABEL: load_splat_v8i16_a4:
441; CHECK:         .functype load_splat_v8i16_a4 (i32) -> (v128)
442; CHECK-NEXT:  # %bb.0:
443; CHECK-NEXT:    local.get 0
444; CHECK-NEXT:    v128.load16_splat 0
445; CHECK-NEXT:    # fallthrough-return
446  %e = load i16, i16* %p, align 4
447  %v1 = insertelement <8 x i16> undef, i16 %e, i32 0
448  %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer
449  ret <8 x i16> %v2
450}
451
452define <8 x i16> @load_lane_i16_a1(i16* %p, <8 x i16> %v) {
453; CHECK-LABEL: load_lane_i16_a1:
454; CHECK:         .functype load_lane_i16_a1 (i32, v128) -> (v128)
455; CHECK-NEXT:  # %bb.0:
456; CHECK-NEXT:    local.get 0
457; CHECK-NEXT:    local.get 1
458; CHECK-NEXT:    v128.load16_lane 0:p2align=0, 0
459; CHECK-NEXT:    # fallthrough-return
460  %e = load i16, i16* %p, align 1
461  %v1 = insertelement <8 x i16> %v, i16 %e, i32 0
462  ret <8 x i16> %v1
463}
464
465; 2 is the default alignment for v128.load16_lane so no attribute is needed.
466define <8 x i16> @load_lane_i16_a2(i16* %p, <8 x i16> %v) {
467; CHECK-LABEL: load_lane_i16_a2:
468; CHECK:         .functype load_lane_i16_a2 (i32, v128) -> (v128)
469; CHECK-NEXT:  # %bb.0:
470; CHECK-NEXT:    local.get 0
471; CHECK-NEXT:    local.get 1
472; CHECK-NEXT:    v128.load16_lane 0, 0
473; CHECK-NEXT:    # fallthrough-return
474  %e = load i16, i16* %p, align 2
475  %v1 = insertelement <8 x i16> %v, i16 %e, i32 0
476  ret <8 x i16> %v1
477}
478
479; 4 is greater than the default alignment so it is ignored.
480define <8 x i16> @load_lane_i16_a4(i16* %p, <8 x i16> %v) {
481; CHECK-LABEL: load_lane_i16_a4:
482; CHECK:         .functype load_lane_i16_a4 (i32, v128) -> (v128)
483; CHECK-NEXT:  # %bb.0:
484; CHECK-NEXT:    local.get 0
485; CHECK-NEXT:    local.get 1
486; CHECK-NEXT:    v128.load16_lane 0, 0
487; CHECK-NEXT:    # fallthrough-return
488  %e = load i16, i16* %p, align 4
489  %v1 = insertelement <8 x i16> %v, i16 %e, i32 0
490  ret <8 x i16> %v1
491}
492
493define void @store_lane_i16_a1(<8 x i16> %v, i16* %p) {
494; CHECK-LABEL: store_lane_i16_a1:
495; CHECK:         .functype store_lane_i16_a1 (v128, i32) -> ()
496; CHECK-NEXT:  # %bb.0:
497; CHECK-NEXT:    local.get 1
498; CHECK-NEXT:    local.get 0
499; CHECK-NEXT:    v128.store16_lane 0:p2align=0, 0
500; CHECK-NEXT:    # fallthrough-return
501  %x = extractelement <8 x i16> %v, i32 0
502  store i16 %x, i16* %p, align 1
503  ret void
504}
505
506; 2 is the default alignment for v128.store16_lane so no attribute is needed.
507define void @store_lane_i16_a2(<8 x i16> %v, i16* %p) {
508; CHECK-LABEL: store_lane_i16_a2:
509; CHECK:         .functype store_lane_i16_a2 (v128, i32) -> ()
510; CHECK-NEXT:  # %bb.0:
511; CHECK-NEXT:    local.get 1
512; CHECK-NEXT:    local.get 0
513; CHECK-NEXT:    v128.store16_lane 0, 0
514; CHECK-NEXT:    # fallthrough-return
515  %x = extractelement <8 x i16> %v, i32 0
516  store i16 %x, i16* %p, align 2
517  ret void
518}
519
520; 4 is greater than the default alignment so it is ignored.
521define void @store_lane_i16_a4(<8 x i16> %v, i16* %p) {
522; CHECK-LABEL: store_lane_i16_a4:
523; CHECK:         .functype store_lane_i16_a4 (v128, i32) -> ()
524; CHECK-NEXT:  # %bb.0:
525; CHECK-NEXT:    local.get 1
526; CHECK-NEXT:    local.get 0
527; CHECK-NEXT:    v128.store16_lane 0, 0
528; CHECK-NEXT:    # fallthrough-return
529  %x = extractelement <8 x i16> %v, i32 0
530  store i16 %x, i16* %p, align 4
531  ret void
532}
533
534; ==============================================================================
535; 4 x i32
536; ==============================================================================
537
538define <4 x i32> @load_v4i32_a1(<4 x i32> *%p) {
539; CHECK-LABEL: load_v4i32_a1:
540; CHECK:         .functype load_v4i32_a1 (i32) -> (v128)
541; CHECK-NEXT:  # %bb.0:
542; CHECK-NEXT:    local.get 0
543; CHECK-NEXT:    v128.load 0:p2align=0
544; CHECK-NEXT:    # fallthrough-return
545  %v = load <4 x i32>, <4 x i32>* %p, align 1
546  ret <4 x i32> %v
547}
548
549define <4 x i32> @load_v4i32_a4(<4 x i32> *%p) {
550; CHECK-LABEL: load_v4i32_a4:
551; CHECK:         .functype load_v4i32_a4 (i32) -> (v128)
552; CHECK-NEXT:  # %bb.0:
553; CHECK-NEXT:    local.get 0
554; CHECK-NEXT:    v128.load 0:p2align=2
555; CHECK-NEXT:    # fallthrough-return
556  %v = load <4 x i32>, <4 x i32>* %p, align 4
557  ret <4 x i32> %v
558}
559
560; 4 is the default alignment for v128 so no attribute is needed.
561define <4 x i32> @load_v4i32_a16(<4 x i32> *%p) {
562; CHECK-LABEL: load_v4i32_a16:
563; CHECK:         .functype load_v4i32_a16 (i32) -> (v128)
564; CHECK-NEXT:  # %bb.0:
565; CHECK-NEXT:    local.get 0
566; CHECK-NEXT:    v128.load 0
567; CHECK-NEXT:    # fallthrough-return
568  %v = load <4 x i32>, <4 x i32>* %p, align 16
569  ret <4 x i32> %v
570}
571
572; 32 is greater than the default alignment so it is ignored.
573define <4 x i32> @load_v4i32_a32(<4 x i32> *%p) {
574; CHECK-LABEL: load_v4i32_a32:
575; CHECK:         .functype load_v4i32_a32 (i32) -> (v128)
576; CHECK-NEXT:  # %bb.0:
577; CHECK-NEXT:    local.get 0
578; CHECK-NEXT:    v128.load 0
579; CHECK-NEXT:    # fallthrough-return
580  %v = load <4 x i32>, <4 x i32>* %p, align 32
581  ret <4 x i32> %v
582}
583
584define void @store_v4i32_a1(<4 x i32> *%p, <4 x i32> %v) {
585; CHECK-LABEL: store_v4i32_a1:
586; CHECK:         .functype store_v4i32_a1 (i32, v128) -> ()
587; CHECK-NEXT:  # %bb.0:
588; CHECK-NEXT:    local.get 0
589; CHECK-NEXT:    local.get 1
590; CHECK-NEXT:    v128.store 0:p2align=0
591; CHECK-NEXT:    # fallthrough-return
592  store <4 x i32> %v, <4 x i32>* %p, align 1
593  ret void
594}
595
596define void @store_v4i32_a4(<4 x i32> *%p, <4 x i32> %v) {
597; CHECK-LABEL: store_v4i32_a4:
598; CHECK:         .functype store_v4i32_a4 (i32, v128) -> ()
599; CHECK-NEXT:  # %bb.0:
600; CHECK-NEXT:    local.get 0
601; CHECK-NEXT:    local.get 1
602; CHECK-NEXT:    v128.store 0:p2align=2
603; CHECK-NEXT:    # fallthrough-return
604  store <4 x i32> %v, <4 x i32>* %p, align 4
605  ret void
606}
607
608; 16 is the default alignment for v128 so no attribute is needed.
609define void @store_v4i32_a16(<4 x i32> *%p, <4 x i32> %v) {
610; CHECK-LABEL: store_v4i32_a16:
611; CHECK:         .functype store_v4i32_a16 (i32, v128) -> ()
612; CHECK-NEXT:  # %bb.0:
613; CHECK-NEXT:    local.get 0
614; CHECK-NEXT:    local.get 1
615; CHECK-NEXT:    v128.store 0
616; CHECK-NEXT:    # fallthrough-return
617  store <4 x i32> %v, <4 x i32>* %p, align 16
618  ret void
619}
620
621; 32 is greater than the default alignment so it is ignored.
622define void @store_v4i32_a32(<4 x i32> *%p, <4 x i32> %v) {
623; CHECK-LABEL: store_v4i32_a32:
624; CHECK:         .functype store_v4i32_a32 (i32, v128) -> ()
625; CHECK-NEXT:  # %bb.0:
626; CHECK-NEXT:    local.get 0
627; CHECK-NEXT:    local.get 1
628; CHECK-NEXT:    v128.store 0
629; CHECK-NEXT:    # fallthrough-return
630  store <4 x i32> %v, <4 x i32>* %p, align 32
631  ret void
632}
633
634define <4 x i16> @load_ext_v4i32_a1(<4 x i16>* %p) {
635; CHECK-LABEL: load_ext_v4i32_a1:
636; CHECK:         .functype load_ext_v4i32_a1 (i32) -> (v128)
637; CHECK-NEXT:  # %bb.0:
638; CHECK-NEXT:    local.get 0
639; CHECK-NEXT:    i32x4.load16x4_u 0:p2align=0
640; CHECK-NEXT:    # fallthrough-return
641  %v = load <4 x i16>, <4 x i16>* %p, align 1
642  ret <4 x i16> %v
643}
644
645define <4 x i16> @load_ext_v4i32_a2(<4 x i16>* %p) {
646; CHECK-LABEL: load_ext_v4i32_a2:
647; CHECK:         .functype load_ext_v4i32_a2 (i32) -> (v128)
648; CHECK-NEXT:  # %bb.0:
649; CHECK-NEXT:    local.get 0
650; CHECK-NEXT:    i32x4.load16x4_u 0:p2align=1
651; CHECK-NEXT:    # fallthrough-return
652  %v = load <4 x i16>, <4 x i16>* %p, align 2
653  ret <4 x i16> %v
654}
655
656define <4 x i16> @load_ext_v4i32_a4(<4 x i16>* %p) {
657; CHECK-LABEL: load_ext_v4i32_a4:
658; CHECK:         .functype load_ext_v4i32_a4 (i32) -> (v128)
659; CHECK-NEXT:  # %bb.0:
660; CHECK-NEXT:    local.get 0
661; CHECK-NEXT:    i32x4.load16x4_u 0:p2align=2
662; CHECK-NEXT:    # fallthrough-return
663  %v = load <4 x i16>, <4 x i16>* %p, align 4
664  ret <4 x i16> %v
665}
666
667; 8 is the default alignment for v128 extending load so no attribute is needed.
668define <4 x i16> @load_ext_v4i32_a8(<4 x i16>* %p) {
669; CHECK-LABEL: load_ext_v4i32_a8:
670; CHECK:         .functype load_ext_v4i32_a8 (i32) -> (v128)
671; CHECK-NEXT:  # %bb.0:
672; CHECK-NEXT:    local.get 0
673; CHECK-NEXT:    i32x4.load16x4_u 0
674; CHECK-NEXT:    # fallthrough-return
675  %v = load <4 x i16>, <4 x i16>* %p, align 8
676  ret <4 x i16> %v
677}
678
679; 16 is greater than the default alignment so it is ignored.
680define <4 x i16> @load_ext_v4i32_a16(<4 x i16>* %p) {
681; CHECK-LABEL: load_ext_v4i32_a16:
682; CHECK:         .functype load_ext_v4i32_a16 (i32) -> (v128)
683; CHECK-NEXT:  # %bb.0:
684; CHECK-NEXT:    local.get 0
685; CHECK-NEXT:    i32x4.load16x4_u 0
686; CHECK-NEXT:    # fallthrough-return
687  %v = load <4 x i16>, <4 x i16>* %p, align 16
688  ret <4 x i16> %v
689}
690
691define <4 x i32> @load_sext_v4i32_a1(<4 x i16>* %p) {
692; CHECK-LABEL: load_sext_v4i32_a1:
693; CHECK:         .functype load_sext_v4i32_a1 (i32) -> (v128)
694; CHECK-NEXT:  # %bb.0:
695; CHECK-NEXT:    local.get 0
696; CHECK-NEXT:    i32x4.load16x4_s 0:p2align=0
697; CHECK-NEXT:    # fallthrough-return
698  %v = load <4 x i16>, <4 x i16>* %p, align 1
699  %v2 = sext <4 x i16> %v to <4 x i32>
700  ret <4 x i32> %v2
701}
702
703define <4 x i32> @load_sext_v4i32_a2(<4 x i16>* %p) {
704; CHECK-LABEL: load_sext_v4i32_a2:
705; CHECK:         .functype load_sext_v4i32_a2 (i32) -> (v128)
706; CHECK-NEXT:  # %bb.0:
707; CHECK-NEXT:    local.get 0
708; CHECK-NEXT:    i32x4.load16x4_s 0:p2align=1
709; CHECK-NEXT:    # fallthrough-return
710  %v = load <4 x i16>, <4 x i16>* %p, align 2
711  %v2 = sext <4 x i16> %v to <4 x i32>
712  ret <4 x i32> %v2
713}
714
715define <4 x i32> @load_sext_v4i32_a4(<4 x i16>* %p) {
716; CHECK-LABEL: load_sext_v4i32_a4:
717; CHECK:         .functype load_sext_v4i32_a4 (i32) -> (v128)
718; CHECK-NEXT:  # %bb.0:
719; CHECK-NEXT:    local.get 0
720; CHECK-NEXT:    i32x4.load16x4_s 0:p2align=2
721; CHECK-NEXT:    # fallthrough-return
722  %v = load <4 x i16>, <4 x i16>* %p, align 4
723  %v2 = sext <4 x i16> %v to <4 x i32>
724  ret <4 x i32> %v2
725}
726
727; 8 is the default alignment for v128 extending load so no attribute is needed.
728define <4 x i32> @load_sext_v4i32_a8(<4 x i16>* %p) {
729; CHECK-LABEL: load_sext_v4i32_a8:
730; CHECK:         .functype load_sext_v4i32_a8 (i32) -> (v128)
731; CHECK-NEXT:  # %bb.0:
732; CHECK-NEXT:    local.get 0
733; CHECK-NEXT:    i32x4.load16x4_s 0
734; CHECK-NEXT:    # fallthrough-return
735  %v = load <4 x i16>, <4 x i16>* %p, align 8
736  %v2 = sext <4 x i16> %v to <4 x i32>
737  ret <4 x i32> %v2
738}
739
740; 16 is greater than the default alignment so it is ignored.
741define <4 x i32> @load_sext_v4i32_a16(<4 x i16>* %p) {
742; CHECK-LABEL: load_sext_v4i32_a16:
743; CHECK:         .functype load_sext_v4i32_a16 (i32) -> (v128)
744; CHECK-NEXT:  # %bb.0:
745; CHECK-NEXT:    local.get 0
746; CHECK-NEXT:    i32x4.load16x4_s 0
747; CHECK-NEXT:    # fallthrough-return
748  %v = load <4 x i16>, <4 x i16>* %p, align 16
749  %v2 = sext <4 x i16> %v to <4 x i32>
750  ret <4 x i32> %v2
751}
752
753define <4 x i32> @load_splat_v4i32_a1(i32* %addr) {
754; CHECK-LABEL: load_splat_v4i32_a1:
755; CHECK:         .functype load_splat_v4i32_a1 (i32) -> (v128)
756; CHECK-NEXT:  # %bb.0:
757; CHECK-NEXT:    local.get 0
758; CHECK-NEXT:    v128.load32_splat 0:p2align=0
759; CHECK-NEXT:    # fallthrough-return
760  %e = load i32, i32* %addr, align 1
761  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
762  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
763  ret <4 x i32> %v2
764}
765
766define <4 x i32> @load_splat_v4i32_a2(i32* %addr) {
767; CHECK-LABEL: load_splat_v4i32_a2:
768; CHECK:         .functype load_splat_v4i32_a2 (i32) -> (v128)
769; CHECK-NEXT:  # %bb.0:
770; CHECK-NEXT:    local.get 0
771; CHECK-NEXT:    v128.load32_splat 0:p2align=1
772; CHECK-NEXT:    # fallthrough-return
773  %e = load i32, i32* %addr, align 2
774  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
775  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
776  ret <4 x i32> %v2
777}
778
779; 4 is the default alignment for v128.load32_splat so no attribute is needed.
780define <4 x i32> @load_splat_v4i32_a4(i32* %addr) {
781; CHECK-LABEL: load_splat_v4i32_a4:
782; CHECK:         .functype load_splat_v4i32_a4 (i32) -> (v128)
783; CHECK-NEXT:  # %bb.0:
784; CHECK-NEXT:    local.get 0
785; CHECK-NEXT:    v128.load32_splat 0
786; CHECK-NEXT:    # fallthrough-return
787  %e = load i32, i32* %addr, align 4
788  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
789  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
790  ret <4 x i32> %v2
791}
792
793; 8 is greater than the default alignment so it is ignored.
794define <4 x i32> @load_splat_v4i32_a8(i32* %addr) {
795; CHECK-LABEL: load_splat_v4i32_a8:
796; CHECK:         .functype load_splat_v4i32_a8 (i32) -> (v128)
797; CHECK-NEXT:  # %bb.0:
798; CHECK-NEXT:    local.get 0
799; CHECK-NEXT:    v128.load32_splat 0
800; CHECK-NEXT:    # fallthrough-return
801  %e = load i32, i32* %addr, align 8
802  %v1 = insertelement <4 x i32> undef, i32 %e, i32 0
803  %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer
804  ret <4 x i32> %v2
805}
806
807define <4 x i32> @load_lane_i32_a1(i32* %p, <4 x i32> %v) {
808; CHECK-LABEL: load_lane_i32_a1:
809; CHECK:         .functype load_lane_i32_a1 (i32, v128) -> (v128)
810; CHECK-NEXT:  # %bb.0:
811; CHECK-NEXT:    local.get 0
812; CHECK-NEXT:    local.get 1
813; CHECK-NEXT:    v128.load32_lane 0:p2align=0, 0
814; CHECK-NEXT:    # fallthrough-return
815  %e = load i32, i32* %p, align 1
816  %v1 = insertelement <4 x i32> %v, i32 %e, i32 0
817  ret <4 x i32> %v1
818}
819
820define <4 x i32> @load_lane_i32_a2(i32* %p, <4 x i32> %v) {
821; CHECK-LABEL: load_lane_i32_a2:
822; CHECK:         .functype load_lane_i32_a2 (i32, v128) -> (v128)
823; CHECK-NEXT:  # %bb.0:
824; CHECK-NEXT:    local.get 0
825; CHECK-NEXT:    local.get 1
826; CHECK-NEXT:    v128.load32_lane 0:p2align=1, 0
827; CHECK-NEXT:    # fallthrough-return
828  %e = load i32, i32* %p, align 2
829  %v1 = insertelement <4 x i32> %v, i32 %e, i32 0
830  ret <4 x i32> %v1
831}
832
833; 4 is the default alignment for v128.load32_lane so no attribute is needed.
834define <4 x i32> @load_lane_i32_a4(i32* %p, <4 x i32> %v) {
835; CHECK-LABEL: load_lane_i32_a4:
836; CHECK:         .functype load_lane_i32_a4 (i32, v128) -> (v128)
837; CHECK-NEXT:  # %bb.0:
838; CHECK-NEXT:    local.get 0
839; CHECK-NEXT:    local.get 1
840; CHECK-NEXT:    v128.load32_lane 0, 0
841; CHECK-NEXT:    # fallthrough-return
842  %e = load i32, i32* %p, align 4
843  %v1 = insertelement <4 x i32> %v, i32 %e, i32 0
844  ret <4 x i32> %v1
845}
846
847; 8 is greater than the default alignment so it is ignored.
848define <4 x i32> @load_lane_i32_a8(i32* %p, <4 x i32> %v) {
849; CHECK-LABEL: load_lane_i32_a8:
850; CHECK:         .functype load_lane_i32_a8 (i32, v128) -> (v128)
851; CHECK-NEXT:  # %bb.0:
852; CHECK-NEXT:    local.get 0
853; CHECK-NEXT:    local.get 1
854; CHECK-NEXT:    v128.load32_lane 0, 0
855; CHECK-NEXT:    # fallthrough-return
856  %e = load i32, i32* %p, align 8
857  %v1 = insertelement <4 x i32> %v, i32 %e, i32 0
858  ret <4 x i32> %v1
859}
860
861define void @store_lane_i32_a1(<4 x i32> %v, i32* %p) {
862; CHECK-LABEL: store_lane_i32_a1:
863; CHECK:         .functype store_lane_i32_a1 (v128, i32) -> ()
864; CHECK-NEXT:  # %bb.0:
865; CHECK-NEXT:    local.get 1
866; CHECK-NEXT:    local.get 0
867; CHECK-NEXT:    v128.store32_lane 0:p2align=0, 0
868; CHECK-NEXT:    # fallthrough-return
869  %x = extractelement <4 x i32> %v, i32 0
870  store i32 %x, i32* %p, align 1
871  ret void
872}
873
874define void @store_lane_i32_a2(<4 x i32> %v, i32* %p) {
875; CHECK-LABEL: store_lane_i32_a2:
876; CHECK:         .functype store_lane_i32_a2 (v128, i32) -> ()
877; CHECK-NEXT:  # %bb.0:
878; CHECK-NEXT:    local.get 1
879; CHECK-NEXT:    local.get 0
880; CHECK-NEXT:    v128.store32_lane 0:p2align=1, 0
881; CHECK-NEXT:    # fallthrough-return
882  %x = extractelement <4 x i32> %v, i32 0
883  store i32 %x, i32* %p, align 2
884  ret void
885}
886
887; 4 is the default alignment for v128.store32_lane so no attribute is needed.
888define void @store_lane_i32_a4(<4 x i32> %v, i32* %p) {
889; CHECK-LABEL: store_lane_i32_a4:
890; CHECK:         .functype store_lane_i32_a4 (v128, i32) -> ()
891; CHECK-NEXT:  # %bb.0:
892; CHECK-NEXT:    local.get 1
893; CHECK-NEXT:    local.get 0
894; CHECK-NEXT:    v128.store32_lane 0, 0
895; CHECK-NEXT:    # fallthrough-return
896  %x = extractelement <4 x i32> %v, i32 0
897  store i32 %x, i32* %p, align 4
898  ret void
899}
900
901; 8 is greater than the default alignment so it is ignored.
902define void @store_lane_i32_a8(<4 x i32> %v, i32* %p) {
903; CHECK-LABEL: store_lane_i32_a8:
904; CHECK:         .functype store_lane_i32_a8 (v128, i32) -> ()
905; CHECK-NEXT:  # %bb.0:
906; CHECK-NEXT:    local.get 1
907; CHECK-NEXT:    local.get 0
908; CHECK-NEXT:    v128.store32_lane 0, 0
909; CHECK-NEXT:    # fallthrough-return
910  %x = extractelement <4 x i32> %v, i32 0
911  store i32 %x, i32* %p, align 8
912  ret void
913}
914
915; ==============================================================================
916; 2 x i64
917; ==============================================================================
918
919define <2 x i64> @load_v2i64_a1(<2 x i64> *%p) {
920; CHECK-LABEL: load_v2i64_a1:
921; CHECK:         .functype load_v2i64_a1 (i32) -> (v128)
922; CHECK-NEXT:  # %bb.0:
923; CHECK-NEXT:    local.get 0
924; CHECK-NEXT:    v128.load 0:p2align=0
925; CHECK-NEXT:    # fallthrough-return
926  %v = load <2 x i64>, <2 x i64>* %p, align 1
927  ret <2 x i64> %v
928}
929
930define <2 x i64> @load_v2i64_a4(<2 x i64> *%p) {
931; CHECK-LABEL: load_v2i64_a4:
932; CHECK:         .functype load_v2i64_a4 (i32) -> (v128)
933; CHECK-NEXT:  # %bb.0:
934; CHECK-NEXT:    local.get 0
935; CHECK-NEXT:    v128.load 0:p2align=2
936; CHECK-NEXT:    # fallthrough-return
937  %v = load <2 x i64>, <2 x i64>* %p, align 4
938  ret <2 x i64> %v
939}
940
941; 2 is the default alignment for v128 so no attribute is needed.
942define <2 x i64> @load_v2i64_a16(<2 x i64> *%p) {
943; CHECK-LABEL: load_v2i64_a16:
944; CHECK:         .functype load_v2i64_a16 (i32) -> (v128)
945; CHECK-NEXT:  # %bb.0:
946; CHECK-NEXT:    local.get 0
947; CHECK-NEXT:    v128.load 0
948; CHECK-NEXT:    # fallthrough-return
949  %v = load <2 x i64>, <2 x i64>* %p, align 16
950  ret <2 x i64> %v
951}
952
953; 32 is greater than the default alignment so it is ignored.
954define <2 x i64> @load_v2i64_a32(<2 x i64> *%p) {
955; CHECK-LABEL: load_v2i64_a32:
956; CHECK:         .functype load_v2i64_a32 (i32) -> (v128)
957; CHECK-NEXT:  # %bb.0:
958; CHECK-NEXT:    local.get 0
959; CHECK-NEXT:    v128.load 0
960; CHECK-NEXT:    # fallthrough-return
961  %v = load <2 x i64>, <2 x i64>* %p, align 32
962  ret <2 x i64> %v
963}
964
965define void @store_v2i64_a1(<2 x i64> *%p, <2 x i64> %v) {
966; CHECK-LABEL: store_v2i64_a1:
967; CHECK:         .functype store_v2i64_a1 (i32, v128) -> ()
968; CHECK-NEXT:  # %bb.0:
969; CHECK-NEXT:    local.get 0
970; CHECK-NEXT:    local.get 1
971; CHECK-NEXT:    v128.store 0:p2align=0
972; CHECK-NEXT:    # fallthrough-return
973  store <2 x i64> %v, <2 x i64>* %p, align 1
974  ret void
975}
976
977define void @store_v2i64_a4(<2 x i64> *%p, <2 x i64> %v) {
978; CHECK-LABEL: store_v2i64_a4:
979; CHECK:         .functype store_v2i64_a4 (i32, v128) -> ()
980; CHECK-NEXT:  # %bb.0:
981; CHECK-NEXT:    local.get 0
982; CHECK-NEXT:    local.get 1
983; CHECK-NEXT:    v128.store 0:p2align=2
984; CHECK-NEXT:    # fallthrough-return
985  store <2 x i64> %v, <2 x i64>* %p, align 4
986  ret void
987}
988
989; 16 is the default alignment for v128 so no attribute is needed.
990define void @store_v2i64_a16(<2 x i64> *%p, <2 x i64> %v) {
991; CHECK-LABEL: store_v2i64_a16:
992; CHECK:         .functype store_v2i64_a16 (i32, v128) -> ()
993; CHECK-NEXT:  # %bb.0:
994; CHECK-NEXT:    local.get 0
995; CHECK-NEXT:    local.get 1
996; CHECK-NEXT:    v128.store 0
997; CHECK-NEXT:    # fallthrough-return
998  store <2 x i64> %v, <2 x i64>* %p, align 16
999  ret void
1000}
1001
1002; 32 is greater than the default alignment so it is ignored.
1003define void @store_v2i64_a32(<2 x i64> *%p, <2 x i64> %v) {
1004; CHECK-LABEL: store_v2i64_a32:
1005; CHECK:         .functype store_v2i64_a32 (i32, v128) -> ()
1006; CHECK-NEXT:  # %bb.0:
1007; CHECK-NEXT:    local.get 0
1008; CHECK-NEXT:    local.get 1
1009; CHECK-NEXT:    v128.store 0
1010; CHECK-NEXT:    # fallthrough-return
1011  store <2 x i64> %v, <2 x i64>* %p, align 32
1012  ret void
1013}
1014
1015define <2 x i64> @load_splat_v2i64_a1(i64* %p) {
1016; CHECK-LABEL: load_splat_v2i64_a1:
1017; CHECK:         .functype load_splat_v2i64_a1 (i32) -> (v128)
1018; CHECK-NEXT:  # %bb.0:
1019; CHECK-NEXT:    local.get 0
1020; CHECK-NEXT:    v128.load64_splat 0:p2align=0
1021; CHECK-NEXT:    # fallthrough-return
1022  %e = load i64, i64* %p, align 1
1023  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1024  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1025  ret <2 x i64> %v2
1026}
1027
1028define <2 x i64> @load_splat_v2i64_a2(i64* %p) {
1029; CHECK-LABEL: load_splat_v2i64_a2:
1030; CHECK:         .functype load_splat_v2i64_a2 (i32) -> (v128)
1031; CHECK-NEXT:  # %bb.0:
1032; CHECK-NEXT:    local.get 0
1033; CHECK-NEXT:    v128.load64_splat 0:p2align=1
1034; CHECK-NEXT:    # fallthrough-return
1035  %e = load i64, i64* %p, align 2
1036  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1037  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1038  ret <2 x i64> %v2
1039}
1040
1041define <2 x i64> @load_splat_v2i64_a4(i64* %p) {
1042; CHECK-LABEL: load_splat_v2i64_a4:
1043; CHECK:         .functype load_splat_v2i64_a4 (i32) -> (v128)
1044; CHECK-NEXT:  # %bb.0:
1045; CHECK-NEXT:    local.get 0
1046; CHECK-NEXT:    v128.load64_splat 0:p2align=2
1047; CHECK-NEXT:    # fallthrough-return
1048  %e = load i64, i64* %p, align 4
1049  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1050  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1051  ret <2 x i64> %v2
1052}
1053
1054; 8 is the default alignment for v128.load64_splat so no attribute is needed.
1055define <2 x i64> @load_splat_v2i64_a8(i64* %p) {
1056; CHECK-LABEL: load_splat_v2i64_a8:
1057; CHECK:         .functype load_splat_v2i64_a8 (i32) -> (v128)
1058; CHECK-NEXT:  # %bb.0:
1059; CHECK-NEXT:    local.get 0
1060; CHECK-NEXT:    v128.load64_splat 0
1061; CHECK-NEXT:    # fallthrough-return
1062  %e = load i64, i64* %p, align 8
1063  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1064  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1065  ret <2 x i64> %v2
1066}
1067
1068; 16 is greater than the default alignment so it is ignored.
1069define <2 x i64> @load_splat_v2i64_a16(i64* %p) {
1070; CHECK-LABEL: load_splat_v2i64_a16:
1071; CHECK:         .functype load_splat_v2i64_a16 (i32) -> (v128)
1072; CHECK-NEXT:  # %bb.0:
1073; CHECK-NEXT:    local.get 0
1074; CHECK-NEXT:    v128.load64_splat 0
1075; CHECK-NEXT:    # fallthrough-return
1076  %e = load i64, i64* %p, align 16
1077  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1078  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1079  ret <2 x i64> %v2
1080}
1081
1082define <2 x i64> @load_lane_i64_a1(i64* %p, <2 x i64> %v) {
1083; CHECK-LABEL: load_lane_i64_a1:
1084; CHECK:         .functype load_lane_i64_a1 (i32, v128) -> (v128)
1085; CHECK-NEXT:  # %bb.0:
1086; CHECK-NEXT:    local.get 0
1087; CHECK-NEXT:    local.get 1
1088; CHECK-NEXT:    v128.load64_lane 0:p2align=0, 0
1089; CHECK-NEXT:    # fallthrough-return
1090  %e = load i64, i64* %p, align 1
1091  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1092  ret <2 x i64> %v1
1093}
1094
1095define <2 x i64> @load_lane_i64_a2(i64* %p, <2 x i64> %v) {
1096; CHECK-LABEL: load_lane_i64_a2:
1097; CHECK:         .functype load_lane_i64_a2 (i32, v128) -> (v128)
1098; CHECK-NEXT:  # %bb.0:
1099; CHECK-NEXT:    local.get 0
1100; CHECK-NEXT:    local.get 1
1101; CHECK-NEXT:    v128.load64_lane 0:p2align=1, 0
1102; CHECK-NEXT:    # fallthrough-return
1103  %e = load i64, i64* %p, align 2
1104  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1105  ret <2 x i64> %v1
1106}
1107
1108define <2 x i64> @load_lane_i64_a4(i64* %p, <2 x i64> %v) {
1109; CHECK-LABEL: load_lane_i64_a4:
1110; CHECK:         .functype load_lane_i64_a4 (i32, v128) -> (v128)
1111; CHECK-NEXT:  # %bb.0:
1112; CHECK-NEXT:    local.get 0
1113; CHECK-NEXT:    local.get 1
1114; CHECK-NEXT:    v128.load64_lane 0:p2align=2, 0
1115; CHECK-NEXT:    # fallthrough-return
1116  %e = load i64, i64* %p, align 4
1117  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1118  ret <2 x i64> %v1
1119}
1120
1121; 8 is the default alignment for v128.load64_lane so no attribute is needed.
1122define <2 x i64> @load_lane_i64_a8(i64* %p, <2 x i64> %v) {
1123; CHECK-LABEL: load_lane_i64_a8:
1124; CHECK:         .functype load_lane_i64_a8 (i32, v128) -> (v128)
1125; CHECK-NEXT:  # %bb.0:
1126; CHECK-NEXT:    local.get 0
1127; CHECK-NEXT:    local.get 1
1128; CHECK-NEXT:    v128.load64_lane 0, 0
1129; CHECK-NEXT:    # fallthrough-return
1130  %e = load i64, i64* %p, align 8
1131  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1132  ret <2 x i64> %v1
1133}
1134
1135; 16 is greater than the default alignment so it is ignored.
1136define <2 x i64> @load_lane_i64_a16(i64* %p, <2 x i64> %v) {
1137; CHECK-LABEL: load_lane_i64_a16:
1138; CHECK:         .functype load_lane_i64_a16 (i32, v128) -> (v128)
1139; CHECK-NEXT:  # %bb.0:
1140; CHECK-NEXT:    local.get 0
1141; CHECK-NEXT:    local.get 1
1142; CHECK-NEXT:    v128.load64_lane 0, 0
1143; CHECK-NEXT:    # fallthrough-return
1144  %e = load i64, i64* %p, align 16
1145  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1146  ret <2 x i64> %v1
1147}
1148
1149define void @store_lane_i64_a1(<2 x i64> %v, i64* %p) {
1150; CHECK-LABEL: store_lane_i64_a1:
1151; CHECK:         .functype store_lane_i64_a1 (v128, i32) -> ()
1152; CHECK-NEXT:  # %bb.0:
1153; CHECK-NEXT:    local.get 1
1154; CHECK-NEXT:    local.get 0
1155; CHECK-NEXT:    v128.store64_lane 0:p2align=0, 0
1156; CHECK-NEXT:    # fallthrough-return
1157  %x = extractelement <2 x i64> %v, i32 0
1158  store i64 %x, i64* %p, align 1
1159  ret void
1160}
1161
1162define void @store_lane_i64_a2(<2 x i64> %v, i64* %p) {
1163; CHECK-LABEL: store_lane_i64_a2:
1164; CHECK:         .functype store_lane_i64_a2 (v128, i32) -> ()
1165; CHECK-NEXT:  # %bb.0:
1166; CHECK-NEXT:    local.get 1
1167; CHECK-NEXT:    local.get 0
1168; CHECK-NEXT:    v128.store64_lane 0:p2align=1, 0
1169; CHECK-NEXT:    # fallthrough-return
1170  %x = extractelement <2 x i64> %v, i32 0
1171  store i64 %x, i64* %p, align 2
1172  ret void
1173}
1174
1175define void @store_lane_i64_a4(<2 x i64> %v, i64* %p) {
1176; CHECK-LABEL: store_lane_i64_a4:
1177; CHECK:         .functype store_lane_i64_a4 (v128, i32) -> ()
1178; CHECK-NEXT:  # %bb.0:
1179; CHECK-NEXT:    local.get 1
1180; CHECK-NEXT:    local.get 0
1181; CHECK-NEXT:    v128.store64_lane 0:p2align=2, 0
1182; CHECK-NEXT:    # fallthrough-return
1183  %x = extractelement <2 x i64> %v, i32 0
1184  store i64 %x, i64* %p, align 4
1185  ret void
1186}
1187
1188; 8 is the default alignment for v128.store64_lane so no attribute is needed.
1189define void @store_lane_i64_a8(<2 x i64> %v, i64* %p) {
1190; CHECK-LABEL: store_lane_i64_a8:
1191; CHECK:         .functype store_lane_i64_a8 (v128, i32) -> ()
1192; CHECK-NEXT:  # %bb.0:
1193; CHECK-NEXT:    local.get 1
1194; CHECK-NEXT:    local.get 0
1195; CHECK-NEXT:    v128.store64_lane 0, 0
1196; CHECK-NEXT:    # fallthrough-return
1197  %x = extractelement <2 x i64> %v, i32 0
1198  store i64 %x, i64* %p, align 8
1199  ret void
1200}
1201
1202; 16 is greater than the default alignment so it is ignored.
1203define void @store_lane_i64_a16(<2 x i64> %v, i64* %p) {
1204; CHECK-LABEL: store_lane_i64_a16:
1205; CHECK:         .functype store_lane_i64_a16 (v128, i32) -> ()
1206; CHECK-NEXT:  # %bb.0:
1207; CHECK-NEXT:    local.get 1
1208; CHECK-NEXT:    local.get 0
1209; CHECK-NEXT:    v128.store64_lane 0, 0
1210; CHECK-NEXT:    # fallthrough-return
1211  %x = extractelement <2 x i64> %v, i32 0
1212  store i64 %x, i64* %p, align 16
1213  ret void
1214}
1215
1216; ==============================================================================
1217; 4 x float
1218; ==============================================================================
1219
1220define <4 x float> @load_v4f32_a1(<4 x float> *%p) {
1221; CHECK-LABEL: load_v4f32_a1:
1222; CHECK:         .functype load_v4f32_a1 (i32) -> (v128)
1223; CHECK-NEXT:  # %bb.0:
1224; CHECK-NEXT:    local.get 0
1225; CHECK-NEXT:    v128.load 0:p2align=0
1226; CHECK-NEXT:    # fallthrough-return
1227  %v = load <4 x float>, <4 x float>* %p, align 1
1228  ret <4 x float> %v
1229}
1230
1231define <4 x float> @load_v4f32_a4(<4 x float> *%p) {
1232; CHECK-LABEL: load_v4f32_a4:
1233; CHECK:         .functype load_v4f32_a4 (i32) -> (v128)
1234; CHECK-NEXT:  # %bb.0:
1235; CHECK-NEXT:    local.get 0
1236; CHECK-NEXT:    v128.load 0:p2align=2
1237; CHECK-NEXT:    # fallthrough-return
1238  %v = load <4 x float>, <4 x float>* %p, align 4
1239  ret <4 x float> %v
1240}
1241
1242; 4 is the default alignment for v128 so no attribute is needed.
1243define <4 x float> @load_v4f32_a16(<4 x float> *%p) {
1244; CHECK-LABEL: load_v4f32_a16:
1245; CHECK:         .functype load_v4f32_a16 (i32) -> (v128)
1246; CHECK-NEXT:  # %bb.0:
1247; CHECK-NEXT:    local.get 0
1248; CHECK-NEXT:    v128.load 0
1249; CHECK-NEXT:    # fallthrough-return
1250  %v = load <4 x float>, <4 x float>* %p, align 16
1251  ret <4 x float> %v
1252}
1253
1254; 32 is greater than the default alignment so it is ignored.
1255define <4 x float> @load_v4f32_a32(<4 x float> *%p) {
1256; CHECK-LABEL: load_v4f32_a32:
1257; CHECK:         .functype load_v4f32_a32 (i32) -> (v128)
1258; CHECK-NEXT:  # %bb.0:
1259; CHECK-NEXT:    local.get 0
1260; CHECK-NEXT:    v128.load 0
1261; CHECK-NEXT:    # fallthrough-return
1262  %v = load <4 x float>, <4 x float>* %p, align 32
1263  ret <4 x float> %v
1264}
1265
1266define void @store_v4f32_a1(<4 x float> *%p, <4 x float> %v) {
1267; CHECK-LABEL: store_v4f32_a1:
1268; CHECK:         .functype store_v4f32_a1 (i32, v128) -> ()
1269; CHECK-NEXT:  # %bb.0:
1270; CHECK-NEXT:    local.get 0
1271; CHECK-NEXT:    local.get 1
1272; CHECK-NEXT:    v128.store 0:p2align=0
1273; CHECK-NEXT:    # fallthrough-return
1274  store <4 x float> %v, <4 x float>* %p, align 1
1275  ret void
1276}
1277
1278define void @store_v4f32_a4(<4 x float> *%p, <4 x float> %v) {
1279; CHECK-LABEL: store_v4f32_a4:
1280; CHECK:         .functype store_v4f32_a4 (i32, v128) -> ()
1281; CHECK-NEXT:  # %bb.0:
1282; CHECK-NEXT:    local.get 0
1283; CHECK-NEXT:    local.get 1
1284; CHECK-NEXT:    v128.store 0:p2align=2
1285; CHECK-NEXT:    # fallthrough-return
1286  store <4 x float> %v, <4 x float>* %p, align 4
1287  ret void
1288}
1289
1290; 16 is the default alignment for v128 so no attribute is needed.
1291define void @store_v4f32_a16(<4 x float> *%p, <4 x float> %v) {
1292; CHECK-LABEL: store_v4f32_a16:
1293; CHECK:         .functype store_v4f32_a16 (i32, v128) -> ()
1294; CHECK-NEXT:  # %bb.0:
1295; CHECK-NEXT:    local.get 0
1296; CHECK-NEXT:    local.get 1
1297; CHECK-NEXT:    v128.store 0
1298; CHECK-NEXT:    # fallthrough-return
1299  store <4 x float> %v, <4 x float>* %p, align 16
1300  ret void
1301}
1302
1303; 32 is greater than the default alignment so it is ignored.
1304define void @store_v4f32_a32(<4 x float> *%p, <4 x float> %v) {
1305; CHECK-LABEL: store_v4f32_a32:
1306; CHECK:         .functype store_v4f32_a32 (i32, v128) -> ()
1307; CHECK-NEXT:  # %bb.0:
1308; CHECK-NEXT:    local.get 0
1309; CHECK-NEXT:    local.get 1
1310; CHECK-NEXT:    v128.store 0
1311; CHECK-NEXT:    # fallthrough-return
1312  store <4 x float> %v, <4 x float>* %p, align 32
1313  ret void
1314}
1315
1316; ==============================================================================
1317; 2 x double
1318; ==============================================================================
1319
1320define <2 x double> @load_v2f64_a1(<2 x double> *%p) {
1321; CHECK-LABEL: load_v2f64_a1:
1322; CHECK:         .functype load_v2f64_a1 (i32) -> (v128)
1323; CHECK-NEXT:  # %bb.0:
1324; CHECK-NEXT:    local.get 0
1325; CHECK-NEXT:    v128.load 0:p2align=0
1326; CHECK-NEXT:    # fallthrough-return
1327  %v = load <2 x double>, <2 x double>* %p, align 1
1328  ret <2 x double> %v
1329}
1330
1331define <2 x double> @load_v2f64_a4(<2 x double> *%p) {
1332; CHECK-LABEL: load_v2f64_a4:
1333; CHECK:         .functype load_v2f64_a4 (i32) -> (v128)
1334; CHECK-NEXT:  # %bb.0:
1335; CHECK-NEXT:    local.get 0
1336; CHECK-NEXT:    v128.load 0:p2align=2
1337; CHECK-NEXT:    # fallthrough-return
1338  %v = load <2 x double>, <2 x double>* %p, align 4
1339  ret <2 x double> %v
1340}
1341
1342; 2 is the default alignment for v128 so no attribute is needed.
1343define <2 x double> @load_v2f64_a16(<2 x double> *%p) {
1344; CHECK-LABEL: load_v2f64_a16:
1345; CHECK:         .functype load_v2f64_a16 (i32) -> (v128)
1346; CHECK-NEXT:  # %bb.0:
1347; CHECK-NEXT:    local.get 0
1348; CHECK-NEXT:    v128.load 0
1349; CHECK-NEXT:    # fallthrough-return
1350  %v = load <2 x double>, <2 x double>* %p, align 16
1351  ret <2 x double> %v
1352}
1353
1354; 32 is greater than the default alignment so it is ignored.
1355define <2 x double> @load_v2f64_a32(<2 x double> *%p) {
1356; CHECK-LABEL: load_v2f64_a32:
1357; CHECK:         .functype load_v2f64_a32 (i32) -> (v128)
1358; CHECK-NEXT:  # %bb.0:
1359; CHECK-NEXT:    local.get 0
1360; CHECK-NEXT:    v128.load 0
1361; CHECK-NEXT:    # fallthrough-return
1362  %v = load <2 x double>, <2 x double>* %p, align 32
1363  ret <2 x double> %v
1364}
1365
1366define void @store_v2f64_a1(<2 x double> *%p, <2 x double> %v) {
1367; CHECK-LABEL: store_v2f64_a1:
1368; CHECK:         .functype store_v2f64_a1 (i32, v128) -> ()
1369; CHECK-NEXT:  # %bb.0:
1370; CHECK-NEXT:    local.get 0
1371; CHECK-NEXT:    local.get 1
1372; CHECK-NEXT:    v128.store 0:p2align=0
1373; CHECK-NEXT:    # fallthrough-return
1374  store <2 x double> %v, <2 x double>* %p, align 1
1375  ret void
1376}
1377
1378define void @store_v2f64_a4(<2 x double> *%p, <2 x double> %v) {
1379; CHECK-LABEL: store_v2f64_a4:
1380; CHECK:         .functype store_v2f64_a4 (i32, v128) -> ()
1381; CHECK-NEXT:  # %bb.0:
1382; CHECK-NEXT:    local.get 0
1383; CHECK-NEXT:    local.get 1
1384; CHECK-NEXT:    v128.store 0:p2align=2
1385; CHECK-NEXT:    # fallthrough-return
1386  store <2 x double> %v, <2 x double>* %p, align 4
1387  ret void
1388}
1389
1390; 16 is the default alignment for v128 so no attribute is needed.
1391define void @store_v2f64_a16(<2 x double> *%p, <2 x double> %v) {
1392; CHECK-LABEL: store_v2f64_a16:
1393; CHECK:         .functype store_v2f64_a16 (i32, v128) -> ()
1394; CHECK-NEXT:  # %bb.0:
1395; CHECK-NEXT:    local.get 0
1396; CHECK-NEXT:    local.get 1
1397; CHECK-NEXT:    v128.store 0
1398; CHECK-NEXT:    # fallthrough-return
1399  store <2 x double> %v, <2 x double>* %p, align 16
1400  ret void
1401}
1402
1403; 32 is greater than the default alignment so it is ignored.
1404define void @store_v2f64_a32(<2 x double> *%p, <2 x double> %v) {
1405; CHECK-LABEL: store_v2f64_a32:
1406; CHECK:         .functype store_v2f64_a32 (i32, v128) -> ()
1407; CHECK-NEXT:  # %bb.0:
1408; CHECK-NEXT:    local.get 0
1409; CHECK-NEXT:    local.get 1
1410; CHECK-NEXT:    v128.store 0
1411; CHECK-NEXT:    # fallthrough-return
1412  store <2 x double> %v, <2 x double>* %p, align 32
1413  ret void
1414}
1415