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.

Tested on aarch64-linux-gnu.  OK to install?

Richard


2019-04-04  Richard Sandiford  <richard.sandif...@arm.com>

gcc/
        PR tree-optimization/89956
        * tree-ssa-math-opts.c (convert_mult_to_fma): Protected against
        multiple negates of the same value.

gcc/testsuite/
        PR tree-optimization/89956
        * gfortran.dg/pr89956.f90: New test.

Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c    2019-04-04 08:34:52.217937275 +0100
+++ gcc/tree-ssa-math-opts.c    2019-04-04 09:11:12.733814338 +0100
@@ -3094,6 +3094,7 @@ convert_mult_to_fma (gimple *mul_stmt, t
        && (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, t
          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, t
          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];
Index: gcc/testsuite/gfortran.dg/pr89956.f90
===================================================================
--- /dev/null   2019-03-08 11:40:14.606883727 +0000
+++ gcc/testsuite/gfortran.dg/pr89956.f90       2019-04-04 09:11:12.733814338 
+0100
@@ -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

Reply via email to