Commit 081fdda6 by Jeff Law Committed by Jeff Law

tree-ssa-threadbackwards.c (convert_and_register_jump_thread_path): New function, extracted from...

	* tree-ssa-threadbackwards.c (convert_and_register_jump_thread_path):
	New function, extracted from...
	(fsm_find_control_statement_thread_paths): Here.  Use the new function.
	Allow simple copies and constant initializations in the SSA chain.

From-SVN: r236653
parent 72f382fb
2016-05-24 Jeff Law <law@redhat.com>
* tree-ssa-threadbackwards.c (convert_and_register_jump_thread_path):
New function, extracted from...
(fsm_find_control_statement_thread_paths): Here. Use the new function.
Allow simple copies and constant initializations in the SSA chain.
2016-05-24 Marek Polacek <polacek@redhat.com> 2016-05-24 Marek Polacek <polacek@redhat.com>
PR c/71249 PR c/71249
......
...@@ -356,6 +356,44 @@ profitable_jump_thread_path (vec<basic_block, va_gc> *&path, ...@@ -356,6 +356,44 @@ profitable_jump_thread_path (vec<basic_block, va_gc> *&path,
return taken_edge; return taken_edge;
} }
/* PATH is vector of blocks forming a jump threading path in reverse
order. TAKEN_EDGE is the edge taken from path[0].
Convert that path into the form used by register_jump_thread and
register the path. */
static void
convert_and_register_jump_thread_path (vec<basic_block, va_gc> *&path,
edge taken_edge)
{
vec<jump_thread_edge *> *jump_thread_path = new vec<jump_thread_edge *> ();
/* Record the edges between the blocks in PATH. */
for (unsigned int j = 0; j < path->length () - 1; j++)
{
basic_block bb1 = (*path)[path->length () - j - 1];
basic_block bb2 = (*path)[path->length () - j - 2];
if (bb1 == bb2)
continue;
edge e = find_edge (bb1, bb2);
gcc_assert (e);
jump_thread_edge *x = new jump_thread_edge (e, EDGE_FSM_THREAD);
jump_thread_path->safe_push (x);
}
/* Add the edge taken when the control variable has value ARG. */
jump_thread_edge *x
= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
jump_thread_path->safe_push (x);
register_jump_thread (jump_thread_path);
--max_threaded_paths;
/* Remove BBI from the path. */
path->pop ();
}
/* We trace the value of the SSA_NAME NAME back through any phi nodes looking /* We trace the value of the SSA_NAME NAME back through any phi nodes looking
for places where it gets a constant value and save the path. Stop after for places where it gets a constant value and save the path. Stop after
having recorded MAX_PATHS jump threading paths. */ having recorded MAX_PATHS jump threading paths. */
...@@ -377,24 +415,30 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -377,24 +415,30 @@ fsm_find_control_statement_thread_paths (tree name,
if (var_bb == NULL) if (var_bb == NULL)
return; return;
/* For the moment we assume that an SSA chain only contains phi nodes, and /* We allow the SSA chain to contains PHIs and simple copies and constant
eventually one of the phi arguments will be an integer constant. In the initializations. */
future, this could be extended to also handle simple assignments of
arithmetic operations. */
if (gimple_code (def_stmt) != GIMPLE_PHI if (gimple_code (def_stmt) != GIMPLE_PHI
|| (gimple_phi_num_args (def_stmt) && gimple_code (def_stmt) != GIMPLE_ASSIGN)
return;
if (gimple_code (def_stmt) == GIMPLE_PHI
&& (gimple_phi_num_args (def_stmt)
>= (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS))) >= (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS)))
return; return;
if (gimple_code (def_stmt) == GIMPLE_ASSIGN
&& gimple_assign_rhs_code (def_stmt) != INTEGER_CST
&& gimple_assign_rhs_code (def_stmt) != SSA_NAME)
return;
/* Avoid infinite recursion. */ /* Avoid infinite recursion. */
if (visited_bbs->add (var_bb)) if (visited_bbs->add (var_bb))
return; return;
gphi *phi = as_a <gphi *> (def_stmt);
int next_path_length = 0; int next_path_length = 0;
basic_block last_bb_in_path = path->last (); basic_block last_bb_in_path = path->last ();
if (loop_containing_stmt (phi)->header == gimple_bb (phi)) if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt))
{ {
/* Do not walk through more than one loop PHI node. */ /* Do not walk through more than one loop PHI node. */
if (seen_loop_phi) if (seen_loop_phi)
...@@ -469,9 +513,9 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -469,9 +513,9 @@ fsm_find_control_statement_thread_paths (tree name,
/* Iterate over the arguments of PHI. */ /* Iterate over the arguments of PHI. */
unsigned int i; unsigned int i;
if (gimple_phi_num_args (phi) if (gimple_code (def_stmt) == GIMPLE_PHI)
< (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS))
{ {
gphi *phi = as_a <gphi *> (def_stmt);
for (i = 0; i < gimple_phi_num_args (phi); i++) for (i = 0; i < gimple_phi_num_args (phi); i++)
{ {
tree arg = gimple_phi_arg_def (phi, i); tree arg = gimple_phi_arg_def (phi, i);
...@@ -500,32 +544,23 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -500,32 +544,23 @@ fsm_find_control_statement_thread_paths (tree name,
into the canonical form and register it. */ into the canonical form and register it. */
edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg); edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg);
if (taken_edge) if (taken_edge)
{ convert_and_register_jump_thread_path (path, taken_edge);
vec<jump_thread_edge *> *jump_thread_path }
= new vec<jump_thread_edge *> (); }
else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
/* Record the edges between the blocks in PATH. */ {
for (unsigned int j = 0; j < path->length () - 1; j++) tree arg = gimple_assign_rhs1 (def_stmt);
{
edge e = find_edge ((*path)[path->length () - j - 1],
(*path)[path->length () - j - 2]);
gcc_assert (e);
jump_thread_edge *x
= new jump_thread_edge (e, EDGE_FSM_THREAD);
jump_thread_path->safe_push (x);
}
/* Add the edge taken when the control variable has value ARG. */
jump_thread_edge *x
= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
jump_thread_path->safe_push (x);
register_jump_thread (jump_thread_path); if (TREE_CODE (arg) == SSA_NAME)
--max_threaded_paths; fsm_find_control_statement_thread_paths (arg, visited_bbs,
path, seen_loop_phi);
/* Remove BBI from the path. */ else
path->pop (); {
} edge taken_edge = profitable_jump_thread_path (path, var_bb,
name, arg);
if (taken_edge)
convert_and_register_jump_thread_path (path, taken_edge);
} }
} }
......
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