summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-19 09:03:45 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-19 09:03:45 +0000
commitb11e16d5eacc6bee8aa7ea50be5f2b3f95581b4b (patch)
tree8029b8a046840a43572ac9c006c6c8f55d2b096e /gcc/tree-ssa-ccp.c
parentf0620a215a807d40102f6165c6002a94b4bc283e (diff)
downloadgcc-b11e16d5eacc6bee8aa7ea50be5f2b3f95581b4b.tar.gz
2011-12-19 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 182471 using svnmerge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@182472 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c100
1 files changed, 97 insertions, 3 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 31c31c141c9..a9c38ee8fad 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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;
}