1 ; Check that scalar FP conversions to signed and unsigned int64 are using 2 ; reasonable sequences, across platforms and target switches. 3 ; 4 ; The signed case is straight forward, and the tests here basically 5 ; ensure successful compilation (f80 with avx512 was broken at one point). 6 ; 7 ; For the unsigned case there are many possible sequences, so to avoid 8 ; a fragile test we just check for the presence of a few key instructions. 9 ; AVX512 on Intel64 can use vcvtts[ds]2usi directly for float and double. 10 ; Otherwise the sequence will involve an FP subtract (fsub, subss or subsd), 11 ; and a truncating conversion (cvtts[ds]2si, fisttp, or fnstcw+fist). When 12 ; both a subtract and fnstcw are needed, they can occur in either order. 13 ; 14 ; The interesting subtargets are AVX512F (vcvtts[ds]2usi), SSE3 (fisttp), 15 ; SSE2 (cvtts[ds]2si) and vanilla X87 (fnstcw+fist, 32-bit only). 16 ; 17 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_32 18 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_32 19 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_64 20 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512_64 21 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_32 22 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_32 23 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_64 24 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse3 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE3_64 25 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_32 26 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_32 27 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_64 28 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse2 | FileCheck %s --check-prefix=CHECK --check-prefix=SSE2_64 29 ; RUN: llc < %s -mtriple=i386-pc-windows-msvc -mattr=-sse | FileCheck %s --check-prefix=CHECK --check-prefix=X87 30 ; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -mattr=-sse | FileCheck %s --check-prefix=CHECK --check-prefix=X87 31 32 ; CHECK-LABEL: f_to_u64 33 ; X87-DAG: fsub 34 ; X87-DAG: fnstcw 35 ; X87: fist 36 ; SSE2_32-DAG: {{subss|fsub}} 37 ; SSE2_32-DAG: fnstcw 38 ; SSE2_32: fist 39 ; SSE2_64: subss 40 ; SSE2_64: cvttss2si 41 ; SSE3_32: {{subss|fsub}} 42 ; SSE3_32: fistt 43 ; SSE3_64: subss 44 ; SSE3_64: cvttss2si 45 ; AVX512_32: {{subss|fsub}} 46 ; AVX512_32: fistt 47 ; AVX512_64: vcvttss2usi 48 ; CHECK: ret 49 define i64 @f_to_u64(float %a) nounwind { 50 %r = fptoui float %a to i64 51 ret i64 %r 52 } 53 54 ; CHECK-LABEL: f_to_s64 55 ; X87: fnstcw 56 ; X87: fist 57 ; SSE2_32: fnstcw 58 ; SSE2_32: fist 59 ; SSE2_64: cvttss2si 60 ; SSE3_32: fistt 61 ; SSE3_64: cvttss2si 62 ; AVX512_32: fistt 63 ; AVX512_64: vcvttss2si 64 ; CHECK: ret 65 define i64 @f_to_s64(float %a) nounwind { 66 %r = fptosi float %a to i64 67 ret i64 %r 68 } 69 70 ; CHECK-LABEL: d_to_u64 71 ; X87-DAG: fsub 72 ; X87-DAG: fnstcw 73 ; X87: fist 74 ; SSE2_32-DAG: {{subsd|fsub}} 75 ; SSE2_32-DAG: fnstcw 76 ; SSE2_32: fist 77 ; SSE2_64: subsd 78 ; SSE2_64: cvttsd2si 79 ; SSE3_32: {{subsd|fsub}} 80 ; SSE3_32: fistt 81 ; SSE3_64: subsd 82 ; SSE3_64: cvttsd2si 83 ; AVX512_32: {{subsd|fsub}} 84 ; AVX512_32: fistt 85 ; AVX512_64: vcvttsd2usi 86 ; CHECK: ret 87 define i64 @d_to_u64(double %a) nounwind { 88 %r = fptoui double %a to i64 89 ret i64 %r 90 } 91 92 ; CHECK-LABEL: d_to_s64 93 ; X87: fnstcw 94 ; X87: fist 95 ; SSE2_32: fnstcw 96 ; SSE2_32: fist 97 ; SSE2_64: cvttsd2si 98 ; SSE3_32: fistt 99 ; SSE3_64: cvttsd2si 100 ; AVX512_32: fistt 101 ; AVX512_64: vcvttsd2si 102 ; CHECK: ret 103 define i64 @d_to_s64(double %a) nounwind { 104 %r = fptosi double %a to i64 105 ret i64 %r 106 } 107 108 ; CHECK-LABEL: x_to_u64 109 ; CHECK-DAG: fsub 110 ; X87-DAG: fnstcw 111 ; SSE2_32-DAG: fnstcw 112 ; SSE2_64-DAG: fnstcw 113 ; CHECK: fist 114 ; CHECK: ret 115 define i64 @x_to_u64(x86_fp80 %a) nounwind { 116 %r = fptoui x86_fp80 %a to i64 117 ret i64 %r 118 } 119 120 ; CHECK-LABEL: x_to_s64 121 ; X87: fnstcw 122 ; X87: fist 123 ; SSE2_32: fnstcw 124 ; SSE2_32: fist 125 ; SSE2_64: fnstcw 126 ; SSE2_64: fist 127 ; SSE3_32: fistt 128 ; SSE3_64: fistt 129 ; AVX512_32: fistt 130 ; AVX512_64: fistt 131 ; CHECK: ret 132 define i64 @x_to_s64(x86_fp80 %a) nounwind { 133 %r = fptosi x86_fp80 %a to i64 134 ret i64 %r 135 } 136 137 ; CHECK-LABEL: t_to_u64 138 ; CHECK: __fixunstfdi 139 ; CHECK: ret 140 define i64 @t_to_u64(fp128 %a) nounwind { 141 %r = fptoui fp128 %a to i64 142 ret i64 %r 143 } 144 145 ; CHECK-LABEL: t_to_s64 146 ; CHECK: __fixtfdi 147 ; CHECK: ret 148 define i64 @t_to_s64(fp128 %a) nounwind { 149 %r = fptosi fp128 %a to i64 150 ret i64 %r 151 } 152