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
This commit is contained in:
parent
f0bb873672
commit
acce8ce3bf
|
@ -1,3 +1,11 @@
|
|||
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>
|
||||
|
||||
* ipa-prop.c (get_place_in_agg_contents_list): New function.
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* gcc.dg/tree-ssa/pr42585.c: Skip for AArch64.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* { 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)
|
|||
used in, so that you only have one place you can sink it to. */
|
||||
|
||||
static bool
|
||||
all_immediate_uses_same_place (gimple stmt)
|
||||
all_immediate_uses_same_place (def_operand_p def_p)
|
||||
{
|
||||
gimple firstuse = NULL;
|
||||
ssa_op_iter op_iter;
|
||||
tree var = DEF_FROM_PTR (def_p);
|
||||
imm_use_iterator imm_iter;
|
||||
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 (firstuse == NULL)
|
||||
firstuse = USE_STMT (use_p);
|
||||
else
|
||||
if (firstuse != USE_STMT (use_p))
|
||||
return false;
|
||||
}
|
||||
if (is_gimple_debug (USE_STMT (use_p)))
|
||||
continue;
|
||||
if (firstuse == NULL)
|
||||
firstuse = USE_STMT (use_p);
|
||||
else
|
||||
if (firstuse != USE_STMT (use_p))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -138,49 +134,44 @@ all_immediate_uses_same_place (gimple stmt)
|
|||
/* Find the nearest common dominator of all of the immediate uses in IMM. */
|
||||
|
||||
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);
|
||||
basic_block commondom;
|
||||
unsigned int j;
|
||||
bitmap_iterator bi;
|
||||
ssa_op_iter op_iter;
|
||||
imm_use_iterator imm_iter;
|
||||
use_operand_p use_p;
|
||||
tree var;
|
||||
|
||||
bitmap_clear (blocks);
|
||||
FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
|
||||
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int idx = PHI_ARG_INDEX_FROM_USE (use_p);
|
||||
if (gimple_code (usestmt) == GIMPLE_PHI)
|
||||
{
|
||||
int idx = PHI_ARG_INDEX_FROM_USE (use_p);
|
||||
|
||||
useblock = gimple_phi_arg_edge (usestmt, idx)->src;
|
||||
}
|
||||
else if (is_gimple_debug (usestmt))
|
||||
{
|
||||
*debug_stmts = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
useblock = gimple_bb (usestmt);
|
||||
}
|
||||
|
||||
/* Short circuit. Nothing dominates the entry block. */
|
||||
if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun))
|
||||
{
|
||||
BITMAP_FREE (blocks);
|
||||
return NULL;
|
||||
}
|
||||
bitmap_set_bit (blocks, useblock->index);
|
||||
useblock = gimple_phi_arg_edge (usestmt, idx)->src;
|
||||
}
|
||||
else if (is_gimple_debug (usestmt))
|
||||
{
|
||||
*debug_stmts = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
useblock = gimple_bb (usestmt);
|
||||
}
|
||||
|
||||
/* Short circuit. Nothing dominates the entry block. */
|
||||
if (useblock == ENTRY_BLOCK_PTR_FOR_FN (cfun))
|
||||
{
|
||||
BITMAP_FREE (blocks);
|
||||
return NULL;
|
||||
}
|
||||
bitmap_set_bit (blocks, useblock->index);
|
||||
}
|
||||
commondom = BASIC_BLOCK_FOR_FN (cfun, bitmap_first_set_bit (blocks));
|
||||
EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi)
|
||||
|
@ -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
|
||||
moved to.
|
||||
|
||||
We don't want to sink loads from memory.
|
||||
|
||||
We can't sink statements that end basic blocks without splitting the
|
||||
incoming edge for the sink location to place it there.
|
||||
|
||||
|
@ -313,7 +302,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
|
|||
if (stmt_ends_bb_p (stmt)
|
||||
|| gimple_has_side_effects (stmt)
|
||||
|| gimple_has_volatile_ops (stmt)
|
||||
|| (gimple_vuse (stmt) && !gimple_vdef (stmt))
|
||||
|| (cfun->has_local_explicit_reg_vars
|
||||
&& TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode))
|
||||
return false;
|
||||
|
@ -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
|
||||
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))
|
||||
{
|
||||
|
@ -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
|
||||
find the nearest common dominator of all of the predecessor blocks, since
|
||||
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;
|
||||
basic_block commondom = nearest_common_dominator_of_uses (stmt,
|
||||
basic_block commondom = nearest_common_dominator_of_uses (def_p,
|
||||
&debug_stmts);
|
||||
|
||||
if (commondom == frombb)
|
||||
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
|
||||
trivially safe place to put this statement, since it has multiple
|
||||
uses. */
|
||||
|
|
Loading…
Reference in New Issue