+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>
* 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>
PR middle-end/68142
/* 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
iteration. */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "FSM jump thread" 1 "dom2" } } */
/* 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
are both caught by threading in DOM. */
-/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp1"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 0 "dom1"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "dom1"} } */
+/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "vrp1"} } */
static int max_threaded_paths;
/* 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 *
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))
return NULL;
gimple *stmt = gsi_stmt (gsi);
enum gimple_code code = gimple_code (stmt);
- gcc_assert (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO);
- return stmt;
+ if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
+ return stmt;
+ return NULL;
}
/* Return true if the CFG contains at least one path from START_BB to END_BB.
finding a path where NAME is a constant, we can thread the path. */
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_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>;
max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS);
delete visited_bbs;
vec_free (bb_path);
-}
+}
#ifndef 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 */
It is possible to get loops in the SSA_NAME_VALUE chains
(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)
{
for (int i = 0; i < 2; i++)
bitmap visited,
bool *backedge_seen_p)
{
- /* If we have traversed a backedge, then we do not want to look
- at certain expressions in the table that can not be relied upon.
- Luckily the only code that looked at those expressions is the
- SIMPLIFY callback, which we replace if we can no longer use it. */
+ /* If we have seen a backedge, then we rely solely on the FSM threader
+ to find jump threads. */
if (*backedge_seen_p)
- simplify = dummy_simplify;
+ return 0;
/* We want to record any equivalences created by traversing E. */
if (!handle_dominating_asserts)
backedge_seen_p);
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;
}
path->release ();
delete path;
+ find_jump_threads_backwards (e);
+
/* A negative status indicates the target block was deemed too big to
duplicate. Just quit now rather than trying to use the block as
a joiner in a jump threading path.
}
else
{
+ find_jump_threads_backwards (path->last ()->e);
delete_jump_thread_path (path);
}