This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples] Fix various C++ failures
- From: "Diego Novillo" <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 11 Apr 2008 01:03:54 -0400
- Subject: [tuples] Fix various C++ failures
This patch fixes other bugs that were causing problems in
C++:
- It re-enables clone_body and inlining of functions in High
GIMPLE form. It also removes support for inlining bodies in GENERIC
form. It was not necessary, as clone_body is called with functions
in High GIMPLE form.
- TREE_BLOCKs were being removed because mark_all_vars_used_1 was
handling TREE_BLOCK of expressions. This is no longer possible,
as there can be no expressions inside a gimple statement, so the
gimple_block() of every statement weren't being marked as needed.
Causing spurious failures.
- It removes gimple_shallow_copy (not used) and adds support for deep
copying high gimple statements that have sub-statements
(GIMPLE_BIND, GIMPLE_TRY, etc).
This fixes about 1,070 failures in C++ and 4 failures in C. We still
don't totally build libstdc++, but this fixes enough failures that I
didn't want to hold it back.
Tested on x86.
Diego.
* ipa-inline.c (cgraph_clone_inlined_nodes): Change uses
of DECL_SAVED_TREE with gimple_body.
(cgraph_decide_inlining_incrementally): Likewise.
* gimple-iterator.c (gsi_insert_seq_before_without_update):
Do nothing if SEQ is NULL.
(gsi_insert_seq_after_without_update): Likewise.
* tree-ssa-live.c (mark_all_vars_used_1): Do not handle
EXPR trees.
(remove_unused_locals): Mark the gimple_block of every
statement as used.
* tree-inline.c (remap_gimple_stmt): Forward declare.
(remap_decls): Tidy comments.
(remap_gimple_seq): New.
(copy_gimple_bind): New.
(remap_gimple_stmt): Call it.
Handle High GIMPLE statements.
(copy_bb): Regimplify operands on COPY_GSI instead of
GSI.
(copy_cfg_body): Tidy.
(copy_generic_body): Remove unused function.
(clone_body): Tuplify.
* c-common.c (c_warn_unused_result): Remove assertion for
FUNCTION_TYPE.
* gimple.c (gimple_seq_copy): Rename from
gimple_seq_deep_copy. Update all users.
(walk_gimple_stmt): Assert that STMT has no substatements
in the default case.
(gimple_copy_1): Merge into gimple_copy.
(gimple_copy): Always do deep copying.
Handle statements with substatements.
(gimple_shallow_copy): Remove unused function.
(gimple_deep_copy): Remove. Update all users.
* gimple.h: Tidy comments and structure fields
everywhere.
(gimple_has_substatements): New.
(walk_stmt_fn): Change last argument to struct walk_stmt_info *.
Update all users.
cp/ChangeLog.tuples
* optimize.c (maybe_clone_body): Re-enable call to
clone_body.
* cp-gimplify.c (cp_gimplify_omp_for): Mark disabled
code with call to gimple_unreachable.
(cp_genericize): Fix handling of clone bodies.
Index: value-prof.c
===================================================================
--- value-prof.c (revision 134164)
+++ value-prof.c (working copy)
@@ -1075,7 +1075,7 @@ gimple_ic (gimple stmt, gimple call, str
bb1end = stmt3;
label1 = gimple_build_label (label_decl1);
- stmt1 = gimple_deep_copy (stmt);
+ stmt1 = gimple_copy (stmt);
gimple_call_set_fn (stmt,
build_addr (direct_call->decl, current_function_decl));
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
@@ -1271,7 +1271,7 @@ gimple_stringop_fixed_value (gimple stmt
bb1end = stmt3;
label1 = gimple_build_label (label_decl1);
- stmt1 = gimple_deep_copy (stmt);
+ stmt1 = gimple_copy (stmt);
gimple_call_set_arg (stmt1, 2, value);
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
Index: omp-low.c
===================================================================
--- omp-low.c (revision 134164)
+++ omp-low.c (working copy)
@@ -1444,10 +1444,10 @@ scan_omp_1_op (tree *tp, int *walk_subtr
the current statement in GSI. */
static tree
-scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, void *data)
+scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
+ struct walk_stmt_info *wi)
{
gimple stmt = gsi_stmt (*gsi);
- struct walk_stmt_info *wi = data;
omp_context *ctx = wi->info;
if (gimple_has_location (stmt))
Index: cp/optimize.c
===================================================================
--- cp/optimize.c (revision 134164)
+++ cp/optimize.c (working copy)
@@ -185,12 +185,7 @@ maybe_clone_body (tree fn)
*pointer_map_insert (decl_map, parm) = clone_parm;
}
/* Clone the body. */
- /* FIXME tuples. */
-#if 0
clone_body (clone, fn, decl_map);
-#else
- gimple_unreachable ();
-#endif
/* Clean up. */
pointer_map_destroy (decl_map);
Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c (revision 134164)
+++ cp/cp-gimplify.c (working copy)
@@ -341,9 +341,12 @@ cp_gimplify_omp_for (tree *expr_p)
statement expressions within the INIT, COND, or INCR expressions. */
cont_block = begin_bc_block (bc_continue);
- /* FIXME tuples
+ /* FIXME tuples. */
+#if 0
gimplify_stmt (expr_p);
- */
+#else
+ gimple_unreachable ();
+#endif
OMP_FOR_BODY (for_stmt)
= finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
@@ -766,17 +769,9 @@ cp_genericize (tree fndecl)
relayout_decl (t);
}
- /* If we're a clone, the body is already GIMPLE. Find the original
- body, and set the gimple body for this function accordingly. */
+ /* If we're a clone, the body is already GIMPLE. */
if (DECL_CLONED_FUNCTION_P (fndecl))
- {
- tree orig = DECL_CLONED_FUNCTION (fndecl);
- gimple_seq seq = gimple_body (orig);
-
- gimple_set_body (fndecl, seq);
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
- return;
- }
+ return;
/* We do want to see every occurrence of the parms, so we can't just use
walk_tree's hash functionality. */
Index: ipa-inline.c
===================================================================
--- ipa-inline.c (revision 134164)
+++ ipa-inline.c (working copy)
@@ -210,7 +210,7 @@ cgraph_clone_inlined_nodes (struct cgrap
&& flag_unit_at_a_time)
{
gcc_assert (!e->callee->global.inlined_to);
- if (DECL_SAVED_TREE (e->callee->decl))
+ if (gimple_body (e->callee->decl))
overall_insns -= e->callee->global.insns, nfunctions_inlined++;
duplicate = false;
}
@@ -1329,7 +1329,7 @@ cgraph_decide_inlining_incrementally (st
}
continue;
}
- if (!DECL_SAVED_TREE (e->callee->decl) && !e->callee->inline_decl)
+ if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
{
if (dump_file)
{
@@ -1406,7 +1406,7 @@ cgraph_decide_inlining_incrementally (st
}
continue;
}
- if (!DECL_SAVED_TREE (e->callee->decl) && !e->callee->inline_decl)
+ if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
{
if (dump_file)
{
Index: gimple-iterator.c
===================================================================
--- gimple-iterator.c (revision 134164)
+++ gimple-iterator.c (working copy)
@@ -146,6 +146,9 @@ gsi_insert_seq_before_without_update (gi
{
gimple_seq_node first, last;
+ if (seq == NULL)
+ return;
+
/* Don't allow inserting a sequence into itself. */
gcc_assert (seq != i->seq);
@@ -254,6 +257,9 @@ gsi_insert_seq_after_without_update (gim
{
gimple_seq_node first, last;
+ if (seq == NULL)
+ return;
+
/* Don't allow inserting a sequence into itself. */
gcc_assert (seq != i->seq);
Index: tree-eh.c
===================================================================
--- tree-eh.c (revision 134164)
+++ tree-eh.c (working copy)
@@ -528,7 +528,7 @@ replace_goto_queue_1 (gimple stmt, struc
seq = find_goto_replacement (tf, temp);
if (seq)
{
- gsi_insert_seq_before (gsi, gimple_seq_deep_copy (seq), GSI_SAME_STMT);
+ gsi_insert_seq_before (gsi, gimple_seq_copy (seq), GSI_SAME_STMT);
gsi_remove (gsi, false);
return;
}
@@ -839,7 +839,7 @@ lower_try_finally_dup_block (gimple_seq
gimple region = NULL;
gimple_seq new_seq;
- new_seq = gimple_seq_deep_copy (seq);
+ new_seq = gimple_seq_copy (seq);
if (outer_state->tf)
region = outer_state->tf->try_finally_expr;
Index: tree-ssa-live.c
===================================================================
--- tree-ssa-live.c (revision 134164)
+++ tree-ssa-live.c (working copy)
@@ -402,19 +402,12 @@ static inline void mark_all_vars_used (t
/* Helper function for mark_all_vars_used, called via walk_tree. */
static tree
-mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
- void *data)
+mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
{
tree t = *tp;
- enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
- tree b;
if (TREE_CODE (t) == SSA_NAME)
t = SSA_NAME_VAR (t);
- if ((IS_EXPR_CODE_CLASS (c)
- || IS_GIMPLE_STMT_CODE_CLASS (c))
- && (b = TREE_BLOCK (t)) != NULL)
- TREE_USED (b) = true;
/* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other
fields that do not contain vars. */
@@ -582,6 +575,7 @@ remove_unused_locals (void)
bitmap global_unused_vars = NULL;
mark_scope_block_unused (DECL_INITIAL (current_function_decl));
+
/* Assume all locals are unused. */
FOR_EACH_REFERENCED_VAR (t, rvi)
var_ann (t)->used = false;
@@ -594,8 +588,16 @@ remove_unused_locals (void)
/* Walk the statements. */
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- for (i = 0; i < gimple_num_ops (gsi_stmt (gsi)); i++)
- mark_all_vars_used (gimple_op_ptr (gsi_stmt (gsi), i), NULL);
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree b = gimple_block (stmt);
+
+ if (b)
+ TREE_USED (b) = true;
+
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ mark_all_vars_used (gimple_op_ptr (gsi_stmt (gsi), i), NULL);
+ }
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
Index: tree-ssa-dce.c
===================================================================
--- tree-ssa-dce.c (revision 134164)
+++ tree-ssa-dce.c (working copy)
@@ -710,7 +710,7 @@ eliminate_unnecessary_stmts (void)
}
push_stmt_changes (gsi_stmt_ptr (&gsi));
- g = gimple_deep_copy (stmt);
+ g = gimple_copy (stmt);
gimple_call_set_lhs (g, NULL_TREE);
gsi_replace (&gsi, g, false);
maybe_clean_or_replace_eh_stmt (stmt, g);
Index: tree-nested.c
===================================================================
--- tree-nested.c (revision 134164)
+++ tree-nested.c (working copy)
@@ -1094,9 +1094,8 @@ convert_nonlocal_omp_clauses (tree *pcla
static tree
convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool
*handled_ops_p,
- void *data)
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree save_local_var_chain;
bitmap save_suppress;
@@ -1454,9 +1453,8 @@ convert_local_omp_clauses (tree *pclause
static tree
convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
- void *data)
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree save_local_var_chain;
bitmap save_suppress;
@@ -1545,9 +1543,8 @@ convert_local_reference_stmt (gimple_stm
static tree
convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
- void *data)
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info, *i;
tree label, new_label, target_context, x, field;
void **slot;
@@ -1617,9 +1614,8 @@ convert_nl_goto_reference (gimple_stmt_i
static tree
convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
- void *data)
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree label, new_label;
gimple_stmt_iterator tmp_gsi;
@@ -1737,9 +1733,8 @@ convert_tramp_reference_op (tree *tp, in
static tree
convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
- void *data)
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
gimple stmt = gsi_stmt (*gsi);
switch (gimple_code (stmt))
@@ -1772,9 +1767,9 @@ convert_tramp_reference_stmt (gimple_stm
is set up properly for the call. */
static tree
-convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
void *data)
+convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
+ struct walk_stmt_info *wi)
{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree decl, target_context;
char save_static_chain_added;
Index: tree-inline.c
===================================================================
--- tree-inline.c (revision 134164)
+++ tree-inline.c (working copy)
@@ -127,7 +127,6 @@ eni_weights eni_time_weights;
/* Prototypes. */
static tree declare_return_variable (copy_body_data *, tree, tree, tree *);
-static tree copy_generic_body (copy_body_data *);
static bool inlinable_function_p (tree);
static void remap_block (tree *, copy_body_data *);
static tree remap_decls (tree, copy_body_data *);
@@ -142,6 +141,7 @@ static tree copy_decl_to_var (tree, copy
static tree copy_result_decl_to_var (tree, copy_body_data *);
static tree copy_decl_no_change (tree, copy_body_data *);
static tree copy_decl_maybe_to_var (tree, copy_body_data *);
+static gimple remap_gimple_stmt (gimple, copy_body_data *);
/* Insert a tree->tree mapping for ID. Despite the name suggests
that the trees should be variables, it is used for more than that. */
@@ -448,9 +448,9 @@ remap_decls (tree decls, copy_body_data
{
tree new_var;
- /* We can not chain the local static declarations into the
unexpanded_var_list
- as we can't duplicate them or break one decl rule. Go ahead and link
- them into unexpanded_var_list. */
+ /* We cannot chain the local static declarations into the
+ unexpanded_var_list as we can't duplicate them or break one
+ decl rule. Go ahead and link them into unexpanded_var_list. */
if (!auto_var_in_fn_p (old_var, id->src_fn)
&& !DECL_EXTERNAL (old_var))
{
@@ -462,7 +462,7 @@ remap_decls (tree decls, copy_body_data
/* Remap the variable. */
new_var = remap_decl (old_var, id);
- /* If we didn't remap this variable, so we can't mess with its
+ /* If we didn't remap this variable, we can't mess with its
TREE_CHAIN. If we remapped this variable to the return slot, it's
already declared somewhere else, so don't declare it here. */
if (!new_var || new_var == id->retvar)
@@ -559,6 +559,56 @@ copy_bind_expr (tree *tp, int *walk_subt
}
+/* Create a new gimple_seq by remapping all the statements in BODY
+ using the inlining information in ID. */
+
+static gimple_seq
+remap_gimple_seq (gimple_seq body, copy_body_data *id)
+{
+ gimple_stmt_iterator si;
+ gimple_seq new_body = NULL;
+
+ for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple new_stmt = remap_gimple_stmt (gsi_stmt (si), id);
+ gimple_seq_add_stmt (&new_body, new_stmt);
+ }
+
+ return new_body;
+}
+
+
+/* Copy a GIMPLE_BIND statement STMT, remapping all the symbols in its
+ block using the mapping information in ID. */
+
+static gimple
+copy_gimple_bind (gimple stmt, copy_body_data *id)
+{
+ gimple new_bind;
+ tree new_block, new_vars;
+ gimple_seq body, new_body;
+
+ /* Copy the statement. Note that we purposely don't use copy_stmt
+ here because we need to remap statements as we copy. */
+ body = gimple_bind_body (stmt);
+ new_body = remap_gimple_seq (body, id);
+
+ new_block = gimple_bind_block (stmt);
+ if (new_block)
+ remap_block (&new_block, id);
+
+ /* This will remap a lot of the same decls again, but this should be
+ harmless. */
+ new_vars = gimple_bind_vars (stmt);
+ if (new_vars)
+ new_vars = remap_decls (new_vars, id);
+
+ new_bind = gimple_build_bind (new_vars, new_body, new_block);
+
+ return new_bind;
+}
+
+
/* Remap the GIMPLE operand pointed to by *TP. DATA is really a
'struct walk_stmt_info *'. DATA->INFO is a 'copy_body_data *'.
WALK_SUBTREES is used to indicate walk_gimple_op whether to keep
@@ -985,7 +1035,7 @@ copy_tree_body_r (tree *tp, int *walk_su
static gimple
remap_gimple_stmt (gimple stmt, copy_body_data *id)
{
- gimple copy;
+ gimple copy = NULL;
struct walk_stmt_info wi;
tree new_block;
@@ -1005,47 +1055,89 @@ remap_gimple_stmt (gimple stmt, copy_bod
/* If we're returning something, just turn that into an
assignment into the equivalent of the original RESULT_DECL.
- If RETVAL is just the result decl, the result decl has
+ If RETVAL is just the result decl, the result decl has
already been set (e.g. a recent "foo (&result_decl, ...)");
just toss the entire GIMPLE_RETURN. */
if (retval && TREE_CODE (retval) != RESULT_DECL)
- {
- gimple s = gimple_build_assign (id->retvar, retval);
- return remap_gimple_stmt (s, id);
- }
+ copy = gimple_build_assign (id->retvar, retval);
else
return gimple_build_nop ();
}
- else if (gimple_code (stmt) == GIMPLE_BIND)
- /* FIXME tuples: Should be removed?
- Was copy_bind_expr (tp, walk_subtrees, id); */
- gcc_unreachable ();
-
- /* Here we handle statements that are not completely rewritten.
- First we detect some inlining-induced bogosities for
- discarding. */
- if (gimple_assign_copy_p (stmt)
- && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt)
- && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn))
+ else if (gimple_has_substatements (stmt))
{
- /* Some assignments VAR = VAR; don't generate any rtl code
- and thus don't count as variable modification. Avoid
- keeping bogosities like 0 = 0. */
- tree decl = gimple_assign_lhs (stmt), value;
- tree *n;
+ gimple_seq s1, s2;
- n = (tree *) pointer_map_contains (id->decl_map, decl);
- if (n)
+ /* When cloning bodies from the C++ front end, we will be handed bodies
+ in High GIMPLE form. Handle here all the High GIMPLE statements that
+ have embedded statements. */
+ switch (gimple_code (stmt))
{
- value = *n;
- STRIP_TYPE_NOPS (value);
- if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
- return gimple_build_nop ();
+ case GIMPLE_BIND:
+ copy = copy_gimple_bind (stmt, id);
+ break;
+
+ case GIMPLE_CATCH:
+ s1 = remap_gimple_seq (gimple_catch_handler (stmt), id);
+ copy = gimple_build_catch (gimple_catch_types (stmt), s1);
+ break;
+
+ case GIMPLE_EH_FILTER:
+ s1 = remap_gimple_seq (gimple_eh_filter_failure (stmt), id);
+ copy = gimple_build_eh_filter (gimple_eh_filter_types (stmt), s1);
+ break;
+
+ case GIMPLE_TRY:
+ s1 = remap_gimple_seq (gimple_try_eval (stmt), id);
+ s2 = remap_gimple_seq (gimple_try_cleanup (stmt), id);
+ copy = gimple_build_try (s1, s2, gimple_try_kind (stmt));
+ break;
+
+ case GIMPLE_WITH_CLEANUP_EXPR:
+ s1 = remap_gimple_seq (gimple_wce_cleanup (stmt), id);
+ copy = gimple_build_wce (s1);
+ break;
+
+ /* FIXME tuples. */
+ case GIMPLE_OMP_FOR:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_SINGLE:
+ default:
+ gcc_unreachable ();
}
}
+ else
+ {
+ if (gimple_assign_copy_p (stmt)
+ && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt)
+ && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn))
+ {
+ /* Here we handle statements that are not completely rewritten.
+ First we detect some inlining-induced bogosities for
+ discarding. */
- /* Create a new deep copy of the statement. */
- copy = gimple_deep_copy (stmt);
+ /* Some assignments VAR = VAR; don't generate any rtl code
+ and thus don't count as variable modification. Avoid
+ keeping bogosities like 0 = 0. */
+ tree decl = gimple_assign_lhs (stmt), value;
+ tree *n;
+
+ n = (tree *) pointer_map_contains (id->decl_map, decl);
+ if (n)
+ {
+ value = *n;
+ STRIP_TYPE_NOPS (value);
+ if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
+ return gimple_build_nop ();
+ }
+ }
+
+ /* Create a new deep copy of the statement. */
+ copy = gimple_copy (stmt);
+ }
/* If STMT has a block defined, map it to the newly constructed
block. When inlining we want statements without a block to
@@ -1115,12 +1207,13 @@ copy_bb (copy_body_data *id, basic_block
|| id->regimplify)
{
tree new_rhs;
- new_rhs = force_gimple_operand_gsi (&gsi, gimple_assign_rhs1 (stmt),
+ new_rhs = force_gimple_operand_gsi (©_gsi,
+ gimple_assign_rhs1 (stmt),
true, NULL, true, GSI_SAME_STMT);
gimple_assign_set_rhs1 (stmt, new_rhs);
}
else if (id->regimplify)
- gimple_regimplify_operands (stmt, &gsi);
+ gimple_regimplify_operands (stmt, ©_gsi);
gsi_insert_after (©_gsi, stmt, GSI_NEW_STMT);
@@ -1623,7 +1716,6 @@ copy_cfg_body (copy_body_data * id, gcov
cfun_to_copy = id->src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
-
ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = entry_block_map;
EXIT_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = exit_block_map;
entry_block_map->aux = ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy);
@@ -1646,17 +1738,21 @@ copy_cfg_body (copy_body_data * id, gcov
}
last = last_basic_block;
+
/* Now that we've duplicated the blocks, duplicate their edges. */
FOR_ALL_BB_FN (bb, cfun_to_copy)
copy_edges_for_bb (bb, count_scale, exit_block_map);
+
if (gimple_in_ssa_p (cfun))
FOR_ALL_BB_FN (bb, cfun_to_copy)
copy_phis_for_bb (bb, id);
+
FOR_ALL_BB_FN (bb, cfun_to_copy)
{
((basic_block)bb->aux)->aux = NULL;
bb->aux = NULL;
}
+
/* Zero out AUX fields of newly created block during EH edge
insertion. */
for (; last < last_basic_block; last++)
@@ -1667,22 +1763,6 @@ copy_cfg_body (copy_body_data * id, gcov
return new_fndecl;
}
-/* Make a copy of the GENERIC body of FN so that it can be inserted
- inline in another function. */
-
-static tree
-copy_generic_body (copy_body_data *id)
-{
- tree body;
- tree fndecl = id->src_fn;
-
- gcc_assert (!gimple_body (fndecl));
- body = DECL_SAVED_TREE (fndecl);
- walk_tree (&body, copy_tree_body_r, id, NULL);
-
- return body;
-}
-
/* Make a copy of the GIMPLE body of function ID->SRC_FN. Profile and
coverage count are in FREQUENCY and COUNT. ENTRY_BLOCK_MAP and
EXIT_BLOCK_MAP are the entry and exit blocks to the region. */
@@ -2204,10 +2284,9 @@ inline_forbidden_p_op (tree *nodep, int
static tree
inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
- void *wip)
+ struct walk_stmt_info *wip)
{
- struct walk_stmt_info wi = *(struct walk_stmt_info *) wip;
- tree fn = (tree) wi.info;
+ tree fn = (tree) wip->info;
tree t;
gimple stmt = gsi_stmt (*gsi);
@@ -2895,7 +2974,9 @@ count_insns_seq (gimple_seq seq, eni_wei
return n;
}
+
/* Install new lexical TREE_BLOCK underneath 'current_block'. */
+
static void
add_lexical_block (tree current_block, tree new_block)
{
@@ -3401,14 +3482,18 @@ optimize_inline_calls (tree fn)
}
-/* FN is a function that has a complete body, and CLONE is a function
- whose body is to be set to a copy of FN, mapping argument
- declarations according to the ARG_MAP splay_tree. */
+/* FN is a function in High GIMPLE form that has a complete body and no
+ CFG. CLONE is a function whose body is to be set to a copy of FN,
+ mapping argument declarations according to the ARG_MAP splay_tree. */
void
clone_body (tree clone, tree fn, void *arg_map)
{
copy_body_data id;
+ gimple_seq new_body;
+
+ /* FN must already be in GIMPLE form. */
+ gcc_assert (gimple_body (fn));
/* Clone the body, as if we were making an inline call. But, remap
the parameters in the callee to the parameters of caller. */
@@ -3427,11 +3512,9 @@ clone_body (tree clone, tree fn, void *a
/* We're not inside any EH region. */
id.eh_region = -1;
- gcc_unreachable ();
-
/* Actually copy the body. */
- /* FIXME tuples. DECL_SAVED_TREE needs to be changed to gimple_body. */
- append_to_statement_list_force (copy_generic_body (&id),
&DECL_SAVED_TREE (clone));
+ new_body = remap_gimple_seq (gimple_body (fn), &id);
+ gimple_set_body (clone, new_body);
}
/* Passed to walk_tree. Copies the node pointed to, if appropriate. */
Index: c-common.c
===================================================================
--- c-common.c (revision 134164)
+++ c-common.c (working copy)
@@ -6749,7 +6749,6 @@ c_warn_unused_result (gimple_seq seq)
/* Look past pointer-to-function to the function type itself. */
ftype = TREE_TYPE (ftype);
}
- gcc_assert (TREE_CODE (ftype) == FUNCTION_TYPE);
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{
Index: gimple.c
===================================================================
--- gimple.c (revision 134164)
+++ gimple.c (working copy)
@@ -1150,7 +1150,7 @@ empty_body_p (gimple_seq body)
/* Perform a deep copy of sequence SRC and return the result. */
gimple_seq
-gimple_seq_deep_copy (gimple_seq src)
+gimple_seq_copy (gimple_seq src)
{
gimple_stmt_iterator gsi;
gimple_seq new = gimple_seq_alloc ();
@@ -1158,7 +1158,7 @@ gimple_seq_deep_copy (gimple_seq src)
for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
{
- stmt = gimple_deep_copy (gsi_stmt (gsi));
+ stmt = gimple_copy (gsi_stmt (gsi));
gimple_seq_add_stmt (&new, stmt);
}
@@ -1586,7 +1586,6 @@ walk_gimple_stmt (gimple_stmt_iterator *
return wi->callback_result;
/* FALL THROUGH. */
-
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
@@ -1608,6 +1607,7 @@ walk_gimple_stmt (gimple_stmt_iterator *
break;
default:
+ gcc_assert (!gimple_has_substatements (stmt));
break;
}
@@ -1904,33 +1904,119 @@ gimple_set_lhs (gimple stmt, tree lhs)
}
-/* Helper for gimple_deep_copy and gimple_shallow_copy. If
- IS_DEEP_COPY is true, return a deep copy of STMT (all the operands
- are copied with unshare_expr). Otherwise, return a shallow copy of
- STMT (all the operands in the new copy point to the operands in the
- original). The DEF, USE, VDEF and VUSE operand arrays in the new
- copy are set to NULL. */
+/* Return a deep copy of statement STMT. All the operands from STMT
+ are reallocated and copied using unshare_expr. The DEF, USE, VDEF
+ and VUSE operand arrays are set to empty in the new copy. */
-static inline gimple
-gimple_copy_1 (gimple stmt, bool is_deep_copy)
+gimple
+gimple_copy (gimple stmt)
{
enum gimple_code code = gimple_code (stmt);
size_t num_ops = gimple_num_ops (stmt);
gimple copy = gimple_alloc (code);
unsigned i;
+ /* Shallow copy all the fields from STMT. */
memcpy (copy, stmt, gimple_size (code));
+
+ /* If STMT has sub-statements, deep-copy them as well. */
+ if (gimple_has_substatements (stmt))
+ {
+ gimple_seq new_seq;
+ tree t;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_BIND:
+ new_seq = gimple_seq_copy (gimple_bind_body (stmt));
+ gimple_bind_set_body (copy, new_seq);
+ gimple_bind_set_vars (copy, unshare_expr (gimple_bind_vars (stmt)));
+ gimple_bind_set_block (copy, unshare_expr (gimple_bind_block (stmt)));
+ break;
+
+ case GIMPLE_CATCH:
+ new_seq = gimple_seq_copy (gimple_catch_handler (stmt));
+ gimple_catch_set_handler (copy, new_seq);
+ t = unshare_expr (gimple_catch_types (stmt));
+ gimple_catch_set_types (copy, t);
+ break;
+
+ case GIMPLE_EH_FILTER:
+ new_seq = gimple_seq_copy (gimple_eh_filter_failure (stmt));
+ gimple_eh_filter_set_failure (copy, new_seq);
+ t = unshare_expr (gimple_eh_filter_types (stmt));
+ gimple_eh_filter_set_types (copy, t);
+ break;
+
+ case GIMPLE_TRY:
+ new_seq = gimple_seq_copy (gimple_try_eval (stmt));
+ gimple_try_set_eval (copy, new_seq);
+ new_seq = gimple_seq_copy (gimple_try_cleanup (stmt));
+ gimple_try_set_cleanup (copy, new_seq);
+ break;
+
+ case GIMPLE_OMP_FOR:
+ new_seq = gimple_seq_copy (gimple_omp_for_pre_body (stmt));
+ gimple_omp_for_set_pre_body (copy, new_seq);
+ t = unshare_expr (gimple_omp_for_clauses (stmt));
+ gimple_omp_for_set_clauses (copy, t);
+ t = unshare_expr (gimple_omp_for_initial (stmt));
+ gimple_omp_for_set_initial (copy, t);
+ t = unshare_expr (gimple_omp_for_final (stmt));
+ gimple_omp_for_set_final (copy, t);
+ t = unshare_expr (gimple_omp_for_incr (stmt));
+ gimple_omp_for_set_incr (copy, t);
+ goto copy_omp_body;
+
+ case GIMPLE_OMP_PARALLEL:
+ t = unshare_expr (gimple_omp_parallel_clauses (stmt));
+ gimple_omp_parallel_set_clauses (copy, t);
+ t = unshare_expr (gimple_omp_parallel_child_fn (stmt));
+ gimple_omp_parallel_set_child_fn (copy, t);
+ t = unshare_expr (gimple_omp_parallel_data_arg (stmt));
+ gimple_omp_parallel_set_data_arg (copy, t);
+ goto copy_omp_body;
+
+ case GIMPLE_OMP_CRITICAL:
+ t = unshare_expr (gimple_omp_critical_name (stmt));
+ gimple_omp_critical_set_name (copy, t);
+ goto copy_omp_body;
+
+ case GIMPLE_OMP_SECTIONS:
+ t = unshare_expr (gimple_omp_sections_clauses (stmt));
+ gimple_omp_sections_set_clauses (copy, t);
+ t = unshare_expr (gimple_omp_sections_control (stmt));
+ gimple_omp_sections_set_control (copy, t);
+ /* FALLTHRU */
+
+ case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ copy_omp_body:
+ new_seq = gimple_seq_copy (gimple_omp_body (stmt));
+ gimple_omp_set_body (copy, new_seq);
+ break;
+
+ case GIMPLE_WITH_CLEANUP_EXPR:
+ new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt));
+ gimple_wce_set_cleanup (copy, new_seq);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ /* Make copy of operands. */
if (num_ops > 0)
{
gimple_alloc_ops (copy, num_ops);
- if (is_deep_copy)
- for (i = 0; i < num_ops; i++)
- gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
- else
- for (i = 0; i < num_ops; i++)
- gimple_set_op (copy, i, gimple_op (stmt, i));
+ for (i = 0; i < num_ops; i++)
+ gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
}
+ /* Clear out SSA operand vectors on COPY. */
if (gimple_has_ops (stmt))
{
gimple_set_def_ops (copy, NULL);
@@ -1950,33 +2036,6 @@ gimple_copy_1 (gimple stmt, bool is_deep
}
-/* Return a shallow copy of statement STMT. The operands in the new
- statement will point to the original operands in STMT. The DEF,
- USE, VDEF and VUSE operand arrays are set to empty in the new copy.
-
- NOTE: The copy returned by this function is not suitable for
- insertion into the IL, as it shares the operands with the original
- statement. It is used by transformations like inlining which will
- remap operands from one function to another. */
-
-gimple
-gimple_shallow_copy (gimple stmt)
-{
- return gimple_copy_1 (stmt, false);
-}
-
-
-/* Return a deep copy of statement STMT. All the operands from STMT
- are reallocated and copied using unshare_expr. The DEF, USE, VDEF
- and VUSE operand arrays are set to empty in the new copy. */
-
-gimple
-gimple_deep_copy (gimple stmt)
-{
- return gimple_copy_1 (stmt, true);
-}
-
-
/* Return a copy of statement STMT. The copy should not retain any use
information for the variables that appear within it. */
/* FIXME tuples. The charter of this function is unclear. It was
Index: gimple.h
===================================================================
--- gimple.h (revision 134164)
+++ gimple.h (working copy)
@@ -340,6 +340,7 @@ struct gimple_statement_eh_filter GTY(()
/* Filter types. */
tree types;
+
/* Failure actions. */
gimple_seq failure;
};
@@ -423,6 +424,7 @@ struct gimple_statement_asm GTY(())
struct gimple_statement_omp_critical GTY(())
{
struct gimple_statement_omp omp;
+
/* Critical section name. */
tree name;
};
@@ -434,14 +436,19 @@ struct gimple_statement_omp_for GTY(())
{
struct gimple_statement_omp omp;
tree clauses;
+
/* Index variable. */
tree index;
+
/* Initial value. */
tree initial;
+
/* Final value. */
tree final;
+
/* Increment. */
tree incr;
+
/* Pre-body evaluated before the loop body begins. */
gimple_seq pre_body;
};
@@ -452,8 +459,13 @@ struct gimple_statement_omp_for GTY(())
struct gimple_statement_omp_parallel GTY(())
{
struct gimple_statement_omp omp;
+
+ /* Clauses. */
tree clauses;
+
+ /* Child function holding the body of the parallel region. */
tree child_fn;
+
/* Shared data argument. */
tree data_arg;
};
@@ -604,7 +616,7 @@ gimple_seq gimple_body (tree);
gimple_seq gimple_seq_alloc (void);
void gimple_seq_free (gimple_seq);
void gimple_seq_add_seq (gimple_seq *, gimple_seq);
-gimple_seq gimple_seq_deep_copy (gimple_seq);
+gimple_seq gimple_seq_copy (gimple_seq);
int gimple_call_flags (gimple);
bool gimple_assign_copy_p (gimple);
bool gimple_assign_single_p (gimple);
@@ -615,8 +627,7 @@ void gimple_assign_set_rhs_from_tree (gi
void gimple_assign_set_rhs_with_ops (gimple, enum tree_code, tree, tree);
tree gimple_get_lhs (gimple);
void gimple_set_lhs (gimple, tree);
-gimple gimple_deep_copy (gimple);
-gimple gimple_shallow_copy (gimple);
+gimple gimple_copy (gimple);
gimple gimple_copy_no_def_use (gimple);
bool is_gimple_operand (const_tree);
void gimple_set_modified (gimple, bool);
@@ -671,6 +682,34 @@ gimple_subcode (const_gimple g)
}
+/* Return true if statement G has sub-statements. This is only true for
+ High GIMPLE statements. */
+
+static inline bool
+gimple_has_substatements (gimple g)
+{
+ switch (gimple_code (g))
+ {
+ case GIMPLE_BIND:
+ case GIMPLE_CATCH:
+ case GIMPLE_EH_FILTER:
+ case GIMPLE_TRY:
+ case GIMPLE_OMP_FOR:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_SINGLE:
+ case GIMPLE_WITH_CLEANUP_EXPR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
/* Return the basic block holding statement G. */
static inline struct basic_block_def *
@@ -3352,15 +3391,6 @@ void gsi_commit_one_edge_insert (edge, b
void gsi_commit_edge_inserts (void);
-/* Callback for walk_gimple_stmt. Called for every statement found
- during traversal. The first argument points to the statement to
- walk. The second argument is a flag that the callback sets to
- 'false' if it needs walk_gimple_stmt to also traverse the operands
- and sub-statements (for statements with associated bodies like
- GIMPLE_BIND). The third argument is an anonymous pointer to data
- to be used by the callback. */
-typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *, void *);
-
/* Convenience routines to walk all statements of a gimple function.
Note that this is useful exclusively before the code is converted
into SSA form. Once the program is in SSA form, the standard
@@ -3410,6 +3440,16 @@ struct walk_stmt_info
tree callback_result;
};
+/* Callback for walk_gimple_stmt. Called for every statement found
+ during traversal. The first argument points to the statement to
+ walk. The second argument is a flag that the callback sets to
+ 'true' if it the callback handled all the operands and
+ sub-statements of the statement (the default value of this flag is
+ 'false'). The third argument is an anonymous pointer to data
+ to be used by the callback. */
+typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *,
+ struct walk_stmt_info *);
+
gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
struct walk_stmt_info *);
tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn, walk_tree_fn,
Index: tree-cfg.c
===================================================================
--- tree-cfg.c (revision 134164)
+++ tree-cfg.c (working copy)
@@ -4711,7 +4711,7 @@ gimple_duplicate_bb (basic_block bb)
/* Create a new copy of STMT and duplicate STMT's virtual
operands. */
- copy = gimple_deep_copy (stmt);
+ copy = gimple_copy (stmt);
gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
copy_virtual_operands (copy, stmt);
region = lookup_stmt_eh_region (stmt);