Home | History | Annotate | Download | only in Float2Int
      1 ; RUN: opt < %s -float2int -S | FileCheck %s
      2 
      3 ;
      4 ; Positive tests
      5 ;
      6 
      7 ; CHECK-LABEL: @simple1
      8 ; CHECK:  %1 = zext i8 %a to i32
      9 ; CHECK:  %2 = add i32 %1, 1
     10 ; CHECK:  %3 = trunc i32 %2 to i16
     11 ; CHECK:  ret i16 %3
     12 define i16 @simple1(i8 %a) {
     13   %1 = uitofp i8 %a to float
     14   %2 = fadd float %1, 1.0
     15   %3 = fptoui float %2 to i16
     16   ret i16 %3
     17 }
     18 
     19 ; CHECK-LABEL: @simple2
     20 ; CHECK:  %1 = zext i8 %a to i32
     21 ; CHECK:  %2 = sub i32 %1, 1
     22 ; CHECK:  %3 = trunc i32 %2 to i8
     23 ; CHECK:  ret i8 %3
     24 define i8 @simple2(i8 %a) {
     25   %1 = uitofp i8 %a to float
     26   %2 = fsub float %1, 1.0
     27   %3 = fptoui float %2 to i8
     28   ret i8 %3
     29 }
     30 
     31 ; CHECK-LABEL: @simple3
     32 ; CHECK:  %1 = zext i8 %a to i32
     33 ; CHECK:  %2 = sub i32 %1, 1
     34 ; CHECK:  ret i32 %2
     35 define i32 @simple3(i8 %a) {
     36   %1 = uitofp i8 %a to float
     37   %2 = fsub float %1, 1.0
     38   %3 = fptoui float %2 to i32
     39   ret i32 %3
     40 }
     41 
     42 ; CHECK-LABEL: @cmp
     43 ; CHECK:  %1 = zext i8 %a to i32
     44 ; CHECK:  %2 = zext i8 %b to i32
     45 ; CHECK:  %3 = icmp slt i32 %1, %2
     46 ; CHECK:  ret i1 %3
     47 define i1 @cmp(i8 %a, i8 %b) {
     48   %1 = uitofp i8 %a to float
     49   %2 = uitofp i8 %b to float
     50   %3 = fcmp ult float %1, %2
     51   ret i1 %3
     52 }
     53 
     54 ; CHECK-LABEL: @simple4
     55 ; CHECK:  %1 = zext i32 %a to i64
     56 ; CHECK:  %2 = add i64 %1, 1
     57 ; CHECK:  %3 = trunc i64 %2 to i32
     58 ; CHECK:  ret i32 %3
     59 define i32 @simple4(i32 %a) {
     60   %1 = uitofp i32 %a to double
     61   %2 = fadd double %1, 1.0
     62   %3 = fptoui double %2 to i32
     63   ret i32 %3
     64 }
     65 
     66 ; CHECK-LABEL: @simple5
     67 ; CHECK:  %1 = zext i8 %a to i32
     68 ; CHECK:  %2 = zext i8 %b to i32
     69 ; CHECK:  %3 = add i32 %1, 1
     70 ; CHECK:  %4 = mul i32 %3, %2
     71 ; CHECK:  ret i32 %4
     72 define i32 @simple5(i8 %a, i8 %b) {
     73   %1 = uitofp i8 %a to float
     74   %2 = uitofp i8 %b to float
     75   %3 = fadd float %1, 1.0
     76   %4 = fmul float %3, %2
     77   %5 = fptoui float %4 to i32
     78   ret i32 %5
     79 }
     80 
     81 ; The two chains don't interact - failure of one shouldn't
     82 ; cause failure of the other.
     83 
     84 ; CHECK-LABEL: @multi1
     85 ; CHECK:  %1 = zext i8 %a to i32
     86 ; CHECK:  %2 = zext i8 %b to i32
     87 ; CHECK:  %fc = uitofp i8 %c to float
     88 ; CHECK:  %x1 = add i32 %1, %2
     89 ; CHECK:  %z = fadd float %fc, %d
     90 ; CHECK:  %w = fptoui float %z to i32
     91 ; CHECK:  %r = add i32 %x1, %w
     92 ; CHECK:  ret i32 %r
     93 define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
     94   %fa = uitofp i8 %a to float
     95   %fb = uitofp i8 %b to float
     96   %fc = uitofp i8 %c to float
     97   %x = fadd float %fa, %fb
     98   %y = fptoui float %x to i32
     99   %z = fadd float %fc, %d
    100   %w = fptoui float %z to i32
    101   %r = add i32 %y, %w
    102   ret i32 %r
    103 }
    104 
    105 ; CHECK-LABEL: @simple_negzero
    106 ; CHECK:  %1 = zext i8 %a to i32
    107 ; CHECK:  %2 = add i32 %1, 0
    108 ; CHECK:  %3 = trunc i32 %2 to i16
    109 ; CHECK:  ret i16 %3
    110 define i16 @simple_negzero(i8 %a) {
    111   %1 = uitofp i8 %a to float
    112   %2 = fadd fast float %1, -0.0
    113   %3 = fptoui float %2 to i16
    114   ret i16 %3
    115 }
    116 
    117 ; CHECK-LABEL: @simple_negative
    118 ; CHECK: %1 = sext i8 %call to i32
    119 ; CHECK: %mul1 = mul i32 %1, -3
    120 ; CHECK: %2 = trunc i32 %mul1 to i8
    121 ; CHECK: %conv3 = sext i8 %2 to i32
    122 ; CHECK: ret i32 %conv3
    123 define i32 @simple_negative(i8 %call) {
    124   %conv1 = sitofp i8 %call to float
    125   %mul = fmul float %conv1, -3.000000e+00
    126   %conv2 = fptosi float %mul to i8
    127   %conv3 = sext i8 %conv2 to i32
    128   ret i32 %conv3
    129 }
    130 
    131 ;
    132 ; Negative tests
    133 ;
    134 
    135 ; CHECK-LABEL: @neg_multi1
    136 ; CHECK:  %fa = uitofp i8 %a to float
    137 ; CHECK:  %fc = uitofp i8 %c to float
    138 ; CHECK:  %x = fadd float %fa, %fc
    139 ; CHECK:  %y = fptoui float %x to i32
    140 ; CHECK:  %z = fadd float %fc, %d
    141 ; CHECK:  %w = fptoui float %z to i32
    142 ; CHECK:  %r = add i32 %y, %w
    143 ; CHECK:  ret i32 %r
    144 ; The two chains intersect, which means because one fails, no
    145 ; transform can occur.
    146 define i32 @neg_multi1(i8 %a, i8 %b, i8 %c, float %d) {
    147   %fa = uitofp i8 %a to float
    148   %fc = uitofp i8 %c to float
    149   %x = fadd float %fa, %fc
    150   %y = fptoui float %x to i32
    151   %z = fadd float %fc, %d
    152   %w = fptoui float %z to i32
    153   %r = add i32 %y, %w
    154   ret i32 %r
    155 }
    156 
    157 ; CHECK-LABEL: @neg_muld
    158 ; CHECK:  %fa = uitofp i32 %a to double
    159 ; CHECK:  %fb = uitofp i32 %b to double
    160 ; CHECK:  %mul = fmul double %fa, %fb
    161 ; CHECK:  %r = fptoui double %mul to i64
    162 ; CHECK:  ret i64 %r
    163 ; The i32 * i32 = i64, which has 64 bits, which is greater than the 52 bits
    164 ; that can be exactly represented in a double.
    165 define i64 @neg_muld(i32 %a, i32 %b) {
    166   %fa = uitofp i32 %a to double
    167   %fb = uitofp i32 %b to double
    168   %mul = fmul double %fa, %fb
    169   %r = fptoui double %mul to i64
    170   ret i64 %r
    171 }
    172 
    173 ; CHECK-LABEL: @neg_mulf
    174 ; CHECK:  %fa = uitofp i16 %a to float
    175 ; CHECK:  %fb = uitofp i16 %b to float
    176 ; CHECK:  %mul = fmul float %fa, %fb
    177 ; CHECK:  %r = fptoui float %mul to i32
    178 ; CHECK:  ret i32 %r
    179 ; The i16 * i16 = i32, which can't be represented in a float, but can in a
    180 ; double. This should fail, as the written code uses floats, not doubles so
    181 ; the original result may be inaccurate.
    182 define i32 @neg_mulf(i16 %a, i16 %b) {
    183   %fa = uitofp i16 %a to float
    184   %fb = uitofp i16 %b to float
    185   %mul = fmul float %fa, %fb
    186   %r = fptoui float %mul to i32
    187   ret i32 %r
    188 }
    189 
    190 ; CHECK-LABEL: @neg_cmp
    191 ; CHECK:  %1 = uitofp i8 %a to float
    192 ; CHECK:  %2 = uitofp i8 %b to float
    193 ; CHECK:  %3 = fcmp false float %1, %2
    194 ; CHECK:  ret i1 %3
    195 ; "false" doesn't have an icmp equivalent.
    196 define i1 @neg_cmp(i8 %a, i8 %b) {
    197   %1 = uitofp i8 %a to float
    198   %2 = uitofp i8 %b to float
    199   %3 = fcmp false float %1, %2
    200   ret i1 %3
    201 }
    202 
    203 ; CHECK-LABEL: @neg_div
    204 ; CHECK:  %1 = uitofp i8 %a to float
    205 ; CHECK:  %2 = fdiv float %1, 1.0
    206 ; CHECK:  %3 = fptoui float %2 to i16
    207 ; CHECK:  ret i16 %3
    208 ; Division isn't a supported operator.
    209 define i16 @neg_div(i8 %a) {
    210   %1 = uitofp i8 %a to float
    211   %2 = fdiv float %1, 1.0
    212   %3 = fptoui float %2 to i16
    213   ret i16 %3
    214 }
    215 
    216 ; CHECK-LABEL: @neg_remainder
    217 ; CHECK:  %1 = uitofp i8 %a to float
    218 ; CHECK:  %2 = fadd float %1, 1.2
    219 ; CHECK:  %3 = fptoui float %2 to i16
    220 ; CHECK:  ret i16 %3
    221 ; 1.2 is not an integer.
    222 define i16 @neg_remainder(i8 %a) {
    223   %1 = uitofp i8 %a to float
    224   %2 = fadd float %1, 1.25
    225   %3 = fptoui float %2 to i16
    226   ret i16 %3
    227 }
    228 
    229 ; CHECK-LABEL: @neg_toolarge
    230 ; CHECK:  %1 = uitofp i80 %a to fp128
    231 ; CHECK:  %2 = fadd fp128 %1, %1
    232 ; CHECK:  %3 = fptoui fp128 %2 to i80
    233 ; CHECK:  ret i80 %3
    234 ; i80 > i64, which is the largest bitwidth handleable by default.
    235 define i80 @neg_toolarge(i80 %a) {
    236   %1 = uitofp i80 %a to fp128
    237   %2 = fadd fp128 %1, %1
    238   %3 = fptoui fp128 %2 to i80
    239   ret i80 %3
    240 }
    241 
    242 ; CHECK-LABEL: @neg_calluser
    243 ; CHECK: sitofp
    244 ; CHECK: fcmp
    245 ; The sequence %1..%3 cannot be converted because %4 uses %2.
    246 define i32 @neg_calluser(i32 %value) {
    247   %1 = sitofp i32 %value to double
    248   %2 = fadd double %1, 1.0
    249   %3 = fcmp olt double %2, 0.000000e+00
    250   %4 = tail call double @g(double %2)
    251   %5 = fptosi double %4 to i32
    252   %6 = zext i1 %3 to i32
    253   %7 = add i32 %6, %5
    254   ret i32 %7
    255 }
    256 declare double @g(double)
    257 
    258 ; CHECK-LABEL: @neg_vector
    259 ; CHECK:  %1 = uitofp <4 x i8> %a to <4 x float>
    260 ; CHECK:  %2 = fptoui <4 x float> %1 to <4 x i16>
    261 ; CHECK:  ret <4 x i16> %2
    262 define <4 x i16> @neg_vector(<4 x i8> %a) {
    263   %1 = uitofp <4 x i8> %a to <4 x float>
    264   %2 = fptoui <4 x float> %1 to <4 x i16>
    265   ret <4 x i16> %2
    266 }
    267