Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -511,7 +511,8 @@ } Value *FAddCombine::simplify(Instruction *I) { - assert(I->isFast() && "Expected 'fast' instruction"); + assert(I->hasAllowReassoc() && I->hasNoSignedZeros() && + "Expected 'reassoc'+'nsz' instruction"); // Currently we are not able to handle vector type. if (I->getType()->isVectorTy()) @@ -1378,7 +1379,7 @@ if (Value *V = SimplifySelectsFeedingBinaryOp(I, LHS, RHS)) return replaceInstUsesWith(I, V); - if (I.isFast()) { + if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } @@ -1747,7 +1748,7 @@ if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) return replaceInstUsesWith(I, V); - if (I.isFast()) { + if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } Index: test/Transforms/InstCombine/fast-math.ll =================================================================== --- test/Transforms/InstCombine/fast-math.ll +++ test/Transforms/InstCombine/fast-math.ll @@ -47,6 +47,29 @@ ret double %t2 } +; Check again using the minimal subset of FMF. +define double @fold3_reassoc_nsz(double %f1) { +; CHECK-LABEL: @fold3_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz double [[F1:%.*]], 3.000000e+00 +; CHECK-NEXT: ret double [[TMP1]] +; + %t1 = fmul reassoc nsz double 2.000000e+00, %f1 + %t2 = fadd reassoc nsz double %f1, %t1 + ret double %t2 +} + +; Verify the fold is not done with only reassoc. +define double @fold3_reassoc(double %f1) { +; CHECK-LABEL: @fold3_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[F1:%.*]], 2.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc double [[TMP1]], [[F1]] +; CHECK-NEXT: ret double [[TMP2]] +; + %t1 = fmul reassoc double 2.000000e+00, %f1 + %t2 = fadd reassoc double %f1, %t1 + ret double %t2 +} + ; (C1 - X) + (C2 - Y) => (C1+C2) - (X + Y) define float @fold4(float %f1, float %f2) { ; CHECK-LABEL: @fold4( @@ -60,6 +83,33 @@ ret float %add } +; Check again using the minimal subset of FMF. +define float @fold4_reassoc_nsz(float %f1, float %f2) { +; CHECK-LABEL: @fold4_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[F1:%.*]], [[F2:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fsub reassoc nsz float 9.000000e+00, [[TMP1]] +; CHECK-NEXT: ret float [[TMP2]] +; + %sub = fsub float 4.000000e+00, %f1 + %sub1 = fsub float 5.000000e+00, %f2 + %add = fadd reassoc nsz float %sub, %sub1 + ret float %add +} + +; Verify the fold is not done with only reassoc. +define float @fold4_reassoc(float %f1, float %f2) { +; CHECK-LABEL: @fold4_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fsub float 4.000000e+00, [[F1:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fsub float 5.000000e+00, [[F2:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %sub = fsub float 4.000000e+00, %f1 + %sub1 = fsub float 5.000000e+00, %f2 + %add = fadd reassoc float %sub, %sub1 + ret float %add +} + ; (X + C1) + C2 => X + (C1 + C2) define float @fold5(float %f1, float %f2) { ; CHECK-LABEL: @fold5( @@ -71,6 +121,29 @@ ret float %add1 } +; Check again using the minimal subset of FMF. +define float @fold5_reassoc_nsz(float %f1, float %f2) { +; CHECK-LABEL: @fold5_reassoc_nsz( +; CHECK-NEXT: [[ADD1:%.*]] = fadd reassoc nsz float [[F1:%.*]], 9.000000e+00 +; CHECK-NEXT: ret float [[ADD1]] +; + %add = fadd float %f1, 4.000000e+00 + %add1 = fadd reassoc nsz float %add, 5.000000e+00 + ret float %add1 +} + +; Verify the fold is not done with only reassoc. +define float @fold5_reassoc(float %f1, float %f2) { +; CHECK-LABEL: @fold5_reassoc( +; CHECK-NEXT: [[ADD:%.*]] = fadd float [[F1:%.*]], 4.000000e+00 +; CHECK-NEXT: [[ADD1:%.*]] = fadd reassoc float [[ADD]], 5.000000e+00 +; CHECK-NEXT: ret float [[ADD1]] +; + %add = fadd float %f1, 4.000000e+00 + %add1 = fadd reassoc float %add, 5.000000e+00 + ret float %add1 +} + ; (X + X) + X => 3.0 * X define float @fold6(float %f1) { ; CHECK-LABEL: @fold6( @@ -82,6 +155,29 @@ ret float %t2 } +; Check again using the minimal subset of FMF. +define float @fold6_reassoc_nsz(float %f1) { +; CHECK-LABEL: @fold6_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[F1:%.*]], 3.000000e+00 +; CHECK-NEXT: ret float [[TMP1]] +; + %t1 = fadd reassoc nsz float %f1, %f1 + %t2 = fadd reassoc nsz float %f1, %t1 + ret float %t2 +} + +; Verify the fold is not done with only reassoc. +define float @fold6_reassoc(float %f1) { +; CHECK-LABEL: @fold6_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[F1:%.*]], [[F1]] +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[TMP1]], [[F1]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fadd reassoc float %f1, %f1 + %t2 = fadd reassoc float %f1, %t1 + ret float %t2 +} + ; C1 * X + (X + X) = (C1 + 2) * X define float @fold7(float %f1) { ; CHECK-LABEL: @fold7( @@ -94,6 +190,32 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fold7_reassoc_nsz(float %f1) { +; CHECK-LABEL: @fold7_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[F1:%.*]], 7.000000e+00 +; CHECK-NEXT: ret float [[TMP1]] +; + %t1 = fmul reassoc nsz float %f1, 5.000000e+00 + %t2 = fadd reassoc nsz float %f1, %f1 + %t3 = fadd reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fold7_reassoc(float %f1) { +; CHECK-LABEL: @fold7_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[F1:%.*]], 5.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[F1]], [[F1]] +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fmul reassoc float %f1, 5.000000e+00 + %t2 = fadd reassoc float %f1, %f1 + %t3 = fadd reassoc float %t1, %t2 + ret float %t3 +} + ; (X + X) + (X + X) => 4.0 * X define float @fold8(float %f1) { ; CHECK-LABEL: @fold8( @@ -106,6 +228,32 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fold8_reassoc_nsz(float %f1) { +; CHECK-LABEL: @fold8_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[F1:%.*]], 4.000000e+00 +; CHECK-NEXT: ret float [[TMP1]] +; + %t1 = fadd reassoc nsz float %f1, %f1 + %t2 = fadd reassoc nsz float %f1, %f1 + %t3 = fadd reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fold8_reassoc(float %f1) { +; CHECK-LABEL: @fold8_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[F1:%.*]], [[F1]] +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[F1]], [[F1]] +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fadd reassoc float %f1, %f1 + %t2 = fadd reassoc float %f1, %f1 + %t3 = fadd reassoc float %t1, %t2 + ret float %t3 +} + ; X - (X + Y) => 0 - Y define float @fold9(float %f1, float %f2) { ; CHECK-LABEL: @fold9( @@ -117,6 +265,29 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fold9_reassoc_nsz(float %f1, float %f2) { +; CHECK-LABEL: @fold9_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float -0.000000e+00, [[F2:%.*]] +; CHECK-NEXT: ret float [[TMP1]] +; + %t1 = fadd float %f1, %f2 + %t3 = fsub reassoc nsz float %f1, %t1 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fold9_reassoc(float %f1, float %f2) { +; CHECK-LABEL: @fold9_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fadd float [[F1:%.*]], [[F2:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fsub reassoc float [[F1]], [[TMP1]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fadd float %f1, %f2 + %t3 = fsub reassoc float %f1, %t1 + ret float %t3 +} + ; Let C3 = C1 + C2. (f1 + C1) + (f2 + C2) => (f1 + f2) + C3 instead of ; "(f1 + C3) + f2" or "(f2 + C3) + f1". Placing constant-addend at the ; top of resulting simplified expression tree may potentially reveal some @@ -134,6 +305,34 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fold10_reassoc_nsz(float %f1, float %f2) { +; CHECK-LABEL: @fold10_reassoc_nsz( +; CHECK-NEXT: [[T2:%.*]] = fadd reassoc nsz float [[F1:%.*]], [[F2:%.*]] +; CHECK-NEXT: [[T3:%.*]] = fadd reassoc nsz float [[T2]], -1.000000e+00 +; CHECK-NEXT: ret float [[T3]] +; + %t1 = fadd reassoc nsz float 2.000000e+00, %f1 + %t2 = fsub reassoc nsz float %f2, 3.000000e+00 + %t3 = fadd reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc (the instructions are +; canonicalized, but not folded). +define float @fold10_reassoc(float %f1, float %f2) { +; CHECK-LABEL: @fold10_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc float [[F1:%.*]], 2.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc float [[F2:%.*]], -3.000000e+00 +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fadd reassoc float 2.000000e+00, %f1 + %t2 = fsub reassoc float %f2, 3.000000e+00 + %t3 = fadd reassoc float %t1, %t2 + ret float %t3 +} + ; This used to crash/miscompile. define float @fail1(float %f1, float %f2) { @@ -171,6 +370,29 @@ ret float %sub } +; Check again using the minimal subset of FMF. +define float @fold13_reassoc_nsz(float %x) { +; CHECK-LABEL: @fold13_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], 6.000000e+00 +; CHECK-NEXT: ret float [[TMP1]] +; + %mul = fmul reassoc nsz float %x, 7.000000e+00 + %sub = fsub reassoc nsz float %mul, %x + ret float %sub +} + +; Verify the fold is not done with only reassoc. +define float @fold13_reassoc(float %x) { +; CHECK-LABEL: @fold13_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], 7.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = fsub reassoc float [[TMP1]], [[X]] +; CHECK-NEXT: ret float [[TMP2]] +; + %mul = fmul reassoc float %x, 7.000000e+00 + %sub = fsub reassoc float %mul, %x + ret float %sub +} + ; -x + y => y - x define float @fold14(float %x, float %y) { ; CHECK-LABEL: @fold14( @@ -182,6 +404,17 @@ ret float %add } +; Check again using the minimal subset of FMF (reassoc is sufficient). +define float @fold14_reassoc(float %x, float %y) { +; CHECK-LABEL: @fold14_reassoc( +; CHECK-NEXT: [[ADD:%.*]] = fsub reassoc float [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret float [[ADD]] +; + %neg = fsub reassoc float -0.0, %x + %add = fadd reassoc float %neg, %y + ret float %add +} + ; x + -y => x - y define float @fold15(float %x, float %y) { ; CHECK-LABEL: @fold15( @@ -193,6 +426,17 @@ ret float %add } +; Check again using the minimal subset of FMF (reassoc is sufficient). +define float @fold15_reassoc(float %x, float %y) { +; CHECK-LABEL: @fold15_reassoc( +; CHECK-NEXT: [[ADD:%.*]] = fsub reassoc float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret float [[ADD]] +; + %neg = fsub reassoc float -0.0, %y + %add = fadd reassoc float %x, %neg + ret float %add +} + ; (select X+Y, X-Y) => X + (select Y, -Y) define float @fold16(float %x, float %y) { ; CHECK-LABEL: @fold16( @@ -209,6 +453,22 @@ ret float %r } +; Check again using the minimal subset of FMF (reassoc is sufficient). +define float @fold16_reassoc(float %x, float %y) { +; CHECK-LABEL: @fold16_reassoc( +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc float -0.000000e+00, [[Y]] +; CHECK-NEXT: [[R_P:%.*]] = select i1 [[CMP]], float [[Y]], float [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fadd reassoc float [[R_P]], [[X]] +; CHECK-NEXT: ret float [[R]] +; + %cmp = fcmp ogt float %x, %y + %plus = fadd reassoc float %x, %y + %minus = fsub reassoc float %x, %y + %r = select i1 %cmp, float %plus, float %minus + ret float %r +} + ; ========================================================================= ; ; Testing-cases about negation @@ -331,6 +591,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_mul1_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul1_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul reassoc nsz float %x, %z + %t2 = fmul reassoc nsz float %y, %z + %t3 = fadd reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_mul1_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul1_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc float [[Y:%.*]] [[Z]] +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fmul reassoc float %x, %z + %t2 = fmul reassoc float %y, %z + %t3 = fadd reassoc float %t1, %t2 + ret float %t3 +} + ; z*x + y*z => (x+y) * z define float @fact_mul2(float %x, float %y, float %z) { ; CHECK-LABEL: @fact_mul2( @@ -344,6 +631,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_mul2_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul2_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul reassoc nsz float %z, %x + %t2 = fmul reassoc nsz float %y, %z + %t3 = fsub reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_mul2_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul2_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc float [[Y:%.*]], [[Z]] +; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fmul reassoc float %z, %x + %t2 = fmul reassoc float %y, %z + %t3 = fsub reassoc float %t1, %t2 + ret float %t3 +} + ; z*x - z*y => (x-y) * z define float @fact_mul3(float %x, float %y, float %z) { ; CHECK-LABEL: @fact_mul3( @@ -357,6 +671,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_mul3_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul3_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t2 = fmul reassoc nsz float %z, %y + %t1 = fmul reassoc nsz float %z, %x + %t3 = fsub reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_mul3_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul3_reassoc( +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc float [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[Z]], [[X:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t2 = fmul reassoc float %z, %y + %t1 = fmul reassoc float %z, %x + %t3 = fsub reassoc float %t1, %t2 + ret float %t3 +} + ; x*z - z*y => (x-y) * z define float @fact_mul4(float %x, float %y, float %z) { ; CHECK-LABEL: @fact_mul4( @@ -370,6 +711,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_mul4_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul4_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fmul reassoc nsz float %x, %z + %t2 = fmul reassoc nsz float %z, %y + %t3 = fsub reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_mul4_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_mul4_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc float [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc float [[Z]], [[Y:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fmul reassoc float %x, %z + %t2 = fmul reassoc float %z, %y + %t3 = fsub reassoc float %t1, %t2 + ret float %t3 +} + ; x/y + x/z, no xform define float @fact_div1(float %x, float %y, float %z) { ; CHECK-LABEL: @fact_div1( @@ -411,6 +779,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_div3_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_div3_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[Y:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv reassoc nsz float %y, %x + %t2 = fdiv reassoc nsz float %z, %x + %t3 = fadd reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_div3_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_div3_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fdiv reassoc float [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc float [[Z:%.*]], [[X]] +; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fdiv reassoc float %y, %x + %t2 = fdiv reassoc float %z, %x + %t3 = fadd reassoc float %t1, %t2 + ret float %t3 +} + ; y/x - z/x => (y-z)/x define float @fact_div4(float %x, float %y, float %z) { ; CHECK-LABEL: @fact_div4( @@ -424,6 +819,33 @@ ret float %t3 } +; Check again using the minimal subset of FMF. +define float @fact_div4_reassoc_nsz(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_div4_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[Y:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc nsz float [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret float [[TMP2]] +; + %t1 = fdiv reassoc nsz float %y, %x + %t2 = fdiv reassoc nsz float %z, %x + %t3 = fsub reassoc nsz float %t1, %t2 + ret float %t3 +} + +; Verify the fold is not done with only reassoc. +define float @fact_div4_reassoc(float %x, float %y, float %z) { +; CHECK-LABEL: @fact_div4_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fdiv reassoc float [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fdiv reassoc float [[Z:%.*]], [[X]] +; CHECK-NEXT: [[TMP3:%.*]] = fsub reassoc float [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fdiv reassoc float %y, %x + %t2 = fdiv reassoc float %z, %x + %t3 = fsub reassoc float %t1, %t2 + ret float %t3 +} + ; y/x - z/x => (y-z)/x is disabled if y-z is denormal. define float @fact_div5(float %x) { ; CHECK-LABEL: @fact_div5( @@ -758,3 +1180,26 @@ ret float %value } +; Check again using the minimal subset of FMF (reassoc is sufficient). +define float @test55_reassoc(i1 %which, float %a) { +; CHECK-LABEL: @test55_reassoc( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] +; CHECK: delay: +; CHECK-NEXT: [[PHITMP:%.*]] = fadd reassoc float [[A:%.*]], 1.000000e+00 +; CHECK-NEXT: br label [[FINAL]] +; CHECK: final: +; CHECK-NEXT: [[A:%.*]] = phi float [ 3.000000e+00, [[ENTRY:%.*]] ], [ [[PHITMP]], [[DELAY]] ] +; CHECK-NEXT: ret float [[A]] +; +entry: + br i1 %which, label %final, label %delay + +delay: + br label %final + +final: + %A = phi float [ 2.0, %entry ], [ %a, %delay ] + %value = fadd reassoc float %A, 1.0 + ret float %value +} Index: test/Transforms/Reassociate/fast-MissedTree.ll =================================================================== --- test/Transforms/Reassociate/fast-MissedTree.ll +++ test/Transforms/Reassociate/fast-MissedTree.ll @@ -13,16 +13,14 @@ ; Check again using minimal subset of FMF. -define float @test1_reassoc(float %A, float %B) { -; CHECK-LABEL: @test1_reassoc( -; CHECK-NEXT: [[W:%.*]] = fadd reassoc float %B, -5.000000e+00 -; CHECK-NEXT: [[Y:%.*]] = fadd reassoc float %A, 5.000000e+00 -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[Y]], [[W]] +define float @test1_minimal(float %A, float %B) { +; CHECK-LABEL: @test1_minimal( +; CHECK-NEXT: [[Z:%.*]] = fadd reassoc nsz float %A, %B ; CHECK-NEXT: ret float [[Z]] ; - %W = fadd reassoc float %B, -5.0 - %Y = fadd reassoc float %A, 5.0 - %Z = fadd reassoc float %W, %Y + %W = fadd reassoc nsz float %B, -5.0 + %Y = fadd reassoc nsz float %A, 5.0 + %Z = fadd reassoc nsz float %W, %Y ret float %Z } Index: test/Transforms/Reassociate/fast-SubReassociate.ll =================================================================== --- test/Transforms/Reassociate/fast-SubReassociate.ll +++ test/Transforms/Reassociate/fast-SubReassociate.ll @@ -30,18 +30,15 @@ ; Check again using minimal subset of FMF. -define float @test2_reassoc(float %A, float %B) { -; CHECK-LABEL: @test2_reassoc( -; CHECK-NEXT: [[W:%.*]] = fadd reassoc float %B, 5.000000e+00 -; CHECK-NEXT: [[X:%.*]] = fadd reassoc float %A, -7.000000e+00 -; CHECK-NEXT: [[Y:%.*]] = fsub reassoc float [[X]], [[W]] -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[Y]], 1.200000e+01 +define float @test2_minimal(float %A, float %B) { +; CHECK-LABEL: @test2_minimal( +; CHECK-NEXT: [[Z:%.*]] = fsub reassoc nsz float %A, %B ; CHECK-NEXT: ret float [[Z]] ; - %W = fadd reassoc float %B, 5.000000e+00 - %X = fadd reassoc float %A, -7.000000e+00 - %Y = fsub reassoc float %X, %W - %Z = fadd reassoc float %Y, 1.200000e+01 + %W = fadd reassoc nsz float %B, 5.000000e+00 + %X = fadd reassoc nsz float %A, -7.000000e+00 + %Y = fsub reassoc nsz float %X, %W + %Z = fadd reassoc nsz float %Y, 1.200000e+01 ret float %Z } Index: test/Transforms/Reassociate/fast-basictest.ll =================================================================== --- test/Transforms/Reassociate/fast-basictest.ll +++ test/Transforms/Reassociate/fast-basictest.ll @@ -12,14 +12,14 @@ ret float %t2 } -define float @test1_reassoc(float %arg) { -; CHECK-LABEL: @test1_reassoc( -; CHECK-NEXT: [[T1:%.*]] = fsub reassoc float -1.200000e+01, [[ARG:%.*]] -; CHECK-NEXT: [[T2:%.*]] = fadd reassoc float [[T1]], 1.200000e+01 -; CHECK-NEXT: ret float [[T2]] +; Check again using the minimal subset of FMF. +define float @test1_minimal(float %arg) { +; CHECK-LABEL: @test1_minimal( +; CHECK-NEXT: [[ARG_NEG:%.*]] = fsub reassoc nsz float -0.000000e+00, [[ARG:%.*]] +; CHECK-NEXT: ret float [[ARG_NEG]] ; - %t1 = fsub reassoc float -1.200000e+01, %arg - %t2 = fadd reassoc float %t1, 1.200000e+01 + %t1 = fsub reassoc nsz float -1.200000e+01, %arg + %t2 = fadd reassoc nsz float %t1, 1.200000e+01 ret float %t2 } @@ -210,14 +210,14 @@ ret float %Z } -define float @test9_reassoc(float %X) { -; CHECK-LABEL: @test9_reassoc( -; CHECK-NEXT: [[Y:%.*]] = fmul reassoc float [[X:%.*]], 4.700000e+01 -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[Y]], [[Y]] -; CHECK-NEXT: ret float [[Z]] +; Check again using the minimal subset of FMF. +define float @test9_minimal(float %X) { +; CHECK-LABEL: @test9_minimal( +; CHECK-NEXT: [[FACTOR:%.*]] = fmul reassoc nsz float [[X:%.*]], 9.400000e+01 +; CHECK-NEXT: ret float [[FACTOR]] ; - %Y = fmul reassoc float %X, 4.700000e+01 - %Z = fadd reassoc float %Y, %Y + %Y = fmul reassoc nsz float %X, 4.700000e+01 + %Z = fadd reassoc nsz float %Y, %Y ret float %Z } @@ -231,14 +231,14 @@ ret float %Z } -define float @test10_reassoc(float %X) { -; CHECK-LABEL: @test10_reassoc( -; CHECK-NEXT: [[Y:%.*]] = fadd reassoc float [[X:%.*]], [[X]] -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[Y]], [[X]] -; CHECK-NEXT: ret float [[Z]] +; Check again using the minimal subset of FMF. +define float @test10_minimal(float %X) { +; CHECK-LABEL: @test10_minimal( +; CHECK-NEXT: [[FACTOR:%.*]] = fmul reassoc nsz float [[X:%.*]], 3.000000e+00 +; CHECK-NEXT: ret float [[FACTOR]] ; - %Y = fadd reassoc float %X ,%X - %Z = fadd reassoc float %Y, %X + %Y = fadd reassoc nsz float %X ,%X + %Z = fadd reassoc nsz float %Y, %X ret float %Z } @@ -253,16 +253,15 @@ ret float %Z } -define float @test11_reassoc(float %W) { -; CHECK-LABEL: @test11_reassoc( -; CHECK-NEXT: [[X:%.*]] = fmul reassoc float [[W:%.*]], 1.270000e+02 -; CHECK-NEXT: [[Y:%.*]] = fadd reassoc float [[X]], [[X]] -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[X]], [[Y]] -; CHECK-NEXT: ret float [[Z]] +; Check again using the minimal subset of FMF. +define float @test11_minimal(float %W) { +; CHECK-LABEL: @test11_minimal( +; CHECK-NEXT: [[FACTOR:%.*]] = fmul reassoc nsz float [[W:%.*]], 3.810000e+02 +; CHECK-NEXT: ret float [[FACTOR]] ; - %X = fmul reassoc float %W, 127.0 - %Y = fadd reassoc float %X ,%X - %Z = fadd reassoc float %Y, %X + %X = fmul reassoc nsz float %W, 127.0 + %Y = fadd reassoc nsz float %X ,%X + %Z = fadd reassoc nsz float %Y, %X ret float %Z } @@ -280,20 +279,18 @@ ret float %Z } -define float @test12_reassoc(float %X) { -; CHECK-LABEL: @test12_reassoc( -; CHECK-NEXT: [[A:%.*]] = fsub reassoc float 1.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = fsub reassoc float 2.000000e+00, [[X]] -; CHECK-NEXT: [[C:%.*]] = fsub reassoc float 3.000000e+00, [[X]] -; CHECK-NEXT: [[Y:%.*]] = fadd reassoc float [[A]], [[B]] -; CHECK-NEXT: [[Z:%.*]] = fadd reassoc float [[C]], [[Y]] +; Check again using the minimal subset of FMF. +define float @test12_minimal(float %X) { +; CHECK-LABEL: @test12_minimal( +; CHECK-NEXT: [[FACTOR:%.*]] = fmul reassoc nsz float [[X:%.*]], 3.000000e+00 +; CHECK-NEXT: [[Z:%.*]] = fsub reassoc nsz float 6.000000e+00, [[FACTOR]] ; CHECK-NEXT: ret float [[Z]] ; - %A = fsub reassoc float 1.000000e+00, %X - %B = fsub reassoc float 2.000000e+00, %X - %C = fsub reassoc float 3.000000e+00, %X - %Y = fadd reassoc float %A ,%B - %Z = fadd reassoc float %Y, %C + %A = fsub reassoc nsz float 1.000000e+00, %X + %B = fsub reassoc nsz float 2.000000e+00, %X + %C = fsub reassoc nsz float 3.000000e+00, %X + %Y = fadd reassoc nsz float %A ,%B + %Z = fadd reassoc nsz float %Y, %C ret float %Z } @@ -337,16 +334,16 @@ ret float %D } -define float @test14_reassoc(float %X1, float %X2) { -; CHECK-LABEL: @test14_reassoc( -; CHECK-NEXT: [[B:%.*]] = fmul reassoc float [[X1:%.*]], 4.700000e+01 -; CHECK-NEXT: [[C:%.*]] = fmul reassoc float [[X2:%.*]], 4.700000e+01 -; CHECK-NEXT: [[D1:%.*]] = fsub reassoc float [[B]], [[C]] -; CHECK-NEXT: ret float [[D1]] +; Check again using the minimal subset of FMF. +define float @test14_minimal(float %X1, float %X2) { +; CHECK-LABEL: @test14_minimal( +; CHECK-NEXT: [[TMP1:%.*]] = fsub reassoc nsz float [[X1:%.*]], [[X2:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc nsz float [[TMP1]], 4.700000e+01 +; CHECK-NEXT: ret float [[TMP2]] ; - %B = fmul reassoc float %X1, 47. ; X1*47 - %C = fmul reassoc float %X2, -47. ; X2*-47 - %D = fadd reassoc float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) + %B = fmul reassoc nsz float %X1, 47. ; X1*47 + %C = fmul reassoc nsz float %X2, -47. ; X2*-47 + %D = fadd reassoc nsz float %B, %C ; X1*47 + X2*-47 -> 47*(X1-X2) ret float %D }