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 49define 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 65define 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 87define 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 103define 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 115define 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 132define 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 140define 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 148define i64 @t_to_s64(fp128 %a) nounwind { 149 %r = fptosi fp128 %a to i64 150 ret i64 %r 151} 152