This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]