diff options
Diffstat (limited to 'llvm/test/Transforms/InstCombine/fast-math.ll')
| -rw-r--r-- | llvm/test/Transforms/InstCombine/fast-math.ll | 445 |
1 files changed, 423 insertions, 22 deletions
diff --git a/llvm/test/Transforms/InstCombine/fast-math.ll b/llvm/test/Transforms/InstCombine/fast-math.ll index 82bc16c2828..132432f1013 100644 --- a/llvm/test/Transforms/InstCombine/fast-math.ll +++ b/llvm/test/Transforms/InstCombine/fast-math.ll @@ -37,16 +37,42 @@ define float @fold2(float %a) { } ; C * f1 + f1 = (C+1) * f1 +; TODO: The particular case where C is 2 (so the folded result is 3.0*f1) is +; always safe, and so doesn't need any FMF. +; That is, (x + x + x) and (3*x) each have only a single rounding. define double @fold3(double %f1) { ; CHECK-LABEL: @fold3( -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast double [[F1:%.*]], 3.000000e+00 +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast double [[F1:%.*]], 6.000000e+00 ; CHECK-NEXT: ret double [[TMP1]] ; - %t1 = fmul fast double 2.000000e+00, %f1 + %t1 = fmul fast double 5.000000e+00, %f1 %t2 = fadd fast double %f1, %t1 ret double %t2 } +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +define double @fold3_reassoc_nsz(double %f1) { +; CHECK-LABEL: @fold3_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz double [[F1:%.*]], 6.000000e+00 +; CHECK-NEXT: ret double [[TMP1]] +; + %t1 = fmul reassoc nsz double 5.000000e+00, %f1 + %t2 = fadd reassoc nsz double %f1, %t1 + ret double %t2 +} + +; TODO: This doesn't require 'nsz'. It should fold to f1 * 6.0. +define double @fold3_reassoc(double %f1) { +; CHECK-LABEL: @fold3_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc double [[F1:%.*]], 5.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc double [[TMP1]], [[F1]] +; CHECK-NEXT: ret double [[TMP2]] +; + %t1 = fmul reassoc double 5.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,8 +86,35 @@ define float @fold4(float %f1, float %f2) { ret float %add } +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +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 +} + +; TODO: This doesn't require 'nsz'. It should fold to (9.0 - (f1 + f2)). +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) { +define float @fold5(float %f1) { ; CHECK-LABEL: @fold5( ; CHECK-NEXT: [[ADD1:%.*]] = fadd fast float [[F1:%.*]], 9.000000e+00 ; CHECK-NEXT: ret float [[ADD1]] @@ -71,15 +124,65 @@ define float @fold5(float %f1, float %f2) { ret float %add1 } -; (X + X) + X => 3.0 * X +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +define float @fold5_reassoc_nsz(float %f1) { +; 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 +} + +; TODO: This doesn't require 'nsz'. It should fold to f1 + 9.0 +define float @fold5_reassoc(float %f1) { +; 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 + X => 4.0 * X define float @fold6(float %f1) { ; CHECK-LABEL: @fold6( -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[F1:%.*]], 3.000000e+00 +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[F1:%.*]], 4.000000e+00 ; CHECK-NEXT: ret float [[TMP1]] ; %t1 = fadd fast float %f1, %f1 %t2 = fadd fast float %f1, %t1 - ret float %t2 + %t3 = fadd fast float %t2, %f1 + ret float %t3 +} + +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +define float @fold6_reassoc_nsz(float %f1) { +; CHECK-LABEL: @fold6_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, %t1 + %t3 = fadd reassoc nsz float %t2, %f1 + ret float %t3 +} + +; TODO: This doesn't require 'nsz'. It should fold to f1 * 4.0. +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: [[TMP3:%.*]] = fadd reassoc float [[TMP2]], [[F1]] +; CHECK-NEXT: ret float [[TMP3]] +; + %t1 = fadd reassoc float %f1, %f1 + %t2 = fadd reassoc float %f1, %t1 + %t3 = fadd reassoc float %t2, %f1 + ret float %t3 } ; C1 * X + (X + X) = (C1 + 2) * X @@ -94,16 +197,72 @@ define float @fold7(float %f1) { ret float %t3 } -; (X + X) + (X + X) => 4.0 * X +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +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 +} + +; TODO: This doesn't require 'nsz'. It should fold to f1 * 7.0. +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) + X => 5.0 * X define float @fold8(float %f1) { ; CHECK-LABEL: @fold8( -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[F1:%.*]], 4.000000e+00 +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[F1:%.*]], 5.000000e+00 ; CHECK-NEXT: ret float [[TMP1]] ; %t1 = fadd fast float %f1, %f1 %t2 = fadd fast float %f1, %f1 %t3 = fadd fast float %t1, %t2 - ret float %t3 + %t4 = fadd fast float %t3, %f1 + ret float %t4 +} + +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +define float @fold8_reassoc_nsz(float %f1) { +; CHECK-LABEL: @fold8_reassoc_nsz( +; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[F1:%.*]], 5.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 + %t4 = fadd reassoc nsz float %t3, %f1 + ret float %t4 +} + +; TODO: This doesn't require 'nsz'. It should fold to f1 * 5.0. +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: [[TMP4:%.*]] = fadd reassoc float [[TMP3]], [[F1]] +; CHECK-NEXT: ret float [[TMP4]] +; + %t1 = fadd reassoc float %f1, %f1 + %t2 = fadd reassoc float %f1, %f1 + %t3 = fadd reassoc float %t1, %t2 + %t4 = fadd reassoc float %t3, %f1 + ret float %t4 } ; X - (X + Y) => 0 - Y @@ -117,6 +276,29 @@ define float @fold9(float %f1, float %f2) { ret float %t3 } +; Check again with 'reassoc' and 'nsz' ('nsz' not technically required). +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 +} + +; TODO: This doesn't require 'nsz'. It should fold to 0 - f2 +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 +316,36 @@ define float @fold10(float %f1, float %f2) { ret float %t3 } +; Check again with 'reassoc' and 'nsz'. +; TODO: We may be able to remove the 'nsz' requirement. +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 +} + +; Observe that the fold is not done with only reassoc (the instructions are +; canonicalized, but not folded). +; TODO: As noted above, 'nsz' may not be required for this to be fully 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,40 +383,66 @@ define float @fold13(float %x) { 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' ('nsz' is required). +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 +; This is always safe. No FMF required. define float @fold14(float %x, float %y) { ; CHECK-LABEL: @fold14( -; CHECK-NEXT: [[ADD:%.*]] = fsub fast float [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[ADD:%.*]] = fsub float [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret float [[ADD]] ; - %neg = fsub fast float -0.0, %x - %add = fadd fast float %neg, %y + %neg = fsub float -0.0, %x + %add = fadd float %neg, %y ret float %add } ; x + -y => x - y +; This is always safe. No FMF required. define float @fold15(float %x, float %y) { ; CHECK-LABEL: @fold15( -; CHECK-NEXT: [[ADD:%.*]] = fsub fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[ADD:%.*]] = fsub float [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret float [[ADD]] ; - %neg = fsub fast float -0.0, %y - %add = fadd fast float %x, %neg + %neg = fsub float -0.0, %y + %add = fadd float %x, %neg ret float %add } ; (select X+Y, X-Y) => X + (select Y, -Y) +; This is always safe. No FMF required. define float @fold16(float %x, float %y) { ; CHECK-LABEL: @fold16( ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = fsub fast float -0.000000e+00, [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = fsub float -0.000000e+00, [[Y]] ; CHECK-NEXT: [[R_P:%.*]] = select i1 [[CMP]], float [[Y]], float [[TMP1]] -; CHECK-NEXT: [[R:%.*]] = fadd fast float [[R_P]], [[X]] +; CHECK-NEXT: [[R:%.*]] = fadd float [[R_P]], [[X]] ; CHECK-NEXT: ret float [[R]] ; %cmp = fcmp ogt float %x, %y - %plus = fadd fast float %x, %y - %minus = fsub fast float %x, %y + %plus = fadd float %x, %y + %minus = fsub float %x, %y %r = select i1 %cmp, float %plus, float %minus ret float %r } @@ -331,6 +569,33 @@ define float @fact_mul1(float %x, float %y, float %z) { 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' ('nsz' is required). +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 +609,33 @@ define float @fact_mul2(float %x, float %y, float %z) { 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' ('nsz' is required). +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 +649,33 @@ define float @fact_mul3(float %x, float %y, float %z) { 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' ('nsz' is required). +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 +689,33 @@ define float @fact_mul4(float %x, float %y, float %z) { 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' ('nsz' is required). +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 +757,33 @@ define float @fact_div3(float %x, float %y, float %z) { 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' ('nsz' is required). +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 +797,33 @@ define float @fact_div4(float %x, float %y, float %z) { 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' ('nsz' is required). +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( @@ -735,12 +1135,14 @@ define fp128 @min4(fp128 %a, fp128 %b) { ret fp128 %c } +; ((which ? 2.0 : a) + 1.0) => (which ? 3.0 : (a + 1.0)) +; This is always safe. No FMF required. define float @test55(i1 %which, float %a) { ; CHECK-LABEL: @test55( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] ; CHECK: delay: -; CHECK-NEXT: [[PHITMP:%.*]] = fadd fast float [[A:%.*]], 1.000000e+00 +; CHECK-NEXT: [[PHITMP:%.*]] = fadd float [[A:%.*]], 1.000000e+00 ; CHECK-NEXT: br label [[FINAL]] ; CHECK: final: ; CHECK-NEXT: [[A:%.*]] = phi float [ 3.000000e+00, [[ENTRY:%.*]] ], [ [[PHITMP]], [[DELAY]] ] @@ -754,7 +1156,6 @@ delay: final: %A = phi float [ 2.0, %entry ], [ %a, %delay ] - %value = fadd fast float %A, 1.0 + %value = fadd float %A, 1.0 ret float %value } - |

