llvm-project/llvm/test/CodeGen/X86/vec_fp_to_int.ll

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2785 lines
99 KiB
LLVM
Raw Normal View History

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=ALL --check-prefix=SSE --check-prefix=SSE2
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=VEX --check-prefix=AVX1
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=VEX --check-prefix=AVX2
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=AVX512 --check-prefix=AVX512F
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512vl | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=AVX512 --check-prefix=AVX512VL
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512dq | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=AVX512 --check-prefix=AVX512DQ
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512dq,+avx512vl | FileCheck %s --check-prefix=ALL --check-prefix=AVX --check-prefix=AVX512 --check-prefix=AVX512VLDQ
;
; 32-bit tests to make sure we're not doing anything stupid.
; RUN: llc < %s -mtriple=i686-unknown-unknown
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2
;
; Double to Signed Integer
;
define <2 x i64> @fptosi_2f64_to_2i64(<2 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_2f64_to_2i64:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm0
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_2f64_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vcvttsd2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm1
; VEX-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; VEX-NEXT: vcvttsd2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptosi_2f64_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttsd2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512F-NEXT: vcvttsd2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_2f64_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttsd2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512VL-NEXT: vcvttsd2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_2f64_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2qq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_2f64_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2qq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptosi <2 x double> %a to <2 x i64>
ret <2 x i64> %cvt
}
define <4 x i32> @fptosi_2f64_to_4i32(<2 x double> %a) {
; SSE-LABEL: fptosi_2f64_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_4i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: retq
%cvt = fptosi <2 x double> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %ext
}
define <2 x i32> @fptosi_2f64_to_2i32(<2 x double> %a) {
; SSE-LABEL: fptosi_2f64_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_2i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: retq
%cvt = fptosi <2 x double> %a to <2 x i32>
ret <2 x i32> %cvt
}
define <4 x i32> @fptosi_4f64_to_2i32(<2 x double> %a) {
; SSE-LABEL: fptosi_4f64_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f64_to_2i32:
; AVX: # %bb.0:
; AVX-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
%ext = shufflevector <2 x double> %a, <2 x double> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
%cvt = fptosi <4 x double> %ext to <4 x i32>
ret <4 x i32> %cvt
}
define <4 x i64> @fptosi_4f64_to_4i64(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f64_to_4i64:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm2
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm0
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0]
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm3
; SSE-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1,1]
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm0
; SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm0[0]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movdqa %xmm2, %xmm0
; SSE-NEXT: movdqa %xmm3, %xmm1
; SSE-NEXT: retq
;
; AVX1-LABEL: fptosi_4f64_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX1-NEXT: vcvttsd2si %xmm1, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX1-NEXT: vcvttsd2si %xmm1, %rax
; AVX1-NEXT: vmovq %rax, %xmm1
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX1-NEXT: vcvttsd2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX1-NEXT: vcvttsd2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptosi_4f64_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX2-NEXT: vcvttsd2si %xmm1, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX2-NEXT: vcvttsd2si %xmm1, %rax
; AVX2-NEXT: vmovq %rax, %xmm1
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX2-NEXT: vcvttsd2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX2-NEXT: vcvttsd2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptosi_4f64_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX512F-NEXT: vcvttsd2si %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX512F-NEXT: vcvttsd2si %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512F-NEXT: vcvttsd2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512F-NEXT: vcvttsd2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512F-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_4f64_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX512VL-NEXT: vcvttsd2si %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX512VL-NEXT: vcvttsd2si %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512VL-NEXT: vcvttsd2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512VL-NEXT: vcvttsd2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_4f64_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2qq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_4f64_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2qq %ymm0, %ymm0
; AVX512VLDQ-NEXT: retq
%cvt = fptosi <4 x double> %a to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i32> @fptosi_4f64_to_4i32(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f64_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm1, %xmm1
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f64_to_4i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
%cvt = fptosi <4 x double> %a to <4 x i32>
ret <4 x i32> %cvt
}
;
; Double to Unsigned Integer
;
define <2 x i64> @fptoui_2f64_to_2i64(<2 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_2f64_to_2i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
; SSE-NEXT: movapd %xmm0, %xmm1
; SSE-NEXT: subsd %xmm2, %xmm1
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttsd2si %xmm0, %rdx
; SSE-NEXT: ucomisd %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rdx
; SSE-NEXT: movq %rdx, %xmm1
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: movapd %xmm0, %xmm3
; SSE-NEXT: subsd %xmm2, %xmm3
; SSE-NEXT: cvttsd2si %xmm3, %rax
; SSE-NEXT: xorq %rcx, %rax
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttsd2si %xmm0, %rcx
; SSE-NEXT: ucomisd %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rcx
; SSE-NEXT: movq %rcx, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptoui_2f64_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
; VEX-NEXT: vsubsd %xmm1, %xmm0, %xmm2
; VEX-NEXT: vcvttsd2si %xmm2, %rax
; VEX-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttsd2si %xmm0, %rdx
; VEX-NEXT: vucomisd %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rdx
; VEX-NEXT: vmovq %rdx, %xmm2
; VEX-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; VEX-NEXT: vsubsd %xmm1, %xmm0, %xmm3
; VEX-NEXT: vcvttsd2si %xmm3, %rax
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttsd2si %xmm0, %rcx
; VEX-NEXT: vucomisd %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rcx
; VEX-NEXT: vmovq %rcx, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f64_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512F-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f64_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512VL-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f64_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2uqq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f64_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2uqq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <2 x double> %a to <2 x i64>
ret <2 x i64> %cvt
}
define <4 x i32> @fptoui_2f64_to_4i32(<2 x double> %a) {
; SSE-LABEL: fptoui_2f64_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rcx
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: movd %ecx, %xmm1
; SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
; SSE-NEXT: movq {{.*#+}} xmm0 = xmm0[0],zero
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_2f64_to_4i32:
; AVX1: # %bb.0:
; AVX1-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX1-NEXT: vmovapd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX1-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX1-NEXT: vpackssdw %xmm0, %xmm2, %xmm2
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm3
; AVX1-NEXT: vsubpd %ymm1, %ymm0, %ymm0
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX1-NEXT: vxorpd {{.*}}(%rip), %xmm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm3, %xmm0, %xmm0
; AVX1-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_2f64_to_4i32:
; AVX2: # %bb.0:
; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX2-NEXT: vbroadcastsd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX2-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX2-NEXT: vpackssdw %xmm0, %xmm2, %xmm2
; AVX2-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX2-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorpd %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f64_to_4i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512F-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512F-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f64_to_4i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttpd2udq %xmm0, %xmm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f64_to_4i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512DQ-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f64_to_4i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2udq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <2 x double> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %ext
}
define <4 x i32> @fptoui_2f64_to_2i32(<2 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_2f64_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm1
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: movdqa %xmm1, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_2f64_to_2i32:
; AVX1: # %bb.0:
; AVX1-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX1-NEXT: vmovapd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX1-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX1-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm3
; AVX1-NEXT: vsubpd %ymm1, %ymm0, %ymm0
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX1-NEXT: vxorpd {{.*}}(%rip), %xmm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm3, %xmm0, %xmm0
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_2f64_to_2i32:
; AVX2: # %bb.0:
; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX2-NEXT: vbroadcastsd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX2-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX2-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX2-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX2-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX2-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorpd %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f64_to_2i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512F-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f64_to_2i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttpd2udq %xmm0, %xmm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f64_to_2i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f64_to_2i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2udq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <2 x double> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x i32> %ext
}
define <4 x i32> @fptoui_4f64_to_2i32(<2 x double> %a) {
; SSE-LABEL: fptoui_4f64_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm1
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: movq {{.*#+}} xmm0 = xmm1[0],zero
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_4f64_to_2i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovapd %xmm0, %xmm0
; AVX1-NEXT: vmovapd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX1-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX1-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX1-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX1-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX1-NEXT: vxorpd {{.*}}(%rip), %xmm1, %xmm1
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_4f64_to_2i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vmovapd %xmm0, %xmm0
; AVX2-NEXT: vbroadcastsd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX2-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX2-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX2-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX2-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX2-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorpd %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f64_to_2i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovaps %xmm0, %xmm0
; AVX512F-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f64_to_2i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovaps %xmm0, %xmm0
; AVX512VL-NEXT: vcvttpd2udq %ymm0, %xmm0
; AVX512VL-NEXT: vzeroupper
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f64_to_2i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vmovaps %xmm0, %xmm0
; AVX512DQ-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f64_to_2i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vmovaps %xmm0, %xmm0
; AVX512VLDQ-NEXT: vcvttpd2udq %ymm0, %xmm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%ext = shufflevector <2 x double> %a, <2 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%cvt = fptoui <4 x double> %ext to <4 x i32>
ret <4 x i32> %cvt
}
define <4 x i64> @fptoui_4f64_to_4i64(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f64_to_4i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movapd %xmm0, %xmm2
; SSE-NEXT: movsd {{.*#+}} xmm3 = mem[0],zero
; SSE-NEXT: subsd %xmm3, %xmm0
; SSE-NEXT: cvttsd2si %xmm0, %rcx
; SSE-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttsd2si %xmm2, %rdx
; SSE-NEXT: ucomisd %xmm3, %xmm2
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm0
; SSE-NEXT: unpckhpd {{.*#+}} xmm2 = xmm2[1,1]
; SSE-NEXT: movapd %xmm2, %xmm4
; SSE-NEXT: subsd %xmm3, %xmm4
; SSE-NEXT: cvttsd2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttsd2si %xmm2, %rdx
; SSE-NEXT: ucomisd %xmm3, %xmm2
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm2
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
; SSE-NEXT: movapd %xmm1, %xmm2
; SSE-NEXT: subsd %xmm3, %xmm2
; SSE-NEXT: cvttsd2si %xmm2, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttsd2si %xmm1, %rdx
; SSE-NEXT: ucomisd %xmm3, %xmm1
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm2
; SSE-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1,1]
; SSE-NEXT: movapd %xmm1, %xmm4
; SSE-NEXT: subsd %xmm3, %xmm4
; SSE-NEXT: cvttsd2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: ucomisd %xmm3, %xmm1
; SSE-NEXT: cmovaeq %rcx, %rax
; SSE-NEXT: movq %rax, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm1[0]
; SSE-NEXT: movdqa %xmm2, %xmm1
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_4f64_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2
; AVX1-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
; AVX1-NEXT: vsubsd %xmm1, %xmm2, %xmm3
; AVX1-NEXT: vcvttsd2si %xmm3, %rax
; AVX1-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttsd2si %xmm2, %rdx
; AVX1-NEXT: vucomisd %xmm1, %xmm2
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vpermilpd {{.*#+}} xmm2 = xmm2[1,0]
; AVX1-NEXT: vsubsd %xmm1, %xmm2, %xmm4
; AVX1-NEXT: vcvttsd2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttsd2si %xmm2, %rdx
; AVX1-NEXT: vucomisd %xmm1, %xmm2
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm2
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX1-NEXT: vsubsd %xmm1, %xmm0, %xmm3
; AVX1-NEXT: vcvttsd2si %xmm3, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttsd2si %xmm0, %rdx
; AVX1-NEXT: vucomisd %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX1-NEXT: vsubsd %xmm1, %xmm0, %xmm4
; AVX1-NEXT: vcvttsd2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttsd2si %xmm0, %rcx
; AVX1-NEXT: vucomisd %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rcx
; AVX1-NEXT: vmovq %rcx, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_4f64_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vextractf128 $1, %ymm0, %xmm2
; AVX2-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
; AVX2-NEXT: vsubsd %xmm1, %xmm2, %xmm3
; AVX2-NEXT: vcvttsd2si %xmm3, %rax
; AVX2-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttsd2si %xmm2, %rdx
; AVX2-NEXT: vucomisd %xmm1, %xmm2
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vpermilpd {{.*#+}} xmm2 = xmm2[1,0]
; AVX2-NEXT: vsubsd %xmm1, %xmm2, %xmm4
; AVX2-NEXT: vcvttsd2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttsd2si %xmm2, %rdx
; AVX2-NEXT: vucomisd %xmm1, %xmm2
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm2
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX2-NEXT: vsubsd %xmm1, %xmm0, %xmm3
; AVX2-NEXT: vcvttsd2si %xmm3, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttsd2si %xmm0, %rdx
; AVX2-NEXT: vucomisd %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX2-NEXT: vsubsd %xmm1, %xmm0, %xmm4
; AVX2-NEXT: vcvttsd2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttsd2si %xmm0, %rcx
; AVX2-NEXT: vucomisd %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rcx
; AVX2-NEXT: vmovq %rcx, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f64_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX512F-NEXT: vcvttsd2usi %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX512F-NEXT: vcvttsd2usi %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512F-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512F-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512F-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f64_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vextractf128 $1, %ymm0, %xmm1
; AVX512VL-NEXT: vcvttsd2usi %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm1 = xmm1[1,0]
; AVX512VL-NEXT: vcvttsd2usi %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512VL-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm0 = xmm0[1,0]
; AVX512VL-NEXT: vcvttsd2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f64_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2uqq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f64_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2uqq %ymm0, %ymm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <4 x double> %a to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i32> @fptoui_4f64_to_4i32(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f64_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: movd %eax, %xmm2
; SSE-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1,1]
; SSE-NEXT: cvttsd2si %xmm1, %rax
; SSE-NEXT: movd %eax, %xmm1
; SSE-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm1
; SSE-NEXT: unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttsd2si %xmm0, %rax
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_4f64_to_4i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovapd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX1-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX1-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX1-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX1-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX1-NEXT: vxorpd {{.*}}(%rip), %xmm1, %xmm1
; AVX1-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_4f64_to_4i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vbroadcastsd {{.*#+}} ymm1 = [2.147483648E+9,2.147483648E+9,2.147483648E+9,2.147483648E+9]
; AVX2-NEXT: vcmpltpd %ymm1, %ymm0, %ymm2
; AVX2-NEXT: vextractf128 $1, %ymm2, %xmm3
; AVX2-NEXT: vpackssdw %xmm3, %xmm2, %xmm2
; AVX2-NEXT: vsubpd %ymm1, %ymm0, %ymm1
; AVX2-NEXT: vcvttpd2dq %ymm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorpd %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttpd2dq %ymm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f64_to_4i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512F-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f64_to_4i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttpd2udq %ymm0, %xmm0
; AVX512VL-NEXT: vzeroupper
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f64_to_4i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512DQ-NEXT: vcvttpd2udq %zmm0, %ymm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f64_to_4i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2udq %ymm0, %xmm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <4 x double> %a to <4 x i32>
ret <4 x i32> %cvt
}
;
; Float to Signed Integer
;
define <2 x i32> @fptosi_2f32_to_2i32(<2 x float> %a) {
; SSE-LABEL: fptosi_2f32_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f32_to_2i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: retq
%cvt = fptosi <2 x float> %a to <2 x i32>
ret <2 x i32> %cvt
}
define <4 x i32> @fptosi_4f32_to_4i32(<4 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f32_to_4i32:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f32_to_4i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: retq
%cvt = fptosi <4 x float> %a to <4 x i32>
ret <4 x i32> %cvt
}
define <2 x i64> @fptosi_2f32_to_2i64(<4 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_2f32_to_2i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_2f32_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vcvttss2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm1
; VEX-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; VEX-NEXT: vcvttss2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptosi_2f32_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_2f32_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_2f32_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX512DQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_2f32_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2qq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%shuf = shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%cvt = fptosi <2 x float> %shuf to <2 x i64>
ret <2 x i64> %cvt
}
define <2 x i64> @fptosi_4f32_to_2i64(<4 x float> %a) {
; SSE-LABEL: fptosi_4f32_to_2i64:
; SSE: # %bb.0:
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm0
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_4f32_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; VEX-NEXT: vcvttss2si %xmm1, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rcx
; VEX-NEXT: vmovq %rcx, %xmm0
; VEX-NEXT: vmovq %rax, %xmm1
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptosi_4f32_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2si %xmm1, %rax
; AVX512F-NEXT: vcvttss2si %xmm0, %rcx
; AVX512F-NEXT: vmovq %rcx, %xmm0
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_4f32_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2si %xmm1, %rax
; AVX512VL-NEXT: vcvttss2si %xmm0, %rcx
; AVX512VL-NEXT: vmovq %rcx, %xmm0
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_4f32_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX512DQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_4f32_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2qq %xmm0, %ymm0
; AVX512VLDQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%cvt = fptosi <4 x float> %a to <4 x i64>
%shuf = shufflevector <4 x i64> %cvt, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %shuf
}
define <8 x i32> @fptosi_8f32_to_8i32(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_8f32_to_8i32:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: cvttps2dq %xmm1, %xmm1
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_8f32_to_8i32:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX-NEXT: retq
%cvt = fptosi <8 x float> %a to <8 x i32>
ret <8 x i32> %cvt
}
define <4 x i64> @fptosi_4f32_to_4i64(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f32_to_4i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm2
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,1],xmm0[2,3]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm1[0]
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[3,1],xmm0[2,3]
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm3
; SSE-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movdqa %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptosi_4f32_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX1-NEXT: vcvttss2si %xmm1, %rax
; AVX1-NEXT: vmovq %rax, %xmm1
; AVX1-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX1-NEXT: vcvttss2si %xmm2, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX1-NEXT: vcvttss2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX1-NEXT: vcvttss2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptosi_4f32_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX2-NEXT: vcvttss2si %xmm1, %rax
; AVX2-NEXT: vmovq %rax, %xmm1
; AVX2-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX2-NEXT: vcvttss2si %xmm2, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX2-NEXT: vcvttss2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vcvttss2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptosi_4f32_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX512F-NEXT: vcvttss2si %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX512F-NEXT: vcvttss2si %xmm2, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512F-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_4f32_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX512VL-NEXT: vcvttss2si %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX512VL-NEXT: vcvttss2si %xmm2, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_4f32_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_4f32_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2qq %xmm0, %ymm0
; AVX512VLDQ-NEXT: retq
%shuf = shufflevector <8 x float> %a, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%cvt = fptosi <4 x float> %shuf to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i64> @fptosi_8f32_to_4i64(<8 x float> %a) {
; SSE-LABEL: fptosi_8f32_to_4i64:
; SSE: # %bb.0:
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm2
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,1],xmm0[2,3]
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm1[0]
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[3,1],xmm0[2,3]
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm3
; SSE-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0]
; SSE-NEXT: movdqa %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptosi_8f32_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX1-NEXT: vcvttss2si %xmm1, %rax
; AVX1-NEXT: vmovq %rax, %xmm1
; AVX1-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX1-NEXT: vcvttss2si %xmm2, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX1-NEXT: vcvttss2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm2
; AVX1-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX1-NEXT: vcvttss2si %xmm0, %rax
; AVX1-NEXT: vmovq %rax, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptosi_8f32_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX2-NEXT: vcvttss2si %xmm1, %rax
; AVX2-NEXT: vmovq %rax, %xmm1
; AVX2-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX2-NEXT: vcvttss2si %xmm2, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX2-NEXT: vcvttss2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm2
; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vcvttss2si %xmm0, %rax
; AVX2-NEXT: vmovq %rax, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptosi_8f32_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2si %xmm1, %rax
; AVX512F-NEXT: vcvttss2si %xmm0, %rcx
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,0]
; AVX512F-NEXT: vcvttss2si %xmm1, %rdx
; AVX512F-NEXT: vpermilps {{.*#+}} xmm0 = xmm0[3,1,2,3]
; AVX512F-NEXT: vcvttss2si %xmm0, %rsi
; AVX512F-NEXT: vmovq %rsi, %xmm0
; AVX512F-NEXT: vmovq %rdx, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: vmovq %rcx, %xmm1
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
; AVX512F-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_8f32_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2si %xmm1, %rax
; AVX512VL-NEXT: vcvttss2si %xmm0, %rcx
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,0]
; AVX512VL-NEXT: vcvttss2si %xmm1, %rdx
; AVX512VL-NEXT: vpermilps {{.*#+}} xmm0 = xmm0[3,1,2,3]
; AVX512VL-NEXT: vcvttss2si %xmm0, %rsi
; AVX512VL-NEXT: vmovq %rsi, %xmm0
; AVX512VL-NEXT: vmovq %rdx, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: vmovq %rcx, %xmm1
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_8f32_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_8f32_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512VLDQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptosi <8 x float> %a to <8 x i64>
%shuf = shufflevector <8 x i64> %cvt, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i64> %shuf
}
;
; Float to Unsigned Integer
;
define <2 x i32> @fptoui_2f32_to_2i32(<2 x float> %a) {
; SSE-LABEL: fptoui_2f32_to_2i32:
; SSE: # %bb.0:
; SSE-NEXT: movaps {{.*#+}} xmm2 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: cmpltps %xmm2, %xmm1
; SSE-NEXT: cvttps2dq %xmm0, %xmm3
; SSE-NEXT: subps %xmm2, %xmm0
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: xorps {{.*}}(%rip), %xmm0
; SSE-NEXT: andps %xmm1, %xmm3
; SSE-NEXT: andnps %xmm0, %xmm1
; SSE-NEXT: orps %xmm3, %xmm1
; SSE-NEXT: movaps %xmm1, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_2f32_to_2i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovaps {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX1-NEXT: vcmpltps %xmm1, %xmm0, %xmm2
; AVX1-NEXT: vsubps %xmm1, %xmm0, %xmm1
; AVX1-NEXT: vcvttps2dq %xmm1, %xmm1
; AVX1-NEXT: vxorps {{.*}}(%rip), %xmm1, %xmm1
; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_2f32_to_2i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX2-NEXT: vcmpltps %xmm1, %xmm0, %xmm2
; AVX2-NEXT: vsubps %xmm1, %xmm0, %xmm1
; AVX2-NEXT: vcvttps2dq %xmm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorps %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f32_to_2i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f32_to_2i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttps2udq %xmm0, %xmm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f32_to_2i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f32_to_2i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2udq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <2 x float> %a to <2 x i32>
ret <2 x i32> %cvt
}
define <4 x i32> @fptoui_4f32_to_4i32(<4 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f32_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: movaps {{.*#+}} xmm2 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: cmpltps %xmm2, %xmm1
; SSE-NEXT: cvttps2dq %xmm0, %xmm3
; SSE-NEXT: subps %xmm2, %xmm0
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: xorps {{.*}}(%rip), %xmm0
; SSE-NEXT: andps %xmm1, %xmm3
; SSE-NEXT: andnps %xmm0, %xmm1
; SSE-NEXT: orps %xmm3, %xmm1
; SSE-NEXT: movaps %xmm1, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_4f32_to_4i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovaps {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX1-NEXT: vcmpltps %xmm1, %xmm0, %xmm2
; AVX1-NEXT: vsubps %xmm1, %xmm0, %xmm1
; AVX1-NEXT: vcvttps2dq %xmm1, %xmm1
; AVX1-NEXT: vxorps {{.*}}(%rip), %xmm1, %xmm1
; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX1-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_4f32_to_4i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX2-NEXT: vcmpltps %xmm1, %xmm0, %xmm2
; AVX2-NEXT: vsubps %xmm1, %xmm0, %xmm1
; AVX2-NEXT: vcvttps2dq %xmm1, %xmm1
; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorps %xmm3, %xmm1, %xmm1
; AVX2-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX2-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f32_to_4i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f32_to_4i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttps2udq %xmm0, %xmm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f32_to_4i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
; AVX512DQ-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f32_to_4i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2udq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <4 x float> %a to <4 x i32>
ret <4 x i32> %cvt
}
define <2 x i64> @fptoui_2f32_to_2i64(<4 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_2f32_to_2i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: subss %xmm2, %xmm1
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm0, %rdx
; SSE-NEXT: ucomiss %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rdx
; SSE-NEXT: movq %rdx, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: subss %xmm2, %xmm3
; SSE-NEXT: cvttss2si %xmm3, %rax
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm0, %rcx
; SSE-NEXT: ucomiss %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rcx
; SSE-NEXT: movq %rcx, %xmm0
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptoui_2f32_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; VEX-NEXT: vsubss %xmm1, %xmm0, %xmm2
; VEX-NEXT: vcvttss2si %xmm2, %rax
; VEX-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rdx
; VEX-NEXT: vucomiss %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rdx
; VEX-NEXT: vmovq %rdx, %xmm2
; VEX-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; VEX-NEXT: vsubss %xmm1, %xmm0, %xmm3
; VEX-NEXT: vcvttss2si %xmm3, %rax
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rcx
; VEX-NEXT: vucomiss %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rcx
; VEX-NEXT: vmovq %rcx, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f32_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f32_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f32_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX512DQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f32_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2uqq %xmm0, %xmm0
; AVX512VLDQ-NEXT: retq
%shuf = shufflevector <4 x float> %a, <4 x float> undef, <2 x i32> <i32 0, i32 1>
%cvt = fptoui <2 x float> %shuf to <2 x i64>
ret <2 x i64> %cvt
}
define <2 x i64> @fptoui_4f32_to_2i64(<4 x float> %a) {
; SSE-LABEL: fptoui_4f32_to_2i64:
; SSE: # %bb.0:
; SSE-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
; SSE-NEXT: movaps %xmm0, %xmm1
; SSE-NEXT: subss %xmm2, %xmm1
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm0, %rdx
; SSE-NEXT: ucomiss %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rdx
; SSE-NEXT: movq %rdx, %xmm1
; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: subss %xmm2, %xmm3
; SSE-NEXT: cvttss2si %xmm3, %rax
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm0, %rcx
; SSE-NEXT: ucomiss %xmm2, %xmm0
; SSE-NEXT: cmovaeq %rax, %rcx
; SSE-NEXT: movq %rcx, %xmm0
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
; SSE-NEXT: movdqa %xmm1, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptoui_4f32_to_2i64:
; VEX: # %bb.0:
; VEX-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; VEX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
; VEX-NEXT: vsubss %xmm2, %xmm1, %xmm3
; VEX-NEXT: vcvttss2si %xmm3, %rax
; VEX-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm1, %rdx
; VEX-NEXT: vucomiss %xmm2, %xmm1
; VEX-NEXT: cmovaeq %rax, %rdx
; VEX-NEXT: vsubss %xmm2, %xmm0, %xmm1
; VEX-NEXT: vcvttss2si %xmm1, %rax
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rcx
; VEX-NEXT: vucomiss %xmm2, %xmm0
; VEX-NEXT: cmovaeq %rax, %rcx
; VEX-NEXT: vmovq %rcx, %xmm0
; VEX-NEXT: vmovq %rdx, %xmm1
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f32_to_2i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2usi %xmm1, %rax
; AVX512F-NEXT: vcvttss2usi %xmm0, %rcx
; AVX512F-NEXT: vmovq %rcx, %xmm0
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f32_to_2i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2usi %xmm1, %rax
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rcx
; AVX512VL-NEXT: vmovq %rcx, %xmm0
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f32_to_2i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; AVX512DQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f32_to_2i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2uqq %xmm0, %ymm0
; AVX512VLDQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <4 x float> %a to <4 x i64>
%shuf = shufflevector <4 x i64> %cvt, <4 x i64> undef, <2 x i32> <i32 0, i32 1>
ret <2 x i64> %shuf
}
define <8 x i32> @fptoui_8f32_to_8i32(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_8f32_to_8i32:
; SSE: # %bb.0:
; SSE-NEXT: movaps {{.*#+}} xmm4 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm0, %xmm2
; SSE-NEXT: cmpltps %xmm4, %xmm2
; SSE-NEXT: cvttps2dq %xmm0, %xmm3
; SSE-NEXT: subps %xmm4, %xmm0
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: movaps {{.*#+}} xmm5 = [2147483648,2147483648,2147483648,2147483648]
; SSE-NEXT: xorps %xmm5, %xmm0
; SSE-NEXT: andps %xmm2, %xmm3
; SSE-NEXT: andnps %xmm0, %xmm2
; SSE-NEXT: orps %xmm3, %xmm2
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm1, %xmm3
; SSE-NEXT: cmpltps %xmm4, %xmm3
; SSE-NEXT: cvttps2dq %xmm1, %xmm0
; SSE-NEXT: subps %xmm4, %xmm1
; SSE-NEXT: cvttps2dq %xmm1, %xmm1
; SSE-NEXT: xorps %xmm5, %xmm1
; SSE-NEXT: andps %xmm3, %xmm0
; SSE-NEXT: andnps %xmm1, %xmm3
; SSE-NEXT: orps %xmm0, %xmm3
; SSE-NEXT: movaps %xmm2, %xmm0
; SSE-NEXT: movaps %xmm3, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_8f32_to_8i32:
; AVX1: # %bb.0:
; AVX1-NEXT: vmovaps {{.*#+}} ymm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX1-NEXT: vcmpltps %ymm1, %ymm0, %ymm2
; AVX1-NEXT: vsubps %ymm1, %ymm0, %ymm1
; AVX1-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX1-NEXT: vxorps {{.*}}(%rip), %ymm1, %ymm1
; AVX1-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX1-NEXT: vblendvps %ymm2, %ymm0, %ymm1, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_8f32_to_8i32:
; AVX2: # %bb.0:
; AVX2-NEXT: vbroadcastss {{.*#+}} ymm1 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
; AVX2-NEXT: vcmpltps %ymm1, %ymm0, %ymm2
; AVX2-NEXT: vsubps %ymm1, %ymm0, %ymm1
; AVX2-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX2-NEXT: vbroadcastss {{.*#+}} ymm3 = [2147483648,2147483648,2147483648,2147483648,2147483648,2147483648,2147483648,2147483648]
; AVX2-NEXT: vxorps %ymm3, %ymm1, %ymm1
; AVX2-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX2-NEXT: vblendvps %ymm2, %ymm0, %ymm1, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_8f32_to_8i32:
; AVX512F: # %bb.0:
; AVX512F-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512F-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_8f32_to_8i32:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttps2udq %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_8f32_to_8i32:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 def $zmm0
; AVX512DQ-NEXT: vcvttps2udq %zmm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_8f32_to_8i32:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2udq %ymm0, %ymm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <8 x float> %a to <8 x i32>
ret <8 x i32> %cvt
}
define <4 x i64> @fptoui_4f32_to_4i64(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f32_to_4i64:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; SSE-NEXT: movaps %xmm0, %xmm2
; SSE-NEXT: subss %xmm1, %xmm2
; SSE-NEXT: cvttss2si %xmm2, %rcx
; SSE-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm0, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm0
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm2
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: shufps {{.*#+}} xmm3 = xmm3[1,1],xmm0[2,3]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm3, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm3, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm3
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm3
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm3[0]
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: shufps {{.*#+}} xmm3 = xmm3[3,1],xmm0[2,3]
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps %xmm3, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm3, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm3
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm3
; SSE-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: movaps %xmm0, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
2015-07-19 00:53:51 +08:00
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: ucomiss %xmm1, %xmm0
; SSE-NEXT: cmovaeq %rcx, %rax
; SSE-NEXT: movq %rax, %xmm1
2015-07-19 00:53:51 +08:00
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0]
; SSE-NEXT: movdqa %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_4f32_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vpermilps {{.*#+}} xmm2 = xmm0[3,1,2,3]
; AVX1-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; AVX1-NEXT: vsubss %xmm1, %xmm2, %xmm3
; AVX1-NEXT: vcvttss2si %xmm3, %rax
; AVX1-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm2, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm2
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm2
; AVX1-NEXT: vpermilpd {{.*#+}} xmm3 = xmm0[1,0]
; AVX1-NEXT: vsubss %xmm1, %xmm3, %xmm4
; AVX1-NEXT: vcvttss2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm3, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm3
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX1-NEXT: vsubss %xmm1, %xmm0, %xmm3
; AVX1-NEXT: vcvttss2si %xmm3, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm0, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX1-NEXT: vsubss %xmm1, %xmm0, %xmm4
; AVX1-NEXT: vcvttss2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm0, %rcx
; AVX1-NEXT: vucomiss %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rcx
; AVX1-NEXT: vmovq %rcx, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_4f32_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vpermilps {{.*#+}} xmm2 = xmm0[3,1,2,3]
; AVX2-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; AVX2-NEXT: vsubss %xmm1, %xmm2, %xmm3
; AVX2-NEXT: vcvttss2si %xmm3, %rax
; AVX2-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm2, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm2
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm2
; AVX2-NEXT: vpermilpd {{.*#+}} xmm3 = xmm0[1,0]
; AVX2-NEXT: vsubss %xmm1, %xmm3, %xmm4
; AVX2-NEXT: vcvttss2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm3, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm3
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX2-NEXT: vsubss %xmm1, %xmm0, %xmm3
; AVX2-NEXT: vcvttss2si %xmm3, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm0, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vsubss %xmm1, %xmm0, %xmm4
; AVX2-NEXT: vcvttss2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm0, %rcx
; AVX2-NEXT: vucomiss %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rcx
; AVX2-NEXT: vmovq %rcx, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_4f32_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX512F-NEXT: vcvttss2usi %xmm1, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX512F-NEXT: vcvttss2usi %xmm2, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512F-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_4f32_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vpermilps {{.*#+}} xmm1 = xmm0[3,1,2,3]
; AVX512VL-NEXT: vcvttss2usi %xmm1, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm2 = xmm0[1,0]
; AVX512VL-NEXT: vcvttss2usi %xmm2, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0]
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_4f32_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_4f32_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2uqq %xmm0, %ymm0
; AVX512VLDQ-NEXT: retq
%shuf = shufflevector <8 x float> %a, <8 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
%cvt = fptoui <4 x float> %shuf to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i64> @fptoui_8f32_to_4i64(<8 x float> %a) {
; SSE-LABEL: fptoui_8f32_to_4i64:
; SSE: # %bb.0:
; SSE-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; SSE-NEXT: movaps %xmm0, %xmm2
; SSE-NEXT: subss %xmm1, %xmm2
; SSE-NEXT: cvttss2si %xmm2, %rcx
; SSE-NEXT: movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm0, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm0
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm2
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: shufps {{.*#+}} xmm3 = xmm3[1,1],xmm0[2,3]
; SSE-NEXT: movaps %xmm3, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm3, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm3
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm3
; SSE-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm3[0]
; SSE-NEXT: movaps %xmm0, %xmm3
; SSE-NEXT: shufps {{.*#+}} xmm3 = xmm3[3,1],xmm0[2,3]
; SSE-NEXT: movaps %xmm3, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm3, %rdx
; SSE-NEXT: ucomiss %xmm1, %xmm3
; SSE-NEXT: cmovaeq %rcx, %rdx
; SSE-NEXT: movq %rdx, %xmm3
; SSE-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
; SSE-NEXT: movaps %xmm0, %xmm4
; SSE-NEXT: subss %xmm1, %xmm4
; SSE-NEXT: cvttss2si %xmm4, %rcx
; SSE-NEXT: xorq %rax, %rcx
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: ucomiss %xmm1, %xmm0
; SSE-NEXT: cmovaeq %rcx, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0]
; SSE-NEXT: movdqa %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_8f32_to_4i64:
; AVX1: # %bb.0:
; AVX1-NEXT: vpermilps {{.*#+}} xmm2 = xmm0[3,1,2,3]
; AVX1-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; AVX1-NEXT: vsubss %xmm1, %xmm2, %xmm3
; AVX1-NEXT: vcvttss2si %xmm3, %rax
; AVX1-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm2, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm2
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm2
; AVX1-NEXT: vpermilpd {{.*#+}} xmm3 = xmm0[1,0]
; AVX1-NEXT: vsubss %xmm1, %xmm3, %xmm4
; AVX1-NEXT: vcvttss2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm3, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm3
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX1-NEXT: vsubss %xmm1, %xmm0, %xmm3
; AVX1-NEXT: vcvttss2si %xmm3, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm0, %rdx
; AVX1-NEXT: vucomiss %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rdx
; AVX1-NEXT: vmovq %rdx, %xmm3
; AVX1-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX1-NEXT: vsubss %xmm1, %xmm0, %xmm4
; AVX1-NEXT: vcvttss2si %xmm4, %rax
; AVX1-NEXT: xorq %rcx, %rax
; AVX1-NEXT: vcvttss2si %xmm0, %rcx
; AVX1-NEXT: vucomiss %xmm1, %xmm0
; AVX1-NEXT: cmovaeq %rax, %rcx
; AVX1-NEXT: vmovq %rcx, %xmm0
; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_8f32_to_4i64:
; AVX2: # %bb.0:
; AVX2-NEXT: vpermilps {{.*#+}} xmm2 = xmm0[3,1,2,3]
; AVX2-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; AVX2-NEXT: vsubss %xmm1, %xmm2, %xmm3
; AVX2-NEXT: vcvttss2si %xmm3, %rax
; AVX2-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm2, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm2
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm2
; AVX2-NEXT: vpermilpd {{.*#+}} xmm3 = xmm0[1,0]
; AVX2-NEXT: vsubss %xmm1, %xmm3, %xmm4
; AVX2-NEXT: vcvttss2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm3, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm3
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0]
; AVX2-NEXT: vsubss %xmm1, %xmm0, %xmm3
; AVX2-NEXT: vcvttss2si %xmm3, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm0, %rdx
; AVX2-NEXT: vucomiss %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rdx
; AVX2-NEXT: vmovq %rdx, %xmm3
; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX2-NEXT: vsubss %xmm1, %xmm0, %xmm4
; AVX2-NEXT: vcvttss2si %xmm4, %rax
; AVX2-NEXT: xorq %rcx, %rax
; AVX2-NEXT: vcvttss2si %xmm0, %rcx
; AVX2-NEXT: vucomiss %xmm1, %xmm0
; AVX2-NEXT: cmovaeq %rax, %rcx
; AVX2-NEXT: vmovq %rcx, %xmm0
; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm3[0],xmm0[0]
; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: fptoui_8f32_to_4i64:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2usi %xmm1, %rax
; AVX512F-NEXT: vcvttss2usi %xmm0, %rcx
; AVX512F-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,0]
; AVX512F-NEXT: vcvttss2usi %xmm1, %rdx
; AVX512F-NEXT: vpermilps {{.*#+}} xmm0 = xmm0[3,1,2,3]
; AVX512F-NEXT: vcvttss2usi %xmm0, %rsi
; AVX512F-NEXT: vmovq %rsi, %xmm0
; AVX512F-NEXT: vmovq %rdx, %xmm1
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: vmovq %rcx, %xmm1
; AVX512F-NEXT: vmovq %rax, %xmm2
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
; AVX512F-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_8f32_to_4i64:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm1 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2usi %xmm1, %rax
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rcx
; AVX512VL-NEXT: vpermilpd {{.*#+}} xmm1 = xmm0[1,0]
; AVX512VL-NEXT: vcvttss2usi %xmm1, %rdx
; AVX512VL-NEXT: vpermilps {{.*#+}} xmm0 = xmm0[3,1,2,3]
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rsi
; AVX512VL-NEXT: vmovq %rsi, %xmm0
; AVX512VL-NEXT: vmovq %rdx, %xmm1
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: vmovq %rcx, %xmm1
; AVX512VL-NEXT: vmovq %rax, %xmm2
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
; AVX512VL-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_8f32_to_4i64:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_8f32_to_4i64:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512VLDQ-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <8 x float> %a to <8 x i64>
%shuf = shufflevector <8 x i64> %cvt, <8 x i64> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i64> %shuf
}
;
; Constant Folding
;
define <2 x i64> @fptosi_2f64_to_2i64_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_2f64_to_2i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,18446744073709551615]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_2i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [1,18446744073709551615]
; AVX-NEXT: retq
%cvt = fptosi <2 x double> <double 1.0, double -1.0> to <2 x i64>
ret <2 x i64> %cvt
}
define <4 x i32> @fptosi_2f64_to_2i32_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_2f64_to_2i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = <4294967295,1,u,u>
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_2i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = <4294967295,1,u,u>
; AVX-NEXT: retq
%cvt = fptosi <2 x double> <double -1.0, double 1.0> to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x i32> %ext
}
define <4 x i64> @fptosi_4f64_to_4i64_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f64_to_4i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,18446744073709551615]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [2,18446744073709551613]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f64_to_4i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [1,18446744073709551615,2,18446744073709551613]
; AVX-NEXT: retq
%cvt = fptosi <4 x double> <double 1.0, double -1.0, double 2.0, double -3.0> to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i32> @fptosi_4f64_to_4i32_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f64_to_4i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [4294967295,1,4294967294,3]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f64_to_4i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [4294967295,1,4294967294,3]
; AVX-NEXT: retq
%cvt = fptosi <4 x double> <double -1.0, double 1.0, double -2.0, double 3.0> to <4 x i32>
ret <4 x i32> %cvt
}
define <2 x i64> @fptoui_2f64_to_2i64_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_2f64_to_2i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [2,4]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f64_to_2i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [2,4]
; AVX-NEXT: retq
%cvt = fptoui <2 x double> <double 2.0, double 4.0> to <2 x i64>
ret <2 x i64> %cvt
}
define <4 x i32> @fptoui_2f64_to_2i32_const(<2 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_2f64_to_2i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = <2,4,u,u>
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f64_to_2i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = <2,4,u,u>
; AVX-NEXT: retq
%cvt = fptoui <2 x double> <double 2.0, double 4.0> to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
ret <4 x i32> %ext
}
define <4 x i64> @fptoui_4f64_to_4i64_const(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f64_to_4i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [2,4]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [6,8]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_4f64_to_4i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [2,4,6,8]
; AVX-NEXT: retq
%cvt = fptoui <4 x double> <double 2.0, double 4.0, double 6.0, double 8.0> to <4 x i64>
ret <4 x i64> %cvt
}
define <4 x i32> @fptoui_4f64_to_4i32_const(<4 x double> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f64_to_4i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [2,4,6,8]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_4f64_to_4i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [2,4,6,8]
; AVX-NEXT: retq
%cvt = fptoui <4 x double> <double 2.0, double 4.0, double 6.0, double 8.0> to <4 x i32>
ret <4 x i32> %cvt
}
define <4 x i32> @fptosi_4f32_to_4i32_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f32_to_4i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,4294967295,2,3]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f32_to_4i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [1,4294967295,2,3]
; AVX-NEXT: retq
%cvt = fptosi <4 x float> <float 1.0, float -1.0, float 2.0, float 3.0> to <4 x i32>
ret <4 x i32> %cvt
}
define <4 x i64> @fptosi_4f32_to_4i64_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_4f32_to_4i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,18446744073709551615]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [2,3]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_4f32_to_4i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [1,18446744073709551615,2,3]
; AVX-NEXT: retq
%cvt = fptosi <4 x float> <float 1.0, float -1.0, float 2.0, float 3.0> to <4 x i64>
ret <4 x i64> %cvt
}
define <8 x i32> @fptosi_8f32_to_8i32_const(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptosi_8f32_to_8i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,4294967295,2,3]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [6,4294967288,2,4294967295]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_8f32_to_8i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [1,4294967295,2,3,6,4294967288,2,4294967295]
; AVX-NEXT: retq
%cvt = fptosi <8 x float> <float 1.0, float -1.0, float 2.0, float 3.0, float 6.0, float -8.0, float 2.0, float -1.0> to <8 x i32>
ret <8 x i32> %cvt
}
define <4 x i32> @fptoui_4f32_to_4i32_const(<4 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f32_to_4i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,2,4,6]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_4f32_to_4i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [1,2,4,6]
; AVX-NEXT: retq
%cvt = fptoui <4 x float> <float 1.0, float 2.0, float 4.0, float 6.0> to <4 x i32>
ret <4 x i32> %cvt
}
define <4 x i64> @fptoui_4f32_to_4i64_const() {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_4f32_to_4i64_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,2]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [4,8]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_4f32_to_4i64_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [1,2,4,8]
; AVX-NEXT: retq
%cvt = fptoui <4 x float> <float 1.0, float 2.0, float 4.0, float 8.0> to <4 x i64>
ret <4 x i64> %cvt
}
define <8 x i32> @fptoui_8f32_to_8i32_const(<8 x float> %a) {
2015-07-19 00:53:51 +08:00
; SSE-LABEL: fptoui_8f32_to_8i32_const:
; SSE: # %bb.0:
2015-07-19 00:53:51 +08:00
; SSE-NEXT: movaps {{.*#+}} xmm0 = [1,2,4,6]
; SSE-NEXT: movaps {{.*#+}} xmm1 = [8,6,4,1]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_8f32_to_8i32_const:
; AVX: # %bb.0:
; AVX-NEXT: vmovaps {{.*#+}} ymm0 = [1,2,4,6,8,6,4,1]
; AVX-NEXT: retq
%cvt = fptoui <8 x float> <float 1.0, float 2.0, float 4.0, float 6.0, float 8.0, float 6.0, float 4.0, float 1.0> to <8 x i32>
ret <8 x i32> %cvt
}
;
; Special Cases
;
define <4 x i32> @fptosi_2f16_to_4i32(<2 x half> %a) nounwind {
; SSE-LABEL: fptosi_2f16_to_4i32:
; SSE: # %bb.0:
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; SSE-NEXT: pushq %rbp
; SSE-NEXT: pushq %rbx
; SSE-NEXT: pushq %rax
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; SSE-NEXT: movl %esi, %ebx
; SSE-NEXT: movzwl %di, %edi
; SSE-NEXT: callq __gnu_h2f_ieee
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; SSE-NEXT: cvttss2si %xmm0, %ebp
; SSE-NEXT: movzwl %bx, %edi
; SSE-NEXT: callq __gnu_h2f_ieee
; SSE-NEXT: cvttss2si %xmm0, %eax
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: movd %ebp, %xmm1
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: movq {{.*#+}} xmm0 = xmm1[0],zero
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; SSE-NEXT: addq $8, %rsp
; SSE-NEXT: popq %rbx
; SSE-NEXT: popq %rbp
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_2f16_to_4i32:
; VEX: # %bb.0:
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; VEX-NEXT: pushq %rbp
; VEX-NEXT: pushq %rbx
; VEX-NEXT: pushq %rax
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; VEX-NEXT: movl %esi, %ebx
; VEX-NEXT: movzwl %di, %edi
; VEX-NEXT: callq __gnu_h2f_ieee
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; VEX-NEXT: vcvttss2si %xmm0, %ebp
; VEX-NEXT: movzwl %bx, %edi
; VEX-NEXT: callq __gnu_h2f_ieee
; VEX-NEXT: vcvttss2si %xmm0, %eax
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; VEX-NEXT: vmovd %eax, %xmm0
; VEX-NEXT: vmovd %ebp, %xmm1
; VEX-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; VEX-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; VEX-NEXT: addq $8, %rsp
; VEX-NEXT: popq %rbx
; VEX-NEXT: popq %rbp
; VEX-NEXT: retq
;
; AVX512-LABEL: fptosi_2f16_to_4i32:
; AVX512: # %bb.0:
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; AVX512-NEXT: movswl %di, %eax
; AVX512-NEXT: vmovd %eax, %xmm0
; AVX512-NEXT: vcvtph2ps %xmm0, %xmm0
; AVX512-NEXT: vcvttss2si %xmm0, %eax
[LegalizeTypes][X86] Add a new strategy for type legalizing f16 type that softens it to i16, but promotes to f32 around arithmetic ops. This is based on this llvm-dev thread http://lists.llvm.org/pipermail/llvm-dev/2019-December/137521.html The current strategy for f16 is to promote type to float every except where the specific width is required like loads, stores, and bitcasts. This results in rounding occurring in odd places instead of immediately after arithmetic operations. This interacts in weird ways with the __fp16 type in clang which is a storage only type where arithmetic is always promoted to float. InstCombine can remove some fpext/fptruncs around such arithmetic and turn it into arithmetic on half. This wouldn't be so bad if SelectionDAG was able to put those fpext/fpround back in when it promotes. It is also not obvious how to handle to make the existing strategy work with STRICT fp. We need to use STRICT versions of the conversions which require chain operands. But if the conversions are created for a bitcast, there is no place to get an appropriate chain from. This patch implements a different strategy where conversions are emitted directly around arithmetic operations. And otherwise its passed around as an i16 including in arguments and return values. This can result in more conversions between arithmetic operations, but is closer to matching the IR the frontend generates for __fp16. And it will allow us to use the chain from constrained arithmetic nodes to link the STRICT_FP_TO_FP16/STRICT_FP16_TO_FP that will need to be added. I've set it up so that each target can opt into the new behavior. Converting all the targets myself was more than I was able to handle. Differential Revision: https://reviews.llvm.org/D73749
2020-02-01 14:42:07 +08:00
; AVX512-NEXT: movswl %si, %ecx
; AVX512-NEXT: vmovd %ecx, %xmm0
; AVX512-NEXT: vcvtph2ps %xmm0, %xmm0
; AVX512-NEXT: vcvttss2si %xmm0, %ecx
; AVX512-NEXT: vmovd %ecx, %xmm0
; AVX512-NEXT: vmovd %eax, %xmm1
; AVX512-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; AVX512-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX512-NEXT: retq
%cvt = fptosi <2 x half> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %ext
}
define <4 x i32> @fptosi_2f80_to_4i32(<2 x x86_fp80> %a) nounwind {
; SSE-LABEL: fptosi_2f80_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: fldt {{[0-9]+}}(%rsp)
; SSE-NEXT: fldt {{[0-9]+}}(%rsp)
; SSE-NEXT: fnstcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax
; SSE-NEXT: orl $3072, %eax # imm = 0xC00
; SSE-NEXT: movw %ax, -{{[0-9]+}}(%rsp)
; SSE-NEXT: fldcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: fistpl -{{[0-9]+}}(%rsp)
; SSE-NEXT: fldcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: fnstcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax
; SSE-NEXT: orl $3072, %eax # imm = 0xC00
; SSE-NEXT: movw %ax, -{{[0-9]+}}(%rsp)
; SSE-NEXT: fldcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: fistpl -{{[0-9]+}}(%rsp)
; SSE-NEXT: fldcw -{{[0-9]+}}(%rsp)
; SSE-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
; SSE-NEXT: movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: movq {{.*#+}} xmm0 = xmm1[0],zero
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f80_to_4i32:
; AVX: # %bb.0:
; AVX-NEXT: fldt {{[0-9]+}}(%rsp)
; AVX-NEXT: fldt {{[0-9]+}}(%rsp)
; AVX-NEXT: fisttpl -{{[0-9]+}}(%rsp)
; AVX-NEXT: fisttpl -{{[0-9]+}}(%rsp)
; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
; AVX-NEXT: vmovd {{.*#+}} xmm1 = mem[0],zero,zero,zero
; AVX-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; AVX-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX-NEXT: retq
%cvt = fptosi <2 x x86_fp80> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %ext
}
define <4 x i32> @fptosi_2f128_to_4i32(<2 x fp128> %a) nounwind {
; SSE-LABEL: fptosi_2f128_to_4i32:
; SSE: # %bb.0:
; SSE-NEXT: pushq %rbx
; SSE-NEXT: subq $16, %rsp
; SSE-NEXT: movaps %xmm1, (%rsp) # 16-byte Spill
; SSE-NEXT: callq __fixtfsi
; SSE-NEXT: movl %eax, %ebx
; SSE-NEXT: movaps (%rsp), %xmm0 # 16-byte Reload
; SSE-NEXT: callq __fixtfsi
; SSE-NEXT: movd %eax, %xmm0
; SSE-NEXT: movd %ebx, %xmm1
; SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; SSE-NEXT: movq {{.*#+}} xmm0 = xmm1[0],zero
; SSE-NEXT: addq $16, %rsp
; SSE-NEXT: popq %rbx
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f128_to_4i32:
; AVX: # %bb.0:
; AVX-NEXT: pushq %rbx
; AVX-NEXT: subq $16, %rsp
; AVX-NEXT: vmovaps %xmm1, (%rsp) # 16-byte Spill
; AVX-NEXT: callq __fixtfsi
; AVX-NEXT: movl %eax, %ebx
; AVX-NEXT: vmovaps (%rsp), %xmm0 # 16-byte Reload
; AVX-NEXT: callq __fixtfsi
; AVX-NEXT: vmovd %eax, %xmm0
; AVX-NEXT: vmovd %ebx, %xmm1
; AVX-NEXT: vpunpckldq {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
; AVX-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero
; AVX-NEXT: addq $16, %rsp
; AVX-NEXT: popq %rbx
; AVX-NEXT: retq
%cvt = fptosi <2 x fp128> %a to <2 x i32>
%ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %ext
}
define <2 x i8> @fptosi_2f32_to_2i8(<2 x float> %a) {
; SSE-LABEL: fptosi_2f32_to_2i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f32_to_2i8:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,4,u,u,u,u,u,u,u,u,u,u,u,u,u,u]
; AVX-NEXT: retq
%cvt = fptosi <2 x float> %a to <2 x i8>
ret <2 x i8> %cvt
}
define <2 x i16> @fptosi_2f32_to_2i16(<2 x float> %a) {
; SSE-LABEL: fptosi_2f32_to_2i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f32_to_2i16:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: vpshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; AVX-NEXT: retq
%cvt = fptosi <2 x float> %a to <2 x i16>
ret <2 x i16> %cvt
}
define <2 x i8> @fptoui_2f32_to_2i8(<2 x float> %a) {
; SSE-LABEL: fptoui_2f32_to_2i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: pand {{.*}}(%rip), %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f32_to_2i8:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,4,u,u,u,u,u,u,u,u,u,u,u,u,u,u]
; AVX-NEXT: retq
%cvt = fptoui <2 x float> %a to <2 x i8>
ret <2 x i8> %cvt
}
define <2 x i16> @fptoui_2f32_to_2i16(<2 x float> %a) {
; SSE-LABEL: fptoui_2f32_to_2i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f32_to_2i16:
; AVX: # %bb.0:
; AVX-NEXT: vcvttps2dq %xmm0, %xmm0
; AVX-NEXT: vpshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; AVX-NEXT: retq
%cvt = fptoui <2 x float> %a to <2 x i16>
ret <2 x i16> %cvt
}
define <2 x i8> @fptosi_2f64_to_2i8(<2 x double> %a) {
; SSE-LABEL: fptosi_2f64_to_2i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: andpd {{.*}}(%rip), %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_2i8:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,4,u,u,u,u,u,u,u,u,u,u,u,u,u,u]
; AVX-NEXT: retq
%cvt = fptosi <2 x double> %a to <2 x i8>
ret <2 x i8> %cvt
}
define <2 x i16> @fptosi_2f64_to_2i16(<2 x double> %a) {
; SSE-LABEL: fptosi_2f64_to_2i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; SSE-NEXT: retq
;
; AVX-LABEL: fptosi_2f64_to_2i16:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: vpshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; AVX-NEXT: retq
%cvt = fptosi <2 x double> %a to <2 x i16>
ret <2 x i16> %cvt
}
define <2 x i8> @fptoui_2f64_to_2i8(<2 x double> %a) {
; SSE-LABEL: fptoui_2f64_to_2i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: andpd {{.*}}(%rip), %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: packuswb %xmm0, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f64_to_2i8:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,4,u,u,u,u,u,u,u,u,u,u,u,u,u,u]
; AVX-NEXT: retq
%cvt = fptoui <2 x double> %a to <2 x i8>
ret <2 x i8> %cvt
}
define <2 x i16> @fptoui_2f64_to_2i16(<2 x double> %a) {
; SSE-LABEL: fptoui_2f64_to_2i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; SSE-NEXT: retq
;
; AVX-LABEL: fptoui_2f64_to_2i16:
; AVX: # %bb.0:
; AVX-NEXT: vcvttpd2dq %xmm0, %xmm0
; AVX-NEXT: vpshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; AVX-NEXT: retq
%cvt = fptoui <2 x double> %a to <2 x i16>
ret <2 x i16> %cvt
}
define <8 x i16> @fptosi_8f64_to_8i16(<8 x double> %a) {
; SSE-LABEL: fptosi_8f64_to_8i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm3, %xmm3
; SSE-NEXT: cvttpd2dq %xmm2, %xmm2
; SSE-NEXT: unpcklpd {{.*#+}} xmm2 = xmm2[0],xmm3[0]
; SSE-NEXT: cvttpd2dq %xmm1, %xmm1
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; SSE-NEXT: packssdw %xmm2, %xmm0
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_8f64_to_8i16:
; VEX: # %bb.0:
; VEX-NEXT: vcvttpd2dq %ymm1, %xmm1
; VEX-NEXT: vcvttpd2dq %ymm0, %xmm0
; VEX-NEXT: vpackssdw %xmm1, %xmm0, %xmm0
; VEX-NEXT: vzeroupper
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptosi_8f64_to_8i16:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512F-NEXT: vpmovdw %zmm0, %ymm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_8f64_to_8i16:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512VL-NEXT: vpmovdw %ymm0, %xmm0
; AVX512VL-NEXT: vzeroupper
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_8f64_to_8i16:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512DQ-NEXT: vpmovdw %zmm0, %ymm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_8f64_to_8i16:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512VLDQ-NEXT: vpmovdw %ymm0, %xmm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%cvt = fptosi <8 x double> %a to <8 x i16>
ret <8 x i16> %cvt
}
define <8 x i16> @fptoui_8f64_to_8i16(<8 x double> %a) {
; SSE-LABEL: fptoui_8f64_to_8i16:
; SSE: # %bb.0:
; SSE-NEXT: cvttpd2dq %xmm3, %xmm3
; SSE-NEXT: cvttpd2dq %xmm2, %xmm2
; SSE-NEXT: unpcklpd {{.*#+}} xmm2 = xmm2[0],xmm3[0]
; SSE-NEXT: pshuflw {{.*#+}} xmm2 = xmm2[0,2,2,3,4,5,6,7]
; SSE-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,4,6,6,7]
; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3]
; SSE-NEXT: cvttpd2dq %xmm1, %xmm1
; SSE-NEXT: cvttpd2dq %xmm0, %xmm0
; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
; SSE-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,6,6,7]
; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
; SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
; SSE-NEXT: retq
;
; VEX-LABEL: fptoui_8f64_to_8i16:
; VEX: # %bb.0:
; VEX-NEXT: vcvttpd2dq %ymm1, %xmm1
; VEX-NEXT: vcvttpd2dq %ymm0, %xmm0
; VEX-NEXT: vpackusdw %xmm1, %xmm0, %xmm0
; VEX-NEXT: vzeroupper
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptoui_8f64_to_8i16:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512F-NEXT: vpmovdw %zmm0, %ymm0
; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_8f64_to_8i16:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512VL-NEXT: vpmovdw %ymm0, %xmm0
; AVX512VL-NEXT: vzeroupper
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_8f64_to_8i16:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512DQ-NEXT: vpmovdw %zmm0, %ymm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_8f64_to_8i16:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttpd2dq %zmm0, %ymm0
; AVX512VLDQ-NEXT: vpmovdw %ymm0, %xmm0
; AVX512VLDQ-NEXT: vzeroupper
; AVX512VLDQ-NEXT: retq
%cvt = fptoui <8 x double> %a to <8 x i16>
ret <8 x i16> %cvt
}
define <16 x i8> @fptosi_16f32_to_16i8(<16 x float> %a) {
; SSE-LABEL: fptosi_16f32_to_16i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm3, %xmm3
; SSE-NEXT: cvttps2dq %xmm2, %xmm2
; SSE-NEXT: packssdw %xmm3, %xmm2
; SSE-NEXT: cvttps2dq %xmm1, %xmm1
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: packssdw %xmm1, %xmm0
; SSE-NEXT: packsswb %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptosi_16f32_to_16i8:
; AVX1: # %bb.0:
; AVX1-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
; AVX1-NEXT: vpackssdw %xmm2, %xmm1, %xmm1
; AVX1-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2
; AVX1-NEXT: vpackssdw %xmm2, %xmm0, %xmm0
; AVX1-NEXT: vpacksswb %xmm1, %xmm0, %xmm0
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptosi_16f32_to_16i8:
; AVX2: # %bb.0:
; AVX2-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm2
; AVX2-NEXT: vpackssdw %xmm2, %xmm1, %xmm1
; AVX2-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2
; AVX2-NEXT: vpackssdw %xmm2, %xmm0, %xmm0
; AVX2-NEXT: vpacksswb %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: fptosi_16f32_to_16i8:
; AVX512: # %bb.0:
; AVX512-NEXT: vcvttps2dq %zmm0, %zmm0
; AVX512-NEXT: vpmovdb %zmm0, %xmm0
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%cvt = fptosi <16 x float> %a to <16 x i8>
ret <16 x i8> %cvt
}
define <16 x i8> @fptoui_16f32_to_16i8(<16 x float> %a) {
; SSE-LABEL: fptoui_16f32_to_16i8:
; SSE: # %bb.0:
; SSE-NEXT: cvttps2dq %xmm3, %xmm3
; SSE-NEXT: cvttps2dq %xmm2, %xmm2
; SSE-NEXT: packssdw %xmm3, %xmm2
; SSE-NEXT: cvttps2dq %xmm1, %xmm1
; SSE-NEXT: cvttps2dq %xmm0, %xmm0
; SSE-NEXT: packssdw %xmm1, %xmm0
; SSE-NEXT: packuswb %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX1-LABEL: fptoui_16f32_to_16i8:
; AVX1: # %bb.0:
; AVX1-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
; AVX1-NEXT: vpackssdw %xmm2, %xmm1, %xmm1
; AVX1-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2
; AVX1-NEXT: vpackssdw %xmm2, %xmm0, %xmm0
; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0
; AVX1-NEXT: vzeroupper
; AVX1-NEXT: retq
;
; AVX2-LABEL: fptoui_16f32_to_16i8:
; AVX2: # %bb.0:
; AVX2-NEXT: vcvttps2dq %ymm1, %ymm1
; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm2
; AVX2-NEXT: vpackssdw %xmm2, %xmm1, %xmm1
; AVX2-NEXT: vcvttps2dq %ymm0, %ymm0
; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2
; AVX2-NEXT: vpackssdw %xmm2, %xmm0, %xmm0
; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
;
; AVX512-LABEL: fptoui_16f32_to_16i8:
; AVX512: # %bb.0:
; AVX512-NEXT: vcvttps2dq %zmm0, %zmm0
; AVX512-NEXT: vpmovdb %zmm0, %xmm0
; AVX512-NEXT: vzeroupper
; AVX512-NEXT: retq
%cvt = fptoui <16 x float> %a to <16 x i8>
ret <16 x i8> %cvt
}
define <2 x i64> @fptosi_2f32_to_2i64_load(<2 x float>* %x) {
; SSE-LABEL: fptosi_2f32_to_2i64_load:
; SSE: # %bb.0:
; SSE-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm0
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,1,2,3]
; SSE-NEXT: cvttss2si %xmm1, %rax
; SSE-NEXT: movq %rax, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; SSE-NEXT: retq
;
; VEX-LABEL: fptosi_2f32_to_2i64_load:
; VEX: # %bb.0:
; VEX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; VEX-NEXT: vcvttss2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm1
; VEX-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; VEX-NEXT: vcvttss2si %xmm0, %rax
; VEX-NEXT: vmovq %rax, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptosi_2f32_to_2i64_load:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2si %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptosi_2f32_to_2i64_load:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2si %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptosi_2f32_to_2i64_load:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512DQ-NEXT: vcvttps2qq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptosi_2f32_to_2i64_load:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2qq (%rdi), %xmm0
; AVX512VLDQ-NEXT: retq
%a = load <2 x float>, <2 x float>* %x
%b = fptosi <2 x float> %a to <2 x i64>
ret <2 x i64> %b
}
define <2 x i64> @fptoui_2f32_to_2i64_load(<2 x float>* %x) {
; SSE-LABEL: fptoui_2f32_to_2i64_load:
; SSE: # %bb.0:
; SSE-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
; SSE-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
; SSE-NEXT: movaps %xmm1, %xmm0
; SSE-NEXT: subss %xmm2, %xmm0
; SSE-NEXT: cvttss2si %xmm0, %rax
; SSE-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm1, %rdx
; SSE-NEXT: ucomiss %xmm2, %xmm1
; SSE-NEXT: cmovaeq %rax, %rdx
; SSE-NEXT: movq %rdx, %xmm0
; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,1,2,3]
; SSE-NEXT: movaps %xmm1, %xmm3
; SSE-NEXT: subss %xmm2, %xmm3
; SSE-NEXT: cvttss2si %xmm3, %rax
; SSE-NEXT: xorq %rcx, %rax
; SSE-NEXT: cvttss2si %xmm1, %rcx
; SSE-NEXT: ucomiss %xmm2, %xmm1
; SSE-NEXT: cmovaeq %rax, %rcx
; SSE-NEXT: movq %rcx, %xmm1
; SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; SSE-NEXT: retq
;
; VEX-LABEL: fptoui_2f32_to_2i64_load:
; VEX: # %bb.0:
; VEX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; VEX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; VEX-NEXT: vsubss %xmm1, %xmm0, %xmm2
; VEX-NEXT: vcvttss2si %xmm2, %rax
; VEX-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rdx
; VEX-NEXT: vucomiss %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rdx
; VEX-NEXT: vmovq %rdx, %xmm2
; VEX-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; VEX-NEXT: vsubss %xmm1, %xmm0, %xmm3
; VEX-NEXT: vcvttss2si %xmm3, %rax
; VEX-NEXT: xorq %rcx, %rax
; VEX-NEXT: vcvttss2si %xmm0, %rcx
; VEX-NEXT: vucomiss %xmm1, %xmm0
; VEX-NEXT: cmovaeq %rax, %rcx
; VEX-NEXT: vmovq %rcx, %xmm0
; VEX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm2[0],xmm0[0]
; VEX-NEXT: retq
;
; AVX512F-LABEL: fptoui_2f32_to_2i64_load:
; AVX512F: # %bb.0:
; AVX512F-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm1
; AVX512F-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512F-NEXT: vcvttss2usi %xmm0, %rax
; AVX512F-NEXT: vmovq %rax, %xmm0
; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: fptoui_2f32_to_2i64_load:
; AVX512VL: # %bb.0:
; AVX512VL-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm1
; AVX512VL-NEXT: vmovshdup {{.*#+}} xmm0 = xmm0[1,1,3,3]
; AVX512VL-NEXT: vcvttss2usi %xmm0, %rax
; AVX512VL-NEXT: vmovq %rax, %xmm0
; AVX512VL-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; AVX512VL-NEXT: retq
;
; AVX512DQ-LABEL: fptoui_2f32_to_2i64_load:
; AVX512DQ: # %bb.0:
; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
; AVX512DQ-NEXT: vcvttps2uqq %ymm0, %zmm0
; AVX512DQ-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
; AVX512DQ-NEXT: vzeroupper
; AVX512DQ-NEXT: retq
;
; AVX512VLDQ-LABEL: fptoui_2f32_to_2i64_load:
; AVX512VLDQ: # %bb.0:
; AVX512VLDQ-NEXT: vcvttps2uqq (%rdi), %xmm0
; AVX512VLDQ-NEXT: retq
%a = load <2 x float>, <2 x float>* %x
%b = fptoui <2 x float> %a to <2 x i64>
ret <2 x i64> %b
}