diff mbox

Fix PR tree-optimization/71170

Message ID CAELXzTPgcUrck1o5oGGHU6W_nUtGBrRRuKmV6YhsiGyTftEkrQ@mail.gmail.com
State New
Headers show

Commit Message

Kugan Vivekanandarajah May 21, 2016, 6:08 a.m. UTC
On 20 May 2016 at 21:07, Richard Biener <richard.guenther@gmail.com> wrote:
> On Fri, May 20, 2016 at 1:51 AM, Kugan Vivekanandarajah

> <kugan.vivekanandarajah@linaro.org> wrote:

>> Hi Richard,

>>

>>> I think it should have the same rank as op or op + 1 which is the current

>>> behavior.  Sth else doesn't work correctly here I think, like inserting the

>>> multiplication not near the definition of op.

>>>

>>> Well, the whole "clever insertion" logic is simply flawed.

>>

>> What I meant to say was that the simple logic we have now wouldn’t

>> work. "clever logic" is knowing where exactly where it is needed and

>> inserting there.  I think thats what  you are suggesting below in a

>> simple to implement way.

>>

>>> I'd say that ideally we would delay inserting the multiplication to

>>> rewrite_expr_tree time.  For example by adding a ops->stmt_to_insert

>>> member.

>>>

>>

>> Here is an implementation based on above. Bootstrap on x86-linux-gnu

>> is OK. regression testing is ongoing.

>

> I like it.  Please push the insertion code to a helper as I think you need

> to post-pone setting the stmts UID to that point.

>

> Ideally we'd make use of the same machinery in attempt_builtin_powi,

> removing the special-casing of powi_result.  (same as I said that ideally

> the plus->mult stuff would use the repeat-ops machinery...)

>

> I'm not 100% convinced the place you insert the stmt is correct but I

> haven't spent too much time to decipher reassoc in this area.



Hi Richard,

Thanks. Here is a tested version of the patch. I did miss one place
which I fixed now (tranform_stmt_to_copy) I also created a function to
do the insertion.


Bootstrap and regression testing on x86_64-linux-gnu are fine. Is this
OK for trunk.

Thanks,
Kugan


gcc/ChangeLog:

2016-05-21  Kugan Vivekanandarajah  <kuganv@linaro.org>

    PR middle-end/71170
    * tree-ssa-reassoc.c (struct operand_entry): Add field stmt_to_insert.
    (add_to_ops_vec): Add stmt_to_insert.
    (add_repeat_to_ops_vec): Init stmt_to_insert.
    (insert_stmt_before_use): New.
    (transform_add_to_multiply): Remove mult_stmt insertion and add it
to ops vector.
    (get_ops): Init stmt_to_insert.
    (maybe_optimize_range_tests): Likewise.
    (rewrite_expr_tree): Insert  stmt_to_insert before use stmt.
    (rewrite_expr_tree_parallel): Likewise.
    (reassociate_bb): Likewise.
diff mbox

Patch

diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 3b5f36b..0b905e9 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -195,6 +195,7 @@  struct operand_entry
   int id;
   tree op;
   unsigned int count;
+  gimple *stmt_to_insert;
 };
 
 static object_allocator<operand_entry> operand_entry_pool
@@ -553,7 +554,7 @@  sort_by_operand_rank (const void *pa, const void *pb)
 /* Add an operand entry to *OPS for the tree operand OP.  */
 
 static void
-add_to_ops_vec (vec<operand_entry *> *ops, tree op)
+add_to_ops_vec (vec<operand_entry *> *ops, tree op, gimple *stmt_to_insert = NULL)
 {
   operand_entry *oe = operand_entry_pool.allocate ();
 
@@ -561,6 +562,7 @@  add_to_ops_vec (vec<operand_entry *> *ops, tree op)
   oe->rank = get_rank (op);
   oe->id = next_operand_entry_id++;
   oe->count = 1;
+  oe->stmt_to_insert = stmt_to_insert;
   ops->safe_push (oe);
 }
 
