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. 5 define float @fold(float %a) { 6 %mul = fmul fast float %a, 0x3FF3333340000000 7 %mul1 = fmul fast float %mul, 0x4002666660000000 8 ret float %mul1 9 ; CHECK-LABEL: @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. 15 define float @notfold(float %a) { 16 ; CHECK-LABEL: @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 23 define float @fold2(float %a) { 24 ; CHECK-LABEL: @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 32 define 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-LABEL: @fold3( 37 ; CHECK: fmul fast double %f1, 3.000000e+00 38 } 39 40 ; (C1 - X) + (C2 - Y) => (C1+C2) - (X + Y) 41 define 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-LABEL: @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) 52 define 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-LABEL: @fold5( 57 ; CHECK: fadd fast float %f1, 9.000000e+00 58 } 59 60 ; (X + X) + X => 3.0 * X 61 define float @fold6(float %f1) { 62 %t1 = fadd fast float %f1, %f1 63 %t2 = fadd fast float %f1, %t1 64 ret float %t2 65 ; CHECK-LABEL: @fold6( 66 ; CHECK: fmul fast float %f1, 3.000000e+00 67 } 68 69 ; C1 * X + (X + X) = (C1 + 2) * X 70 define 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-LABEL: @fold7( 76 ; CHECK: fmul fast float %f1, 7.000000e+00 77 } 78 79 ; (X + X) + (X + X) => 4.0 * X 80 define 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 90 define 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-LABEL: @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 ; 104 define 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-LABEL: @fold10( 110 ; CHECK: %t3 = fadd fast float %t2, -1.000000e+00 111 ; CHECK: ret float %t3 112 } 113 114 ; once cause Crash/miscompilation 115 define 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-LABEL: @fail1( 121 ; CHECK: ret 122 } 123 124 define 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-LABEL: @fail2( 130 ; CHECK: ret 131 } 132 133 ; c1 * x - x => (c1 - 1.0) * x 134 define float @fold13(float %x) { 135 %mul = fmul fast float %x, 7.000000e+00 136 %sub = fsub fast float %mul, %x 137 ret float %sub 138 ; CHECK: fold13 139 ; CHECK: fmul fast float %x, 6.000000e+00 140 ; CHECK: ret 141 } 142 143 ; ========================================================================= 144 ; 145 ; Testing-cases about fmul begin 146 ; 147 ; ========================================================================= 148 149 ; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3) (i.e. distribution) 150 define float @fmul_distribute1(float %f1) { 151 %t1 = fmul float %f1, 6.0e+3 152 %t2 = fadd float %t1, 2.0e+3 153 %t3 = fmul fast float %t2, 5.0e+3 154 ret float %t3 155 ; CHECK-LABEL: @fmul_distribute1( 156 ; CHECK: %1 = fmul fast float %f1, 3.000000e+07 157 ; CHECK: %t3 = fadd fast float %1, 1.000000e+07 158 } 159 160 ; (X/C1 + C2) * C3 => X/(C1/C3) + C2*C3 161 define double @fmul_distribute2(double %f1, double %f2) { 162 %t1 = fdiv double %f1, 3.0e+0 163 %t2 = fadd double %t1, 5.0e+1 164 ; 0x10000000000000 = DBL_MIN 165 %t3 = fmul fast double %t2, 0x10000000000000 166 ret double %t3 167 168 ; CHECK-LABEL: @fmul_distribute2( 169 ; CHECK: %1 = fdiv fast double %f1, 0x7FE8000000000000 170 ; CHECK: fadd fast double %1, 0x69000000000000 171 } 172 173 ; 5.0e-1 * DBL_MIN yields denormal, so "(f1*3.0 + 5.0e-1) * DBL_MIN" cannot 174 ; be simplified into f1 * (3.0*DBL_MIN) + (5.0e-1*DBL_MIN) 175 define double @fmul_distribute3(double %f1) { 176 %t1 = fdiv double %f1, 3.0e+0 177 %t2 = fadd double %t1, 5.0e-1 178 %t3 = fmul fast double %t2, 0x10000000000000 179 ret double %t3 180 181 ; CHECK-LABEL: @fmul_distribute3( 182 ; CHECK: fmul fast double %t2, 0x10000000000000 183 } 184 185 ; ((X*C1) + C2) * C3 => (X * (C1*C3)) + (C2*C3) (i.e. distribution) 186 define float @fmul_distribute4(float %f1) { 187 %t1 = fmul float %f1, 6.0e+3 188 %t2 = fsub float 2.0e+3, %t1 189 %t3 = fmul fast float %t2, 5.0e+3 190 ret float %t3 191 ; CHECK-LABEL: @fmul_distribute4( 192 ; CHECK: %1 = fmul fast float %f1, 3.000000e+07 193 ; CHECK: %t3 = fsub fast float 1.000000e+07, %1 194 } 195 196 ; C1/X * C2 => (C1*C2) / X 197 define float @fmul2(float %f1) { 198 %t1 = fdiv float 2.0e+3, %f1 199 %t3 = fmul fast float %t1, 6.0e+3 200 ret float %t3 201 ; CHECK-LABEL: @fmul2( 202 ; CHECK: fdiv fast float 1.200000e+07, %f1 203 } 204 205 ; X/C1 * C2 => X * (C2/C1) (if C2/C1 is normal Fp) 206 define float @fmul3(float %f1, float %f2) { 207 %t1 = fdiv float %f1, 2.0e+3 208 %t3 = fmul fast float %t1, 6.0e+3 209 ret float %t3 210 ; CHECK-LABEL: @fmul3( 211 ; CHECK: fmul fast float %f1, 3.000000e+00 212 } 213 214 ; Rule "X/C1 * C2 => X * (C2/C1) is not applicable if C2/C1 is either a special 215 ; value of a denormal. The 0x3810000000000000 here take value FLT_MIN 216 ; 217 define float @fmul4(float %f1, float %f2) { 218 %t1 = fdiv float %f1, 2.0e+3 219 %t3 = fmul fast float %t1, 0x3810000000000000 220 ret float %t3 221 ; CHECK-LABEL: @fmul4( 222 ; CHECK: fmul fast float %t1, 0x3810000000000000 223 } 224 225 ; X / C1 * C2 => X / (C2/C1) if C1/C2 is either a special value of a denormal, 226 ; and C2/C1 is a normal value. 227 ; 228 define float @fmul5(float %f1, float %f2) { 229 %t1 = fdiv float %f1, 3.0e+0 230 %t3 = fmul fast float %t1, 0x3810000000000000 231 ret float %t3 232 ; CHECK-LABEL: @fmul5( 233 ; CHECK: fdiv fast float %f1, 0x47E8000000000000 234 } 235 236 ; (X*Y) * X => (X*X) * Y 237 define float @fmul6(float %f1, float %f2) { 238 %mul = fmul float %f1, %f2 239 %mul1 = fmul fast float %mul, %f1 240 ret float %mul1 241 ; CHECK-LABEL: @fmul6( 242 ; CHECK: fmul fast float %f1, %f1 243 } 244 245 ; "(X*Y) * X => (X*X) * Y" is disabled if "X*Y" has multiple uses 246 define float @fmul7(float %f1, float %f2) { 247 %mul = fmul float %f1, %f2 248 %mul1 = fmul fast float %mul, %f1 249 %add = fadd float %mul1, %mul 250 ret float %add 251 ; CHECK-LABEL: @fmul7( 252 ; CHECK: fmul fast float %mul, %f1 253 } 254 255 ; ========================================================================= 256 ; 257 ; Testing-cases about negation 258 ; 259 ; ========================================================================= 260 define float @fneg1(float %f1, float %f2) { 261 %sub = fsub float -0.000000e+00, %f1 262 %sub1 = fsub nsz float 0.000000e+00, %f2 263 %mul = fmul float %sub, %sub1 264 ret float %mul 265 ; CHECK-LABEL: @fneg1( 266 ; CHECK: fmul float %f1, %f2 267 } 268 269 ; ========================================================================= 270 ; 271 ; Testing-cases about div 272 ; 273 ; ========================================================================= 274 275 ; X/C1 / C2 => X * (1/(C2*C1)) 276 define float @fdiv1(float %x) { 277 %div = fdiv float %x, 0x3FF3333340000000 278 %div1 = fdiv fast float %div, 0x4002666660000000 279 ret float %div1 280 ; 0x3FF3333340000000 = 1.2f 281 ; 0x4002666660000000 = 2.3f 282 ; 0x3FD7303B60000000 = 0.36231884057971014492 283 ; CHECK-LABEL: @fdiv1( 284 ; CHECK: fmul fast float %x, 0x3FD7303B60000000 285 } 286 287 ; X*C1 / C2 => X * (C1/C2) 288 define float @fdiv2(float %x) { 289 %mul = fmul float %x, 0x3FF3333340000000 290 %div1 = fdiv fast float %mul, 0x4002666660000000 291 ret float %div1 292 293 ; 0x3FF3333340000000 = 1.2f 294 ; 0x4002666660000000 = 2.3f 295 ; 0x3FE0B21660000000 = 0.52173918485641479492 296 ; CHECK-LABEL: @fdiv2( 297 ; CHECK: fmul fast float %x, 0x3FE0B21660000000 298 } 299 300 ; "X/C1 / C2 => X * (1/(C2*C1))" is disabled (for now) is C2/C1 is a denormal 301 ; 302 define float @fdiv3(float %x) { 303 %div = fdiv float %x, 0x47EFFFFFE0000000 304 %div1 = fdiv fast float %div, 0x4002666660000000 305 ret float %div1 306 ; CHECK-LABEL: @fdiv3( 307 ; CHECK: fdiv float %x, 0x47EFFFFFE0000000 308 } 309 310 ; "X*C1 / C2 => X * (C1/C2)" is disabled if C1/C2 is a denormal 311 define float @fdiv4(float %x) { 312 %mul = fmul float %x, 0x47EFFFFFE0000000 313 %div = fdiv float %mul, 0x3FC99999A0000000 314 ret float %div 315 ; CHECK-LABEL: @fdiv4( 316 ; CHECK: fmul float %x, 0x47EFFFFFE0000000 317 } 318 319 ; (X/Y)/Z = > X/(Y*Z) 320 define float @fdiv5(float %f1, float %f2, float %f3) { 321 %t1 = fdiv float %f1, %f2 322 %t2 = fdiv fast float %t1, %f3 323 ret float %t2 324 ; CHECK-LABEL: @fdiv5( 325 ; CHECK: fmul float %f2, %f3 326 } 327 328 ; Z/(X/Y) = > (Z*Y)/X 329 define float @fdiv6(float %f1, float %f2, float %f3) { 330 %t1 = fdiv float %f1, %f2 331 %t2 = fdiv fast float %f3, %t1 332 ret float %t2 333 ; CHECK-LABEL: @fdiv6( 334 ; CHECK: fmul float %f3, %f2 335 } 336 337 ; C1/(X*C2) => (C1/C2) / X 338 define float @fdiv7(float %x) { 339 %t1 = fmul float %x, 3.0e0 340 %t2 = fdiv fast float 15.0e0, %t1 341 ret float %t2 342 ; CHECK-LABEL: @fdiv7( 343 ; CHECK: fdiv fast float 5.000000e+00, %x 344 } 345 346 ; C1/(X/C2) => (C1*C2) / X 347 define float @fdiv8(float %x) { 348 %t1 = fdiv float %x, 3.0e0 349 %t2 = fdiv fast float 15.0e0, %t1 350 ret float %t2 351 ; CHECK-LABEL: @fdiv8( 352 ; CHECK: fdiv fast float 4.500000e+01, %x 353 } 354 355 ; C1/(C2/X) => (C1/C2) * X 356 define float @fdiv9(float %x) { 357 %t1 = fdiv float 3.0e0, %x 358 %t2 = fdiv fast float 15.0e0, %t1 359 ret float %t2 360 ; CHECK-LABEL: @fdiv9( 361 ; CHECK: fmul fast float %x, 5.000000e+00 362 } 363 364 ; ========================================================================= 365 ; 366 ; Testing-cases about factorization 367 ; 368 ; ========================================================================= 369 ; x*z + y*z => (x+y) * z 370 define float @fact_mul1(float %x, float %y, float %z) { 371 %t1 = fmul fast float %x, %z 372 %t2 = fmul fast float %y, %z 373 %t3 = fadd fast float %t1, %t2 374 ret float %t3 375 ; CHECK-LABEL: @fact_mul1( 376 ; CHECK: fmul fast float %1, %z 377 } 378 379 ; z*x + y*z => (x+y) * z 380 define float @fact_mul2(float %x, float %y, float %z) { 381 %t1 = fmul fast float %z, %x 382 %t2 = fmul fast float %y, %z 383 %t3 = fsub fast float %t1, %t2 384 ret float %t3 385 ; CHECK-LABEL: @fact_mul2( 386 ; CHECK: fmul fast float %1, %z 387 } 388 389 ; z*x - z*y => (x-y) * z 390 define float @fact_mul3(float %x, float %y, float %z) { 391 %t2 = fmul fast float %z, %y 392 %t1 = fmul fast float %z, %x 393 %t3 = fsub fast float %t1, %t2 394 ret float %t3 395 ; CHECK-LABEL: @fact_mul3( 396 ; CHECK: fmul fast float %1, %z 397 } 398 399 ; x*z - z*y => (x-y) * z 400 define float @fact_mul4(float %x, float %y, float %z) { 401 %t1 = fmul fast float %x, %z 402 %t2 = fmul fast float %z, %y 403 %t3 = fsub fast float %t1, %t2 404 ret float %t3 405 ; CHECK-LABEL: @fact_mul4( 406 ; CHECK: fmul fast float %1, %z 407 } 408 409 ; x/y + x/z, no xform 410 define float @fact_div1(float %x, float %y, float %z) { 411 %t1 = fdiv fast float %x, %y 412 %t2 = fdiv fast float %x, %z 413 %t3 = fadd fast float %t1, %t2 414 ret float %t3 415 ; CHECK: fact_div1 416 ; CHECK: fadd fast float %t1, %t2 417 } 418 419 ; x/y + z/x; no xform 420 define float @fact_div2(float %x, float %y, float %z) { 421 %t1 = fdiv fast float %x, %y 422 %t2 = fdiv fast float %z, %x 423 %t3 = fadd fast float %t1, %t2 424 ret float %t3 425 ; CHECK: fact_div2 426 ; CHECK: fadd fast float %t1, %t2 427 } 428 429 ; y/x + z/x => (y+z)/x 430 define float @fact_div3(float %x, float %y, float %z) { 431 %t1 = fdiv fast float %y, %x 432 %t2 = fdiv fast float %z, %x 433 %t3 = fadd fast float %t1, %t2 434 ret float %t3 435 ; CHECK: fact_div3 436 ; CHECK: fdiv fast float %1, %x 437 } 438 439 ; y/x - z/x => (y-z)/x 440 define float @fact_div4(float %x, float %y, float %z) { 441 %t1 = fdiv fast float %y, %x 442 %t2 = fdiv fast float %z, %x 443 %t3 = fsub fast float %t1, %t2 444 ret float %t3 445 ; CHECK: fact_div4 446 ; CHECK: fdiv fast float %1, %x 447 } 448 449 ; y/x - z/x => (y-z)/x is disabled if y-z is denormal. 450 define float @fact_div5(float %x) { 451 %t1 = fdiv fast float 0x3810000000000000, %x 452 %t2 = fdiv fast float 0x3800000000000000, %x 453 %t3 = fadd fast float %t1, %t2 454 ret float %t3 455 ; CHECK: fact_div5 456 ; CHECK: fdiv fast float 0x3818000000000000, %x 457 } 458 459 ; y/x - z/x => (y-z)/x is disabled if y-z is denormal. 460 define float @fact_div6(float %x) { 461 %t1 = fdiv fast float 0x3810000000000000, %x 462 %t2 = fdiv fast float 0x3800000000000000, %x 463 %t3 = fsub fast float %t1, %t2 464 ret float %t3 465 ; CHECK: fact_div6 466 ; CHECK: %t3 = fsub fast float %t1, %t2 467 } 468