Make FMA code cope with redundant negates (PR89956)

Message ID mpt1s2if3uz.fsf@arm.com
State New
Headers show
Series
  • Make FMA code cope with redundant negates (PR89956)
Related show

Commit Message

Richard Sandiford April 4, 2019, 10:43 a.m.
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.sandiford@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.

Comments

Jeff Law April 4, 2019, 9:19 p.m. | #1
On 4/4/19 4:43 AM, Richard Sandiford wrote:
> 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.sandiford@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.

OK
jeff

Patch

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