Commit acce8ce3 by Richard Biener Committed by Richard Biener

re PR tree-optimization/59299 (We do not sink loads)

2014-06-06  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/59299
	* tree-ssa-sink.c (all_immediate_uses_same_place): Work on
	a def operand.
	(nearest_common_dominator_of_uses): Likewise.
	(statement_sink_location): Adjust.  Support sinking loads.

	* gcc.dg/tree-ssa/ssa-sink-10.c: New testcase.

From-SVN: r211317
parent f0bb8736
2014-06-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/59299
* tree-ssa-sink.c (all_immediate_uses_same_place): Work on
a def operand.
(nearest_common_dominator_of_uses): Likewise.
(statement_sink_location): Adjust. Support sinking loads.
2014-06-06 Martin Jambor <mjambor@suse.cz> 2014-06-06 Martin Jambor <mjambor@suse.cz>
* ipa-prop.c (get_place_in_agg_contents_list): New function. * ipa-prop.c (get_place_in_agg_contents_list): New function.
......
2014-06-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/59299
* gcc.dg/tree-ssa/ssa-sink-10.c: New testcase.
2014-06-06 James Greenhalgh <james.greenhalgh@arm.com> 2014-06-06 James Greenhalgh <james.greenhalgh@arm.com>
* gcc.dg/tree-ssa/pr42585.c: Skip for AArch64. * gcc.dg/tree-ssa/pr42585.c: Skip for AArch64.
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-sink-details" } */
int x[1024], y[1024], z[1024], w[1024];
void foo (void)
{
int i;
for (i = 1; i < 1024; ++i)
{
int a = x[i];
int b = y[i];
int c = x[i-1];
int d = y[i-1];
if (w[i])
z[i] = (a + b) + (c + d);
}
}
/* { dg-final { scan-tree-dump-times "Sinking # VUSE" 4 "sink" } } */
/* { dg-final { cleanup-tree-dump "sink" } } */
...@@ -110,26 +110,22 @@ find_bb_for_arg (gimple phi, tree def) ...@@ -110,26 +110,22 @@ find_bb_for_arg (gimple phi, tree def)
used in, so that you only have one place you can sink it to. */ used in, so that you only have one place you can sink it to. */
static bool static bool
all_immediate_uses_same_place (gimple stmt) all_immediate_uses_same_place (def_operand_p def_p)
{ {
gimple firstuse = NULL; tree var = DEF_FROM_PTR (def_p);
ssa_op_iter op_iter;
imm_use_iterator imm_iter; imm_use_iterator imm_iter;
use_operand_p use_p; use_operand_p use_p;
tree var;
FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS) gimple firstuse = NULL;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
{ {
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var) if (is_gimple_debug (USE_STMT (use_p)))
{ continue;
if (is_gimple_debug (USE_STMT (use_p))) if (firstuse == NULL)
continue; firstuse = USE_STMT (use_p);
if (firstuse == NULL) else
firstuse = USE_STMT (use_p); if (firstuse != USE_STMT (use_p))
else return false;
if (firstuse != USE_STMT (use_p))
return false;
}
} }
return true; return true;
...@@ -138,49 +134,44 @@ all_immediate_uses_same_place (gimple stmt) ...@@ -138,49 +134,44 @@ all_immediate_uses_same_place (gimple stmt)
/* Find the nearest common dominator of all of the immediate uses in IMM. */ /* Find the nearest common dominator of all of the immediate uses in IMM. */
static basic_block static basic_block
nearest_common_dominator_of_uses (gimple stmt, bool *debug_stmts) nearest_common_dominator_of_uses (def_operand_p def_p, bool *debug_stmts)
{ {
tree var = DEF_FROM_PTR (def_p);
bitmap blocks = BITMAP_ALLOC (NULL); bitmap blocks = BITMAP_ALLOC (NULL);
basic_block commondom; basic_block commondom;
unsigned int j; unsigned int j;
bitmap_iterator bi; bitmap_iterator bi;
ssa_op_iter op_iter;
imm_use_iterator imm_iter; imm_use_iterator imm_iter;
use_operand_p use_p; use_operand_p use_p;
tree var;
bitmap_clear (blocks); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
{ {
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var) gimple usestmt = USE_STMT (use_p);
{ basic_block useblock;
gimple usestmt = USE_STMT (use_p);
basic_block useblock;
if (gimple_code (usestmt) == GIMPLE_PHI) if (gimple_code (usestmt) == GIMPLE_PHI)
{ {
int idx = PHI_ARG_INDEX_FROM_USE (use_p); int idx = PHI_ARG_INDEX_FROM_USE (use_p);
useblock = gimple_phi_arg_edge (usestmt, idx)->src; useblock = gimple_phi_arg_edge (usestmt, idx)->src;
} }
else if (is_gimple_debug (usestmt)) else if (is_gimple_debug (usestmt))
{ {
*debug_stmts = true; *debug_stmts = true;
continue; continue;
} }
else else
{ {
useblock = gimple_bb (usestmt); useblock = gimple_bb (usestmt);
} }
/* Short circuit. Nothing dominates the entry block. */ /* Short circuit. Nothing dominates the entry block. */
if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun)) if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun))
{ {
BITMAP_FREE (blocks); BITMAP_FREE (blocks);
return NULL; return NULL;
}
bitmap_set_bit (blocks, useblock->index);
} }
bitmap_set_bit (blocks, useblock->index);
} }
commondom = BASIC_BLOCK_FOR_FN (cfun, bitmap_first_set_bit (blocks)); commondom = BASIC_BLOCK_FOR_FN (cfun, bitmap_first_set_bit (blocks));
EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi) EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi)
...@@ -294,8 +285,6 @@ statement_sink_location (gimple stmt, basic_block frombb, ...@@ -294,8 +285,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
be seen by an external routine that needs it depending on where it gets be seen by an external routine that needs it depending on where it gets
moved to. moved to.
We don't want to sink loads from memory.
We can't sink statements that end basic blocks without splitting the We can't sink statements that end basic blocks without splitting the
incoming edge for the sink location to place it there. incoming edge for the sink location to place it there.
...@@ -313,7 +302,6 @@ statement_sink_location (gimple stmt, basic_block frombb, ...@@ -313,7 +302,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
if (stmt_ends_bb_p (stmt) if (stmt_ends_bb_p (stmt)
|| gimple_has_side_effects (stmt) || gimple_has_side_effects (stmt)
|| gimple_has_volatile_ops (stmt) || gimple_has_volatile_ops (stmt)
|| (gimple_vuse (stmt) && !gimple_vdef (stmt))
|| (cfun->has_local_explicit_reg_vars || (cfun->has_local_explicit_reg_vars
&& TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)) && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode))
return false; return false;
...@@ -332,7 +320,7 @@ statement_sink_location (gimple stmt, basic_block frombb, ...@@ -332,7 +320,7 @@ statement_sink_location (gimple stmt, basic_block frombb,
/* If stmt is a store the one and only use needs to be the VOP /* If stmt is a store the one and only use needs to be the VOP
merging PHI node. */ merging PHI node. */
if (gimple_vdef (stmt)) if (virtual_operand_p (DEF_FROM_PTR (def_p)))
{ {
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p)) FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
{ {
...@@ -369,15 +357,50 @@ statement_sink_location (gimple stmt, basic_block frombb, ...@@ -369,15 +357,50 @@ statement_sink_location (gimple stmt, basic_block frombb,
common dominator of all the immediate uses. For PHI nodes, we have to common dominator of all the immediate uses. For PHI nodes, we have to
find the nearest common dominator of all of the predecessor blocks, since find the nearest common dominator of all of the predecessor blocks, since
that is where insertion would have to take place. */ that is where insertion would have to take place. */
else if (!all_immediate_uses_same_place (stmt)) else if (gimple_vuse (stmt)
|| !all_immediate_uses_same_place (def_p))
{ {
bool debug_stmts = false; bool debug_stmts = false;
basic_block commondom = nearest_common_dominator_of_uses (stmt, basic_block commondom = nearest_common_dominator_of_uses (def_p,
&debug_stmts); &debug_stmts);
if (commondom == frombb) if (commondom == frombb)
return false; return false;
/* If this is a load then do not sink past any stores.
??? This is overly simple but cheap. We basically look
for an existing load with the same VUSE in the path to one
of the sink candidate blocks and we adjust commondom to the
nearest to commondom. */
if (gimple_vuse (stmt))
{
imm_use_iterator imm_iter;
use_operand_p use_p;
basic_block found = NULL;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vuse (stmt))
{
gimple use_stmt = USE_STMT (use_p);
basic_block bb = gimple_bb (use_stmt);
/* For PHI nodes the block we know sth about
is the incoming block with the use. */
if (gimple_code (use_stmt) == GIMPLE_PHI)
bb = EDGE_PRED (bb, PHI_ARG_INDEX_FROM_USE (use_p))->src;
/* Any dominator of commondom would be ok with
adjusting commondom to that block. */
bb = nearest_common_dominator (CDI_DOMINATORS, bb, commondom);
if (!found)
found = bb;
else if (dominated_by_p (CDI_DOMINATORS, bb, found))
found = bb;
/* If we can't improve, stop. */
if (found == commondom)
break;
}
commondom = found;
if (commondom == frombb)
return false;
}
/* Our common dominator has to be dominated by frombb in order to be a /* Our common dominator has to be dominated by frombb in order to be a
trivially safe place to put this statement, since it has multiple trivially safe place to put this statement, since it has multiple
uses. */ uses. */
......
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