1; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
2; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
3; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
4
5; Test that basic SIMD128 vector manipulation operations assemble as expected.
6
7target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
8target triple = "wasm32-unknown-unknown"
9
10; ==============================================================================
11; 16 x i8
12; ==============================================================================
13; CHECK-LABEL: const_v16i8:
14; NO-SIMD128-NOT: i8x16
15; SIMD128: .result v128{{$}}
16; SIMD128: v128.const $push0=,
17; SIMD128-SAME: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
18; SIMD128-SAME: # encoding: [0xfd,0x00,
19; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
20; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
21define <16 x i8> @const_v16i8() {
22  ret <16 x i8> <i8 00, i8 01, i8 02, i8 03, i8 04, i8 05, i8 06, i8 07,
23                 i8 08, i8 09, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>
24}
25
26; CHECK-LABEL: splat_v16i8:
27; NO-SIMD128-NOT: i8x16
28; SIMD128: .param i32{{$}}
29; SIMD128: .result v128{{$}}
30; SIMD128: i8x16.splat $push0=, $0 # encoding: [0xfd,0x03]{{$}}
31; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
32define <16 x i8> @splat_v16i8(i8 %x) {
33  %v = insertelement <16 x i8> undef, i8 %x, i32 0
34  %res = shufflevector <16 x i8> %v, <16 x i8> undef,
35    <16 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0,
36                i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
37  ret <16 x i8> %res
38}
39
40; CHECK-LABEL: extract_v16i8_s:
41; NO-SIMD128-NOT: i8x16
42; SIMD128: .param v128{{$}}
43; SIMD128: .result i32{{$}}
44; SIMD128: i8x16.extract_lane_s $push0=, $0, 13 # encoding: [0xfd,0x09,0x0d]{{$}}
45; SIMD128: return $pop0 #
46define i32 @extract_v16i8_s(<16 x i8> %v) {
47  %elem = extractelement <16 x i8> %v, i8 13
48  %a = sext i8 %elem to i32
49  ret i32 %a
50}
51
52; CHECK-LABEL: extract_v16i8_u:
53; NO-SIMD128-NOT: i8x16
54; SIMD128: .param v128{{$}}
55; SIMD128: .result i32{{$}}
56; SIMD128: i8x16.extract_lane_u $push0=, $0, 13 # encoding: [0xfd,0x0a,0x0d]{{$}}
57; SIMD128: return $pop0 #
58define i32 @extract_v16i8_u(<16 x i8> %v) {
59  %elem = extractelement <16 x i8> %v, i8 13
60  %a = zext i8 %elem to i32
61  ret i32 %a
62}
63
64; CHECK-LABEL: extract_v16i8:
65; NO-SIMD128-NOT: i8x16
66; SIMD128: .param v128{{$}}
67; SIMD128: .result i32{{$}}
68; SIMD128: i8x16.extract_lane_u $push0=, $0, 13 # encoding: [0xfd,0x0a,0x0d]{{$}}
69; SIMD128: return $pop0 #
70define i8 @extract_v16i8(<16 x i8> %v) {
71  %elem = extractelement <16 x i8> %v, i8 13
72  ret i8 %elem
73}
74
75; CHECK-LABEL: replace_v16i8:
76; NO-SIMD128-NOT: i8x16
77; SIMD128: .param v128, i32{{$}}
78; SIMD128: .result v128{{$}}
79; SIMD128: i8x16.replace_lane $push0=, $0, 11, $1 # encoding: [0xfd,0x11,0x0b]{{$}}
80; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
81define <16 x i8> @replace_v16i8(<16 x i8> %v, i8 %x) {
82  %res = insertelement <16 x i8> %v, i8 %x, i32 11
83  ret <16 x i8> %res
84}
85
86; ==============================================================================
87; 8 x i16
88; ==============================================================================
89; CHECK-LABEL: const_v8i16:
90; NO-SIMD128-NOT: i16x8
91; SIMD128: .result v128{{$}}
92; SIMD128: v128.const $push0=, 256, 770, 1284, 1798, 2312, 2826, 3340, 3854
93; SIMD128-SAME: # encoding: [0xfd,0x00,
94; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
95; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
96define <8 x i16> @const_v8i16() {
97  ret <8 x i16> <i16 256, i16 770, i16 1284, i16 1798,
98                 i16 2312, i16 2826, i16 3340, i16 3854>
99}
100
101; CHECK-LABEL: splat_v8i16:
102; NO-SIMD128-NOT: i16x8
103; SIMD128: .param i32{{$}}
104; SIMD128: .result v128{{$}}
105; SIMD128: i16x8.splat $push0=, $0 # encoding: [0xfd,0x04]{{$}}
106; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
107define <8 x i16> @splat_v8i16(i16 %x) {
108  %v = insertelement <8 x i16> undef, i16 %x, i32 0
109  %res = shufflevector <8 x i16> %v, <8 x i16> undef,
110    <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
111  ret <8 x i16> %res
112}
113
114; CHECK-LABEL: extract_v8i16_s:
115; NO-SIMD128-NOT: i16x8
116; SIMD128: .param v128{{$}}
117; SIMD128: .result i32{{$}}
118; SIMD128: i16x8.extract_lane_s $push0=, $0, 5 # encoding: [0xfd,0x0b,0x05]{{$}}
119; SIMD128: return $pop0 #
120define i32 @extract_v8i16_s(<8 x i16> %v) {
121  %elem = extractelement <8 x i16> %v, i16 5
122  %a = sext i16 %elem to i32
123  ret i32 %a
124}
125
126; CHECK-LABEL: extract_v8i16_u:
127; NO-SIMD128-NOT: i16x8
128; SIMD128: .param v128{{$}}
129; SIMD128: .result i32{{$}}
130; SIMD128: i16x8.extract_lane_u $push0=, $0, 5 # encoding: [0xfd,0x0c,0x05]{{$}}
131; SIMD128: return $pop0 #
132define i32 @extract_v8i16_u(<8 x i16> %v) {
133  %elem = extractelement <8 x i16> %v, i16 5
134  %a = zext i16 %elem to i32
135  ret i32 %a
136}
137
138; CHECK-LABEL: extract_v8i16:
139; NO-SIMD128-NOT: i16x8
140; SIMD128: .param v128{{$}}
141; SIMD128: .result i32{{$}}
142; SIMD128: i16x8.extract_lane_u $push0=, $0, 5 # encoding: [0xfd,0x0c,0x05]{{$}}
143; SIMD128: return $pop0 #
144define i16 @extract_v8i16(<8 x i16> %v) {
145  %elem = extractelement <8 x i16> %v, i16 5
146  ret i16 %elem
147}
148
149; CHECK-LABEL: replace_v8i16:
150; NO-SIMD128-NOT: i16x8
151; SIMD128: .param v128, i32{{$}}
152; SIMD128: .result v128{{$}}
153; SIMD128: i16x8.replace_lane $push0=, $0, 7, $1 # encoding: [0xfd,0x12,0x07]{{$}}
154; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
155define <8 x i16> @replace_v8i16(<8 x i16> %v, i16 %x) {
156  %res = insertelement <8 x i16> %v, i16 %x, i32 7
157  ret <8 x i16> %res
158}
159
160; ==============================================================================
161; 4 x i32
162; ==============================================================================
163; CHECK-LABEL: const_v4i32:
164; NO-SIMD128-NOT: i32x4
165; SIMD128: .result v128{{$}}
166; SIMD128: v128.const $push0=, 50462976, 117835012, 185207048, 252579084
167; SIMD128-SAME: # encoding: [0xfd,0x00,
168; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
169; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
170define <4 x i32> @const_v4i32() {
171  ret <4 x i32> <i32 50462976, i32 117835012, i32 185207048, i32 252579084>
172}
173
174; CHECK-LABEL: splat_v4i32:
175; NO-SIMD128-NOT: i32x4
176; SIMD128: .param i32{{$}}
177; SIMD128: .result v128{{$}}
178; SIMD128: i32x4.splat $push0=, $0 # encoding: [0xfd,0x05]{{$}}
179; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
180define <4 x i32> @splat_v4i32(i32 %x) {
181  %v = insertelement <4 x i32> undef, i32 %x, i32 0
182  %res = shufflevector <4 x i32> %v, <4 x i32> undef,
183    <4 x i32> <i32 0, i32 0, i32 0, i32 0>
184  ret <4 x i32> %res
185}
186
187; CHECK-LABEL: extract_v4i32:
188; NO-SIMD128-NOT: i32x4
189; SIMD128: .param v128{{$}}
190; SIMD128: .result i32{{$}}
191; SIMD128: i32x4.extract_lane $push0=, $0, 3 # encoding: [0xfd,0x0d,0x03]{{$}}
192; SIMD128: return $pop0 #
193define i32 @extract_v4i32(<4 x i32> %v) {
194  %elem = extractelement <4 x i32> %v, i32 3
195  ret i32 %elem
196}
197
198; CHECK-LABEL: replace_v4i32:
199; NO-SIMD128-NOT: i32x4
200; SIMD128: .param v128, i32{{$}}
201; SIMD128: .result v128{{$}}
202; SIMD128: i32x4.replace_lane $push0=, $0, 2, $1 # encoding: [0xfd,0x13,0x02]{{$}}
203; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
204define <4 x i32> @replace_v4i32(<4 x i32> %v, i32 %x) {
205  %res = insertelement <4 x i32> %v, i32 %x, i32 2
206  ret <4 x i32> %res
207}
208
209; ==============================================================================
210; 2 x i64
211; ==============================================================================
212; CHECK-LABEL: const_v2i64:
213; NO-SIMD128-NOT: i64x2
214; SIMD128-VM-NOT: i64x2
215; SIMD128: .result v128{{$}}
216; SIMD128: v128.const $push0=, 506097522914230528, 1084818905618843912
217; SIMD128-SAME: # encoding: [0xfd,0x00,
218; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
219; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
220define <2 x i64> @const_v2i64() {
221  ret <2 x i64> <i64 506097522914230528, i64 1084818905618843912>
222}
223
224; CHECK-LABEL: splat_v2i64:
225; NO-SIMD128-NOT: i64x2
226; SIMD128-VM-NOT: i64x2
227; SIMD128: .param i64{{$}}
228; SIMD128: .result v128{{$}}
229; SIMD128: i64x2.splat $push0=, $0 # encoding: [0xfd,0x06]{{$}}
230; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
231define <2 x i64> @splat_v2i64(i64 %x) {
232  %t1 = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
233  %res = insertelement <2 x i64> %t1, i64 %x, i32 1
234  ret <2 x i64> %res
235}
236
237; CHECK-LABEL: extract_v2i64:
238; NO-SIMD128-NOT: i64x2
239; SIMD128-VM-NOT: i64x2
240; SIMD128: .param v128{{$}}
241; SIMD128: .result i64{{$}}
242; SIMD128: i64x2.extract_lane $push0=, $0, 1 # encoding: [0xfd,0x0e,0x01]{{$}}
243; SIMD128: return $pop0 #
244define i64 @extract_v2i64(<2 x i64> %v) {
245  %elem = extractelement <2 x i64> %v, i64 1
246  ret i64 %elem
247}
248
249; CHECK-LABEL: replace_v2i64:
250; NO-SIMD128-NOT: i64x2
251; SIMD128-VM-NOT: i64x2
252; SIMD128: .param v128, i64{{$}}
253; SIMD128: .result v128{{$}}
254; SIMD128: i64x2.replace_lane $push0=, $0, 0, $1 # encoding: [0xfd,0x14,0x00]{{$}}
255; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
256define <2 x i64> @replace_v2i64(<2 x i64> %v, i64 %x) {
257  %res = insertelement <2 x i64> %v, i64 %x, i32 0
258  ret <2 x i64> %res
259}
260
261; ==============================================================================
262; 4 x f32
263; ==============================================================================
264; CHECK-LABEL: const_v4f32:
265; NO-SIMD128-NOT: f32x4
266; SIMD128: .result v128{{$}}
267; SIMD128: v128.const $push0=,
268; SIMD128-SAME: 0x1.0402p-121, 0x1.0c0a08p-113, 0x1.14121p-105, 0x1.1c1a18p-97
269; SIMD128-SAME: # encoding: [0xfd,0x00,
270; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
271; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
272define <4 x float> @const_v4f32() {
273  ret <4 x float> <float 0x3860402000000000, float 0x38e0c0a080000000,
274                   float 0x3961412100000000, float 0x39e1c1a180000000>
275}
276
277; CHECK-LABEL: splat_v4f32:
278; NO-SIMD128-NOT: f32x4
279; SIMD128: .param f32{{$}}
280; SIMD128: .result v128{{$}}
281; SIMD128: f32x4.splat $push0=, $0 # encoding: [0xfd,0x07]{{$}}
282; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
283define <4 x float> @splat_v4f32(float %x) {
284  %v = insertelement <4 x float> undef, float %x, i32 0
285  %res = shufflevector <4 x float> %v, <4 x float> undef,
286    <4 x i32> <i32 0, i32 0, i32 0, i32 0>
287  ret <4 x float> %res
288}
289
290; CHECK-LABEL: extract_v4f32:
291; NO-SIMD128-NOT: f32x4
292; SIMD128: .param v128{{$}}
293; SIMD128: .result f32{{$}}
294; SIMD128: f32x4.extract_lane $push0=, $0, 3 # encoding: [0xfd,0x0f,0x03]{{$}}
295; SIMD128: return $pop0 #
296define float @extract_v4f32(<4 x float> %v) {
297  %elem = extractelement <4 x float> %v, i32 3
298  ret float %elem
299}
300
301; CHECK-LABEL: replace_v4f32:
302; NO-SIMD128-NOT: f32x4
303; SIMD128: .param v128, f32{{$}}
304; SIMD128: .result v128{{$}}
305; SIMD128: f32x4.replace_lane $push0=, $0, 2, $1 # encoding: [0xfd,0x15,0x02]{{$}}
306; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
307define <4 x float> @replace_v4f32(<4 x float> %v, float %x) {
308  %res = insertelement <4 x float> %v, float %x, i32 2
309  ret <4 x float> %res
310}
311
312; ==============================================================================
313; 2 x f64
314; ==============================================================================
315; CHECK-LABEL: const_v2f64:
316; NO-SIMD128-NOT: f64x2
317; SIMD128: .result v128{{$}}
318; SIMD128: v128.const $push0=, 0x1.60504030201p-911, 0x1.e0d0c0b0a0908p-783
319; SIMD128-SAME: # encoding: [0xfd,0x00,
320; SIMD128-SAME: 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
321; SIMD128-SAME: 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f]{{$}}
322define <2 x double> @const_v2f64() {
323  ret <2 x double> <double 0x0706050403020100, double 0x0F0E0D0C0B0A0908>
324}
325
326; CHECK-LABEL: splat_v2f64:
327; NO-SIMD128-NOT: f64x2
328; SIMD128-VM-NOT: f64x2
329; SIMD128: .param f64{{$}}
330; SIMD128: .result v128{{$}}
331; SIMD128: f64x2.splat $push0=, $0 # encoding: [0xfd,0x08]{{$}}
332; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
333define <2 x double> @splat_v2f64(double %x) {
334  %t1 = insertelement <2 x double> zeroinitializer, double %x, i3 0
335  %res = insertelement <2 x double> %t1, double %x, i32 1
336  ret <2 x double> %res
337}
338
339; CHECK-LABEL: extract_v2f64:
340; NO-SIMD128-NOT: f64x2
341; SIMD128-VM-NOT: f64x2
342; SIMD128: .param v128{{$}}
343; SIMD128: .result f64{{$}}
344; SIMD128: f64x2.extract_lane $push0=, $0, 1 # encoding: [0xfd,0x10,0x01]{{$}}
345; SIMD128: return $pop0 #
346define double @extract_v2f64(<2 x double> %v) {
347  %elem = extractelement <2 x double> %v, i32 1
348  ret double %elem
349}
350
351; CHECK-LABEL: replace_v2f64:
352; NO-SIMD128-NOT: f64x2
353; SIMD128-VM-NOT: f64x2
354; SIMD128: .param v128, f64{{$}}
355; SIMD128: .result v128{{$}}
356; SIMD128: f64x2.replace_lane $push0=, $0, 0, $1 # encoding: [0xfd,0x16,0x00]{{$}}
357; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
358define <2 x double> @replace_v2f64(<2 x double> %v, double %x) {
359  %res = insertelement <2 x double> %v, double %x, i32 0
360  ret <2 x double> %res
361}
362