@@ -577,6 +579,7 @@  add_repeat_to_ops_vec (vec<operand_entry *> *ops, tree op,
   oe->rank = get_rank (op);
   oe->id = next_operand_entry_id++;
   oe->count = repeat;
+  oe->stmt_to_insert = NULL;
   ops->safe_push (oe);
 
   reassociate_stats.pows_encountered++;
@@ -1756,10 +1759,21 @@  eliminate_redundant_comparison (enum tree_code opcode,
   return false;
 }
 
+/* If the stmt that defines operand has to be inserted, insert it
+   before the use.  */
+static void
+insert_stmt_before_use (gimple *stmt, gimple *stmt_to_insert)
+{
+  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+  gimple_set_uid (stmt_to_insert, gimple_uid (stmt));
+  gsi_insert_before (&gsi, stmt_to_insert, GSI_NEW_STMT);
+}
+
+
 /* Transform repeated addition of same values into multiply with
    constant.  */
 static bool
-transform_add_to_multiply (gimple *stmt, vec<operand_entry *> *ops)
+transform_add_to_multiply (vec<operand_entry *> *ops)
 {
   operand_entry *oe;
   tree op = NULL_TREE;
@@ -1810,21 +1824,11 @@  transform_add_to_multiply (gimple *stmt, vec<operand_entry *> *ops)
 	ops->unordered_remove (i);
       tree tmp = make_ssa_name (TREE_TYPE (op));
       tree cst = build_int_cst (integer_type_node, count);
-      gimple *def_stmt = SSA_NAME_DEF_STMT (op);
       gassign *mul_stmt
 	= gimple_build_assign (tmp, MULT_EXPR,
 			       op, fold_convert (TREE_TYPE (op), cst));
-      if (gimple_code (def_stmt) == GIMPLE_NOP
-	  || gimple_bb (stmt) != gimple_bb (def_stmt))
-	{
-	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-	  gimple_set_uid (mul_stmt, gimple_uid (stmt));
-	  gsi_insert_before (&gsi, mul_stmt, GSI_NEW_STMT);
-	}
-      else
-	insert_stmt_after (mul_stmt, def_stmt);
       gimple_set_visited (mul_stmt, true);
-      add_to_ops_vec (ops, tmp);
+      add_to_ops_vec (ops, tmp, mul_stmt);
       changed = true;
     }
 
@@ -3224,6 +3228,7 @@  get_ops (tree var, enum tree_code code, vec<operand_entry *> *ops,
 	oe->rank = code;
 	oe->id = 0;
 	oe->count = 1;
+	oe->stmt_to_insert = NULL;
 	ops->safe_push (oe);
       }
   return true;
@@ -3464,6 +3469,7 @@  maybe_optimize_range_tests (gimple *stmt)
 	      oe->rank = code;
 	      oe->id = 0;
 	      oe->count = 1;
+	      oe->stmt_to_insert = NULL;
 	      ops.safe_push (oe);
 	      bb_ent.last_idx++;
 	    }
@@ -3501,6 +3507,7 @@  maybe_optimize_range_tests (gimple *stmt)
 	     is.  */
 	  oe->id = bb->index;
 	  oe->count = 1;
+	  oe->stmt_to_insert = NULL;
 	  ops.safe_push (oe);
 	  bb_ent.op = NULL;
 	  bb_ent.last_idx++;
