Make FMA code cope with redundant negates (PR89956)
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 5 Apr 2019 07:31:12 +0000 (07:31 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 5 Apr 2019 07:31:12 +0000 (07:31 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/pr89956.f90 [new file with mode: 0644]
gcc/tree-ssa-math-opts.c

index 4e17249cda354c8ce1704712d0f77b51a971e351..c4693bfc324353be46acb1cfef67e9fe440357a2 100644 (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
index 26c5637619fae1b87097f7a8b286dbbccc180cc9..af77f0252aeb1363d8783950d6c7f55063b20a0b 100644 (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
diff --git a/gcc/testsuite/gfortran.dg/pr89956.f90 b/gcc/testsuite/gfortran.dg/pr89956.f90
new file mode 100644 (file)
index 0000000..f850afd
--- /dev/null
@@ -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
index 8902d85a7c94f5895c686912fb090b1cf57643de..1496520c9dc6b94807a1493be5976b40c2ab8f33 100644 (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];