mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
1f2f6dc2bc
commit
933f507d1f
|
|
@ -1,3 +1,17 @@
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/* { 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue