diff mbox

[RFC,PR40921] Convert x + (-y * z * z) into x - y * z * z

Message ID 571B7448.4080005@linaro.org
State Superseded
Headers show

Commit Message

Kugan Vivekanandarajah April 23, 2016, 1:10 p.m. UTC
>> I am not sure I understand this. I tried doing this. If I add  -1 and rhs1

>> for the NEGATE_EXPR to ops list,  when it come to rewrite_expr_tree constant

>> will be sorted early and would make it hard to generate:

>>   x + (-y * z * z) => x - y * z * z

>>

>> Do you want to swap the constant in MULT_EXPR chain (if present) like in

>> swap_ops_for_binary_stmt and then create a NEGATE_EXPR ?

>

> In addition to linearize_expr handling you need to handle a -1 in the MULT_EXPR

> chain specially at rewrite_expr_tree time by emitting a NEGATE_EXPR instead

> of a MULT_EXPR (which also means you should sort the -1 "last").


Hi Richard,

Thanks. Here is an attempt which does this.

Regression tested and bootstrapped on x86-64-linux-gnu with no new 
regressions.

Is this OK for trunk?

Thanks,
Kugan

2016-04-23  Kugan Vivekanandarajah  <kuganv@linaro.org>

	PR middle-end/40921
	* gcc.dg/tree-ssa/pr40921.c: New test.

gcc/ChangeLog:

2016-04-23  Kugan Vivekanandarajah  <kuganv@linaro.org>

	PR middle-end/40921
	* tree-ssa-reassoc.c (try_special_add_to_ops): New.
	(linearize_expr_tree): Call try_special_add_to_ops.
	(reassociate_bb): Convert MULT_EXPR by (-1) to NEGATE_EXPR.
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr40921.c b/gcc/testsuite/gcc.dg/tree-ssa/pr40921.c
index e69de29..f587a8f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr40921.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr40921.c
@@ -0,0 +1,20 @@ 
+
+/* { dg-do compile } */
+/* { dg-options "-O2  -fdump-tree-optimized -ffast-math" } */
+
+unsigned int foo (unsigned int x, unsigned int y, unsigned int z)
+{
+      return x + (-y * z*z);
+}
+
+float bar (float x, float y, float z)
+{
+      return x + (-y * z*z);
+}
+
+float bar (float x, float y, float z)
+{
+      return x + (-y * z*z * 5.0);
+}
+
+/* { dg-final { scan-tree-dump-times "_* = -y_" 0 "optimized" } } */
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index d23dabd..1b38207 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -4252,6 +4252,45 @@  acceptable_pow_call (gimple *stmt, tree *base, HOST_WIDE_INT *exponent)
   return true;
 }
 
+/* Try to derive and add operand entry for OP to *OPS.  Return false if
+   unsuccessful.  */
+
+static bool
+try_special_add_to_ops (vec<operand_entry *> *ops,
+			enum tree_code code,
+			tree op, gimple* def_stmt)
+{
+  tree base = NULL_TREE;
+  HOST_WIDE_INT exponent = 0;
+
+  if (TREE_CODE (op) != SSA_NAME)
+    return false;
+
+  if (code == MULT_EXPR
+      && acceptable_pow_call (def_stmt, &base, &exponent))
+    {
+      add_repeat_to_ops_vec (ops, base, exponent);
+      gimple_set_visited (def_stmt, true);
+      return true;
+    }
+  else if (code == MULT_EXPR
+	   && is_gimple_assign (def_stmt)
+	   && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
+	   && !HONOR_SNANS (TREE_TYPE (op))
+	   && (!HONOR_SIGNED_ZEROS (TREE_TYPE (op))
+	       || !COMPLEX_FLOAT_TYPE_P (TREE_TYPE (op))))
+    {
+      tree rhs1 = gimple_assign_rhs1 (def_stmt);
+      tree cst = build_minus_one_cst (TREE_TYPE (op));
+      add_to_ops_vec (ops, rhs1);
+      add_to_ops_vec (ops, cst);
+      gimple_set_visited (def_stmt, true);
+      return true;
+    }
+
+  return false;
+}
+
 /* Recursively linearize a binary expression that is the RHS of STMT.
    Place the operands of the expression tree in the vector named OPS.  */
 
