1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx,+f16c -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX1
3; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx2,+f16c -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX2
4; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx2,+f16c,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX2
5; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx2,+f16c,+fast-variable-perlane-shuffle -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX2
6; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX512
7; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512vl,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX512
8; RUN: llc < %s -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512vl,+fast-variable-perlane-shuffle -verify-machineinstrs | FileCheck %s --check-prefixes=ALL,AVX512
9
10;
11; Half to Float
12;
13
14define float @cvt_i16_to_f32(i16 %a0) nounwind {
15; ALL-LABEL: cvt_i16_to_f32:
16; ALL:       # %bb.0:
17; ALL-NEXT:    movzwl %di, %eax
18; ALL-NEXT:    vmovd %eax, %xmm0
19; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
20; ALL-NEXT:    retq
21  %1 = bitcast i16 %a0 to half
22  %2 = fpext half %1 to float
23  ret float %2
24}
25
26define <4 x float> @cvt_4i16_to_4f32(<4 x i16> %a0) nounwind {
27; ALL-LABEL: cvt_4i16_to_4f32:
28; ALL:       # %bb.0:
29; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
30; ALL-NEXT:    retq
31  %1 = bitcast <4 x i16> %a0 to <4 x half>
32  %2 = fpext <4 x half> %1 to <4 x float>
33  ret <4 x float> %2
34}
35
36define <4 x float> @cvt_8i16_to_4f32(<8 x i16> %a0) nounwind {
37; ALL-LABEL: cvt_8i16_to_4f32:
38; ALL:       # %bb.0:
39; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
40; ALL-NEXT:    retq
41  %1 = shufflevector <8 x i16> %a0, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
42  %2 = bitcast <4 x i16> %1 to <4 x half>
43  %3 = fpext <4 x half> %2 to <4 x float>
44  ret <4 x float> %3
45}
46
47define <8 x float> @cvt_8i16_to_8f32(<8 x i16> %a0) nounwind {
48; ALL-LABEL: cvt_8i16_to_8f32:
49; ALL:       # %bb.0:
50; ALL-NEXT:    vcvtph2ps %xmm0, %ymm0
51; ALL-NEXT:    retq
52  %1 = bitcast <8 x i16> %a0 to <8 x half>
53  %2 = fpext <8 x half> %1 to <8 x float>
54  ret <8 x float> %2
55}
56
57define <16 x float> @cvt_16i16_to_16f32(<16 x i16> %a0) nounwind {
58; AVX1-LABEL: cvt_16i16_to_16f32:
59; AVX1:       # %bb.0:
60; AVX1-NEXT:    vcvtph2ps %xmm0, %ymm2
61; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
62; AVX1-NEXT:    vcvtph2ps %xmm0, %ymm1
63; AVX1-NEXT:    vmovaps %ymm2, %ymm0
64; AVX1-NEXT:    retq
65;
66; AVX2-LABEL: cvt_16i16_to_16f32:
67; AVX2:       # %bb.0:
68; AVX2-NEXT:    vcvtph2ps %xmm0, %ymm2
69; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
70; AVX2-NEXT:    vcvtph2ps %xmm0, %ymm1
71; AVX2-NEXT:    vmovaps %ymm2, %ymm0
72; AVX2-NEXT:    retq
73;
74; AVX512-LABEL: cvt_16i16_to_16f32:
75; AVX512:       # %bb.0:
76; AVX512-NEXT:    vcvtph2ps %ymm0, %zmm0
77; AVX512-NEXT:    retq
78  %1 = bitcast <16 x i16> %a0 to <16 x half>
79  %2 = fpext <16 x half> %1 to <16 x float>
80  ret <16 x float> %2
81}
82
83define <2 x float> @cvt_2i16_to_2f32_constrained(<2 x i16> %a0) nounwind strictfp {
84; ALL-LABEL: cvt_2i16_to_2f32_constrained:
85; ALL:       # %bb.0:
86; ALL-NEXT:    vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
87; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
88; ALL-NEXT:    retq
89  %1 = bitcast <2 x i16> %a0 to <2 x half>
90  %2 = call <2 x float> @llvm.experimental.constrained.fpext.v2f32.v2f16(<2 x half> %1, metadata !"fpexcept.strict") strictfp
91  ret <2 x float> %2
92}
93declare <2 x float> @llvm.experimental.constrained.fpext.v2f32.v2f16(<2 x half>, metadata) strictfp
94
95define <4 x float> @cvt_4i16_to_4f32_constrained(<4 x i16> %a0) nounwind strictfp {
96; ALL-LABEL: cvt_4i16_to_4f32_constrained:
97; ALL:       # %bb.0:
98; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
99; ALL-NEXT:    retq
100  %1 = bitcast <4 x i16> %a0 to <4 x half>
101  %2 = call <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half> %1, metadata !"fpexcept.strict") strictfp
102  ret <4 x float> %2
103}
104declare <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half>, metadata) strictfp
105
106define <8 x float> @cvt_8i16_to_8f32_constrained(<8 x i16> %a0) nounwind strictfp {
107; ALL-LABEL: cvt_8i16_to_8f32_constrained:
108; ALL:       # %bb.0:
109; ALL-NEXT:    vcvtph2ps %xmm0, %ymm0
110; ALL-NEXT:    retq
111  %1 = bitcast <8 x i16> %a0 to <8 x half>
112  %2 = call <8 x float> @llvm.experimental.constrained.fpext.v8f32.v8f16(<8 x half> %1, metadata !"fpexcept.strict") strictfp
113  ret <8 x float> %2
114}
115declare <8 x float> @llvm.experimental.constrained.fpext.v8f32.v8f16(<8 x half>, metadata) strictfp
116
117define <16 x float> @cvt_16i16_to_16f32_constrained(<16 x i16> %a0) nounwind strictfp {
118; AVX1-LABEL: cvt_16i16_to_16f32_constrained:
119; AVX1:       # %bb.0:
120; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm1
121; AVX1-NEXT:    vcvtph2ps %xmm1, %ymm1
122; AVX1-NEXT:    vcvtph2ps %xmm0, %ymm0
123; AVX1-NEXT:    retq
124;
125; AVX2-LABEL: cvt_16i16_to_16f32_constrained:
126; AVX2:       # %bb.0:
127; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm1
128; AVX2-NEXT:    vcvtph2ps %xmm1, %ymm1
129; AVX2-NEXT:    vcvtph2ps %xmm0, %ymm0
130; AVX2-NEXT:    retq
131;
132; AVX512-LABEL: cvt_16i16_to_16f32_constrained:
133; AVX512:       # %bb.0:
134; AVX512-NEXT:    vcvtph2ps %ymm0, %zmm0
135; AVX512-NEXT:    retq
136  %1 = bitcast <16 x i16> %a0 to <16 x half>
137  %2 = call <16 x float> @llvm.experimental.constrained.fpext.v16f32.v16f16(<16 x half> %1, metadata !"fpexcept.strict") strictfp
138  ret <16 x float> %2
139}
140declare <16 x float> @llvm.experimental.constrained.fpext.v16f32.v16f16(<16 x half>, metadata) strictfp
141
142;
143; Half to Float (Load)
144;
145
146define float @load_cvt_i16_to_f32(ptr %a0) nounwind {
147; ALL-LABEL: load_cvt_i16_to_f32:
148; ALL:       # %bb.0:
149; ALL-NEXT:    movzwl (%rdi), %eax
150; ALL-NEXT:    vmovd %eax, %xmm0
151; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
152; ALL-NEXT:    retq
153  %1 = load i16, ptr %a0
154  %2 = bitcast i16 %1 to half
155  %3 = fpext half %2 to float
156  ret float %3
157}
158
159define <4 x float> @load_cvt_4i16_to_4f32(ptr %a0) nounwind {
160; ALL-LABEL: load_cvt_4i16_to_4f32:
161; ALL:       # %bb.0:
162; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
163; ALL-NEXT:    retq
164  %1 = load <4 x i16>, ptr %a0
165  %2 = bitcast <4 x i16> %1 to <4 x half>
166  %3 = fpext <4 x half> %2 to <4 x float>
167  ret <4 x float> %3
168}
169
170define <4 x float> @load_cvt_8i16_to_4f32(ptr %a0) nounwind {
171; ALL-LABEL: load_cvt_8i16_to_4f32:
172; ALL:       # %bb.0:
173; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
174; ALL-NEXT:    retq
175  %1 = load <8 x i16>, ptr %a0
176  %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
177  %3 = bitcast <4 x i16> %2 to <4 x half>
178  %4 = fpext <4 x half> %3 to <4 x float>
179  ret <4 x float> %4
180}
181
182define <8 x float> @load_cvt_8i16_to_8f32(ptr %a0) nounwind {
183; ALL-LABEL: load_cvt_8i16_to_8f32:
184; ALL:       # %bb.0:
185; ALL-NEXT:    vcvtph2ps (%rdi), %ymm0
186; ALL-NEXT:    retq
187  %1 = load <8 x i16>, ptr %a0
188  %2 = bitcast <8 x i16> %1 to <8 x half>
189  %3 = fpext <8 x half> %2 to <8 x float>
190  ret <8 x float> %3
191}
192
193define <16 x float> @load_cvt_16i16_to_16f32(ptr %a0) nounwind {
194; AVX1-LABEL: load_cvt_16i16_to_16f32:
195; AVX1:       # %bb.0:
196; AVX1-NEXT:    vcvtph2ps (%rdi), %ymm0
197; AVX1-NEXT:    vcvtph2ps 16(%rdi), %ymm1
198; AVX1-NEXT:    retq
199;
200; AVX2-LABEL: load_cvt_16i16_to_16f32:
201; AVX2:       # %bb.0:
202; AVX2-NEXT:    vcvtph2ps (%rdi), %ymm0
203; AVX2-NEXT:    vcvtph2ps 16(%rdi), %ymm1
204; AVX2-NEXT:    retq
205;
206; AVX512-LABEL: load_cvt_16i16_to_16f32:
207; AVX512:       # %bb.0:
208; AVX512-NEXT:    vcvtph2ps (%rdi), %zmm0
209; AVX512-NEXT:    retq
210  %1 = load <16 x i16>, ptr %a0
211  %2 = bitcast <16 x i16> %1 to <16 x half>
212  %3 = fpext <16 x half> %2 to <16 x float>
213  ret <16 x float> %3
214}
215
216define <4 x float> @load_cvt_4i16_to_4f32_constrained(ptr %a0) nounwind strictfp {
217; ALL-LABEL: load_cvt_4i16_to_4f32_constrained:
218; ALL:       # %bb.0:
219; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
220; ALL-NEXT:    retq
221  %1 = load <4 x i16>, ptr %a0
222  %2 = bitcast <4 x i16> %1 to <4 x half>
223  %3 = call <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half> %2, metadata !"fpexcept.strict") strictfp
224  ret <4 x float> %3
225}
226
227define <4 x float> @load_cvt_8i16_to_4f32_constrained(ptr %a0) nounwind strictfp {
228; ALL-LABEL: load_cvt_8i16_to_4f32_constrained:
229; ALL:       # %bb.0:
230; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
231; ALL-NEXT:    retq
232  %1 = load <8 x i16>, ptr %a0
233  %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
234  %3 = bitcast <4 x i16> %2 to <4 x half>
235  %4 = call <4 x float> @llvm.experimental.constrained.fpext.v4f32.v4f16(<4 x half> %3, metadata !"fpexcept.strict") strictfp
236  ret <4 x float> %4
237}
238
239;
240; Half to Double
241;
242
243define double @cvt_i16_to_f64(i16 %a0) nounwind {
244; ALL-LABEL: cvt_i16_to_f64:
245; ALL:       # %bb.0:
246; ALL-NEXT:    movzwl %di, %eax
247; ALL-NEXT:    vmovd %eax, %xmm0
248; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
249; ALL-NEXT:    vcvtss2sd %xmm0, %xmm0, %xmm0
250; ALL-NEXT:    retq
251  %1 = bitcast i16 %a0 to half
252  %2 = fpext half %1 to double
253  ret double %2
254}
255
256define <2 x double> @cvt_2i16_to_2f64(<2 x i16> %a0) nounwind {
257; ALL-LABEL: cvt_2i16_to_2f64:
258; ALL:       # %bb.0:
259; ALL-NEXT:    vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
260; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
261; ALL-NEXT:    vcvtps2pd %xmm0, %xmm0
262; ALL-NEXT:    retq
263  %1 = bitcast <2 x i16> %a0 to <2 x half>
264  %2 = fpext <2 x half> %1 to <2 x double>
265  ret <2 x double> %2
266}
267
268define <4 x double> @cvt_4i16_to_4f64(<4 x i16> %a0) nounwind {
269; ALL-LABEL: cvt_4i16_to_4f64:
270; ALL:       # %bb.0:
271; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
272; ALL-NEXT:    vcvtps2pd %xmm0, %ymm0
273; ALL-NEXT:    retq
274  %1 = bitcast <4 x i16> %a0 to <4 x half>
275  %2 = fpext <4 x half> %1 to <4 x double>
276  ret <4 x double> %2
277}
278
279define <2 x double> @cvt_8i16_to_2f64(<8 x i16> %a0) nounwind {
280; ALL-LABEL: cvt_8i16_to_2f64:
281; ALL:       # %bb.0:
282; ALL-NEXT:    vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
283; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
284; ALL-NEXT:    vcvtps2pd %xmm0, %xmm0
285; ALL-NEXT:    retq
286  %1 = shufflevector <8 x i16> %a0, <8 x i16> undef, <2 x i32> <i32 0, i32 1>
287  %2 = bitcast <2 x i16> %1 to <2 x half>
288  %3 = fpext <2 x half> %2 to <2 x double>
289  ret <2 x double> %3
290}
291
292define <4 x double> @cvt_8i16_to_4f64(<8 x i16> %a0) nounwind {
293; ALL-LABEL: cvt_8i16_to_4f64:
294; ALL:       # %bb.0:
295; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
296; ALL-NEXT:    vcvtps2pd %xmm0, %ymm0
297; ALL-NEXT:    retq
298  %1 = shufflevector <8 x i16> %a0, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
299  %2 = bitcast <4 x i16> %1 to <4 x half>
300  %3 = fpext <4 x half> %2 to <4 x double>
301  ret <4 x double> %3
302}
303
304define <8 x double> @cvt_8i16_to_8f64(<8 x i16> %a0) nounwind {
305; AVX1-LABEL: cvt_8i16_to_8f64:
306; AVX1:       # %bb.0:
307; AVX1-NEXT:    vcvtph2ps %xmm0, %ymm1
308; AVX1-NEXT:    vcvtps2pd %xmm1, %ymm0
309; AVX1-NEXT:    vextractf128 $1, %ymm1, %xmm1
310; AVX1-NEXT:    vcvtps2pd %xmm1, %ymm1
311; AVX1-NEXT:    retq
312;
313; AVX2-LABEL: cvt_8i16_to_8f64:
314; AVX2:       # %bb.0:
315; AVX2-NEXT:    vcvtph2ps %xmm0, %ymm1
316; AVX2-NEXT:    vcvtps2pd %xmm1, %ymm0
317; AVX2-NEXT:    vextractf128 $1, %ymm1, %xmm1
318; AVX2-NEXT:    vcvtps2pd %xmm1, %ymm1
319; AVX2-NEXT:    retq
320;
321; AVX512-LABEL: cvt_8i16_to_8f64:
322; AVX512:       # %bb.0:
323; AVX512-NEXT:    vcvtph2ps %xmm0, %ymm0
324; AVX512-NEXT:    vcvtps2pd %ymm0, %zmm0
325; AVX512-NEXT:    retq
326  %1 = bitcast <8 x i16> %a0 to <8 x half>
327  %2 = fpext <8 x half> %1 to <8 x double>
328  ret <8 x double> %2
329}
330
331define <2 x double> @cvt_2i16_to_2f64_constrained(<2 x i16> %a0) nounwind strictfp {
332; ALL-LABEL: cvt_2i16_to_2f64_constrained:
333; ALL:       # %bb.0:
334; ALL-NEXT:    vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
335; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
336; ALL-NEXT:    vcvtps2pd %xmm0, %xmm0
337; ALL-NEXT:    retq
338  %1 = bitcast <2 x i16> %a0 to <2 x half>
339  %2 = call <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f16(<2 x half> %1, metadata !"fpexcept.strict") strictfp
340  ret <2 x double> %2
341}
342declare <2 x double> @llvm.experimental.constrained.fpext.v2f64.v2f16(<2 x half>, metadata) strictfp
343
344define <4 x double> @cvt_4i16_to_4f64_constrained(<4 x i16> %a0) nounwind strictfp {
345; ALL-LABEL: cvt_4i16_to_4f64_constrained:
346; ALL:       # %bb.0:
347; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
348; ALL-NEXT:    vcvtps2pd %xmm0, %ymm0
349; ALL-NEXT:    retq
350  %1 = bitcast <4 x i16> %a0 to <4 x half>
351  %2 = call <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f16(<4 x half> %1, metadata !"fpexcept.strict") strictfp
352  ret <4 x double> %2
353}
354declare <4 x double> @llvm.experimental.constrained.fpext.v4f64.v4f16(<4 x half>, metadata) strictfp
355
356define <8 x double> @cvt_8i16_to_8f64_constrained(<8 x i16> %a0) nounwind strictfp {
357; AVX1-LABEL: cvt_8i16_to_8f64_constrained:
358; AVX1:       # %bb.0:
359; AVX1-NEXT:    vcvtph2ps %xmm0, %ymm0
360; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm1
361; AVX1-NEXT:    vcvtps2pd %xmm1, %ymm1
362; AVX1-NEXT:    vcvtps2pd %xmm0, %ymm0
363; AVX1-NEXT:    retq
364;
365; AVX2-LABEL: cvt_8i16_to_8f64_constrained:
366; AVX2:       # %bb.0:
367; AVX2-NEXT:    vcvtph2ps %xmm0, %ymm0
368; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm1
369; AVX2-NEXT:    vcvtps2pd %xmm1, %ymm1
370; AVX2-NEXT:    vcvtps2pd %xmm0, %ymm0
371; AVX2-NEXT:    retq
372;
373; AVX512-LABEL: cvt_8i16_to_8f64_constrained:
374; AVX512:       # %bb.0:
375; AVX512-NEXT:    vcvtph2ps %xmm0, %ymm0
376; AVX512-NEXT:    vcvtps2pd %ymm0, %zmm0
377; AVX512-NEXT:    retq
378  %1 = bitcast <8 x i16> %a0 to <8 x half>
379  %2 = call <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f16(<8 x half> %1, metadata !"fpexcept.strict") strictfp
380  ret <8 x double> %2
381}
382declare <8 x double> @llvm.experimental.constrained.fpext.v8f64.v8f16(<8 x half>, metadata) strictfp
383
384;
385; Half to Double (Load)
386;
387
388define double @load_cvt_i16_to_f64(ptr %a0) nounwind {
389; ALL-LABEL: load_cvt_i16_to_f64:
390; ALL:       # %bb.0:
391; ALL-NEXT:    movzwl (%rdi), %eax
392; ALL-NEXT:    vmovd %eax, %xmm0
393; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
394; ALL-NEXT:    vcvtss2sd %xmm0, %xmm0, %xmm0
395; ALL-NEXT:    retq
396  %1 = load i16, ptr %a0
397  %2 = bitcast i16 %1 to half
398  %3 = fpext half %2 to double
399  ret double %3
400}
401
402define <2 x double> @load_cvt_2i16_to_2f64(ptr %a0) nounwind {
403; ALL-LABEL: load_cvt_2i16_to_2f64:
404; ALL:       # %bb.0:
405; ALL-NEXT:    vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
406; ALL-NEXT:    vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
407; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
408; ALL-NEXT:    vcvtps2pd %xmm0, %xmm0
409; ALL-NEXT:    retq
410  %1 = load <2 x i16>, ptr %a0
411  %2 = bitcast <2 x i16> %1 to <2 x half>
412  %3 = fpext <2 x half> %2 to <2 x double>
413  ret <2 x double> %3
414}
415
416define <4 x double> @load_cvt_4i16_to_4f64(ptr %a0) nounwind {
417; ALL-LABEL: load_cvt_4i16_to_4f64:
418; ALL:       # %bb.0:
419; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
420; ALL-NEXT:    vcvtps2pd %xmm0, %ymm0
421; ALL-NEXT:    retq
422  %1 = load <4 x i16>, ptr %a0
423  %2 = bitcast <4 x i16> %1 to <4 x half>
424  %3 = fpext <4 x half> %2 to <4 x double>
425  ret <4 x double> %3
426}
427
428define <4 x double> @load_cvt_8i16_to_4f64(ptr %a0) nounwind {
429; ALL-LABEL: load_cvt_8i16_to_4f64:
430; ALL:       # %bb.0:
431; ALL-NEXT:    vcvtph2ps (%rdi), %xmm0
432; ALL-NEXT:    vcvtps2pd %xmm0, %ymm0
433; ALL-NEXT:    retq
434  %1 = load <8 x i16>, ptr %a0
435  %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
436  %3 = bitcast <4 x i16> %2 to <4 x half>
437  %4 = fpext <4 x half> %3 to <4 x double>
438  ret <4 x double> %4
439}
440
441define <8 x double> @load_cvt_8i16_to_8f64(ptr %a0) nounwind {
442; AVX1-LABEL: load_cvt_8i16_to_8f64:
443; AVX1:       # %bb.0:
444; AVX1-NEXT:    vcvtph2ps (%rdi), %ymm1
445; AVX1-NEXT:    vcvtps2pd %xmm1, %ymm0
446; AVX1-NEXT:    vextractf128 $1, %ymm1, %xmm1
447; AVX1-NEXT:    vcvtps2pd %xmm1, %ymm1
448; AVX1-NEXT:    retq
449;
450; AVX2-LABEL: load_cvt_8i16_to_8f64:
451; AVX2:       # %bb.0:
452; AVX2-NEXT:    vcvtph2ps (%rdi), %ymm1
453; AVX2-NEXT:    vcvtps2pd %xmm1, %ymm0
454; AVX2-NEXT:    vextractf128 $1, %ymm1, %xmm1
455; AVX2-NEXT:    vcvtps2pd %xmm1, %ymm1
456; AVX2-NEXT:    retq
457;
458; AVX512-LABEL: load_cvt_8i16_to_8f64:
459; AVX512:       # %bb.0:
460; AVX512-NEXT:    vcvtph2ps (%rdi), %ymm0
461; AVX512-NEXT:    vcvtps2pd %ymm0, %zmm0
462; AVX512-NEXT:    retq
463  %1 = load <8 x i16>, ptr %a0
464  %2 = bitcast <8 x i16> %1 to <8 x half>
465  %3 = fpext <8 x half> %2 to <8 x double>
466  ret <8 x double> %3
467}
468
469;
470; Float to Half
471;
472
473define i16 @cvt_f32_to_i16(float %a0) nounwind {
474; ALL-LABEL: cvt_f32_to_i16:
475; ALL:       # %bb.0:
476; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
477; ALL-NEXT:    vmovd %xmm0, %eax
478; ALL-NEXT:    # kill: def $ax killed $ax killed $eax
479; ALL-NEXT:    retq
480  %1 = fptrunc float %a0 to half
481  %2 = bitcast half %1 to i16
482  ret i16 %2
483}
484
485define <4 x i16> @cvt_4f32_to_4i16(<4 x float> %a0) nounwind {
486; ALL-LABEL: cvt_4f32_to_4i16:
487; ALL:       # %bb.0:
488; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
489; ALL-NEXT:    retq
490  %1 = fptrunc <4 x float> %a0 to <4 x half>
491  %2 = bitcast <4 x half> %1 to <4 x i16>
492  ret <4 x i16> %2
493}
494
495define <8 x i16> @cvt_4f32_to_8i16_undef(<4 x float> %a0) nounwind {
496; ALL-LABEL: cvt_4f32_to_8i16_undef:
497; ALL:       # %bb.0:
498; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
499; ALL-NEXT:    retq
500  %1 = fptrunc <4 x float> %a0 to <4 x half>
501  %2 = bitcast <4 x half> %1 to <4 x i16>
502  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
503  ret <8 x i16> %3
504}
505
506define <8 x i16> @cvt_4f32_to_8i16_zero(<4 x float> %a0) nounwind {
507; ALL-LABEL: cvt_4f32_to_8i16_zero:
508; ALL:       # %bb.0:
509; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
510; ALL-NEXT:    retq
511  %1 = fptrunc <4 x float> %a0 to <4 x half>
512  %2 = bitcast <4 x half> %1 to <4 x i16>
513  %3 = shufflevector <4 x i16> %2, <4 x i16> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
514  ret <8 x i16> %3
515}
516
517define <8 x i16> @cvt_8f32_to_8i16(<8 x float> %a0) nounwind {
518; ALL-LABEL: cvt_8f32_to_8i16:
519; ALL:       # %bb.0:
520; ALL-NEXT:    vcvtps2ph $4, %ymm0, %xmm0
521; ALL-NEXT:    vzeroupper
522; ALL-NEXT:    retq
523  %1 = fptrunc <8 x float> %a0 to <8 x half>
524  %2 = bitcast <8 x half> %1 to <8 x i16>
525  ret <8 x i16> %2
526}
527
528define <16 x i16> @cvt_16f32_to_16i16(<16 x float> %a0) nounwind {
529; AVX1-LABEL: cvt_16f32_to_16i16:
530; AVX1:       # %bb.0:
531; AVX1-NEXT:    vcvtps2ph $4, %ymm0, %xmm0
532; AVX1-NEXT:    vcvtps2ph $4, %ymm1, %xmm1
533; AVX1-NEXT:    vinsertf128 $1, %xmm1, %ymm0, %ymm0
534; AVX1-NEXT:    retq
535;
536; AVX2-LABEL: cvt_16f32_to_16i16:
537; AVX2:       # %bb.0:
538; AVX2-NEXT:    vcvtps2ph $4, %ymm0, %xmm0
539; AVX2-NEXT:    vcvtps2ph $4, %ymm1, %xmm1
540; AVX2-NEXT:    vinsertf128 $1, %xmm1, %ymm0, %ymm0
541; AVX2-NEXT:    retq
542;
543; AVX512-LABEL: cvt_16f32_to_16i16:
544; AVX512:       # %bb.0:
545; AVX512-NEXT:    vcvtps2ph $4, %zmm0, %ymm0
546; AVX512-NEXT:    retq
547  %1 = fptrunc <16 x float> %a0 to <16 x half>
548  %2 = bitcast <16 x half> %1 to <16 x i16>
549  ret <16 x i16> %2
550}
551
552;
553; Float to Half (Store)
554;
555
556define void @store_cvt_f32_to_i16(float %a0, ptr %a1) nounwind {
557; ALL-LABEL: store_cvt_f32_to_i16:
558; ALL:       # %bb.0:
559; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
560; ALL-NEXT:    vmovd %xmm0, %eax
561; ALL-NEXT:    movw %ax, (%rdi)
562; ALL-NEXT:    retq
563  %1 = fptrunc float %a0 to half
564  %2 = bitcast half %1 to i16
565  store i16 %2, ptr %a1
566  ret void
567}
568
569define void @store_cvt_4f32_to_4i16(<4 x float> %a0, ptr %a1) nounwind {
570; ALL-LABEL: store_cvt_4f32_to_4i16:
571; ALL:       # %bb.0:
572; ALL-NEXT:    vcvtps2ph $4, %xmm0, (%rdi)
573; ALL-NEXT:    retq
574  %1 = fptrunc <4 x float> %a0 to <4 x half>
575  %2 = bitcast <4 x half> %1 to <4 x i16>
576  store <4 x i16> %2, ptr %a1
577  ret void
578}
579
580define void @store_cvt_4f32_to_8i16_undef(<4 x float> %a0, ptr %a1) nounwind {
581; ALL-LABEL: store_cvt_4f32_to_8i16_undef:
582; ALL:       # %bb.0:
583; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
584; ALL-NEXT:    vmovaps %xmm0, (%rdi)
585; ALL-NEXT:    retq
586  %1 = fptrunc <4 x float> %a0 to <4 x half>
587  %2 = bitcast <4 x half> %1 to <4 x i16>
588  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
589  store <8 x i16> %3, ptr %a1
590  ret void
591}
592
593define void @store_cvt_4f32_to_8i16_zero(<4 x float> %a0, ptr %a1) nounwind {
594; ALL-LABEL: store_cvt_4f32_to_8i16_zero:
595; ALL:       # %bb.0:
596; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
597; ALL-NEXT:    vmovaps %xmm0, (%rdi)
598; ALL-NEXT:    retq
599  %1 = fptrunc <4 x float> %a0 to <4 x half>
600  %2 = bitcast <4 x half> %1 to <4 x i16>
601  %3 = shufflevector <4 x i16> %2, <4 x i16> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
602  store <8 x i16> %3, ptr %a1
603  ret void
604}
605
606define void @store_cvt_8f32_to_8i16(<8 x float> %a0, ptr %a1) nounwind {
607; ALL-LABEL: store_cvt_8f32_to_8i16:
608; ALL:       # %bb.0:
609; ALL-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
610; ALL-NEXT:    vzeroupper
611; ALL-NEXT:    retq
612  %1 = fptrunc <8 x float> %a0 to <8 x half>
613  %2 = bitcast <8 x half> %1 to <8 x i16>
614  store <8 x i16> %2, ptr %a1
615  ret void
616}
617
618define void @store_cvt_16f32_to_16i16(<16 x float> %a0, ptr %a1) nounwind {
619; AVX1-LABEL: store_cvt_16f32_to_16i16:
620; AVX1:       # %bb.0:
621; AVX1-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
622; AVX1-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
623; AVX1-NEXT:    vzeroupper
624; AVX1-NEXT:    retq
625;
626; AVX2-LABEL: store_cvt_16f32_to_16i16:
627; AVX2:       # %bb.0:
628; AVX2-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
629; AVX2-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
630; AVX2-NEXT:    vzeroupper
631; AVX2-NEXT:    retq
632;
633; AVX512-LABEL: store_cvt_16f32_to_16i16:
634; AVX512:       # %bb.0:
635; AVX512-NEXT:    vcvtps2ph $4, %zmm0, (%rdi)
636; AVX512-NEXT:    vzeroupper
637; AVX512-NEXT:    retq
638  %1 = fptrunc <16 x float> %a0 to <16 x half>
639  %2 = bitcast <16 x half> %1 to <16 x i16>
640  store <16 x i16> %2, ptr %a1
641  ret void
642}
643
644;
645; Double to Half
646;
647
648define i16 @cvt_f64_to_i16(double %a0) nounwind {
649; ALL-LABEL: cvt_f64_to_i16:
650; ALL:       # %bb.0:
651; ALL-NEXT:    vcvtsd2ss %xmm0, %xmm0, %xmm0
652; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
653; ALL-NEXT:    vmovd %xmm0, %eax
654; ALL-NEXT:    # kill: def $ax killed $ax killed $eax
655; ALL-NEXT:    retq
656  %1 = fptrunc double %a0 to half
657  %2 = bitcast half %1 to i16
658  ret i16 %2
659}
660
661define <2 x i16> @cvt_2f64_to_2i16(<2 x double> %a0) nounwind {
662; ALL-LABEL: cvt_2f64_to_2i16:
663; ALL:       # %bb.0:
664; ALL-NEXT:    vcvtpd2ps %xmm0, %xmm0
665; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
666; ALL-NEXT:    retq
667  %1 = fptrunc <2 x double> %a0 to <2 x half>
668  %2 = bitcast <2 x half> %1 to <2 x i16>
669  ret <2 x i16> %2
670}
671
672define <4 x i16> @cvt_4f64_to_4i16(<4 x double> %a0) nounwind {
673; ALL-LABEL: cvt_4f64_to_4i16:
674; ALL:       # %bb.0:
675; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
676; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
677; ALL-NEXT:    vzeroupper
678; ALL-NEXT:    retq
679  %1 = fptrunc <4 x double> %a0 to <4 x half>
680  %2 = bitcast <4 x half> %1 to <4 x i16>
681  ret <4 x i16> %2
682}
683
684define <8 x i16> @cvt_4f64_to_8i16_undef(<4 x double> %a0) nounwind {
685; ALL-LABEL: cvt_4f64_to_8i16_undef:
686; ALL:       # %bb.0:
687; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
688; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
689; ALL-NEXT:    vzeroupper
690; ALL-NEXT:    retq
691  %1 = fptrunc <4 x double> %a0 to <4 x half>
692  %2 = bitcast <4 x half> %1 to <4 x i16>
693  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
694  ret <8 x i16> %3
695}
696
697define <8 x i16> @cvt_4f64_to_8i16_zero(<4 x double> %a0) nounwind {
698; ALL-LABEL: cvt_4f64_to_8i16_zero:
699; ALL:       # %bb.0:
700; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
701; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
702; ALL-NEXT:    vzeroupper
703; ALL-NEXT:    retq
704  %1 = fptrunc <4 x double> %a0 to <4 x half>
705  %2 = bitcast <4 x half> %1 to <4 x i16>
706  %3 = shufflevector <4 x i16> %2, <4 x i16> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
707  ret <8 x i16> %3
708}
709
710define <8 x i16> @cvt_8f64_to_8i16(<8 x double> %a0) nounwind {
711; AVX1-LABEL: cvt_8f64_to_8i16:
712; AVX1:       # %bb.0:
713; AVX1-NEXT:    vcvtpd2ps %ymm1, %xmm1
714; AVX1-NEXT:    vcvtps2ph $0, %xmm1, %xmm1
715; AVX1-NEXT:    vcvtpd2ps %ymm0, %xmm0
716; AVX1-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
717; AVX1-NEXT:    vmovlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
718; AVX1-NEXT:    vzeroupper
719; AVX1-NEXT:    retq
720;
721; AVX2-LABEL: cvt_8f64_to_8i16:
722; AVX2:       # %bb.0:
723; AVX2-NEXT:    vcvtpd2ps %ymm1, %xmm1
724; AVX2-NEXT:    vcvtps2ph $0, %xmm1, %xmm1
725; AVX2-NEXT:    vcvtpd2ps %ymm0, %xmm0
726; AVX2-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
727; AVX2-NEXT:    vmovlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
728; AVX2-NEXT:    vzeroupper
729; AVX2-NEXT:    retq
730;
731; AVX512-LABEL: cvt_8f64_to_8i16:
732; AVX512:       # %bb.0:
733; AVX512-NEXT:    vcvtpd2ps %zmm0, %ymm0
734; AVX512-NEXT:    vcvtps2ph $4, %ymm0, %xmm0
735; AVX512-NEXT:    vzeroupper
736; AVX512-NEXT:    retq
737  %1 = fptrunc <8 x double> %a0 to <8 x half>
738  %2 = bitcast <8 x half> %1 to <8 x i16>
739  ret <8 x i16> %2
740}
741
742;
743; Double to Half (Store)
744;
745
746define void @store_cvt_f64_to_i16(double %a0, ptr %a1) nounwind {
747; ALL-LABEL: store_cvt_f64_to_i16:
748; ALL:       # %bb.0:
749; ALL-NEXT:    vcvtsd2ss %xmm0, %xmm0, %xmm0
750; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
751; ALL-NEXT:    vmovd %xmm0, %eax
752; ALL-NEXT:    movw %ax, (%rdi)
753; ALL-NEXT:    retq
754  %1 = fptrunc double %a0 to half
755  %2 = bitcast half %1 to i16
756  store i16 %2, ptr %a1
757  ret void
758}
759
760define void @store_cvt_2f64_to_2i16(<2 x double> %a0, ptr %a1) nounwind {
761; ALL-LABEL: store_cvt_2f64_to_2i16:
762; ALL:       # %bb.0:
763; ALL-NEXT:    vcvtpd2ps %xmm0, %xmm0
764; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
765; ALL-NEXT:    vmovss %xmm0, (%rdi)
766; ALL-NEXT:    retq
767  %1 = fptrunc <2 x double> %a0 to <2 x half>
768  %2 = bitcast <2 x half> %1 to <2 x i16>
769  store <2 x i16> %2, ptr %a1
770  ret void
771}
772
773define void @store_cvt_4f64_to_4i16(<4 x double> %a0, ptr %a1) nounwind {
774; ALL-LABEL: store_cvt_4f64_to_4i16:
775; ALL:       # %bb.0:
776; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
777; ALL-NEXT:    vcvtps2ph $0, %xmm0, (%rdi)
778; ALL-NEXT:    vzeroupper
779; ALL-NEXT:    retq
780  %1 = fptrunc <4 x double> %a0 to <4 x half>
781  %2 = bitcast <4 x half> %1 to <4 x i16>
782  store <4 x i16> %2, ptr %a1
783  ret void
784}
785
786define void @store_cvt_4f64_to_8i16_undef(<4 x double> %a0, ptr %a1) nounwind {
787; ALL-LABEL: store_cvt_4f64_to_8i16_undef:
788; ALL:       # %bb.0:
789; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
790; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
791; ALL-NEXT:    vmovaps %xmm0, (%rdi)
792; ALL-NEXT:    vzeroupper
793; ALL-NEXT:    retq
794  %1 = fptrunc <4 x double> %a0 to <4 x half>
795  %2 = bitcast <4 x half> %1 to <4 x i16>
796  %3 = shufflevector <4 x i16> %2, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
797  store <8 x i16> %3, ptr %a1
798  ret void
799}
800
801define void @store_cvt_4f64_to_8i16_zero(<4 x double> %a0, ptr %a1) nounwind {
802; ALL-LABEL: store_cvt_4f64_to_8i16_zero:
803; ALL:       # %bb.0:
804; ALL-NEXT:    vcvtpd2ps %ymm0, %xmm0
805; ALL-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
806; ALL-NEXT:    vmovaps %xmm0, (%rdi)
807; ALL-NEXT:    vzeroupper
808; ALL-NEXT:    retq
809  %1 = fptrunc <4 x double> %a0 to <4 x half>
810  %2 = bitcast <4 x half> %1 to <4 x i16>
811  %3 = shufflevector <4 x i16> %2, <4 x i16> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
812  store <8 x i16> %3, ptr %a1
813  ret void
814}
815
816define void @store_cvt_8f64_to_8i16(<8 x double> %a0, ptr %a1) nounwind {
817; AVX1-LABEL: store_cvt_8f64_to_8i16:
818; AVX1:       # %bb.0:
819; AVX1-NEXT:    vcvtpd2ps %ymm1, %xmm1
820; AVX1-NEXT:    vcvtps2ph $0, %xmm1, %xmm1
821; AVX1-NEXT:    vcvtpd2ps %ymm0, %xmm0
822; AVX1-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
823; AVX1-NEXT:    vmovlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
824; AVX1-NEXT:    vmovaps %xmm0, (%rdi)
825; AVX1-NEXT:    vzeroupper
826; AVX1-NEXT:    retq
827;
828; AVX2-LABEL: store_cvt_8f64_to_8i16:
829; AVX2:       # %bb.0:
830; AVX2-NEXT:    vcvtpd2ps %ymm1, %xmm1
831; AVX2-NEXT:    vcvtps2ph $0, %xmm1, %xmm1
832; AVX2-NEXT:    vcvtpd2ps %ymm0, %xmm0
833; AVX2-NEXT:    vcvtps2ph $0, %xmm0, %xmm0
834; AVX2-NEXT:    vmovlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
835; AVX2-NEXT:    vmovaps %xmm0, (%rdi)
836; AVX2-NEXT:    vzeroupper
837; AVX2-NEXT:    retq
838;
839; AVX512-LABEL: store_cvt_8f64_to_8i16:
840; AVX512:       # %bb.0:
841; AVX512-NEXT:    vcvtpd2ps %zmm0, %ymm0
842; AVX512-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
843; AVX512-NEXT:    vzeroupper
844; AVX512-NEXT:    retq
845  %1 = fptrunc <8 x double> %a0 to <8 x half>
846  %2 = bitcast <8 x half> %1 to <8 x i16>
847  store <8 x i16> %2, ptr %a1
848  ret void
849}
850
851define void @store_cvt_32f32_to_32f16(<32 x float> %a0, ptr %a1) nounwind {
852; AVX1-LABEL: store_cvt_32f32_to_32f16:
853; AVX1:       # %bb.0:
854; AVX1-NEXT:    vcvtps2ph $4, %ymm3, 48(%rdi)
855; AVX1-NEXT:    vcvtps2ph $4, %ymm2, 32(%rdi)
856; AVX1-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
857; AVX1-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
858; AVX1-NEXT:    vzeroupper
859; AVX1-NEXT:    retq
860;
861; AVX2-LABEL: store_cvt_32f32_to_32f16:
862; AVX2:       # %bb.0:
863; AVX2-NEXT:    vcvtps2ph $4, %ymm3, 48(%rdi)
864; AVX2-NEXT:    vcvtps2ph $4, %ymm2, 32(%rdi)
865; AVX2-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
866; AVX2-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
867; AVX2-NEXT:    vzeroupper
868; AVX2-NEXT:    retq
869;
870; AVX512-LABEL: store_cvt_32f32_to_32f16:
871; AVX512:       # %bb.0:
872; AVX512-NEXT:    vcvtps2ph $4, %zmm1, 32(%rdi)
873; AVX512-NEXT:    vcvtps2ph $4, %zmm0, (%rdi)
874; AVX512-NEXT:    vzeroupper
875; AVX512-NEXT:    retq
876  %1 = fptrunc <32 x float> %a0 to <32 x half>
877  store <32 x half> %1, ptr %a1
878  ret void
879}
880
881define <4 x i32> @fptosi_2f16_to_4i32(<2 x half> %a) nounwind {
882; ALL-LABEL: fptosi_2f16_to_4i32:
883; ALL:       # %bb.0:
884; ALL-NEXT:    vpsrld $16, %xmm0, %xmm1
885; ALL-NEXT:    vpextrw $0, %xmm1, %eax
886; ALL-NEXT:    movzwl %ax, %eax
887; ALL-NEXT:    vmovd %eax, %xmm1
888; ALL-NEXT:    vcvtph2ps %xmm1, %xmm1
889; ALL-NEXT:    vcvttss2si %xmm1, %eax
890; ALL-NEXT:    vpextrw $0, %xmm0, %ecx
891; ALL-NEXT:    movzwl %cx, %ecx
892; ALL-NEXT:    vmovd %ecx, %xmm0
893; ALL-NEXT:    vcvtph2ps %xmm0, %xmm0
894; ALL-NEXT:    vcvttss2si %xmm0, %ecx
895; ALL-NEXT:    vmovd %ecx, %xmm0
896; ALL-NEXT:    vmovd %eax, %xmm1
897; ALL-NEXT:    vpunpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
898; ALL-NEXT:    vmovq {{.*#+}} xmm0 = xmm0[0],zero
899; ALL-NEXT:    retq
900  %cvt = fptosi <2 x half> %a to <2 x i32>
901  %ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
902  ret <4 x i32> %ext
903}
904