mirror of git://gcc.gnu.org/git/gcc.git
[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
This commit is contained in:
parent
3ddb720ebf
commit
21f0717ab1
|
|
@ -1,3 +1,21 @@
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
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:
|
||||||
/* 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)
|
||||||
/* 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
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
#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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
find_jump_threads_backwards (path->last ()->e);
|
||||||
delete_jump_thread_path (path);
|
delete_jump_thread_path (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue