This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples]: Fix function unnesting and enable GIMPLE lowering
- From: "Diego Novillo" <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: "Aldy Hernandez" <aldyh at redhat dot com>, "Christopher Matthews" <chrismatthews at google dot com>, "Ben Elliston" <bje at au1 dot ibm dot com>
- Date: Sat, 25 Aug 2007 17:56:07 -0400
- Subject: [tuples]: Fix function unnesting and enable GIMPLE lowering
This patch is actually two different changes, but unfortunately one
depends on the other so I had to commit them as one.
The first part enables GIMPLE lowering and fixes the generation of a
new GIMPLE body in gimplify_function_tree. The call to gimplify_body
now returns a GIMPLE_BIND with the whole function body in GIMPLE form.
This is then inserted in a gimple_seq which is then stored as the
body for the function.
So, when we get to lowering the function is always a GIMPLE sequence
that contains exactly one statement: a GIMPLE_BIND with all the
statements in the function.
The second part adapts the file tree-nested.c to work with GIMPLE
tuples. The major refactoring done here was the splitting of most
callback routines into two functions: one that handles statements and
the other handles operands. Since statements are no longer of type
'tree', but of type 'gimple', this means that we can no longer
interchangeably treat a 'tree' expression as a statement or operand.
The changes are fairly intrusive, but mechanical. With this we can
now enable GIMPLE lowering and can process all of compile.exp into low
GIMPLE.
I tried to enable building the CFG but we fail fairly early, and I
didn't want to pollute the patch much more. Aldy, I'll look at
enabling the CFG early next week. I noticed a whole bunch of new
warnings with your patch, were those the warnings you said you were
looking at?
Chris, I found some more cases where we are missing type casts, that
will probably fail your conversion of the type verifier.
testsuite/gcc.c-torture/compile/20030716-1.c should be a simple enough
test where this happens. We are dropping a cast from unsigned long
int.
Ben, I had to disable a chunk of OMP lowering code. You can find it
by looking for 'FIXME tuples' in omp-low.c. Sorry :)
Tested on compile.exp and libgcc. Committed to branch.
2007-08-25 Diego Novillo <dnovillo@google.com>
* tree.c (build_gimple_modify_stmt_stat): Add depecrate note.
* omp-low.c (scan_omp_1): Disable.
(scan_omp): Likewise.
(lower_omp_for): Likewise.
(lower_omp_parallel): Likewise.
(lower_omp_1): Likewise.
(lower_omp): Likewise.
(diagnose_sb_1): Likewise.
(diagnose_sb_2): Likewise.
(diagnose_omp_structured_block_errors): Likewise.
* tree-gimple.h (_TREE_GIMPLE_H): Rename from _TREE_SIMPLE_H.
(gimplify_body): Return the new GIMPLE body.
(struct walk_stmt_info): Move to gimple.h.
* gimple-low.c (lower_function_body): Assert that the function
body is a single GIMPLE_BIND statement.
Create a new gimple sequence to lower the existing body.
Replace the function body with the new lowered sequence.
(pass_lower_cf): Enable GIMPLE lowering.
(lower_omp_directive): Disable.
(lower_stmt): Do not call lower_omp_directive.
(gimple_stmt_may_fallthru): Factor out of ...
(gimple_seq_may_fallthru): ... here.
* gimple-iterator.c (gsi_replace): New.
* gimple-iterator.h (gsi_replace): Declare.
* gimple-pretty-print.c: Do not include gimple-iterator.h
* gimplify.c (gimplify_asm_expr): Tidy.
Store the whole TREE_LIST node in the inputs and outputs vectors.
(gimple_push_cleanup): Disable completely.
(gimplify_body): Return a GIMPLE_BIND holding the gimplified
body.
Update all users.
(gimplify_function_tree): Create a GIMPLE sequence to hold
the gimplified body.
* tree-flow.h (gimple_stmt_may_fallthru): Declare.
* Makefile.in (GIMPLE_H): Add gimple-iterator.h.
2007-08-25 Diego Novillo <dnovillo@google.com>
* tree-nested.c: Re-implement to use GIMPLE tuples.
(init_tmp_var_with_call): New.
(init_tmp_var): Adapt to GIMPLE tuples.
(save_tmp_var): Likewise.
(convert_nl_goto_receiver): Likewise.
(finalize_nesting_tree_1): Likewise.
(gsi_gimplify_val): Likewise.
Rename from tsi_gimplify_val. Update all users.
(walk_asm_expr): Remove.
(walk_stmts): Remove.
(walk_body): Call walk_gimple_seq.
Add new argument callback_op. Update all users.
(walk_function): Add argument callback_op. Update all users.
(convert_nonlocal_reference_op): Rename from
convert_nonlocal_omp_reference. Update all users.
(convert_nonlocal_reference_stmt): New. Handle GIMPLE
statements that used to be tree nodes.
(convert_local_reference_op): Rename from
convert_local_reference. Update all users.
(convert_local_reference_stmt): New. Handle GIMPLE statements
that used to be tree nodes.
(convert_nl_goto_reference): Convert to walk_stmt_fn callback.
Update all users.
(convert_tramp_reference_op): Rename from
convert_tramp_reference. Update all users.
(convert_tramp_reference_stmt): New. Handle GIMPLE statements
that used to be tree nodes.
(convert_gimple_call): Rename from convert_call_expr. Convert
to be a walk_stmt_fn callback.
* gimple.c (gimple_seq_add): Rename from gimple_add. Update
all users.
(walk_gimple_seq): Rename from walk_seq_ops. Update all
users.
(walk_gimple_stmt): Rename from walk_tuple_ops. Update all
users.
Use two callback functions one for statements and another for
operands. If either is NULL do not invoke it.
Allow callbacks to replace operands.
(WALKIT): Remove.
(walk_gimple_asm): New.
* gimple.h: Include ggc.h
(gimple_seq_alloc): New. Use everywhere a GIMPLE sequence is
allocated.
(gimple_op_ptr): New.
(gimple_call_arg_ptr): New.
(gimple_catch_types_ptr): New.
(gimple_eh_filter_types_ptr): New.
(gimple_omp_critical_name_ptr): New.
(gimple_omp_for_clauses_ptr): New.
(gimple_omp_for_index_ptr): New.
(gimple_omp_for_initial_ptr): New.
(gimple_omp_for_final_ptr): New.
(gimple_omp_for_incr_ptr): New.
(gimple_omp_parallel_clauses_ptr): New.
(gimple_omp_parallel_child_fn_ptr): New.
(gimple_omp_parallel_data_arg_ptr): New.
(gimple_omp_single_clauses_ptr): New.
(gimple_omp_sections_clauses_ptr): New.
(walk_stmt_fn): New type.
(struct walk_stmt_info): Move from tree-gimple.h.
Rename field callback to callback_op.
Add new field callback_stmt.
Replace field tsi with gsi of type gimple_stmt_iterator.
(walk_gimple_seq): Declare.
(walk_gimple_stmt): Declare.
* tree-cfg.c (execute_build_cfg): Do not call
build_gimple_cfg.
(pass_build_cfg): Enable.
Disable TODO_verify_stmts and TODO_cleanup_cfg.
Index: tree.c
===================================================================
--- tree.c (revision 127800)
+++ tree.c (working copy)
@@ -3151,6 +3151,8 @@ build2_stat (enum tree_code code, tree t
tree
build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL)
{
+ /* FIXME tuples. Deprecate this. There should not be any calls to this
+ routine. Use build_gimple_assign instead. */
tree t;
t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT);
Index: omp-low.c
===================================================================
--- omp-low.c (revision 127800)
+++ omp-low.c (working copy)
@@ -1337,6 +1337,12 @@ check_omp_nesting_restrictions (tree t,
static tree
scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
{
+ /* FIXME tuples. This routine needs to be split up into two. One
+ dealing with statements, to be used as a CALLBACK_STMT and the
+ other dealing with operands, to be used as a CALLBACK_OP. Since
+ statements and operands are now of different types, we need the
+ two different callbacks. */
+#if 0
struct walk_stmt_info *wi = data;
omp_context *ctx = wi->info;
tree t = *tp;
@@ -1404,6 +1410,7 @@ scan_omp_1 (tree *tp, int *walk_subtrees
}
return NULL_TREE;
+#endif
}
@@ -1417,6 +1424,9 @@ scan_omp (tree *stmt_p, omp_context *ctx
location_t saved_location;
struct walk_stmt_info wi;
+ /* FIXME tuples. Convert to use the new walk_gimple_seq/walk_gimple_stmt
+ routines. */
+#if 0
memset (&wi, 0, sizeof (wi));
wi.callback = scan_omp_1;
wi.info = ctx;
@@ -1426,6 +1436,7 @@ scan_omp (tree *stmt_p, omp_context *ctx
saved_location = input_location;
walk_stmts (&wi, stmt_p);
input_location = saved_location;
+#endif
}
/* Re-gimplification and code generation routines. */
@@ -4076,6 +4087,12 @@ lower_omp_for (tree *stmt_p, omp_context
static tree
check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
{
+ /* FIXME tuples. This routine needs to be split up into two. One
+ dealing with statements, to be used as a CALLBACK_STMT and the
+ other dealing with operands, to be used as a CALLBACK_OP. Since
+ statements and operands are now of different types, we need the
+ two different callbacks. */
+#if 0
struct walk_stmt_info *wi = data;
int *info = wi->info;
@@ -4091,6 +4108,7 @@ check_combined_parallel (tree *tp, int *
break;
}
return NULL;
+#endif
}
/* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
@@ -4114,11 +4132,15 @@ lower_omp_parallel (tree *stmt_p, omp_co
struct walk_stmt_info wi;
int ws_num = 0;
+ /* FIXME tuples. This needs to be changed to use the new
+ walk_gimple_stmt routine. */
+#if 0
memset (&wi, 0, sizeof (wi));
wi.callback = check_combined_parallel;
wi.info = &ws_num;
wi.val_only = true;
walk_stmts (&wi, &par_bind);
+#endif
if (ws_num == 1)
OMP_PARALLEL_COMBINED (stmt) = 1;
}
@@ -4200,7 +4222,8 @@ lower_regimplify (tree *tp, struct walk_
gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
gcc_assert (gs == GS_ALL_DONE);
- /* FIXME tuples. Need a gimple_seq_insert_before. WI->TSI must be a GS_SEQ. */
+ /* FIXME tuples. Need a gimple_seq_insert_before. WI->TSI must be
+ a GS_SEQ. */
#if 0
if (!gimple_seq_empty_p (&pre))
tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
@@ -4246,6 +4269,12 @@ save_tmp_var (tree exp, tree_stmt_iterat
static tree
lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
{
+ /* FIXME tuples. This routine needs to be split up into two. One
+ dealing with statements, to be used as a CALLBACK_STMT and the
+ other dealing with operands, to be used as a CALLBACK_OP. Since
+ statements and operands are now of different types, we need the
+ two different callbacks. */
+#if 0
struct walk_stmt_info *wi = data;
omp_context *ctx = wi->info;
tree t = *tp;
@@ -4349,11 +4378,14 @@ lower_omp_1 (tree *tp, int *walk_subtree
}
return NULL_TREE;
+#endif
}
static void
lower_omp (tree *stmt_p, omp_context *ctx)
{
+ /* FIXME tuples. This needs to use the new walk_gimple_seq routine. */
+#if 0
struct walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
@@ -4363,6 +4395,7 @@ lower_omp (tree *stmt_p, omp_context *ct
wi.want_locations = true;
walk_stmts (&wi, stmt_p);
+#endif
}
/* Main entry point. */
@@ -4461,6 +4494,12 @@ diagnose_sb_0 (tree *stmt_p, tree branch
static tree
diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
{
+ /* FIXME tuples. This routine needs to be split up into two. One
+ dealing with statements, to be used as a CALLBACK_STMT and the
+ other dealing with operands, to be used as a CALLBACK_OP. Since
+ statements and operands are now of different types, we need the
+ two different callbacks. */
+#if 0
struct walk_stmt_info *wi = data;
tree context = (tree) wi->info;
tree inner_context;
@@ -4507,6 +4546,7 @@ diagnose_sb_1 (tree *tp, int *walk_subtr
}
return NULL_TREE;
+#endif
}
/* Pass 2: Check each branch and see if its context differs from that of
@@ -4515,6 +4555,12 @@ diagnose_sb_1 (tree *tp, int *walk_subtr
static tree
diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
{
+ /* FIXME tuples. This routine needs to be split up into two. One
+ dealing with statements, to be used as a CALLBACK_STMT and the
+ other dealing with operands, to be used as a CALLBACK_OP. Since
+ statements and operands are now of different types, we need the
+ two different callbacks. */
+#if 0
struct walk_stmt_info *wi = data;
tree context = (tree) wi->info;
splay_tree_node n;
@@ -4582,6 +4628,7 @@ diagnose_sb_2 (tree *tp, int *walk_subtr
}
return NULL_TREE;
+#endif
}
void
@@ -4594,15 +4641,19 @@ diagnose_omp_structured_block_errors (tr
all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+ /* FIXME tuples. Convert to use the new walk_gimple_seq/walk_gimple_stmt
+ routines. */
+#if 0
memset (&wi, 0, sizeof (wi));
wi.callback = diagnose_sb_1;
walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
memset (&wi, 0, sizeof (wi));
- wi.callback = diagnose_sb_2;
+ wi.callback_stmt = diagnose_sb_2;
wi.want_locations = true;
wi.want_return_expr = true;
walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
+#endif
splay_tree_delete (all_labels);
all_labels = NULL;
Index: tree-gimple.h
===================================================================
--- tree-gimple.h (revision 127800)
+++ tree-gimple.h (working copy)
@@ -18,8 +18,8 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-#ifndef _TREE_SIMPLE_H
-#define _TREE_SIMPLE_H 1
+#ifndef _TREE_GIMPLE_H
+#define _TREE_GIMPLE_H 1
#include "tree-iterator.h"
#include "gimple.h"
@@ -132,7 +132,7 @@ extern enum gimplify_status gimplify_exp
extern void gimplify_type_sizes (tree, gimple_seq);
extern void gimplify_one_sizepos (tree *, gimple_seq);
extern bool gimplify_stmt (tree *, gimple_seq);
-extern void gimplify_body (tree *, gimple_seq, tree, bool);
+extern gimple gimplify_body (tree *, tree, bool);
extern void push_gimplify_context (void);
extern void pop_gimplify_context (gimple);
extern void gimplify_and_add (tree, gimple_seq);
@@ -162,64 +162,4 @@ extern void insert_field_into_struct (tr
/* In gimplify.c. */
extern void gimplify_function_tree (tree);
-/* Convenience routines to walk all statements of a gimple function.
- The difference between these walkers and the generic walk_tree is
- that walk_stmt provides context information to the callback
- routine to know whether it is currently on the LHS or RHS of an
- assignment (IS_LHS) or contexts where only GIMPLE values are
- allowed (VAL_ONLY).
-
- This is useful in walkers that need to re-write sub-expressions
- inside statements while making sure the result is still in GIMPLE
- form.
-
- Note that this is useful exclusively before the code is converted
- into SSA form. Once the program is in SSA form, the standard
- operand interface should be used to analyze/modify statements. */
-
-struct walk_stmt_info
-{
- /* For each statement, we invoke CALLBACK via walk_tree. The passed
- data is a walk_stmt_info structure. */
- walk_tree_fn callback;
-
- /* Points to the current statement being walked. */
- tree_stmt_iterator tsi;
-
- /* Additional data that CALLBACK may want to carry through the
- recursion. */
- void *info;
-
- /* Indicates whether the *TP being examined may be replaced
- with something that matches is_gimple_val (if true) or something
- slightly more complicated (if false). "Something" technically
- means the common subset of is_gimple_lvalue and is_gimple_rhs,
- but we never try to form anything more complicated than that, so
- we don't bother checking.
-
- Also note that CALLBACK should update this flag while walking the
- sub-expressions of a statement. For instance, when walking the
- statement 'foo (&var)', the flag VAL_ONLY will initially be set
- to true, however, when walking &var, the operand of that
- ADDR_EXPR does not need to be a GIMPLE value. */
- bool val_only;
-
- /* True if we are currently walking the LHS of an assignment. */
- bool is_lhs;
-
- /* Optional. Set to true by CALLBACK if it made any changes. */
- bool changed;
-
- /* True if we're interested in seeing BIND_EXPRs. */
- bool want_bind_expr;
-
- /* True if we're interested in seeing RETURN_EXPRs. */
- bool want_return_expr;
-
- /* True if we're interested in location information. */
- bool want_locations;
-};
-
-void walk_stmts (struct walk_stmt_info *, tree *);
-
-#endif /* _TREE_SIMPLE_H */
+#endif /* _TREE_GIMPLE_H */
Index: gimple-low.c
===================================================================
--- gimple-low.c (revision 127800)
+++ gimple-low.c (working copy)
@@ -91,13 +91,17 @@ static unsigned int
lower_function_body (void)
{
struct lower_data data;
- gimple_seq body_seq = gimple_body (current_function_decl);
- gimple bind = gimple_seq_first (body_seq);
+ gimple_seq body = gimple_body (current_function_decl);
+ gimple_seq lowered_body;
gimple_stmt_iterator *i;
+ gimple bind;
tree t;
gimple x;
- gcc_assert (gimple_code (bind) == GIMPLE_BIND);
+ /* The gimplifier should've left a body of exactly one statement,
+ namely a GIMPLE_BIND. */
+ gcc_assert (gimple_seq_first (body) == gimple_seq_last (body)
+ && gimple_code (gimple_seq_first (body)) == GIMPLE_BIND);
memset (&data, 0, sizeof (data));
data.block = DECL_INITIAL (current_function_decl);
@@ -106,17 +110,22 @@ lower_function_body (void)
TREE_ASM_WRITTEN (data.block) = 1;
data.return_statements = VEC_alloc (return_statements_t, heap, 8);
- gimple_seq_init (body_seq);
- gimple_add (body_seq, bind);
- i = gsi_start (body_seq);
+ bind = gimple_seq_first (body);
+ lowered_body = gimple_seq_alloc ();
+ gimple_seq_add (lowered_body, bind);
+ i = gsi_start (lowered_body);
lower_gimple_bind (i, &data);
- i = gsi_last (body_seq);
+ /* Once the old body has been lowered, replace it with the new
+ lowered sequence. */
+ set_gimple_body (current_function_decl, lowered_body);
+
+ i = gsi_last (lowered_body);
/* If the function falls off the end, we need a null return statement.
If we've already got one in the return_statements vector, we don't
need to do anything special. Otherwise build one by hand. */
- if (gimple_seq_may_fallthru (body_seq)
+ if (gimple_seq_may_fallthru (lowered_body)
&& (VEC_empty (return_statements_t, data.return_statements)
|| gimple_return_retval
(VEC_last (return_statements_t,
@@ -210,7 +219,7 @@ struct tree_opt_pass pass_lower_cf =
0, /* todo_flags_start */
TODO_dump_func, /* todo_flags_finish */
0 /* letter */
- ,0 /* works_with_tuples_p */
+ ,1 /* works_with_tuples_p */
};
@@ -231,6 +240,8 @@ lower_sequence (gimple_seq seq, struct l
/* Lower the OpenMP directive statement pointed by GSI. DATA is
passed through the recursion. */
+ /* FIXME tuples. */
+#if 0
static void
lower_omp_directive (gimple_stmt_iterator *gsi, struct lower_data *data)
{
@@ -238,14 +249,13 @@ lower_omp_directive (gimple_stmt_iterato
stmt = gsi_stmt (gsi);
- /* FIXME tuples
lower_sequence (OMP_BODY (stmt), data);
gsi_link_before (gsi, stmt, GSI_SAME_STMT);
gsi_link_before (gsi, OMP_BODY (stmt), GSI_SAME_STMT);
OMP_BODY (stmt) = NULL_TREE;
- */
gsi_delink (gsi);
}
+#endif
/* Lower statement TSI. DATA is passed through the recursion. */
@@ -315,9 +325,12 @@ lower_stmt (gimple_stmt_iterator *gsi, s
}
break;
+ /* FIXME tuples. */
+#if 0
case GIMPLE_OMP_PARALLEL:
lower_omp_directive (gsi, data);
return;
+#endif
default:
gcc_unreachable ();
@@ -429,7 +442,7 @@ try_catch_may_fallthru (tree stmt)
}
-/* Same as above, but for a gimple GIMPLE_TRY_FINALLY. */
+/* Same as above, but for a GIMPLE_TRY_CATCH. */
static bool
gimple_try_catch_may_fallthru (gimple stmt)
@@ -548,13 +561,15 @@ block_may_fallthru (tree block)
}
-/* The same as above, but for gimple sequences. */
+/* Try to determine if we can continue executing the statement
+ immediately following STMT. This guess need not be 100% accurate;
+ simply be conservative and return true if we don't know. This is
+ used only to avoid stupidly generating extra code. If we're wrong,
+ we'll just delete the extra code later. */
bool
-gimple_seq_may_fallthru (gimple_seq seq)
+gimple_stmt_may_fallthru (gimple stmt)
{
- gimple stmt = gimple_seq_last (seq);
-
if (!stmt)
return true;
@@ -603,10 +618,11 @@ gimple_seq_may_fallthru (gimple_seq seq)
/* Functions that do not return do not fall through. */
return (gimple_call_flags (stmt) & ECF_NORETURN) == 0;
- /* FIXME tuples
+ /* FIXME tuples. No CLEANUP_POINT_EXPR in GIMPLE. Needed? */
+#if 0
case CLEANUP_POINT_EXPR:
return block_may_fallthru (TREE_OPERAND (stmt, 0));
- */
+#endif
default:
return true;
@@ -614,6 +630,15 @@ gimple_seq_may_fallthru (gimple_seq seq)
}
+/* Same as gimple_stmt_may_fallthru, but for the gimple sequence SEQ. */
+
+bool
+gimple_seq_may_fallthru (gimple_seq seq)
+{
+ return gimple_stmt_may_fallthru (gimple_seq_last (seq));
+}
+
+
/* Lower a GIMPLE_RETURN GSI. DATA is passed through the recursion. */
static void
Index: gimple-iterator.c
===================================================================
--- gimple-iterator.c (revision 127800)
+++ gimple-iterator.c (working copy)
@@ -96,7 +96,7 @@ gsi_link_before (gimple_stmt_iterator *i
struct gimple_sequence tseq;
gimple_seq_init (&tseq);
- gimple_add (&tseq, g);
+ gimple_seq_add (&tseq, g);
gsi_link_seq_before (i, &tseq, mode);
}
@@ -171,7 +171,7 @@ gsi_link_after (gimple_stmt_iterator *i,
struct gimple_sequence tseq;
gimple_seq_init (&tseq);
- gimple_add (&tseq, g);
+ gimple_seq_add (&tseq, g);
gsi_link_seq_after (i, &tseq, mode);
}
@@ -219,7 +219,7 @@ gsi_split_seq_after (const gimple_stmt_i
next = gimple_next (cur);
old_seq = i->seq;
- new_seq = (gimple_seq) ggc_alloc_cleared (sizeof (*new_seq));
+ new_seq = gimple_seq_alloc ();
gimple_seq_set_first (new_seq, next);
gimple_seq_set_last (new_seq, gimple_seq_last (old_seq));
@@ -246,7 +246,7 @@ gsi_split_seq_before (gimple_stmt_iterat
prev = gimple_prev (cur);
old_seq = i->seq;
- new_seq = (gimple_seq) ggc_alloc_cleared (sizeof (*new_seq));
+ new_seq = gimple_seq_alloc ();
i->seq = new_seq;
gimple_seq_set_first (new_seq, cur);
@@ -260,3 +260,50 @@ gsi_split_seq_before (gimple_stmt_iterat
return new_seq;
}
+
+
+/* Replace the statement pointed-to by GSI to STMT. If UPDATE_EH_INFO
+ is true, the exception handling information of the original
+ statement is moved to the new statement. */
+
+void
+gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
+{
+#if 0
+ int eh_region;
+#endif
+ gimple orig_stmt = gsi_stmt (gsi);
+
+ if (stmt == orig_stmt)
+ return;
+
+ set_gimple_locus (stmt, gimple_locus (orig_stmt));
+ set_gimple_bb (stmt, gimple_bb (orig_stmt));
+
+ /* FIXME tuples. Enable after converting tree-eh.c */
+#if 0
+ /* Preserve EH region information from the original statement, if
+ requested by the caller. */
+ if (update_eh_info)
+ {
+ eh_region = lookup_stmt_eh_region (orig_stmt);
+ if (eh_region >= 0)
+ {
+ remove_stmt_from_eh_region (orig_stmt);
+ add_stmt_to_eh_region (stmt, eh_region);
+ }
+ }
+
+ gimple_duplicate_stmt_histograms (cfun, stmt, cfun, orig_stmt);
+ gimple_remove_stmt_histograms (cfun, orig_stmt);
+ delink_stmt_imm_use (orig_stmt);
+#endif
+
+ /* FIXME tuples. Enable after converting tree-ssa-operands.c. */
+#if 0
+ mark_stmt_modified (stmt);
+ update_modified_stmts (stmt);
+#endif
+
+ gsi->stmt = stmt;
+}
Index: gimple-iterator.h
===================================================================
--- gimple-iterator.h (revision 127800)
+++ gimple-iterator.h (working copy)
@@ -21,6 +21,7 @@ Boston, MA 02110-1301, USA. */
#ifndef GCC_SEQ_ITERATOR_H
#define GCC_SEQ_ITERATOR_H
+
#include "ggc.h"
/* Iterator object for GIMPLE statement sequences. */
@@ -110,7 +111,6 @@ gsi_stmt (gimple_stmt_iterator *i)
return i->stmt;
}
-
enum gsi_iterator_update
{
GSI_NEW_STMT, /* Only valid when single statement is added, move
@@ -131,5 +131,6 @@ void gsi_link_after (gimple_stmt_iterato
void gsi_delink (gimple_stmt_iterator *);
gimple_seq gsi_split_seq_after (const gimple_stmt_iterator *);
gimple_seq gsi_split_seq_before (gimple_stmt_iterator *);
+void gsi_replace (gimple_stmt_iterator *, gimple, bool);
#endif /* GCC_SEQ_ITERATOR_H */
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c (revision 127800)
+++ gimple-pretty-print.c (working copy)
@@ -30,7 +30,6 @@ Software Foundation, 51 Franklin Street,
#include "real.h"
#include "hashtab.h"
#include "tree-flow.h"
-#include "gimple-iterator.h"
#include "tree-pass.h"
#include "gimple.h"
Index: gimplify.c
===================================================================
--- gimplify.c (revision 127800)
+++ gimplify.c (working copy)
@@ -1089,18 +1089,18 @@ gimplify_bind_expr (tree *expr_p, gimple
gs = build_gimple_try (gimple_bind_body (gimple_bind), NULL,
GIMPLE_TRY_FINALLY);
- gimple_add (gimple_try_cleanup (gs), stack_restore);
+ gimple_seq_add (gimple_try_cleanup (gs), stack_restore);
gimple_seq_init (&empty_seq);
gimple_bind_set_body (gimple_bind, &empty_seq);
- gimple_add (gimple_bind_body (gimple_bind), stack_save);
- gimple_add (gimple_bind_body (gimple_bind), gs);
+ gimple_seq_add (gimple_bind_body (gimple_bind), stack_save);
+ gimple_seq_add (gimple_bind_body (gimple_bind), gs);
}
gimplify_ctxp->save_stack = old_save_stack;
gimple_pop_bind_expr ();
- gimple_add (pre_p, gimple_bind);
+ gimple_seq_add (pre_p, gimple_bind);
if (temp)
{
@@ -1130,7 +1130,7 @@ gimplify_return_expr (tree stmt, gimple_
{
bool use_return_decl_p = ret_expr && TREE_CODE (ret_expr) == RESULT_DECL;
gimple ret = build_gimple_return (use_return_decl_p, ret_expr);
- gimple_add (pre_p, ret);
+ gimple_seq_add (pre_p, ret);
return GS_ALL_DONE;
}
@@ -1186,7 +1186,7 @@ gimplify_return_expr (tree stmt, gimple_
gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
- gimple_add (pre_p, build_gimple_return (result == result_decl, result));
+ gimple_seq_add (pre_p, build_gimple_return (result == result_decl, result));
return GS_ALL_DONE;
}
@@ -1284,16 +1284,16 @@ gimplify_loop_expr (tree *expr_p, gimple
tree saved_label = gimplify_ctxp->exit_label;
tree start_label = create_artificial_label ();
- gimple_add (pre_p, build_gimple_label (start_label));
+ gimple_seq_add (pre_p, build_gimple_label (start_label));
gimplify_ctxp->exit_label = NULL_TREE;
gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
- gimple_add (pre_p, build_gimple_goto (start_label));
+ gimple_seq_add (pre_p, build_gimple_goto (start_label));
if (gimplify_ctxp->exit_label)
- gimple_add (pre_p, build_gimple_label (gimplify_ctxp->exit_label));
+ gimple_seq_add (pre_p, build_gimple_label (gimplify_ctxp->exit_label));
gimplify_ctxp->exit_label = saved_label;
@@ -1448,7 +1448,7 @@ gimplify_switch_expr (tree *expr_p, gimp
tree def_lab = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
NULL_TREE, create_artificial_label ());
gimple new_default = build_gimple_label (def_lab);
- gimple_add (&switch_body_seq, new_default);
+ gimple_seq_add (&switch_body_seq, new_default);
default_case = gimple_label_label (new_default);
}
@@ -1457,7 +1457,7 @@ gimplify_switch_expr (tree *expr_p, gimp
gimple_switch = build_gimple_switch_vec (SWITCH_COND (switch_expr),
default_case, labels);
- gimple_add (pre_p, gimple_switch);
+ gimple_seq_add (pre_p, gimple_switch);
gimple_seq_append (pre_p, &switch_body_seq);
VEC_free(tree, heap, labels);
}
@@ -1483,7 +1483,7 @@ gimplify_case_label_expr (tree *expr_p,
gimple gimple_label = build_gimple_label (*expr_p);
VEC_safe_push (tree, heap, ctxp->case_labels,
gimple_label_label (gimple_label));
- gimple_add (pre_p, gimple_label);
+ gimple_seq_add (pre_p, gimple_label);
return GS_ALL_DONE;
}
@@ -2245,7 +2245,7 @@ gimplify_call_expr (tree *expr_p, gimple
/* Now add the GIMPLE call to PRE_P. If WANT_VALUE is set, we need
to create the appropriate temporary for the call's LHS. */
call = build_gimple_call_vec (fndecl ? fndecl : CALL_EXPR_FN (*expr_p), args);
- gimple_add (pre_p, call);
+ gimple_seq_add (pre_p, call);
if (want_value)
{
tree lhs = get_tmp_var_for (call);
@@ -2692,14 +2692,14 @@ gimplify_cond_expr (tree *expr_p, gimple
label_false);
}
- gimple_add (pre_p, gimple_cond);
- gimple_add (pre_p, build_gimple_label (label_true));
+ gimple_seq_add (pre_p, gimple_cond);
+ gimple_seq_add (pre_p, build_gimple_label (label_true));
have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), pre_p);
label_cont = create_artificial_label ();
- gimple_add (pre_p, build_gimple_goto (label_cont));
- gimple_add (pre_p, build_gimple_label (label_false));
+ gimple_seq_add (pre_p, build_gimple_goto (label_cont));
+ gimple_seq_add (pre_p, build_gimple_label (label_false));
have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), pre_p);
- gimple_add (pre_p, build_gimple_label (label_cont));
+ gimple_seq_add (pre_p, build_gimple_label (label_cont));
gimple_pop_condition (pre_p);
@@ -2747,13 +2747,13 @@ gimplify_modify_expr_to_memcpy (tree *ex
/* tmp = memcpy() */
t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
gimple_call_set_lhs (gs, t);
- gimple_add (seq_p, gs);
+ gimple_seq_add (seq_p, gs);
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
return GS_ALL_DONE;
}
- gimple_add (seq_p, gs);
+ gimple_seq_add (seq_p, gs);
*expr_p = NULL;
return GS_ALL_DONE;
}
@@ -2781,13 +2781,13 @@ gimplify_modify_expr_to_memset (tree *ex
/* tmp = memset() */
t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
gimple_call_set_lhs (gs, t);
- gimple_add (seq_p, gs);
+ gimple_seq_add (seq_p, gs);
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
return GS_ALL_DONE;
}
- gimple_add (seq_p, gs);
+ gimple_seq_add (seq_p, gs);
*expr_p = NULL;
return GS_ALL_DONE;
}
@@ -2950,10 +2950,10 @@ gimplify_init_ctor_eval_range (tree obje
/* Create and initialize the index variable. */
var_type = TREE_TYPE (upper);
var = create_tmp_var (var_type, NULL);
- gimple_add (pre_p, build_gimple_assign (var, lower));
+ gimple_seq_add (pre_p, build_gimple_assign (var, lower));
/* Add the loop entry label. */
- gimple_add (pre_p, build_gimple_label (loop_entry_label));
+ gimple_seq_add (pre_p, build_gimple_label (loop_entry_label));
/* Build the reference. */
cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
@@ -2968,23 +2968,23 @@ gimplify_init_ctor_eval_range (tree obje
gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
pre_p, cleared);
else
- gimple_add (pre_p, build_gimple_assign (cref, value));
+ gimple_seq_add (pre_p, build_gimple_assign (cref, value));
/* We exit the loop when the index var is equal to the upper bound. */
- gimple_add (pre_p,
+ gimple_seq_add (pre_p,
build_gimple_cond (GIMPLE_COND_EQ, var, upper, loop_exit_label,
NULL_TREE));
/* Otherwise, increment the index var... */
tmp = build2 (PLUS_EXPR, var_type, var,
fold_convert (var_type, integer_one_node));
- gimple_add (pre_p, build_gimple_assign (var, tmp));
+ gimple_seq_add (pre_p, build_gimple_assign (var, tmp));
/* ...and jump back to the loop entry. */
- gimple_add (pre_p, build_gimple_goto (loop_entry_label));
+ gimple_seq_add (pre_p, build_gimple_goto (loop_entry_label));
/* Add the loop exit label. */
- gimple_add (pre_p, build_gimple_label (loop_exit_label));
+ gimple_seq_add (pre_p, build_gimple_label (loop_exit_label));
}
/* Return true if FDECL is accessing a field that is zero sized. */
@@ -3085,7 +3085,7 @@ gimplify_init_ctor_eval (tree object, VE
gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
pre_p, cleared);
else
- gimple_add (pre_p, build_gimple_assign (cref, value));
+ gimple_seq_add (pre_p, build_gimple_assign (cref, value));
}
}
@@ -3388,7 +3388,7 @@ gimplify_init_constructor (tree *expr_p,
tree lhs = TREE_OPERAND (*expr_p, 0);
tree rhs = TREE_OPERAND (*expr_p, 1);
gimple init = build_gimple_assign (lhs, rhs);
- gimple_add (pre_p, init);
+ gimple_seq_add (pre_p, init);
*expr_p = NULL;
}
@@ -3724,7 +3724,7 @@ gimplify_modify_expr_complex_part (tree
else
new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
- gimple_add (pre_p, build_gimple_assign (lhs, new_rhs));
+ gimple_seq_add (pre_p, build_gimple_assign (lhs, new_rhs));
*expr_p = (want_value) ? rhs : NULL_TREE;
return GS_ALL_DONE;
@@ -3843,7 +3843,7 @@ gimplify_modify_expr (tree *expr_p, gimp
SET_DECL_DEBUG_EXPR (*from_p, *to_p);
}
- gimple_add (pre_p, build_gimple_assign (*to_p, *from_p));
+ gimple_seq_add (pre_p, build_gimple_assign (*to_p, *from_p));
if (want_value)
{
@@ -4103,22 +4103,23 @@ gimplify_addr_expr (tree *expr_p, gimple
static enum gimplify_status
gimplify_asm_expr (tree *expr_p, gimple_seq pre_p, gimple_seq post_p)
{
- tree expr = *expr_p;
- int noutputs = list_length (ASM_OUTPUTS (expr));
- const char **oconstraints
- = (const char **) alloca ((noutputs) * sizeof (const char *));
+ tree expr;
+ int noutputs;
+ const char **oconstraints;
int i;
tree link;
const char *constraint;
bool allows_mem, allows_reg, is_inout;
enum gimplify_status ret, tret;
-
gimple stmt;
-
VEC(tree, gc) *inputs;
VEC(tree, gc) *outputs;
VEC(tree, gc) *clobbers;
+ expr = *expr_p;
+ noutputs = list_length (ASM_OUTPUTS (expr));
+ oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
+
inputs = VEC_alloc (tree, gc, 5);
outputs = VEC_alloc (tree, gc, 5);
clobbers = VEC_alloc (tree, gc, 5);
@@ -4127,14 +4128,16 @@ gimplify_asm_expr (tree *expr_p, gimple_
for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link))
{
size_t constraint_len;
- oconstraints[i] = constraint
+
+ oconstraints[i]
+ = constraint
= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
constraint_len = strlen (constraint);
if (constraint_len == 0)
continue;
- parse_output_constraint (&constraint, i, 0, 0,
- &allows_mem, &allows_reg, &is_inout);
+ parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg,
+ &is_inout);
if (!allows_reg && allows_mem)
mark_addressable (TREE_VALUE (link));
@@ -4148,7 +4151,7 @@ gimplify_asm_expr (tree *expr_p, gimple_
ret = tret;
}
- VEC_safe_push (tree, gc, outputs, TREE_VALUE (link));
+ VEC_safe_push (tree, gc, outputs, link);
if (is_inout)
{
@@ -4282,15 +4285,16 @@ gimplify_asm_expr (tree *expr_p, gimple_
if (tret == GS_ERROR)
ret = tret;
}
- VEC_safe_push (tree, gc, inputs, TREE_VALUE (link));
+
+ VEC_safe_push (tree, gc, inputs, link);
}
for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link))
- VEC_safe_push (tree, gc, clobbers, TREE_VALUE (link));
+ VEC_safe_push (tree, gc, clobbers, link);
- stmt = build_gimple_asm_vec (TREE_STRING_POINTER (ASM_STRING(expr)),
- inputs, outputs, clobbers);
- gimple_add (pre_p, stmt);
+ stmt = build_gimple_asm_vec (TREE_STRING_POINTER (ASM_STRING(expr)),
+ inputs, outputs, clobbers);
+ gimple_seq_add (pre_p, stmt);
return ret;
}
@@ -4387,6 +4391,8 @@ gimplify_cleanup_point_expr (tree *expr_
static void
gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq pre_p)
{
+/* FIXME tuples */
+#if 0 /* FIXME tuples */
tree wce;
/* Errors can result in improperly nested cleanups. Which results in
@@ -4417,17 +4423,14 @@ gimple_push_cleanup (tree var, tree clea
val
*/
-#if 0 /* FIXME tuples */
-/* FIXME tuples */
tree flag = create_tmp_var (boolean_type_node, "cleanup");
gimple ffalse = build_gimple_assign (flag, boolean_false_node);
gimple ftrue = build_gimple_assign (flag, boolean_true_node);
cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
wce = build1 (WITH_CLEANUP_EXPR, void_type_node, cleanup);
- gimple_add (&gimplify_ctxp->conditional_cleanups, ffalse);
+ gimple_seq_add (&gimplify_ctxp->conditional_cleanups, ffalse);
gimple_seq_append (&gimplify_ctxp->conditional_cleanups, wce);
- gimple_add (pre_p, ftrue);
-#endif
+ gimple_seq_add (pre_p, ftrue);
/* Because of this manipulation, and the EH edges that jump
threading cannot redirect, the temporary (VAR) will appear
@@ -4438,13 +4441,11 @@ gimple_push_cleanup (tree var, tree clea
{
wce = build1 (WITH_CLEANUP_EXPR, void_type_node, cleanup);
CLEANUP_EH_ONLY (wce) = eh_only;
-#if 0
-/* FIXME tuples */
append_to_statement_list (wce, pre_p);
-#endif
}
gimplify_stmt (&TREE_OPERAND (wce, 0), pre_p);
+#endif
}
/* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
@@ -5950,14 +5951,14 @@ gimplify_expr (tree *expr_p, gimple_seq
if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
NULL, is_gimple_val, fb_rvalue);
- gimple_add (pre_p, build_gimple_goto (GOTO_DESTINATION (*expr_p)));
+ gimple_seq_add (pre_p, build_gimple_goto (GOTO_DESTINATION (*expr_p)));
break;
case LABEL_EXPR:
ret = GS_ALL_DONE;
gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
== current_function_decl);
- gimple_add (pre_p, build_gimple_label (LABEL_EXPR_LABEL (*expr_p)));
+ gimple_seq_add (pre_p, build_gimple_label (LABEL_EXPR_LABEL (*expr_p)));
break;
case CASE_LABEL_EXPR:
@@ -6044,7 +6045,7 @@ gimplify_expr (tree *expr_p, gimple_seq
gimplify_and_add (TREE_OPERAND (*expr_p, 0), gimple_try_eval (try));
gimplify_and_add (TREE_OPERAND (*expr_p, 1),
gimple_try_cleanup (try));
- gimple_add (pre_p, try);
+ gimple_seq_add (pre_p, try);
ret = GS_ALL_DONE;
break;
@@ -6602,15 +6603,16 @@ gimplify_one_sizepos (tree *expr_p, gimp
}
-/* Gimplify the body of statements pointed to by BODY_P and store the
- corresponding GIMPLE sequence in SEQ_P. FNDECL is the function
- decl containing BODY. */
+/* Gimplify the body of statements pointed to by BODY_P and return a
+ GIMPLE_BIND containing the sequence of GIMPLE statements
+ corresponding to BODY_P. FNDECL is the function decl containing
+ *BODY_P. */
-void
-gimplify_body (tree *body_p, gimple_seq seq_p, tree fndecl, bool do_parms)
+gimple
+gimplify_body (tree *body_p, tree fndecl, bool do_parms)
{
location_t saved_location = input_location;
- struct gimple_sequence parm_stmts;
+ struct gimple_sequence parm_stmts, seq;
gimple outer_bind;
timevar_push (TV_TREE_GIMPLIFY);
@@ -6636,24 +6638,25 @@ gimplify_body (tree *body_p, gimple_seq
gimple_seq_init (&parm_stmts);
/* Gimplify the function's body. */
- gimplify_stmt (body_p, seq_p);
+ gimple_seq_init (&seq);
+ gimplify_stmt (body_p, &seq);
- outer_bind = gimple_seq_first (seq_p);
+ outer_bind = gimple_seq_first (&seq);
if (!outer_bind)
{
outer_bind = build_gimple_nop ();
- gimple_add (seq_p, outer_bind);
+ gimple_seq_add (&seq, outer_bind);
}
/* If there isn't an outer GIMPLE_BIND, add one. */
if (gimple_code (outer_bind) != GIMPLE_BIND)
- outer_bind = build_gimple_bind (NULL_TREE, seq_p);
+ outer_bind = build_gimple_bind (NULL_TREE, &seq);
*body_p = NULL_TREE;
/* If we had callee-copies statements, insert them at the beginning
of the function. */
- if (gimple_seq_empty_p (&parm_stmts) != false)
+ if (!gimple_seq_empty_p (&parm_stmts))
{
gimple_seq_append (&parm_stmts, gimple_bind_body (outer_bind));
gimple_bind_set_body (outer_bind, &parm_stmts);
@@ -6672,6 +6675,8 @@ gimplify_body (tree *body_p, gimple_seq
timevar_pop (TV_TREE_GIMPLIFY);
input_location = saved_location;
+
+ return outer_bind;
}
/* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
@@ -6685,6 +6690,7 @@ gimplify_function_tree (tree fndecl)
{
tree oldfn, parm, ret;
gimple_seq seq;
+ gimple bind;
oldfn = current_function_decl;
current_function_decl = fndecl;
@@ -6710,8 +6716,8 @@ gimplify_function_tree (tree fndecl)
&& !needs_to_live_in_memory (ret))
DECL_GIMPLE_REG_P (ret) = 1;
- seq = (gimple_seq) ggc_alloc_cleared (sizeof (*seq));
- gimplify_body (&DECL_SAVED_TREE (fndecl), seq, fndecl, true);
+ bind = gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
+ seq = gimple_bind_body (bind);
/* If we're instrumenting function entry/exit, then prepend the call to
the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
@@ -6722,23 +6728,22 @@ gimplify_function_tree (tree fndecl)
&& !flag_instrument_functions_exclude_p (fndecl))
{
tree x;
- gimple tf, bind;
+ gimple tf;
tf = build_gimple_try (seq, NULL, GIMPLE_TRY_FINALLY);
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
- gimple_add (gimple_try_cleanup (tf), build_gimple_call (x, 0));
+ gimple_seq_add (gimple_try_cleanup (tf), build_gimple_call (x, 0));
bind = build_gimple_bind (NULL, NULL);
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
- gimple_add (gimple_bind_body (bind), build_gimple_call (x, 0));
- gimple_add (gimple_bind_body (bind), tf);
-
- gimple_seq_init (seq);
- gimple_add (seq, bind);
+ gimple_seq_add (gimple_bind_body (bind), build_gimple_call (x, 0));
+ gimple_seq_add (gimple_bind_body (bind), tf);
}
/* The tree body of the function is no longer needed, replace it
with the new GIMPLE body. */
+ seq = gimple_seq_alloc ();
+ gimple_seq_add (seq, bind);
set_gimple_body (fndecl, seq);
DECL_SAVED_TREE (fndecl) = NULL_TREE;
Index: tree-nested.c
===================================================================
--- tree-nested.c (revision 127800)
+++ tree-nested.c (working copy)
@@ -1,4 +1,4 @@
-/* Nested function decomposition for trees.
+/* Nested function decomposition for GIMPLE.
Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ <http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
@@ -351,46 +351,67 @@ get_chain_field (struct nesting_info *in
return field;
}
+/* Initialize a new temporary with the GIMPLE_CALL STMT. */
+
+static tree
+init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
+ gimple call)
+{
+ tree t;
+
+ t = create_tmp_var_for (info, TREE_TYPE (TREE_TYPE (gimple_call_fn (call))),
+ NULL);
+ gimple_call_set_lhs (call, t);
+ set_gimple_locus (call, gimple_locus (gsi_stmt (gsi)));
+ gsi_link_before (gsi, call, GSI_SAME_STMT);
+
+ return t;
+}
+
+
/* Copy EXP into a temporary. Allocate the temporary in the context of
- INFO and insert the initialization statement before TSI. */
+ INFO and insert the initialization statement before GSI. */
static tree
-init_tmp_var (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
+init_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
{
- tree t, stmt;
+ tree t;
+ gimple stmt;
t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
- stmt = build_gimple_modify_stmt (t, exp);
- SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
- tsi_link_before (tsi, stmt, TSI_SAME_STMT);
+ stmt = build_gimple_assign (t, exp);
+ set_gimple_locus (stmt, gimple_locus (gsi_stmt (gsi)));
+ gsi_link_before (gsi, stmt, GSI_SAME_STMT);
return t;
}
+
/* Similarly, but only do so to force EXP to satisfy is_gimple_val. */
static tree
-tsi_gimplify_val (struct nesting_info *info, tree exp, tree_stmt_iterator *tsi)
+gsi_gimplify_val (struct nesting_info *info, tree exp,
+ gimple_stmt_iterator *gsi)
{
if (is_gimple_val (exp))
return exp;
else
- return init_tmp_var (info, exp, tsi);
+ return init_tmp_var (info, exp, gsi);
}
/* Similarly, but copy from the temporary and insert the statement
after the iterator. */
static tree
-save_tmp_var (struct nesting_info *info, tree exp,
- tree_stmt_iterator *tsi)
+save_tmp_var (struct nesting_info *info, tree exp, gimple_stmt_iterator *gsi)
{
- tree t, stmt;
+ tree t;
+ gimple stmt;
t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
- stmt = build_gimple_modify_stmt (exp, t);
- SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
- tsi_link_after (tsi, stmt, TSI_SAME_STMT);
+ stmt = build_gimple_assign (exp, t);
+ set_gimple_locus (stmt, gimple_locus (gsi_stmt (gsi)));
+ gsi_link_after (gsi, stmt, GSI_SAME_STMT);
return t;
}
@@ -507,179 +528,51 @@ get_nl_goto_field (struct nesting_info *
return field;
}
-
-/* Helper function for walk_stmts. Walk output operands of an ASM_EXPR. */
-static void
-walk_asm_expr (struct walk_stmt_info *wi, tree stmt)
-{
- int noutputs = list_length (ASM_OUTPUTS (stmt));
- const char **oconstraints
- = (const char **) alloca ((noutputs) * sizeof (const char *));
- int i;
- tree link;
- const char *constraint;
- bool allows_mem, allows_reg, is_inout;
-
- wi->is_lhs = true;
- for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
- {
- constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- oconstraints[i] = constraint;
- parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
- &allows_reg, &is_inout);
-
- wi->val_only = (allows_reg || !allows_mem);
- walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
- }
-
- for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
- {
- constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_input_constraint (&constraint, 0, 0, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg);
-
- wi->val_only = (allows_reg || !allows_mem);
- /* Although input "m" is not really a LHS, we need a lvalue. */
- wi->is_lhs = !wi->val_only;
- walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
- }
-
- wi->is_lhs = false;
- wi->val_only = true;
-}
-
-/* Iterate over all sub-statements of *TP calling walk_tree with
- WI->CALLBACK for every sub-expression in each statement found. */
-
-void
-walk_stmts (struct walk_stmt_info *wi, tree *tp)
-{
- tree t = *tp;
- int walk_subtrees;
-
- if (!t)
- return;
-
- if (wi->want_locations && EXPR_HAS_LOCATION (t))
- input_location = EXPR_LOCATION (t);
-
- switch (TREE_CODE (t))
- {
- case STATEMENT_LIST:
- {
- tree_stmt_iterator i;
- for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- {
- wi->tsi = i;
- walk_stmts (wi, tsi_stmt_ptr (i));
- }
- }
- break;
-
- case COND_EXPR:
- walk_tree (&COND_EXPR_COND (t), wi->callback, wi, NULL);
- walk_stmts (wi, &COND_EXPR_THEN (t));
- walk_stmts (wi, &COND_EXPR_ELSE (t));
- break;
- case CATCH_EXPR:
- walk_stmts (wi, &CATCH_BODY (t));
- break;
- case EH_FILTER_EXPR:
- walk_stmts (wi, &EH_FILTER_FAILURE (t));
- break;
- case TRY_CATCH_EXPR:
- case TRY_FINALLY_EXPR:
- walk_stmts (wi, &TREE_OPERAND (t, 0));
- walk_stmts (wi, &TREE_OPERAND (t, 1));
- break;
-
- case BIND_EXPR:
- if (wi->want_bind_expr)
- {
- walk_subtrees = 1;
- wi->callback (tp, &walk_subtrees, wi);
- if (!walk_subtrees)
- break;
- }
- walk_stmts (wi, &BIND_EXPR_BODY (t));
- break;
-
- case RETURN_EXPR:
- if (wi->want_return_expr)
- {
- walk_subtrees = 1;
- wi->callback (tp, &walk_subtrees, wi);
- if (!walk_subtrees)
- break;
- }
- walk_stmts (wi, &TREE_OPERAND (t, 0));
- break;
-
- case GIMPLE_MODIFY_STMT:
- /* A formal temporary lhs may use a COMPONENT_REF rhs. */
- wi->val_only = !is_gimple_formal_tmp_var (GIMPLE_STMT_OPERAND (t, 0));
- walk_tree (&GIMPLE_STMT_OPERAND (t, 1), wi->callback, wi, NULL);
-
- /* If the rhs is appropriate for a memory, we may use a
- COMPONENT_REF on the lhs. */
- wi->val_only = !is_gimple_mem_rhs (GIMPLE_STMT_OPERAND (t, 1));
- wi->is_lhs = true;
- walk_tree (&GIMPLE_STMT_OPERAND (t, 0), wi->callback, wi, NULL);
-
- wi->val_only = true;
- wi->is_lhs = false;
- break;
-
- case ASM_EXPR:
- walk_asm_expr (wi, *tp);
- break;
-
- default:
- wi->val_only = true;
- walk_tree (tp, wi->callback, wi, NULL);
- break;
- }
-}
-
-/* Invoke CALLBACK on all statements of *STMT_P. */
+/* Invoke CALLBACK on all statements of GIMPLE sequence SEQ. */
static void
-walk_body (walk_tree_fn callback, struct nesting_info *info, tree *stmt_p)
+walk_body (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
+ struct nesting_info *info, gimple_seq seq)
{
struct walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
- wi.callback = callback;
+ wi.callback_stmt = callback_stmt;
+ wi.callback_op = callback_op;
wi.info = info;
wi.val_only = true;
-
- walk_stmts (&wi, stmt_p);
+ walk_gimple_seq (seq, &wi);
}
-/* Invoke CALLBACK on all statements of INFO->CONTEXT. */
+
+/* Invoke CALLBACK_STMT/CALLBACK_OP on all statements of INFO->CONTEXT. */
static inline void
-walk_function (walk_tree_fn callback, struct nesting_info *info)
+walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
+ struct nesting_info *info)
{
- walk_body (callback, info, &DECL_SAVED_TREE (info->context));
+ walk_body (callback_stmt, callback_op, info, gimple_body (info->context));
}
+
/* Similarly for ROOT and all functions nested underneath, depth first. */
static void
-walk_all_functions (walk_tree_fn callback, struct nesting_info *root)
+walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
+ struct nesting_info *root)
{
do
{
if (root->inner)
- walk_all_functions (callback, root->inner);
- walk_function (callback, root);
+ walk_all_functions (callback_stmt, callback_op, root->inner);
+ walk_function (callback_stmt, callback_op, root);
root = root->next;
}
while (root);
}
-
+
+
/* We have to check for a fairly pathological case. The operands of function
nested function are to be interpreted in the context of the enclosing
function. So if any are variably-sized, they will get remapped when the
@@ -755,7 +648,7 @@ create_nesting_tree (struct cgraph_node
static tree
get_static_chain (struct nesting_info *info, tree target_context,
- tree_stmt_iterator *tsi)
+ gimple_stmt_iterator *gsi)
{
struct nesting_info *i;
tree x;
@@ -774,20 +667,21 @@ get_static_chain (struct nesting_info *i
x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
- x = init_tmp_var (info, x, tsi);
+ x = init_tmp_var (info, x, gsi);
}
}
return x;
}
+
/* Return an expression referencing FIELD from TARGET_CONTEXT's non-local
frame as seen from INFO->CONTEXT. Insert any necessary computations
- before TSI. */
+ before GSI. */
static tree
get_frame_field (struct nesting_info *info, tree target_context,
- tree field, tree_stmt_iterator *tsi)
+ tree field, gimple_stmt_iterator *gsi)
{
struct nesting_info *i;
tree x;
@@ -808,7 +702,7 @@ get_frame_field (struct nesting_info *in
x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL_TREE);
- x = init_tmp_var (info, x, tsi);
+ x = init_tmp_var (info, x, gsi);
}
x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
@@ -818,7 +712,8 @@ get_frame_field (struct nesting_info *in
return x;
}
-/* A subroutine of convert_nonlocal_reference. Create a local variable
+
+/* A subroutine of convert_nonlocal_reference_op. Create a local variable
in the nested function with DECL_VALUE_EXPR set to reference the true
variable in the parent function. This is used both for debug info
and in OpenMP lowering. */
@@ -885,7 +780,8 @@ get_nonlocal_debug_decl (struct nesting_
return new_decl;
}
-/* Called via walk_function+walk_tree, rewrite all references to VAR
+
+/* Callback for walk_gimple_stmt, rewrite all references to VAR
and PARM_DECLs that belong to outer functions.
The rewrite will involve some number of structure accesses back up
@@ -893,16 +789,12 @@ get_nonlocal_debug_decl (struct nesting_
be CHAIN->FOO. For two levels it'll be CHAIN->__chain->FOO. Further
indirections apply to decls for which use_pointer_in_frame is true. */
-static bool convert_nonlocal_omp_clauses (tree *, struct walk_stmt_info *);
-
static tree
-convert_nonlocal_reference (tree *tp, int *walk_subtrees, void *data)
+convert_nonlocal_reference_op (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree t = *tp;
- tree save_local_var_chain;
- bitmap save_suppress;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -927,10 +819,10 @@ convert_nonlocal_reference (tree *tp, in
for (i = info->outer; i->context != target_context; i = i->outer)
continue;
x = lookup_field_for_decl (i, t, INSERT);
- x = get_frame_field (info, target_context, x, &wi->tsi);
+ x = get_frame_field (info, target_context, x, wi->gsi);
if (use_pointer_in_frame (t))
{
- x = init_tmp_var (info, x, &wi->tsi);
+ x = init_tmp_var (info, x, wi->gsi);
x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
}
}
@@ -938,25 +830,15 @@ convert_nonlocal_reference (tree *tp, in
if (wi->val_only)
{
if (wi->is_lhs)
- x = save_tmp_var (info, x, &wi->tsi);
+ x = save_tmp_var (info, x, wi->gsi);
else
- x = init_tmp_var (info, x, &wi->tsi);
+ x = init_tmp_var (info, x, wi->gsi);
}
*tp = x;
}
break;
- case GOTO_EXPR:
- /* Don't walk non-local gotos for now. */
- if (TREE_CODE (GOTO_DESTINATION (t)) != LABEL_DECL)
- {
- *walk_subtrees = 1;
- wi->val_only = true;
- wi->is_lhs = false;
- }
- break;
-
case LABEL_DECL:
/* We're taking the address of a label from a parent function, but
this is not itself a non-local goto. Mark the label such that it
@@ -973,7 +855,7 @@ convert_nonlocal_reference (tree *tp, in
wi->val_only = false;
wi->is_lhs = false;
wi->changed = false;
- walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL);
+ walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference_op, wi, 0);
wi->val_only = true;
if (wi->changed)
@@ -991,7 +873,7 @@ convert_nonlocal_reference (tree *tp, in
where we only accept variables (and min_invariant, presumably),
then compute the address into a temporary. */
if (save_val_only)
- *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
+ *tp = gsi_gimplify_val (wi->info, t, wi->gsi);
}
}
break;
@@ -1010,28 +892,28 @@ convert_nonlocal_reference (tree *tp, in
for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
{
if (TREE_CODE (t) == COMPONENT_REF)
- walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op, wi,
NULL);
else if (TREE_CODE (t) == ARRAY_REF
|| TREE_CODE (t) == ARRAY_RANGE_REF)
{
- walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi,
- NULL);
- walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
- NULL);
- walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference, wi,
- NULL);
+ walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
+ wi, NULL);
+ walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
+ wi, NULL);
+ walk_tree (&TREE_OPERAND (t, 3), convert_nonlocal_reference_op,
+ wi, NULL);
}
else if (TREE_CODE (t) == BIT_FIELD_REF)
{
- walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference, wi,
- NULL);
- walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference, wi,
- NULL);
+ walk_tree (&TREE_OPERAND (t, 1), convert_nonlocal_reference_op,
+ wi, NULL);
+ walk_tree (&TREE_OPERAND (t, 2), convert_nonlocal_reference_op,
+ wi, NULL);
}
}
wi->val_only = false;
- walk_tree (tp, convert_nonlocal_reference, wi, NULL);
+ walk_tree (tp, convert_nonlocal_reference_op, wi, NULL);
break;
case VIEW_CONVERT_EXPR:
@@ -1041,44 +923,6 @@ convert_nonlocal_reference (tree *tp, in
*walk_subtrees = 1;
break;
- case OMP_PARALLEL:
- save_suppress = info->suppress_expansion;
- if (convert_nonlocal_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
- {
- tree c, decl;
- decl = get_chain_decl (info);
- c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
- OMP_CLAUSE_DECL (c) = decl;
- OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
- OMP_PARALLEL_CLAUSES (t) = c;
- }
-
- save_local_var_chain = info->new_local_var_chain;
- info->new_local_var_chain = NULL;
-
- walk_body (convert_nonlocal_reference, info, &OMP_PARALLEL_BODY (t));
-
- if (info->new_local_var_chain)
- declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
- info->new_local_var_chain = save_local_var_chain;
- info->suppress_expansion = save_suppress;
- break;
-
- case OMP_FOR:
- case OMP_SECTIONS:
- case OMP_SINGLE:
- save_suppress = info->suppress_expansion;
- convert_nonlocal_omp_clauses (&OMP_CLAUSES (t), wi);
- walk_body (convert_nonlocal_reference, info, &OMP_BODY (t));
- info->suppress_expansion = save_suppress;
- break;
-
- case OMP_SECTION:
- case OMP_MASTER:
- case OMP_ORDERED:
- walk_body (convert_nonlocal_reference, info, &OMP_BODY (t));
- break;
-
default:
if (!IS_TYPE_OR_DECL_P (t))
{
@@ -1092,6 +936,10 @@ convert_nonlocal_reference (tree *tp, in
return NULL_TREE;
}
+
+/* Helper for convert_nonlocal_references, rewrite all references to VAR
+ and PARM_DECLs that belong to outer functions. */
+
static bool
convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
{
@@ -1131,8 +979,8 @@ convert_nonlocal_omp_clauses (tree *pcla
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
wi->is_lhs = false;
- convert_nonlocal_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
- wi);
+ convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+ &dummy, wi);
break;
case OMP_CLAUSE_NOWAIT:
@@ -1151,6 +999,87 @@ convert_nonlocal_omp_clauses (tree *pcla
return need_chain;
}
+
+/* Callback for walk_gimple_stmt. Rewrite all references to VAR and
+ PARM_DECLs that belong to outer functions. This handles statements
+ that are not handled via the standard recursion done in
+ walk_gimple_stmt. STMT is the statement to examine, DATA is as in
+ convert_nonlocal_reference_op. */
+
+static bool
+convert_nonlocal_reference_stmt (gimple stmt, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+ struct nesting_info *info = wi->info;
+ tree save_local_var_chain;
+ bitmap save_suppress;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_GOTO:
+ /* Don't walk non-local gotos for now. */
+ if (TREE_CODE (gimple_goto_dest (stmt)) != LABEL_DECL)
+ {
+ wi->val_only = true;
+ wi->is_lhs = false;
+ return false;
+ }
+ break;
+
+ case GIMPLE_OMP_PARALLEL:
+ save_suppress = info->suppress_expansion;
+ if (convert_nonlocal_omp_clauses (gimple_omp_parallel_clauses_ptr (stmt),
+ wi))
+ {
+ tree c, decl;
+ decl = get_chain_decl (info);
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
+ gimple_omp_parallel_set_clauses (stmt, c);
+ }
+
+ save_local_var_chain = info->new_local_var_chain;
+ info->new_local_var_chain = NULL;
+
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_body (stmt));
+
+ if (info->new_local_var_chain)
+ declare_vars (info->new_local_var_chain,
+ gimple_seq_first (gimple_omp_body (stmt)),
+ false);
+ info->new_local_var_chain = save_local_var_chain;
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case GIMPLE_OMP_FOR:
+ case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_SINGLE:
+ save_suppress = info->suppress_expansion;
+ convert_nonlocal_omp_clauses (gimple_omp_parallel_clauses_ptr (stmt), wi);
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_body (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_body (stmt));
+ break;
+
+ default:
+ /* For every other statement that we are not interested in
+ handling here, let the walker traverse the operands. */
+ return true;
+ }
+
+ return false;
+}
+
+
/* A subroutine of convert_local_reference. Create a local variable
in the parent function with DECL_VALUE_EXPR set to reference the
field in FRAME. This is used both for debug info and in OpenMP
@@ -1195,21 +1124,20 @@ get_local_debug_decl (struct nesting_inf
return new_decl;
}
-/* Called via walk_function+walk_tree, rewrite all references to VAR
+
+/* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR
and PARM_DECLs that were referenced by inner nested functions.
The rewrite will be a structure reference to the local frame variable. */
static bool convert_local_omp_clauses (tree *, struct walk_stmt_info *);
static tree
-convert_local_reference (tree *tp, int *walk_subtrees, void *data)
+convert_local_reference_op (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
tree t = *tp, field, x;
bool save_val_only;
- tree save_local_var_chain;
- bitmap save_suppress;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -1237,14 +1165,14 @@ convert_local_reference (tree *tp, int *
x = get_local_debug_decl (info, t, field);
if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
- x = get_frame_field (info, info->context, field, &wi->tsi);
+ x = get_frame_field (info, info->context, field, wi->gsi);
if (wi->val_only)
{
if (wi->is_lhs)
- x = save_tmp_var (info, x, &wi->tsi);
+ x = save_tmp_var (info, x, wi->gsi);
else
- x = init_tmp_var (info, x, &wi->tsi);
+ x = init_tmp_var (info, x, wi->gsi);
}
*tp = x;
@@ -1256,7 +1184,7 @@ convert_local_reference (tree *tp, int *
wi->val_only = false;
wi->is_lhs = false;
wi->changed = false;
- walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
+ walk_tree (&TREE_OPERAND (t, 0), convert_local_reference_op, wi, NULL);
wi->val_only = save_val_only;
/* If we converted anything ... */
@@ -1275,7 +1203,7 @@ convert_local_reference (tree *tp, int *
/* If we are in a context where we only accept values, then
compute the address into a temporary. */
if (save_val_only)
- *tp = tsi_gimplify_val (wi->info, t, &wi->tsi);
+ *tp = gsi_gimplify_val (wi->info, t, wi->gsi);
}
break;
@@ -1294,28 +1222,28 @@ convert_local_reference (tree *tp, int *
for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
{
if (TREE_CODE (t) == COMPONENT_REF)
- walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
NULL);
else if (TREE_CODE (t) == ARRAY_REF
|| TREE_CODE (t) == ARRAY_RANGE_REF)
{
- walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
NULL);
- walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
NULL);
- walk_tree (&TREE_OPERAND (t, 3), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 3), convert_local_reference_op, wi,
NULL);
}
else if (TREE_CODE (t) == BIT_FIELD_REF)
{
- walk_tree (&TREE_OPERAND (t, 1), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 1), convert_local_reference_op, wi,
NULL);
- walk_tree (&TREE_OPERAND (t, 2), convert_local_reference, wi,
+ walk_tree (&TREE_OPERAND (t, 2), convert_local_reference_op, wi,
NULL);
}
}
wi->val_only = false;
- walk_tree (tp, convert_local_reference, wi, NULL);
+ walk_tree (tp, convert_local_reference_op, wi, NULL);
wi->val_only = save_val_only;
break;
@@ -1326,44 +1254,6 @@ convert_local_reference (tree *tp, int *
*walk_subtrees = 1;
break;
- case OMP_PARALLEL:
- save_suppress = info->suppress_expansion;
- if (convert_local_omp_clauses (&OMP_PARALLEL_CLAUSES (t), wi))
- {
- tree c;
- (void) get_frame_type (info);
- c = build_omp_clause (OMP_CLAUSE_SHARED);
- OMP_CLAUSE_DECL (c) = info->frame_decl;
- OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
- OMP_PARALLEL_CLAUSES (t) = c;
- }
-
- save_local_var_chain = info->new_local_var_chain;
- info->new_local_var_chain = NULL;
-
- walk_body (convert_local_reference, info, &OMP_PARALLEL_BODY (t));
-
- if (info->new_local_var_chain)
- declare_vars (info->new_local_var_chain, OMP_PARALLEL_BODY (t), false);
- info->new_local_var_chain = save_local_var_chain;
- info->suppress_expansion = save_suppress;
- break;
-
- case OMP_FOR:
- case OMP_SECTIONS:
- case OMP_SINGLE:
- save_suppress = info->suppress_expansion;
- convert_local_omp_clauses (&OMP_CLAUSES (t), wi);
- walk_body (convert_local_reference, info, &OMP_BODY (t));
- info->suppress_expansion = save_suppress;
- break;
-
- case OMP_SECTION:
- case OMP_MASTER:
- case OMP_ORDERED:
- walk_body (convert_local_reference, info, &OMP_BODY (t));
- break;
-
default:
if (!IS_TYPE_OR_DECL_P (t))
{
@@ -1377,6 +1267,10 @@ convert_local_reference (tree *tp, int *
return NULL_TREE;
}
+
+/* Helper for convert_local_reference. Convert all the references in
+ the chain of clauses at *PCLAUSES. WI is as in convert_local_reference. */
+
static bool
convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
{
@@ -1422,7 +1316,8 @@ convert_local_omp_clauses (tree *pclause
case OMP_CLAUSE_NUM_THREADS:
wi->val_only = true;
wi->is_lhs = false;
- convert_local_reference (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, wi);
+ convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy,
+ wi);
break;
case OMP_CLAUSE_NOWAIT:
@@ -1441,27 +1336,97 @@ convert_local_omp_clauses (tree *pclause
return need_frame;
}
-/* Called via walk_function+walk_tree, rewrite all GOTO_EXPRs that
- reference labels from outer functions. The rewrite will be a
+
+/* Called via walk_function+walk_gimple_stmt, rewrite all references to VAR
+ and PARM_DECLs that were referenced by inner nested functions.
+ The rewrite will be a structure reference to the local frame variable. */
+
+static bool
+convert_local_reference_stmt (gimple stmt, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+ struct nesting_info *info = wi->info;
+ tree save_local_var_chain;
+ bitmap save_suppress;
+
+ switch (gimple_code (stmt))
+ {
+ case OMP_PARALLEL:
+ save_suppress = info->suppress_expansion;
+ if (convert_local_omp_clauses (gimple_omp_parallel_clauses_ptr (stmt),
+ wi))
+ {
+ tree c;
+ (void) get_frame_type (info);
+ c = build_omp_clause (OMP_CLAUSE_SHARED);
+ OMP_CLAUSE_DECL (c) = info->frame_decl;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
+ gimple_omp_parallel_set_clauses (stmt, c);
+ }
+
+ save_local_var_chain = info->new_local_var_chain;
+ info->new_local_var_chain = NULL;
+
+ walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
+ gimple_omp_body (stmt));
+
+ if (info->new_local_var_chain)
+ declare_vars (info->new_local_var_chain,
+ gimple_seq_first (gimple_omp_body (stmt)), false);
+ info->new_local_var_chain = save_local_var_chain;
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_FOR:
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ save_suppress = info->suppress_expansion;
+ convert_local_omp_clauses (gimple_omp_parallel_clauses_ptr (stmt), wi);
+ walk_body (convert_local_reference_stmt, convert_local_reference_op,
+ info, gimple_omp_body (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case OMP_SECTION:
+ case OMP_MASTER:
+ case OMP_ORDERED:
+ walk_body (convert_local_reference_stmt, convert_local_reference_op,
+ info, gimple_omp_body (stmt));
+ break;
+
+ default:
+ /* For every other statement that we are not interested in
+ handling here, let the walker traverse the operands. */
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_GOTOs
+ that reference labels from outer functions. The rewrite will be a
call to __builtin_nonlocal_goto. */
-static tree
-convert_nl_goto_reference (tree *tp, int *walk_subtrees, void *data)
+static bool
+convert_nl_goto_reference (gimple stmt, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info, *i;
- tree t = *tp, label, new_label, target_context, x, field;
+ tree label, new_label, target_context, x, field;
void **slot;
+ gimple call;
- *walk_subtrees = 0;
- if (TREE_CODE (t) != GOTO_EXPR)
- return NULL_TREE;
- label = GOTO_DESTINATION (t);
+ if (gimple_code (stmt) != GIMPLE_GOTO)
+ return false;
+
+ label = gimple_goto_dest (stmt);
if (TREE_CODE (label) != LABEL_DECL)
- return NULL_TREE;
+ return false;
+
target_context = decl_function_context (label);
if (target_context == info->context)
- return NULL_TREE;
+ return false;
for (i = info->outer; target_context != i->context; i = i->outer)
continue;
@@ -1485,16 +1450,14 @@ convert_nl_goto_reference (tree *tp, int
/* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field). */
field = get_nl_goto_field (i);
- x = get_frame_field (info, target_context, field, &wi->tsi);
+ x = get_frame_field (info, target_context, field, wi->gsi);
x = build_addr (x, target_context);
- x = tsi_gimplify_val (info, x, &wi->tsi);
- x = build_call_expr (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
- build_addr (new_label, target_context), x);
-
- SET_EXPR_LOCUS (x, EXPR_LOCUS (tsi_stmt (wi->tsi)));
- *tsi_stmt_ptr (wi->tsi) = x;
+ x = gsi_gimplify_val (info, x, wi->gsi);
+ call = build_gimple_call (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
+ build_addr (new_label, target_context), x);
+ gsi_replace (wi->gsi, call, false);
- return NULL_TREE;
+ return false;
}
/* Called via walk_function+walk_tree, rewrite all LABEL_EXPRs that
@@ -1508,9 +1471,10 @@ convert_nl_goto_receiver (tree *tp, int
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
- tree t = *tp, label, new_label, x;
- tree_stmt_iterator tmp_tsi;
+ tree t = *tp, label, new_label;
+ gimple_stmt_iterator *tmp_gsi;
void **slot;
+ gimple stmt;
*walk_subtrees = 0;
if (TREE_CODE (t) != LABEL_EXPR)
@@ -1523,31 +1487,33 @@ convert_nl_goto_receiver (tree *tp, int
/* If there's any possibility that the previous statement falls through,
then we must branch around the new non-local label. */
- tmp_tsi = wi->tsi;
- tsi_prev (&tmp_tsi);
- if (tsi_end_p (tmp_tsi) || block_may_fallthru (tsi_stmt (tmp_tsi)))
+ tmp_gsi = wi->gsi;
+ gsi_prev (tmp_gsi);
+ if (gsi_end_p (tmp_gsi) || gimple_stmt_may_fallthru (gsi_stmt (tmp_gsi)))
{
- x = build1 (GOTO_EXPR, void_type_node, label);
- tsi_link_before (&wi->tsi, x, TSI_SAME_STMT);
+ gimple stmt = build_gimple_goto (label);
+ gsi_link_before (wi->gsi, stmt, GSI_SAME_STMT);
}
new_label = (tree) *slot;
- x = build1 (LABEL_EXPR, void_type_node, new_label);
- tsi_link_before (&wi->tsi, x, TSI_SAME_STMT);
+ stmt = build_gimple_label (new_label);
+ gsi_link_before (wi->gsi, stmt, GSI_SAME_STMT);
return NULL_TREE;
}
-/* Called via walk_function+walk_tree, rewrite all references to addresses
+
+/* Called via walk_function+walk_stmt, rewrite all references to addresses
of nested functions that require the use of trampolines. The rewrite
will involve a reference a trampoline generated for the occasion. */
static tree
-convert_tramp_reference (tree *tp, int *walk_subtrees, void *data)
+convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info, *i;
- tree t = *tp, decl, target_context, x;
+ tree t = *tp, decl, target_context, x, builtin;
+ gimple call;
*walk_subtrees = 0;
switch (TREE_CODE (t))
@@ -1580,84 +1546,99 @@ convert_tramp_reference (tree *tp, int *
x = lookup_tramp_for_decl (i, decl, INSERT);
/* Compute the address of the field holding the trampoline. */
- x = get_frame_field (info, target_context, x, &wi->tsi);
+ x = get_frame_field (info, target_context, x, wi->gsi);
x = build_addr (x, target_context);
- x = tsi_gimplify_val (info, x, &wi->tsi);
+ x = gsi_gimplify_val (info, x, wi->gsi);
/* Do machine-specific ugliness. Normally this will involve
computing extra alignment, but it can really be anything. */
- x = build_call_expr (implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE],
- 1, x);
- x = init_tmp_var (info, x, &wi->tsi);
+ builtin = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
+ call = build_gimple_call (builtin, 1, x);
+ x = init_tmp_var_with_call (info, wi->gsi, call);
/* Cast back to the proper function type. */
x = build1 (NOP_EXPR, TREE_TYPE (t), x);
- x = init_tmp_var (info, x, &wi->tsi);
+ x = init_tmp_var (info, x, wi->gsi);
*tp = x;
break;
- case CALL_EXPR:
+ default:
+ if (!IS_TYPE_OR_DECL_P (t))
+ *walk_subtrees = 1;
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Called via walk_function+walk_gimple_stmt, rewrite all references
+ to addresses of nested functions that require the use of
+ trampolines. The rewrite will involve a reference a trampoline
+ generated for the occasion. */
+
+static bool
+convert_tramp_reference_stmt (gimple stmt, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_CALL:
/* Only walk call arguments, lest we generate trampolines for
direct calls. */
{
- int nargs = call_expr_nargs (t);
- int i;
+ unsigned long i, nargs = gimple_call_nargs (stmt);
for (i = 0; i < nargs; i++)
- walk_tree (&CALL_EXPR_ARG (t, i), convert_tramp_reference, wi, NULL);
+ walk_tree (gimple_call_arg_ptr (stmt, i), convert_tramp_reference_op,
+ wi, NULL);
+
+ return false;
}
- break;
default:
- if (!IS_TYPE_OR_DECL_P (t))
- *walk_subtrees = 1;
break;
}
- return NULL_TREE;
+ return true;
}
-/* Called via walk_function+walk_tree, rewrite all CALL_EXPRs that
- reference nested functions to make sure that the static chain is
- set up properly for the call. */
-static tree
-convert_call_expr (tree *tp, int *walk_subtrees, void *data)
+
+/* Called via walk_function+walk_gimple_stmt, rewrite all GIMPLE_CALLs
+ that reference nested functions to make sure that the static chain
+ is set up properly for the call. */
+
+static bool
+convert_gimple_call (gimple stmt, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
struct nesting_info *info = wi->info;
- tree t = *tp, decl, target_context;
+ tree decl, target_context;
char save_static_chain_added;
int i;
- *walk_subtrees = 0;
- switch (TREE_CODE (t))
+ switch (gimple_code (stmt))
{
- case CALL_EXPR:
- decl = get_callee_fndecl (t);
- if (!decl)
+ case GIMPLE_CALL:
+ decl = gimple_call_fn (stmt);
+ if (TREE_CODE (decl) != FUNCTION_DECL)
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
{
- CALL_EXPR_STATIC_CHAIN (t)
- = get_static_chain (info, target_context, &wi->tsi);
+ gimple_call_set_chain (stmt, get_static_chain (info, target_context,
+ wi->gsi));
info->static_chain_added
|= (1 << (info->context != target_context));
}
break;
- case RETURN_EXPR:
- case GIMPLE_MODIFY_STMT:
- case WITH_SIZE_EXPR:
- /* Only return modify and with_size_expr may contain calls. */
- *walk_subtrees = 1;
- break;
-
- case OMP_PARALLEL:
+ case GIMPLE_OMP_PARALLEL:
save_static_chain_added = info->static_chain_added;
info->static_chain_added = 0;
- walk_body (convert_call_expr, info, &OMP_PARALLEL_BODY (t));
+ walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
for (i = 0; i < 2; i++)
{
tree c, decl;
@@ -1665,7 +1646,9 @@ convert_call_expr (tree *tp, int *walk_s
continue;
decl = i ? get_chain_decl (info) : info->frame_decl;
/* Don't add CHAIN.* or FRAME.* twice. */
- for (c = OMP_PARALLEL_CLAUSES (t); c; c = OMP_CLAUSE_CHAIN (c))
+ for (c = gimple_omp_parallel_clauses (stmt);
+ c;
+ c = OMP_CLAUSE_CHAIN (c))
if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
&& OMP_CLAUSE_DECL (c) == decl)
@@ -1674,30 +1657,31 @@ convert_call_expr (tree *tp, int *walk_s
{
c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
OMP_CLAUSE_DECL (c) = decl;
- OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (t);
- OMP_PARALLEL_CLAUSES (t) = c;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
+ gimple_omp_parallel_set_clauses (stmt, c);
}
}
info->static_chain_added |= save_static_chain_added;
break;
- case OMP_FOR:
- case OMP_SECTIONS:
- case OMP_SECTION:
- case OMP_SINGLE:
- case OMP_MASTER:
- case OMP_ORDERED:
- case OMP_CRITICAL:
- walk_body (convert_call_expr, info, &OMP_BODY (t));
+ case GIMPLE_OMP_FOR:
+ case GIMPLE_OMP_SECTIONS:
+ case GIMPLE_OMP_SECTION:
+ case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_CRITICAL:
+ walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
break;
default:
break;
}
- return NULL_TREE;
+ return false;
}
+
/* Walk the nesting tree starting with ROOT, depth first. Convert all
trampolines and call expressions. On the way back up, determine if
a nested function actually uses its static chain; if not, remember that. */
@@ -1710,8 +1694,9 @@ convert_all_function_calls (struct nesti
if (root->inner)
convert_all_function_calls (root->inner);
- walk_function (convert_tramp_reference, root);
- walk_function (convert_call_expr, root);
+ walk_function (convert_tramp_reference_stmt, convert_tramp_reference_op,
+ root);
+ walk_function (convert_gimple_call, NULL, root);
/* If the function does not use a static chain, then remember that. */
if (root->outer && !root->chain_decl && !root->chain_field)
@@ -1732,10 +1717,13 @@ convert_all_function_calls (struct nesti
static void
finalize_nesting_tree_1 (struct nesting_info *root)
{
- tree stmt_list = NULL;
+ gimple_seq stmt_list;
+ gimple stmt;
tree context = root->context;
struct function *sf;
+ stmt_list = gimple_seq_alloc ();
+
/* If we created a non-local frame type or decl, we need to lay them
out at this time. */
if (root->frame_type)
@@ -1770,8 +1758,8 @@ finalize_nesting_tree_1 (struct nesting_
y = build3 (COMPONENT_REF, TREE_TYPE (field),
root->frame_decl, field, NULL_TREE);
- x = build_gimple_modify_stmt (y, x);
- append_to_statement_list (x, &stmt_list);
+ stmt = build_gimple_assign (y, x);
+ gimple_seq_add (stmt_list, stmt);
}
}
@@ -1781,8 +1769,8 @@ finalize_nesting_tree_1 (struct nesting_
{
tree x = build3 (COMPONENT_REF, TREE_TYPE (root->chain_field),
root->frame_decl, root->chain_field, NULL_TREE);
- x = build_gimple_modify_stmt (x, get_chain_decl (root));
- append_to_statement_list (x, &stmt_list);
+ stmt = build_gimple_assign (x, get_chain_decl (root));
+ gimple_seq_add (stmt_list, stmt);
}
/* If trampolines were created, then we need to initialize them. */
@@ -1809,19 +1797,19 @@ finalize_nesting_tree_1 (struct nesting_
arg1 = build_addr (x, context);
x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
- x = build_call_expr (x, 3, arg1, arg2, arg3);
- append_to_statement_list (x, &stmt_list);
+ stmt = build_gimple_call (x, 3, arg1, arg2, arg3);
+ gimple_seq_add (stmt_list, stmt);
}
}
/* If we created initialization statements, insert them. */
if (stmt_list)
{
- annotate_all_with_locus (&stmt_list,
- DECL_SOURCE_LOCATION (context));
- append_to_statement_list (BIND_EXPR_BODY (DECL_SAVED_TREE (context)),
- &stmt_list);
- BIND_EXPR_BODY (DECL_SAVED_TREE (context)) = stmt_list;
+ gimple bind;
+ annotate_all_with_locus (stmt_list, DECL_SOURCE_LOCATION (context));
+ bind = gimple_seq_first (gimple_body (context));
+ gimple_seq_append (stmt_list, gimple_bind_body (bind));
+ gimple_bind_set_body (bind, stmt_list);
}
/* If a chain_decl was created, then it needs to be registered with
@@ -1841,10 +1829,12 @@ finalize_nesting_tree_1 (struct nesting_
/* Make sure all new local variables get inserted into the
proper BIND_EXPR. */
if (root->new_local_var_chain)
- declare_vars (root->new_local_var_chain, DECL_SAVED_TREE (root->context),
+ declare_vars (root->new_local_var_chain,
+ gimple_seq_first (gimple_body (root->context)),
false);
if (root->debug_var_chain)
- declare_vars (root->debug_var_chain, DECL_SAVED_TREE (root->context),
+ declare_vars (root->debug_var_chain,
+ gimple_seq_first (gimple_body (root->context)),
true);
/* Dump the translated tree function. */
@@ -1928,10 +1918,14 @@ lower_nested_functions (tree fndecl)
bitmap_obstack_initialize (&nesting_info_bitmap_obstack);
root = create_nesting_tree (cgn);
- walk_all_functions (convert_nonlocal_reference, root);
- walk_all_functions (convert_local_reference, root);
- walk_all_functions (convert_nl_goto_reference, root);
- walk_all_functions (convert_nl_goto_receiver, root);
+ walk_all_functions (convert_nonlocal_reference_stmt,
+ convert_nonlocal_reference_op,
+ root);
+ walk_all_functions (convert_local_reference_stmt,
+ convert_local_reference_op,
+ root);
+ walk_all_functions (convert_nl_goto_reference, NULL, root);
+ walk_all_functions (NULL, convert_nl_goto_receiver, root);
convert_all_function_calls (root);
finalize_nesting_tree (root);
unnest_nesting_tree (root);
Index: tree-flow.h
===================================================================
--- tree-flow.h (revision 127800)
+++ tree-flow.h (working copy)
@@ -826,6 +826,7 @@ extern void record_vars_into (tree, tree
extern void record_vars (tree);
extern bool block_may_fallthru (tree);
extern bool gimple_seq_may_fallthru (gimple_seq);
+extern bool gimple_stmt_may_fallthru (gimple);
/* In tree-ssa-alias.c */
extern void dump_may_aliases_for (FILE *, tree);
Index: Makefile.in
===================================================================
--- Makefile.in (revision 127800)
+++ Makefile.in (working copy)
@@ -759,8 +759,8 @@ BUILTINS_DEF = builtins.def sync-builtin
TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h $(BUILTINS_DEF) \
input.h statistics.h vec.h treestruct.def $(HASHTAB_H) \
double-int.h
-GIMPLE_H = gimple.h gimple.def gsstruct.def gimple-iterator.h \
- pointer-set.h vec.h
+GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h vec.h \
+ gimple-iterator.h
BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
hard-reg-set.h cfghooks.h $(OBSTACK_H)
GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
Index: gimple.c
===================================================================
--- gimple.c (revision 127800)
+++ gimple.c (working copy)
@@ -834,7 +834,7 @@ gimple_range_check_failed (const gimple
/* Link a gimple statement(s) to the end of the sequence SEQ. */
void
-gimple_add (gimple_seq seq, gimple gs)
+gimple_seq_add (gimple_seq seq, gimple gs)
{
/* Make sure this stmt is not part of another chain. */
gcc_assert (gimple_prev (gs) == NULL && gimple_next (gs) == NULL);
@@ -878,120 +878,193 @@ gimple_seq_append (gimple_seq dst, gimpl
}
-/* Visit all the tuples in sequence SEQ, and apply FUNC to all the tree leaves
- in the tuples. The trees in the tuples encountered will be walked with
- walk_tree(). FUNC, DATA, and PSET are as in walk_tree.
-
- You cannot use this function to rewrite trees, as the address of
- thre trees passed to walk_tree are local to this function.
- Besides, you shouldn't be rewriting trees this late in the
- game. */
+/* Walk all the statements in the sequence SEQ calling walk_gimple_stmt
+ on each one. WI is as in walk_gimple_stmt. */
void
-walk_seq_ops (gimple_seq seq, walk_tree_fn func, void *data,
- struct pointer_set_t *pset)
+walk_gimple_seq (gimple_seq seq, struct walk_stmt_info *wi)
{
gimple_stmt_iterator *gsi;
for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (gsi))
- walk_tuple_ops (gsi_stmt (gsi), func, data, pset);
+ {
+ wi->gsi = gsi;
+ walk_gimple_stmt (gsi_stmt (gsi), wi);
+ }
}
-/* Helper function of walk_seq_ops. Walks one tuple's trees. The
- arguments are as in walk_seq_ops, except GS is the tuple to
- walk. */
-#define WALKIT(__this) leaf = (__this), walk_tree (&leaf, func, data, pset)
+/* Helper function for walk_gimple_stmt. Walk operands of a GIMPLE_ASM. */
+
+static void
+walk_gimple_asm (gimple stmt, struct walk_stmt_info *wi)
+{
+ unsigned noutputs = gimple_asm_noutputs (stmt);
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ unsigned i;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+
+ wi->is_lhs = true;
+ for (i = 0; i < noutputs; i++)
+ {
+ tree op = gimple_asm_output_op (stmt, i);
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (op));
+ oconstraints[i] = constraint;
+ parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg,
+ &is_inout);
+ wi->val_only = (allows_reg || !allows_mem);
+ walk_tree (&TREE_VALUE (op), wi->callback_op, wi, NULL);
+ }
+
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ {
+ tree op = gimple_asm_input_op (stmt, i);
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (op));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+ wi->val_only = (allows_reg || !allows_mem);
+
+ /* Although input "m" is not really a LHS, we need a lvalue. */
+ wi->is_lhs = !wi->val_only;
+ walk_tree (&TREE_VALUE (op), wi->callback_op, wi, NULL);
+ }
+
+ wi->is_lhs = false;
+ wi->val_only = true;
+}
+
+
+
+/* Walk GIMPLE statement STMT using traversal state stored in WI. The
+ callback WI->CALLBACK_STMT is called and then the operands of STMT
+ are traversed, calling WI->CALLBACK_OP on each one. */
+
void
-walk_tuple_ops (gimple gs, walk_tree_fn func, void *data,
- struct pointer_set_t *pset)
+walk_gimple_stmt (gimple stmt, struct walk_stmt_info *wi)
{
unsigned int i;
- tree leaf;
enum gimple_statement_structure_enum gss;
- gss = gimple_statement_structure (gs);
- if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS || gss == GSS_ASM)
- for (i = 0; i < gimple_num_ops (gs); i++)
- WALKIT (gimple_op (gs, i));
- else
- switch (gimple_code (gs))
- {
- case GIMPLE_BIND:
- WALKIT (gimple_bind_vars (gs));
- walk_seq_ops (gimple_bind_body (gs), func, data, pset);
- break;
+ if (wi->want_locations && !gimple_locus_empty_p (stmt))
+ input_location = gimple_locus (stmt);
- case GIMPLE_CATCH:
- WALKIT (gimple_catch_types (gs));
- walk_seq_ops (gimple_catch_handler (gs), func, data, pset);
- break;
+ /* Invoke the statement callback. Return if the callback handled
+ all of STMT operands by itself. */
+ if (wi->callback_stmt)
+ if (wi->callback_stmt (stmt, wi) == false)
+ return;
- case GIMPLE_EH_FILTER:
- WALKIT (gimple_eh_filter_types (gs));
- walk_seq_ops (gimple_eh_filter_failure (gs), func, data, pset);
- break;
+ /* If no callback was defined for operands, ignore them. */
+ if (wi->callback_op == NULL)
+ return;
- case GIMPLE_PHI:
- WALKIT (gimple_phi_result (gs));
- break;
+ /* Invoke WI->CALLBACK_OP on every operand of STMT. */
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_ASSIGN:
+ /* A formal temporary LHS may use a COMPONENT_REF RHS. */
+ wi->val_only = !is_gimple_formal_tmp_var (gimple_assign_lhs (stmt));
+ walk_tree (gimple_op_ptr (stmt, 1), wi->callback_op, wi, NULL);
- case GIMPLE_TRY:
- walk_seq_ops (gimple_try_eval (gs), func, data, pset);
- walk_seq_ops (gimple_try_cleanup (gs), func, data, pset);
- break;
+ /* If the RHS is appropriate for a memory, we may use a
+ COMPONENT_REF on the LHS. */
+ wi->val_only = !is_gimple_mem_rhs (gimple_assign_rhs1 (stmt));
+ wi->is_lhs = true;
+ walk_tree (gimple_op_ptr (stmt, 0), wi->callback_op, wi, NULL);
- case GIMPLE_OMP_CRITICAL:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- WALKIT (gimple_omp_critical_name (gs));
- break;
+ wi->val_only = true;
+ wi->is_lhs = false;
+ break;
- /* Just a body. */
- case GIMPLE_OMP_CONTINUE:
- case GIMPLE_OMP_MASTER:
- case GIMPLE_OMP_ORDERED:
- case GIMPLE_OMP_SECTION:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- break;
+ case GIMPLE_BIND:
+ walk_gimple_seq (gimple_bind_body (stmt), wi);
+ break;
- case GIMPLE_OMP_FOR:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- WALKIT (gimple_omp_for_clauses (gs));
- WALKIT (gimple_omp_for_index (gs));
- WALKIT (gimple_omp_for_initial (gs));
- WALKIT (gimple_omp_for_final (gs));
- WALKIT (gimple_omp_for_incr (gs));
- walk_seq_ops (gimple_omp_for_pre_body (gs), func, data, pset);
- break;
+ case GIMPLE_CATCH:
+ walk_tree (gimple_catch_types_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_gimple_seq (gimple_catch_handler (stmt), wi);
+ break;
- case GIMPLE_OMP_PARALLEL:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- WALKIT (gimple_omp_parallel_clauses (gs));
- WALKIT (gimple_omp_parallel_child_fn (gs));
- WALKIT (gimple_omp_parallel_data_arg (gs));
- break;
+ case GIMPLE_EH_FILTER:
+ walk_tree (gimple_eh_filter_types_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_gimple_seq (gimple_eh_filter_failure (stmt), wi);
+ break;
- case GIMPLE_OMP_SECTIONS:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- WALKIT (gimple_omp_sections_clauses (gs));
- break;
+ case GIMPLE_TRY:
+ walk_gimple_seq (gimple_try_eval (stmt), wi);
+ walk_gimple_seq (gimple_try_cleanup (stmt), wi);
+ break;
- case GIMPLE_OMP_SINGLE:
- walk_seq_ops (gimple_omp_body (gs), func, data, pset);
- WALKIT (gimple_omp_single_clauses (gs));
- break;
+ case GIMPLE_ASM:
+ walk_gimple_asm (stmt, wi);
+ break;
- /* Tuples that do not have trees. */
- case GIMPLE_NOP:
- case GIMPLE_RESX:
- case GIMPLE_OMP_RETURN:
- break;
+ case GIMPLE_OMP_CRITICAL:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ walk_tree (gimple_omp_critical_name_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ break;
- default:
- debug_gimple_stmt (gs);
- gcc_unreachable ();
- break;
- }
+ /* Just a body. */
+ case GIMPLE_OMP_CONTINUE:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SECTION:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ break;
+
+ case GIMPLE_OMP_FOR:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ walk_tree (gimple_omp_for_clauses_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_tree (gimple_omp_for_index_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_tree (gimple_omp_for_initial_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_tree (gimple_omp_for_final_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_tree (gimple_omp_for_incr_ptr (stmt), wi->callback_op, wi, NULL);
+ walk_gimple_seq (gimple_omp_for_pre_body (stmt), wi);
+ break;
+
+ case GIMPLE_OMP_PARALLEL:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ walk_tree (gimple_omp_parallel_clauses_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ walk_tree (gimple_omp_parallel_child_fn_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ walk_tree (gimple_omp_parallel_data_arg_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ break;
+
+ case GIMPLE_OMP_SECTIONS:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ walk_tree (gimple_omp_sections_clauses_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ break;
+
+ case GIMPLE_OMP_SINGLE:
+ walk_gimple_seq (gimple_omp_body (stmt), wi);
+ walk_tree (gimple_omp_single_clauses_ptr (stmt), wi->callback_op, wi,
+ NULL);
+ break;
+
+ /* Tuples that do not have operands. */
+ case GIMPLE_NOP:
+ case GIMPLE_RESX:
+ case GIMPLE_OMP_RETURN:
+ break;
+
+ default:
+ gss = gimple_statement_structure (stmt);
+ if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ walk_tree (gimple_op_ptr (stmt, i), wi->callback_op, wi, NULL);
+ else
+ {
+ debug_gimple_stmt (stmt);
+ gcc_unreachable ();
+ }
+ break;
+ }
}
Index: gimple.h
===================================================================
--- gimple.h (revision 127800)
+++ gimple.h (working copy)
@@ -24,6 +24,7 @@ Software Foundation, 51 Franklin Street,
#define GCC_GIMPLE_IR_H
#include "pointer-set.h"
+#include "ggc.h"
DEF_VEC_P(gimple);
DEF_VEC_ALLOC_P(gimple,heap);
@@ -79,6 +80,12 @@ gimple_seq_init (gimple_seq s)
s->last = NULL;
}
+static inline gimple_seq
+gimple_seq_alloc (void)
+{
+ return (gimple_seq) ggc_alloc_cleared (sizeof (struct gimple_sequence));
+}
+
/* Copy the sequence SRC into the sequence DEST. */
static inline void
@@ -321,7 +328,6 @@ union gimple_statement_d GTY ((desc ("gi
struct gimple_statement_omp_single GTY ((tag ("GSS_OMP_SINGLE"))) gimple_omp_single;
};
-
/* Set PREV to be the previous statement to G. */
static inline void
@@ -453,7 +459,6 @@ set_gimple_modified (gimple g, bool modi
g->with_ops.modified = (unsigned) modifiedp;
}
-
/* Returns TRUE if a statement is a GIMPLE_OMP_RETURN and has the
OMP_RETURN_NOWAIT_FLAG set. */
@@ -488,50 +493,45 @@ gimple_omp_parallel_combined_p (gimple g
/* Prototypes in gimple.c. */
-extern gimple build_gimple_return (bool, tree);
-extern gimple build_gimple_assign (tree, tree);
-extern gimple build_gimple_call_vec (tree, VEC(tree, gc) *);
-extern gimple build_gimple_call (tree, size_t, ...);
-extern gimple build_gimple_cond (enum gimple_cond, tree, tree, tree, tree);
-extern void gimple_cond_invert (gimple);
-extern gimple build_gimple_label (tree label);
-extern gimple build_gimple_goto (tree dest);
-extern gimple build_gimple_nop (void);
-extern gimple build_gimple_bind (tree, gimple_seq);
-extern gimple build_gimple_asm (const char *, unsigned, unsigned, unsigned,
- ...);
-extern gimple build_gimple_asm_vec (const char *, VEC(tree,gc) * ,
- VEC(tree,gc) *, VEC(tree,gc) *);
-extern gimple build_gimple_catch (tree, gimple_seq);
-extern gimple build_gimple_eh_filter (tree, gimple_seq);
-extern gimple build_gimple_try (gimple_seq, gimple_seq, unsigned int);
-extern gimple build_gimple_phi (unsigned, unsigned, tree, ...);
-extern gimple build_gimple_resx (int);
-extern gimple build_gimple_switch (unsigned int, tree, tree, ...);
-extern gimple build_gimple_switch_vec (tree, tree, VEC(tree,heap) *);
-extern gimple build_gimple_omp_parallel (gimple_seq, tree, tree, tree);
-extern gimple build_gimple_omp_for (gimple_seq, tree, tree, tree, tree, tree,
- gimple_seq, enum gimple_cond);
-extern gimple build_gimple_omp_critical (gimple_seq, tree);
-extern gimple build_gimple_omp_section (gimple_seq);
-extern gimple build_gimple_omp_continue (gimple_seq);
-extern gimple build_gimple_omp_master (gimple_seq);
-extern gimple build_gimple_omp_return (bool);
-extern gimple build_gimple_omp_ordered (gimple_seq);
-extern gimple build_gimple_omp_sections (gimple_seq, tree);
-extern gimple build_gimple_omp_single (gimple_seq, tree);
-extern enum gimple_statement_structure_enum gimple_statement_structure (gimple);
-extern void gimple_add (gimple_seq, gimple);
-extern enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
-extern void sort_case_labels (VEC(tree,heap) *);
-extern void walk_tuple_ops (gimple, walk_tree_fn, void *,
- struct pointer_set_t *);
-extern void walk_seq_ops (gimple_seq, walk_tree_fn, void *,
- struct pointer_set_t *);
-extern void set_gimple_body (tree, gimple_seq);
-extern gimple_seq gimple_body (tree);
-extern void gimple_seq_append (gimple_seq, gimple_seq);
-extern int gimple_call_flags (gimple);
+gimple build_gimple_return (bool, tree);
+gimple build_gimple_assign (tree, tree);
+gimple build_gimple_call_vec (tree, VEC(tree, gc) *);
+gimple build_gimple_call (tree, size_t, ...);
+gimple build_gimple_cond (enum gimple_cond, tree, tree, tree, tree);
+void gimple_cond_invert (gimple);
+gimple build_gimple_label (tree label);
+gimple build_gimple_goto (tree dest);
+gimple build_gimple_nop (void);
+gimple build_gimple_bind (tree, gimple_seq);
+gimple build_gimple_asm (const char *, unsigned, unsigned, unsigned, ...);
+gimple build_gimple_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *,
+ VEC(tree,gc) *);
+gimple build_gimple_catch (tree, gimple_seq);
+gimple build_gimple_eh_filter (tree, gimple_seq);
+gimple build_gimple_try (gimple_seq, gimple_seq, unsigned int);
+gimple build_gimple_phi (unsigned, unsigned, tree, ...);
+gimple build_gimple_resx (int);
+gimple build_gimple_switch (unsigned int, tree, tree, ...);
+gimple build_gimple_switch_vec (tree, tree, VEC(tree,heap) *);
+gimple build_gimple_omp_parallel (gimple_seq, tree, tree, tree);
+gimple build_gimple_omp_for (gimple_seq, tree, tree, tree, tree, tree,
+ gimple_seq, enum gimple_cond);
+gimple build_gimple_omp_critical (gimple_seq, tree);
+gimple build_gimple_omp_section (gimple_seq);
+gimple build_gimple_omp_continue (gimple_seq);
+gimple build_gimple_omp_master (gimple_seq);
+gimple build_gimple_omp_return (bool);
+gimple build_gimple_omp_ordered (gimple_seq);
+gimple build_gimple_omp_sections (gimple_seq, tree);
+gimple build_gimple_omp_single (gimple_seq, tree);
+enum gimple_statement_structure_enum gimple_statement_structure (gimple);
+void gimple_seq_add (gimple_seq, gimple);
+enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
+void sort_case_labels (VEC(tree,heap) *);
+void set_gimple_body (tree, gimple_seq);
+gimple_seq gimple_body (tree);
+void gimple_seq_append (gimple_seq, gimple_seq);
+int gimple_call_flags (gimple);
extern const char *const gimple_code_name[];
@@ -595,6 +595,14 @@ gimple_op (gimple gs, size_t i)
return gs->with_ops.op[i];
}
+static inline tree *
+gimple_op_ptr (gimple gs, size_t i)
+{
+ GIMPLE_RANGE_CHECK (gs, GIMPLE_ASSIGN, GIMPLE_RETURN);
+ gcc_assert (i < gs->with_ops.num_ops);
+ return &gs->with_ops.op[i];
+}
+
static inline void
gimple_set_op (gimple gs, size_t i, tree op)
{
@@ -749,6 +757,14 @@ gimple_call_arg (gimple gs, size_t index
return gs->with_ops.op[index + 3];
}
+static inline tree *
+gimple_call_arg_ptr (gimple gs, size_t index)
+{
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
+ gcc_assert (gs->with_ops.num_ops > index + 3);
+ return &gs->with_ops.op[index + 3];
+}
+
static inline void
gimple_call_set_arg (gimple gs, size_t index, tree arg)
{
@@ -996,6 +1012,13 @@ gimple_catch_types (gimple gs)
return gs->gimple_catch.types;
}
+static inline tree *
+gimple_catch_types_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_CATCH);
+ return &gs->gimple_catch.types;
+}
+
static inline gimple_seq
gimple_catch_handler (gimple gs)
{
@@ -1027,6 +1050,13 @@ gimple_eh_filter_types (gimple gs)
return gs->gimple_eh_filter.types;
}
+static inline tree *
+gimple_eh_filter_types_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
+ return &gs->gimple_eh_filter.types;
+}
+
static inline gimple_seq
gimple_eh_filter_failure (gimple gs)
{
@@ -1250,6 +1280,13 @@ gimple_omp_critical_name (gimple gs)
return gs->gimple_omp_critical.name;
}
+static inline tree *
+gimple_omp_critical_name_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
+ return &gs->gimple_omp_critical.name;
+}
+
static inline void
gimple_omp_critical_set_name (gimple gs, tree name)
{
@@ -1266,6 +1303,13 @@ gimple_omp_for_clauses (gimple gs)
return gs->gimple_omp_for.clauses;
}
+static inline tree *
+gimple_omp_for_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+ return &gs->gimple_omp_for.clauses;
+}
+
static inline void
gimple_omp_for_set_clauses (gimple gs, tree clauses)
{
@@ -1280,6 +1324,13 @@ gimple_omp_for_index (gimple gs)
return gs->gimple_omp_for.index;
}
+static inline tree *
+gimple_omp_for_index_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+ return &gs->gimple_omp_for.index;
+}
+
static inline void
gimple_omp_for_set_index (gimple gs, tree index)
{
@@ -1294,6 +1345,13 @@ gimple_omp_for_initial (gimple gs)
return gs->gimple_omp_for.initial;
}
+static inline tree *
+gimple_omp_for_initial_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+ return &gs->gimple_omp_for.initial;
+}
+
static inline void
gimple_omp_for_set_initial (gimple gs, tree initial)
{
@@ -1308,6 +1366,13 @@ gimple_omp_for_final (gimple gs)
return gs->gimple_omp_for.final;
}
+static inline tree *
+gimple_omp_for_final_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+ return &gs->gimple_omp_for.final;
+}
+
static inline void
gimple_omp_for_set_final (gimple gs, tree final)
{
@@ -1322,6 +1387,13 @@ gimple_omp_for_incr (gimple gs)
return gs->gimple_omp_for.incr;
}
+static inline tree *
+gimple_omp_for_incr_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+ return &gs->gimple_omp_for.incr;
+}
+
static inline void
gimple_omp_for_set_incr (gimple gs, tree incr)
{
@@ -1352,6 +1424,13 @@ gimple_omp_parallel_clauses (gimple gs)
return gs->gimple_omp_parallel.clauses;
}
+static inline tree *
+gimple_omp_parallel_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
+ return &gs->gimple_omp_parallel.clauses;
+}
+
static inline void
gimple_omp_parallel_set_clauses (gimple gs, tree clauses)
{
@@ -1366,6 +1445,13 @@ gimple_omp_parallel_child_fn (gimple gs)
return gs->gimple_omp_parallel.child_fn;
}
+static inline tree *
+gimple_omp_parallel_child_fn_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
+ return &gs->gimple_omp_parallel.child_fn;
+}
+
static inline void
gimple_omp_parallel_set_child_fn (gimple gs, tree child_fn)
{
@@ -1380,6 +1466,13 @@ gimple_omp_parallel_data_arg (gimple gs)
return gs->gimple_omp_parallel.data_arg;
}
+static inline tree *
+gimple_omp_parallel_data_arg_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
+ return &gs->gimple_omp_parallel.data_arg;
+}
+
static inline void
gimple_omp_parallel_set_data_arg (gimple gs, tree data_arg)
{
@@ -1398,6 +1491,13 @@ gimple_omp_single_clauses (gimple gs)
return gs->gimple_omp_single.clauses;
}
+static inline tree *
+gimple_omp_single_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
+ return &gs->gimple_omp_single.clauses;
+}
+
static inline void
gimple_omp_single_set_clauses (gimple gs, tree clauses)
{
@@ -1412,6 +1512,13 @@ gimple_omp_sections_clauses (gimple gs)
return gs->gimple_omp_sections.clauses;
}
+static inline tree *
+gimple_omp_sections_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
+ return &gs->gimple_omp_sections.clauses;
+}
+
static inline void
gimple_omp_sections_set_clauses (gimple gs, tree clauses)
{
@@ -1466,4 +1573,62 @@ gimple_nop_p (gimple g)
#include "gimple-iterator.h"
+/* Callback for walk_gimple_stmt. Called for every statement found
+ during traversal. */
+typedef bool (*walk_stmt_fn) (gimple, 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
+ operand interface should be used to analyze/modify statements. */
+struct walk_stmt_info
+{
+ /* For each statement, we invoke CALLBACK_STMT. The passed
+ data is a walk_stmt_info structure. */
+ walk_stmt_fn callback_stmt;
+
+ /* For each operand in every statement, we invoke CALLBACK_OP via
+ walk_tree. The passed data is a walk_stmt_info structure. */
+ walk_tree_fn callback_op;
+
+ /* Points to the current statement being walked. */
+ gimple_stmt_iterator *gsi;
+
+ /* Additional data that CALLBACK may want to carry through the
+ recursion. */
+ void *info;
+
+ /* Indicates whether the *TP being examined may be replaced
+ with something that matches is_gimple_val (if true) or something
+ slightly more complicated (if false). "Something" technically
+ means the common subset of is_gimple_lvalue and is_gimple_rhs,
+ but we never try to form anything more complicated than that, so
+ we don't bother checking.
+
+ Also note that CALLBACK should update this flag while walking the
+ sub-expressions of a statement. For instance, when walking the
+ statement 'foo (&var)', the flag VAL_ONLY will initially be set
+ to true, however, when walking &var, the operand of that
+ ADDR_EXPR does not need to be a GIMPLE value. */
+ bool val_only;
+
+ /* True if we are currently walking the LHS of an assignment. */
+ bool is_lhs;
+
+ /* Optional. Set to true by CALLBACK if it made any changes. */
+ bool changed;
+
+ /* True if we're interested in seeing BIND_EXPRs. */
+ bool want_bind_expr;
+
+ /* True if we're interested in seeing RETURN_EXPRs. */
+ bool want_return_expr;
+
+ /* True if we're interested in location information. */
+ bool want_locations;
+};
+
+void walk_gimple_seq (gimple_seq, struct walk_stmt_info *);
+void walk_gimple_stmt (gimple, struct walk_stmt_info *);
+
#endif /* GCC_GIMPLE_IR_H */
Index: tree-cfg.c
===================================================================
--- tree-cfg.c (revision 127800)
+++ tree-cfg.c (working copy)
@@ -139,7 +139,7 @@ init_empty_tree_cfg (void)
Create basic blocks
---------------------------------------------------------------------------*/
-/* Entry point to the CFG builder for trees. SEQ to the sequence of
+/* Entry point to the CFG builder for trees. SEQ is the sequence of
statements to be added to the flowgraph. */
static void
@@ -208,7 +208,9 @@ build_gimple_cfg (gimple_seq seq)
static unsigned int
execute_build_cfg (void)
{
+#if 0
build_gimple_cfg (gimple_body (current_function_decl));
+#endif
set_gimple_body (current_function_decl, NULL);
return 0;
}
@@ -222,13 +224,13 @@ struct tree_opt_pass pass_build_cfg =
NULL, /* next */
0, /* static_pass_number */
TV_TREE_CFG, /* tv_id */
- PROP_gimple_leh, /* properties_required */
+ 0, /* FIXME tuples PROP_gimple_leh, *//* properties_required */
PROP_cfg, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_verify_stmts | TODO_cleanup_cfg, /* todo_flags_finish */
+ 0, /* FIXME tuples TODO_verify_stmts | TODO_cleanup_cfg,*/ /* todo_flags_finish */
0 /* letter */
- ,0 /* works_with_tuples_p */
+ ,1 /* works_with_tuples_p */
};
/* Search the CFG for any computed gotos. If found, factor them to a
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 127800)
+++ config/i386/i386.c (working copy)
@@ -5098,9 +5098,9 @@ ix86_gimplify_va_arg (tree valist, tree
gimplify_and_add (t, pre_p);
}
- gimple_add (pre_p, build_gimple_goto (lab_over));
+ gimple_seq_add (pre_p, build_gimple_goto (lab_over));
- gimple_add (pre_p, build_gimple_label (lab_false));
+ gimple_seq_add (pre_p, build_gimple_label (lab_false));
}
/* ... otherwise out of the overflow area. */
@@ -5130,7 +5130,7 @@ ix86_gimplify_va_arg (tree valist, tree
gimplify_and_add (t, pre_p);
if (container)
- gimple_add (pre_p, build_gimple_label (lab_over));
+ gimple_seq_add (pre_p, build_gimple_label (lab_over));
ptrtype = build_pointer_type (type);
addr = fold_convert (ptrtype, addr);