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(i16* %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, i16* %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(<4 x i16>* %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>, <4 x i16>* %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(<8 x i16>* %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>, <8 x i16>* %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(<8 x i16>* %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>, <8 x i16>* %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(<16 x i16>* %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>, <16 x i16>* %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(<4 x i16>* %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>, <4 x i16>* %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(<8 x i16>* %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>, <8 x i16>* %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(i16* %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, i16* %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(<2 x i16>* %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>, <2 x i16>* %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(<4 x i16>* %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>, <4 x i16>* %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(<8 x i16>* %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>, <8 x i16>* %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(<8 x i16>* %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>, <8 x i16>* %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, i16* %a1) nounwind {
557; ALL-LABEL: store_cvt_f32_to_i16:
558; ALL:       # %bb.0:
559; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
560; ALL-NEXT:    vpextrw $0, %xmm0, (%rdi)
561; ALL-NEXT:    retq
562  %1 = fptrunc float %a0 to half
563  %2 = bitcast half %1 to i16
564  store i16 %2, i16* %a1
565  ret void
566}
567
568define void @store_cvt_4f32_to_4i16(<4 x float> %a0, <4 x i16>* %a1) nounwind {
569; ALL-LABEL: store_cvt_4f32_to_4i16:
570; ALL:       # %bb.0:
571; ALL-NEXT:    vcvtps2ph $4, %xmm0, (%rdi)
572; ALL-NEXT:    retq
573  %1 = fptrunc <4 x float> %a0 to <4 x half>
574  %2 = bitcast <4 x half> %1 to <4 x i16>
575  store <4 x i16> %2, <4 x i16>* %a1
576  ret void
577}
578
579define void @store_cvt_4f32_to_8i16_undef(<4 x float> %a0, <8 x i16>* %a1) nounwind {
580; ALL-LABEL: store_cvt_4f32_to_8i16_undef:
581; ALL:       # %bb.0:
582; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
583; ALL-NEXT:    vmovaps %xmm0, (%rdi)
584; ALL-NEXT:    retq
585  %1 = fptrunc <4 x float> %a0 to <4 x half>
586  %2 = bitcast <4 x half> %1 to <4 x i16>
587  %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>
588  store <8 x i16> %3, <8 x i16>* %a1
589  ret void
590}
591
592define void @store_cvt_4f32_to_8i16_zero(<4 x float> %a0, <8 x i16>* %a1) nounwind {
593; ALL-LABEL: store_cvt_4f32_to_8i16_zero:
594; ALL:       # %bb.0:
595; ALL-NEXT:    vcvtps2ph $4, %xmm0, %xmm0
596; ALL-NEXT:    vmovaps %xmm0, (%rdi)
597; ALL-NEXT:    retq
598  %1 = fptrunc <4 x float> %a0 to <4 x half>
599  %2 = bitcast <4 x half> %1 to <4 x i16>
600  %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>
601  store <8 x i16> %3, <8 x i16>* %a1
602  ret void
603}
604
605define void @store_cvt_8f32_to_8i16(<8 x float> %a0, <8 x i16>* %a1) nounwind {
606; ALL-LABEL: store_cvt_8f32_to_8i16:
607; ALL:       # %bb.0:
608; ALL-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
609; ALL-NEXT:    vzeroupper
610; ALL-NEXT:    retq
611  %1 = fptrunc <8 x float> %a0 to <8 x half>
612  %2 = bitcast <8 x half> %1 to <8 x i16>
613  store <8 x i16> %2, <8 x i16>* %a1
614  ret void
615}
616
617define void @store_cvt_16f32_to_16i16(<16 x float> %a0, <16 x i16>* %a1) nounwind {
618; AVX1-LABEL: store_cvt_16f32_to_16i16:
619; AVX1:       # %bb.0:
620; AVX1-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
621; AVX1-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
622; AVX1-NEXT:    vzeroupper
623; AVX1-NEXT:    retq
624;
625; AVX2-LABEL: store_cvt_16f32_to_16i16:
626; AVX2:       # %bb.0:
627; AVX2-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
628; AVX2-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
629; AVX2-NEXT:    vzeroupper
630; AVX2-NEXT:    retq
631;
632; AVX512-LABEL: store_cvt_16f32_to_16i16:
633; AVX512:       # %bb.0:
634; AVX512-NEXT:    vcvtps2ph $4, %zmm0, (%rdi)
635; AVX512-NEXT:    vzeroupper
636; AVX512-NEXT:    retq
637  %1 = fptrunc <16 x float> %a0 to <16 x half>
638  %2 = bitcast <16 x half> %1 to <16 x i16>
639  store <16 x i16> %2, <16 x i16>* %a1
640  ret void
641}
642
643;
644; Double to Half
645;
646
647define i16 @cvt_f64_to_i16(double %a0) nounwind {
648; ALL-LABEL: cvt_f64_to_i16:
649; ALL:       # %bb.0:
650; ALL-NEXT:    jmp __truncdfhf2@PLT # TAILCALL
651  %1 = fptrunc double %a0 to half
652  %2 = bitcast half %1 to i16
653  ret i16 %2
654}
655
656define <2 x i16> @cvt_2f64_to_2i16(<2 x double> %a0) nounwind {
657; ALL-LABEL: cvt_2f64_to_2i16:
658; ALL:       # %bb.0:
659; ALL-NEXT:    subq $40, %rsp
660; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
661; ALL-NEXT:    callq __truncdfhf2@PLT
662; ALL-NEXT:    movw %ax, (%rsp)
663; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
664; ALL-NEXT:    # xmm0 = mem[1,0]
665; ALL-NEXT:    callq __truncdfhf2@PLT
666; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
667; ALL-NEXT:    vmovaps (%rsp), %xmm0
668; ALL-NEXT:    addq $40, %rsp
669; ALL-NEXT:    retq
670  %1 = fptrunc <2 x double> %a0 to <2 x half>
671  %2 = bitcast <2 x half> %1 to <2 x i16>
672  ret <2 x i16> %2
673}
674
675define <4 x i16> @cvt_4f64_to_4i16(<4 x double> %a0) nounwind {
676; ALL-LABEL: cvt_4f64_to_4i16:
677; ALL:       # %bb.0:
678; ALL-NEXT:    subq $72, %rsp
679; ALL-NEXT:    vmovups %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
680; ALL-NEXT:    vextractf128 $1, %ymm0, %xmm0
681; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
682; ALL-NEXT:    vzeroupper
683; ALL-NEXT:    callq __truncdfhf2@PLT
684; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
685; ALL-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
686; ALL-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
687; ALL-NEXT:    vzeroupper
688; ALL-NEXT:    callq __truncdfhf2@PLT
689; ALL-NEXT:    movw %ax, (%rsp)
690; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
691; ALL-NEXT:    # xmm0 = mem[1,0]
692; ALL-NEXT:    callq __truncdfhf2@PLT
693; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
694; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
695; ALL-NEXT:    # xmm0 = mem[1,0]
696; ALL-NEXT:    callq __truncdfhf2@PLT
697; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
698; ALL-NEXT:    vmovaps (%rsp), %xmm0
699; ALL-NEXT:    addq $72, %rsp
700; ALL-NEXT:    retq
701  %1 = fptrunc <4 x double> %a0 to <4 x half>
702  %2 = bitcast <4 x half> %1 to <4 x i16>
703  ret <4 x i16> %2
704}
705
706define <8 x i16> @cvt_4f64_to_8i16_undef(<4 x double> %a0) nounwind {
707; ALL-LABEL: cvt_4f64_to_8i16_undef:
708; ALL:       # %bb.0:
709; ALL-NEXT:    subq $72, %rsp
710; ALL-NEXT:    vmovups %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
711; ALL-NEXT:    vextractf128 $1, %ymm0, %xmm0
712; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
713; ALL-NEXT:    vzeroupper
714; ALL-NEXT:    callq __truncdfhf2@PLT
715; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
716; ALL-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
717; ALL-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
718; ALL-NEXT:    vzeroupper
719; ALL-NEXT:    callq __truncdfhf2@PLT
720; ALL-NEXT:    movw %ax, (%rsp)
721; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
722; ALL-NEXT:    # xmm0 = mem[1,0]
723; ALL-NEXT:    callq __truncdfhf2@PLT
724; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
725; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
726; ALL-NEXT:    # xmm0 = mem[1,0]
727; ALL-NEXT:    callq __truncdfhf2@PLT
728; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
729; ALL-NEXT:    vmovaps (%rsp), %xmm0
730; ALL-NEXT:    addq $72, %rsp
731; ALL-NEXT:    retq
732  %1 = fptrunc <4 x double> %a0 to <4 x half>
733  %2 = bitcast <4 x half> %1 to <4 x i16>
734  %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>
735  ret <8 x i16> %3
736}
737
738define <8 x i16> @cvt_4f64_to_8i16_zero(<4 x double> %a0) nounwind {
739; ALL-LABEL: cvt_4f64_to_8i16_zero:
740; ALL:       # %bb.0:
741; ALL-NEXT:    subq $72, %rsp
742; ALL-NEXT:    vmovups %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
743; ALL-NEXT:    vextractf128 $1, %ymm0, %xmm0
744; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
745; ALL-NEXT:    vzeroupper
746; ALL-NEXT:    callq __truncdfhf2@PLT
747; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
748; ALL-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
749; ALL-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
750; ALL-NEXT:    vzeroupper
751; ALL-NEXT:    callq __truncdfhf2@PLT
752; ALL-NEXT:    movw %ax, (%rsp)
753; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
754; ALL-NEXT:    # xmm0 = mem[1,0]
755; ALL-NEXT:    callq __truncdfhf2@PLT
756; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
757; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
758; ALL-NEXT:    # xmm0 = mem[1,0]
759; ALL-NEXT:    callq __truncdfhf2@PLT
760; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
761; ALL-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
762; ALL-NEXT:    addq $72, %rsp
763; ALL-NEXT:    retq
764  %1 = fptrunc <4 x double> %a0 to <4 x half>
765  %2 = bitcast <4 x half> %1 to <4 x i16>
766  %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>
767  ret <8 x i16> %3
768}
769
770define <8 x i16> @cvt_8f64_to_8i16(<8 x double> %a0) nounwind {
771; AVX1-LABEL: cvt_8f64_to_8i16:
772; AVX1:       # %bb.0:
773; AVX1-NEXT:    pushq %r15
774; AVX1-NEXT:    pushq %r14
775; AVX1-NEXT:    pushq %rbx
776; AVX1-NEXT:    subq $64, %rsp
777; AVX1-NEXT:    vmovups %ymm1, (%rsp) # 32-byte Spill
778; AVX1-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
779; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
780; AVX1-NEXT:    vzeroupper
781; AVX1-NEXT:    callq __truncdfhf2@PLT
782; AVX1-NEXT:    movl %eax, %ebx
783; AVX1-NEXT:    shll $16, %ebx
784; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
785; AVX1-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
786; AVX1-NEXT:    vzeroupper
787; AVX1-NEXT:    callq __truncdfhf2@PLT
788; AVX1-NEXT:    movzwl %ax, %r15d
789; AVX1-NEXT:    orl %ebx, %r15d
790; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
791; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
792; AVX1-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
793; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
794; AVX1-NEXT:    vzeroupper
795; AVX1-NEXT:    callq __truncdfhf2@PLT
796; AVX1-NEXT:    movl %eax, %ebx
797; AVX1-NEXT:    shll $16, %ebx
798; AVX1-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
799; AVX1-NEXT:    callq __truncdfhf2@PLT
800; AVX1-NEXT:    movzwl %ax, %r14d
801; AVX1-NEXT:    orl %ebx, %r14d
802; AVX1-NEXT:    shlq $32, %r14
803; AVX1-NEXT:    orq %r15, %r14
804; AVX1-NEXT:    vpermilpd $1, (%rsp), %xmm0 # 16-byte Folded Reload
805; AVX1-NEXT:    # xmm0 = mem[1,0]
806; AVX1-NEXT:    callq __truncdfhf2@PLT
807; AVX1-NEXT:    movl %eax, %ebx
808; AVX1-NEXT:    shll $16, %ebx
809; AVX1-NEXT:    vmovups (%rsp), %ymm0 # 32-byte Reload
810; AVX1-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
811; AVX1-NEXT:    vzeroupper
812; AVX1-NEXT:    callq __truncdfhf2@PLT
813; AVX1-NEXT:    movzwl %ax, %r15d
814; AVX1-NEXT:    orl %ebx, %r15d
815; AVX1-NEXT:    vmovups (%rsp), %ymm0 # 32-byte Reload
816; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
817; AVX1-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
818; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
819; AVX1-NEXT:    vzeroupper
820; AVX1-NEXT:    callq __truncdfhf2@PLT
821; AVX1-NEXT:    movl %eax, %ebx
822; AVX1-NEXT:    shll $16, %ebx
823; AVX1-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
824; AVX1-NEXT:    callq __truncdfhf2@PLT
825; AVX1-NEXT:    movzwl %ax, %eax
826; AVX1-NEXT:    orl %ebx, %eax
827; AVX1-NEXT:    shlq $32, %rax
828; AVX1-NEXT:    orq %r15, %rax
829; AVX1-NEXT:    vmovq %rax, %xmm0
830; AVX1-NEXT:    vmovq %r14, %xmm1
831; AVX1-NEXT:    vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
832; AVX1-NEXT:    addq $64, %rsp
833; AVX1-NEXT:    popq %rbx
834; AVX1-NEXT:    popq %r14
835; AVX1-NEXT:    popq %r15
836; AVX1-NEXT:    retq
837;
838; AVX2-LABEL: cvt_8f64_to_8i16:
839; AVX2:       # %bb.0:
840; AVX2-NEXT:    pushq %r15
841; AVX2-NEXT:    pushq %r14
842; AVX2-NEXT:    pushq %rbx
843; AVX2-NEXT:    subq $64, %rsp
844; AVX2-NEXT:    vmovups %ymm1, (%rsp) # 32-byte Spill
845; AVX2-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
846; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
847; AVX2-NEXT:    vzeroupper
848; AVX2-NEXT:    callq __truncdfhf2@PLT
849; AVX2-NEXT:    movl %eax, %ebx
850; AVX2-NEXT:    shll $16, %ebx
851; AVX2-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
852; AVX2-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
853; AVX2-NEXT:    vzeroupper
854; AVX2-NEXT:    callq __truncdfhf2@PLT
855; AVX2-NEXT:    movzwl %ax, %r15d
856; AVX2-NEXT:    orl %ebx, %r15d
857; AVX2-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
858; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
859; AVX2-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
860; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
861; AVX2-NEXT:    vzeroupper
862; AVX2-NEXT:    callq __truncdfhf2@PLT
863; AVX2-NEXT:    movl %eax, %ebx
864; AVX2-NEXT:    shll $16, %ebx
865; AVX2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
866; AVX2-NEXT:    callq __truncdfhf2@PLT
867; AVX2-NEXT:    movzwl %ax, %r14d
868; AVX2-NEXT:    orl %ebx, %r14d
869; AVX2-NEXT:    shlq $32, %r14
870; AVX2-NEXT:    orq %r15, %r14
871; AVX2-NEXT:    vpermilpd $1, (%rsp), %xmm0 # 16-byte Folded Reload
872; AVX2-NEXT:    # xmm0 = mem[1,0]
873; AVX2-NEXT:    callq __truncdfhf2@PLT
874; AVX2-NEXT:    movl %eax, %ebx
875; AVX2-NEXT:    shll $16, %ebx
876; AVX2-NEXT:    vmovups (%rsp), %ymm0 # 32-byte Reload
877; AVX2-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
878; AVX2-NEXT:    vzeroupper
879; AVX2-NEXT:    callq __truncdfhf2@PLT
880; AVX2-NEXT:    movzwl %ax, %r15d
881; AVX2-NEXT:    orl %ebx, %r15d
882; AVX2-NEXT:    vmovupd (%rsp), %ymm0 # 32-byte Reload
883; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
884; AVX2-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
885; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
886; AVX2-NEXT:    vzeroupper
887; AVX2-NEXT:    callq __truncdfhf2@PLT
888; AVX2-NEXT:    movl %eax, %ebx
889; AVX2-NEXT:    shll $16, %ebx
890; AVX2-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
891; AVX2-NEXT:    callq __truncdfhf2@PLT
892; AVX2-NEXT:    movzwl %ax, %eax
893; AVX2-NEXT:    orl %ebx, %eax
894; AVX2-NEXT:    shlq $32, %rax
895; AVX2-NEXT:    orq %r15, %rax
896; AVX2-NEXT:    vmovq %rax, %xmm0
897; AVX2-NEXT:    vmovq %r14, %xmm1
898; AVX2-NEXT:    vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
899; AVX2-NEXT:    addq $64, %rsp
900; AVX2-NEXT:    popq %rbx
901; AVX2-NEXT:    popq %r14
902; AVX2-NEXT:    popq %r15
903; AVX2-NEXT:    retq
904;
905; AVX512-LABEL: cvt_8f64_to_8i16:
906; AVX512:       # %bb.0:
907; AVX512-NEXT:    pushq %r15
908; AVX512-NEXT:    pushq %r14
909; AVX512-NEXT:    pushq %rbx
910; AVX512-NEXT:    subq $80, %rsp
911; AVX512-NEXT:    vmovupd %zmm0, (%rsp) # 64-byte Spill
912; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
913; AVX512-NEXT:    vzeroupper
914; AVX512-NEXT:    callq __truncdfhf2@PLT
915; AVX512-NEXT:    movl %eax, %ebx
916; AVX512-NEXT:    shll $16, %ebx
917; AVX512-NEXT:    vmovups (%rsp), %zmm0 # 64-byte Reload
918; AVX512-NEXT:    # kill: def $xmm0 killed $xmm0 killed $zmm0
919; AVX512-NEXT:    vzeroupper
920; AVX512-NEXT:    callq __truncdfhf2@PLT
921; AVX512-NEXT:    movzwl %ax, %r15d
922; AVX512-NEXT:    orl %ebx, %r15d
923; AVX512-NEXT:    vmovupd (%rsp), %zmm0 # 64-byte Reload
924; AVX512-NEXT:    vextractf128 $1, %ymm0, %xmm0
925; AVX512-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
926; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
927; AVX512-NEXT:    vzeroupper
928; AVX512-NEXT:    callq __truncdfhf2@PLT
929; AVX512-NEXT:    movl %eax, %ebx
930; AVX512-NEXT:    shll $16, %ebx
931; AVX512-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
932; AVX512-NEXT:    callq __truncdfhf2@PLT
933; AVX512-NEXT:    movzwl %ax, %r14d
934; AVX512-NEXT:    orl %ebx, %r14d
935; AVX512-NEXT:    shlq $32, %r14
936; AVX512-NEXT:    orq %r15, %r14
937; AVX512-NEXT:    vmovupd (%rsp), %zmm0 # 64-byte Reload
938; AVX512-NEXT:    vextractf64x4 $1, %zmm0, %ymm0
939; AVX512-NEXT:    vmovupd %ymm0, (%rsp) # 32-byte Spill
940; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
941; AVX512-NEXT:    vzeroupper
942; AVX512-NEXT:    callq __truncdfhf2@PLT
943; AVX512-NEXT:    movl %eax, %ebx
944; AVX512-NEXT:    shll $16, %ebx
945; AVX512-NEXT:    vmovups (%rsp), %ymm0 # 32-byte Reload
946; AVX512-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
947; AVX512-NEXT:    vzeroupper
948; AVX512-NEXT:    callq __truncdfhf2@PLT
949; AVX512-NEXT:    movzwl %ax, %r15d
950; AVX512-NEXT:    orl %ebx, %r15d
951; AVX512-NEXT:    vmovupd (%rsp), %ymm0 # 32-byte Reload
952; AVX512-NEXT:    vextractf128 $1, %ymm0, %xmm0
953; AVX512-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
954; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
955; AVX512-NEXT:    vzeroupper
956; AVX512-NEXT:    callq __truncdfhf2@PLT
957; AVX512-NEXT:    movl %eax, %ebx
958; AVX512-NEXT:    shll $16, %ebx
959; AVX512-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
960; AVX512-NEXT:    callq __truncdfhf2@PLT
961; AVX512-NEXT:    movzwl %ax, %eax
962; AVX512-NEXT:    orl %ebx, %eax
963; AVX512-NEXT:    shlq $32, %rax
964; AVX512-NEXT:    orq %r15, %rax
965; AVX512-NEXT:    vmovq %rax, %xmm0
966; AVX512-NEXT:    vmovq %r14, %xmm1
967; AVX512-NEXT:    vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
968; AVX512-NEXT:    addq $80, %rsp
969; AVX512-NEXT:    popq %rbx
970; AVX512-NEXT:    popq %r14
971; AVX512-NEXT:    popq %r15
972; AVX512-NEXT:    retq
973  %1 = fptrunc <8 x double> %a0 to <8 x half>
974  %2 = bitcast <8 x half> %1 to <8 x i16>
975  ret <8 x i16> %2
976}
977
978;
979; Double to Half (Store)
980;
981
982define void @store_cvt_f64_to_i16(double %a0, i16* %a1) nounwind {
983; ALL-LABEL: store_cvt_f64_to_i16:
984; ALL:       # %bb.0:
985; ALL-NEXT:    pushq %rbx
986; ALL-NEXT:    movq %rdi, %rbx
987; ALL-NEXT:    callq __truncdfhf2@PLT
988; ALL-NEXT:    movw %ax, (%rbx)
989; ALL-NEXT:    popq %rbx
990; ALL-NEXT:    retq
991  %1 = fptrunc double %a0 to half
992  %2 = bitcast half %1 to i16
993  store i16 %2, i16* %a1
994  ret void
995}
996
997define void @store_cvt_2f64_to_2i16(<2 x double> %a0, <2 x i16>* %a1) nounwind {
998; ALL-LABEL: store_cvt_2f64_to_2i16:
999; ALL:       # %bb.0:
1000; ALL-NEXT:    pushq %rbp
1001; ALL-NEXT:    pushq %rbx
1002; ALL-NEXT:    subq $24, %rsp
1003; ALL-NEXT:    movq %rdi, %rbx
1004; ALL-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
1005; ALL-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1006; ALL-NEXT:    callq __truncdfhf2@PLT
1007; ALL-NEXT:    movl %eax, %ebp
1008; ALL-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
1009; ALL-NEXT:    callq __truncdfhf2@PLT
1010; ALL-NEXT:    movw %ax, (%rbx)
1011; ALL-NEXT:    movw %bp, 2(%rbx)
1012; ALL-NEXT:    addq $24, %rsp
1013; ALL-NEXT:    popq %rbx
1014; ALL-NEXT:    popq %rbp
1015; ALL-NEXT:    retq
1016  %1 = fptrunc <2 x double> %a0 to <2 x half>
1017  %2 = bitcast <2 x half> %1 to <2 x i16>
1018  store <2 x i16> %2, <2 x i16>* %a1
1019  ret void
1020}
1021
1022define void @store_cvt_4f64_to_4i16(<4 x double> %a0, <4 x i16>* %a1) nounwind {
1023; AVX1-LABEL: store_cvt_4f64_to_4i16:
1024; AVX1:       # %bb.0:
1025; AVX1-NEXT:    pushq %rbp
1026; AVX1-NEXT:    pushq %r15
1027; AVX1-NEXT:    pushq %r14
1028; AVX1-NEXT:    pushq %rbx
1029; AVX1-NEXT:    subq $56, %rsp
1030; AVX1-NEXT:    movq %rdi, %rbx
1031; AVX1-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1032; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1033; AVX1-NEXT:    vzeroupper
1034; AVX1-NEXT:    callq __truncdfhf2@PLT
1035; AVX1-NEXT:    movl %eax, %r14d
1036; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1037; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
1038; AVX1-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
1039; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1040; AVX1-NEXT:    vzeroupper
1041; AVX1-NEXT:    callq __truncdfhf2@PLT
1042; AVX1-NEXT:    movl %eax, %r15d
1043; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1044; AVX1-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1045; AVX1-NEXT:    vzeroupper
1046; AVX1-NEXT:    callq __truncdfhf2@PLT
1047; AVX1-NEXT:    movl %eax, %ebp
1048; AVX1-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
1049; AVX1-NEXT:    callq __truncdfhf2@PLT
1050; AVX1-NEXT:    movw %ax, 4(%rbx)
1051; AVX1-NEXT:    movw %bp, (%rbx)
1052; AVX1-NEXT:    movw %r15w, 6(%rbx)
1053; AVX1-NEXT:    movw %r14w, 2(%rbx)
1054; AVX1-NEXT:    addq $56, %rsp
1055; AVX1-NEXT:    popq %rbx
1056; AVX1-NEXT:    popq %r14
1057; AVX1-NEXT:    popq %r15
1058; AVX1-NEXT:    popq %rbp
1059; AVX1-NEXT:    retq
1060;
1061; AVX2-LABEL: store_cvt_4f64_to_4i16:
1062; AVX2:       # %bb.0:
1063; AVX2-NEXT:    pushq %rbp
1064; AVX2-NEXT:    pushq %r15
1065; AVX2-NEXT:    pushq %r14
1066; AVX2-NEXT:    pushq %rbx
1067; AVX2-NEXT:    subq $56, %rsp
1068; AVX2-NEXT:    movq %rdi, %rbx
1069; AVX2-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1070; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1071; AVX2-NEXT:    vzeroupper
1072; AVX2-NEXT:    callq __truncdfhf2@PLT
1073; AVX2-NEXT:    movl %eax, %r14d
1074; AVX2-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1075; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
1076; AVX2-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
1077; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1078; AVX2-NEXT:    vzeroupper
1079; AVX2-NEXT:    callq __truncdfhf2@PLT
1080; AVX2-NEXT:    movl %eax, %r15d
1081; AVX2-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1082; AVX2-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1083; AVX2-NEXT:    vzeroupper
1084; AVX2-NEXT:    callq __truncdfhf2@PLT
1085; AVX2-NEXT:    movl %eax, %ebp
1086; AVX2-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
1087; AVX2-NEXT:    callq __truncdfhf2@PLT
1088; AVX2-NEXT:    movw %ax, 4(%rbx)
1089; AVX2-NEXT:    movw %bp, (%rbx)
1090; AVX2-NEXT:    movw %r15w, 6(%rbx)
1091; AVX2-NEXT:    movw %r14w, 2(%rbx)
1092; AVX2-NEXT:    addq $56, %rsp
1093; AVX2-NEXT:    popq %rbx
1094; AVX2-NEXT:    popq %r14
1095; AVX2-NEXT:    popq %r15
1096; AVX2-NEXT:    popq %rbp
1097; AVX2-NEXT:    retq
1098;
1099; AVX512-LABEL: store_cvt_4f64_to_4i16:
1100; AVX512:       # %bb.0:
1101; AVX512-NEXT:    pushq %rbp
1102; AVX512-NEXT:    pushq %r15
1103; AVX512-NEXT:    pushq %r14
1104; AVX512-NEXT:    pushq %rbx
1105; AVX512-NEXT:    subq $56, %rsp
1106; AVX512-NEXT:    movq %rdi, %rbx
1107; AVX512-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1108; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1109; AVX512-NEXT:    vzeroupper
1110; AVX512-NEXT:    callq __truncdfhf2@PLT
1111; AVX512-NEXT:    movl %eax, %r14d
1112; AVX512-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1113; AVX512-NEXT:    vextractf128 $1, %ymm0, %xmm0
1114; AVX512-NEXT:    vmovapd %xmm0, (%rsp) # 16-byte Spill
1115; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1116; AVX512-NEXT:    vzeroupper
1117; AVX512-NEXT:    callq __truncdfhf2@PLT
1118; AVX512-NEXT:    movl %eax, %r15d
1119; AVX512-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1120; AVX512-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1121; AVX512-NEXT:    vzeroupper
1122; AVX512-NEXT:    callq __truncdfhf2@PLT
1123; AVX512-NEXT:    movl %eax, %ebp
1124; AVX512-NEXT:    vmovaps (%rsp), %xmm0 # 16-byte Reload
1125; AVX512-NEXT:    callq __truncdfhf2@PLT
1126; AVX512-NEXT:    movw %ax, 4(%rbx)
1127; AVX512-NEXT:    movw %bp, (%rbx)
1128; AVX512-NEXT:    movw %r15w, 6(%rbx)
1129; AVX512-NEXT:    movw %r14w, 2(%rbx)
1130; AVX512-NEXT:    addq $56, %rsp
1131; AVX512-NEXT:    popq %rbx
1132; AVX512-NEXT:    popq %r14
1133; AVX512-NEXT:    popq %r15
1134; AVX512-NEXT:    popq %rbp
1135; AVX512-NEXT:    retq
1136  %1 = fptrunc <4 x double> %a0 to <4 x half>
1137  %2 = bitcast <4 x half> %1 to <4 x i16>
1138  store <4 x i16> %2, <4 x i16>* %a1
1139  ret void
1140}
1141
1142define void @store_cvt_4f64_to_8i16_undef(<4 x double> %a0, <8 x i16>* %a1) nounwind {
1143; ALL-LABEL: store_cvt_4f64_to_8i16_undef:
1144; ALL:       # %bb.0:
1145; ALL-NEXT:    pushq %rbx
1146; ALL-NEXT:    subq $64, %rsp
1147; ALL-NEXT:    movq %rdi, %rbx
1148; ALL-NEXT:    vmovups %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1149; ALL-NEXT:    vextractf128 $1, %ymm0, %xmm0
1150; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1151; ALL-NEXT:    vzeroupper
1152; ALL-NEXT:    callq __truncdfhf2@PLT
1153; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1154; ALL-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1155; ALL-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1156; ALL-NEXT:    vzeroupper
1157; ALL-NEXT:    callq __truncdfhf2@PLT
1158; ALL-NEXT:    movw %ax, (%rsp)
1159; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1160; ALL-NEXT:    # xmm0 = mem[1,0]
1161; ALL-NEXT:    callq __truncdfhf2@PLT
1162; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1163; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1164; ALL-NEXT:    # xmm0 = mem[1,0]
1165; ALL-NEXT:    callq __truncdfhf2@PLT
1166; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1167; ALL-NEXT:    vmovaps (%rsp), %xmm0
1168; ALL-NEXT:    vmovaps %xmm0, (%rbx)
1169; ALL-NEXT:    addq $64, %rsp
1170; ALL-NEXT:    popq %rbx
1171; ALL-NEXT:    retq
1172  %1 = fptrunc <4 x double> %a0 to <4 x half>
1173  %2 = bitcast <4 x half> %1 to <4 x i16>
1174  %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>
1175  store <8 x i16> %3, <8 x i16>* %a1
1176  ret void
1177}
1178
1179define void @store_cvt_4f64_to_8i16_zero(<4 x double> %a0, <8 x i16>* %a1) nounwind {
1180; ALL-LABEL: store_cvt_4f64_to_8i16_zero:
1181; ALL:       # %bb.0:
1182; ALL-NEXT:    pushq %rbx
1183; ALL-NEXT:    subq $64, %rsp
1184; ALL-NEXT:    movq %rdi, %rbx
1185; ALL-NEXT:    vmovups %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1186; ALL-NEXT:    vextractf128 $1, %ymm0, %xmm0
1187; ALL-NEXT:    vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1188; ALL-NEXT:    vzeroupper
1189; ALL-NEXT:    callq __truncdfhf2@PLT
1190; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1191; ALL-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1192; ALL-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1193; ALL-NEXT:    vzeroupper
1194; ALL-NEXT:    callq __truncdfhf2@PLT
1195; ALL-NEXT:    movw %ax, (%rsp)
1196; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1197; ALL-NEXT:    # xmm0 = mem[1,0]
1198; ALL-NEXT:    callq __truncdfhf2@PLT
1199; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1200; ALL-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1201; ALL-NEXT:    # xmm0 = mem[1,0]
1202; ALL-NEXT:    callq __truncdfhf2@PLT
1203; ALL-NEXT:    movw %ax, {{[0-9]+}}(%rsp)
1204; ALL-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
1205; ALL-NEXT:    vmovaps %xmm0, (%rbx)
1206; ALL-NEXT:    addq $64, %rsp
1207; ALL-NEXT:    popq %rbx
1208; ALL-NEXT:    retq
1209  %1 = fptrunc <4 x double> %a0 to <4 x half>
1210  %2 = bitcast <4 x half> %1 to <4 x i16>
1211  %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>
1212  store <8 x i16> %3, <8 x i16>* %a1
1213  ret void
1214}
1215
1216define void @store_cvt_8f64_to_8i16(<8 x double> %a0, <8 x i16>* %a1) nounwind {
1217; AVX1-LABEL: store_cvt_8f64_to_8i16:
1218; AVX1:       # %bb.0:
1219; AVX1-NEXT:    pushq %rbp
1220; AVX1-NEXT:    pushq %r15
1221; AVX1-NEXT:    pushq %r14
1222; AVX1-NEXT:    pushq %r13
1223; AVX1-NEXT:    pushq %r12
1224; AVX1-NEXT:    pushq %rbx
1225; AVX1-NEXT:    subq $120, %rsp
1226; AVX1-NEXT:    movq %rdi, %rbx
1227; AVX1-NEXT:    vmovups %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1228; AVX1-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1229; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1230; AVX1-NEXT:    vzeroupper
1231; AVX1-NEXT:    callq __truncdfhf2@PLT
1232; AVX1-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1233; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1234; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
1235; AVX1-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1236; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1237; AVX1-NEXT:    vzeroupper
1238; AVX1-NEXT:    callq __truncdfhf2@PLT
1239; AVX1-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1240; AVX1-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1241; AVX1-NEXT:    # xmm0 = mem[1,0]
1242; AVX1-NEXT:    callq __truncdfhf2@PLT
1243; AVX1-NEXT:    movl %eax, %r12d
1244; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1245; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm0
1246; AVX1-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1247; AVX1-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1248; AVX1-NEXT:    vzeroupper
1249; AVX1-NEXT:    callq __truncdfhf2@PLT
1250; AVX1-NEXT:    movl %eax, %r13d
1251; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1252; AVX1-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1253; AVX1-NEXT:    vzeroupper
1254; AVX1-NEXT:    callq __truncdfhf2@PLT
1255; AVX1-NEXT:    movl %eax, %ebp
1256; AVX1-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1257; AVX1-NEXT:    callq __truncdfhf2@PLT
1258; AVX1-NEXT:    movl %eax, %r14d
1259; AVX1-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1260; AVX1-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1261; AVX1-NEXT:    vzeroupper
1262; AVX1-NEXT:    callq __truncdfhf2@PLT
1263; AVX1-NEXT:    movl %eax, %r15d
1264; AVX1-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1265; AVX1-NEXT:    callq __truncdfhf2@PLT
1266; AVX1-NEXT:    movw %ax, 12(%rbx)
1267; AVX1-NEXT:    movw %r15w, 8(%rbx)
1268; AVX1-NEXT:    movw %r14w, 4(%rbx)
1269; AVX1-NEXT:    movw %bp, (%rbx)
1270; AVX1-NEXT:    movw %r13w, 14(%rbx)
1271; AVX1-NEXT:    movw %r12w, 10(%rbx)
1272; AVX1-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1273; AVX1-NEXT:    movw %ax, 6(%rbx)
1274; AVX1-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1275; AVX1-NEXT:    movw %ax, 2(%rbx)
1276; AVX1-NEXT:    addq $120, %rsp
1277; AVX1-NEXT:    popq %rbx
1278; AVX1-NEXT:    popq %r12
1279; AVX1-NEXT:    popq %r13
1280; AVX1-NEXT:    popq %r14
1281; AVX1-NEXT:    popq %r15
1282; AVX1-NEXT:    popq %rbp
1283; AVX1-NEXT:    retq
1284;
1285; AVX2-LABEL: store_cvt_8f64_to_8i16:
1286; AVX2:       # %bb.0:
1287; AVX2-NEXT:    pushq %rbp
1288; AVX2-NEXT:    pushq %r15
1289; AVX2-NEXT:    pushq %r14
1290; AVX2-NEXT:    pushq %r13
1291; AVX2-NEXT:    pushq %r12
1292; AVX2-NEXT:    pushq %rbx
1293; AVX2-NEXT:    subq $120, %rsp
1294; AVX2-NEXT:    movq %rdi, %rbx
1295; AVX2-NEXT:    vmovups %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1296; AVX2-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1297; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1298; AVX2-NEXT:    vzeroupper
1299; AVX2-NEXT:    callq __truncdfhf2@PLT
1300; AVX2-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1301; AVX2-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1302; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
1303; AVX2-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1304; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1305; AVX2-NEXT:    vzeroupper
1306; AVX2-NEXT:    callq __truncdfhf2@PLT
1307; AVX2-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1308; AVX2-NEXT:    vpermilpd $1, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload
1309; AVX2-NEXT:    # xmm0 = mem[1,0]
1310; AVX2-NEXT:    callq __truncdfhf2@PLT
1311; AVX2-NEXT:    movl %eax, %r12d
1312; AVX2-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1313; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm0
1314; AVX2-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1315; AVX2-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1316; AVX2-NEXT:    vzeroupper
1317; AVX2-NEXT:    callq __truncdfhf2@PLT
1318; AVX2-NEXT:    movl %eax, %r13d
1319; AVX2-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1320; AVX2-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1321; AVX2-NEXT:    vzeroupper
1322; AVX2-NEXT:    callq __truncdfhf2@PLT
1323; AVX2-NEXT:    movl %eax, %ebp
1324; AVX2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1325; AVX2-NEXT:    callq __truncdfhf2@PLT
1326; AVX2-NEXT:    movl %eax, %r14d
1327; AVX2-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1328; AVX2-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1329; AVX2-NEXT:    vzeroupper
1330; AVX2-NEXT:    callq __truncdfhf2@PLT
1331; AVX2-NEXT:    movl %eax, %r15d
1332; AVX2-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1333; AVX2-NEXT:    callq __truncdfhf2@PLT
1334; AVX2-NEXT:    movw %ax, 12(%rbx)
1335; AVX2-NEXT:    movw %r15w, 8(%rbx)
1336; AVX2-NEXT:    movw %r14w, 4(%rbx)
1337; AVX2-NEXT:    movw %bp, (%rbx)
1338; AVX2-NEXT:    movw %r13w, 14(%rbx)
1339; AVX2-NEXT:    movw %r12w, 10(%rbx)
1340; AVX2-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1341; AVX2-NEXT:    movw %ax, 6(%rbx)
1342; AVX2-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1343; AVX2-NEXT:    movw %ax, 2(%rbx)
1344; AVX2-NEXT:    addq $120, %rsp
1345; AVX2-NEXT:    popq %rbx
1346; AVX2-NEXT:    popq %r12
1347; AVX2-NEXT:    popq %r13
1348; AVX2-NEXT:    popq %r14
1349; AVX2-NEXT:    popq %r15
1350; AVX2-NEXT:    popq %rbp
1351; AVX2-NEXT:    retq
1352;
1353; AVX512-LABEL: store_cvt_8f64_to_8i16:
1354; AVX512:       # %bb.0:
1355; AVX512-NEXT:    pushq %rbp
1356; AVX512-NEXT:    pushq %r15
1357; AVX512-NEXT:    pushq %r14
1358; AVX512-NEXT:    pushq %r13
1359; AVX512-NEXT:    pushq %r12
1360; AVX512-NEXT:    pushq %rbx
1361; AVX512-NEXT:    subq $152, %rsp
1362; AVX512-NEXT:    movq %rdi, %rbx
1363; AVX512-NEXT:    vmovupd %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill
1364; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1365; AVX512-NEXT:    vzeroupper
1366; AVX512-NEXT:    callq __truncdfhf2@PLT
1367; AVX512-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1368; AVX512-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload
1369; AVX512-NEXT:    vextractf128 $1, %ymm0, %xmm0
1370; AVX512-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1371; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1372; AVX512-NEXT:    vzeroupper
1373; AVX512-NEXT:    callq __truncdfhf2@PLT
1374; AVX512-NEXT:    movw %ax, {{[-0-9]+}}(%r{{[sb]}}p) # 2-byte Spill
1375; AVX512-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload
1376; AVX512-NEXT:    vextractf64x4 $1, %zmm0, %ymm0
1377; AVX512-NEXT:    vmovupd %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill
1378; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1379; AVX512-NEXT:    vzeroupper
1380; AVX512-NEXT:    callq __truncdfhf2@PLT
1381; AVX512-NEXT:    movl %eax, %r12d
1382; AVX512-NEXT:    vmovupd {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1383; AVX512-NEXT:    vextractf128 $1, %ymm0, %xmm0
1384; AVX512-NEXT:    vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
1385; AVX512-NEXT:    vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
1386; AVX512-NEXT:    vzeroupper
1387; AVX512-NEXT:    callq __truncdfhf2@PLT
1388; AVX512-NEXT:    movl %eax, %r13d
1389; AVX512-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload
1390; AVX512-NEXT:    # kill: def $xmm0 killed $xmm0 killed $zmm0
1391; AVX512-NEXT:    vzeroupper
1392; AVX512-NEXT:    callq __truncdfhf2@PLT
1393; AVX512-NEXT:    movl %eax, %ebp
1394; AVX512-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1395; AVX512-NEXT:    callq __truncdfhf2@PLT
1396; AVX512-NEXT:    movl %eax, %r14d
1397; AVX512-NEXT:    vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload
1398; AVX512-NEXT:    # kill: def $xmm0 killed $xmm0 killed $ymm0
1399; AVX512-NEXT:    vzeroupper
1400; AVX512-NEXT:    callq __truncdfhf2@PLT
1401; AVX512-NEXT:    movl %eax, %r15d
1402; AVX512-NEXT:    vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
1403; AVX512-NEXT:    callq __truncdfhf2@PLT
1404; AVX512-NEXT:    movw %ax, 12(%rbx)
1405; AVX512-NEXT:    movw %r15w, 8(%rbx)
1406; AVX512-NEXT:    movw %r14w, 4(%rbx)
1407; AVX512-NEXT:    movw %bp, (%rbx)
1408; AVX512-NEXT:    movw %r13w, 14(%rbx)
1409; AVX512-NEXT:    movw %r12w, 10(%rbx)
1410; AVX512-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1411; AVX512-NEXT:    movw %ax, 6(%rbx)
1412; AVX512-NEXT:    movzwl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 2-byte Folded Reload
1413; AVX512-NEXT:    movw %ax, 2(%rbx)
1414; AVX512-NEXT:    addq $152, %rsp
1415; AVX512-NEXT:    popq %rbx
1416; AVX512-NEXT:    popq %r12
1417; AVX512-NEXT:    popq %r13
1418; AVX512-NEXT:    popq %r14
1419; AVX512-NEXT:    popq %r15
1420; AVX512-NEXT:    popq %rbp
1421; AVX512-NEXT:    retq
1422  %1 = fptrunc <8 x double> %a0 to <8 x half>
1423  %2 = bitcast <8 x half> %1 to <8 x i16>
1424  store <8 x i16> %2, <8 x i16>* %a1
1425  ret void
1426}
1427
1428define void @store_cvt_32f32_to_32f16(<32 x float> %a0, <32 x half>* %a1) nounwind {
1429; AVX1-LABEL: store_cvt_32f32_to_32f16:
1430; AVX1:       # %bb.0:
1431; AVX1-NEXT:    vcvtps2ph $4, %ymm3, 48(%rdi)
1432; AVX1-NEXT:    vcvtps2ph $4, %ymm2, 32(%rdi)
1433; AVX1-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
1434; AVX1-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
1435; AVX1-NEXT:    vzeroupper
1436; AVX1-NEXT:    retq
1437;
1438; AVX2-LABEL: store_cvt_32f32_to_32f16:
1439; AVX2:       # %bb.0:
1440; AVX2-NEXT:    vcvtps2ph $4, %ymm3, 48(%rdi)
1441; AVX2-NEXT:    vcvtps2ph $4, %ymm2, 32(%rdi)
1442; AVX2-NEXT:    vcvtps2ph $4, %ymm1, 16(%rdi)
1443; AVX2-NEXT:    vcvtps2ph $4, %ymm0, (%rdi)
1444; AVX2-NEXT:    vzeroupper
1445; AVX2-NEXT:    retq
1446;
1447; AVX512-LABEL: store_cvt_32f32_to_32f16:
1448; AVX512:       # %bb.0:
1449; AVX512-NEXT:    vcvtps2ph $4, %zmm1, 32(%rdi)
1450; AVX512-NEXT:    vcvtps2ph $4, %zmm0, (%rdi)
1451; AVX512-NEXT:    vzeroupper
1452; AVX512-NEXT:    retq
1453  %1 = fptrunc <32 x float> %a0 to <32 x half>
1454  store <32 x half> %1, <32 x half>* %a1
1455  ret void
1456}
1457