Reimplement rewrite_virtuals_into_loop_closed_ssa

2015-08-31  Tom de Vries  <tom@codesourcery.com>

	* tree-ssa-loop-manip.c (find_uses_to_rename_stmt)
	(find_uses_to_rename_bb, find_uses_to_rename): Add and handle use_flags
	parameter.
	(find_uses_to_rename_def, find_uses_to_rename_in_loop): New function.
	(rewrite_into_loop_closed_ssa_1): New function, factored out of ...
	(rewrite_into_loop_closed_ssa): ... here.
	(replace_uses_in_dominated_bbs): Remove function.
	(rewrite_virtuals_into_loop_closed_ssa): Reimplement using
	rewrite_into_loop_closed_ssa_1.

From-SVN: r227342
This commit is contained in:
Tom de Vries 2015-08-31 13:48:29 +00:00 committed by Tom de Vries
parent e5f95b665b
commit eaef98f3af
2 changed files with 172 additions and 66 deletions

View File

@ -1,3 +1,15 @@
2015-08-31 Tom de Vries <tom@codesourcery.com>
* tree-ssa-loop-manip.c (find_uses_to_rename_stmt)
(find_uses_to_rename_bb, find_uses_to_rename): Add and handle use_flags
parameter.
(find_uses_to_rename_def, find_uses_to_rename_in_loop): New function.
(rewrite_into_loop_closed_ssa_1): New function, factored out of ...
(rewrite_into_loop_closed_ssa): ... here.
(replace_uses_in_dominated_bbs): Remove function.
(rewrite_virtuals_into_loop_closed_ssa): Reimplement using
rewrite_into_loop_closed_ssa_1.
2015-08-31 Michael Matz <matz@suse.de>
* cfganal.c (pre_and_rev_post_order_compute_fn): Correctly

View File

