1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -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 7 8define float @exact_inverse(float %x) { 9; CHECK-LABEL: @exact_inverse( 10; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 1.250000e-01 11; CHECK-NEXT: ret float [[DIV]] 12; 13 %div = fdiv float %x, 8.0 14 ret float %div 15} 16 17; Min normal float = 1.17549435E-38 18 19define float @exact_inverse2(float %x) { 20; CHECK-LABEL: @exact_inverse2( 21; CHECK-NEXT: [[DIV:%.*]] = fmul float [[X:%.*]], 0x47D0000000000000 22; CHECK-NEXT: ret float [[DIV]] 23; 24 %div = fdiv float %x, 0x3810000000000000 25 ret float %div 26} 27 28; Max exponent = 1.70141183E+38; don't transform to multiply with denormal. 29 30define float @exact_inverse_but_denorm(float %x) { 31; CHECK-LABEL: @exact_inverse_but_denorm( 32; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x47E0000000000000 33; CHECK-NEXT: ret float [[DIV]] 34; 35 %div = fdiv float %x, 0x47E0000000000000 36 ret float %div 37} 38 39; Denormal = float 1.40129846E-45; inverse can't be represented. 40 41define float @not_exact_inverse2(float %x) { 42; CHECK-LABEL: @not_exact_inverse2( 43; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], 0x36A0000000000000 44; CHECK-NEXT: ret float [[DIV]] 45; 46 %div = fdiv float %x, 0x36A0000000000000 47 ret float %div 48} 49 50; Fast math allows us to replace this fdiv. 51 52define float @not_exact_but_allow_recip(float %x) { 53; CHECK-LABEL: @not_exact_but_allow_recip( 54; CHECK-NEXT: [[DIV:%.*]] = fmul arcp float [[X:%.*]], 0x3FD5555560000000 55; CHECK-NEXT: ret float [[DIV]] 56; 57 %div = fdiv arcp float %x, 3.0 58 ret float %div 59} 60 61; Fast math allows us to replace this fdiv, but we don't to avoid a denormal. 62; TODO: What if the function attributes tell us that denormals are flushed? 63 64define float @not_exact_but_allow_recip_but_denorm(float %x) { 65; CHECK-LABEL: @not_exact_but_allow_recip_but_denorm( 66; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp float [[X:%.*]], 0x47E0000100000000 67; CHECK-NEXT: ret float [[DIV]] 68; 69 %div = fdiv arcp float %x, 0x47E0000100000000 70 ret float %div 71} 72 73define <2 x float> @exact_inverse_splat(<2 x float> %x) { 74; CHECK-LABEL: @exact_inverse_splat( 75; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 2.500000e-01> 76; CHECK-NEXT: ret <2 x float> [[DIV]] 77; 78 %div = fdiv <2 x float> %x, <float 4.0, float 4.0> 79 ret <2 x float> %div 80} 81 82; Fast math allows us to replace this fdiv. 83 84define <2 x float> @not_exact_but_allow_recip_splat(<2 x float> %x) { 85; CHECK-LABEL: @not_exact_but_allow_recip_splat( 86; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 0x3FD5555560000000, float 0x3FD5555560000000> 87; CHECK-NEXT: ret <2 x float> [[DIV]] 88; 89 %div = fdiv arcp <2 x float> %x, <float 3.0, float 3.0> 90 ret <2 x float> %div 91} 92 93define <2 x float> @exact_inverse_vec(<2 x float> %x) { 94; CHECK-LABEL: @exact_inverse_vec( 95; CHECK-NEXT: [[DIV:%.*]] = fmul <2 x float> [[X:%.*]], <float 2.500000e-01, float 1.250000e-01> 96; CHECK-NEXT: ret <2 x float> [[DIV]] 97; 98 %div = fdiv <2 x float> %x, <float 4.0, float 8.0> 99 ret <2 x float> %div 100} 101 102define <2 x float> @not_exact_inverse_splat(<2 x float> %x) { 103; CHECK-LABEL: @not_exact_inverse_splat( 104; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float 3.000000e+00> 105; CHECK-NEXT: ret <2 x float> [[DIV]] 106; 107 %div = fdiv <2 x float> %x, <float 3.0, float 3.0> 108 ret <2 x float> %div 109} 110 111define <2 x float> @not_exact_inverse_vec(<2 x float> %x) { 112; CHECK-LABEL: @not_exact_inverse_vec( 113; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.000000e+00, float 3.000000e+00> 114; CHECK-NEXT: ret <2 x float> [[DIV]] 115; 116 %div = fdiv <2 x float> %x, <float 4.0, float 3.0> 117 ret <2 x float> %div 118} 119 120define <2 x float> @not_exact_inverse_vec_arcp(<2 x float> %x) { 121; CHECK-LABEL: @not_exact_inverse_vec_arcp( 122; CHECK-NEXT: [[DIV:%.*]] = fmul arcp <2 x float> [[X:%.*]], <float 2.500000e-01, float 0x3FD5555560000000> 123; CHECK-NEXT: ret <2 x float> [[DIV]] 124; 125 %div = fdiv arcp <2 x float> %x, <float 4.0, float 3.0> 126 ret <2 x float> %div 127} 128 129define <2 x float> @not_exact_inverse_vec_arcp_with_undef_elt(<2 x float> %x) { 130; CHECK-LABEL: @not_exact_inverse_vec_arcp_with_undef_elt( 131; CHECK-NEXT: [[DIV:%.*]] = fdiv arcp <2 x float> [[X:%.*]], <float undef, float 3.000000e+00> 132; CHECK-NEXT: ret <2 x float> [[DIV]] 133; 134 %div = fdiv arcp <2 x float> %x, <float undef, float 3.0> 135 ret <2 x float> %div 136} 137 138; (X / Y) / Z --> X / (Y * Z) 139 140define float @div_with_div_numerator(float %x, float %y, float %z) { 141; CHECK-LABEL: @div_with_div_numerator( 142; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp float [[Y:%.*]], [[Z:%.*]] 143; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp float [[X:%.*]], [[TMP1]] 144; CHECK-NEXT: ret float [[DIV2]] 145; 146 %div1 = fdiv ninf float %x, %y 147 %div2 = fdiv arcp reassoc float %div1, %z 148 ret float %div2 149} 150 151; Z / (X / Y) --> (Z * Y) / X 152 153define <2 x float> @div_with_div_denominator(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 154; CHECK-LABEL: @div_with_div_denominator( 155; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[Y:%.*]], [[Z:%.*]] 156; CHECK-NEXT: [[DIV2:%.*]] = fdiv reassoc arcp <2 x float> [[TMP1]], [[X:%.*]] 157; CHECK-NEXT: ret <2 x float> [[DIV2]] 158; 159 %div1 = fdiv nnan <2 x float> %x, %y 160 %div2 = fdiv arcp reassoc <2 x float> %z, %div1 161 ret <2 x float> %div2 162} 163 164; Don't create an extra multiply if we can't eliminate the first div. 165 166declare void @use_f32(float) 167 168define float @div_with_div_numerator_extra_use(float %x, float %y, float %z) { 169; CHECK-LABEL: @div_with_div_numerator_extra_use( 170; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 171; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[DIV1]], [[Z:%.*]] 172; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 173; CHECK-NEXT: ret float [[DIV2]] 174; 175 %div1 = fdiv float %x, %y 176 %div2 = fdiv fast float %div1, %z 177 call void @use_f32(float %div1) 178 ret float %div2 179} 180 181define float @div_with_div_denominator_extra_use(float %x, float %y, float %z) { 182; CHECK-LABEL: @div_with_div_denominator_extra_use( 183; CHECK-NEXT: [[DIV1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 184; CHECK-NEXT: [[DIV2:%.*]] = fdiv fast float [[Z:%.*]], [[DIV1]] 185; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 186; CHECK-NEXT: ret float [[DIV2]] 187; 188 %div1 = fdiv float %x, %y 189 %div2 = fdiv fast float %z, %div1 190 call void @use_f32(float %div1) 191 ret float %div2 192} 193 194; Z / (1.0 / Y) ==> Y * Z 195 196define float @div_with_div_denominator_with_one_as_numerator_extra_use(float %x, float %y, float %z) { 197; CHECK-LABEL: @div_with_div_denominator_with_one_as_numerator_extra_use( 198; CHECK-NEXT: [[DIV1:%.*]] = fdiv float 1.000000e+00, [[Y:%.*]] 199; CHECK-NEXT: [[DIV2:%.*]] = fmul reassoc arcp float [[Y]], [[Z:%.*]] 200; CHECK-NEXT: call void @use_f32(float [[DIV1]]) 201; CHECK-NEXT: ret float [[DIV2]] 202; 203 %div1 = fdiv float 1.0, %y 204 %div2 = fdiv reassoc arcp float %z, %div1 205 call void @use_f32(float %div1) 206 ret float %div2 207} 208 209define float @fneg_fneg(float %x, float %y) { 210; CHECK-LABEL: @fneg_fneg( 211; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 212; CHECK-NEXT: ret float [[DIV]] 213; 214 %x.fneg = fsub float -0.0, %x 215 %y.fneg = fsub float -0.0, %y 216 %div = fdiv float %x.fneg, %y.fneg 217 ret float %div 218} 219 220define float @unary_fneg_unary_fneg(float %x, float %y) { 221; CHECK-LABEL: @unary_fneg_unary_fneg( 222; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 223; CHECK-NEXT: ret float [[DIV]] 224; 225 %x.fneg = fneg float %x 226 %y.fneg = fneg float %y 227 %div = fdiv float %x.fneg, %y.fneg 228 ret float %div 229} 230 231define float @unary_fneg_fneg(float %x, float %y) { 232; CHECK-LABEL: @unary_fneg_fneg( 233; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 234; CHECK-NEXT: ret float [[DIV]] 235; 236 %x.fneg = fneg float %x 237 %y.fneg = fsub float -0.0, %y 238 %div = fdiv float %x.fneg, %y.fneg 239 ret float %div 240} 241 242define float @fneg_unary_fneg(float %x, float %y) { 243; CHECK-LABEL: @fneg_unary_fneg( 244; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 245; CHECK-NEXT: ret float [[DIV]] 246; 247 %x.fneg = fsub float -0.0, %x 248 %y.fneg = fneg float %y 249 %div = fdiv float %x.fneg, %y.fneg 250 ret float %div 251} 252 253; The test above shows that no FMF are needed, but show that we are not dropping FMF. 254 255define float @fneg_fneg_fast(float %x, float %y) { 256; CHECK-LABEL: @fneg_fneg_fast( 257; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] 258; CHECK-NEXT: ret float [[DIV]] 259; 260 %x.fneg = fsub float -0.0, %x 261 %y.fneg = fsub float -0.0, %y 262 %div = fdiv fast float %x.fneg, %y.fneg 263 ret float %div 264} 265 266define float @unary_fneg_unary_fneg_fast(float %x, float %y) { 267; CHECK-LABEL: @unary_fneg_unary_fneg_fast( 268; CHECK-NEXT: [[DIV:%.*]] = fdiv fast float [[X:%.*]], [[Y:%.*]] 269; CHECK-NEXT: ret float [[DIV]] 270; 271 %x.fneg = fneg float %x 272 %y.fneg = fneg float %y 273 %div = fdiv fast float %x.fneg, %y.fneg 274 ret float %div 275} 276 277define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) { 278; CHECK-LABEL: @fneg_fneg_vec( 279; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 280; CHECK-NEXT: ret <2 x float> [[DIV]] 281; 282 %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x 283 %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y 284 %div = fdiv <2 x float> %xneg, %yneg 285 ret <2 x float> %div 286} 287 288define <2 x float> @unary_fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) { 289; CHECK-LABEL: @unary_fneg_unary_fneg_vec( 290; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 291; CHECK-NEXT: ret <2 x float> [[DIV]] 292; 293 %xneg = fneg <2 x float> %x 294 %yneg = fneg <2 x float> %y 295 %div = fdiv <2 x float> %xneg, %yneg 296 ret <2 x float> %div 297} 298 299define <2 x float> @fneg_unary_fneg_vec(<2 x float> %x, <2 x float> %y) { 300; CHECK-LABEL: @fneg_unary_fneg_vec( 301; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 302; CHECK-NEXT: ret <2 x float> [[DIV]] 303; 304 %xneg = fsub <2 x float> <float -0.0, float -0.0>, %x 305 %yneg = fneg <2 x float> %y 306 %div = fdiv <2 x float> %xneg, %yneg 307 ret <2 x float> %div 308} 309 310define <2 x float> @unary_fneg_fneg_vec(<2 x float> %x, <2 x float> %y) { 311; CHECK-LABEL: @unary_fneg_fneg_vec( 312; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 313; CHECK-NEXT: ret <2 x float> [[DIV]] 314; 315 %xneg = fneg <2 x float> %x 316 %yneg = fsub <2 x float> <float -0.0, float -0.0>, %y 317 %div = fdiv <2 x float> %xneg, %yneg 318 ret <2 x float> %div 319} 320 321define <2 x float> @fneg_fneg_vec_undef_elts(<2 x float> %x, <2 x float> %y) { 322; CHECK-LABEL: @fneg_fneg_vec_undef_elts( 323; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[X:%.*]], [[Y:%.*]] 324; CHECK-NEXT: ret <2 x float> [[DIV]] 325; 326 %xneg = fsub <2 x float> <float undef, float -0.0>, %x 327 %yneg = fsub <2 x float> <float -0.0, float undef>, %y 328 %div = fdiv <2 x float> %xneg, %yneg 329 ret <2 x float> %div 330} 331 332define float @fneg_dividend_constant_divisor(float %x) { 333; CHECK-LABEL: @fneg_dividend_constant_divisor( 334; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00 335; CHECK-NEXT: ret float [[DIV]] 336; 337 %neg = fsub float -0.0, %x 338 %div = fdiv nsz float %neg, 3.0 339 ret float %div 340} 341 342define float @unary_fneg_dividend_constant_divisor(float %x) { 343; CHECK-LABEL: @unary_fneg_dividend_constant_divisor( 344; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00 345; CHECK-NEXT: ret float [[DIV]] 346; 347 %neg = fneg float %x 348 %div = fdiv nsz float %neg, 3.0 349 ret float %div 350} 351 352define float @fneg_divisor_constant_dividend(float %x) { 353; CHECK-LABEL: @fneg_divisor_constant_dividend( 354; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]] 355; CHECK-NEXT: ret float [[DIV]] 356; 357 %neg = fsub float -0.0, %x 358 %div = fdiv nnan float -3.0, %neg 359 ret float %div 360} 361 362define float @unary_fneg_divisor_constant_dividend(float %x) { 363; CHECK-LABEL: @unary_fneg_divisor_constant_dividend( 364; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float 3.000000e+00, [[X:%.*]] 365; CHECK-NEXT: ret float [[DIV]] 366; 367 %neg = fneg float %x 368 %div = fdiv nnan float -3.0, %neg 369 ret float %div 370} 371 372define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) { 373; CHECK-LABEL: @fneg_dividend_constant_divisor_vec( 374; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 375; CHECK-NEXT: ret <2 x float> [[DIV]] 376; 377 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 378 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 379 ret <2 x float> %div 380} 381 382define <2 x float> @unary_fneg_dividend_constant_divisor_vec(<2 x float> %x) { 383; CHECK-LABEL: @unary_fneg_dividend_constant_divisor_vec( 384; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 385; CHECK-NEXT: ret <2 x float> [[DIV]] 386; 387 %neg = fneg <2 x float> %x 388 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 389 ret <2 x float> %div 390} 391 392define <2 x float> @fneg_dividend_constant_divisor_vec_undef_elt(<2 x float> %x) { 393; CHECK-LABEL: @fneg_dividend_constant_divisor_vec_undef_elt( 394; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], <float -3.000000e+00, float 8.000000e+00> 395; CHECK-NEXT: ret <2 x float> [[DIV]] 396; 397 %neg = fsub <2 x float> <float undef, float -0.0>, %x 398 %div = fdiv ninf <2 x float> %neg, <float 3.0, float -8.0> 399 ret <2 x float> %div 400} 401 402define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) { 403; CHECK-LABEL: @fneg_divisor_constant_dividend_vec( 404; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]] 405; CHECK-NEXT: ret <2 x float> [[DIV]] 406; 407 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 408 %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg 409 ret <2 x float> %div 410} 411 412define <2 x float> @unary_fneg_divisor_constant_dividend_vec(<2 x float> %x) { 413; CHECK-LABEL: @unary_fneg_divisor_constant_dividend_vec( 414; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> <float 3.000000e+00, float -5.000000e+00>, [[X:%.*]] 415; CHECK-NEXT: ret <2 x float> [[DIV]] 416; 417 %neg = fneg <2 x float> %x 418 %div = fdiv afn <2 x float> <float -3.0, float 5.0>, %neg 419 ret <2 x float> %div 420} 421 422 423; X / (X * Y) --> 1.0 / Y 424 425define float @div_factor(float %x, float %y) { 426; CHECK-LABEL: @div_factor( 427; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan float 1.000000e+00, [[Y:%.*]] 428; CHECK-NEXT: ret float [[D]] 429; 430 %m = fmul float %x, %y 431 %d = fdiv nnan reassoc float %x, %m 432 ret float %d; 433} 434 435; We can't do the transform without 'nnan' because if x is NAN and y is a number, this should return NAN. 436 437define float @div_factor_too_strict(float %x, float %y) { 438; CHECK-LABEL: @div_factor_too_strict( 439; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 440; CHECK-NEXT: [[D:%.*]] = fdiv reassoc float [[X]], [[M]] 441; CHECK-NEXT: ret float [[D]] 442; 443 %m = fmul float %x, %y 444 %d = fdiv reassoc float %x, %m 445 ret float %d 446} 447 448; Commute, verify vector types, and show that we are not dropping extra FMF. 449; X / (Y * X) --> 1.0 / Y 450 451define <2 x float> @div_factor_commute(<2 x float> %x, <2 x float> %y) { 452; CHECK-LABEL: @div_factor_commute( 453; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan ninf nsz <2 x float> <float 1.000000e+00, float 1.000000e+00>, [[Y:%.*]] 454; CHECK-NEXT: ret <2 x float> [[D]] 455; 456 %m = fmul <2 x float> %y, %x 457 %d = fdiv nnan ninf nsz reassoc <2 x float> %x, %m 458 ret <2 x float> %d 459} 460 461; C1/(X*C2) => (C1/C2) / X 462 463define <2 x float> @div_constant_dividend1(<2 x float> %x) { 464; CHECK-LABEL: @div_constant_dividend1( 465; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 5.000000e+00, float 1.000000e+00>, [[X:%.*]] 466; CHECK-NEXT: ret <2 x float> [[T2]] 467; 468 %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0> 469 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float 7.0e0>, %t1 470 ret <2 x float> %t2 471} 472 473define <2 x float> @div_constant_dividend1_arcp_only(<2 x float> %x) { 474; CHECK-LABEL: @div_constant_dividend1_arcp_only( 475; CHECK-NEXT: [[T1:%.*]] = fmul <2 x float> [[X:%.*]], <float 3.000000e+00, float 7.000000e+00> 476; CHECK-NEXT: [[T2:%.*]] = fdiv arcp <2 x float> <float 1.500000e+01, float 7.000000e+00>, [[T1]] 477; CHECK-NEXT: ret <2 x float> [[T2]] 478; 479 %t1 = fmul <2 x float> %x, <float 3.0e0, float 7.0e0> 480 %t2 = fdiv arcp <2 x float> <float 15.0e0, float 7.0e0>, %t1 481 ret <2 x float> %t2 482} 483 484; C1/(X/C2) => (C1*C2) / X 485 486define <2 x float> @div_constant_dividend2(<2 x float> %x) { 487; CHECK-LABEL: @div_constant_dividend2( 488; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc arcp <2 x float> <float 4.500000e+01, float 4.900000e+01>, [[X:%.*]] 489; CHECK-NEXT: ret <2 x float> [[T2]] 490; 491 %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0> 492 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 493 ret <2 x float> %t2 494} 495 496define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) { 497; CHECK-LABEL: @div_constant_dividend2_reassoc_only( 498; CHECK-NEXT: [[T1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 3.000000e+00, float -7.000000e+00> 499; CHECK-NEXT: [[T2:%.*]] = fdiv reassoc <2 x float> <float 1.500000e+01, float -7.000000e+00>, [[T1]] 500; CHECK-NEXT: ret <2 x float> [[T2]] 501; 502 %t1 = fdiv <2 x float> %x, <float 3.0e0, float -7.0e0> 503 %t2 = fdiv reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 504 ret <2 x float> %t2 505} 506 507; C1/(C2/X) => (C1/C2) * X 508; This tests the combination of 2 folds: (C1 * X) / C2 --> (C1 / C2) * X 509 510define <2 x float> @div_constant_dividend3(<2 x float> %x) { 511; CHECK-LABEL: @div_constant_dividend3( 512; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 1.500000e+01, float -7.000000e+00> 513; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 0x3FD5555560000000, float 0x3FC24924A0000000> 514; CHECK-NEXT: ret <2 x float> [[T2]] 515; 516 %t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %x 517 %t2 = fdiv arcp reassoc <2 x float> <float 15.0e0, float -7.0e0>, %t1 518 ret <2 x float> %t2 519} 520 521define double @fdiv_fneg1(double %x, double %y) { 522; CHECK-LABEL: @fdiv_fneg1( 523; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 524; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]] 525; CHECK-NEXT: ret double [[DIV]] 526; 527 %neg = fsub double -0.0, %x 528 %div = fdiv double %neg, %y 529 ret double %div 530} 531 532define double @fdiv_unary_fneg1(double %x, double %y) { 533; CHECK-LABEL: @fdiv_unary_fneg1( 534; CHECK-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] 535; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[NEG]], [[Y:%.*]] 536; CHECK-NEXT: ret double [[DIV]] 537; 538 %neg = fneg double %x 539 %div = fdiv double %neg, %y 540 ret double %div 541} 542 543define <2 x float> @fdiv_fneg2(<2 x float> %x, <2 x float> %y) { 544; CHECK-LABEL: @fdiv_fneg2( 545; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 546; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]] 547; CHECK-NEXT: ret <2 x float> [[DIV]] 548; 549 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x 550 %div = fdiv <2 x float> %y, %neg 551 ret <2 x float> %div 552} 553 554define <2 x float> @fdiv_unary_fneg2(<2 x float> %x, <2 x float> %y) { 555; CHECK-LABEL: @fdiv_unary_fneg2( 556; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 557; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[Y:%.*]], [[NEG]] 558; CHECK-NEXT: ret <2 x float> [[DIV]] 559; 560 %neg = fneg <2 x float> %x 561 %div = fdiv <2 x float> %y, %neg 562 ret <2 x float> %div 563} 564 565define float @fdiv_fneg1_extra_use(float %x, float %y) { 566; CHECK-LABEL: @fdiv_fneg1_extra_use( 567; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]] 568; CHECK-NEXT: call void @use_f32(float [[NEG]]) 569; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]] 570; CHECK-NEXT: ret float [[DIV]] 571; 572 %neg = fsub float -0.0, %x 573 call void @use_f32(float %neg) 574 %div = fdiv float %neg, %y 575 ret float %div 576} 577 578define float @fabs_same_op(float %x) { 579; CHECK-LABEL: @fabs_same_op( 580; CHECK-NEXT: [[R:%.*]] = fdiv float [[X:%.*]], [[X]] 581; CHECK-NEXT: ret float [[R]] 582; 583 %a = call float @llvm.fabs.f32(float %x) 584 %r = fdiv float %a, %a 585 ret float %r 586} 587 588define float @fabs_same_op_extra_use(float %x) { 589; CHECK-LABEL: @fabs_same_op_extra_use( 590; CHECK-NEXT: [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 591; CHECK-NEXT: call void @use_f32(float [[A]]) 592; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]] 593; CHECK-NEXT: ret float [[R]] 594; 595 %a = call float @llvm.fabs.f32(float %x) 596 call void @use_f32(float %a) 597 %r = fdiv ninf reassoc float %a, %a 598 ret float %r 599} 600 601define float @fabs_fabs(float %x, float %y) { 602; CHECK-LABEL: @fabs_fabs( 603; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X:%.*]], [[Y:%.*]] 604; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) 605; CHECK-NEXT: ret float [[R]] 606; 607 %x.fabs = call float @llvm.fabs.f32(float %x) 608 %y.fabs = call float @llvm.fabs.f32(float %y) 609 %r = fdiv float %x.fabs, %y.fabs 610 ret float %r 611} 612 613define float @fabs_fabs_extra_use1(float %x, float %y) { 614; CHECK-LABEL: @fabs_fabs_extra_use1( 615; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 616; CHECK-NEXT: call void @use_f32(float [[X_FABS]]) 617; CHECK-NEXT: [[TMP1:%.*]] = fdiv ninf float [[X]], [[Y:%.*]] 618; CHECK-NEXT: [[R:%.*]] = call ninf float @llvm.fabs.f32(float [[TMP1]]) 619; CHECK-NEXT: ret float [[R]] 620; 621 %x.fabs = call float @llvm.fabs.f32(float %x) 622 call void @use_f32(float %x.fabs) 623 %y.fabs = call float @llvm.fabs.f32(float %y) 624 %r = fdiv ninf float %x.fabs, %y.fabs 625 ret float %r 626} 627 628define float @fabs_fabs_extra_use2(float %x, float %y) { 629; CHECK-LABEL: @fabs_fabs_extra_use2( 630; CHECK-NEXT: [[Y_FABS:%.*]] = call fast float @llvm.fabs.f32(float [[Y:%.*]]) 631; CHECK-NEXT: call void @use_f32(float [[Y_FABS]]) 632; CHECK-NEXT: [[TMP1:%.*]] = fdiv reassoc ninf float [[X:%.*]], [[Y]] 633; CHECK-NEXT: [[R:%.*]] = call reassoc ninf float @llvm.fabs.f32(float [[TMP1]]) 634; CHECK-NEXT: ret float [[R]] 635; 636 %x.fabs = call fast float @llvm.fabs.f32(float %x) 637 %y.fabs = call fast float @llvm.fabs.f32(float %y) 638 call void @use_f32(float %y.fabs) 639 %r = fdiv reassoc ninf float %x.fabs, %y.fabs 640 ret float %r 641} 642 643; negative test - don't create an extra instruction 644 645define float @fabs_fabs_extra_use3(float %x, float %y) { 646; CHECK-LABEL: @fabs_fabs_extra_use3( 647; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 648; CHECK-NEXT: call void @use_f32(float [[X_FABS]]) 649; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) 650; CHECK-NEXT: call void @use_f32(float [[Y_FABS]]) 651; CHECK-NEXT: [[R:%.*]] = fdiv float [[X_FABS]], [[Y_FABS]] 652; CHECK-NEXT: ret float [[R]] 653; 654 %x.fabs = call float @llvm.fabs.f32(float %x) 655 call void @use_f32(float %x.fabs) 656 %y.fabs = call float @llvm.fabs.f32(float %y) 657 call void @use_f32(float %y.fabs) 658 %r = fdiv float %x.fabs, %y.fabs 659 ret float %r 660} 661 662define float @pow_divisor(float %x, float %y, float %z) { 663; CHECK-LABEL: @pow_divisor( 664; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc arcp float [[Y:%.*]] 665; CHECK-NEXT: [[TMP2:%.*]] = call reassoc arcp float @llvm.pow.f32(float [[X:%.*]], float [[TMP1]]) 666; CHECK-NEXT: [[R:%.*]] = fmul reassoc arcp float [[TMP2]], [[Z:%.*]] 667; CHECK-NEXT: ret float [[R]] 668; 669 %p = call float @llvm.pow.f32(float %x, float %y) 670 %r = fdiv reassoc arcp float %z, %p 671 ret float %r 672} 673 674; Negative test - don't create an extra pow 675 676define float @pow_divisor_extra_use(float %x, float %y, float %z) { 677; CHECK-LABEL: @pow_divisor_extra_use( 678; CHECK-NEXT: [[P:%.*]] = call float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 679; CHECK-NEXT: call void @use_f32(float [[P]]) 680; CHECK-NEXT: [[R:%.*]] = fdiv reassoc arcp float [[Z:%.*]], [[P]] 681; CHECK-NEXT: ret float [[R]] 682; 683 %p = call float @llvm.pow.f32(float %x, float %y) 684 call void @use_f32(float %p) 685 %r = fdiv reassoc arcp float %z, %p 686 ret float %r 687} 688 689; Negative test - must have reassoc+arcp 690 691define float @pow_divisor_not_enough_fmf(float %x, float %y, float %z) { 692; CHECK-LABEL: @pow_divisor_not_enough_fmf( 693; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 694; CHECK-NEXT: [[R:%.*]] = fdiv reassoc float [[Z:%.*]], [[P]] 695; CHECK-NEXT: ret float [[R]] 696; 697 %p = call fast float @llvm.pow.f32(float %x, float %y) 698 %r = fdiv reassoc float %z, %p 699 ret float %r 700} 701 702; Negative test - must have reassoc+arcp 703 704define float @pow_divisor_not_enough_fmf2(float %x, float %y, float %z) { 705; CHECK-LABEL: @pow_divisor_not_enough_fmf2( 706; CHECK-NEXT: [[P:%.*]] = call fast float @llvm.pow.f32(float [[X:%.*]], float [[Y:%.*]]) 707; CHECK-NEXT: [[R:%.*]] = fdiv arcp float [[Z:%.*]], [[P]] 708; CHECK-NEXT: ret float [[R]] 709; 710 %p = call fast float @llvm.pow.f32(float %x, float %y) 711 %r = fdiv arcp float %z, %p 712 ret float %r 713} 714 715; Special-case - reciprocal does not require extra fmul 716 717define <2 x half> @pow_recip(<2 x half> %x, <2 x half> %y) { 718; CHECK-LABEL: @pow_recip( 719; CHECK-NEXT: [[TMP1:%.*]] = fneg reassoc ninf arcp <2 x half> [[Y:%.*]] 720; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp <2 x half> @llvm.pow.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]]) 721; CHECK-NEXT: ret <2 x half> [[TMP2]] 722; 723 %p = call <2 x half> @llvm.pow.v2f16(<2 x half> %x, <2 x half> %y) 724 %r = fdiv reassoc arcp ninf <2 x half> <half 1.0, half 1.0>, %p 725 ret <2 x half> %r 726} 727