From 8d6b13da61aabc7c55d858ee3fd7ae22798d6a61 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 5 Apr 2019 07:31:12 +0000 Subject: [PATCH] Make FMA code cope with redundant negates (PR89956) This patch fixes a case in which, due to forced missed optimisations in earlier passes, we have: _1 = a * b _2 = -_1 _3 = -_1 _4 = _2 + _3 and treated _4 as two FNMA candidates, once via _2 and once via _3. 2019-04-05 Richard Sandiford gcc/ PR tree-optimization/89956 * tree-ssa-math-opts.c (convert_mult_to_fma): Protect against multiple negates of the same value. gcc/testsuite/ PR tree-optimization/89956 * gfortran.dg/pr89956.f90: New test. From-SVN: r270162 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gfortran.dg/pr89956.f90 | 16 ++++++++++++++++ gcc/tree-ssa-math-opts.c | 9 ++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/pr89956.f90 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4e17249cda3..c4693bfc324 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-04-05 Richard Sandiford + + PR tree-optimization/89956 + * tree-ssa-math-opts.c (convert_mult_to_fma): Protect against + multiple negates of the same value. + 2019-04-04 Martin Sebor PR middle-end/89957 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 26c5637619f..af77f0252ae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-04-05 Richard Sandiford + + PR tree-optimization/89956 + * gfortran.dg/pr89956.f90: New test. + 2019-04-04 Martin Sebor PR c++/89974 diff --git a/gcc/testsuite/gfortran.dg/pr89956.f90 b/gcc/testsuite/gfortran.dg/pr89956.f90 new file mode 100644 index 00000000000..f850afdebc1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr89956.f90 @@ -0,0 +1,16 @@ +! { dg-options "-O3 -fno-tree-forwprop -fno-tree-pre -fno-tree-dominator-opts -fno-code-hoisting -ffast-math" } + +module de +contains + function zu (az, xx) result (q3) + real :: az, xx, q3 + + q3 = 1.0 - lz (az, xx) - lz (xx, az) + end function zu + + function lz (ho, gh) result (ye) + real :: ho, gh, ye + + ye = sqrt (ho) - ho * gh + end function lz +end module de diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 8902d85a7c9..1496520c9dc 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3094,6 +3094,7 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2, && (tree_to_shwi (TYPE_SIZE (type)) <= PARAM_VALUE (PARAM_AVOID_FMA_MAX_BITS))); bool defer = check_defer; + bool seen_negate_p = false; /* Make sure that the multiplication statement becomes dead after the transformation, thus that all uses are transformed to FMAs. This means we assume that an FMA operation has the same cost @@ -3127,6 +3128,12 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2, ssa_op_iter iter; use_operand_p usep; + /* If (due to earlier missed optimizations) we have two + negates of the same value, treat them as equivalent + to a single negate with multiple uses. */ + if (seen_negate_p) + return false; + result = gimple_assign_lhs (use_stmt); /* Make sure the negate statement becomes dead with this @@ -3145,7 +3152,7 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2, if (gimple_bb (use_stmt) != gimple_bb (mul_stmt)) return false; - negate_p = true; + negate_p = seen_negate_p = true; } tree cond, else_value, ops[3];