On 20 May 2016 at 21:07, Richard Biener <richard.guent...@gmail.com> wrote: > On Fri, May 20, 2016 at 1:51 AM, Kugan Vivekanandarajah > <kugan.vivekanandara...@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 <kug...@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 --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);