@@ -4266,8 +4305,6 @@  linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
   bool binrhsisreassoc = false;
   enum tree_code rhscode = gimple_assign_rhs_code (stmt);
   struct loop *loop = loop_containing_stmt (stmt);
-  tree base = NULL_TREE;
-  HOST_WIDE_INT exponent = 0;
 
   if (set_visited)
     gimple_set_visited (stmt, true);
@@ -4303,26 +4340,11 @@  linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
 
       if (!binrhsisreassoc)
 	{
-	  if (rhscode == MULT_EXPR
-	      && TREE_CODE (binrhs) == SSA_NAME
-	      && acceptable_pow_call (binrhsdef, &base, &exponent))
-	    {
-	      add_repeat_to_ops_vec (ops, base, exponent);
-	      gimple_set_visited (binrhsdef, true);
-	    }
-	  else
+	  if (!try_special_add_to_ops (ops, rhscode, binrhs, binrhsdef))
 	    add_to_ops_vec (ops, binrhs);
 
-	  if (rhscode == MULT_EXPR
-	      && TREE_CODE (binlhs) == SSA_NAME
-	      && acceptable_pow_call (binlhsdef, &base, &exponent))
-	    {
-	      add_repeat_to_ops_vec (ops, base, exponent);
-	      gimple_set_visited (binlhsdef, true);
-	    }
-	  else
+	  if (!try_special_add_to_ops (ops, rhscode, binlhs, binlhsdef))
 	    add_to_ops_vec (ops, binlhs);
-
 	  return;
 	}
 
@@ -4360,14 +4382,7 @@  linearize_expr_tree (vec<operand_entry *> *ops, gimple *stmt,
   linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
 		       is_associative, set_visited);
 
-  if (rhscode == MULT_EXPR
-      && TREE_CODE (binrhs) == SSA_NAME
-      && acceptable_pow_call (SSA_NAME_DEF_STMT (binrhs), &base, &exponent))
-    {
-      add_repeat_to_ops_vec (ops, base, exponent);
-      gimple_set_visited (SSA_NAME_DEF_STMT (binrhs), true);
-    }
-  else
+  if (!try_special_add_to_ops (ops, rhscode, binrhs, binrhsdef))
     add_to_ops_vec (ops, binrhs);
 }
 
@@ -5127,6 +5142,19 @@  reassociate_bb (basic_block bb)
 		    powi_result = attempt_builtin_powi (stmt, &ops);
 		}
 
+	      int last = ops.length () - 1;
+	      bool negate_result = false;
+	      if (rhs_code == MULT_EXPR
+		  && ops.length () > 1
+		  && ((TREE_CODE (ops[last]->op) == INTEGER_CST
+		       && integer_minus_onep (ops[last]->op))
+		      || ((TREE_CODE (ops[last]->op) == REAL_CST)
+			  && real_equal (&TREE_REAL_CST (ops[last]->op), &dconstm1))))
+		{
+		  ops.unordered_remove (last);
+		  negate_result = true;
+		}
+
 	      /* If the operand vector is now empty, all operands were 
 		 consumed by the __builtin_powi optimization.  */
 	      if (ops.length () == 0)
@@ -5169,6 +5197,17 @@  reassociate_bb (basic_block bb)
 						   powi_result != NULL);
                     }
 
+		  if (negate_result)
+		    {
+		      tree tmp = make_ssa_name (TREE_TYPE (lhs));
+		      gimple_set_lhs (stmt, tmp);
+		      gassign *neg_stmt = gimple_build_assign (lhs, NEGATE_EXPR,
+							       tmp);
+		      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+		      gsi_insert_after (&gsi, neg_stmt, GSI_NEW_STMT);
+		      update_stmt (stmt);
+		    }
+
 		  /* If we combined some repeated factors into a 
 		     __builtin_powi call, multiply that result by the
 		     reassociated operands.  */