1; RUN: opt -S -instcombine < %s | FileCheck %s 2 3declare double @llvm.fabs.f64(double) nounwind readnone 4 5define 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 14define 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 22define 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 30define 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 38define 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 46define 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 55define 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 63define 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 74declare double @fabs(double) nounwind readnone 75 76define 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 86define 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 96define 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 106define 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 116define 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 126define 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 136define 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 146define 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 156define 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 166define 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 176define 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 186define 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 196define 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 206define 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 216define 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 226define 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. 237define 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 245define 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 253define 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 266define 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} 272define 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