Commit 933f507d by Easwaran Raman

tree-ssa-reassoc.c (find_insert_point): New function.

2013-05-17   Easwaran Raman  <eraman@google.com>

        * tree-ssa-reassoc.c (find_insert_point): New function.
        (insert_stmt_after): Likewise.
        (get_def_stmt): Likewise.
        (ensure_ops_are_available): Likewise.
        (not_dominated_by): Likewise.
        (rewrite_expr_tree): Do not move statements beyond what is
        necessary. Remove call to swap_ops_for_binary_stmt...
        (reassociate_bb): ... and move it here.
        (build_and_add_sum): Assign UIDs for new statements.
        (linearize_expr): Likewise.
        (do_reassoc): Renumber gimple statement UIDs.

testsuite/ChangeLog:

2013-05-17   Easwaran Raman  <eraman@google.com>

        * gcc.dg/tree-ssa/reassoc-28.c: New testcase.

From-SVN: r199048
parent 1f2f6dc2
2013-05-17 Easwaran Raman <eraman@google.com>
* tree-ssa-reassoc.c (find_insert_point): New function.
(insert_stmt_after): Likewise.
(get_def_stmt): Likewise.
(ensure_ops_are_available): Likewise.
(not_dominated_by): Likewise.
(rewrite_expr_tree): Do not move statements beyond what is
necessary. Remove call to swap_ops_for_binary_stmt...
(reassociate_bb): ... and move it here.
(build_and_add_sum): Assign UIDs for new statements.
(linearize_expr): Likewise.
(do_reassoc): Renumber gimple statement UIDs.
2013-05-17 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_symtab_merge_cgraph_nodes): Resolve cross module
......@@ -156,6 +170,7 @@
* Makefile.in (tree-switch-conversion.o): Depend on $(OPTABS_H).
>>>>>>> .r199043
2013-05-16 Uros Bizjak <ubizjak@gmail.com>
* config/i386/driver-i386.c (host_detect_local_cpu): Determine
......
2013-05-17 Easwaran Raman <eraman@google.com>
* gcc.dg/tree-ssa/reassoc-28.c: New testcase.
2013-05-17 Marc Glisse <marc.glisse@inria.fr>
PR testsuite/57313
......
/* { dg-do run} */
/* { dg-options "-O2 -fdump-tree-reassoc1-details" } */
#define LENGTH 4
void abort (void);
unsigned
__attribute__ ((noinline)) foo (unsigned char *buf, int n)
{
unsigned sum = 0, i = 0;
do {
sum +=(buf)[n-1];
/* Split the BB to test statements are correctly moved to
satisfy dependences. */
if (n > LENGTH)
i++;
sum += buf[n-2];
sum += buf[n-3];
sum += buf[n-4];
n = n-4;
} while (n > 0);
return sum + i;
}
unsigned char a[] = {1, 1, 1, 1};
int main() {
int sum = foo (a, LENGTH);
if (sum != 4)
abort ();
return 0;
}
/* Verify one stmt has been moved to another BB to ensure correct dependences. */
/* { dg-final { scan-tree-dump-times "to a different BB" 1 "reassoc1"} }*/
/* { dg-final { scan-tree-dump-times "within same BB" 2 "reassoc1"} }*/
/* { dg-final { cleanup-tree-dump "reassoc1" } } */
......@@ -1166,6 +1166,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
&& (!op2def || gimple_nop_p (op2def)))
{
gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
}
else if ((!op1def || gimple_nop_p (op1def))
......@@ -1175,6 +1176,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
if (gimple_code (op2def) == GIMPLE_PHI)
{
gsi = gsi_after_labels (gimple_bb (op2def));
gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
}
else
......@@ -1182,6 +1184,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
if (!stmt_ends_bb_p (op2def))
{
gsi = gsi_for_stmt (op2def);
gimple_set_uid (sum, gimple_uid (op2def));
gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
}
else
......@@ -1200,6 +1203,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
if (gimple_code (op1def) == GIMPLE_PHI)
{
gsi = gsi_after_labels (gimple_bb (op1def));
gimple_set_uid (sum, gimple_uid (op1def));
gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
}
else
......@@ -1207,6 +1211,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
if (!stmt_ends_bb_p (op1def))
{
gsi = gsi_for_stmt (op1def);
gimple_set_uid (sum, gimple_uid (op1def));
gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
}
else
......@@ -2841,6 +2846,135 @@ swap_ops_for_binary_stmt (vec<operand_entry_t> ops,
}
}
/* Determine if stmt A is not dominated by stmt B. If A and B are in
same basic block, then A's UID has to be less than B. If they are
in different BB's, then A's BB must not be dominated by B's BB. */
static inline bool
not_dominated_by (gimple a, gimple b)
{
basic_block bb_a, bb_b;
bb_a = gimple_bb (a);
bb_b = gimple_bb (b);
return ((bb_a == bb_b && gimple_uid (a) < gimple_uid (b))
|| (bb_a != bb_b
&& !dominated_by_p (CDI_DOMINATORS, bb_a, bb_b)));
}
/* Find the statement after which STMT must be moved so that the
dependency from DEP_STMT to STMT is maintained. */
static gimple
find_insert_point (gimple stmt, gimple dep_stmt)
{
gimple insert_stmt = stmt;
if (dep_stmt == NULL)
return stmt;
if (not_dominated_by (insert_stmt, dep_stmt))
insert_stmt = dep_stmt;
return insert_stmt;
}
/* Insert STMT after INSERT_POINT. */
static void
insert_stmt_after (gimple stmt, gimple insert_point)
{
imm_use_iterator iter;
tree lhs;
gimple use_stmt;
gimple_stmt_iterator gsistmt = gsi_for_stmt (stmt), gsi_insert;
basic_block insert_bb = gimple_bb (insert_point);
bool insert_bb_different = (insert_bb != gimple_bb (stmt));
lhs = gimple_assign_lhs (stmt);
/* If there are any debug uses of LHS, reset them. */
FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
{
if (is_gimple_debug (use_stmt)
&& not_dominated_by (use_stmt, insert_point))
{
gimple_debug_bind_reset_value (use_stmt);
update_stmt (use_stmt);
}
}
/* If INSERT_STMT is a phi node, then do not insert just after that statement.
Instead, find the first non-label gimple statement in BB and insert before
that. */
if (gimple_code (insert_point) == GIMPLE_PHI)
{
gsi_insert = gsi_after_labels (insert_bb);
gsi_move_before (&gsistmt, &gsi_insert);
}
/* Statements marked for throw can not be in the middle of a basic block. So
we can not insert a statement (not marked for throw) immediately after. */
else if (stmt_ends_bb_p (insert_point))
{
edge succ_edge = find_fallthru_edge (insert_bb->succs);
insert_bb = succ_edge->dest;
insert_bb_different = (insert_bb != gimple_bb (stmt));
/* Insert STMT at the beginning of the successor basic block. */
gsi_insert = gsi_after_labels (insert_bb);
gsi_move_before (&gsistmt, &gsi_insert);
}
else
{
gsi_insert = gsi_for_stmt (insert_point);
gsi_move_after (&gsistmt, &gsi_insert);
}
/* Set the UID of STMT to that of INSERT_POINT so that subsequent comparisons
of UIDs to determine dominance within a basic block works. */
gimple_set_uid (stmt, gimple_uid (insert_point));
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Moved stmt ");
print_gimple_stmt (dump_file, stmt, 0, 0);
fprintf (dump_file, " %s to satisfy dependences\n",
insert_bb_different ? "to a different BB" : "within same BB");
}
}
/* If OP is a SSA variable and is not the default definition, return the
gimple statement that defines OP. Else return NULL. */
static inline gimple
get_def_stmt (tree op)
{
if (TREE_CODE (op) == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (op))
return SSA_NAME_DEF_STMT (op);
else
return NULL;
}
/* Ensure that operands in the OPS vector are available for STMT and all
gimple statements on which STMT depends. */
static void
ensure_ops_are_available (gimple stmt, vec<operand_entry_t> ops, int opindex)
{
unsigned int len = ops.length ();
gimple insert_stmt = stmt;
gimple dep_stmts[2];
dep_stmts[0] = get_def_stmt (ops[opindex]->op);
if (len - opindex == 2)
{
dep_stmts[1] = get_def_stmt (ops[opindex + 1]->op);
}
else
{
gimple stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
ensure_ops_are_available (stmt1, ops, opindex + 1);
dep_stmts[1] = stmt1;
}
for (int i = 0; i < 2; i++)
insert_stmt = find_insert_point (insert_stmt, dep_stmts[i]);
if (insert_stmt != stmt)
insert_stmt_after (stmt, insert_stmt);
}
/* Recursively rewrite our linearized statements so that the operators
match those in OPS[OPINDEX], putting the computation in rank
order. */
......@@ -2853,11 +2987,6 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
tree rhs2 = gimple_assign_rhs2 (stmt);
operand_entry_t oe;
/* If we have three operands left, then we want to make sure the ones
that get the double binary op are chosen wisely. */
if (opindex + 3 == ops.length ())
swap_ops_for_binary_stmt (ops, opindex, stmt);
/* The final recursion case for this function is that you have
exactly two operations left.
If we had one exactly one op in the entire list to start with, we
......@@ -2903,20 +3032,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
{
if (!moved)
{
gimple_stmt_iterator gsinow, gsirhs1;
gimple stmt1 = stmt, stmt2;
unsigned int count;
gsinow = gsi_for_stmt (stmt);
count = ops.length () - opindex - 2;
while (count-- != 0)
{
stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
gsirhs1 = gsi_for_stmt (stmt2);
gsi_move_before (&gsirhs1, &gsinow);
gsi_prev (&gsinow);
stmt1 = stmt2;
}
ensure_ops_are_available (stmt, ops, opindex);
moved = true;
}
......@@ -3128,6 +3244,7 @@ linearize_expr (gimple stmt)
gsinow = gsi_for_stmt (stmt);
gsirhs = gsi_for_stmt (binrhs);
gsi_move_before (&gsirhs, &gsinow);
gimple_set_uid (binrhs, gimple_uid (stmt));
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
......@@ -4134,7 +4251,16 @@ reassociate_bb (basic_block bb)
&& ops.length () > 3)
rewrite_expr_tree_parallel (stmt, width, ops);
else
rewrite_expr_tree (stmt, 0, ops, false);
{
/* When there are three operands left, we want
to make sure the ones that get the double
binary op are chosen wisely. */
int len = ops.length ();
if (len >= 3)
swap_ops_for_binary_stmt (ops, len - 3, stmt);
rewrite_expr_tree (stmt, 0, ops, false);
}
/* If we combined some repeated factors into a
__builtin_powi call, multiply that result by the
......@@ -4195,6 +4321,7 @@ static void
do_reassoc (void)
{
break_up_subtract_bb (ENTRY_BLOCK_PTR);
renumber_gimple_stmt_uids ();
reassociate_bb (EXIT_BLOCK_PTR);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment