1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; 3; Test numbering remains continuous across: 4; - InstCombine/fast-basictest.ll 5; - PhaseOrdering/fast-basictest.ll 6; - PhaseOrdering/fast-reassociate-gvn.ll 7; - Reassociate/fast-basictest.ll 8; 9; RUN: opt < %s -reassociate -S | FileCheck %s 10 11; ((a + (-3)) + b) + 3 -> a + b 12; That only works with both instcombine and reassociate passes enabled. 13; Check that reassociate is not enough. 14 15; TODO: check if we can eliminate zero add. 16define float @test2(float %reg109, float %reg1111) { 17; CHECK-LABEL: @test2( 18; CHECK-NEXT: [[REG116:%.*]] = fadd fast float [[REG109:%.*]], 0.000000e+00 19; CHECK-NEXT: [[REG117:%.*]] = fadd fast float [[REG116]], [[REG1111:%.*]] 20; CHECK-NEXT: ret float [[REG117]] 21; 22 %reg115 = fadd fast float %reg109, -3.000000e+01 23 %reg116 = fadd fast float %reg115, %reg1111 24 %reg117 = fadd fast float %reg116, 3.000000e+01 25 ret float %reg117 26} 27 28define float @test2_no_FMF(float %reg109, float %reg1111) { 29; CHECK-LABEL: @test2_no_FMF( 30; CHECK-NEXT: [[REG115:%.*]] = fadd float [[REG109:%.*]], -3.000000e+01 31; CHECK-NEXT: [[REG116:%.*]] = fadd float [[REG115]], [[REG1111:%.*]] 32; CHECK-NEXT: [[REG117:%.*]] = fadd float [[REG116]], 3.000000e+01 33; CHECK-NEXT: ret float [[REG117]] 34; 35 %reg115 = fadd float %reg109, -3.000000e+01 36 %reg116 = fadd float %reg115, %reg1111 37 %reg117 = fadd float %reg116, 3.000000e+01 38 ret float %reg117 39} 40 41define float @test2_reassoc(float %reg109, float %reg1111) { 42; CHECK-LABEL: @test2_reassoc( 43; CHECK-NEXT: [[REG115:%.*]] = fadd reassoc float [[REG109:%.*]], -3.000000e+01 44; CHECK-NEXT: [[REG116:%.*]] = fadd reassoc float [[REG115]], [[REG1111:%.*]] 45; CHECK-NEXT: [[REG117:%.*]] = fadd reassoc float [[REG116]], 3.000000e+01 46; CHECK-NEXT: ret float [[REG117]] 47; 48 %reg115 = fadd reassoc float %reg109, -3.000000e+01 49 %reg116 = fadd reassoc float %reg115, %reg1111 50 %reg117 = fadd reassoc float %reg116, 3.000000e+01 51 ret float %reg117 52} 53 54@fe = external global float 55@fa = external global float 56@fb = external global float 57@fc = external global float 58@ff = external global float 59 60; If two sums of the same operands in different order are counted with 'fast' 61; flag and then stored to global variables, we can reuse the same value twice. 62; Sums: 63; - test3: (a+b)+c and (a+c)+b 64; - test4: c+(a+b) and (c+a)+b 65; - test5: c+(b+a) and (c+a)+b 66; 67; That only works with both gvn and reassociate passes enabled. 68; Check that reassociate is not enough. 69 70define void @test3() { 71; CHECK-LABEL: @test3( 72; CHECK-NEXT: [[A:%.*]] = load float, float* @fa, align 4 73; CHECK-NEXT: [[B:%.*]] = load float, float* @fb, align 4 74; CHECK-NEXT: [[C:%.*]] = load float, float* @fc, align 4 75; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]] 76; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]] 77; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]] 78; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]] 79; CHECK-NEXT: store float [[T2]], float* @fe, align 4 80; CHECK-NEXT: store float [[T4]], float* @ff, align 4 81; CHECK-NEXT: ret void 82; 83 %A = load float, float* @fa 84 %B = load float, float* @fb 85 %C = load float, float* @fc 86 %t1 = fadd fast float %A, %B 87 %t2 = fadd fast float %t1, %C 88 %t3 = fadd fast float %A, %C 89 %t4 = fadd fast float %t3, %B 90 ; e = (a+b)+c; 91 store float %t2, float* @fe 92 ; f = (a+c)+b 93 store float %t4, float* @ff 94 ret void 95} 96 97define void @test4() { 98; CHECK-LABEL: @test4( 99; CHECK-NEXT: [[A:%.*]] = load float, float* @fa, align 4 100; CHECK-NEXT: [[B:%.*]] = load float, float* @fb, align 4 101; CHECK-NEXT: [[C:%.*]] = load float, float* @fc, align 4 102; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]] 103; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]] 104; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]] 105; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]] 106; CHECK-NEXT: store float [[T2]], float* @fe, align 4 107; CHECK-NEXT: store float [[T4]], float* @ff, align 4 108; CHECK-NEXT: ret void 109; 110 %A = load float, float* @fa 111 %B = load float, float* @fb 112 %C = load float, float* @fc 113 %t1 = fadd fast float %A, %B 114 %t2 = fadd fast float %C, %t1 115 %t3 = fadd fast float %C, %A 116 %t4 = fadd fast float %t3, %B 117 ; e = c+(a+b) 118 store float %t2, float* @fe 119 ; f = (c+a)+b 120 store float %t4, float* @ff 121 ret void 122} 123 124define void @test5() { 125; CHECK-LABEL: @test5( 126; CHECK-NEXT: [[A:%.*]] = load float, float* @fa, align 4 127; CHECK-NEXT: [[B:%.*]] = load float, float* @fb, align 4 128; CHECK-NEXT: [[C:%.*]] = load float, float* @fc, align 4 129; CHECK-NEXT: [[T1:%.*]] = fadd fast float [[B]], [[A]] 130; CHECK-NEXT: [[T2:%.*]] = fadd fast float [[T1]], [[C]] 131; CHECK-NEXT: [[T3:%.*]] = fadd fast float [[B]], [[A]] 132; CHECK-NEXT: [[T4:%.*]] = fadd fast float [[T3]], [[C]] 133; CHECK-NEXT: store float [[T2]], float* @fe, align 4 134; CHECK-NEXT: store float [[T4]], float* @ff, align 4 135; CHECK-NEXT: ret void 136; 137 %A = load float, float* @fa 138 %B = load float, float* @fb 139 %C = load float, float* @fc 140 %t1 = fadd fast float %B, %A 141 %t2 = fadd fast float %C, %t1 142 %t3 = fadd fast float %C, %A 143 %t4 = fadd fast float %t3, %B 144 ; e = c+(b+a) 145 store float %t2, float* @fe 146 ; f = (c+a)+b 147 store float %t4, float* @ff 148 ret void 149} 150 151define float @test6(float %A, float %B, float %C) { 152; CHECK-LABEL: @test6( 153; CHECK-NEXT: [[REASS_ADD1:%.*]] = fadd fast float [[C:%.*]], [[B:%.*]] 154; CHECK-NEXT: [[REASS_MUL2:%.*]] = fmul fast float [[A:%.*]], [[A]] 155; CHECK-NEXT: [[REASS_MUL:%.*]] = fmul fast float [[REASS_MUL2]], [[REASS_ADD1]] 156; CHECK-NEXT: ret float [[REASS_MUL]] 157; 158 %aa = fmul fast float %A, %A 159 %aab = fmul fast float %aa, %B 160 %ac = fmul fast float %A, %C 161 %aac = fmul fast float %ac, %A 162 %r = fadd fast float %aab, %aac 163 ret float %r 164} 165 166define float @test6_reassoc(float %A, float %B, float %C) { 167; CHECK-LABEL: @test6_reassoc( 168; CHECK-NEXT: [[AA:%.*]] = fmul reassoc float [[A:%.*]], [[A]] 169; CHECK-NEXT: [[AAB:%.*]] = fmul reassoc float [[AA]], [[B:%.*]] 170; CHECK-NEXT: [[AC:%.*]] = fmul reassoc float [[A]], [[C:%.*]] 171; CHECK-NEXT: [[AAC:%.*]] = fmul reassoc float [[A]], [[AC]] 172; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[AAB]], [[AAC]] 173; CHECK-NEXT: ret float [[R]] 174; 175 %aa = fmul reassoc float %A, %A 176 %aab = fmul reassoc float %aa, %B 177 %ac = fmul reassoc float %A, %C 178 %aac = fmul reassoc float %ac, %A 179 %r = fadd reassoc float %aab, %aac 180 ret float %r 181} 182 183; (-X)*Y + Z -> Z-X*Y 184 185define float @test7(float %X, float %Y, float %Z) { 186; CHECK-LABEL: @test7( 187; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]] 188; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]] 189; CHECK-NEXT: ret float [[TMP1]] 190; 191 %A = fsub fast float 0.0, %X 192 %B = fmul fast float %A, %Y 193 %C = fadd fast float %B, %Z 194 ret float %C 195} 196 197define float @test7_unary_fneg(float %X, float %Y, float %Z) { 198; CHECK-LABEL: @test7_unary_fneg( 199; CHECK-NEXT: [[B:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]] 200; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[Z:%.*]], [[B]] 201; CHECK-NEXT: ret float [[TMP1]] 202; 203 %A = fneg fast float %X 204 %B = fmul fast float %A, %Y 205 %C = fadd fast float %B, %Z 206 ret float %C 207} 208 209define float @test7_reassoc_nsz(float %X, float %Y, float %Z) { 210; CHECK-LABEL: @test7_reassoc_nsz( 211; CHECK-NEXT: [[A:%.*]] = fsub reassoc nsz float 0.000000e+00, [[X:%.*]] 212; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[A]], [[Y:%.*]] 213; CHECK-NEXT: [[C:%.*]] = fadd reassoc nsz float [[B]], [[Z:%.*]] 214; CHECK-NEXT: ret float [[C]] 215; 216 %A = fsub reassoc nsz float 0.0, %X 217 %B = fmul reassoc nsz float %A, %Y 218 %C = fadd reassoc nsz float %B, %Z 219 ret float %C 220} 221 222; Verify that fold is not done only with 'reassoc' ('nsz' is required) 223define float @test7_reassoc(float %X, float %Y, float %Z) { 224; CHECK-LABEL: @test7_reassoc( 225; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X:%.*]] 226; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[Y:%.*]] 227; CHECK-NEXT: [[C:%.*]] = fadd reassoc float [[B]], [[Z:%.*]] 228; CHECK-NEXT: ret float [[C]] 229; 230 %A = fsub reassoc float 0.0, %X 231 %B = fmul reassoc float %A, %Y 232 %C = fadd reassoc float %B, %Z 233 ret float %C 234} 235 236; Integer version of: 237; (-X)*Y + Z -> Z-X*Y 238; TODO: check if we can change the mul of -1 and the add to a sub. 239define i32 @test7_int(i32 %X, i32 %Y, i32 %Z) { 240; CHECK-LABEL: @test7_int( 241; CHECK-NEXT: [[A:%.*]] = mul i32 [[Y:%.*]], [[X:%.*]] 242; CHECK-NEXT: [[B:%.*]] = mul i32 [[A]], -1 243; CHECK-NEXT: [[C:%.*]] = add i32 [[B]], [[Z:%.*]] 244; CHECK-NEXT: ret i32 [[C]] 245; 246 %A = sub i32 0, %X 247 %B = mul i32 %A, %Y 248 %C = add i32 %B, %Z 249 ret i32 %C 250} 251 252define float @test8(float %X) { 253; CHECK-LABEL: @test8( 254; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 9.400000e+01 255; CHECK-NEXT: ret float [[FACTOR]] 256; 257 %Y = fmul fast float %X, 4.700000e+01 258 %Z = fadd fast float %Y, %Y 259 ret float %Z 260} 261 262; Side note: (x + x + x) and (3*x) each have only a single rounding. So 263; transforming x+x+x to 3*x is always safe, even without any FMF. 264; To avoid that special-case, we have the addition of 'x' four times, here. 265define float @test9(float %X) { 266; CHECK-LABEL: @test9( 267; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], 4.000000e+00 268; CHECK-NEXT: ret float [[FACTOR]] 269; 270 %Y = fadd fast float %X ,%X 271 %Z = fadd fast float %Y, %X 272 %W = fadd fast float %Z, %X 273 ret float %W 274} 275 276define float @test10(float %W) { 277; CHECK-LABEL: @test10( 278; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[W:%.*]], 3.810000e+02 279; CHECK-NEXT: ret float [[FACTOR]] 280; 281 %X = fmul fast float %W, 127.0 282 %Y = fadd fast float %X ,%X 283 %Z = fadd fast float %Y, %X 284 ret float %Z 285} 286 287define float @test11(float %X) { 288; CHECK-LABEL: @test11( 289; CHECK-NEXT: [[FACTOR:%.*]] = fmul fast float [[X:%.*]], -3.000000e+00 290; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[FACTOR]], 6.000000e+00 291; CHECK-NEXT: ret float [[Z]] 292; 293 %A = fsub fast float 1.000000e+00, %X 294 %B = fsub fast float 2.000000e+00, %X 295 %C = fsub fast float 3.000000e+00, %X 296 %Y = fadd fast float %A ,%B 297 %Z = fadd fast float %Y, %C 298 ret float %Z 299} 300 301define float @test12(float %X1, float %X2, float %X3) { 302; CHECK-LABEL: @test12( 303; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]] 304; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]] 305; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]] 306; CHECK-NEXT: ret float [[TMP1]] 307; 308 %A = fsub fast float 0.000000e+00, %X1 309 %B = fmul fast float %A, %X2 ; -X1*X2 310 %C = fmul fast float %X1, %X3 ; X1*X3 311 %D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2) 312 ret float %D 313} 314 315define float @test12_unary_fneg(float %X1, float %X2, float %X3) { 316; CHECK-LABEL: @test12_unary_fneg( 317; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X2:%.*]], [[X1:%.*]] 318; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X3:%.*]], [[X1]] 319; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[C]], [[B]] 320; CHECK-NEXT: ret float [[TMP1]] 321; 322 %A = fneg fast float %X1 323 %B = fmul fast float %A, %X2 ; -X1*X2 324 %C = fmul fast float %X1, %X3 ; X1*X3 325 %D = fadd fast float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2) 326 ret float %D 327} 328 329define float @test12_reassoc_nsz(float %X1, float %X2, float %X3) { 330; CHECK-LABEL: @test12_reassoc_nsz( 331; CHECK-NEXT: [[A:%.*]] = fsub reassoc nsz float 0.000000e+00, [[X1:%.*]] 332; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[A]], [[X2:%.*]] 333; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X1]], [[X3:%.*]] 334; CHECK-NEXT: [[D:%.*]] = fadd reassoc nsz float [[B]], [[C]] 335; CHECK-NEXT: ret float [[D]] 336; 337 %A = fsub reassoc nsz float 0.000000e+00, %X1 338 %B = fmul reassoc nsz float %A, %X2 ; -X1*X2 339 %C = fmul reassoc nsz float %X1, %X3 ; X1*X3 340 %D = fadd reassoc nsz float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2) 341 ret float %D 342} 343 344; TODO: check if 'nsz' is technically required. Currently the optimization 345; is not done with only 'reassoc' without 'nsz'. 346define float @test12_reassoc(float %X1, float %X2, float %X3) { 347; CHECK-LABEL: @test12_reassoc( 348; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 0.000000e+00, [[X1:%.*]] 349; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[A]], [[X2:%.*]] 350; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X1]], [[X3:%.*]] 351; CHECK-NEXT: [[D:%.*]] = fadd reassoc float [[B]], [[C]] 352; CHECK-NEXT: ret float [[D]] 353; 354 %A = fsub reassoc float 0.000000e+00, %X1 355 %B = fmul reassoc float %A, %X2 ; -X1*X2 356 %C = fmul reassoc float %X1, %X3 ; X1*X3 357 %D = fadd reassoc float %B, %C ; -X1*X2 + X1*X3 -> X1*(X3-X2) 358 ret float %D 359} 360 361; (x1 * 47) + (x2 * -47) => (x1 - x2) * 47 362; That only works with both instcombine and reassociate passes enabled. 363; Check that reassociate is not enough. 364 365define float @test13(float %X1, float %X2) { 366; CHECK-LABEL: @test13( 367; CHECK-NEXT: [[B:%.*]] = fmul fast float [[X1:%.*]], 4.700000e+01 368; CHECK-NEXT: [[C:%.*]] = fmul fast float [[X2:%.*]], 4.700000e+01 369; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float [[B]], [[C]] 370; CHECK-NEXT: ret float [[TMP1]] 371; 372 %B = fmul fast float %X1, 47. ; X1*47 373 %C = fmul fast float %X2, -47. ; X2*-47 374 %D = fadd fast float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) 375 ret float %D 376} 377 378define float @test13_reassoc_nsz(float %X1, float %X2) { 379; CHECK-LABEL: @test13_reassoc_nsz( 380; CHECK-NEXT: [[B:%.*]] = fmul reassoc nsz float [[X1:%.*]], 4.700000e+01 381; CHECK-NEXT: [[C:%.*]] = fmul reassoc nsz float [[X2:%.*]], 4.700000e+01 382; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[B]], [[C]] 383; CHECK-NEXT: ret float [[TMP1]] 384; 385 %B = fmul reassoc nsz float %X1, 47. ; X1*47 386 %C = fmul reassoc nsz float %X2, -47. ; X2*-47 387 %D = fadd reassoc nsz float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) 388 ret float %D 389} 390 391define float @test13_reassoc(float %X1, float %X2) { 392; CHECK-LABEL: @test13_reassoc( 393; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[X1:%.*]], 4.700000e+01 394; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X2:%.*]], 4.700000e+01 395; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc float [[B]], [[C]] 396; CHECK-NEXT: ret float [[TMP1]] 397; 398 %B = fmul reassoc float %X1, 47. ; X1*47 399 %C = fmul reassoc float %X2, -47. ; X2*-47 400 %D = fadd reassoc float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) 401 ret float %D 402} 403 404define float @test14(float %arg) { 405; CHECK-LABEL: @test14( 406; CHECK-NEXT: [[T2:%.*]] = fmul fast float [[ARG:%.*]], 1.440000e+02 407; CHECK-NEXT: ret float [[T2]] 408; 409 %t1 = fmul fast float 1.200000e+01, %arg 410 %t2 = fmul fast float %t1, 1.200000e+01 411 ret float %t2 412} 413 414; TODO: check if we can transform the code with 'reassoc' only. 415; The same IR is transformed to one fmul in instcombine pass. 416define float @test14_reassoc(float %arg) { 417; CHECK-LABEL: @test14_reassoc( 418; CHECK-NEXT: [[T1:%.*]] = fmul reassoc float [[ARG:%.*]], 1.200000e+01 419; CHECK-NEXT: [[T2:%.*]] = fmul reassoc float [[T1]], 1.200000e+01 420; CHECK-NEXT: ret float [[T2]] 421; 422 %t1 = fmul reassoc float 1.200000e+01, %arg 423 %t2 = fmul reassoc float %t1, 1.200000e+01 424 ret float %t2 425} 426 427; (b+(a+1234))+-a -> b+1234 428; That only works with both instcombine and reassociate passes enabled. 429; Check that reassociate is not enough. 430 431; TODO: check if we can remove dead fsub. 432define float @test15(float %b, float %a) { 433; CHECK-LABEL: @test15( 434; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float 0.000000e+00, [[A:%.*]] 435; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03 436; CHECK-NEXT: ret float [[TMP2]] 437; 438 %1 = fadd fast float %a, 1234.0 439 %2 = fadd fast float %b, %1 440 %3 = fsub fast float 0.0, %a 441 %4 = fadd fast float %2, %3 442 ret float %4 443} 444 445; TODO: check if we can remove dead fneg. 446define float @test15_unary_fneg(float %b, float %a) { 447; CHECK-LABEL: @test15_unary_fneg( 448; CHECK-NEXT: [[TMP1:%.*]] = fneg fast float [[A:%.*]] 449; CHECK-NEXT: [[TMP2:%.*]] = fadd fast float [[B:%.*]], 1.234000e+03 450; CHECK-NEXT: ret float [[TMP2]] 451; 452 %1 = fadd fast float %a, 1234.0 453 %2 = fadd fast float %b, %1 454 %3 = fneg fast float %a 455 %4 = fadd fast float %2, %3 456 ret float %4 457} 458 459define float @test15_reassoc_nsz(float %b, float %a) { 460; CHECK-LABEL: @test15_reassoc_nsz( 461; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[A:%.*]], 1.234000e+03 462; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc nsz float [[B:%.*]], [[TMP1]] 463; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc nsz float 0.000000e+00, [[A]] 464; CHECK-NEXT: [[TMP4:%.*]] = fadd reassoc nsz float [[TMP3]], [[TMP2]] 465; CHECK-NEXT: ret float [[TMP4]] 466; 467 %1 = fadd reassoc nsz float %a, 1234.0 468 %2 = fadd reassoc nsz float %b, %1 469 %3 = fsub reassoc nsz float 0.0, %a 470 %4 = fadd reassoc nsz float %2, %3 471 ret float %4 472} 473 474define float @test15_reassoc(float %b, float %a) { 475; CHECK-LABEL: @test15_reassoc( 476; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[A:%.*]], 1.234000e+03 477; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[B:%.*]], [[TMP1]] 478; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float 0.000000e+00, [[A]] 479; CHECK-NEXT: [[TMP4:%.*]] = fadd reassoc float [[TMP3]], [[TMP2]] 480; CHECK-NEXT: ret float [[TMP4]] 481; 482 %1 = fadd reassoc float %a, 1234.0 483 %2 = fadd reassoc float %b, %1 484 %3 = fsub reassoc float 0.0, %a 485 %4 = fadd reassoc float %2, %3 486 ret float %4 487} 488 489; Test that we can turn things like X*-(Y*Z) -> X*-1*Y*Z. 490; That only works with both instcombine and reassociate passes enabled. 491; Check that reassociate is not enough. 492 493define float @test16(float %a, float %b, float %z) { 494; CHECK-LABEL: @test16( 495; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04 496; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[B:%.*]] 497; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]] 498; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[F]], 0.000000e+00 499; CHECK-NEXT: ret float [[TMP1]] 500; 501 %c = fsub fast float 0.000000e+00, %z 502 %d = fmul fast float %a, %b 503 %e = fmul fast float %c, %d 504 %f = fmul fast float %e, 1.234500e+04 505 %g = fsub fast float 0.000000e+00, %f 506 ret float %g 507} 508 509define float @test16_unary_fneg(float %a, float %b, float %z) { 510; CHECK-LABEL: @test16_unary_fneg( 511; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 1.234500e+04 512; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[B:%.*]] 513; CHECK-NEXT: [[G:%.*]] = fmul fast float [[F]], [[Z:%.*]] 514; CHECK-NEXT: ret float [[G]] 515; 516 %c = fneg fast float %z 517 %d = fmul fast float %a, %b 518 %e = fmul fast float %c, %d 519 %f = fmul fast float %e, 1.234500e+04 520 %g = fneg fast float %f 521 ret float %g 522} 523 524define float @test16_reassoc(float %a, float %b, float %z) { 525; CHECK-LABEL: @test16_reassoc( 526; CHECK-NEXT: [[C:%.*]] = fsub reassoc float 0.000000e+00, [[Z:%.*]] 527; CHECK-NEXT: [[D:%.*]] = fmul reassoc float [[A:%.*]], [[B:%.*]] 528; CHECK-NEXT: [[E:%.*]] = fmul reassoc float [[D]], [[C]] 529; CHECK-NEXT: [[F:%.*]] = fmul reassoc float [[E]], 1.234500e+04 530; CHECK-NEXT: [[G:%.*]] = fsub reassoc float 0.000000e+00, [[F]] 531; CHECK-NEXT: ret float [[G]] 532; 533 %c = fsub reassoc float 0.000000e+00, %z 534 %d = fmul reassoc float %a, %b 535 %e = fmul reassoc float %c, %d 536 %f = fmul reassoc float %e, 1.234500e+04 537 %g = fsub reassoc float 0.000000e+00, %f 538 ret float %g 539} 540 541; TODO: check if we can remove: 542; - fadd fast x, 0 543; ... as 'fast' implies 'nsz' 544define float @test17(float %a, float %b, float %z) { 545; CHECK-LABEL: @test17( 546; CHECK-NEXT: [[C:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01 547; CHECK-NEXT: [[E:%.*]] = fmul fast float [[C]], [[Z:%.*]] 548; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[E]], 0.000000e+00 549; CHECK-NEXT: ret float [[TMP1]] 550; 551 %d = fmul fast float %z, 4.000000e+01 552 %c = fsub fast float 0.000000e+00, %d 553 %e = fmul fast float %a, %c 554 %f = fsub fast float 0.000000e+00, %e 555 ret float %f 556} 557 558define float @test17_unary_fneg(float %a, float %b, float %z) { 559; CHECK-LABEL: @test17_unary_fneg( 560; CHECK-NEXT: [[E:%.*]] = fmul fast float [[A:%.*]], 4.000000e+01 561; CHECK-NEXT: [[F:%.*]] = fmul fast float [[E]], [[Z:%.*]] 562; CHECK-NEXT: ret float [[F]] 563; 564 %d = fmul fast float %z, 4.000000e+01 565 %c = fneg fast float %d 566 %e = fmul fast float %a, %c 567 %f = fneg fast float %e 568 ret float %f 569} 570 571; With sub reassociation, constant folding can eliminate the 12 and -12 constants. 572; TODO: check if we can remove fadd fast x, 0 as 'fast' implies 'nsz' 573define float @test18(float %A, float %B) { 574; CHECK-LABEL: @test18( 575; CHECK-NEXT: [[B_NEG:%.*]] = fneg fast float [[B:%.*]] 576; CHECK-NEXT: [[Y:%.*]] = fadd fast float [[A:%.*]], 0.000000e+00 577; CHECK-NEXT: [[Z:%.*]] = fadd fast float [[Y]], [[B_NEG]] 578; CHECK-NEXT: ret float [[Z]] 579; 580 %X = fadd fast float -1.200000e+01, %A 581 %Y = fsub fast float %X, %B 582 %Z = fadd fast float %Y, 1.200000e+01 583 ret float %Z 584} 585