Commit 8d7437be by Jeff Law Committed by Jeff Law

re PR tree-optimization/71437 (Performance regression after r235817)

	PR tree-optimization/71437
	* tree-ssa-dom.c (pfn_simplify): Add basic_block argument.  All
	callers changed.
	(simplify_stmt_for_jump_threading): Add basic_block argument.  All
	callers changed.
	(lhs_of_dominating_assert): Moved from here into tree-vrp.c.
	(dom_opt_dom_walker::thread_across_edge): Remove
	handle_dominating_asserts argument.  All callers changed.
	(record_temporary_equivalences_from_stmts_at_dest): Corresponding
	changes.  Remove calls to lhs_of_dominating_assert.  Other
	uses of handle_dominating_asserts turn into unconditional code
	(simplify_control_stmt_condition_1): Likewise.
	(simplify_control_stmt_condition): Likewise.
	(thread_through_normal_block, thread_across_edge): Likewise.
	* tree-ssa-threadedge.h (thread_across_edge): Corresponding changes.
	* tree-vrp.c (lhs_of_dominating_assert): Move here.  Return original
	object if it is not an SSA_NAME.
	(simplify_stmt_for_jump_threading): Call lhs_of_dominating_assert
	before calling into the VRP specific simplifiers.
	(identify_jump_threads): Remove handle_dominating_asserts
	argument.

