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