1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3; RUN: opt -S -passes=instcombine -use-constant-fp-for-fixed-length-splat < %s | FileCheck %s 4 5declare float @llvm.fabs.f32(float) nounwind readnone 6declare float @llvm.pow.f32(float, float) nounwind readnone 7declare <2 x half> @llvm.pow.v2f16(<2 x half>, <2 x half>) nounwind readnone 8declare float @llvm.exp.f32(float) nounwind readnone 9declare <2 x half> @llvm.exp.v2f16(<2 x half>) nounwind readnone 10declare float @llvm.exp2.f32(float) nounwind readnone 11declare <2 x half> @llvm.exp2.v2f16(<2 x half>) nounwind readnone 12declare float @llvm.powi.f32.i32(float, i32) nounwind readnone 13declare <2 x half> @llvm.powi.v2f16.i32(<2 x half>, i32) nounwind readnone 14 15define float @exact_inverse(float %x) { 16; CHECK-LABEL: @exact_inverse( 17; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 1.250000e-01 18; CHECK-NEXT: ret float [[DIV]] 19; 20 %div = fdiv float %x, 8.0 21 ret float %div 22} 23 24; Min normal float = 1.17549435E-38 25 26define float @exact_inverse2(float %x) { 27; CHECK-LABEL: @exact_inverse2( 28; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000 29; CHECK-NEXT: ret float [[DIV]] 30; 31 %div = fdiv float %x, 0x3810000000000000 32 ret float %div 33} 34 35; Max exponent = 1.70141183E+38; don't transform to multiply with denormal. 36 37define float @exact_inverse_but_denorm(float %x) { 38; CHECK-LABEL: @exact_inverse_but_denorm( 39; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47E0000000000000 40; CHECK-NEXT: ret float [[DIV]] 41; 42 %div = fdiv float %x, 0x47E0000000000000 43 ret float %div 44} 45 46; Denormal = float 1.40129846E-45; inverse can't be represented. 47 48define float @not_exact_inverse2(float %x) { 49; CHECK-LABEL: @not_exact_inverse2( 50; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x36A0000000000000 51; CHECK-NEXT: ret float [[DIV]] 52; 53 %div = fdiv float %x, 0x36A0000000000000 54 ret float %div 55} 56 57; Fast math allows us to replace this fdiv. 58 59define float @not_exact_but_allow_recip(float %x) { 60; CHECK-LABEL: @not_exact_but_allow_recip( 61; CHECK-NEXT: [[DIV:%.*]] = fmul arcp float [[X:%.*]], 0x3FD5555560000000 62; CHECK-NEXT: ret float [[DIV]] 63; 64 %div = fdiv arcp float %x, 3.0 65 ret float %div 66} 67 68; Fast math allows us to replace this fdiv, but we don't to avoid a denormal. 69; TODO: What if the function attributes tell us that denormals are flushed? 70 71define float @not_exact_but_allow_recip_but_denorm(float %x) { 72; CHECK-LABEL: @not_exact_but_allow_recip_but_denorm( 73; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp float [[X:%.*]], 0x47E0000100000000 74; CHECK-NEXT: ret float [[DIV]] 75; 76 %div = fdiv arcp float %x, 0x47E0000100000000 77 ret float %div 78} 79 80define <2 x float> @exact_inverse_splat(<2 x float> %x) { 81; CHECK-LABEL: @exact_inverse_splat( 82; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], splat (float 2.500000e-01) 83; CHECK-NEXT: ret <2 x float> [[DIV]] 84; 85 %div = fdiv <2 x float> %x, <float 4.0, float 4.0> 86 ret <2 x float> %div 87} 88 89define <vscale x 2 x float> @exact_inverse_scalable_splat(<vscale x 2 x float> %x) { 90; CHECK-LABEL: @exact_inverse_scalable_splat( 91; CHECK-NEXT: [[DIV:%.*]] = fmul <vscale x 2 x float> [[X:%.*]], splat (float 2.500000e-01) 92; CHECK-NEXT: ret <vscale x 2 x float> [[DIV]] 93; 94 %div = fdiv <vscale x 2 x float> %x, splat (float 4.0) 95 ret <vscale x 2 x float> %div 96} 97 98; Fast math allows us to replace this fdiv. 99 100define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) { 101; CHECK-LABEL: @not_exact_but_allow_recip_splat( 102; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], splat (float 0x3FD5555560000000) 103; CHECK-NEXT: ret <2 x float> [[DIV]] 104; 105 %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0> 106 ret <2 x float> %div 107} 108 109define <2 x float> @exact_inverse_vec(<2 x float> %x) { 110; CHECK-LABEL: @exact_inverse_vec( 111; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01> 112; CHECK-NEXT: ret <2 x float> [[DIV]] 113; 114 %div = fdiv <2 x float> %x, <float 4.0, float 8.0> 115 ret <2 x float> %div 116} 117 118define <2 x float> @not_exact_inverse_splat(<2 x float> %x) { 119; CHECK-LABEL: @not_exact_inverse_splat( 120; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], splat (float 3.000000e+00) 121; CHECK-NEXT: ret <2 x float> [[DIV]] 122; 123 %div = fdiv <2 x float> %x, <float 3.0, float 3.0> 124 ret <2 x float> %div 125} 126 127define <2 x float> @not_exact_inverse_vec(<2 x float> %x) { 128; CHECK-LABEL: @not_exact_inverse_vec( 129; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 3.000000e+00> 130; CHECK-NEXT: ret <2 x float> [[DIV]] 131; 132 %div = fdiv <2 x float> %x, <float 4.0, float 3.0> 133 ret <2 x float> %div 134} 135 136define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) { 137; CHECK-LABEL: @not_exact_inverse_vec_arcp( 138; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000> 139; CHECK-NEXT: ret <2 x float> [[DIV]] 140; 141 %div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0> 142 ret <2 x float> %div 143} 144 145define <2 x float> @not_exact_inverse_vec_arcp_with_poison_elt(<2 x float> %x) { 146; CHECK-LABEL: @not_exact_inverse_vec_arcp_with_poison_elt( 147; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp <2 x float> [[X:%.*]], <float poison, float 3.000000e+00> 148; CHECK-NEXT: ret <2 x float> [[DIV]] 149; 150 %div = fdiv arcp <2 x float> %x, <float poison, float 3.0> 151 ret <2 x float> %div 152} 153 154; (X / Y) / Z --> X / (Y * Z) 155 156define float @div_with_div_numerator(float %x, float %y, float %z) { 157; CHECK-LABEL: @div_with_div_numerator( 158; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp float [[Y:%.*]], [[Z:%.*]] 159; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp float [[X:%.*]], [[TMP1]] 160; CHECK-NEXT: ret float [[DIV2]] 161; 162 %div1 = fdiv ninf float %x, %y 163 %div2 = fdiv arcp reassoc float %div1, %z 164 ret float %div2 165} 166 167; Z / (X / Y) --> (Z * Y) / X 168 169define <2 x float> @div_with_div_denominator(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 170; CHECK-LABEL: @div_with_div_denominator( 171; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[Y:%.*]], [[Z:%.*]] 172; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp <2 x float> [[TMP1]], [[X:%.*]] 173; CHECK-NEXT: ret <2 x float> [[DIV2]] 174; 175 %div1 = fdiv nnan <2 x float> %x, %y 176 %div2 = fdiv arcp reassoc <2 x float> %z, %div1 177 ret <2 x float> %div2 178} 179 180; Don't create an extra multiply if we can't eliminate the first div. 181 182declare void @use_f32(float) 183 184define float @div_with_div_numerator_extra_use(float %x, float %y, float %z) { 185; CHECK-LABEL: @div_with_div_numerator_extra_use( 186; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 187; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[DIV1]], [[Z:%.*]] 188; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 189; CHECK-NEXT: ret float [[DIV2]] 190; 191 %div1 = fdiv float %x, %y 192 %div2 = fdiv fast float %div1, %z 193 call void @use_f32(float %div1) 194 ret float %div2 195} 196 197define float @div_with_div_denominator_extra_use(float %x, float %y, float %z) { 198; CHECK-LABEL: @div_with_div_denominator_extra_use( 199; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 200; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[Z:%.*]], [[DIV1]] 201; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 202; CHECK-NEXT: ret float [[DIV2]] 203; 204 %div1 = fdiv float %x, %y 205 %div2 = fdiv fast float %z, %div1 206 call void @use_f32(float %div1) 207 ret float %div2 208} 209 210; Z / (1.0 / Y) ==> Y * Z 211 212define float @div_with_div_denominator_with_one_as_numerator_extra_use(float %x, float %y, float %z) { 213; CHECK-LABEL: @div_with_div_denominator_with_one_as_numerator_extra_use( 214; CHECK-NEXT: [[DIV1:%.*]] = fdiv float 1.000000e+00, [[Y:%.*]] 215; CHECK-NEXT: [[DIV2:%.*]] = fmul reassoc arcp float [[Y]], [[Z:%.*]] 216; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 217; CHECK-NEXT: ret float [[DIV2]] 218; 219 %div1 = fdiv float 1.0, %y 220 %div2 = fdiv reassoc arcp float %z, %div1 221 call void @use_f32(float %div1) 222 ret float %div2 223} 224 225define float @fneg_fneg(float %x, float %y) { 226; CHECK-LABEL: @fneg_fneg( 227; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 228; CHECK-NEXT: ret float [[DIV]] 229; 230 %x.fneg = fsub float -0.0, %x 231 %y.fneg = fsub float -0.0, %y 232 %div = fdiv float %x.fneg, %y.fneg 233 ret float %div 234} 235 236define float @unary_fneg_unary_fneg(float %x, float %y) { 237; CHECK-LABEL: @unary_fneg_unary_fneg( 238; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 239; CHECK-NEXT: ret float [[DIV]] 240; 241 %x.fneg = fneg float %x 242 %y.fneg = fneg float %y 243 %div = fdiv float %x.fneg, %y.fneg 244 ret float %div 245} 246 247define float @unary_fneg_fneg(float %x, float %y) { 248; CHECK-LABEL: @unary_fneg_fneg( 249; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 250; CHECK-NEXT: ret float [[DIV]] 251; 252 %x.fneg = fneg float %x 253 %y.fneg = fsub float -0.0, %y 254 %div = fdiv float %x.fneg, %y.fneg 255 ret float %div 256} 257 258define float @fneg_unary_fneg(float %x, float %y) { 259; CHECK-LABEL: @fneg_unary_fneg( 260; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 261; CHECK-NEXT: ret float [[DIV]] 262; 263 %x.fneg = fsub float -0.0, %x 264 %y.fneg = fneg float %y 265 %div = fdiv float %x.fneg, %y.fneg 266 ret float %div 267} 268 269; The test above shows that no FMF are needed, but show that we are not dropping FMF. 270 271define float @fneg_fneg_fast(float %x, float %y) { 272; CHECK-LABEL: @fneg_fneg_fast( 273; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] 274; CHECK-NEXT: ret float [[DIV]] 275; 276 %x.fneg = fsub float -0.0, %x 277 %y.fneg = fsub float -0.0, %y 278 %div = fdiv fast float %x.fneg, %y.fneg 279 ret float %div 280} 281 282define float @unary_fneg_unary_fneg_fast(float %x, float %y) { 283; CHECK-LABEL: @unary_fneg_unary_fneg_fast( 284; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] 285; CHECK-NEXT: ret float [[DIV]] 286; 287 %x.fneg = fneg float %x 288 %y.fneg = fneg float %y 289 %div = fdiv fast float %x.fneg, %y.fneg 290 ret float %div 291} 292 293define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) { 294; CHECK-LABEL: @fneg_fneg_vec( 295; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 296; CHECK-NEXT: ret <2 x float> [[DIV]] 297; 298 %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x 299 %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y 300 %div = fdiv <2 x float> %xneg, %yneg 301 ret <2 x float> %div 302} 303 304define <2 x float> @unary_fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) { 305; CHECK-LABEL: @unary_fneg_unary_fneg_vec( 306; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 307; CHECK-NEXT: ret <2 x float> [[DIV]] 308; 309 %xneg = fneg <2 x float> %x 310 %yneg = fneg <2 x float> %y 311 %div = fdiv <2 x float> %xneg, %yneg 312 ret <2 x float> %div 313} 314 315define <2 x float> @fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) { 316; CHECK-LABEL: @fneg_unary_fneg_vec( 317; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 318; CHECK-NEXT: ret <2 x float> [[DIV]] 319; 320 %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x 321 %yneg = fneg <2 x float> %y 322 %div = fdiv <2 x float> %xneg, %yneg 323 ret <2 x float> %div 324} 325 326define <2 x float> @unary_fneg_fneg_vec(<2 x float> %x, <2 x float> %y) { 327; CHECK-LABEL: @unary_fneg_fneg_vec( 328; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 329; CHECK-NEXT: ret <2 x float> [[DIV]] 330; 331 %xneg = fneg <2 x float> %x 332 %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y 333 %div = fdiv <2 x float> %xneg, %yneg 334 ret <2 x float> %div 335} 336 337define <2 x float> @fneg_fneg_vec_poison_elts(<2 x float> %x, <2 x float> %y) { 338; CHECK-LABEL: @fneg_fneg_vec_poison_elts( 339; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 340; CHECK-NEXT: ret <2 x float> [[DIV]] 341; 342 %xneg = fsub <2 x float> <float poison, float -0.0>, %x 343 %yneg = fsub <2 x float> <float -0.0, float poison>, %y 344 %div = fdiv <2 x float> %xneg, %yneg 345 ret <2 x float> %div 346} 347 348define float @fneg_dividend_constant_divisor(float %x) { 349; CHECK-LABEL: @fneg_dividend_constant_divisor( 350; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00 351; CHECK-NEXT: ret float [[DIV]] 352; 353 %neg = fsub float -0.0, %x 354 %div = fdiv nsz float %neg, 3.0 355 ret float %div 356} 357 358define float @unary_fneg_dividend_constant_divisor(float %x) { 359; CHECK-LABEL: @unary_fneg_dividend_constant_divisor( 360; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00 361; CHECK-NEXT: ret float [[DIV]] 362; 363 %neg = fneg float %x 364 %div = fdiv nsz float %neg, 3.0 365 ret float %div 366} 367 368define float @fneg_divisor_constant_dividend(float %x) { 369; CHECK-LABEL: @fneg_divisor_constant_dividend( 370; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]] 371; CHECK-NEXT: ret float [[DIV]] 372; 373 %neg = fsub float -0.0, %x 374 %div = fdiv nnan float -3.0, %neg 375 ret float %div 376} 377 378define float @unary_fneg_divisor_constant_dividend(float %x) { 379; CHECK-LABEL: @unary_fneg_divisor_constant_dividend( 380; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]] 381; CHECK-NEXT: ret float [[DIV]] 382; 383 %neg = fneg float %x 384 %div = fdiv nnan float -3.0, %neg 385 ret float %div 386} 387 388define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) { 389; CHECK-LABEL: @fneg_dividend_constant_divisor_vec( 390; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 391; CHECK-NEXT: ret <2 x float> [[DIV]] 392; 393 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 394 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 395 ret <2 x float> %div 396} 397 398define <2 x float> @unary_fneg_dividend_constant_divisor_vec(<2 x float> %x) { 399; CHECK-LABEL: @unary_fneg_dividend_constant_divisor_vec( 400; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 401; CHECK-NEXT: ret <2 x float> [[DIV]] 402; 403 %neg = fneg <2 x float> %x 404 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 405 ret <2 x float> %div 406} 407 408define <2 x float> @fneg_dividend_constant_divisor_vec_poison_elt(<2 x float> %x) { 409; CHECK-LABEL: @fneg_dividend_constant_divisor_vec_poison_elt( 410; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 411; CHECK-NEXT: ret <2 x float> [[DIV]] 412; 413 %neg = fsub <2 x float> <float poison, float -0.0>, %x 414 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 415 ret <2 x float> %div 416} 417 418define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) { 419; CHECK-LABEL: @fneg_divisor_constant_dividend_vec( 420; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]] 421; CHECK-NEXT: ret <2 x float> [[DIV]] 422; 423 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 424 %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg 425 ret <2 x float> %div 426} 427 428define <2 x float> @unary_fneg_divisor_constant_dividend_vec(<2 x float> %x) { 429; CHECK-LABEL: @unary_fneg_divisor_constant_dividend_vec( 430; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]] 431; CHECK-NEXT: ret <2 x float> [[DIV]] 432; 433 %neg = fneg <2 x float> %x 434 %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg 435 ret <2 x float> %div 436} 437 438 439; X / (X * Y) --> 1.0 / Y 440 441define float @div_factor(float %x, float %y) { 442; CHECK-LABEL: @div_factor( 443; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan float 1.000000e+00, [[Y:%.*]] 444; CHECK-NEXT: ret float [[D]] 445; 446 %m = fmul float %x, %y 447 %d = fdiv nnan reassoc float %x, %m 448 ret float %d; 449} 450 451; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN. 452 453define float @div_factor_too_strict(float %x, float %y) { 454; CHECK-LABEL: @div_factor_too_strict( 455; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 456; CHECK-NEXT: [[D:%.*]] = fdiv reassoc float [[X]], [[M]] 457; CHECK-NEXT: ret float [[D]] 458; 459 %m = fmul float %x, %y 460 %d = fdiv reassoc float %x, %m 461 ret float %d 462} 463 464; Commute, verify vector types, and show that we are not dropping extra FMF. 465; X / (Y * X) --> 1.0 / Y 466 467define <2 x float> @div_factor_commute(<2 x float> %x, <2 x float> %y) { 468; CHECK-LABEL: @div_factor_commute( 469; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan ninf nsz <2 x float> splat (float 1.000000e+00), [[Y:%.*]] 470; CHECK-NEXT: ret <2 x float> [[D]] 471; 472 %m = fmul <2 x float> %y, %x 473 %d = fdiv nnan ninf nsz reassoc <2 x float> %x, %m 474 ret <2 x float> %d 475} 476 477; C1/(X*C2) => (C1/C2) / X 478 479define <2 x float> @div_constant_dividend1(<2 x float> %x) { 480; CHECK-LABEL: @div_constant_dividend1( 481; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 5.000000e+00, float 1.000000e+00>, [[X:%.*]] 482; CHECK-NEXT: ret <2 x float> [[T2]] 483; 484 %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0> 485 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float 7.0e0>, %t1 486 ret <2 x float> %t2 487} 488 489define <2 x float> @div_constant_dividend1_arcp_only(<2 x float> %x) { 490; CHECK-LABEL: @div_constant_dividend1_arcp_only( 491; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[X:%.*]], <float 3.000000e+00, float 7.000000e+00> 492; CHECK-NEXT: [[T2:%.*]] = fdiv arcp <2 x float> <float 1.500000e+01, float 7.000000e+00>, [[T1]] 493; CHECK-NEXT: ret <2 x float> [[T2]] 494; 495 %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0> 496 %t2 = fdiv arcp <2 x float> <float 15.0e0, float 7.0e0>, %t1 497 ret <2 x float> %t2 498} 499 500; C1/(X/C2) => (C1*C2) / X 501 502define <2 x float> @div_constant_dividend2(<2 x float> %x) { 503; CHECK-LABEL: @div_constant_dividend2( 504; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 4.500000e+01, float 4.900000e+01>, [[X:%.*]] 505; CHECK-NEXT: ret <2 x float> [[T2]] 506; 507 %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0> 508 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 509 ret <2 x float> %t2 510} 511 512define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) { 513; CHECK-LABEL: @div_constant_dividend2_reassoc_only( 514; CHECK-NEXT: [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float -7.000000e+00> 515; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc <2 x float> <float 1.500000e+01, float -7.000000e+00>, [[T1]] 516; CHECK-NEXT: ret <2 x float> [[T2]] 517; 518 %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0> 519 %t2 = fdiv reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 520 ret <2 x float> %t2 521} 522 523; C1/(C2/X) => (C1/C2) * X 524; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X 525 526define <2 x float> @div_constant_dividend3(<2 x float> %x) { 527; CHECK-LABEL: @div_constant_dividend3( 528; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00> 529; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000> 530; CHECK-NEXT: ret <2 x float> [[T2]] 531; 532 %t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x 533 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 534 ret <2 x float> %t2 535} 536 537define double @fdiv_fneg1(double %x, double %y) { 538; CHECK-LABEL: @fdiv_fneg1( 539; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 540; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]] 541; CHECK-NEXT: ret double [[DIV]] 542; 543 %neg = fsub double -0.0, %x 544 %div = fdiv double %neg, %y 545 ret double %div 546} 547 548define double @fdiv_unary_fneg1(double %x, double %y) { 549; CHECK-LABEL: @fdiv_unary_fneg1( 550; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 551; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]] 552; CHECK-NEXT: ret double [[DIV]] 553; 554 %neg = fneg double %x 555 %div = fdiv double %neg, %y 556 ret double %div 557} 558 559define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) { 560; CHECK-LABEL: @fdiv_fneg2( 561; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 562; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]] 563; CHECK-NEXT: ret <2 x float> [[DIV]] 564; 565 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 566 %div = fdiv <2 x float> %y, %neg 567 ret <2 x float> %div 568} 569 570define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) { 571; CHECK-LABEL: @fdiv_unary_fneg2( 572; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 573; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]] 574; CHECK-NEXT: ret <2 x float> [[DIV]] 575; 576 %neg = fneg <2 x float> %x 577 %div = fdiv <2 x float> %y, %neg 578 ret <2 x float> %div 579} 580 581define float @fdiv_fneg1_extra_use(float %x, float %y) { 582; CHECK-LABEL: @fdiv_fneg1_extra_use( 583; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 584; CHECK-NEXT: call void @use_f32(float [[NEG]]) 585; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]] 586; CHECK-NEXT: ret float [[DIV]] 587; 588 %neg = fsub float -0.0, %x 589 call void @use_f32(float %neg) 590 %div = fdiv float %neg, %y 591 ret float %div 592} 593 594define float @fabs_same_op(float %x) { 595; CHECK-LABEL: @fabs_same_op( 596; CHECK-NEXT: [[R:%.*]] = fdiv float [[X:%.*]], [[X]] 597; CHECK-NEXT: ret float [[R]] 598; 599 %a = call float @llvm.fabs.f32(float %x) 600 %r = fdiv float %a, %a 601 ret float %r 602} 603 604define float @fabs_same_op_extra_use(float %x) { 605; CHECK-LABEL: @fabs_same_op_extra_use( 606; CHECK-NEXT: [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 607; CHECK-NEXT: call void @use_f32(float [[A]]) 608; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]] 609; CHECK-NEXT: ret float [[R]] 610; 611 %a = call float @llvm.fabs.f32(float %x) 612 call void @use_f32(float %a) 613 %r = fdiv ninf reassoc float %a, %a 614 ret float %r 615} 616 617define float @fabs_fabs(float %x, float %y) { 618; CHECK-LABEL: @fabs_fabs( 619; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 620; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) 621; CHECK-NEXT: ret float [[R]] 622; 623 %x.fabs = call float @llvm.fabs.f32(float %x) 624 %y.fabs = call float @llvm.fabs.f32(float %y) 625 %r = fdiv float %x.fabs, %y.fabs 626 ret float %r 627} 628 629define float @fabs_fabs_extra_use1(float %x, float %y) { 630; CHECK-LABEL: @fabs_fabs_extra_use1( 631; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 632; CHECK-NEXT: call void @use_f32(float [[X_FABS]]) 633; CHECK-NEXT: [[TMP1:%.*]] = fdiv ninf float [[X]], [[Y:%.*]] 634; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]]) 635; CHECK-NEXT: ret float [[R]] 636; 637 %x.fabs = call float @llvm.fabs.f32(float %x) 638 call void @use_f32(float %x.fabs) 639 %y.fabs = call float @llvm.fabs.f32(float %y) 640 %r = fdiv ninf float %x.fabs, %y.fabs 641 ret float %r 642} 643 644define float @fabs_fabs_extra_use2(float %x, float %y) { 645; CHECK-LABEL: @fabs_fabs_extra_use2( 646; CHECK-NEXT: [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]]) 647; CHECK-NEXT: call void @use_f32(float [[Y_FABS]]) 648; CHECK-NEXT: [[TMP1:%.*]] = fdiv reassoc ninf float [[X:%.*]], [[Y]] 649; CHECK-NEXT: [[R:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]]) 650; CHECK-NEXT: ret float [[R]] 651; 652 %x.fabs = call fast float @llvm.fabs.f32(float %x) 653 %y.fabs = call fast float @llvm.fabs.f32(float %y) 654 call void @use_f32(float %y.fabs) 655 %r = fdiv reassoc ninf float %x.fabs, %y.fabs 656 ret float %r 657} 658 659; negative test - don't create an extra instruction 660 661define float @fabs_fabs_extra_use3(float %x, float %y) { 662; CHECK-LABEL: @fabs_fabs_extra_use3( 663; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 664; CHECK-NEXT: call void @use_f32(float [[X_FABS]]) 665; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) 666; CHECK-NEXT: call void @use_f32(float [[Y_FABS]]) 667; CHECK-NEXT: [[R:%.*]] = fdiv float [[X_FABS]], [[Y_FABS]] 668; CHECK-NEXT: ret float [[R]] 669; 670 %x.fabs = call float @llvm.fabs.f32(float %x) 671 call void @use_f32(float %x.fabs) 672 %y.fabs = call float @llvm.fabs.f32(float %y) 673 call void @use_f32(float %y.fabs) 674 %r = fdiv float %x.fabs, %y.fabs 675 ret float %r 676} 677 678define float @pow_divisor(float %x, float %y, float %z) { 679; CHECK-LABEL: @pow_divisor( 680; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]] 681; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.pow.f32(float [[X:%.*]], float [[TMP1]]) 682; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]] 683; CHECK-NEXT: ret float [[R]] 684; 685 %p = call float @llvm.pow.f32(float %x, float %y) 686 %r = fdiv reassoc arcp float %z, %p 687 ret float %r 688} 689 690; Negative test - don't create an extra pow 691 692define float @pow_divisor_extra_use(float %x, float %y, float %z) { 693; CHECK-LABEL: @pow_divisor_extra_use( 694; CHECK-NEXT: [[P:%.*]] = call float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 695; CHECK-NEXT: call void @use_f32(float [[P]]) 696; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]] 697; CHECK-NEXT: ret float [[R]] 698; 699 %p = call float @llvm.pow.f32(float %x, float %y) 700 call void @use_f32(float %p) 701 %r = fdiv reassoc arcp float %z, %p 702 ret float %r 703} 704 705; Negative test - must have reassoc+arcp 706 707define float @pow_divisor_not_enough_fmf(float %x, float %y, float %z) { 708; CHECK-LABEL: @pow_divisor_not_enough_fmf( 709; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 710; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]] 711; CHECK-NEXT: ret float [[R]] 712; 713 %p = call fast float @llvm.pow.f32(float %x, float %y) 714 %r = fdiv reassoc float %z, %p 715 ret float %r 716} 717 718; Negative test - must have reassoc+arcp 719 720define float @pow_divisor_not_enough_fmf2(float %x, float %y, float %z) { 721; CHECK-LABEL: @pow_divisor_not_enough_fmf2( 722; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 723; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]] 724; CHECK-NEXT: ret float [[R]] 725; 726 %p = call fast float @llvm.pow.f32(float %x, float %y) 727 %r = fdiv arcp float %z, %p 728 ret float %r 729} 730 731; Special-case - reciprocal does not require extra fmul 732 733define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) { 734; CHECK-LABEL: @pow_recip( 735; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]] 736; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.pow.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]]) 737; CHECK-NEXT: ret <2 x half> [[TMP2]] 738; 739 %p = call <2 x half> @llvm.pow.v2f16(<2 x half> %x, <2 x half> %y) 740 %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p 741 ret <2 x half> %r 742} 743 744define float @exp_divisor(float %y, float %z) { 745; CHECK-LABEL: @exp_divisor( 746; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]] 747; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp.f32(float [[TMP1]]) 748; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]] 749; CHECK-NEXT: ret float [[R]] 750; 751 %p = call float @llvm.exp.f32(float %y) 752 %r = fdiv reassoc arcp float %z, %p 753 ret float %r 754} 755 756; Negative test - don't create an extra exp 757 758define float @exp_divisor_extra_use(float %y, float %z) { 759; CHECK-LABEL: @exp_divisor_extra_use( 760; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp.f32(float [[Y:%.*]]) 761; CHECK-NEXT: call void @use_f32(float [[P]]) 762; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]] 763; CHECK-NEXT: ret float [[R]] 764; 765 %p = call float @llvm.exp.f32(float %y) 766 call void @use_f32(float %p) 767 %r = fdiv reassoc arcp float %z, %p 768 ret float %r 769} 770 771; Negative test - must have reassoc+arcp 772 773define float @exp_divisor_not_enough_fmf(float %y, float %z) { 774; CHECK-LABEL: @exp_divisor_not_enough_fmf( 775; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]]) 776; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]] 777; CHECK-NEXT: ret float [[R]] 778; 779 %p = call fast float @llvm.exp.f32(float %y) 780 %r = fdiv reassoc float %z, %p 781 ret float %r 782} 783 784; Negative test - must have reassoc+arcp 785 786define float @exp_divisor_not_enough_fmf2(float %y, float %z) { 787; CHECK-LABEL: @exp_divisor_not_enough_fmf2( 788; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp.f32(float [[Y:%.*]]) 789; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]] 790; CHECK-NEXT: ret float [[R]] 791; 792 %p = call fast float @llvm.exp.f32(float %y) 793 %r = fdiv arcp float %z, %p 794 ret float %r 795} 796 797; Special-case - reciprocal does not require extra fmul 798 799define <2 x half> @exp_recip(<2 x half> %x, <2 x half> %y) { 800; CHECK-LABEL: @exp_recip( 801; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]] 802; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp.v2f16(<2 x half> [[TMP1]]) 803; CHECK-NEXT: ret <2 x half> [[TMP2]] 804; 805 %p = call <2 x half> @llvm.exp.v2f16(<2 x half> %y) 806 %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p 807 ret <2 x half> %r 808} 809 810define float @exp2_divisor(float %y, float %z) { 811; CHECK-LABEL: @exp2_divisor( 812; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]] 813; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.exp2.f32(float [[TMP1]]) 814; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[Z:%.*]], [[TMP2]] 815; CHECK-NEXT: ret float [[R]] 816; 817 %p = call float @llvm.exp2.f32(float %y) 818 %r = fdiv reassoc arcp float %z, %p 819 ret float %r 820} 821 822; Negative test - don't create an extra exp 823 824define float @exp2_divisor_extra_use(float %y, float %z) { 825; CHECK-LABEL: @exp2_divisor_extra_use( 826; CHECK-NEXT: [[P:%.*]] = call float @llvm.exp2.f32(float [[Y:%.*]]) 827; CHECK-NEXT: call void @use_f32(float [[P]]) 828; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]] 829; CHECK-NEXT: ret float [[R]] 830; 831 %p = call float @llvm.exp2.f32(float %y) 832 call void @use_f32(float %p) 833 %r = fdiv reassoc arcp float %z, %p 834 ret float %r 835} 836 837; Negative test - must have reassoc+arcp 838 839define float @exp2_divisor_not_enough_fmf(float %y, float %z) { 840; CHECK-LABEL: @exp2_divisor_not_enough_fmf( 841; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]]) 842; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]] 843; CHECK-NEXT: ret float [[R]] 844; 845 %p = call fast float @llvm.exp2.f32(float %y) 846 %r = fdiv reassoc float %z, %p 847 ret float %r 848} 849 850; Negative test - must have reassoc+arcp 851 852define float @exp2_divisor_not_enough_fmf2(float %y, float %z) { 853; CHECK-LABEL: @exp2_divisor_not_enough_fmf2( 854; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.exp2.f32(float [[Y:%.*]]) 855; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]] 856; CHECK-NEXT: ret float [[R]] 857; 858 %p = call fast float @llvm.exp2.f32(float %y) 859 %r = fdiv arcp float %z, %p 860 ret float %r 861} 862 863; Special-case - reciprocal does not require extra fmul 864 865define <2 x half> @exp2_recip(<2 x half> %x, <2 x half> %y) { 866; CHECK-LABEL: @exp2_recip( 867; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]] 868; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.exp2.v2f16(<2 x half> [[TMP1]]) 869; CHECK-NEXT: ret <2 x half> [[TMP2]] 870; 871 %p = call <2 x half> @llvm.exp2.v2f16(<2 x half> %y) 872 %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p 873 ret <2 x half> %r 874} 875 876define float @powi_divisor(float %x, i32 %y, float %z) { 877; CHECK-LABEL: @powi_divisor( 878; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] 879; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[TMP1]]) 880; CHECK-NEXT: [[R:%.*]] = fmul reassoc ninf arcp float [[Z:%.*]], [[TMP2]] 881; CHECK-NEXT: ret float [[R]] 882; 883 %p = call float @llvm.powi.f32.i32(float %x, i32 %y) 884 %r = fdiv reassoc arcp ninf float %z, %p 885 ret float %r 886} 887 888; Negative test - don't create an extra pow 889 890define float @powi_divisor_extra_use(float %x, i32 %y, float %z) { 891; CHECK-LABEL: @powi_divisor_extra_use( 892; CHECK-NEXT: [[P:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) 893; CHECK-NEXT: call void @use_f32(float [[P]]) 894; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf arcp float [[Z:%.*]], [[P]] 895; CHECK-NEXT: ret float [[R]] 896; 897 %p = call float @llvm.powi.f32.i32(float %x, i32 %y) 898 call void @use_f32(float %p) 899 %r = fdiv reassoc arcp ninf float %z, %p 900 ret float %r 901} 902 903; Negative test - must have reassoc+arcp+ninf 904 905define float @powi_divisor_not_enough_fmf(float %x, i32 %y, float %z) { 906; CHECK-LABEL: @powi_divisor_not_enough_fmf( 907; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) 908; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf float [[Z:%.*]], [[P]] 909; CHECK-NEXT: ret float [[R]] 910; 911 %p = call fast float @llvm.powi.f32.i32(float %x, i32 %y) 912 %r = fdiv reassoc ninf float %z, %p 913 ret float %r 914} 915 916; Negative test - must have reassoc+arcp+ninf 917 918define float @powi_divisor_not_enough_fmf2(float %x, i32 %y, float %z) { 919; CHECK-LABEL: @powi_divisor_not_enough_fmf2( 920; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.powi.f32.i32(float [[X:%.*]], i32 [[Y:%.*]]) 921; CHECK-NEXT: [[R:%.*]] = fdiv ninf arcp float [[Z:%.*]], [[P]] 922; CHECK-NEXT: ret float [[R]] 923; 924 %p = call fast float @llvm.powi.f32.i32(float %x, i32 %y) 925 %r = fdiv arcp ninf float %z, %p 926 ret float %r 927} 928 929; Special-case - reciprocal does not require extra fmul 930 931define <2 x half> @powi_recip(<2 x half> %x, i32 %y) { 932; CHECK-LABEL: @powi_recip( 933; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] 934; CHECK-NEXT: [[TMP2:%.*]] = call reassoc nnan ninf arcp <2 x half> @llvm.powi.v2f16.i32(<2 x half> [[X:%.*]], i32 [[TMP1]]) 935; CHECK-NEXT: ret <2 x half> [[TMP2]] 936; 937 %p = call <2 x half> @llvm.powi.v2f16.i32(<2 x half> %x, i32 %y) 938 %r = fdiv reassoc arcp nnan ninf <2 x half> <half 1.0, half 1.0>, %p 939 ret <2 x half> %r 940} 941 942define float @fdiv_zero_f32(float %x) { 943; CHECK-LABEL: @fdiv_zero_f32( 944; CHECK-NEXT: [[FDIV:%.*]] = fdiv float [[X:%.*]], 0.000000e+00 945; CHECK-NEXT: ret float [[FDIV]] 946; 947 %fdiv = fdiv float %x, 0.0 948 ret float %fdiv 949} 950 951; https://alive2.llvm.org/ce/z/gLBFKB 952define float @fdiv_nnan_zero_f32(float %x) { 953; CHECK-LABEL: @fdiv_nnan_zero_f32( 954; CHECK-NEXT: [[FDIV:%.*]] = call nnan float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]]) 955; CHECK-NEXT: ret float [[FDIV]] 956; 957 %fdiv = fdiv nnan float %x, 0.0 958 ret float %fdiv 959} 960 961define <2 x float> @fdiv_nnan_zero_v2f32(<2 x float> %x) { 962; CHECK-LABEL: @fdiv_nnan_zero_v2f32( 963; CHECK-NEXT: [[FDIV:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X:%.*]]) 964; CHECK-NEXT: ret <2 x float> [[FDIV]] 965; 966 %fdiv = fdiv nnan <2 x float> %x, zeroinitializer 967 ret <2 x float> %fdiv 968} 969 970define float @fdiv_nnan_zero_f32_fmf(float %x) { 971; CHECK-LABEL: @fdiv_nnan_zero_f32_fmf( 972; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz float @llvm.copysign.f32(float 0x7FF0000000000000, float [[X:%.*]]) 973; CHECK-NEXT: ret float [[FDIV]] 974; 975 %fdiv = fdiv nnan nsz float %x, 0.0 976 ret float %fdiv 977} 978 979define <2 x float> @fdiv_nnan_zero_v2f32_fmf(<2 x float> %x) { 980; CHECK-LABEL: @fdiv_nnan_zero_v2f32_fmf( 981; CHECK-NEXT: [[FDIV:%.*]] = call nnan nsz <2 x float> @llvm.copysign.v2f32(<2 x float> splat (float 0x7FF0000000000000), <2 x float> [[X:%.*]]) 982; CHECK-NEXT: ret <2 x float> [[FDIV]] 983; 984 %fdiv = fdiv nnan nsz <2 x float> %x, zeroinitializer 985 ret <2 x float> %fdiv 986} 987 988define float @fdiv_nnan_neg_zero_f32(float %x) { 989; CHECK-LABEL: @fdiv_nnan_neg_zero_f32( 990; CHECK-NEXT: [[FDIV:%.*]] = fdiv nnan float [[X:%.*]], -0.000000e+00 991; CHECK-NEXT: ret float [[FDIV]] 992; 993 %fdiv = fdiv nnan float %x, -0.0 994 ret float %fdiv 995} 996 997define double @test_positive_zero_nsz(double %X) { 998; CHECK-LABEL: @test_positive_zero_nsz( 999; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]]) 1000; CHECK-NEXT: ret double [[TMP1]] 1001; 1002 %1 = fdiv nnan nsz double %X, 0.0 1003 ret double %1 1004} 1005 1006define double @test_negative_zero_nsz(double %X) { 1007; CHECK-LABEL: @test_negative_zero_nsz( 1008; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]]) 1009; CHECK-NEXT: ret double [[TMP1]] 1010; 1011 %1 = fdiv nnan nsz double %X, -0.0 1012 ret double %1 1013} 1014 1015define double @test_positive_zero(double %X) { 1016; CHECK-LABEL: @test_positive_zero( 1017; CHECK-NEXT: [[TMP1:%.*]] = call nnan double @llvm.copysign.f64(double 0x7FF0000000000000, double [[X:%.*]]) 1018; CHECK-NEXT: ret double [[TMP1]] 1019; 1020 %1 = fdiv nnan double %X, 0.0 1021 ret double %1 1022} 1023 1024define double @test_negative_zero(double %X) { 1025; CHECK-LABEL: @test_negative_zero( 1026; CHECK-NEXT: [[TMP1:%.*]] = fdiv nnan double [[X:%.*]], -0.000000e+00 1027; CHECK-NEXT: ret double [[TMP1]] 1028; 1029 %1 = fdiv nnan double %X, -0.0 1030 ret double %1 1031} 1032 1033define <2 x double> @test_positive_zero_vector_nsz(<2 x double> %X) { 1034; CHECK-LABEL: @test_positive_zero_vector_nsz( 1035; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]]) 1036; CHECK-NEXT: ret <2 x double> [[TMP1]] 1037; 1038 %1 = fdiv nnan nsz <2 x double> %X, <double 0.0, double 0.0> 1039 ret <2 x double> %1 1040} 1041 1042define <2 x double> @test_negative_zero_vector_nsz(<2 x double> %X) { 1043; CHECK-LABEL: @test_negative_zero_vector_nsz( 1044; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]]) 1045; CHECK-NEXT: ret <2 x double> [[TMP1]] 1046; 1047 %1 = fdiv nnan nsz <2 x double> %X, <double -0.0, double 0.0> 1048 ret <2 x double> %1 1049} 1050 1051define <2 x double> @test_positive_zero_vector(<2 x double> %X) { 1052; CHECK-LABEL: @test_positive_zero_vector( 1053; CHECK-NEXT: [[TMP1:%.*]] = call nnan <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 0x7FF0000000000000), <2 x double> [[X:%.*]]) 1054; CHECK-NEXT: ret <2 x double> [[TMP1]] 1055; 1056 %1 = fdiv nnan <2 x double> %X, <double 0.0, double 0.0> 1057 ret <2 x double> %1 1058} 1059 1060define <2 x double> @test_negative_zero_vector(<2 x double> %X) { 1061; CHECK-LABEL: @test_negative_zero_vector( 1062; CHECK-NEXT: [[TMP1:%.*]] = fdiv nnan <2 x double> [[X:%.*]], <double -0.000000e+00, double 0.000000e+00> 1063; CHECK-NEXT: ret <2 x double> [[TMP1]] 1064; 1065 %1 = fdiv nnan <2 x double> %X, <double -0.0, double 0.0> 1066 ret <2 x double> %1 1067} 1068