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