re PR tree-optimization/51491 (ccp when converting from alloca should add a CLOBBER to right before __builtin_stack_restore)

2011-12-17  Tom de Vries  <tom@codesourcery.com>

	PR tree-optimization/51491
	* tree-ssa-ccp.c (insert_clobber_before_stack_restore)
	(gsi_prev_dom_bb_nondebug, insert_clobbers_for_var): New function.
	(ccp_fold_stmt): Use insert_clobbers_for_var after a successful
	fold_builtin_alloca_with_align.
	(ccp_visit_stmt): Calculate and free dominator info.

From-SVN: r182432
This commit is contained in:
Tom de Vries 2011-12-17 11:39:43 +00:00 committed by Tom de Vries
parent eb0287685d
commit 2f31f742a6
2 changed files with 106 additions and 3 deletions

View File

@ -1,3 +1,12 @@
2011-12-17 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/51491
* tree-ssa-ccp.c (insert_clobber_before_stack_restore)
(gsi_prev_dom_bb_nondebug, insert_clobbers_for_var): New function.
(ccp_fold_stmt): Use insert_clobbers_for_var after a successful
fold_builtin_alloca_with_align.
(ccp_visit_stmt): Calculate and free dominator info.
2011-12-16 Eric Botcazou <ebotcazou@adacore.com>
* config/sparc/sparc.md (UNSPEC_FRAME_BLOCKAGE): New constant.

View File

@ -1690,6 +1690,96 @@ evaluate_stmt (gimple stmt)
return val;
}
/* Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before
each matching BUILT_IN_STACK_RESTORE. Mark visited phis in VISITED. */
static void
insert_clobber_before_stack_restore (tree saved_val, tree var, htab_t *visited)
{
gimple stmt, clobber_stmt;
tree clobber;
imm_use_iterator iter;
gimple_stmt_iterator i;
gimple *slot;
FOR_EACH_IMM_USE_STMT (stmt, iter, saved_val)
if (gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
{
clobber = build_constructor (TREE_TYPE (var), NULL);
TREE_THIS_VOLATILE (clobber) = 1;
clobber_stmt = gimple_build_assign (var, clobber);
i = gsi_for_stmt (stmt);
gsi_insert_before (&i, clobber_stmt, GSI_SAME_STMT);
}
else if (gimple_code (stmt) == GIMPLE_PHI)
{
if (*visited == NULL)
*visited = htab_create (10, htab_hash_pointer, htab_eq_pointer, NULL);
slot = (gimple *)htab_find_slot (*visited, stmt, INSERT);
if (*slot != NULL)
continue;
*slot = stmt;
insert_clobber_before_stack_restore (gimple_phi_result (stmt), var,
visited);
}
else
gcc_assert (is_gimple_debug (stmt));
}
/* Advance the iterator to the previous non-debug gimple statement in the same
or dominating basic block. */
static inline void
gsi_prev_dom_bb_nondebug (gimple_stmt_iterator *i)
{
basic_block dom;
gsi_prev_nondebug (i);
while (gsi_end_p (*i))
{
dom = get_immediate_dominator (CDI_DOMINATORS, i->bb);
if (dom == NULL || dom == ENTRY_BLOCK_PTR)
return;
*i = gsi_last_bb (dom);
}
}
/* Find a BUILT_IN_STACK_SAVE dominating gsi_stmt (I), and insert
a clobber of VAR before each matching BUILT_IN_STACK_RESTORE. */
static void
insert_clobbers_for_var (gimple_stmt_iterator i, tree var)
{
bool save_found;
gimple stmt;
tree saved_val;
htab_t visited = NULL;
for (save_found = false; !gsi_end_p (i); gsi_prev_dom_bb_nondebug (&i))
{
stmt = gsi_stmt (i);
if (!gimple_call_builtin_p (stmt, BUILT_IN_STACK_SAVE))
continue;
save_found = true;
saved_val = gimple_call_lhs (stmt);
if (saved_val == NULL_TREE)
continue;
insert_clobber_before_stack_restore (saved_val, var, &visited);
break;
}
if (visited != NULL)
htab_delete (visited);
gcc_assert (save_found);
}
/* Detects a __builtin_alloca_with_align with constant size argument. Declares
fixed-size array and returns the address, if found, otherwise returns
NULL_TREE. */
@ -1824,7 +1914,9 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
if (new_rhs)
{
bool res = update_call_from_tree (gsi, new_rhs);
tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
gcc_assert (res);
insert_clobbers_for_var (*gsi, var);
return true;
}
}
@ -2024,12 +2116,14 @@ ccp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
static unsigned int
do_ssa_ccp (void)
{
unsigned int todo = 0;
calculate_dominance_info (CDI_DOMINATORS);
ccp_initialize ();
ssa_propagate (ccp_visit_stmt, ccp_visit_phi_node);
if (ccp_finalize ())
return (TODO_cleanup_cfg | TODO_update_ssa | TODO_remove_unused_locals);
else
return 0;
todo = (TODO_cleanup_cfg | TODO_update_ssa | TODO_remove_unused_locals);
free_dominance_info (CDI_DOMINATORS);
return todo;
}