@@ -3798,6 +3805,7 @@  rewrite_expr_tree (gimple *stmt, unsigned int opindex,
       oe1 = ops[opindex];
       oe2 = ops[opindex + 1];
 
+
       if (rhs1 != oe1->op || rhs2 != oe2->op)
 	{
 	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
@@ -3817,6 +3825,12 @@  rewrite_expr_tree (gimple *stmt, unsigned int opindex,
 	    {
 	      gimple *insert_point
 		= find_insert_point (stmt, oe1->op, oe2->op);
+	      /* If the stmt that defines operand has to be inserted, insert it
+		 before the use.  */
+	      if (oe1->stmt_to_insert)
+		insert_stmt_before_use (stmt, oe1->stmt_to_insert);
+	      if (oe2->stmt_to_insert)
+		insert_stmt_before_use (stmt, oe2->stmt_to_insert);
 	      lhs = make_ssa_name (TREE_TYPE (lhs));
 	      stmt
 		= gimple_build_assign (lhs, gimple_assign_rhs_code (stmt),
@@ -3832,6 +3846,12 @@  rewrite_expr_tree (gimple *stmt, unsigned int opindex,
 	    {
 	      gcc_checking_assert (find_insert_point (stmt, oe1->op, oe2->op)
 				   == stmt);
+	      /* If the stmt that defines operand has to be inserted, insert it
+		 before the use.  */
+	      if (oe1->stmt_to_insert)
+		insert_stmt_before_use (stmt, oe1->stmt_to_insert);
+	      if (oe2->stmt_to_insert)
+		insert_stmt_before_use (stmt, oe2->stmt_to_insert);
 	      gimple_assign_set_rhs1 (stmt, oe1->op);
 	      gimple_assign_set_rhs2 (stmt, oe2->op);
 	      update_stmt (stmt);
@@ -3855,6 +3875,11 @@  rewrite_expr_tree (gimple *stmt, unsigned int opindex,
   /* Rewrite the next operator.  */
   oe = ops[opindex];
 
+  /* If the stmt that defines operand has to be inserted, insert it
+     before the use.  */
+  if (oe->stmt_to_insert)
+    insert_stmt_before_use (stmt, oe->stmt_to_insert);
+
   /* Recurse on the LHS of the binary operator, which is guaranteed to
      be the non-leaf side.  */
   tree new_rhs1
@@ -3999,6 +4024,7 @@  rewrite_expr_tree_parallel (gassign *stmt, int width,
   int stmt_index = 0;
   int ready_stmts_end = 0;
   int i = 0;
+  gimple *stmt1 = NULL, *stmt2 = NULL;
   tree last_rhs1 = gimple_assign_rhs1 (stmt);
 
   /* We start expression rewriting from the top statements.
@@ -4027,7 +4053,11 @@  rewrite_expr_tree_parallel (gassign *stmt, int width,
 	  if (ready_stmts_end > stmt_index)
 	    op2 = gimple_assign_lhs (stmts[stmt_index++]);
 	  else if (op_index >= 0)
-	    op2 = ops[op_index--]->op;
+	    {
+	      operand_entry *oe = ops[op_index--];
+	      stmt2 = oe->stmt_to_insert;
+	      op2 = oe->op;
+	    }
 	  else
 	    {
 	      gcc_assert (stmt_index < i);
@@ -4041,8 +4071,12 @@  rewrite_expr_tree_parallel (gassign *stmt, int width,
 	{
 	  if (op_index > 1)
 	    swap_ops_for_binary_stmt (ops, op_index - 2, NULL);
-	  op2 = ops[op_index--]->op;
-	  op1 = ops[op_index--]->op;
+	  operand_entry *oe2 = ops[op_index--];
+	  operand_entry *oe1 = ops[op_index--];
+	  op2 = oe2->op;
+	  stmt2 = oe2->stmt_to_insert;
+	  op1 = oe1->op;
+	  stmt1 = oe1->stmt_to_insert;
 	}
 
       /* If we emit the last statement then we should put
@@ -4057,6 +4091,13 @@  rewrite_expr_tree_parallel (gassign *stmt, int width,
 	  print_gimple_stmt (dump_file, stmts[i], 0, 0);
 	}
 
+      /* If the stmt that defines operand has to be inserted, insert it
+	 before the use.  */
+      if (stmt1)
+	insert_stmt_before_use (stmts[i], stmt1);
+      if (stmt2)
+	insert_stmt_before_use (stmts[i], stmt2);
+
       /* We keep original statement only for the last one.  All
 	 others are recreated.  */
       if (i == stmt_num - 1)
@@ -5187,7 +5228,7 @@  reassociate_bb (basic_block bb)
 		}
 
 	      if (rhs_code == PLUS_EXPR
-		  && transform_add_to_multiply (stmt, &ops))
+		  && transform_add_to_multiply (&ops))
 		ops.qsort (sort_by_operand_rank);
 
 	      if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR)
@@ -5214,7 +5255,11 @@  reassociate_bb (basic_block bb)
 	      else if (ops.length () == 1)
 		{
 		  tree last_op = ops.last ()->op;
-		  
+
+		  /* If the stmt that defines operand has to be inserted, insert it
+		     before the use.  */
+		  if (ops.last ()->stmt_to_insert)
+		    insert_stmt_before_use (stmt, ops.last ()->stmt_to_insert);
 		  if (powi_result)
 		    transform_stmt_to_multiply (&gsi, stmt, last_op,
 						powi_result);