Home | History | Annotate | Download | only in X86
      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