1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare half @llvm.fabs.f16(half) 5declare double @llvm.fabs.f64(double) 6declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 7declare double @llvm.copysign.f64(double, double) 8declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>) 9 10define i1 @fpext_fpext(float %x, float %y) { 11; CHECK-LABEL: @fpext_fpext( 12; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]] 13; CHECK-NEXT: ret i1 [[CMP]] 14; 15 %ext1 = fpext float %x to double 16 %ext2 = fpext float %y to double 17 %cmp = fcmp nnan ogt double %ext1, %ext2 18 ret i1 %cmp 19} 20 21define i1 @fpext_constant(float %a) { 22; CHECK-LABEL: @fpext_constant( 23; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[A:%.*]], 1.000000e+00 24; CHECK-NEXT: ret i1 [[CMP]] 25; 26 %ext = fpext float %a to double 27 %cmp = fcmp ninf ogt double %ext, 1.000000e+00 28 ret i1 %cmp 29} 30 31define <2 x i1> @fpext_constant_vec_splat(<2 x half> %a) { 32; CHECK-LABEL: @fpext_constant_vec_splat( 33; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ole <2 x half> [[A:%.*]], <half 0xH5140, half 0xH5140> 34; CHECK-NEXT: ret <2 x i1> [[CMP]] 35; 36 %ext = fpext <2 x half> %a to <2 x double> 37 %cmp = fcmp nnan ole <2 x double> %ext, <double 42.0, double 42.0> 38 ret <2 x i1> %cmp 39} 40 41define i1 @fpext_constant_lossy(float %a) { 42; CHECK-LABEL: @fpext_constant_lossy( 43; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 44; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001 45; CHECK-NEXT: ret i1 [[CMP]] 46; 47 %ext = fpext float %a to double 48 %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float. 49 ret i1 %cmp 50} 51 52define i1 @fpext_constant_denorm(float %a) { 53; CHECK-LABEL: @fpext_constant_denorm( 54; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double 55; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000 56; CHECK-NEXT: ret i1 [[CMP]] 57; 58 %ext = fpext float %a to double 59 %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float. 60 ret i1 %cmp 61} 62 63define i1 @fneg_constant_swap_pred(float %x) { 64; CHECK-LABEL: @fneg_constant_swap_pred( 65; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00 66; CHECK-NEXT: ret i1 [[CMP]] 67; 68 %neg = fsub float -0.0, %x 69 %cmp = fcmp ogt float %neg, 1.0 70 ret i1 %cmp 71} 72 73define i1 @unary_fneg_constant_swap_pred(float %x) { 74; CHECK-LABEL: @unary_fneg_constant_swap_pred( 75; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00 76; CHECK-NEXT: ret i1 [[CMP]] 77; 78 %neg = fneg float %x 79 %cmp = fcmp ogt float %neg, 1.0 80 ret i1 %cmp 81} 82 83define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) { 84; CHECK-LABEL: @fneg_constant_swap_pred_vec( 85; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 86; CHECK-NEXT: ret <2 x i1> [[CMP]] 87; 88 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 89 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 90 ret <2 x i1> %cmp 91} 92 93define <2 x i1> @unary_fneg_constant_swap_pred_vec(<2 x float> %x) { 94; CHECK-LABEL: @unary_fneg_constant_swap_pred_vec( 95; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 96; CHECK-NEXT: ret <2 x i1> [[CMP]] 97; 98 %neg = fneg <2 x float> %x 99 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 100 ret <2 x i1> %cmp 101} 102 103define <2 x i1> @fneg_constant_swap_pred_vec_undef(<2 x float> %x) { 104; CHECK-LABEL: @fneg_constant_swap_pred_vec_undef( 105; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> 106; CHECK-NEXT: ret <2 x i1> [[CMP]] 107; 108 %neg = fsub <2 x float> <float undef, float -0.0>, %x 109 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> 110 ret <2 x i1> %cmp 111} 112 113; The new fcmp should have the same FMF as the original. 114 115define i1 @fneg_fmf(float %x) { 116; CHECK-LABEL: @fneg_fmf( 117; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01 118; CHECK-NEXT: ret i1 [[R]] 119; 120 %n = fsub fast float -0.0, %x 121 %r = fcmp fast oeq float %n, 42.0 122 ret i1 %r 123} 124 125define i1 @unary_fneg_fmf(float %x) { 126; CHECK-LABEL: @unary_fneg_fmf( 127; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01 128; CHECK-NEXT: ret i1 [[R]] 129; 130 %n = fneg fast float %x 131 %r = fcmp fast oeq float %n, 42.0 132 ret i1 %r 133} 134 135; The new fcmp should have the same FMF as the original, vector edition. 136 137define <2 x i1> @fcmp_fneg_fmf_vec(<2 x float> %x) { 138; CHECK-LABEL: @fcmp_fneg_fmf_vec( 139; CHECK-NEXT: [[R:%.*]] = fcmp reassoc nnan ule <2 x float> [[X:%.*]], <float -4.200000e+01, float 1.900000e+01> 140; CHECK-NEXT: ret <2 x i1> [[R]] 141; 142 %n = fsub nsz <2 x float> zeroinitializer, %x 143 %r = fcmp nnan reassoc uge <2 x float> %n, <float 42.0, float -19.0> 144 ret <2 x i1> %r 145} 146 147define i1 @fneg_fneg_swap_pred(float %x, float %y) { 148; CHECK-LABEL: @fneg_fneg_swap_pred( 149; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]] 150; CHECK-NEXT: ret i1 [[CMP]] 151; 152 %neg1 = fsub float -0.0, %x 153 %neg2 = fsub float -0.0, %y 154 %cmp = fcmp nnan olt float %neg1, %neg2 155 ret i1 %cmp 156} 157 158define i1 @unary_fneg_unary_fneg_swap_pred(float %x, float %y) { 159; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred( 160; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]] 161; CHECK-NEXT: ret i1 [[CMP]] 162; 163 %neg1 = fneg float %x 164 %neg2 = fneg float %y 165 %cmp = fcmp nnan olt float %neg1, %neg2 166 ret i1 %cmp 167} 168 169define i1 @unary_fneg_fneg_swap_pred(float %x, float %y) { 170; CHECK-LABEL: @unary_fneg_fneg_swap_pred( 171; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]] 172; CHECK-NEXT: ret i1 [[CMP]] 173; 174 %neg1 = fneg float %x 175 %neg2 = fsub float -0.0, %y 176 %cmp = fcmp nnan olt float %neg1, %neg2 177 ret i1 %cmp 178} 179 180define i1 @fneg_unary_fneg_swap_pred(float %x, float %y) { 181; CHECK-LABEL: @fneg_unary_fneg_swap_pred( 182; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]] 183; CHECK-NEXT: ret i1 [[CMP]] 184; 185 %neg1 = fsub float -0.0, %x 186 %neg2 = fneg float %y 187 %cmp = fcmp nnan olt float %neg1, %neg2 188 ret i1 %cmp 189} 190 191define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 192; CHECK-LABEL: @fneg_fneg_swap_pred_vec( 193; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]] 194; CHECK-NEXT: ret <2 x i1> [[CMP]] 195; 196 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x 197 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y 198 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2 199 ret <2 x i1> %cmp 200} 201 202define <2 x i1> @unary_fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 203; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred_vec( 204; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]] 205; CHECK-NEXT: ret <2 x i1> [[CMP]] 206; 207 %neg1 = fneg <2 x float> %x 208 %neg2 = fneg <2 x float> %y 209 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2 210 ret <2 x i1> %cmp 211} 212 213define <2 x i1> @unary_fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 214; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec( 215; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]] 216; CHECK-NEXT: ret <2 x i1> [[CMP]] 217; 218 %neg1 = fneg <2 x float> %x 219 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y 220 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2 221 ret <2 x i1> %cmp 222} 223 224define <2 x i1> @fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { 225; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec( 226; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]] 227; CHECK-NEXT: ret <2 x i1> [[CMP]] 228; 229 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x 230 %neg2 = fneg <2 x float> %y 231 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2 232 ret <2 x i1> %cmp 233} 234 235define <2 x i1> @fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { 236; CHECK-LABEL: @fneg_fneg_swap_pred_vec_undef( 237; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 238; CHECK-NEXT: ret <2 x i1> [[CMP]] 239; 240 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x 241 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y 242 %cmp = fcmp olt <2 x float> %neg1, %neg2 243 ret <2 x i1> %cmp 244} 245 246define <2 x i1> @unary_fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { 247; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec_undef( 248; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 249; CHECK-NEXT: ret <2 x i1> [[CMP]] 250; 251 %neg1 = fneg <2 x float> %x 252 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y 253 %cmp = fcmp olt <2 x float> %neg1, %neg2 254 ret <2 x i1> %cmp 255} 256 257define <2 x i1> @fneg_unary_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { 258; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec_undef( 259; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] 260; CHECK-NEXT: ret <2 x i1> [[CMP]] 261; 262 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x 263 %neg2 = fneg <2 x float> %y 264 %cmp = fcmp olt <2 x float> %neg1, %neg2 265 ret <2 x i1> %cmp 266} 267 268define i1 @test7(float %x) { 269; CHECK-LABEL: @test7( 270; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00 271; CHECK-NEXT: ret i1 [[CMP]] 272; 273 %ext = fpext float %x to ppc_fp128 274 %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000 275 ret i1 %cmp 276} 277 278define float @test8(float %x) { 279; CHECK-LABEL: @test8( 280; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 281; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float 282; CHECK-NEXT: ret float [[CONV2]] 283; 284 %conv = fpext float %x to double 285 %cmp = fcmp olt double %conv, 0.000000e+00 286 %conv1 = zext i1 %cmp to i32 287 %conv2 = sitofp i32 %conv1 to float 288 ret float %conv2 289; Float comparison to zero shouldn't cast to double. 290} 291 292define i1 @fabs_uge(double %a) { 293; CHECK-LABEL: @fabs_uge( 294; CHECK-NEXT: ret i1 true 295; 296 %call = call double @llvm.fabs.f64(double %a) 297 %cmp = fcmp uge double %call, 0.0 298 ret i1 %cmp 299} 300 301define i1 @fabs_olt(half %a) { 302; CHECK-LABEL: @fabs_olt( 303; CHECK-NEXT: ret i1 false 304; 305 %call = call half @llvm.fabs.f16(half %a) 306 %cmp = fcmp olt half %call, 0.0 307 ret i1 %cmp 308} 309 310define <2 x i1> @fabs_ole(<2 x float> %a) { 311; CHECK-LABEL: @fabs_ole( 312; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oeq <2 x float> [[A:%.*]], zeroinitializer 313; CHECK-NEXT: ret <2 x i1> [[CMP]] 314; 315 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 316 %cmp = fcmp ninf ole <2 x float> %call, zeroinitializer 317 ret <2 x i1> %cmp 318} 319 320define <2 x i1> @fabs_ule(<2 x float> %a) { 321; CHECK-LABEL: @fabs_ule( 322; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf arcp ueq <2 x float> [[A:%.*]], zeroinitializer 323; CHECK-NEXT: ret <2 x i1> [[CMP]] 324; 325 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 326 %cmp = fcmp ninf arcp ule <2 x float> %call, zeroinitializer 327 ret <2 x i1> %cmp 328} 329 330define i1 @fabs_ogt(double %a) { 331; CHECK-LABEL: @fabs_ogt( 332; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc one double [[A:%.*]], 0.000000e+00 333; CHECK-NEXT: ret i1 [[CMP]] 334; 335 %call = call double @llvm.fabs.f64(double %a) 336 %cmp = fcmp reassoc ogt double %call, 0.0 337 ret i1 %cmp 338} 339 340define i1 @fabs_ugt(double %a) { 341; CHECK-LABEL: @fabs_ugt( 342; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf une double [[A:%.*]], 0.000000e+00 343; CHECK-NEXT: ret i1 [[CMP]] 344; 345 %call = call double @llvm.fabs.f64(double %a) 346 %cmp = fcmp ninf reassoc ugt double %call, 0.0 347 ret i1 %cmp 348} 349 350define i1 @fabs_oge(double %a) { 351; CHECK-LABEL: @fabs_oge( 352; CHECK-NEXT: [[CMP:%.*]] = fcmp afn ord double [[A:%.*]], 0.000000e+00 353; CHECK-NEXT: ret i1 [[CMP]] 354; 355 %call = call double @llvm.fabs.f64(double %a) 356 %cmp = fcmp afn oge double %call, 0.0 357 ret i1 %cmp 358} 359 360define i1 @fabs_ult(double %a) { 361; CHECK-LABEL: @fabs_ult( 362; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc arcp uno double [[A:%.*]], 0.000000e+00 363; CHECK-NEXT: ret i1 [[CMP]] 364; 365 %call = call double @llvm.fabs.f64(double %a) 366 %cmp = fcmp reassoc arcp ult double %call, 0.0 367 ret i1 %cmp 368} 369 370define <2 x i1> @fabs_ult_nnan(<2 x float> %a) { 371; CHECK-LABEL: @fabs_ult_nnan( 372; CHECK-NEXT: ret <2 x i1> zeroinitializer 373; 374 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 375 %cmp = fcmp nnan reassoc arcp ult <2 x float> %call, zeroinitializer 376 ret <2 x i1> %cmp 377} 378 379define i1 @fabs_une(half %a) { 380; CHECK-LABEL: @fabs_une( 381; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une half [[A:%.*]], 0xH0000 382; CHECK-NEXT: ret i1 [[CMP]] 383; 384 %call = call half @llvm.fabs.f16(half %a) 385 %cmp = fcmp ninf une half %call, 0.0 386 ret i1 %cmp 387} 388 389define i1 @fabs_oeq(double %a) { 390; CHECK-LABEL: @fabs_oeq( 391; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf oeq double [[A:%.*]], 0.000000e+00 392; CHECK-NEXT: ret i1 [[CMP]] 393; 394 %call = call double @llvm.fabs.f64(double %a) 395 %cmp = fcmp ninf reassoc oeq double %call, 0.0 396 ret i1 %cmp 397} 398 399define i1 @fabs_one(double %a) { 400; CHECK-LABEL: @fabs_one( 401; CHECK-NEXT: [[CMP:%.*]] = fcmp fast one double [[A:%.*]], 0.000000e+00 402; CHECK-NEXT: ret i1 [[CMP]] 403; 404 %call = call double @llvm.fabs.f64(double %a) 405 %cmp = fcmp fast one double %call, 0.0 406 ret i1 %cmp 407} 408 409define <2 x i1> @fabs_ueq(<2 x float> %a) { 410; CHECK-LABEL: @fabs_ueq( 411; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ueq <2 x float> [[A:%.*]], zeroinitializer 412; CHECK-NEXT: ret <2 x i1> [[CMP]] 413; 414 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 415 %cmp = fcmp arcp ueq <2 x float> %call, zeroinitializer 416 ret <2 x i1> %cmp 417} 418 419define <2 x i1> @fabs_ord(<2 x float> %a) { 420; CHECK-LABEL: @fabs_ord( 421; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ord <2 x float> [[A:%.*]], zeroinitializer 422; CHECK-NEXT: ret <2 x i1> [[CMP]] 423; 424 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 425 %cmp = fcmp arcp ord <2 x float> %call, zeroinitializer 426 ret <2 x i1> %cmp 427} 428 429define <2 x i1> @fabs_uno(<2 x float> %a) { 430; CHECK-LABEL: @fabs_uno( 431; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp uno <2 x float> [[A:%.*]], zeroinitializer 432; CHECK-NEXT: ret <2 x i1> [[CMP]] 433; 434 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) 435 %cmp = fcmp arcp uno <2 x float> %call, zeroinitializer 436 ret <2 x i1> %cmp 437} 438 439; Don't crash. 440define i32 @test17(double %a, double (double)* %p) { 441; CHECK-LABEL: @test17( 442; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]]) 443; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00 444; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 445; CHECK-NEXT: ret i32 [[CONV]] 446; 447 %call = tail call double %p(double %a) 448 %cmp = fcmp ueq double %call, 0.000000e+00 449 %conv = zext i1 %cmp to i32 450 ret i32 %conv 451} 452 453; Can fold fcmp with undef on one side by choosing NaN for the undef 454define i32 @test18_undef_unordered(float %a) { 455; CHECK-LABEL: @test18_undef_unordered( 456; CHECK-NEXT: ret i32 1 457; 458 %cmp = fcmp ueq float %a, undef 459 %conv = zext i1 %cmp to i32 460 ret i32 %conv 461} 462; Can fold fcmp with undef on one side by choosing NaN for the undef 463define i32 @test18_undef_ordered(float %a) { 464; CHECK-LABEL: @test18_undef_ordered( 465; CHECK-NEXT: ret i32 0 466; 467 %cmp = fcmp oeq float %a, undef 468 %conv = zext i1 %cmp to i32 469 ret i32 %conv 470} 471 472; Can fold fcmp with undef on both side 473; fcmp u_pred undef, undef -> true 474; fcmp o_pred undef, undef -> false 475; because whatever you choose for the first undef 476; you can choose NaN for the other undef 477define i1 @test19_undef_unordered() { 478; CHECK-LABEL: @test19_undef_unordered( 479; CHECK-NEXT: ret i1 true 480; 481 %cmp = fcmp ueq float undef, undef 482 ret i1 %cmp 483} 484 485define i1 @test19_undef_ordered() { 486; CHECK-LABEL: @test19_undef_ordered( 487; CHECK-NEXT: ret i1 false 488; 489 %cmp = fcmp oeq float undef, undef 490 ret i1 %cmp 491} 492 493; Can fold 1.0 / X < 0.0 --> X < 0 with ninf 494define i1 @test20_recipX_olt_0(float %X) { 495; CHECK-LABEL: @test20_recipX_olt_0( 496; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt float [[X:%.*]], 0.000000e+00 497; CHECK-NEXT: ret i1 [[CMP]] 498; 499 %div = fdiv ninf float 1.0, %X 500 %cmp = fcmp ninf olt float %div, 0.0 501 ret i1 %cmp 502} 503 504; Can fold -2.0 / X <= 0.0 --> X >= 0 with ninf 505define i1 @test21_recipX_ole_0(float %X) { 506; CHECK-LABEL: @test21_recipX_ole_0( 507; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge float [[X:%.*]], 0.000000e+00 508; CHECK-NEXT: ret i1 [[CMP]] 509; 510 %div = fdiv ninf float -2.0, %X 511 %cmp = fcmp ninf ole float %div, 0.0 512 ret i1 %cmp 513} 514 515; Can fold 2.0 / X > 0.0 --> X > 0 with ninf 516define i1 @test22_recipX_ogt_0(float %X) { 517; CHECK-LABEL: @test22_recipX_ogt_0( 518; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[X:%.*]], 0.000000e+00 519; CHECK-NEXT: ret i1 [[CMP]] 520; 521 %div = fdiv ninf float 2.0, %X 522 %cmp = fcmp ninf ogt float %div, 0.0 523 ret i1 %cmp 524} 525 526; Can fold -1.0 / X >= 0.0 --> X <= 0 with ninf 527define i1 @test23_recipX_oge_0(float %X) { 528; CHECK-LABEL: @test23_recipX_oge_0( 529; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole float [[X:%.*]], 0.000000e+00 530; CHECK-NEXT: ret i1 [[CMP]] 531; 532 %div = fdiv ninf float -1.0, %X 533 %cmp = fcmp ninf oge float %div, 0.0 534 ret i1 %cmp 535} 536 537; Do not fold 1.0 / X > 0.0 when ninf is missing 538define i1 @test24_recipX_noninf_cmp(float %X) { 539; CHECK-LABEL: @test24_recipX_noninf_cmp( 540; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]] 541; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[DIV]], 0.000000e+00 542; CHECK-NEXT: ret i1 [[CMP]] 543; 544 %div = fdiv ninf float 2.0, %X 545 %cmp = fcmp ogt float %div, 0.0 546 ret i1 %cmp 547} 548 549; Do not fold 1.0 / X > 0.0 when ninf is missing 550define i1 @test25_recipX_noninf_div(float %X) { 551; CHECK-LABEL: @test25_recipX_noninf_div( 552; CHECK-NEXT: [[DIV:%.*]] = fdiv float 2.000000e+00, [[X:%.*]] 553; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[DIV]], 0.000000e+00 554; CHECK-NEXT: ret i1 [[CMP]] 555; 556 %div = fdiv float 2.0, %X 557 %cmp = fcmp ninf ogt float %div, 0.0 558 ret i1 %cmp 559} 560 561; Do not fold 1.0 / X > 0.0 with unordered predicates 562define i1 @test26_recipX_unorderd(float %X) { 563; CHECK-LABEL: @test26_recipX_unorderd( 564; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]] 565; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ugt float [[DIV]], 0.000000e+00 566; CHECK-NEXT: ret i1 [[CMP]] 567; 568 %div = fdiv ninf float 2.0, %X 569 %cmp = fcmp ninf ugt float %div, 0.0 570 ret i1 %cmp 571} 572 573; Fold <-1.0, -1.0> / X > <-0.0, -0.0> 574define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) { 575; CHECK-LABEL: @test27_recipX_gt_vecsplat( 576; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt <2 x float> [[X:%.*]], zeroinitializer 577; CHECK-NEXT: ret <2 x i1> [[CMP]] 578; 579 %div = fdiv ninf <2 x float> <float -1.0, float -1.0>, %X 580 %cmp = fcmp ninf ogt <2 x float> %div, <float -0.0, float -0.0> 581 ret <2 x i1> %cmp 582} 583 584define i1 @is_signbit_set(double %x) { 585; CHECK-LABEL: @is_signbit_set( 586; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64 587; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[TMP1]], 0 588; CHECK-NEXT: ret i1 [[R]] 589; 590 %s = call double @llvm.copysign.f64(double 1.0, double %x) 591 %r = fcmp olt double %s, 0.0 592 ret i1 %r 593} 594 595; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number. 596 597define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) { 598; CHECK-LABEL: @is_signbit_set_anyzero( 599; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64> 600; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer 601; CHECK-NEXT: ret <2 x i1> [[R]] 602; 603 %s = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 42.0, double 42.0>, <2 x double> %x) 604 %r = fcmp olt <2 x double> %s, <double -0.0, double 0.0> 605 ret <2 x i1> %r 606} 607 608; TODO: Handle different predicates. 609 610define i1 @is_signbit_clear(double %x) { 611; CHECK-LABEL: @is_signbit_clear( 612; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) 613; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00 614; CHECK-NEXT: ret i1 [[R]] 615; 616 %s = call double @llvm.copysign.f64(double -42.0, double %x) 617 %r = fcmp ogt double %s, 0.0 618 ret i1 %r 619} 620 621; Negative test - uses 622 623define i1 @is_signbit_set_extra_use(double %x, double* %p) { 624; CHECK-LABEL: @is_signbit_set_extra_use( 625; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]]) 626; CHECK-NEXT: store double [[S]], double* [[P:%.*]], align 8 627; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[S]], 0.000000e+00 628; CHECK-NEXT: ret i1 [[R]] 629; 630 %s = call double @llvm.copysign.f64(double 1.0, double %x) 631 store double %s, double* %p 632 %r = fcmp olt double %s, 0.0 633 ret i1 %r 634} 635 636; TODO: Handle non-zero compare constant. 637 638define i1 @is_signbit_clear_nonzero(double %x) { 639; CHECK-LABEL: @is_signbit_clear_nonzero( 640; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) 641; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 1.000000e+00 642; CHECK-NEXT: ret i1 [[R]] 643; 644 %s = call double @llvm.copysign.f64(double -42.0, double %x) 645 %r = fcmp ogt double %s, 1.0 646 ret i1 %r 647} 648 649; TODO: Handle zero copysign constant. 650 651define i1 @is_signbit_set_simplify_zero(double %x) { 652; CHECK-LABEL: @is_signbit_set_simplify_zero( 653; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]]) 654; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00 655; CHECK-NEXT: ret i1 [[R]] 656; 657 %s = call double @llvm.copysign.f64(double 0.0, double %x) 658 %r = fcmp ogt double %s, 0.0 659 ret i1 %r 660} 661 662; TODO: Handle NaN copysign constant. 663 664define i1 @is_signbit_set_simplify_nan(double %x) { 665; CHECK-LABEL: @is_signbit_set_simplify_nan( 666; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]]) 667; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00 668; CHECK-NEXT: ret i1 [[R]] 669; 670 %s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x) 671 %r = fcmp ogt double %s, 0.0 672 ret i1 %r 673} 674 675define <2 x i1> @lossy_oeq(<2 x float> %x) { 676; CHECK-LABEL: @lossy_oeq( 677; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> 678; CHECK-NEXT: [[R:%.*]] = fcmp oeq <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01> 679; CHECK-NEXT: ret <2 x i1> [[R]] 680; 681 %e = fpext <2 x float> %x to <2 x double> 682 %r = fcmp oeq <2 x double> %e, <double 0.1, double 0.1> 683 ret <2 x i1> %r 684} 685 686define i1 @lossy_one(float %x, double* %p) { 687; CHECK-LABEL: @lossy_one( 688; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double 689; CHECK-NEXT: store double [[E]], double* [[P:%.*]], align 8 690; CHECK-NEXT: [[R:%.*]] = fcmp one double [[E]], 1.000000e-01 691; CHECK-NEXT: ret i1 [[R]] 692; 693 %e = fpext float %x to double 694 store double %e, double* %p 695 %r = fcmp one double %e, 0.1 696 ret i1 %r 697} 698 699define i1 @lossy_ueq(half %x) { 700; CHECK-LABEL: @lossy_ueq( 701; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double 702; CHECK-NEXT: [[R:%.*]] = fcmp ueq double [[E]], 6.553600e+04 703; CHECK-NEXT: ret i1 [[R]] 704; 705 %e = fpext half %x to double 706 %r = fcmp ueq double %e, 65536.0 707 ret i1 %r 708} 709 710define i1 @lossy_une(half %x) { 711; CHECK-LABEL: @lossy_une( 712; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float 713; CHECK-NEXT: [[R:%.*]] = fcmp une float [[E]], 2.049000e+03 714; CHECK-NEXT: ret i1 [[R]] 715; 716 %e = fpext half %x to float 717 %r = fcmp une float %e, 2049.0 718 ret i1 %r 719} 720 721define <2 x i1> @lossy_ogt(<2 x float> %x) { 722; CHECK-LABEL: @lossy_ogt( 723; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> 724; CHECK-NEXT: [[R:%.*]] = fcmp ogt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01> 725; CHECK-NEXT: ret <2 x i1> [[R]] 726; 727 %e = fpext <2 x float> %x to <2 x double> 728 %r = fcmp ogt <2 x double> %e, <double 0.1, double 0.1> 729 ret <2 x i1> %r 730} 731 732define i1 @lossy_oge(float %x, double* %p) { 733; CHECK-LABEL: @lossy_oge( 734; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double 735; CHECK-NEXT: store double [[E]], double* [[P:%.*]], align 8 736; CHECK-NEXT: [[R:%.*]] = fcmp oge double [[E]], 1.000000e-01 737; CHECK-NEXT: ret i1 [[R]] 738; 739 %e = fpext float %x to double 740 store double %e, double* %p 741 %r = fcmp oge double %e, 0.1 742 ret i1 %r 743} 744 745define i1 @lossy_olt(half %x) { 746; CHECK-LABEL: @lossy_olt( 747; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double 748; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[E]], 6.553600e+04 749; CHECK-NEXT: ret i1 [[R]] 750; 751 %e = fpext half %x to double 752 %r = fcmp olt double %e, 65536.0 753 ret i1 %r 754} 755 756define i1 @lossy_ole(half %x) { 757; CHECK-LABEL: @lossy_ole( 758; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float 759; CHECK-NEXT: [[R:%.*]] = fcmp ole float [[E]], 2.049000e+03 760; CHECK-NEXT: ret i1 [[R]] 761; 762 %e = fpext half %x to float 763 %r = fcmp ole float %e, 2049.0 764 ret i1 %r 765} 766 767define <2 x i1> @lossy_ugt(<2 x float> %x) { 768; CHECK-LABEL: @lossy_ugt( 769; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double> 770; CHECK-NEXT: [[R:%.*]] = fcmp ugt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01> 771; CHECK-NEXT: ret <2 x i1> [[R]] 772; 773 %e = fpext <2 x float> %x to <2 x double> 774 %r = fcmp ugt <2 x double> %e, <double 0.1, double 0.1> 775 ret <2 x i1> %r 776} 777 778define i1 @lossy_uge(float %x, double* %p) { 779; CHECK-LABEL: @lossy_uge( 780; CHECK-NEXT: [[E:%.*]] = fpext float [[X:%.*]] to double 781; CHECK-NEXT: store double [[E]], double* [[P:%.*]], align 8 782; CHECK-NEXT: [[R:%.*]] = fcmp uge double [[E]], 1.000000e-01 783; CHECK-NEXT: ret i1 [[R]] 784; 785 %e = fpext float %x to double 786 store double %e, double* %p 787 %r = fcmp uge double %e, 0.1 788 ret i1 %r 789} 790 791define i1 @lossy_ult(half %x) { 792; CHECK-LABEL: @lossy_ult( 793; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to double 794; CHECK-NEXT: [[R:%.*]] = fcmp ult double [[E]], 6.553600e+04 795; CHECK-NEXT: ret i1 [[R]] 796; 797 %e = fpext half %x to double 798 %r = fcmp ult double %e, 65536.0 799 ret i1 %r 800} 801 802define i1 @lossy_ule(half %x) { 803; CHECK-LABEL: @lossy_ule( 804; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float 805; CHECK-NEXT: [[R:%.*]] = fcmp ule float [[E]], 2.049000e+03 806; CHECK-NEXT: ret i1 [[R]] 807; 808 %e = fpext half %x to float 809 %r = fcmp ule float %e, 2049.0 810 ret i1 %r 811} 812 813define i1 @lossy_ord(half %x) { 814; CHECK-LABEL: @lossy_ord( 815; CHECK-NEXT: [[R:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 816; CHECK-NEXT: ret i1 [[R]] 817; 818 %e = fpext half %x to double 819 %r = fcmp ord double %e, 65536.0 820 ret i1 %r 821} 822 823define i1 @lossy_uno(half %x) { 824; CHECK-LABEL: @lossy_uno( 825; CHECK-NEXT: [[R:%.*]] = fcmp uno half [[X:%.*]], 0xH0000 826; CHECK-NEXT: ret i1 [[R]] 827; 828 %e = fpext half %x to float 829 %r = fcmp uno float %e, 2049.0 830 ret i1 %r 831} 832 833define i1 @fneg_oeq(float %a) { 834; CHECK-LABEL: @fneg_oeq( 835; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A:%.*]], 0.000000e+00 836; CHECK-NEXT: ret i1 [[CMP]] 837; 838 %fneg = fneg float %a 839 %cmp = fcmp oeq float %fneg, %a 840 ret i1 %cmp 841} 842 843define i1 @fneg_ogt(half %a) { 844; CHECK-LABEL: @fneg_ogt( 845; CHECK-NEXT: [[CMP:%.*]] = fcmp fast olt half [[A:%.*]], 0xH0000 846; CHECK-NEXT: ret i1 [[CMP]] 847; 848 %fneg = fneg half %a 849 %cmp = fcmp fast ogt half %fneg, %a 850 ret i1 %cmp 851} 852 853define <2 x i1> @fneg_oge(<2 x float> %a) { 854; CHECK-LABEL: @fneg_oge( 855; CHECK-NEXT: [[CMP:%.*]] = fcmp ole <2 x float> [[A:%.*]], zeroinitializer 856; CHECK-NEXT: ret <2 x i1> [[CMP]] 857; 858 %fneg = fneg fast <2 x float> %a 859 %cmp = fcmp oge <2 x float> %fneg, %a 860 ret <2 x i1> %cmp 861} 862 863define i1 @fneg_olt(float %a, float* %q) { 864; CHECK-LABEL: @fneg_olt( 865; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]] 866; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4 867; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00 868; CHECK-NEXT: ret i1 [[CMP]] 869; 870 %fneg = fneg float %a 871 store float %fneg, float* %q 872 %cmp = fcmp olt float %fneg, %a 873 ret i1 %cmp 874} 875 876define i1 @fneg_ole(float %a) { 877; CHECK-LABEL: @fneg_ole( 878; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz oge float [[A:%.*]], 0.000000e+00 879; CHECK-NEXT: ret i1 [[CMP]] 880; 881 %fneg = fneg float %a 882 %cmp = fcmp nsz ole float %fneg, %a 883 ret i1 %cmp 884} 885 886define i1 @fneg_one(float %a) { 887; CHECK-LABEL: @fneg_one( 888; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A:%.*]], 0.000000e+00 889; CHECK-NEXT: ret i1 [[CMP]] 890; 891 %fneg = fneg float %a 892 %cmp = fcmp nnan one float %fneg, %a 893 ret i1 %cmp 894} 895 896define i1 @fneg_ord(float %a) { 897; CHECK-LABEL: @fneg_ord( 898; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A:%.*]], 0.000000e+00 899; CHECK-NEXT: ret i1 [[CMP]] 900; 901 %fneg = fneg float %a 902 %cmp = fcmp ninf ord float %fneg, %a 903 ret i1 %cmp 904} 905 906define i1 @fneg_uno(float %a) { 907; CHECK-LABEL: @fneg_uno( 908; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A:%.*]], 0.000000e+00 909; CHECK-NEXT: ret i1 [[CMP]] 910; 911 %fneg = fneg float %a 912 %cmp = fcmp uno float %fneg, %a 913 ret i1 %cmp 914} 915 916define i1 @fneg_ueq(half %a) { 917; CHECK-LABEL: @fneg_ueq( 918; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A:%.*]], 0xH0000 919; CHECK-NEXT: ret i1 [[CMP]] 920; 921 %fneg = fneg half %a 922 %cmp = fcmp fast ueq half %fneg, %a 923 ret i1 %cmp 924} 925 926define <2 x i1> @fneg_ugt(<2 x float> %a) { 927; CHECK-LABEL: @fneg_ugt( 928; CHECK-NEXT: [[CMP:%.*]] = fcmp ult <2 x float> [[A:%.*]], zeroinitializer 929; CHECK-NEXT: ret <2 x i1> [[CMP]] 930; 931 %fneg = fneg fast <2 x float> %a 932 %cmp = fcmp ugt <2 x float> %fneg, %a 933 ret <2 x i1> %cmp 934} 935 936define i1 @fneg_uge(float %a, float* %q) { 937; CHECK-LABEL: @fneg_uge( 938; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A:%.*]] 939; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4 940; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[A]], 0.000000e+00 941; CHECK-NEXT: ret i1 [[CMP]] 942; 943 %fneg = fneg float %a 944 store float %fneg, float* %q 945 %cmp = fcmp uge float %fneg, %a 946 ret i1 %cmp 947} 948 949define i1 @fneg_ult(float %a) { 950; CHECK-LABEL: @fneg_ult( 951; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ugt float [[A:%.*]], 0.000000e+00 952; CHECK-NEXT: ret i1 [[CMP]] 953; 954 %fneg = fneg float %a 955 %cmp = fcmp nsz ult float %fneg, %a 956 ret i1 %cmp 957} 958 959define i1 @fneg_ule(float %a) { 960; CHECK-LABEL: @fneg_ule( 961; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan uge float [[A:%.*]], 0.000000e+00 962; CHECK-NEXT: ret i1 [[CMP]] 963; 964 %fneg = fneg float %a 965 %cmp = fcmp nnan ule float %fneg, %a 966 ret i1 %cmp 967} 968 969define i1 @fneg_une(float %a) { 970; CHECK-LABEL: @fneg_une( 971; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A:%.*]], 0.000000e+00 972; CHECK-NEXT: ret i1 [[CMP]] 973; 974 %fneg = fneg float %a 975 %cmp = fcmp ninf une float %fneg, %a 976 ret i1 %cmp 977} 978 979define i1 @fneg_oeq_swap(float %p) { 980; CHECK-LABEL: @fneg_oeq_swap( 981; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 982; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[A]], 0.000000e+00 983; CHECK-NEXT: ret i1 [[CMP]] 984; 985 %a = fadd float %p, %p ; thwart complexity-based canonicalization 986 %fneg = fneg float %a 987 %cmp = fcmp oeq float %a, %fneg 988 ret i1 %cmp 989} 990 991define i1 @fneg_ogt_swap(half %p) { 992; CHECK-LABEL: @fneg_ogt_swap( 993; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]] 994; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ogt half [[A]], 0xH0000 995; CHECK-NEXT: ret i1 [[CMP]] 996; 997 %a = fadd half %p, %p ; thwart complexity-based canonicalization 998 %fneg = fneg half %a 999 %cmp = fcmp fast ogt half %a, %fneg 1000 ret i1 %cmp 1001} 1002 1003define <2 x i1> @fneg_oge_swap(<2 x float> %p) { 1004; CHECK-LABEL: @fneg_oge_swap( 1005; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]] 1006; CHECK-NEXT: [[CMP:%.*]] = fcmp oge <2 x float> [[A]], zeroinitializer 1007; CHECK-NEXT: ret <2 x i1> [[CMP]] 1008; 1009 %a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization 1010 %fneg = fneg fast <2 x float> %a 1011 %cmp = fcmp oge <2 x float> %a, %fneg 1012 ret <2 x i1> %cmp 1013} 1014 1015define i1 @fneg_olt_swap(float %p, float* %q) { 1016; CHECK-LABEL: @fneg_olt_swap( 1017; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1018; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]] 1019; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4 1020; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A]], 0.000000e+00 1021; CHECK-NEXT: ret i1 [[CMP]] 1022; 1023 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1024 %fneg = fneg float %a 1025 store float %fneg, float* %q 1026 %cmp = fcmp olt float %a, %fneg 1027 ret i1 %cmp 1028} 1029 1030define i1 @fneg_ole_swap(float %p) { 1031; CHECK-LABEL: @fneg_ole_swap( 1032; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1033; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ole float [[A]], 0.000000e+00 1034; CHECK-NEXT: ret i1 [[CMP]] 1035; 1036 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1037 %fneg = fneg float %a 1038 %cmp = fcmp nsz ole float %a, %fneg 1039 ret i1 %cmp 1040} 1041 1042define i1 @fneg_one_swap(float %p) { 1043; CHECK-LABEL: @fneg_one_swap( 1044; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1045; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan one float [[A]], 0.000000e+00 1046; CHECK-NEXT: ret i1 [[CMP]] 1047; 1048 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1049 %fneg = fneg float %a 1050 %cmp = fcmp nnan one float %a, %fneg 1051 ret i1 %cmp 1052} 1053 1054define i1 @fneg_ord_swap(float %p) { 1055; CHECK-LABEL: @fneg_ord_swap( 1056; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1057; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ord float [[A]], 0.000000e+00 1058; CHECK-NEXT: ret i1 [[CMP]] 1059; 1060 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1061 %fneg = fneg float %a 1062 %cmp = fcmp ninf ord float %a, %fneg 1063 ret i1 %cmp 1064} 1065 1066define i1 @fneg_uno_swap(float %p) { 1067; CHECK-LABEL: @fneg_uno_swap( 1068; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1069; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[A]], 0.000000e+00 1070; CHECK-NEXT: ret i1 [[CMP]] 1071; 1072 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1073 %fneg = fneg float %a 1074 %cmp = fcmp uno float %a, %fneg 1075 ret i1 %cmp 1076} 1077 1078define i1 @fneg_ueq_swap(half %p) { 1079; CHECK-LABEL: @fneg_ueq_swap( 1080; CHECK-NEXT: [[A:%.*]] = fadd half [[P:%.*]], [[P]] 1081; CHECK-NEXT: [[CMP:%.*]] = fcmp fast ueq half [[A]], 0xH0000 1082; CHECK-NEXT: ret i1 [[CMP]] 1083; 1084 %a = fadd half %p, %p ; thwart complexity-based canonicalization 1085 %fneg = fneg half %a 1086 %cmp = fcmp fast ueq half %a, %fneg 1087 ret i1 %cmp 1088} 1089 1090define <2 x i1> @fneg_ugt_swap(<2 x float> %p) { 1091; CHECK-LABEL: @fneg_ugt_swap( 1092; CHECK-NEXT: [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]] 1093; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt <2 x float> [[A]], zeroinitializer 1094; CHECK-NEXT: ret <2 x i1> [[CMP]] 1095; 1096 %a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization 1097 %fneg = fneg fast <2 x float> %a 1098 %cmp = fcmp ugt <2 x float> %a, %fneg 1099 ret <2 x i1> %cmp 1100} 1101 1102define i1 @fneg_uge_swap(float %p, float* %q) { 1103; CHECK-LABEL: @fneg_uge_swap( 1104; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1105; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[A]] 1106; CHECK-NEXT: store float [[FNEG]], float* [[Q:%.*]], align 4 1107; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[A]], 0.000000e+00 1108; CHECK-NEXT: ret i1 [[CMP]] 1109; 1110 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1111 %fneg = fneg float %a 1112 store float %fneg, float* %q 1113 %cmp = fcmp uge float %a, %fneg 1114 ret i1 %cmp 1115} 1116 1117define i1 @fneg_ult_swap(float %p) { 1118; CHECK-LABEL: @fneg_ult_swap( 1119; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1120; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ult float [[A]], 0.000000e+00 1121; CHECK-NEXT: ret i1 [[CMP]] 1122; 1123 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1124 %fneg = fneg float %a 1125 %cmp = fcmp nsz ult float %a, %fneg 1126 ret i1 %cmp 1127} 1128 1129define i1 @fneg_ule_swap(float %p) { 1130; CHECK-LABEL: @fneg_ule_swap( 1131; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1132; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ule float [[A]], 0.000000e+00 1133; CHECK-NEXT: ret i1 [[CMP]] 1134; 1135 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1136 %fneg = fneg float %a 1137 %cmp = fcmp nnan ule float %a, %fneg 1138 ret i1 %cmp 1139} 1140 1141define i1 @fneg_une_swap(float %p) { 1142; CHECK-LABEL: @fneg_une_swap( 1143; CHECK-NEXT: [[A:%.*]] = fadd float [[P:%.*]], [[P]] 1144; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une float [[A]], 0.000000e+00 1145; CHECK-NEXT: ret i1 [[CMP]] 1146; 1147 %a = fadd float %p, %p ; thwart complexity-based canonicalization 1148 %fneg = fneg float %a 1149 %cmp = fcmp ninf une float %a, %fneg 1150 ret i1 %cmp 1151} 1152