@ -403,12 +403,13 @@ find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks,
bitmap_set_bit (use_blocks[ver], bb->index);
}
/* For uses in STMT, mark names that are used outside of the loop they are
defined to rewrite. Record the set of blocks in which the ssa names are used
to USE_BLOCKS and the ssa names themselves to NEED_PHIS. */
/* For uses matching USE_FLAGS in STMT, mark names that are used outside of the
loop they are defined to rewrite. Record the set of blocks in which the ssa
names are used to USE_BLOCKS, and the ssa names themselves to NEED_PHIS. */
static void
find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis)
find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis,
int use_flags)
{
ssa_op_iter iter;
tree var;
@ -417,42 +418,59 @@ find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis)
if (is_gimple_debug (stmt))
return;
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
find_uses_to_rename_use (bb, var, use_blocks, need_phis);
/* FOR_EACH_SSA_TREE_OPERAND iterator does not allows SSA_OP_VIRTUAL_USES
only. */
if (use_flags == SSA_OP_VIRTUAL_USES)
{
tree vuse = gimple_vuse (stmt);
if (vuse != NULL_TREE)
find_uses_to_rename_use (bb, gimple_vuse (stmt), use_blocks, need_phis);
}
else
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, use_flags)
find_uses_to_rename_use (bb, var, use_blocks, need_phis);
}
/* Marks names that are used in BB and outside of the loop they are defined in
for rewrite. Records the set of blocks in which the ssa names are used to
USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */
/* Marks names matching USE_FLAGS that are used in BB and outside of the loop
they are defined in for rewrite. Records the set of blocks in which the ssa
names are used to USE_BLOCKS. Record the SSA names that will
need exit PHIs in NEED_PHIS. */
static void
find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks, bitmap need_phis)
find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks, bitmap need_phis,
int use_flags)
{
edge e;
edge_iterator ei;
bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0;
bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0;
FOR_EACH_EDGE (e, ei, bb->succs)
for (gphi_iterator bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi);
gsi_next (&bsi))
{
gphi *phi = bsi.phi ();
if (! virtual_operand_p (gimple_phi_result (phi)))
bool virtual_p = virtual_operand_p (gimple_phi_result (phi));
if ((virtual_p && do_virtuals)
|| (!virtual_p && do_nonvirtuals))
find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (phi, e),
use_blocks, need_phis);
}
for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
gsi_next (&bsi))
find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis);
find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis,
use_flags);
}
/* Marks names that are used outside of the loop they are defined in for
rewrite. Records the set of blocks in which the ssa names are used to
USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. If
CHANGED_BBS is not NULL, scan only blocks in this set. */
/* Marks names matching USE_FLAGS that are used outside of the loop they are
defined in for rewrite. Records the set of blocks in which the ssa names are
used to USE_BLOCKS. Record the SSA names that will need exit PHIs in
NEED_PHIS. If CHANGED_BBS is not NULL, scan only blocks in this set. */
static void
find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis)
find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis,
int use_flags)
{
basic_block bb;
unsigned index;
@ -460,10 +478,96 @@ find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis)
if (changed_bbs)
EXECUTE_IF_SET_IN_BITMAP (changed_bbs, 0, index, bi)
find_uses_to_rename_bb (BASIC_BLOCK_FOR_FN (cfun, index), use_blocks, need_phis);
find_uses_to_rename_bb (BASIC_BLOCK_FOR_FN (cfun, index), use_blocks,
need_phis, use_flags);
else
FOR_EACH_BB_FN (bb, cfun)
find_uses_to_rename_bb (bb, use_blocks, need_phis);
find_uses_to_rename_bb (bb, use_blocks, need_phis, use_flags);
}
/* Mark uses of DEF that are used outside of the loop they are defined in for
rewrite. Record the set of blocks in which the ssa names are used to
USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */
static void
find_uses_to_rename_def (tree def, bitmap *use_blocks, bitmap need_phis)
{
gimple use_stmt;
imm_use_iterator imm_iter;
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def)
{
basic_block use_bb = gimple_bb (use_stmt);
use_operand_p use_p;
FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
{
if (gimple_code (use_stmt) == GIMPLE_PHI)
{
edge e = gimple_phi_arg_edge (as_a <gphi *> (use_stmt),
PHI_ARG_INDEX_FROM_USE (use_p));
use_bb = e->src;
}
find_uses_to_rename_use (use_bb, USE_FROM_PTR (use_p), use_blocks,
need_phis);
}
}
}
/* Marks names matching USE_FLAGS that are defined in LOOP and used outside of
it for rewrite. Records the set of blocks in which the ssa names are used to
USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */
static void
find_uses_to_rename_in_loop (struct loop *loop, bitmap *use_blocks,
bitmap need_phis, int use_flags)
{
bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0;
bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0;
int def_flags = ((do_virtuals ? SSA_OP_VIRTUAL_DEFS : 0)
| (do_nonvirtuals ? SSA_OP_DEF : 0));
basic_block *bbs = get_loop_body (loop);
for (unsigned int i = 0; i < loop->num_nodes; i++)
{
basic_block bb = bbs[i];
for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);
gsi_next (&bsi))
{
gphi *phi = bsi.phi ();
tree res = gimple_phi_result (phi);
bool virtual_p = virtual_operand_p (res);
if ((virtual_p && do_virtuals)
|| (!virtual_p && do_nonvirtuals))
find_uses_to_rename_def (res, use_blocks, need_phis);
}
for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
gsi_next (&bsi))
{
gimple stmt = gsi_stmt (bsi);
/* FOR_EACH_SSA_TREE_OPERAND iterator does not allows
SSA_OP_VIRTUAL_DEFS only. */
if (def_flags == SSA_OP_VIRTUAL_DEFS)
{
tree vdef = gimple_vdef (stmt);
if (vdef != NULL)
find_uses_to_rename_def (vdef, use_blocks, need_phis);
}
else
{
tree var;
ssa_op_iter iter;
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, def_flags)
find_uses_to_rename_def (var, use_blocks, need_phis);
}
}
}
XDELETEVEC (bbs);
}
/* Rewrites the program into a loop closed ssa form -- i.e. inserts extra
@ -495,14 +599,19 @@ find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis)
is not well-behaved, while the second one is an induction variable with
base 99 and step 1.
If CHANGED_BBS is not NULL, we look for uses outside loops only in
the basic blocks in this set.
If LOOP is non-null, only rewrite uses that have defs in LOOP. Otherwise,
if CHANGED_BBS is not NULL, we look for uses outside loops only in the
basic blocks in this set.
USE_FLAGS allows us to specify whether we want virtual, non-virtual or
both variables rewritten.
UPDATE_FLAG is used in the call to update_ssa. See
TODO_update_ssa* for documentation. */
void
rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
rewrite_into_loop_closed_ssa_1 (bitmap changed_bbs, unsigned update_flag,
int use_flags, struct loop *loop)
{
bitmap *use_blocks;
bitmap names_to_rename;
@ -513,7 +622,14 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
/* If the pass has caused the SSA form to be out-of-date, update it
now. */
update_ssa (update_flag);
if (update_flag == 0)
{
#ifdef ENABLE_CHECKING
verify_ssa (true, true);
#endif
}
else
update_ssa (update_flag);
bitmap_obstack_initialize (&loop_renamer_obstack);
@ -524,8 +640,17 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
in NAMES_TO_RENAME. */
use_blocks = XNEWVEC (bitmap, num_ssa_names);
/* Find the uses outside loops. */
find_uses_to_rename (changed_bbs, use_blocks, names_to_rename);
if (loop != NULL)
{
gcc_assert (changed_bbs == NULL);
find_uses_to_rename_in_loop (loop, use_blocks, names_to_rename,
use_flags);
}
else
{
gcc_assert (loop == NULL);
find_uses_to_rename (changed_bbs, use_blocks, names_to_rename, use_flags);
}
if (!bitmap_empty_p (names_to_rename))
{
@ -549,55 +674,24 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
free (use_blocks);
}
/* Replace uses of OLD_VAL with NEW_VAL in bbs dominated by BB. */
/* Rewrites the non-virtual defs and uses into a loop closed ssa form. If
CHANGED_BBS is not NULL, we look for uses outside loops only in the basic
blocks in this set. UPDATE_FLAG is used in the call to update_ssa. See
TODO_update_ssa* for documentation. */
static void
replace_uses_in_dominated_bbs (tree old_val, tree new_val, basic_block bb)
void
rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag)
{
gimple use_stmt;
imm_use_iterator imm_iter;
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, old_val)
{
if (!dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
continue;
use_operand_p use_p;
FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
SET_USE (use_p, new_val);
}
rewrite_into_loop_closed_ssa_1 (changed_bbs, update_flag, SSA_OP_USE, NULL);
}
/* Ensure a virtual phi is present in the exit block, if LOOP contains a vdef.
In other words, ensure loop-closed ssa normal form for virtuals. Handles
only loops with a single exit that dominates the latch. */
/* Rewrites virtual defs and uses with def in LOOP into loop closed ssa
form. */
void
rewrite_virtuals_into_loop_closed_ssa (struct loop *loop)
{
gphi *phi;
/* TODO: Handle !single_dom_exit loops. */
edge exit = single_dom_exit (loop);
gcc_assert (exit != NULL);
phi = get_virtual_phi (loop->header);
if (phi == NULL)
return;
tree final_loop = PHI_ARG_DEF_FROM_EDGE (phi, single_succ_edge (loop->latch));
phi = get_virtual_phi (exit->dest);
if (phi != NULL)
{
tree final_exit = PHI_ARG_DEF_FROM_EDGE (phi, exit);
gcc_assert (operand_equal_p (final_loop, final_exit, 0));
return;
}
tree res_new = copy_ssa_name (final_loop, NULL);
gphi *nphi = create_phi_node (res_new, exit->dest);
replace_uses_in_dominated_bbs (final_loop, res_new, exit->dest);
add_phi_arg (nphi, final_loop, exit, UNKNOWN_LOCATION);
rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_VIRTUAL_USES, loop);
}
/* Check invariants of the loop closed ssa form for the USE in BB. */