1; RUN: opt < %s -instcombine -S | FileCheck %s 2 3; testing-case "float fold(float a) { return 1.2f * a * 2.3f; }" 4; 1.2f and 2.3f is supposed to be fold. 5define float @fold(float %a) { 6 %mul = fmul fast float %a, 0x3FF3333340000000 7 %mul1 = fmul fast float %mul, 0x4002666660000000 8 ret float %mul1 9; CHECK: @fold 10; CHECK: fmul fast float %a, 0x4006147AE0000000 11} 12 13; Same testing-case as the one used in fold() except that the operators have 14; fixed FP mode. 15define float @notfold(float %a) { 16; CHECK: @notfold 17; CHECK: %mul = fmul fast float %a, 0x3FF3333340000000 18 %mul = fmul fast float %a, 0x3FF3333340000000 19 %mul1 = fmul float %mul, 0x4002666660000000 20 ret float %mul1 21} 22 23define float @fold2(float %a) { 24; CHECK: @fold2 25; CHECK: fmul fast float %a, 0x4006147AE0000000 26 %mul = fmul float %a, 0x3FF3333340000000 27 %mul1 = fmul fast float %mul, 0x4002666660000000 28 ret float %mul1 29} 30 31; C * f1 + f1 = (C+1) * f1 32define double @fold3(double %f1) { 33 %t1 = fmul fast double 2.000000e+00, %f1 34 %t2 = fadd fast double %f1, %t1 35 ret double %t2 36; CHECK: @fold3 37; CHECK: fmul fast double %f1, 3.000000e+00 38} 39 40; (C1 - X) + (C2 - Y) => (C1+C2) - (X + Y) 41define float @fold4(float %f1, float %f2) { 42 %sub = fsub float 4.000000e+00, %f1 43 %sub1 = fsub float 5.000000e+00, %f2 44 %add = fadd fast float %sub, %sub1 45 ret float %add 46; CHECK: @fold4 47; CHECK: %1 = fadd fast float %f1, %f2 48; CHECK: fsub fast float 9.000000e+00, %1 49} 50 51; (X + C1) + C2 => X + (C1 + C2) 52define float @fold5(float %f1, float %f2) { 53 %add = fadd float %f1, 4.000000e+00 54 %add1 = fadd fast float %add, 5.000000e+00 55 ret float %add1 56; CHECK: @fold5 57; CHECK: fadd fast float %f1, 9.000000e+00 58} 59 60; (X + X) + X => 3.0 * X 61define float @fold6(float %f1) { 62 %t1 = fadd fast float %f1, %f1 63 %t2 = fadd fast float %f1, %t1 64 ret float %t2 65; CHECK: @fold6 66; CHECK: fmul fast float %f1, 3.000000e+00 67} 68 69; C1 * X + (X + X) = (C1 + 2) * X 70define float @fold7(float %f1) { 71 %t1 = fmul fast float %f1, 5.000000e+00 72 %t2 = fadd fast float %f1, %f1 73 %t3 = fadd fast float %t1, %t2 74 ret float %t3 75; CHECK: @fold7 76; CHECK: fmul fast float %f1, 7.000000e+00 77} 78 79; (X + X) + (X + X) => 4.0 * X 80define float @fold8(float %f1) { 81 %t1 = fadd fast float %f1, %f1 82 %t2 = fadd fast float %f1, %f1 83 %t3 = fadd fast float %t1, %t2 84 ret float %t3 85; CHECK: fold8 86; CHECK: fmul fast float %f1, 4.000000e+00 87} 88 89; X - (X + Y) => 0 - Y 90define float @fold9(float %f1, float %f2) { 91 %t1 = fadd float %f1, %f2 92 %t3 = fsub fast float %f1, %t1 93 ret float %t3 94 95; CHECK: @fold9 96; CHECK: fsub fast float 0.000000e+00, %f2 97} 98 99; Let C3 = C1 + C2. (f1 + C1) + (f2 + C2) => (f1 + f2) + C3 instead of 100; "(f1 + C3) + f2" or "(f2 + C3) + f1". Placing constant-addend at the 101; top of resulting simplified expression tree may potentially reveal some 102; optimization opportunities in the super-expression trees. 103; 104define float @fold10(float %f1, float %f2) { 105 %t1 = fadd fast float 2.000000e+00, %f1 106 %t2 = fsub fast float %f2, 3.000000e+00 107 %t3 = fadd fast float %t1, %t2 108 ret float %t3 109; CHECK: @fold10 110; CHECK: %t3 = fadd fast float %t2, -1.000000e+00 111; CHECK: ret float %t3 112} 113 114; once cause Crash/miscompilation 115define float @fail1(float %f1, float %f2) { 116 %conv3 = fadd fast float %f1, -1.000000e+00 117 %add = fadd fast float %conv3, %conv3 118 %add2 = fadd fast float %add, %conv3 119 ret float %add2 120; CHECK: @fail1 121; CHECK: ret 122} 123 124define double @fail2(double %f1, double %f2) { 125 %t1 = fsub fast double %f1, %f2 126 %t2 = fadd fast double %f1, %f2 127 %t3 = fsub fast double %t1, %t2 128 ret double %t3 129; CHECK: @fail2 130; CHECK: ret 131} 132 133; ========================================================================= 134; 135; Testing-cases about fmul begin 136; 137; ========================================================================= 138 139; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3) (i.e. distribution) 140define float @fmul_distribute1(float %f1) { 141 %t1 = fmul float %f1, 6.0e+3 142 %t2 = fadd float %t1, 2.0e+3 143 %t3 = fmul fast float %t2, 5.0e+3 144 ret float %t3 145; CHECK: @fmul_distribute1 146; CHECK: %1 = fmul fast float %f1, 3.000000e+07 147; CHECK: %t3 = fadd fast float %1, 1.000000e+07 148} 149 150; (X/C1 + C2) * C3 => X/(C1/C3) + C2*C3 151define double @fmul_distribute2(double %f1, double %f2) { 152 %t1 = fdiv double %f1, 3.0e+0 153 %t2 = fadd double %t1, 5.0e+1 154 ; 0x10000000000000 = DBL_MIN 155 %t3 = fmul fast double %t2, 0x10000000000000 156 ret double %t3 157 158; CHECK: @fmul_distribute2 159; CHECK: %1 = fdiv fast double %f1, 0x7FE8000000000000 160; CHECK: fadd fast double %1, 0x69000000000000 161} 162 163; 5.0e-1 * DBL_MIN yields denormal, so "(f1*3.0 + 5.0e-1) * DBL_MIN" cannot 164; be simplified into f1 * (3.0*DBL_MIN) + (5.0e-1*DBL_MIN) 165define double @fmul_distribute3(double %f1) { 166 %t1 = fdiv double %f1, 3.0e+0 167 %t2 = fadd double %t1, 5.0e-1 168 %t3 = fmul fast double %t2, 0x10000000000000 169 ret double %t3 170 171; CHECK: @fmul_distribute3 172; CHECK: fmul fast double %t2, 0x10000000000000 173} 174 175; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3) (i.e. distribution) 176define float @fmul_distribute4(float %f1) { 177 %t1 = fmul float %f1, 6.0e+3 178 %t2 = fsub float 2.0e+3, %t1 179 %t3 = fmul fast float %t2, 5.0e+3 180 ret float %t3 181; CHECK: @fmul_distribute4 182; CHECK: %1 = fmul fast float %f1, 3.000000e+07 183; CHECK: %t3 = fsub fast float 1.000000e+07, %1 184} 185 186; C1/X * C2 => (C1*C2) / X 187define float @fmul2(float %f1) { 188 %t1 = fdiv float 2.0e+3, %f1 189 %t3 = fmul fast float %t1, 6.0e+3 190 ret float %t3 191; CHECK: @fmul2 192; CHECK: fdiv fast float 1.200000e+07, %f1 193} 194 195; X/C1 * C2 => X * (C2/C1) (if C2/C1 is normal Fp) 196define float @fmul3(float %f1, float %f2) { 197 %t1 = fdiv float %f1, 2.0e+3 198 %t3 = fmul fast float %t1, 6.0e+3 199 ret float %t3 200; CHECK: @fmul3 201; CHECK: fmul fast float %f1, 3.000000e+00 202} 203 204; Rule "X/C1 * C2 => X * (C2/C1) is not applicable if C2/C1 is either a special 205; value of a denormal. The 0x3810000000000000 here take value FLT_MIN 206; 207define float @fmul4(float %f1, float %f2) { 208 %t1 = fdiv float %f1, 2.0e+3 209 %t3 = fmul fast float %t1, 0x3810000000000000 210 ret float %t3 211; CHECK: @fmul4 212; CHECK: fmul fast float %t1, 0x3810000000000000 213} 214 215; X / C1 * C2 => X / (C2/C1) if C1/C2 is either a special value of a denormal, 216; and C2/C1 is a normal value. 217; 218define float @fmul5(float %f1, float %f2) { 219 %t1 = fdiv float %f1, 3.0e+0 220 %t3 = fmul fast float %t1, 0x3810000000000000 221 ret float %t3 222; CHECK: @fmul5 223; CHECK: fdiv fast float %f1, 0x47E8000000000000 224} 225 226; (X*Y) * X => (X*X) * Y 227define float @fmul6(float %f1, float %f2) { 228 %mul = fmul float %f1, %f2 229 %mul1 = fmul fast float %mul, %f1 230 ret float %mul1 231; CHECK: @fmul6 232; CHECK: fmul fast float %f1, %f1 233} 234 235; "(X*Y) * X => (X*X) * Y" is disabled if "X*Y" has multiple uses 236define float @fmul7(float %f1, float %f2) { 237 %mul = fmul float %f1, %f2 238 %mul1 = fmul fast float %mul, %f1 239 %add = fadd float %mul1, %mul 240 ret float %add 241; CHECK: @fmul7 242; CHECK: fmul fast float %mul, %f1 243} 244 245; ========================================================================= 246; 247; Testing-cases about negation 248; 249; ========================================================================= 250define float @fneg1(float %f1, float %f2) { 251 %sub = fsub float -0.000000e+00, %f1 252 %sub1 = fsub nsz float 0.000000e+00, %f2 253 %mul = fmul float %sub, %sub1 254 ret float %mul 255; CHECK: @fneg1 256; CHECK: fmul float %f1, %f2 257} 258 259; ========================================================================= 260; 261; Testing-cases about div 262; 263; ========================================================================= 264 265; X/C1 / C2 => X * (1/(C2*C1)) 266define float @fdiv1(float %x) { 267 %div = fdiv float %x, 0x3FF3333340000000 268 %div1 = fdiv fast float %div, 0x4002666660000000 269 ret float %div1 270; 0x3FF3333340000000 = 1.2f 271; 0x4002666660000000 = 2.3f 272; 0x3FD7303B60000000 = 0.36231884057971014492 273; CHECK: @fdiv1 274; CHECK: fmul fast float %x, 0x3FD7303B60000000 275} 276 277; X*C1 / C2 => X * (C1/C2) 278define float @fdiv2(float %x) { 279 %mul = fmul float %x, 0x3FF3333340000000 280 %div1 = fdiv fast float %mul, 0x4002666660000000 281 ret float %div1 282 283; 0x3FF3333340000000 = 1.2f 284; 0x4002666660000000 = 2.3f 285; 0x3FE0B21660000000 = 0.52173918485641479492 286; CHECK: @fdiv2 287; CHECK: fmul fast float %x, 0x3FE0B21660000000 288} 289 290; "X/C1 / C2 => X * (1/(C2*C1))" is disabled (for now) is C2/C1 is a denormal 291; 292define float @fdiv3(float %x) { 293 %div = fdiv float %x, 0x47EFFFFFE0000000 294 %div1 = fdiv fast float %div, 0x4002666660000000 295 ret float %div1 296; CHECK: @fdiv3 297; CHECK: fdiv float %x, 0x47EFFFFFE0000000 298} 299 300; "X*C1 / C2 => X * (C1/C2)" is disabled if C1/C2 is a denormal 301define float @fdiv4(float %x) { 302 %mul = fmul float %x, 0x47EFFFFFE0000000 303 %div = fdiv float %mul, 0x3FC99999A0000000 304 ret float %div 305; CHECK: @fdiv4 306; CHECK: fmul float %x, 0x47EFFFFFE0000000 307} 308 309; (X/Y)/Z = > X/(Y*Z) 310define float @fdiv5(float %f1, float %f2, float %f3) { 311 %t1 = fdiv float %f1, %f2 312 %t2 = fdiv fast float %t1, %f3 313 ret float %t2 314; CHECK: @fdiv5 315; CHECK: fmul float %f2, %f3 316} 317 318; Z/(X/Y) = > (Z*Y)/X 319define float @fdiv6(float %f1, float %f2, float %f3) { 320 %t1 = fdiv float %f1, %f2 321 %t2 = fdiv fast float %f3, %t1 322 ret float %t2 323; CHECK: @fdiv6 324; CHECK: fmul float %f3, %f2 325} 326 327; C1/(X*C2) => (C1/C2) / X 328define float @fdiv7(float %x) { 329 %t1 = fmul float %x, 3.0e0 330 %t2 = fdiv fast float 15.0e0, %t1 331 ret float %t2 332; CHECK: @fdiv7 333; CHECK: fdiv fast float 5.000000e+00, %x 334} 335 336; C1/(X/C2) => (C1*C2) / X 337define float @fdiv8(float %x) { 338 %t1 = fdiv float %x, 3.0e0 339 %t2 = fdiv fast float 15.0e0, %t1 340 ret float %t2 341; CHECK: @fdiv8 342; CHECK: fdiv fast float 4.500000e+01, %x 343} 344 345; C1/(C2/X) => (C1/C2) * X 346define float @fdiv9(float %x) { 347 %t1 = fdiv float 3.0e0, %x 348 %t2 = fdiv fast float 15.0e0, %t1 349 ret float %t2 350; CHECK: @fdiv9 351; CHECK: fmul fast float %x, 5.000000e+00 352} 353 354; ========================================================================= 355; 356; Testing-cases about factorization 357; 358; ========================================================================= 359; x*z + y*z => (x+y) * z 360define float @fact_mul1(float %x, float %y, float %z) { 361 %t1 = fmul fast float %x, %z 362 %t2 = fmul fast float %y, %z 363 %t3 = fadd fast float %t1, %t2 364 ret float %t3 365; CHECK: @fact_mul1 366; CHECK: fmul fast float %1, %z 367} 368 369; z*x + y*z => (x+y) * z 370define float @fact_mul2(float %x, float %y, float %z) { 371 %t1 = fmul fast float %z, %x 372 %t2 = fmul fast float %y, %z 373 %t3 = fsub fast float %t1, %t2 374 ret float %t3 375; CHECK: @fact_mul2 376; CHECK: fmul fast float %1, %z 377} 378 379; z*x - z*y => (x-y) * z 380define float @fact_mul3(float %x, float %y, float %z) { 381 %t2 = fmul fast float %z, %y 382 %t1 = fmul fast float %z, %x 383 %t3 = fsub fast float %t1, %t2 384 ret float %t3 385; CHECK: @fact_mul3 386; CHECK: fmul fast float %1, %z 387} 388 389; x*z - z*y => (x-y) * z 390define float @fact_mul4(float %x, float %y, float %z) { 391 %t1 = fmul fast float %x, %z 392 %t2 = fmul fast float %z, %y 393 %t3 = fsub fast float %t1, %t2 394 ret float %t3 395; CHECK: @fact_mul4 396; CHECK: fmul fast float %1, %z 397} 398 399; x/y + x/z, no xform 400define float @fact_div1(float %x, float %y, float %z) { 401 %t1 = fdiv fast float %x, %y 402 %t2 = fdiv fast float %x, %z 403 %t3 = fadd fast float %t1, %t2 404 ret float %t3 405; CHECK: fact_div1 406; CHECK: fadd fast float %t1, %t2 407} 408 409; x/y + z/x; no xform 410define float @fact_div2(float %x, float %y, float %z) { 411 %t1 = fdiv fast float %x, %y 412 %t2 = fdiv fast float %z, %x 413 %t3 = fadd fast float %t1, %t2 414 ret float %t3 415; CHECK: fact_div2 416; CHECK: fadd fast float %t1, %t2 417} 418 419; y/x + z/x => (y+z)/x 420define float @fact_div3(float %x, float %y, float %z) { 421 %t1 = fdiv fast float %y, %x 422 %t2 = fdiv fast float %z, %x 423 %t3 = fadd fast float %t1, %t2 424 ret float %t3 425; CHECK: fact_div3 426; CHECK: fdiv fast float %1, %x 427} 428 429; y/x - z/x => (y-z)/x 430define float @fact_div4(float %x, float %y, float %z) { 431 %t1 = fdiv fast float %y, %x 432 %t2 = fdiv fast float %z, %x 433 %t3 = fsub fast float %t1, %t2 434 ret float %t3 435; CHECK: fact_div4 436; CHECK: fdiv fast float %1, %x 437} 438 439; y/x - z/x => (y-z)/x is disabled if y-z is denormal. 440define float @fact_div5(float %x) { 441 %t1 = fdiv fast float 0x3810000000000000, %x 442 %t2 = fdiv fast float 0x3800000000000000, %x 443 %t3 = fadd fast float %t1, %t2 444 ret float %t3 445; CHECK: fact_div5 446; CHECK: fdiv fast float 0x3818000000000000, %x 447} 448 449; y/x - z/x => (y-z)/x is disabled if y-z is denormal. 450define float @fact_div6(float %x) { 451 %t1 = fdiv fast float 0x3810000000000000, %x 452 %t2 = fdiv fast float 0x3800000000000000, %x 453 %t3 = fsub fast float %t1, %t2 454 ret float %t3 455; CHECK: fact_div6 456; CHECK: %t3 = fsub fast float %t1, %t2 457} 458