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