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  <richard.sandiford@arm.com>

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
This commit is contained in:
Richard Sandiford 2019-04-05 07:31:12 +00:00 committed by Richard Sandiford
parent ce36ba09fe
commit 8d6b13da61
4 changed files with 35 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2019-04-05 Richard Sandiford <richard.sandiford@arm.com>
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 <msebor@redhat.com>
PR middle-end/89957

View File

@ -1,3 +1,8 @@
2019-04-05 Richard Sandiford <richard.sandiford@arm.com>
PR tree-optimization/89956
* gfortran.dg/pr89956.f90: New test.
2019-04-04 Martin Sebor <msebor@redhat.com>
PR c++/89974

View File

@ -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

View File

@ -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];