1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt -S -instcombine < %s | FileCheck %s 3 4 declare double @llvm.fabs.f64(double) readnone 5 6 define i1 @test1(float %x, float %y) { 7 ; CHECK-LABEL: @test1( 8 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] 9 ; CHECK-NEXT: ret i1 [[CMP]] 10 ; 11 %ext1 = fpext float %x to double 12 %ext2 = fpext float %y to double 13 %cmp = fcmp ogt double %ext1, %ext2 14 ret i1 %cmp 15 } 16 17 define i1 @test2(float %a) { 18 ; CHECK-LABEL: @test2( 19 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 1.000000e+00 20 ; CHECK-NEXT: ret i1 [[CMP]] 21 ; 22 %ext = fpext float %a to double 23 %cmp = fcmp ogt double %ext, 1.000000e+00 24 ret i1 %cmp 25 } 26 27 define i1 @test3(float %a) { 28 ; CHECK-LABEL: @test3( 29 ; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 30 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001 31 ; CHECK-NEXT: ret i1 [[CMP]] 32 ; 33 %ext = fpext float %a to double 34 %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float. 35 ret i1 %cmp 36 } 37 38 define i1 @test4(float %a) { 39 ; CHECK-LABEL: @test4( 40 ; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 41 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000 42 ; CHECK-NEXT: ret i1 [[CMP]] 43 ; 44 %ext = fpext float %a to double 45 %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float. 46 ret i1 %cmp 47 } 48 49 define i1 @fneg_constant_swap_pred(float %x) { 50 ; CHECK-LABEL: @fneg_constant_swap_pred( 51 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00 52 ; CHECK-NEXT: ret i1 [[CMP]] 53 ; 54 %neg = fsub float -0.0, %x 55 %cmp = fcmp ogt float %neg, 1.0 56 ret i1 %cmp 57 } 58 59 define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) { 60 ; CHECK-LABEL: @fneg_constant_swap_pred_vec( 61 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 62 ; CHECK-NEXT: ret <2 x i1> [[CMP]] 63 ; 64 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 65 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 66 ret <2 x i1> %cmp 67 } 68 69 define <2 x i1> @fneg_constant_swap_pred_vec_undef(<2 x float> %x) { 70 ; CHECK-LABEL: @fneg_constant_swap_pred_vec_undef( 71 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 72 ; CHECK-NEXT: ret <2 x i1> [[CMP]] 73 ; 74 %neg = fsub <2 x float> <float undef, float -0.0>, %x 75 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 76 ret <2 x i1> %cmp 77 } 78 79 define i1 @fneg_fneg_swap_pred(float %x, float %y) { 80 ; CHECK-LABEL: @fneg_fneg_swap_pred( 81 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] 82 ; CHECK-NEXT: ret i1 [[CMP]] 83 ; 84 %neg1 = fsub float -0.0, %x 85 %neg2 = fsub float -0.0, %y 86 %cmp = fcmp olt float %neg1, %neg2 87 ret i1 %cmp 88 } 89 90 define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 91 ; CHECK-LABEL: @fneg_fneg_swap_pred_vec( 92 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 93 ; CHECK-NEXT: ret <2 x i1> [[CMP]] 94 ; 95 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x 96 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y 97 %cmp = fcmp olt <2 x float> %neg1, %neg2 98 ret <2 x i1> %cmp 99 } 100 101 define <2 x i1> @fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { 102 ; CHECK-LABEL: @fneg_fneg_swap_pred_vec_undef( 103 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 104 ; CHECK-NEXT: ret <2 x i1> [[CMP]] 105 ; 106 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x 107 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y 108 %cmp = fcmp olt <2 x float> %neg1, %neg2 109 ret <2 x i1> %cmp 110 } 111 112 define i1 @test7(float %x) { 113 ; CHECK-LABEL: @test7( 114 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00 115 ; CHECK-NEXT: ret i1 [[CMP]] 116 ; 117 %ext = fpext float %x to ppc_fp128 118 %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000 119 ret i1 %cmp 120 } 121 122 define float @test8(float %x) { 123 ; CHECK-LABEL: @test8( 124 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 125 ; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float 126 ; CHECK-NEXT: ret float [[CONV2]] 127 ; 128 %conv = fpext float %x to double 129 %cmp = fcmp olt double %conv, 0.000000e+00 130 %conv1 = zext i1 %cmp to i32 131 %conv2 = sitofp i32 %conv1 to float 132 ret float %conv2 133 ; Float comparison to zero shouldn't cast to double. 134 } 135 136 declare double @fabs(double) readnone 137 138 define i32 @test9(double %a) { 139 ; CHECK-LABEL: @test9( 140 ; CHECK-NEXT: ret i32 0 141 ; 142 %call = tail call double @fabs(double %a) 143 %cmp = fcmp olt double %call, 0.000000e+00 144 %conv = zext i1 %cmp to i32 145 ret i32 %conv 146 } 147 148 define i32 @test9_intrinsic(double %a) { 149 ; CHECK-LABEL: @test9_intrinsic( 150 ; CHECK-NEXT: ret i32 0 151 ; 152 %call = tail call double @llvm.fabs.f64(double %a) 153 %cmp = fcmp olt double %call, 0.000000e+00 154 %conv = zext i1 %cmp to i32 155 ret i32 %conv 156 } 157 158 define i32 @test10(double %a) { 159 ; CHECK-LABEL: @test10( 160 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 161 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 162 ; CHECK-NEXT: ret i32 [[CONV]] 163 ; 164 %call = tail call double @fabs(double %a) 165 %cmp = fcmp ole double %call, 0.000000e+00 166 %conv = zext i1 %cmp to i32 167 ret i32 %conv 168 } 169 170 define i32 @test10_intrinsic(double %a) { 171 ; CHECK-LABEL: @test10_intrinsic( 172 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 173 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 174 ; CHECK-NEXT: ret i32 [[CONV]] 175 ; 176 %call = tail call double @llvm.fabs.f64(double %a) 177 %cmp = fcmp ole double %call, 0.000000e+00 178 %conv = zext i1 %cmp to i32 179 ret i32 %conv 180 } 181 182 define i32 @test11(double %a) { 183 ; CHECK-LABEL: @test11( 184 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 185 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 186 ; CHECK-NEXT: ret i32 [[CONV]] 187 ; 188 %call = tail call double @fabs(double %a) 189 %cmp = fcmp ogt double %call, 0.000000e+00 190 %conv = zext i1 %cmp to i32 191 ret i32 %conv 192 } 193 194 define i32 @test11_intrinsic(double %a) { 195 ; CHECK-LABEL: @test11_intrinsic( 196 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 197 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 198 ; CHECK-NEXT: ret i32 [[CONV]] 199 ; 200 %call = tail call double @llvm.fabs.f64(double %a) 201 %cmp = fcmp ogt double %call, 0.000000e+00 202 %conv = zext i1 %cmp to i32 203 ret i32 %conv 204 } 205 206 define i32 @test12(double %a) { 207 ; CHECK-LABEL: @test12( 208 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 209 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 210 ; CHECK-NEXT: ret i32 [[CONV]] 211 ; 212 %call = tail call double @fabs(double %a) 213 %cmp = fcmp oge double %call, 0.000000e+00 214 %conv = zext i1 %cmp to i32 215 ret i32 %conv 216 } 217 218 define i32 @test12_intrinsic(double %a) { 219 ; CHECK-LABEL: @test12_intrinsic( 220 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 221 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 222 ; CHECK-NEXT: ret i32 [[CONV]] 223 ; 224 %call = tail call double @llvm.fabs.f64(double %a) 225 %cmp = fcmp oge double %call, 0.000000e+00 226 %conv = zext i1 %cmp to i32 227 ret i32 %conv 228 } 229 230 define i32 @test13(double %a) { 231 ; CHECK-LABEL: @test13( 232 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 233 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 234 ; CHECK-NEXT: ret i32 [[CONV]] 235 ; 236 %call = tail call double @fabs(double %a) 237 %cmp = fcmp une double %call, 0.000000e+00 238 %conv = zext i1 %cmp to i32 239 ret i32 %conv 240 } 241 242 define i32 @test13_intrinsic(double %a) { 243 ; CHECK-LABEL: @test13_intrinsic( 244 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 245 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 246 ; CHECK-NEXT: ret i32 [[CONV]] 247 ; 248 %call = tail call double @llvm.fabs.f64(double %a) 249 %cmp = fcmp une double %call, 0.000000e+00 250 %conv = zext i1 %cmp to i32 251 ret i32 %conv 252 } 253 254 define i32 @test14(double %a) { 255 ; CHECK-LABEL: @test14( 256 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 257 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 258 ; CHECK-NEXT: ret i32 [[CONV]] 259 ; 260 %call = tail call double @fabs(double %a) 261 %cmp = fcmp oeq double %call, 0.000000e+00 262 %conv = zext i1 %cmp to i32 263 ret i32 %conv 264 } 265 266 define i32 @test14_intrinsic(double %a) { 267 ; CHECK-LABEL: @test14_intrinsic( 268 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 269 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 270 ; CHECK-NEXT: ret i32 [[CONV]] 271 ; 272 %call = tail call double @llvm.fabs.f64(double %a) 273 %cmp = fcmp oeq double %call, 0.000000e+00 274 %conv = zext i1 %cmp to i32 275 ret i32 %conv 276 } 277 278 define i32 @test15(double %a) { 279 ; CHECK-LABEL: @test15( 280 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 281 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 282 ; CHECK-NEXT: ret i32 [[CONV]] 283 ; 284 %call = tail call double @fabs(double %a) 285 %cmp = fcmp one double %call, 0.000000e+00 286 %conv = zext i1 %cmp to i32 287 ret i32 %conv 288 } 289 290 define i32 @test15_intrinsic(double %a) { 291 ; CHECK-LABEL: @test15_intrinsic( 292 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 293 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 294 ; CHECK-NEXT: ret i32 [[CONV]] 295 ; 296 %call = tail call double @llvm.fabs.f64(double %a) 297 %cmp = fcmp one double %call, 0.000000e+00 298 %conv = zext i1 %cmp to i32 299 ret i32 %conv 300 } 301 302 define i32 @test16(double %a) { 303 ; CHECK-LABEL: @test16( 304 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 305 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 306 ; CHECK-NEXT: ret i32 [[CONV]] 307 ; 308 %call = tail call double @fabs(double %a) 309 %cmp = fcmp ueq double %call, 0.000000e+00 310 %conv = zext i1 %cmp to i32 311 ret i32 %conv 312 } 313 314 define i32 @test16_intrinsic(double %a) { 315 ; CHECK-LABEL: @test16_intrinsic( 316 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 317 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 318 ; CHECK-NEXT: ret i32 [[CONV]] 319 ; 320 %call = tail call double @llvm.fabs.f64(double %a) 321 %cmp = fcmp ueq double %call, 0.000000e+00 322 %conv = zext i1 %cmp to i32 323 ret i32 %conv 324 } 325 326 ; Don't crash. 327 define i32 @test17(double %a, double (double)* %p) { 328 ; CHECK-LABEL: @test17( 329 ; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]]) 330 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00 331 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 332 ; CHECK-NEXT: ret i32 [[CONV]] 333 ; 334 %call = tail call double %p(double %a) 335 %cmp = fcmp ueq double %call, 0.000000e+00 336 %conv = zext i1 %cmp to i32 337 ret i32 %conv 338 } 339 340 ; Can fold fcmp with undef on one side by choosing NaN for the undef 341 define i32 @test18_undef_unordered(float %a) { 342 ; CHECK-LABEL: @test18_undef_unordered( 343 ; CHECK-NEXT: ret i32 1 344 ; 345 %cmp = fcmp ueq float %a, undef 346 %conv = zext i1 %cmp to i32 347 ret i32 %conv 348 } 349 ; Can fold fcmp with undef on one side by choosing NaN for the undef 350 define i32 @test18_undef_ordered(float %a) { 351 ; CHECK-LABEL: @test18_undef_ordered( 352 ; CHECK-NEXT: ret i32 0 353 ; 354 %cmp = fcmp oeq float %a, undef 355 %conv = zext i1 %cmp to i32 356 ret i32 %conv 357 } 358 359 ; Can fold fcmp with undef on both side 360 ; fcmp u_pred undef, undef -> true 361 ; fcmp o_pred undef, undef -> false 362 ; because whatever you choose for the first undef 363 ; you can choose NaN for the other undef 364 define i1 @test19_undef_unordered() { 365 ; CHECK-LABEL: @test19_undef_unordered( 366 ; CHECK-NEXT: ret i1 true 367 ; 368 %cmp = fcmp ueq float undef, undef 369 ret i1 %cmp 370 } 371 372 define i1 @test19_undef_ordered() { 373 ; CHECK-LABEL: @test19_undef_ordered( 374 ; CHECK-NEXT: ret i1 false 375 ; 376 %cmp = fcmp oeq float undef, undef 377 ret i1 %cmp 378 } 379 380