From-SVN: r246207
parent 9fc900af
2017-03-16 Jeff Law <law@redhat.com>
PR tree-optimization/71437
* tree-ssa-dom.c (pfn_simplify): Add basic_block argument. All
callers changed.
(simplify_stmt_for_jump_threading): Add basic_block argument. All
callers changed.
(lhs_of_dominating_assert): Moved from here into tree-vrp.c.
(dom_opt_dom_walker::thread_across_edge): Remove
handle_dominating_asserts argument. All callers changed.
(record_temporary_equivalences_from_stmts_at_dest): Corresponding
changes. Remove calls to lhs_of_dominating_assert. Other
uses of handle_dominating_asserts turn into unconditional code
(simplify_control_stmt_condition_1): Likewise.
(simplify_control_stmt_condition): Likewise.
(thread_through_normal_block, thread_across_edge): Likewise.
* tree-ssa-threadedge.h (thread_across_edge): Corresponding changes.
* tree-vrp.c (lhs_of_dominating_assert): Move here. Return original
object if it is not an SSA_NAME.
(simplify_stmt_for_jump_threading): Call lhs_of_dominating_assert
before calling into the VRP specific simplifiers.
(identify_jump_threads): Remove handle_dominating_asserts
argument.
2017-03-16 Jakub Jelinek <jakub@redhat.com> 2017-03-16 Jakub Jelinek <jakub@redhat.com>
PR fortran/79886 PR fortran/79886
......
...@@ -604,7 +604,8 @@ make_pass_dominator (gcc::context *ctxt) ...@@ -604,7 +604,8 @@ make_pass_dominator (gcc::context *ctxt)
static tree static tree
simplify_stmt_for_jump_threading (gimple *stmt, simplify_stmt_for_jump_threading (gimple *stmt,
gimple *within_stmt ATTRIBUTE_UNUSED, gimple *within_stmt ATTRIBUTE_UNUSED,
class avail_exprs_stack *avail_exprs_stack) class avail_exprs_stack *avail_exprs_stack,
basic_block bb ATTRIBUTE_UNUSED)
{ {
return avail_exprs_stack->lookup_avail_expr (stmt, false, true); return avail_exprs_stack->lookup_avail_expr (stmt, false, true);
} }
...@@ -835,7 +836,7 @@ dom_opt_dom_walker::thread_across_edge (edge e) ...@@ -835,7 +836,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
/* With all the edge equivalences in the tables, go ahead and attempt /* With all the edge equivalences in the tables, go ahead and attempt
to thread through E->dest. */ to thread through E->dest. */
::thread_across_edge (m_dummy_cond, e, false, ::thread_across_edge (m_dummy_cond, e,
m_const_and_copies, m_avail_exprs_stack, m_const_and_copies, m_avail_exprs_stack,
simplify_stmt_for_jump_threading); simplify_stmt_for_jump_threading);
......
...@@ -47,7 +47,9 @@ static int stmt_count; ...@@ -47,7 +47,9 @@ static int stmt_count;
/* Array to record value-handles per SSA_NAME. */ /* Array to record value-handles per SSA_NAME. */
vec<tree> ssa_name_values; vec<tree> ssa_name_values;
typedef tree (pfn_simplify) (gimple *, gimple *, class avail_exprs_stack *); typedef tree (pfn_simplify) (gimple *, gimple *,
class avail_exprs_stack *,
basic_block);
/* Set the value for the SSA name NAME to VALUE. */ /* Set the value for the SSA name NAME to VALUE. */
...@@ -111,32 +113,6 @@ potentially_threadable_block (basic_block bb) ...@@ -111,32 +113,6 @@ potentially_threadable_block (basic_block bb)
return true; return true;
} }
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
BB. If no such ASSERT_EXPR is found, return OP. */
static tree
lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt)
{
imm_use_iterator imm_iter;
gimple *use_stmt;
use_operand_p use_p;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
{
use_stmt = USE_STMT (use_p);
if (use_stmt != stmt
&& gimple_assign_single_p (use_stmt)
&& TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ASSERT_EXPR
&& TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == op
&& dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (use_stmt)))
{
return gimple_assign_lhs (use_stmt);
}
}
return op;
}
/* Record temporary equivalences created by PHIs at the target of the /* Record temporary equivalences created by PHIs at the target of the
edge E. Record unwind information for the equivalences onto STACK. edge E. Record unwind information for the equivalences onto STACK.
...@@ -357,7 +333,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, ...@@ -357,7 +333,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
SET_USE (use_p, tmp); SET_USE (use_p, tmp);
} }
cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack); cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack, e->src);
/* Restore the statement's original uses/defs. */ /* Restore the statement's original uses/defs. */
i = 0; i = 0;
...@@ -380,7 +356,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, ...@@ -380,7 +356,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
static tree simplify_control_stmt_condition_1 (edge, gimple *, static tree simplify_control_stmt_condition_1 (edge, gimple *,
class avail_exprs_stack *, class avail_exprs_stack *,
tree, enum tree_code, tree, tree, enum tree_code, tree,
gcond *, pfn_simplify, bool, gcond *, pfn_simplify,
unsigned); unsigned);
/* Simplify the control statement at the end of the block E->dest. /* Simplify the control statement at the end of the block E->dest.
...@@ -402,8 +378,7 @@ simplify_control_stmt_condition (edge e, ...@@ -402,8 +378,7 @@ simplify_control_stmt_condition (edge e,
gimple *stmt, gimple *stmt,
class avail_exprs_stack *avail_exprs_stack, class avail_exprs_stack *avail_exprs_stack,
gcond *dummy_cond, gcond *dummy_cond,
pfn_simplify simplify, pfn_simplify simplify)
bool handle_dominating_asserts)
{ {
tree cond, cached_lhs; tree cond, cached_lhs;
enum gimple_code code = gimple_code (stmt); enum gimple_code code = gimple_code (stmt);
...@@ -450,7 +425,6 @@ simplify_control_stmt_condition (edge e, ...@@ -450,7 +425,6 @@ simplify_control_stmt_condition (edge e,
= simplify_control_stmt_condition_1 (e, stmt, avail_exprs_stack, = simplify_control_stmt_condition_1 (e, stmt, avail_exprs_stack,
op0, cond_code, op1, op0, cond_code, op1,
dummy_cond, simplify, dummy_cond, simplify,
handle_dominating_asserts,
recursion_limit); recursion_limit);
/* If we were testing an integer/pointer against a constant, then /* If we were testing an integer/pointer against a constant, then
...@@ -508,28 +482,24 @@ simplify_control_stmt_condition (edge e, ...@@ -508,28 +482,24 @@ simplify_control_stmt_condition (edge e,
} }
} }
/* If we're dominated by a suitable ASSERT_EXPR, then
update CACHED_LHS appropriately. */
if (handle_dominating_asserts && TREE_CODE (cached_lhs) == SSA_NAME)
cached_lhs = lhs_of_dominating_assert (cached_lhs, e->src, stmt);
/* If we haven't simplified to an invariant yet, then use the /* If we haven't simplified to an invariant yet, then use the
pass specific callback to try and simplify it further. */ pass specific callback to try and simplify it further. */
if (cached_lhs && ! is_gimple_min_invariant (cached_lhs)) if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
{ {
if (handle_dominating_asserts && code == GIMPLE_SWITCH) if (code == GIMPLE_SWITCH)
{ {
/* Replace the index operand of the GIMPLE_SWITCH with the /* Replace the index operand of the GIMPLE_SWITCH with any LHS
dominating ASSERT_EXPR before handing it off to VRP. If we found before handing off to VRP. If simplification is
simplification is possible, the simplified value will be a possible, the simplified value will be a CASE_LABEL_EXPR of
CASE_LABEL_EXPR of the label that is proven to be taken. */ the label that is proven to be taken. */
gswitch *dummy_switch = as_a<gswitch *> (gimple_copy (stmt)); gswitch *dummy_switch = as_a<gswitch *> (gimple_copy (stmt));
gimple_switch_set_index (dummy_switch, cached_lhs); gimple_switch_set_index (dummy_switch, cached_lhs);
cached_lhs = (*simplify) (dummy_switch, stmt, avail_exprs_stack); cached_lhs = (*simplify) (dummy_switch, stmt,
avail_exprs_stack, e->src);
ggc_free (dummy_switch); ggc_free (dummy_switch);
} }
else else
cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack); cached_lhs = (*simplify) (stmt, stmt, avail_exprs_stack, e->src);
} }
/* We couldn't find an invariant. But, callers of this /* We couldn't find an invariant. But, callers of this
...@@ -555,7 +525,6 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -555,7 +525,6 @@ simplify_control_stmt_condition_1 (edge e,
tree op1, tree op1,
gcond *dummy_cond, gcond *dummy_cond,
pfn_simplify simplify, pfn_simplify simplify,
bool handle_dominating_asserts,
unsigned limit) unsigned limit)
{ {
if (limit == 0) if (limit == 0)
...@@ -575,8 +544,7 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -575,8 +544,7 @@ simplify_control_stmt_condition_1 (edge e,
recurse into the LHS to see if there is a dominating ASSERT_EXPR recurse into the LHS to see if there is a dominating ASSERT_EXPR
of A or of B that makes this condition always true or always false of A or of B that makes this condition always true or always false
along the edge E. */ along the edge E. */
if (handle_dominating_asserts if ((cond_code == EQ_EXPR || cond_code == NE_EXPR)
&& (cond_code == EQ_EXPR || cond_code == NE_EXPR)
&& TREE_CODE (op0) == SSA_NAME && TREE_CODE (op0) == SSA_NAME
&& integer_zerop (op1)) && integer_zerop (op1))
{ {
...@@ -595,7 +563,6 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -595,7 +563,6 @@ simplify_control_stmt_condition_1 (edge e,
= simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack, = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
rhs1, NE_EXPR, op1, rhs1, NE_EXPR, op1,
dummy_cond, simplify, dummy_cond, simplify,
handle_dominating_asserts,
limit - 1); limit - 1);
if (res1 == NULL_TREE) if (res1 == NULL_TREE)
; ;
...@@ -623,7 +590,6 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -623,7 +590,6 @@ simplify_control_stmt_condition_1 (edge e,
= simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack, = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
rhs2, NE_EXPR, op1, rhs2, NE_EXPR, op1,
dummy_cond, simplify, dummy_cond, simplify,
handle_dominating_asserts,
limit - 1); limit - 1);
if (res2 == NULL_TREE) if (res2 == NULL_TREE)
; ;
...@@ -689,25 +655,12 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -689,25 +655,12 @@ simplify_control_stmt_condition_1 (edge e,
= simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack, = simplify_control_stmt_condition_1 (e, def_stmt, avail_exprs_stack,
rhs1, new_cond, rhs2, rhs1, new_cond, rhs2,
dummy_cond, simplify, dummy_cond, simplify,
handle_dominating_asserts,
limit - 1); limit - 1);
if (res != NULL_TREE && is_gimple_min_invariant (res)) if (res != NULL_TREE && is_gimple_min_invariant (res))
return res; return res;
} }
} }
if (handle_dominating_asserts)
{
/* Now see if the operand was consumed by an ASSERT_EXPR
which dominates E->src. If so, we want to replace the
operand with the LHS of the ASSERT_EXPR. */
if (TREE_CODE (op0) == SSA_NAME)
op0 = lhs_of_dominating_assert (op0, e->src, stmt);
if (TREE_CODE (op1) == SSA_NAME)
op1 = lhs_of_dominating_assert (op1, e->src, stmt);
}
gimple_cond_set_code (dummy_cond, cond_code); gimple_cond_set_code (dummy_cond, cond_code);
gimple_cond_set_lhs (dummy_cond, op0); gimple_cond_set_lhs (dummy_cond, op0);
gimple_cond_set_rhs (dummy_cond, op1); gimple_cond_set_rhs (dummy_cond, op1);
...@@ -728,7 +681,7 @@ simplify_control_stmt_condition_1 (edge e, ...@@ -728,7 +681,7 @@ simplify_control_stmt_condition_1 (edge e,
then use the pass specific callback to simplify the condition. */ then use the pass specific callback to simplify the condition. */
if (!res if (!res
|| !is_gimple_min_invariant (res)) || !is_gimple_min_invariant (res))
res = (*simplify) (dummy_cond, stmt, avail_exprs_stack); res = (*simplify) (dummy_cond, stmt, avail_exprs_stack, e->src);
return res; return res;
} }
...@@ -868,8 +821,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) ...@@ -868,8 +821,8 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
returning TRUE from the toplevel call. Otherwise do nothing and returning TRUE from the toplevel call. Otherwise do nothing and
return false. return false.
DUMMY_COND, HANDLE_DOMINATING_ASSERTS and SIMPLIFY are used to DUMMY_COND, SIMPLIFY are used to try and simplify the condition at the
try and simplify the condition at the end of TAKEN_EDGE->dest. end of TAKEN_EDGE->dest.
The available expression table is referenced via AVAIL_EXPRS_STACK. */ The available expression table is referenced via AVAIL_EXPRS_STACK. */
...@@ -877,7 +830,6 @@ static bool ...@@ -877,7 +830,6 @@ static bool
thread_around_empty_blocks (edge taken_edge, thread_around_empty_blocks (edge taken_edge,
gcond *dummy_cond, gcond *dummy_cond,
class avail_exprs_stack *avail_exprs_stack, class avail_exprs_stack *avail_exprs_stack,
bool handle_dominating_asserts,
pfn_simplify simplify, pfn_simplify simplify,
bitmap visited, bitmap visited,
vec<jump_thread_edge *> *path) vec<jump_thread_edge *> *path)
...@@ -928,7 +880,6 @@ thread_around_empty_blocks (edge taken_edge, ...@@ -928,7 +880,6 @@ thread_around_empty_blocks (edge taken_edge,
return thread_around_empty_blocks (taken_edge, return thread_around_empty_blocks (taken_edge,
dummy_cond, dummy_cond,
avail_exprs_stack, avail_exprs_stack,
handle_dominating_asserts,
simplify, simplify,
visited, visited,
path); path);
...@@ -950,7 +901,7 @@ thread_around_empty_blocks (edge taken_edge, ...@@ -950,7 +901,7 @@ thread_around_empty_blocks (edge taken_edge,
/* Extract and simplify the condition. */ /* Extract and simplify the condition. */
cond = simplify_control_stmt_condition (taken_edge, stmt, cond = simplify_control_stmt_condition (taken_edge, stmt,
avail_exprs_stack, dummy_cond, avail_exprs_stack, dummy_cond,
simplify, handle_dominating_asserts); simplify);
/* If the condition can be statically computed and we have not already /* If the condition can be statically computed and we have not already
visited the destination edge, then add the taken edge to our thread visited the destination edge, then add the taken edge to our thread
...@@ -978,7 +929,6 @@ thread_around_empty_blocks (edge taken_edge, ...@@ -978,7 +929,6 @@ thread_around_empty_blocks (edge taken_edge,
thread_around_empty_blocks (taken_edge, thread_around_empty_blocks (taken_edge,
dummy_cond, dummy_cond,
avail_exprs_stack, avail_exprs_stack,
handle_dominating_asserts,
simplify, simplify,
visited, visited,
path); path);
...@@ -1004,10 +954,6 @@ thread_around_empty_blocks (edge taken_edge, ...@@ -1004,10 +954,6 @@ thread_around_empty_blocks (edge taken_edge,
DUMMY_COND is a shared cond_expr used by condition simplification as scratch, DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
to avoid allocating memory. to avoid allocating memory.
HANDLE_DOMINATING_ASSERTS is true if we should try to replace operands of
the simplified condition with left-hand sides of ASSERT_EXPRs they are
used in.
STACK is used to undo temporary equivalences created during the walk of STACK is used to undo temporary equivalences created during the walk of
E->dest. E->dest.
...@@ -1024,7 +970,6 @@ thread_around_empty_blocks (edge taken_edge, ...@@ -1024,7 +970,6 @@ thread_around_empty_blocks (edge taken_edge,
static int static int
thread_through_normal_block (edge e, thread_through_normal_block (edge e,
gcond *dummy_cond, gcond *dummy_cond,
bool handle_dominating_asserts,
const_and_copies *const_and_copies, const_and_copies *const_and_copies,
avail_exprs_stack *avail_exprs_stack, avail_exprs_stack *avail_exprs_stack,
pfn_simplify simplify, pfn_simplify simplify,
...@@ -1032,8 +977,7 @@ thread_through_normal_block (edge e, ...@@ -1032,8 +977,7 @@ thread_through_normal_block (edge e,
bitmap visited) bitmap visited)
{ {
/* We want to record any equivalences created by traversing E. */ /* We want to record any equivalences created by traversing E. */
if (!handle_dominating_asserts) record_temporary_equivalences (e, const_and_copies, avail_exprs_stack);
record_temporary_equivalences (e, const_and_copies, avail_exprs_stack);
/* PHIs create temporary equivalences. /* PHIs create temporary equivalences.
Note that if we found a PHI that made the block non-threadable, then Note that if we found a PHI that made the block non-threadable, then
...@@ -1085,8 +1029,7 @@ thread_through_normal_block (edge e, ...@@ -1085,8 +1029,7 @@ thread_through_normal_block (edge e,
/* Extract and simplify the condition. */ /* Extract and simplify the condition. */
cond = simplify_control_stmt_condition (e, stmt, avail_exprs_stack, cond = simplify_control_stmt_condition (e, stmt, avail_exprs_stack,
dummy_cond, simplify, dummy_cond, simplify);
handle_dominating_asserts);
if (!cond) if (!cond)
return 0; return 0;
...@@ -1135,7 +1078,6 @@ thread_through_normal_block (edge e, ...@@ -1135,7 +1078,6 @@ thread_through_normal_block (edge e,
thread_around_empty_blocks (taken_edge, thread_around_empty_blocks (taken_edge,
dummy_cond, dummy_cond,
avail_exprs_stack, avail_exprs_stack,
handle_dominating_asserts,
simplify, simplify,
visited, visited,
path); path);
...@@ -1151,10 +1093,6 @@ thread_through_normal_block (edge e, ...@@ -1151,10 +1093,6 @@ thread_through_normal_block (edge e,
DUMMY_COND is a shared cond_expr used by condition simplification as scratch, DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
to avoid allocating memory. to avoid allocating memory.
HANDLE_DOMINATING_ASSERTS is true if we should try to replace operands of
the simplified condition with left-hand sides of ASSERT_EXPRs they are
used in.
CONST_AND_COPIES is used to undo temporary equivalences created during the CONST_AND_COPIES is used to undo temporary equivalences created during the
walk of E->dest. walk of E->dest.
...@@ -1165,11 +1103,10 @@ thread_through_normal_block (edge e, ...@@ -1165,11 +1103,10 @@ thread_through_normal_block (edge e,
void void
thread_across_edge (gcond *dummy_cond, thread_across_edge (gcond *dummy_cond,
edge e, edge e,
bool handle_dominating_asserts,
class const_and_copies *const_and_copies, class const_and_copies *const_and_copies,
class avail_exprs_stack *avail_exprs_stack, class avail_exprs_stack *avail_exprs_stack,
tree (*simplify) (gimple *, gimple *, tree (*simplify) (gimple *, gimple *,
class avail_exprs_stack *)) class avail_exprs_stack *, basic_block))
{ {
bitmap visited = BITMAP_ALLOC (NULL); bitmap visited = BITMAP_ALLOC (NULL);
...@@ -1183,7 +1120,6 @@ thread_across_edge (gcond *dummy_cond, ...@@ -1183,7 +1120,6 @@ thread_across_edge (gcond *dummy_cond,
int threaded; int threaded;
if ((e->flags & EDGE_DFS_BACK) == 0) if ((e->flags & EDGE_DFS_BACK) == 0)
threaded = thread_through_normal_block (e, dummy_cond, threaded = thread_through_normal_block (e, dummy_cond,
handle_dominating_asserts,
const_and_copies, const_and_copies,
avail_exprs_stack, avail_exprs_stack,
simplify, path, simplify, path,
...@@ -1281,14 +1217,12 @@ thread_across_edge (gcond *dummy_cond, ...@@ -1281,14 +1217,12 @@ thread_across_edge (gcond *dummy_cond,
found = thread_around_empty_blocks (taken_edge, found = thread_around_empty_blocks (taken_edge,
dummy_cond, dummy_cond,
avail_exprs_stack, avail_exprs_stack,
handle_dominating_asserts,
simplify, simplify,
visited, visited,
path); path);
if (!found) if (!found)
found = thread_through_normal_block (path->last ()->e, dummy_cond, found = thread_through_normal_block (path->last ()->e, dummy_cond,
handle_dominating_asserts,
const_and_copies, const_and_copies,
avail_exprs_stack, avail_exprs_stack,
simplify, path, simplify, path,
......
...@@ -30,10 +30,10 @@ extern void threadedge_initialize_values (void); ...@@ -30,10 +30,10 @@ extern void threadedge_initialize_values (void);
extern void threadedge_finalize_values (void); extern void threadedge_finalize_values (void);
extern bool potentially_threadable_block (basic_block); extern bool potentially_threadable_block (basic_block);
extern void propagate_threaded_block_debug_into (basic_block, basic_block); extern void propagate_threaded_block_debug_into (basic_block, basic_block);
extern void thread_across_edge (gcond *, edge, bool, extern void thread_across_edge (gcond *, edge,
const_and_copies *, const_and_copies *,
avail_exprs_stack *, avail_exprs_stack *,
tree (*) (gimple *, gimple *, tree (*) (gimple *, gimple *,
avail_exprs_stack *)); avail_exprs_stack *, basic_block));
#endif /* GCC_TREE_SSA_THREADEDGE_H */ #endif /* GCC_TREE_SSA_THREADEDGE_H */
...@@ -10749,6 +10749,33 @@ vrp_fold_stmt (gimple_stmt_iterator *si) ...@@ -10749,6 +10749,33 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
/* Unwindable const/copy equivalences. */ /* Unwindable const/copy equivalences. */
const_and_copies *equiv_stack; const_and_copies *equiv_stack;
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
BB. If no such ASSERT_EXPR is found, return OP. */
static tree
lhs_of_dominating_assert (tree op, basic_block bb, gimple *stmt)
{
imm_use_iterator imm_iter;
gimple *use_stmt;
use_operand_p use_p;
if (TREE_CODE (op) == SSA_NAME)
{
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
{
use_stmt = USE_STMT (use_p);
if (use_stmt != stmt
&& gimple_assign_single_p (use_stmt)
&& TREE_CODE (gimple_assign_rhs1 (use_stmt)) == ASSERT_EXPR
&& TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == op
&& dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (use_stmt)))
return gimple_assign_lhs (use_stmt);
}
}
return op;
}
/* A trivial wrapper so that we can present the generic jump threading /* A trivial wrapper so that we can present the generic jump threading
code with a simple API for simplifying statements. STMT is the code with a simple API for simplifying statements. STMT is the
statement we want to simplify, WITHIN_STMT provides the location statement we want to simplify, WITHIN_STMT provides the location
...@@ -10756,13 +10783,20 @@ const_and_copies *equiv_stack; ...@@ -10756,13 +10783,20 @@ const_and_copies *equiv_stack;
static tree static tree
simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
class avail_exprs_stack *avail_exprs_stack ATTRIBUTE_UNUSED) class avail_exprs_stack *avail_exprs_stack ATTRIBUTE_UNUSED,
basic_block bb)
{ {
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
return vrp_evaluate_conditional (gimple_cond_code (cond_stmt), {
gimple_cond_lhs (cond_stmt), tree op0 = gimple_cond_lhs (cond_stmt);
gimple_cond_rhs (cond_stmt), op0 = lhs_of_dominating_assert (op0, bb, stmt);
within_stmt);
tree op1 = gimple_cond_rhs (cond_stmt);
op1 = lhs_of_dominating_assert (op1, bb, stmt);
return vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
op0, op1, within_stmt);
}
/* We simplify a switch statement by trying to determine which case label /* We simplify a switch statement by trying to determine which case label
will be taken. If we are successful then we return the corresponding will be taken. If we are successful then we return the corresponding
...@@ -10773,6 +10807,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, ...@@ -10773,6 +10807,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
if (TREE_CODE (op) != SSA_NAME) if (TREE_CODE (op) != SSA_NAME)
return NULL_TREE; return NULL_TREE;
op = lhs_of_dominating_assert (op, bb, stmt);
value_range *vr = get_value_range (op); value_range *vr = get_value_range (op);
if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE) if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
|| symbolic_range_p (vr)) || symbolic_range_p (vr))
...@@ -10948,7 +10984,7 @@ identify_jump_threads (void) ...@@ -10948,7 +10984,7 @@ identify_jump_threads (void)
if (e->flags & (EDGE_IGNORE | EDGE_COMPLEX)) if (e->flags & (EDGE_IGNORE | EDGE_COMPLEX))
continue; continue;
thread_across_edge (dummy, e, true, equiv_stack, NULL, thread_across_edge (dummy, e, equiv_stack, NULL,
simplify_stmt_for_jump_threading); simplify_stmt_for_jump_threading);
} }
} }
......
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