xref: /llvm-project/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll (revision 73856247eef35f5336e485dc009842a5b991c421)
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(ptr %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>, ptr %p, align 1
20  ret <16 x i8> %v
21}
22
23define <16 x i8> @load_v16i8_a4(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %p, align 32
55  ret <16 x i8> %v
56}
57
58define void @store_v16i8_a1(ptr %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, ptr %p, align 1
67  ret void
68}
69
70define void @store_v16i8_a4(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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, ptr %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, ptr %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, ptr %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, ptr %p, align 2
189  ret void
190}
191
192; ==============================================================================
193; 8 x i16
194; ==============================================================================
195
196define <8 x i16> @load_v8i16_a1(ptr %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>, ptr %p, align 1
204  ret <8 x i16> %v
205}
206
207define <8 x i16> @load_v8i16_a4(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %p, align 32
239  ret <8 x i16> %v
240}
241
242define void @store_v8i16_a1(ptr %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, ptr %p, align 1
251  ret void
252}
253
254define void @store_v8i16_a4(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %p, align 32
289  ret void
290}
291
292define <8 x i8> @load_ext_v8i16_a1(ptr %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:    v128.load64_zero 0:p2align=0
298; CHECK-NEXT:    # fallthrough-return
299  %v = load <8 x i8>, ptr %p, align 1
300  ret <8 x i8> %v
301}
302
303define <8 x i8> @load_ext_v8i16_a2(ptr %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:    v128.load64_zero 0:p2align=1
309; CHECK-NEXT:    # fallthrough-return
310  %v = load <8 x i8>, ptr %p, align 2
311  ret <8 x i8> %v
312}
313
314define <8 x i8> @load_ext_v8i16_a4(ptr %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:    v128.load64_zero 0:p2align=2
320; CHECK-NEXT:    # fallthrough-return
321  %v = load <8 x i8>, ptr %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(ptr %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:    v128.load64_zero 0
332; CHECK-NEXT:    # fallthrough-return
333  %v = load <8 x i8>, ptr %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(ptr %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:    v128.load 0
344; CHECK-NEXT:    # fallthrough-return
345  %v = load <8 x i8>, ptr %p, align 16
346  ret <8 x i8> %v
347}
348
349define <8 x i16> @load_sext_v8i16_a1(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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, ptr %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, ptr %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, ptr %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, ptr %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, ptr %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, ptr %p, align 4
531  ret void
532}
533
534; ==============================================================================
535; 4 x i32
536; ==============================================================================
537
538define <4 x i32> @load_v4i32_a1(ptr %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>, ptr %p, align 1
546  ret <4 x i32> %v
547}
548
549define <4 x i32> @load_v4i32_a4(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %p, align 32
581  ret <4 x i32> %v
582}
583
584define void @store_v4i32_a1(ptr %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, ptr %p, align 1
593  ret void
594}
595
596define void @store_v4i32_a4(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %p, align 32
631  ret void
632}
633
634define <4 x i16> @load_ext_v4i32_a1(ptr %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:    v128.load64_zero 0:p2align=0
640; CHECK-NEXT:    # fallthrough-return
641  %v = load <4 x i16>, ptr %p, align 1
642  ret <4 x i16> %v
643}
644
645define <4 x i16> @load_ext_v4i32_a2(ptr %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:    v128.load64_zero 0:p2align=1
651; CHECK-NEXT:    # fallthrough-return
652  %v = load <4 x i16>, ptr %p, align 2
653  ret <4 x i16> %v
654}
655
656define <4 x i16> @load_ext_v4i32_a4(ptr %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:    v128.load64_zero 0:p2align=2
662; CHECK-NEXT:    # fallthrough-return
663  %v = load <4 x i16>, ptr %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(ptr %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:    v128.load64_zero 0
674; CHECK-NEXT:    # fallthrough-return
675  %v = load <4 x i16>, ptr %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(ptr %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:    v128.load 0
686; CHECK-NEXT:    # fallthrough-return
687  %v = load <4 x i16>, ptr %p, align 16
688  ret <4 x i16> %v
689}
690
691define <4 x i32> @load_sext_v4i32_a1(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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>, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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(ptr %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, ptr %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, ptr %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, ptr %p, align 1
871  ret void
872}
873
874define void @store_lane_i32_a2(<4 x i32> %v, ptr %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, ptr %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, ptr %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, ptr %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, ptr %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, ptr %p, align 8
912  ret void
913}
914
915define <4 x i32> @load_zero_i32_a1(ptr %p) {
916; CHECK-LABEL: load_zero_i32_a1:
917; CHECK:         .functype load_zero_i32_a1 (i32) -> (v128)
918; CHECK-NEXT:  # %bb.0:
919; CHECK-NEXT:    local.get 0
920; CHECK-NEXT:    v128.load32_zero 0:p2align=0
921; CHECK-NEXT:    # fallthrough-return
922  %x = load i32, ptr %p, align 1
923  %v = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0
924  ret <4 x i32> %v
925}
926
927define <4 x i32> @load_zero_i32_a2(ptr %p) {
928; CHECK-LABEL: load_zero_i32_a2:
929; CHECK:         .functype load_zero_i32_a2 (i32) -> (v128)
930; CHECK-NEXT:  # %bb.0:
931; CHECK-NEXT:    local.get 0
932; CHECK-NEXT:    v128.load32_zero 0:p2align=1
933; CHECK-NEXT:    # fallthrough-return
934  %x = load i32, ptr %p, align 2
935  %v = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0
936  ret <4 x i32> %v
937}
938
939; 4 is the default alignment for v128.load32_zero so no attribute is needed.
940define <4 x i32> @load_zero_i32_a4(ptr %p) {
941; CHECK-LABEL: load_zero_i32_a4:
942; CHECK:         .functype load_zero_i32_a4 (i32) -> (v128)
943; CHECK-NEXT:  # %bb.0:
944; CHECK-NEXT:    local.get 0
945; CHECK-NEXT:    v128.load32_zero 0
946; CHECK-NEXT:    # fallthrough-return
947  %x = load i32, ptr %p, align 4
948  %v = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0
949  ret <4 x i32> %v
950}
951
952; 8 is greater than the default alignment so it is ignored.
953define <4 x i32> @load_zero_i32_a8(ptr %p) {
954; CHECK-LABEL: load_zero_i32_a8:
955; CHECK:         .functype load_zero_i32_a8 (i32) -> (v128)
956; CHECK-NEXT:  # %bb.0:
957; CHECK-NEXT:    local.get 0
958; CHECK-NEXT:    v128.load32_zero 0
959; CHECK-NEXT:    # fallthrough-return
960  %x = load i32, ptr %p, align 8
961  %v = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0
962  ret <4 x i32> %v
963}
964
965; ==============================================================================
966; 2 x i64
967; ==============================================================================
968
969define <2 x i64> @load_v2i64_a1(ptr %p) {
970; CHECK-LABEL: load_v2i64_a1:
971; CHECK:         .functype load_v2i64_a1 (i32) -> (v128)
972; CHECK-NEXT:  # %bb.0:
973; CHECK-NEXT:    local.get 0
974; CHECK-NEXT:    v128.load 0:p2align=0
975; CHECK-NEXT:    # fallthrough-return
976  %v = load <2 x i64>, ptr %p, align 1
977  ret <2 x i64> %v
978}
979
980define <2 x i64> @load_v2i64_a4(ptr %p) {
981; CHECK-LABEL: load_v2i64_a4:
982; CHECK:         .functype load_v2i64_a4 (i32) -> (v128)
983; CHECK-NEXT:  # %bb.0:
984; CHECK-NEXT:    local.get 0
985; CHECK-NEXT:    v128.load 0:p2align=2
986; CHECK-NEXT:    # fallthrough-return
987  %v = load <2 x i64>, ptr %p, align 4
988  ret <2 x i64> %v
989}
990
991; 2 is the default alignment for v128 so no attribute is needed.
992define <2 x i64> @load_v2i64_a16(ptr %p) {
993; CHECK-LABEL: load_v2i64_a16:
994; CHECK:         .functype load_v2i64_a16 (i32) -> (v128)
995; CHECK-NEXT:  # %bb.0:
996; CHECK-NEXT:    local.get 0
997; CHECK-NEXT:    v128.load 0
998; CHECK-NEXT:    # fallthrough-return
999  %v = load <2 x i64>, ptr %p, align 16
1000  ret <2 x i64> %v
1001}
1002
1003; 32 is greater than the default alignment so it is ignored.
1004define <2 x i64> @load_v2i64_a32(ptr %p) {
1005; CHECK-LABEL: load_v2i64_a32:
1006; CHECK:         .functype load_v2i64_a32 (i32) -> (v128)
1007; CHECK-NEXT:  # %bb.0:
1008; CHECK-NEXT:    local.get 0
1009; CHECK-NEXT:    v128.load 0
1010; CHECK-NEXT:    # fallthrough-return
1011  %v = load <2 x i64>, ptr %p, align 32
1012  ret <2 x i64> %v
1013}
1014
1015define void @store_v2i64_a1(ptr %p, <2 x i64> %v) {
1016; CHECK-LABEL: store_v2i64_a1:
1017; CHECK:         .functype store_v2i64_a1 (i32, v128) -> ()
1018; CHECK-NEXT:  # %bb.0:
1019; CHECK-NEXT:    local.get 0
1020; CHECK-NEXT:    local.get 1
1021; CHECK-NEXT:    v128.store 0:p2align=0
1022; CHECK-NEXT:    # fallthrough-return
1023  store <2 x i64> %v, ptr %p, align 1
1024  ret void
1025}
1026
1027define void @store_v2i64_a4(ptr %p, <2 x i64> %v) {
1028; CHECK-LABEL: store_v2i64_a4:
1029; CHECK:         .functype store_v2i64_a4 (i32, v128) -> ()
1030; CHECK-NEXT:  # %bb.0:
1031; CHECK-NEXT:    local.get 0
1032; CHECK-NEXT:    local.get 1
1033; CHECK-NEXT:    v128.store 0:p2align=2
1034; CHECK-NEXT:    # fallthrough-return
1035  store <2 x i64> %v, ptr %p, align 4
1036  ret void
1037}
1038
1039; 16 is the default alignment for v128 so no attribute is needed.
1040define void @store_v2i64_a16(ptr %p, <2 x i64> %v) {
1041; CHECK-LABEL: store_v2i64_a16:
1042; CHECK:         .functype store_v2i64_a16 (i32, v128) -> ()
1043; CHECK-NEXT:  # %bb.0:
1044; CHECK-NEXT:    local.get 0
1045; CHECK-NEXT:    local.get 1
1046; CHECK-NEXT:    v128.store 0
1047; CHECK-NEXT:    # fallthrough-return
1048  store <2 x i64> %v, ptr %p, align 16
1049  ret void
1050}
1051
1052; 32 is greater than the default alignment so it is ignored.
1053define void @store_v2i64_a32(ptr %p, <2 x i64> %v) {
1054; CHECK-LABEL: store_v2i64_a32:
1055; CHECK:         .functype store_v2i64_a32 (i32, v128) -> ()
1056; CHECK-NEXT:  # %bb.0:
1057; CHECK-NEXT:    local.get 0
1058; CHECK-NEXT:    local.get 1
1059; CHECK-NEXT:    v128.store 0
1060; CHECK-NEXT:    # fallthrough-return
1061  store <2 x i64> %v, ptr %p, align 32
1062  ret void
1063}
1064
1065define <2 x i64> @load_splat_v2i64_a1(ptr %p) {
1066; CHECK-LABEL: load_splat_v2i64_a1:
1067; CHECK:         .functype load_splat_v2i64_a1 (i32) -> (v128)
1068; CHECK-NEXT:  # %bb.0:
1069; CHECK-NEXT:    local.get 0
1070; CHECK-NEXT:    v128.load64_splat 0:p2align=0
1071; CHECK-NEXT:    # fallthrough-return
1072  %e = load i64, ptr %p, align 1
1073  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1074  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1075  ret <2 x i64> %v2
1076}
1077
1078define <2 x i64> @load_splat_v2i64_a2(ptr %p) {
1079; CHECK-LABEL: load_splat_v2i64_a2:
1080; CHECK:         .functype load_splat_v2i64_a2 (i32) -> (v128)
1081; CHECK-NEXT:  # %bb.0:
1082; CHECK-NEXT:    local.get 0
1083; CHECK-NEXT:    v128.load64_splat 0:p2align=1
1084; CHECK-NEXT:    # fallthrough-return
1085  %e = load i64, ptr %p, align 2
1086  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1087  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1088  ret <2 x i64> %v2
1089}
1090
1091define <2 x i64> @load_splat_v2i64_a4(ptr %p) {
1092; CHECK-LABEL: load_splat_v2i64_a4:
1093; CHECK:         .functype load_splat_v2i64_a4 (i32) -> (v128)
1094; CHECK-NEXT:  # %bb.0:
1095; CHECK-NEXT:    local.get 0
1096; CHECK-NEXT:    v128.load64_splat 0:p2align=2
1097; CHECK-NEXT:    # fallthrough-return
1098  %e = load i64, ptr %p, align 4
1099  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1100  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1101  ret <2 x i64> %v2
1102}
1103
1104; 8 is the default alignment for v128.load64_splat so no attribute is needed.
1105define <2 x i64> @load_splat_v2i64_a8(ptr %p) {
1106; CHECK-LABEL: load_splat_v2i64_a8:
1107; CHECK:         .functype load_splat_v2i64_a8 (i32) -> (v128)
1108; CHECK-NEXT:  # %bb.0:
1109; CHECK-NEXT:    local.get 0
1110; CHECK-NEXT:    v128.load64_splat 0
1111; CHECK-NEXT:    # fallthrough-return
1112  %e = load i64, ptr %p, align 8
1113  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1114  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1115  ret <2 x i64> %v2
1116}
1117
1118; 16 is greater than the default alignment so it is ignored.
1119define <2 x i64> @load_splat_v2i64_a16(ptr %p) {
1120; CHECK-LABEL: load_splat_v2i64_a16:
1121; CHECK:         .functype load_splat_v2i64_a16 (i32) -> (v128)
1122; CHECK-NEXT:  # %bb.0:
1123; CHECK-NEXT:    local.get 0
1124; CHECK-NEXT:    v128.load64_splat 0
1125; CHECK-NEXT:    # fallthrough-return
1126  %e = load i64, ptr %p, align 16
1127  %v1 = insertelement <2 x i64> undef, i64 %e, i32 0
1128  %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer
1129  ret <2 x i64> %v2
1130}
1131
1132define <2 x i64> @load_lane_i64_a1(ptr %p, <2 x i64> %v) {
1133; CHECK-LABEL: load_lane_i64_a1:
1134; CHECK:         .functype load_lane_i64_a1 (i32, v128) -> (v128)
1135; CHECK-NEXT:  # %bb.0:
1136; CHECK-NEXT:    local.get 0
1137; CHECK-NEXT:    local.get 1
1138; CHECK-NEXT:    v128.load64_lane 0:p2align=0, 0
1139; CHECK-NEXT:    # fallthrough-return
1140  %e = load i64, ptr %p, align 1
1141  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1142  ret <2 x i64> %v1
1143}
1144
1145define <2 x i64> @load_lane_i64_a2(ptr %p, <2 x i64> %v) {
1146; CHECK-LABEL: load_lane_i64_a2:
1147; CHECK:         .functype load_lane_i64_a2 (i32, v128) -> (v128)
1148; CHECK-NEXT:  # %bb.0:
1149; CHECK-NEXT:    local.get 0
1150; CHECK-NEXT:    local.get 1
1151; CHECK-NEXT:    v128.load64_lane 0:p2align=1, 0
1152; CHECK-NEXT:    # fallthrough-return
1153  %e = load i64, ptr %p, align 2
1154  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1155  ret <2 x i64> %v1
1156}
1157
1158define <2 x i64> @load_lane_i64_a4(ptr %p, <2 x i64> %v) {
1159; CHECK-LABEL: load_lane_i64_a4:
1160; CHECK:         .functype load_lane_i64_a4 (i32, v128) -> (v128)
1161; CHECK-NEXT:  # %bb.0:
1162; CHECK-NEXT:    local.get 0
1163; CHECK-NEXT:    local.get 1
1164; CHECK-NEXT:    v128.load64_lane 0:p2align=2, 0
1165; CHECK-NEXT:    # fallthrough-return
1166  %e = load i64, ptr %p, align 4
1167  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1168  ret <2 x i64> %v1
1169}
1170
1171; 8 is the default alignment for v128.load64_lane so no attribute is needed.
1172define <2 x i64> @load_lane_i64_a8(ptr %p, <2 x i64> %v) {
1173; CHECK-LABEL: load_lane_i64_a8:
1174; CHECK:         .functype load_lane_i64_a8 (i32, v128) -> (v128)
1175; CHECK-NEXT:  # %bb.0:
1176; CHECK-NEXT:    local.get 0
1177; CHECK-NEXT:    local.get 1
1178; CHECK-NEXT:    v128.load64_lane 0, 0
1179; CHECK-NEXT:    # fallthrough-return
1180  %e = load i64, ptr %p, align 8
1181  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1182  ret <2 x i64> %v1
1183}
1184
1185; 16 is greater than the default alignment so it is ignored.
1186define <2 x i64> @load_lane_i64_a16(ptr %p, <2 x i64> %v) {
1187; CHECK-LABEL: load_lane_i64_a16:
1188; CHECK:         .functype load_lane_i64_a16 (i32, v128) -> (v128)
1189; CHECK-NEXT:  # %bb.0:
1190; CHECK-NEXT:    local.get 0
1191; CHECK-NEXT:    local.get 1
1192; CHECK-NEXT:    v128.load64_lane 0, 0
1193; CHECK-NEXT:    # fallthrough-return
1194  %e = load i64, ptr %p, align 16
1195  %v1 = insertelement <2 x i64> %v, i64 %e, i32 0
1196  ret <2 x i64> %v1
1197}
1198
1199define void @store_lane_i64_a1(<2 x i64> %v, ptr %p) {
1200; CHECK-LABEL: store_lane_i64_a1:
1201; CHECK:         .functype store_lane_i64_a1 (v128, i32) -> ()
1202; CHECK-NEXT:  # %bb.0:
1203; CHECK-NEXT:    local.get 1
1204; CHECK-NEXT:    local.get 0
1205; CHECK-NEXT:    v128.store64_lane 0:p2align=0, 0
1206; CHECK-NEXT:    # fallthrough-return
1207  %x = extractelement <2 x i64> %v, i32 0
1208  store i64 %x, ptr %p, align 1
1209  ret void
1210}
1211
1212define void @store_lane_i64_a2(<2 x i64> %v, ptr %p) {
1213; CHECK-LABEL: store_lane_i64_a2:
1214; CHECK:         .functype store_lane_i64_a2 (v128, i32) -> ()
1215; CHECK-NEXT:  # %bb.0:
1216; CHECK-NEXT:    local.get 1
1217; CHECK-NEXT:    local.get 0
1218; CHECK-NEXT:    v128.store64_lane 0:p2align=1, 0
1219; CHECK-NEXT:    # fallthrough-return
1220  %x = extractelement <2 x i64> %v, i32 0
1221  store i64 %x, ptr %p, align 2
1222  ret void
1223}
1224
1225define void @store_lane_i64_a4(<2 x i64> %v, ptr %p) {
1226; CHECK-LABEL: store_lane_i64_a4:
1227; CHECK:         .functype store_lane_i64_a4 (v128, i32) -> ()
1228; CHECK-NEXT:  # %bb.0:
1229; CHECK-NEXT:    local.get 1
1230; CHECK-NEXT:    local.get 0
1231; CHECK-NEXT:    v128.store64_lane 0:p2align=2, 0
1232; CHECK-NEXT:    # fallthrough-return
1233  %x = extractelement <2 x i64> %v, i32 0
1234  store i64 %x, ptr %p, align 4
1235  ret void
1236}
1237
1238; 8 is the default alignment for v128.store64_lane so no attribute is needed.
1239define void @store_lane_i64_a8(<2 x i64> %v, ptr %p) {
1240; CHECK-LABEL: store_lane_i64_a8:
1241; CHECK:         .functype store_lane_i64_a8 (v128, i32) -> ()
1242; CHECK-NEXT:  # %bb.0:
1243; CHECK-NEXT:    local.get 1
1244; CHECK-NEXT:    local.get 0
1245; CHECK-NEXT:    v128.store64_lane 0, 0
1246; CHECK-NEXT:    # fallthrough-return
1247  %x = extractelement <2 x i64> %v, i32 0
1248  store i64 %x, ptr %p, align 8
1249  ret void
1250}
1251
1252; 16 is greater than the default alignment so it is ignored.
1253define void @store_lane_i64_a16(<2 x i64> %v, ptr %p) {
1254; CHECK-LABEL: store_lane_i64_a16:
1255; CHECK:         .functype store_lane_i64_a16 (v128, i32) -> ()
1256; CHECK-NEXT:  # %bb.0:
1257; CHECK-NEXT:    local.get 1
1258; CHECK-NEXT:    local.get 0
1259; CHECK-NEXT:    v128.store64_lane 0, 0
1260; CHECK-NEXT:    # fallthrough-return
1261  %x = extractelement <2 x i64> %v, i32 0
1262  store i64 %x, ptr %p, align 16
1263  ret void
1264}
1265
1266define <2 x i64> @load_zero_i64_a1(ptr %p) {
1267; CHECK-LABEL: load_zero_i64_a1:
1268; CHECK:         .functype load_zero_i64_a1 (i32) -> (v128)
1269; CHECK-NEXT:  # %bb.0:
1270; CHECK-NEXT:    local.get 0
1271; CHECK-NEXT:    v128.load64_zero 0:p2align=0
1272; CHECK-NEXT:    # fallthrough-return
1273  %x = load i64, ptr %p, align 1
1274  %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
1275  ret <2 x i64> %v
1276}
1277
1278define <2 x i64> @load_zero_i64_a2(ptr %p) {
1279; CHECK-LABEL: load_zero_i64_a2:
1280; CHECK:         .functype load_zero_i64_a2 (i32) -> (v128)
1281; CHECK-NEXT:  # %bb.0:
1282; CHECK-NEXT:    local.get 0
1283; CHECK-NEXT:    v128.load64_zero 0:p2align=1
1284; CHECK-NEXT:    # fallthrough-return
1285  %x = load i64, ptr %p, align 2
1286  %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
1287  ret <2 x i64> %v
1288}
1289
1290define <2 x i64> @load_zero_i64_a4(ptr %p) {
1291; CHECK-LABEL: load_zero_i64_a4:
1292; CHECK:         .functype load_zero_i64_a4 (i32) -> (v128)
1293; CHECK-NEXT:  # %bb.0:
1294; CHECK-NEXT:    local.get 0
1295; CHECK-NEXT:    v128.load64_zero 0:p2align=2
1296; CHECK-NEXT:    # fallthrough-return
1297  %x = load i64, ptr %p, align 4
1298  %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
1299  ret <2 x i64> %v
1300}
1301
1302; 8 is the default alignment for v128.load64_zero so no attribute is needed.
1303define <2 x i64> @load_zero_i64_a8(ptr %p) {
1304; CHECK-LABEL: load_zero_i64_a8:
1305; CHECK:         .functype load_zero_i64_a8 (i32) -> (v128)
1306; CHECK-NEXT:  # %bb.0:
1307; CHECK-NEXT:    local.get 0
1308; CHECK-NEXT:    v128.load64_zero 0
1309; CHECK-NEXT:    # fallthrough-return
1310  %x = load i64, ptr %p, align 8
1311  %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
1312  ret <2 x i64> %v
1313}
1314
1315; 16 is greater than the default alignment so it is ignored.
1316define <2 x i64> @load_zero_i64_a16(ptr %p) {
1317; CHECK-LABEL: load_zero_i64_a16:
1318; CHECK:         .functype load_zero_i64_a16 (i32) -> (v128)
1319; CHECK-NEXT:  # %bb.0:
1320; CHECK-NEXT:    local.get 0
1321; CHECK-NEXT:    v128.load64_zero 0
1322; CHECK-NEXT:    # fallthrough-return
1323  %x = load i64, ptr %p, align 16
1324  %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
1325  ret <2 x i64> %v
1326}
1327
1328; ==============================================================================
1329; 4 x float
1330; ==============================================================================
1331
1332define <4 x float> @load_v4f32_a1(ptr %p) {
1333; CHECK-LABEL: load_v4f32_a1:
1334; CHECK:         .functype load_v4f32_a1 (i32) -> (v128)
1335; CHECK-NEXT:  # %bb.0:
1336; CHECK-NEXT:    local.get 0
1337; CHECK-NEXT:    v128.load 0:p2align=0
1338; CHECK-NEXT:    # fallthrough-return
1339  %v = load <4 x float>, ptr %p, align 1
1340  ret <4 x float> %v
1341}
1342
1343define <4 x float> @load_v4f32_a4(ptr %p) {
1344; CHECK-LABEL: load_v4f32_a4:
1345; CHECK:         .functype load_v4f32_a4 (i32) -> (v128)
1346; CHECK-NEXT:  # %bb.0:
1347; CHECK-NEXT:    local.get 0
1348; CHECK-NEXT:    v128.load 0:p2align=2
1349; CHECK-NEXT:    # fallthrough-return
1350  %v = load <4 x float>, ptr %p, align 4
1351  ret <4 x float> %v
1352}
1353
1354; 4 is the default alignment for v128 so no attribute is needed.
1355define <4 x float> @load_v4f32_a16(ptr %p) {
1356; CHECK-LABEL: load_v4f32_a16:
1357; CHECK:         .functype load_v4f32_a16 (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 <4 x float>, ptr %p, align 16
1363  ret <4 x float> %v
1364}
1365
1366; 32 is greater than the default alignment so it is ignored.
1367define <4 x float> @load_v4f32_a32(ptr %p) {
1368; CHECK-LABEL: load_v4f32_a32:
1369; CHECK:         .functype load_v4f32_a32 (i32) -> (v128)
1370; CHECK-NEXT:  # %bb.0:
1371; CHECK-NEXT:    local.get 0
1372; CHECK-NEXT:    v128.load 0
1373; CHECK-NEXT:    # fallthrough-return
1374  %v = load <4 x float>, ptr %p, align 32
1375  ret <4 x float> %v
1376}
1377
1378define void @store_v4f32_a1(ptr %p, <4 x float> %v) {
1379; CHECK-LABEL: store_v4f32_a1:
1380; CHECK:         .functype store_v4f32_a1 (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=0
1385; CHECK-NEXT:    # fallthrough-return
1386  store <4 x float> %v, ptr %p, align 1
1387  ret void
1388}
1389
1390define void @store_v4f32_a4(ptr %p, <4 x float> %v) {
1391; CHECK-LABEL: store_v4f32_a4:
1392; CHECK:         .functype store_v4f32_a4 (i32, v128) -> ()
1393; CHECK-NEXT:  # %bb.0:
1394; CHECK-NEXT:    local.get 0
1395; CHECK-NEXT:    local.get 1
1396; CHECK-NEXT:    v128.store 0:p2align=2
1397; CHECK-NEXT:    # fallthrough-return
1398  store <4 x float> %v, ptr %p, align 4
1399  ret void
1400}
1401
1402; 16 is the default alignment for v128 so no attribute is needed.
1403define void @store_v4f32_a16(ptr %p, <4 x float> %v) {
1404; CHECK-LABEL: store_v4f32_a16:
1405; CHECK:         .functype store_v4f32_a16 (i32, v128) -> ()
1406; CHECK-NEXT:  # %bb.0:
1407; CHECK-NEXT:    local.get 0
1408; CHECK-NEXT:    local.get 1
1409; CHECK-NEXT:    v128.store 0
1410; CHECK-NEXT:    # fallthrough-return
1411  store <4 x float> %v, ptr %p, align 16
1412  ret void
1413}
1414
1415; 32 is greater than the default alignment so it is ignored.
1416define void @store_v4f32_a32(ptr %p, <4 x float> %v) {
1417; CHECK-LABEL: store_v4f32_a32:
1418; CHECK:         .functype store_v4f32_a32 (i32, v128) -> ()
1419; CHECK-NEXT:  # %bb.0:
1420; CHECK-NEXT:    local.get 0
1421; CHECK-NEXT:    local.get 1
1422; CHECK-NEXT:    v128.store 0
1423; CHECK-NEXT:    # fallthrough-return
1424  store <4 x float> %v, ptr %p, align 32
1425  ret void
1426}
1427
1428; ==============================================================================
1429; 2 x double
1430; ==============================================================================
1431
1432define <2 x double> @load_v2f64_a1(ptr %p) {
1433; CHECK-LABEL: load_v2f64_a1:
1434; CHECK:         .functype load_v2f64_a1 (i32) -> (v128)
1435; CHECK-NEXT:  # %bb.0:
1436; CHECK-NEXT:    local.get 0
1437; CHECK-NEXT:    v128.load 0:p2align=0
1438; CHECK-NEXT:    # fallthrough-return
1439  %v = load <2 x double>, ptr %p, align 1
1440  ret <2 x double> %v
1441}
1442
1443define <2 x double> @load_v2f64_a4(ptr %p) {
1444; CHECK-LABEL: load_v2f64_a4:
1445; CHECK:         .functype load_v2f64_a4 (i32) -> (v128)
1446; CHECK-NEXT:  # %bb.0:
1447; CHECK-NEXT:    local.get 0
1448; CHECK-NEXT:    v128.load 0:p2align=2
1449; CHECK-NEXT:    # fallthrough-return
1450  %v = load <2 x double>, ptr %p, align 4
1451  ret <2 x double> %v
1452}
1453
1454; 2 is the default alignment for v128 so no attribute is needed.
1455define <2 x double> @load_v2f64_a16(ptr %p) {
1456; CHECK-LABEL: load_v2f64_a16:
1457; CHECK:         .functype load_v2f64_a16 (i32) -> (v128)
1458; CHECK-NEXT:  # %bb.0:
1459; CHECK-NEXT:    local.get 0
1460; CHECK-NEXT:    v128.load 0
1461; CHECK-NEXT:    # fallthrough-return
1462  %v = load <2 x double>, ptr %p, align 16
1463  ret <2 x double> %v
1464}
1465
1466; 32 is greater than the default alignment so it is ignored.
1467define <2 x double> @load_v2f64_a32(ptr %p) {
1468; CHECK-LABEL: load_v2f64_a32:
1469; CHECK:         .functype load_v2f64_a32 (i32) -> (v128)
1470; CHECK-NEXT:  # %bb.0:
1471; CHECK-NEXT:    local.get 0
1472; CHECK-NEXT:    v128.load 0
1473; CHECK-NEXT:    # fallthrough-return
1474  %v = load <2 x double>, ptr %p, align 32
1475  ret <2 x double> %v
1476}
1477
1478define void @store_v2f64_a1(ptr %p, <2 x double> %v) {
1479; CHECK-LABEL: store_v2f64_a1:
1480; CHECK:         .functype store_v2f64_a1 (i32, v128) -> ()
1481; CHECK-NEXT:  # %bb.0:
1482; CHECK-NEXT:    local.get 0
1483; CHECK-NEXT:    local.get 1
1484; CHECK-NEXT:    v128.store 0:p2align=0
1485; CHECK-NEXT:    # fallthrough-return
1486  store <2 x double> %v, ptr %p, align 1
1487  ret void
1488}
1489
1490define void @store_v2f64_a4(ptr %p, <2 x double> %v) {
1491; CHECK-LABEL: store_v2f64_a4:
1492; CHECK:         .functype store_v2f64_a4 (i32, v128) -> ()
1493; CHECK-NEXT:  # %bb.0:
1494; CHECK-NEXT:    local.get 0
1495; CHECK-NEXT:    local.get 1
1496; CHECK-NEXT:    v128.store 0:p2align=2
1497; CHECK-NEXT:    # fallthrough-return
1498  store <2 x double> %v, ptr %p, align 4
1499  ret void
1500}
1501
1502; 16 is the default alignment for v128 so no attribute is needed.
1503define void @store_v2f64_a16(ptr %p, <2 x double> %v) {
1504; CHECK-LABEL: store_v2f64_a16:
1505; CHECK:         .functype store_v2f64_a16 (i32, v128) -> ()
1506; CHECK-NEXT:  # %bb.0:
1507; CHECK-NEXT:    local.get 0
1508; CHECK-NEXT:    local.get 1
1509; CHECK-NEXT:    v128.store 0
1510; CHECK-NEXT:    # fallthrough-return
1511  store <2 x double> %v, ptr %p, align 16
1512  ret void
1513}
1514
1515; 32 is greater than the default alignment so it is ignored.
1516define void @store_v2f64_a32(ptr %p, <2 x double> %v) {
1517; CHECK-LABEL: store_v2f64_a32:
1518; CHECK:         .functype store_v2f64_a32 (i32, v128) -> ()
1519; CHECK-NEXT:  # %bb.0:
1520; CHECK-NEXT:    local.get 0
1521; CHECK-NEXT:    local.get 1
1522; CHECK-NEXT:    v128.store 0
1523; CHECK-NEXT:    # fallthrough-return
1524  store <2 x double> %v, ptr %p, align 32
1525  ret void
1526}
1527