Commit 21f0717a by Jeff Law Committed by Jeff Law

[PATCH][PR tree-optimization/67892] Use FSM threader to handle backedges

	PR tree-optimization/67892
	* tree-ssa-threadedge.c (simplify_controL_stmt_condition): Fix typo
	in comment.
	(thread_through_normal_block): If we have seen a backedge, then
	do nothing.  No longer call find_jump_threads_backwards here.
	(thread_across_edge): Use find_jump_threads_backwards to find
	jump threads if the old style threader was not successful.
	* tree-ssa-threadbackward.c (get_gimple_control_stmt): Use
	gsi_last_nondebug_bb.  Return NULL if the block does not end
	with a control statement.
	(find_jump_threads_backwards): Setup code moved here from
	tree-ssa-threadedge.c::thread_through_normal_block.  Accept
	single edge argument instead of name & block.
	* tree-ssa-threadbackward.h (find_jump_threads_backwards): Update
	prototype.

        PR tree-optimization/67892
	* gcc.dg/tree-ssa/pr21417: Update expected output.
	* gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Likewise.

From-SVN: r229538
parent 3ddb720e
2015-10-29 Jeff Law <law@redhat.com>
PR tree-optimization/67892
* tree-ssa-threadedge.c (simplify_controL_stmt_condition): Fix typo
in comment.
(thread_through_normal_block): If we have seen a backedge, then
do nothing. No longer call find_jump_threads_backwards here.
(thread_across_edge): Use find_jump_threads_backwards to find
jump threads if the old style threader was not successful.
* tree-ssa-threadbackward.c (get_gimple_control_stmt): Use
gsi_last_nondebug_bb. Return NULL if the block does not end
with a control statement.
(find_jump_threads_backwards): Setup code moved here from
tree-ssa-threadedge.c::thread_through_normal_block. Accept
single edge argument instead of name & block.
* tree-ssa-threadbackward.h (find_jump_threads_backwards): Update
prototype.
2015-10-29 Tom de Vries <tom@codesourcery.com> 2015-10-29 Tom de Vries <tom@codesourcery.com>
* fold-const.c (fold_unary_loc): Remove folding inhibition for restrict * fold-const.c (fold_unary_loc): Remove folding inhibition for restrict
2015-10-29 Jeff Law <law@redhat.com>
PR tree-optimization/67892
* gcc.dg/tree-ssa/pr21417: Update expected output.
* gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Likewise.
2015-10-29 Richard Biener <rguenther@suse.de> 2015-10-29 Richard Biener <rguenther@suse.de>
PR middle-end/68142 PR middle-end/68142
......
...@@ -49,5 +49,5 @@ L23: ...@@ -49,5 +49,5 @@ L23:
/* We should thread the backedge to the top of the loop; ie we only /* We should thread the backedge to the top of the loop; ie we only
execute the if (expr->common.code != 142) test once per loop execute the if (expr->common.code != 142) test once per loop
iteration. */ iteration. */
/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "dom2" } } */ /* { dg-final { scan-tree-dump-times "FSM jump thread" 1 "dom2" } } */
...@@ -25,6 +25,5 @@ void thread_latch_through_header (void) ...@@ -25,6 +25,5 @@ void thread_latch_through_header (void)
/* Threading the latch to a later point in the loop is safe in this /* Threading the latch to a later point in the loop is safe in this
case. And we want to thread through the header as well. These case. And we want to thread through the header as well. These
are both caught by threading in DOM. */ are both caught by threading in DOM. */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp1"} } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom1"} } */
/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 0 "dom1"} } */ /* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "vrp1"} } */
/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "dom1"} } */
...@@ -37,19 +37,22 @@ along with GCC; see the file COPYING3. If not see ...@@ -37,19 +37,22 @@ along with GCC; see the file COPYING3. If not see
static int max_threaded_paths; static int max_threaded_paths;
/* Simple helper to get the last statement from BB, which is assumed /* Simple helper to get the last statement from BB, which is assumed
to be a control statement. */ to be a control statement. Return NULL if the last statement is
not a control statement. */
static gimple * static gimple *
get_gimple_control_stmt (basic_block bb) get_gimple_control_stmt (basic_block bb)
{ {
gimple_stmt_iterator gsi = gsi_last_bb (bb); gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
if (gsi_end_p (gsi)) if (gsi_end_p (gsi))
return NULL; return NULL;
gimple *stmt = gsi_stmt (gsi); gimple *stmt = gsi_stmt (gsi);
enum gimple_code code = gimple_code (stmt); enum gimple_code code = gimple_code (stmt);
gcc_assert (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO); if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
return stmt; return stmt;
return NULL;
} }
/* 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.
...@@ -340,11 +343,39 @@ fsm_find_control_statement_thread_paths (tree name, ...@@ -340,11 +343,39 @@ fsm_find_control_statement_thread_paths (tree name,
finding a path where NAME is a constant, we can thread the path. */ finding a path where NAME is a constant, we can thread the path. */
void void
find_jump_threads_backwards (tree name, basic_block bb) find_jump_threads_backwards (edge e)
{ {
if (!flag_expensive_optimizations
|| optimize_function_for_size_p (cfun)
|| e->dest->loop_father != e->src->loop_father
|| loop_depth (e->dest->loop_father) == 0)
return;
gimple *stmt = get_gimple_control_stmt (e->dest);
if (!stmt)
return;
enum gimple_code code = gimple_code (stmt);
tree name = NULL;
if (code == GIMPLE_SWITCH)
name = gimple_switch_index (as_a <gswitch *> (stmt));
else if (code == GIMPLE_GOTO)
name = gimple_goto_dest (stmt);
else if (code == GIMPLE_COND)
{
if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
&& TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
|| POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
name = gimple_cond_lhs (stmt);
}
if (!name || TREE_CODE (name) != SSA_NAME)
return;
vec<basic_block, va_gc> *bb_path; vec<basic_block, va_gc> *bb_path;
vec_alloc (bb_path, n_basic_blocks_for_fn (cfun)); vec_alloc (bb_path, n_basic_blocks_for_fn (cfun));
vec_safe_push (bb_path, bb); vec_safe_push (bb_path, e->dest);
hash_set<basic_block> *visited_bbs = new hash_set<basic_block>; hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS); max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS);
...@@ -352,4 +383,4 @@ find_jump_threads_backwards (tree name, basic_block bb) ...@@ -352,4 +383,4 @@ find_jump_threads_backwards (tree name, basic_block bb)
delete visited_bbs; delete visited_bbs;
vec_free (bb_path); vec_free (bb_path);
} }
...@@ -20,6 +20,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -20,6 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSA_THREADFSM_H #ifndef GCC_TREE_SSA_THREADFSM_H
#define GCC_TREE_SSA_THREADFSM_H #define GCC_TREE_SSA_THREADFSM_H
extern void find_jump_threads_backwards (tree, basic_block); extern void find_jump_threads_backwards (edge);
#endif /* GCC_TREE_SSA_THREADFSM_H */ #endif /* GCC_TREE_SSA_THREADFSM_H */
...@@ -566,7 +566,7 @@ simplify_control_stmt_condition (edge e, ...@@ -566,7 +566,7 @@ simplify_control_stmt_condition (edge e,
It is possible to get loops in the SSA_NAME_VALUE chains It is possible to get loops in the SSA_NAME_VALUE chains
(consider threading the backedge of a loop where we have (consider threading the backedge of a loop where we have
a loop invariant SSA_NAME used in the condition. */ a loop invariant SSA_NAME used in the condition). */
if (cached_lhs) if (cached_lhs)
{ {
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
...@@ -904,12 +904,10 @@ thread_through_normal_block (edge e, ...@@ -904,12 +904,10 @@ thread_through_normal_block (edge e,
bitmap visited, bitmap visited,
bool *backedge_seen_p) bool *backedge_seen_p)
{ {
/* If we have traversed a backedge, then we do not want to look /* If we have seen a backedge, then we rely solely on the FSM threader
at certain expressions in the table that can not be relied upon. to find jump threads. */
Luckily the only code that looked at those expressions is the
SIMPLIFY callback, which we replace if we can no longer use it. */
if (*backedge_seen_p) if (*backedge_seen_p)
simplify = dummy_simplify; return 0;
/* We want to record any equivalences created by traversing E. */ /* We want to record any equivalences created by traversing E. */
if (!handle_dominating_asserts) if (!handle_dominating_asserts)
...@@ -1019,26 +1017,6 @@ thread_through_normal_block (edge e, ...@@ -1019,26 +1017,6 @@ thread_through_normal_block (edge e,
backedge_seen_p); backedge_seen_p);
return 1; return 1;
} }
if (!flag_expensive_optimizations
|| optimize_function_for_size_p (cfun)
|| !(TREE_CODE (cond) == SSA_NAME
|| (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
&& TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
&& TREE_CODE (TREE_OPERAND (cond, 1)) == INTEGER_CST))
|| e->dest->loop_father != e->src->loop_father
|| loop_depth (e->dest->loop_father) == 0)
return 0;
/* Extract the SSA_NAME we want to trace backwards if COND is not
already a bare SSA_NAME. */
if (TREE_CODE (cond) != SSA_NAME)
cond = TREE_OPERAND (cond, 0);
/* When COND cannot be simplified, try to find paths from a control
statement back through the PHI nodes which would affect that control
statement. */
find_jump_threads_backwards (cond, e->dest);
} }
return 0; return 0;
} }
...@@ -1118,6 +1096,8 @@ thread_across_edge (gcond *dummy_cond, ...@@ -1118,6 +1096,8 @@ thread_across_edge (gcond *dummy_cond,
path->release (); path->release ();
delete path; delete path;
find_jump_threads_backwards (e);
/* A negative status indicates the target block was deemed too big to /* A negative status indicates the target block was deemed too big to
duplicate. Just quit now rather than trying to use the block as duplicate. Just quit now rather than trying to use the block as
a joiner in a jump threading path. a joiner in a jump threading path.
...@@ -1217,6 +1197,7 @@ thread_across_edge (gcond *dummy_cond, ...@@ -1217,6 +1197,7 @@ thread_across_edge (gcond *dummy_cond,
} }
else else
{ {
find_jump_threads_backwards (path->last ()->e);
delete_jump_thread_path (path); delete_jump_thread_path (path);
} }
......
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