Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -S -instcombine < %s | FileCheck %s
      2 
      3 declare double @llvm.fabs.f64(double) nounwind readnone
      4 
      5 define i1 @test1(float %x, float %y) nounwind {
      6   %ext1 = fpext float %x to double
      7   %ext2 = fpext float %y to double
      8   %cmp = fcmp ogt double %ext1, %ext2
      9   ret i1 %cmp
     10 ; CHECK-LABEL: @test1(
     11 ; CHECK-NEXT: fcmp ogt float %x, %y
     12 }
     13 
     14 define i1 @test2(float %a) nounwind {
     15   %ext = fpext float %a to double
     16   %cmp = fcmp ogt double %ext, 1.000000e+00
     17   ret i1 %cmp
     18 ; CHECK-LABEL: @test2(
     19 ; CHECK-NEXT: fcmp ogt float %a, 1.0
     20 }
     21 
     22 define i1 @test3(float %a) nounwind {
     23   %ext = fpext float %a to double
     24   %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float.
     25   ret i1 %cmp
     26 ; CHECK-LABEL: @test3(
     27 ; CHECK-NEXT: fpext float %a to double
     28 }
     29 
     30 define i1 @test4(float %a) nounwind {
     31   %ext = fpext float %a to double
     32   %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float.
     33   ret i1 %cmp
     34 ; CHECK-LABEL: @test4(
     35 ; CHECK-NEXT: fpext float %a to double
     36 }
     37 
     38 define i1 @test5(float %a) nounwind {
     39   %neg = fsub float -0.000000e+00, %a
     40   %cmp = fcmp ogt float %neg, 1.000000e+00
     41   ret i1 %cmp
     42 ; CHECK-LABEL: @test5(
     43 ; CHECK-NEXT: fcmp olt float %a, -1.0
     44 }
     45 
     46 define i1 @test6(float %x, float %y) nounwind {
     47   %neg1 = fsub float -0.000000e+00, %x
     48   %neg2 = fsub float -0.000000e+00, %y
     49   %cmp = fcmp olt float %neg1, %neg2
     50   ret i1 %cmp
     51 ; CHECK-LABEL: @test6(
     52 ; CHECK-NEXT: fcmp ogt float %x, %y
     53 }
     54 
     55 define i1 @test7(float %x) nounwind readnone ssp noredzone {
     56   %ext = fpext float %x to ppc_fp128
     57   %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000
     58   ret i1 %cmp
     59 ; CHECK-LABEL: @test7(
     60 ; CHECK-NEXT: fcmp ogt float %x, 0.000000e+00
     61 }
     62 
     63 define float @test8(float %x) nounwind readnone optsize ssp {
     64   %conv = fpext float %x to double
     65   %cmp = fcmp olt double %conv, 0.000000e+00
     66   %conv1 = zext i1 %cmp to i32
     67   %conv2 = sitofp i32 %conv1 to float
     68   ret float %conv2
     69 ; Float comparison to zero shouldn't cast to double.
     70 ; CHECK-LABEL: @test8(
     71 ; CHECK-NEXT: fcmp olt float %x, 0.000000e+00
     72 }
     73 
     74 declare double @fabs(double) nounwind readnone
     75 
     76 define i32 @test9(double %a) nounwind {
     77   %call = tail call double @fabs(double %a) nounwind
     78   %cmp = fcmp olt double %call, 0.000000e+00
     79   %conv = zext i1 %cmp to i32
     80   ret i32 %conv
     81 ; CHECK-LABEL: @test9(
     82 ; CHECK-NOT: fabs
     83 ; CHECK: ret i32 0
     84 }
     85 
     86 define i32 @test9_intrinsic(double %a) nounwind {
     87   %call = tail call double @llvm.fabs.f64(double %a) nounwind
     88   %cmp = fcmp olt double %call, 0.000000e+00
     89   %conv = zext i1 %cmp to i32
     90   ret i32 %conv
     91 ; CHECK-LABEL: @test9_intrinsic(
     92 ; CHECK-NOT: fabs
     93 ; CHECK: ret i32 0
     94 }
     95 
     96 define i32 @test10(double %a) nounwind {
     97   %call = tail call double @fabs(double %a) nounwind
     98   %cmp = fcmp ole double %call, 0.000000e+00
     99   %conv = zext i1 %cmp to i32
    100   ret i32 %conv
    101 ; CHECK-LABEL: @test10(
    102 ; CHECK-NOT: fabs
    103 ; CHECK: fcmp oeq double %a, 0.000000e+00
    104 }
    105 
    106 define i32 @test10_intrinsic(double %a) nounwind {
    107   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    108   %cmp = fcmp ole double %call, 0.000000e+00
    109   %conv = zext i1 %cmp to i32
    110   ret i32 %conv
    111 ; CHECK-LABEL: @test10_intrinsic(
    112 ; CHECK-NOT: fabs
    113 ; CHECK: fcmp oeq double %a, 0.000000e+00
    114 }
    115 
    116 define i32 @test11(double %a) nounwind {
    117   %call = tail call double @fabs(double %a) nounwind
    118   %cmp = fcmp ogt double %call, 0.000000e+00
    119   %conv = zext i1 %cmp to i32
    120   ret i32 %conv
    121 ; CHECK-LABEL: @test11(
    122 ; CHECK-NOT: fabs
    123 ; CHECK: fcmp one double %a, 0.000000e+00
    124 }
    125 
    126 define i32 @test11_intrinsic(double %a) nounwind {
    127   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    128   %cmp = fcmp ogt double %call, 0.000000e+00
    129   %conv = zext i1 %cmp to i32
    130   ret i32 %conv
    131 ; CHECK-LABEL: @test11_intrinsic(
    132 ; CHECK-NOT: fabs
    133 ; CHECK: fcmp one double %a, 0.000000e+00
    134 }
    135 
    136 define i32 @test12(double %a) nounwind {
    137   %call = tail call double @fabs(double %a) nounwind
    138   %cmp = fcmp oge double %call, 0.000000e+00
    139   %conv = zext i1 %cmp to i32
    140   ret i32 %conv
    141 ; CHECK-LABEL: @test12(
    142 ; CHECK-NOT: fabs
    143 ; CHECK: fcmp ord double %a, 0.000000e+00
    144 }
    145 
    146 define i32 @test12_intrinsic(double %a) nounwind {
    147   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    148   %cmp = fcmp oge double %call, 0.000000e+00
    149   %conv = zext i1 %cmp to i32
    150   ret i32 %conv
    151 ; CHECK-LABEL: @test12_intrinsic(
    152 ; CHECK-NOT: fabs
    153 ; CHECK: fcmp ord double %a, 0.000000e+00
    154 }
    155 
    156 define i32 @test13(double %a) nounwind {
    157   %call = tail call double @fabs(double %a) nounwind
    158   %cmp = fcmp une double %call, 0.000000e+00
    159   %conv = zext i1 %cmp to i32
    160   ret i32 %conv
    161 ; CHECK-LABEL: @test13(
    162 ; CHECK-NOT: fabs
    163 ; CHECK: fcmp une double %a, 0.000000e+00
    164 }
    165 
    166 define i32 @test13_intrinsic(double %a) nounwind {
    167   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    168   %cmp = fcmp une double %call, 0.000000e+00
    169   %conv = zext i1 %cmp to i32
    170   ret i32 %conv
    171 ; CHECK-LABEL: @test13_intrinsic(
    172 ; CHECK-NOT: fabs
    173 ; CHECK: fcmp une double %a, 0.000000e+00
    174 }
    175 
    176 define i32 @test14(double %a) nounwind {
    177   %call = tail call double @fabs(double %a) nounwind
    178   %cmp = fcmp oeq double %call, 0.000000e+00
    179   %conv = zext i1 %cmp to i32
    180   ret i32 %conv
    181 ; CHECK-LABEL: @test14(
    182 ; CHECK-NOT: fabs
    183 ; CHECK: fcmp oeq double %a, 0.000000e+00
    184 }
    185 
    186 define i32 @test14_intrinsic(double %a) nounwind {
    187   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    188   %cmp = fcmp oeq double %call, 0.000000e+00
    189   %conv = zext i1 %cmp to i32
    190   ret i32 %conv
    191 ; CHECK-LABEL: @test14_intrinsic(
    192 ; CHECK-NOT: fabs
    193 ; CHECK: fcmp oeq double %a, 0.000000e+00
    194 }
    195 
    196 define i32 @test15(double %a) nounwind {
    197   %call = tail call double @fabs(double %a) nounwind
    198   %cmp = fcmp one double %call, 0.000000e+00
    199   %conv = zext i1 %cmp to i32
    200   ret i32 %conv
    201 ; CHECK-LABEL: @test15(
    202 ; CHECK-NOT: fabs
    203 ; CHECK: fcmp one double %a, 0.000000e+00
    204 }
    205 
    206 define i32 @test15_intrinsic(double %a) nounwind {
    207   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    208   %cmp = fcmp one double %call, 0.000000e+00
    209   %conv = zext i1 %cmp to i32
    210   ret i32 %conv
    211 ; CHECK-LABEL: @test15_intrinsic(
    212 ; CHECK-NOT: fabs
    213 ; CHECK: fcmp one double %a, 0.000000e+00
    214 }
    215 
    216 define i32 @test16(double %a) nounwind {
    217   %call = tail call double @fabs(double %a) nounwind
    218   %cmp = fcmp ueq double %call, 0.000000e+00
    219   %conv = zext i1 %cmp to i32
    220   ret i32 %conv
    221 ; CHECK-LABEL: @test16(
    222 ; CHECK-NOT: fabs
    223 ; CHECK: fcmp ueq double %a, 0.000000e+00
    224 }
    225 
    226 define i32 @test16_intrinsic(double %a) nounwind {
    227   %call = tail call double @llvm.fabs.f64(double %a) nounwind
    228   %cmp = fcmp ueq double %call, 0.000000e+00
    229   %conv = zext i1 %cmp to i32
    230   ret i32 %conv
    231 ; CHECK-LABEL: @test16_intrinsic(
    232 ; CHECK-NOT: fabs
    233 ; CHECK: fcmp ueq double %a, 0.000000e+00
    234 }
    235 
    236 ; Don't crash.
    237 define i32 @test17(double %a, double (double)* %p) nounwind {
    238   %call = tail call double %p(double %a) nounwind
    239   %cmp = fcmp ueq double %call, 0.000000e+00
    240   %conv = zext i1 %cmp to i32
    241   ret i32 %conv
    242 }
    243 
    244 ; Can fold fcmp with undef on one side by choosing NaN for the undef
    245 define i32 @test18_undef_unordered(float %a) nounwind {
    246 ; CHECK-LABEL: @test18_undef_unordered
    247 ; CHECK: ret i32 1
    248   %cmp = fcmp ueq float %a, undef
    249   %conv = zext i1 %cmp to i32
    250   ret i32 %conv
    251 }
    252 ; Can fold fcmp with undef on one side by choosing NaN for the undef
    253 define i32 @test18_undef_ordered(float %a) nounwind {
    254 ; CHECK-LABEL: @test18_undef_ordered
    255 ; CHECK: ret i32 0
    256   %cmp = fcmp oeq float %a, undef
    257   %conv = zext i1 %cmp to i32
    258   ret i32 %conv
    259 }
    260 
    261 ; Can fold fcmp with undef on both side
    262 ;   fcmp u_pred undef, undef -> true
    263 ;   fcmp o_pred undef, undef -> false
    264 ; because whatever you choose for the first undef
    265 ; you can choose NaN for the other undef
    266 define i1 @test19_undef_unordered() nounwind {
    267 ; CHECK-LABEL: @test19_undef
    268 ; CHECK: ret i1 true
    269   %cmp = fcmp ueq float undef, undef
    270   ret i1 %cmp
    271 }
    272 define i1 @test19_undef_ordered() nounwind {
    273 ; CHECK-LABEL: @test19_undef
    274 ; CHECK: ret i1 false
    275   %cmp = fcmp oeq float undef, undef
    276   ret i1 %cmp
    277 }
    278