Commit 435fd407 by Jeff Law Committed by Jeff Law

tree-ssa-threadbackward.c (fsm_find_thread_path): Remove unneeded parameter.

	* tree-ssa-threadbackward.c (fsm_find_thread_path): Remove unneeded
	parameter.  Callers changed.
	(check-subpath_and_update_thread_path): Extracted from
	fsm_find_control_statement_thread_paths.
	(handle_phi, handle_assignment, handle_assignment_p): Likewise.
	(handle_phi, handle_assignment): Allow any constant node, not
	just INTEGER_CST.

From-SVN: r242431
parent 5a0e7889
2016-11-15 Jeff Law <law@redhat.com>
* tree-ssa-threadbackward.c (fsm_find_thread_path): Remove unneeded
parameter. Callers changed.
(check-subpath_and_update_thread_path): Extracted from
fsm_find_control_statement_thread_paths.
(handle_phi, handle_assignment, handle_assignment_p): Likewise.
(handle_phi, handle_assignment): Allow any constant node, not
just INTEGER_CST.
2016-11-15 Claudiu Zissulescu <claziss@synopsys.com> 2016-11-15 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-arch.h: New file. * config/arc/arc-arch.h: New file.
...@@ -62,14 +62,12 @@ get_gimple_control_stmt (basic_block bb) ...@@ -62,14 +62,12 @@ get_gimple_control_stmt (basic_block bb)
/* Return true if the CFG contains at least one path from START_BB to END_BB. /* Return true if the CFG contains at least one path from START_BB to END_BB.
When a path is found, record in PATH the blocks from END_BB to START_BB. When a path is found, record in PATH the blocks from END_BB to START_BB.
VISITED_BBS is used to make sure we don't fall into an infinite loop. Bound VISITED_BBS is used to make sure we don't fall into an infinite loop. Bound
the recursion to basic blocks belonging to LOOP. the recursion to basic blocks belonging to LOOP. */
SPEED_P indicate that we could increase code size to improve the code path */
static bool static bool
fsm_find_thread_path (basic_block start_bb, basic_block end_bb, fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
vec<basic_block, va_gc> *&path, vec<basic_block, va_gc> *&path,
hash_set<basic_block> *visited_bbs, loop_p loop, hash_set<basic_block> *visited_bbs, loop_p loop)
bool speed_p)
{ {
if (loop != start_bb->loop_father) if (loop != start_bb->loop_father)
return false; return false;
...@@ -85,8 +83,7 @@ fsm_find_thread_path (basic_block start_bb, basic_block end_bb, ...@@ -85,8 +83,7 @@ fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
edge e; edge e;
edge_iterator ei; edge_iterator ei;
FOR_EACH_EDGE (e, ei, start_bb->succs) FOR_EACH_EDGE (e, ei, start_bb->succs)
if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop, if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop))
speed_p))
{ {
vec_safe_push (path, start_bb); vec_safe_push (path, start_bb);
return true; return true;
...@@ -427,82 +424,33 @@ convert_and_register_jump_thread_path (vec<basic_block, va_gc> *path, ...@@ -427,82 +424,33 @@ convert_and_register_jump_thread_path (vec<basic_block, va_gc> *path,
--max_threaded_paths; --max_threaded_paths;
} }
/* We trace the value of the SSA_NAME NAME back through any phi nodes looking /* While following a chain of SSA_NAME definitions, we jumped from a definition
for places where it gets a constant value and save the path. Stop after in LAST_BB to a definition in VAR_BB (walking backwards).
having recorded MAX_PATHS jump threading paths.
SPEED_P indicate that we could increase code size to improve the code path */ Verify there is a single path between the blocks and none of the blocks
in the path is already in VISITED_BBS. If so, then update VISISTED_BBS,
add the new blocks to PATH and return TRUE. Otherwise return FALSE.
static void Store the length of the subpath in NEXT_PATH_LENGTH. */
fsm_find_control_statement_thread_paths (tree name,
static bool
check_subpath_and_update_thread_path (basic_block last_bb, basic_block new_bb,
hash_set<basic_block> *visited_bbs, hash_set<basic_block> *visited_bbs,
vec<basic_block, va_gc> *&path, vec<basic_block, va_gc> *&path,
bool seen_loop_phi, bool speed_p) int *next_path_length)
{ {
/* If NAME appears in an abnormal PHI, then don't try to trace its
value back through PHI nodes. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
return;
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
basic_block var_bb = gimple_bb (def_stmt);
if (var_bb == NULL)
return;
/* We allow the SSA chain to contains PHIs and simple copies and constant
initializations. */
if (gimple_code (def_stmt) != GIMPLE_PHI
&& 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)))
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. */
if (visited_bbs->add (var_bb))
return;
int next_path_length = 0;
basic_block last_bb_in_path = path->last ();
if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt))
{
/* Do not walk through more than one loop PHI node. */
if (seen_loop_phi)
return;
seen_loop_phi = true;
}
/* Following the chain of SSA_NAME definitions, we jumped from a definition in
LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are
different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */
if (var_bb != last_bb_in_path)
{
edge e; edge e;
int e_count = 0; int e_count = 0;
edge_iterator ei; edge_iterator ei;
vec<basic_block, va_gc> *next_path; vec<basic_block, va_gc> *next_path;
vec_alloc (next_path, 10); vec_alloc (next_path, 10);
/* When VAR_BB == LAST_BB_IN_PATH, then the first block in the path FOR_EACH_EDGE (e, ei, last_bb->preds)
will already be in VISITED_BBS. When they are not equal, then we
must ensure that first block is accounted for to ensure we do not
create bogus jump threading paths. */
visited_bbs->add ((*path)[0]);
FOR_EACH_EDGE (e, ei, last_bb_in_path->preds)
{ {
hash_set<basic_block> *visited_bbs = new hash_set<basic_block>; hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
if (fsm_find_thread_path (var_bb, e->src, next_path, visited_bbs, if (fsm_find_thread_path (new_bb, e->src, next_path, visited_bbs,
e->src->loop_father, speed_p)) e->src->loop_father))
++e_count; ++e_count;
delete visited_bbs; delete visited_bbs;
...@@ -511,7 +459,7 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -511,7 +459,7 @@ fsm_find_control_statement_thread_paths (tree name,
if (e_count > 1) if (e_count > 1)
{ {
vec_free (next_path); vec_free (next_path);
return; return false;
} }
} }
...@@ -520,7 +468,7 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -520,7 +468,7 @@ fsm_find_control_statement_thread_paths (tree name,
if (e_count == 0) if (e_count == 0)
{ {
vec_free (next_path); vec_free (next_path);
return; return false;
} }
/* Make sure we haven't already visited any of the nodes in /* Make sure we haven't already visited any of the nodes in
...@@ -530,7 +478,7 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -530,7 +478,7 @@ fsm_find_control_statement_thread_paths (tree name,
if (visited_bbs->contains ((*next_path)[i])) if (visited_bbs->contains ((*next_path)[i]))
{ {
vec_free (next_path); vec_free (next_path);
return; return false;
} }
} }
...@@ -540,18 +488,38 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -540,18 +488,38 @@ fsm_find_control_statement_thread_paths (tree name,
/* Append all the nodes from NEXT_PATH to PATH. */ /* Append all the nodes from NEXT_PATH to PATH. */
vec_safe_splice (path, next_path); vec_safe_splice (path, next_path);
next_path_length = next_path->length (); *next_path_length = next_path->length ();
vec_free (next_path); vec_free (next_path);
}
gcc_assert (path->last () == var_bb); return true;
}
static void fsm_find_control_statement_thread_paths (tree,
hash_set<basic_block> *,
vec<basic_block, va_gc> *&,
bool, bool);
/* Given PHI which defines NAME in block VAR_BB, recurse through the
PHI's arguments searching for paths where NAME will ultimately have
a constant value.
VISITED_BBS tracks the blocks that have been encountered.
PATH contains the series of blocks to traverse that will result in
NAME having a constant value.
SEEN_LOOP_PHI tracks if we have recursed through a loop PHI node.
SPEED_P indicates if we are optimizing for speed over space. */
static void
handle_phi (gphi *phi, tree name, basic_block var_bb,
hash_set<basic_block> *visited_bbs,
vec<basic_block, va_gc> *&path,
bool seen_loop_phi, bool speed_p)
{
/* Iterate over the arguments of PHI. */ /* Iterate over the arguments of PHI. */
unsigned int i; for (unsigned int i = 0; i < gimple_phi_num_args (phi); i++)
if (gimple_code (def_stmt) == GIMPLE_PHI)
{
gphi *phi = as_a <gphi *> (def_stmt);
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);
basic_block bbi = gimple_phi_arg_edge (phi, i)->src; basic_block bbi = gimple_phi_arg_edge (phi, i)->src;
...@@ -572,7 +540,7 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -572,7 +540,7 @@ fsm_find_control_statement_thread_paths (tree name,
continue; continue;
} }
if (TREE_CODE (arg) != INTEGER_CST) if (TREE_CODE_CLASS (TREE_CODE (arg)) != tcc_constant)
continue; continue;
/* If this is a profitable jump thread path, then convert it /* If this is a profitable jump thread path, then convert it
...@@ -589,10 +557,58 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -589,10 +557,58 @@ fsm_find_control_statement_thread_paths (tree name,
vect_free_loop_info_assumptions ((*path)[0]->loop_father); vect_free_loop_info_assumptions ((*path)[0]->loop_father);
} }
} }
} }
else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
/* Return TRUE if STMT is a gimple assignment we want to either directly
handle or recurse through. Return FALSE otherwise.
Note that adding more cases here requires adding cases to handle_assignment
below. */
static bool
handle_assignment_p (gimple *stmt)
{
if (is_gimple_assign (stmt))
{ {
tree arg = gimple_assign_rhs1 (def_stmt); enum tree_code def_code = gimple_assign_rhs_code (stmt);
/* If the RHS is an SSA_NAME, then we will recurse through it.
Go ahead and filter out cases where the SSA_NAME is a default
definition. There's little to be gained by trying to handle that. */
if (def_code == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (gimple_assign_rhs1 (stmt)))
return true;
/* If the RHS is a constant, then it's a terminal that we'll want
to handle as well. */
if (TREE_CODE_CLASS (def_code) == tcc_constant)
return true;
}
/* Anything not explicitly allowed is not handled. */
return false;
}
/* Given STMT which defines NAME in block VAR_BB, recurse through the
PHI's arguments searching for paths where NAME will ultimately have
a constant value.
VISITED_BBS tracks the blocks that have been encountered.
PATH contains the series of blocks to traverse that will result in
NAME having a constant value.
SEEN_LOOP_PHI tracks if we have recursed through a loop PHI node.
SPEED_P indicates if we are optimizing for speed over space. */
static void
handle_assignment (gimple *stmt, tree name, basic_block var_bb,
hash_set<basic_block> *visited_bbs,
vec<basic_block, va_gc> *&path,
bool seen_loop_phi, bool speed_p)
{
tree arg = gimple_assign_rhs1 (stmt);
if (TREE_CODE (arg) == SSA_NAME) if (TREE_CODE (arg) == SSA_NAME)
fsm_find_control_statement_thread_paths (arg, visited_bbs, fsm_find_control_statement_thread_paths (arg, visited_bbs,
...@@ -622,8 +638,86 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -622,8 +638,86 @@ fsm_find_control_statement_thread_paths (tree name,
state of the stack is unchanged when we leave. */ state of the stack is unchanged when we leave. */
vec_safe_push (path, var_bb); vec_safe_push (path, var_bb);
} }
}
/* 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
having recorded MAX_PATHS jump threading paths.
SPEED_P indicate that we could increase code size to improve the code path */
static void
fsm_find_control_statement_thread_paths (tree name,
hash_set<basic_block> *visited_bbs,
vec<basic_block, va_gc> *&path,
bool seen_loop_phi, bool speed_p)
{
/* If NAME appears in an abnormal PHI, then don't try to trace its
value back through PHI nodes. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
return;
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
basic_block var_bb = gimple_bb (def_stmt);
if (var_bb == NULL)
return;
/* We allow the SSA chain to contains PHIs and simple copies and constant
initializations. */
if (gimple_code (def_stmt) != GIMPLE_PHI
&& 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)))
return;
if (is_gimple_assign (def_stmt)
&& ! handle_assignment_p (def_stmt))
return;
/* Avoid infinite recursion. */
if (visited_bbs->add (var_bb))
return;
int next_path_length = 0;
basic_block last_bb_in_path = path->last ();
if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt))
{
/* Do not walk through more than one loop PHI node. */
if (seen_loop_phi)
return;
seen_loop_phi = true;
}
/* Following the chain of SSA_NAME definitions, we jumped from a definition in
LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are
different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */
if (var_bb != last_bb_in_path)
{
/* When VAR_BB == LAST_BB_IN_PATH, then the first block in the path
will already be in VISITED_BBS. When they are not equal, then we
must ensure that first block is accounted for to ensure we do not
create bogus jump threading paths. */
visited_bbs->add ((*path)[0]);
if (!check_subpath_and_update_thread_path (last_bb_in_path, var_bb,
visited_bbs, path,
&next_path_length))
return;
} }
gcc_assert (path->last () == var_bb);
if (gimple_code (def_stmt) == GIMPLE_PHI)
handle_phi (as_a <gphi *> (def_stmt), name, var_bb,
visited_bbs, path, seen_loop_phi, speed_p);
else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
handle_assignment (def_stmt, name, var_bb,
visited_bbs, path, seen_loop_phi, speed_p);
/* Remove all the nodes that we added from NEXT_PATH. */ /* Remove all the nodes that we added from NEXT_PATH. */
if (next_path_length) if (next_path_length)
vec_safe_truncate (path, (path->length () - next_path_length)); vec_safe_truncate (path, (path->length () - next_path_length));
...@@ -652,7 +746,7 @@ find_jump_threads_backwards (basic_block bb, bool speed_p) ...@@ -652,7 +746,7 @@ find_jump_threads_backwards (basic_block bb, bool speed_p)
else if (code == GIMPLE_COND) else if (code == GIMPLE_COND)
{ {
if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
&& TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST && TREE_CODE_CLASS (TREE_CODE (gimple_cond_rhs (stmt))) == tcc_constant
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))) && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
|| POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))))) || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
name = gimple_cond_lhs (stmt); name = gimple_cond_lhs (stmt);
......
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