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]

fix rtlanal.o dependencies


Noticed this while doing other things.


r~


        * Makefile.in (rtlanal.o): Depend on BASIC_BLOCK_H.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.127
diff -u -p -r1.903.2.127 Makefile.in
--- Makefile.in	5 Nov 2003 13:39:22 -0000	1.903.2.127
+++ Makefile.in	9 Nov 2003 09:10:14 -0000
@@ -878,7 +878,7 @@ OBJS-common = \
  tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o         \
  tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o  \
  tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o	   \
- tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o			   \
+ tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o	   \
  alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
  cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
  cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
@@ -1571,6 +1571,8 @@ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $
 tree-tailcall.o : tree-tailcall.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) function.h $(TM_H) coretypes.h \
    $(TREE_DUMP_H) diagnostic.h
+tree-iterator.o : tree-iterator.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+   coretypes.h $(GGC_H) tree-iterator.h tree-simple.h gt-tree-iterator.h
 tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
    errors.h tree-inline.h $(HASHTAB_H) flags.h function.h $(TIMEVAR_H) \
@@ -1656,10 +1658,11 @@ rtl.o : rtl.c $(CONFIG_H) $(SYSTEM_H) co
   $(GGC_H) errors.h
 	$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
-    hard-reg-set.h $(BASIC_BLOCK_H) real.h $(TM_P_H)
-rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(RTL_H) \
-   hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h
+print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+    $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) real.h $(TM_P_H)
+rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \
+   $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h \
+   $(BASIC_BLOCK_H)
 
 errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h
 	$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
@@ -1681,10 +1684,11 @@ except.o : except.c $(CONFIG_H) $(SYSTEM
    langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
    dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \
    gt-except.h cgraph.h
-expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
-   function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h $(INSN_ATTR_H) insn-config.h \
-   $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
-   except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h
+expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+   $(TREE_H) flags.h function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h \
+   $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h typeclass.h \
+   hard-reg-set.h toplev.h hard-reg-set.h except.h reload.h $(GGC_H) \
+   langhooks.h intl.h $(TM_P_H) real.h tree-iterator.h
 dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
    flags.h function.h $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
    langhooks.h
@@ -2204,7 +2208,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/co
   $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parse.in \
   $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
   $(srcdir)/tree-ssa.c $(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-ccp.c \
-  $(srcdir)/tree-ssa-pre.c $(out_file) \
+  $(srcdir)/tree-ssa-pre.c $(srcdir)/tree-iterator.c $(out_file) \
   @all_gtfiles@
 
 GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
@@ -2223,7 +2227,7 @@ gt-c-pragma.h gt-c-objc-common.h gtype-c
 gt-stringpool.h gt-langhooks.h \
 gt-tree-alias-common.h gt-tree-mudflap.h gt-dependence.h \
 gt-tree-ssa.h gt-tree-dfa.h gt-tree-ssa-ccp.h \
-gt-tree-ssa-pre.h : s-gtype ; @true
+gt-tree-ssa-pre.h gt-tree-iterator.h : s-gtype ; @true
 
 gtyp-gen.h: Makefile
 	echo "/* This file is machine generated.  Do not edit.  */" > tmp-gtyp.h
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.33
diff -u -p -r1.153.2.33 basic-block.h
--- basic-block.h	8 Nov 2003 18:17:28 -0000	1.153.2.33
+++ basic-block.h	9 Nov 2003 09:10:15 -0000
@@ -129,7 +129,10 @@ typedef struct edge_def {
   struct basic_block_def *src, *dest;
 
   /* Instructions queued on the edge.  */
-  rtx insns;
+  union {
+    rtx r;
+    tree t;
+  } insns;
 
   /* Auxiliary info specific to a pass.  */
   void *aux;
@@ -205,8 +208,7 @@ typedef struct basic_block_def {
   rtx head, end;
 
   /* Pointers to the first and last trees of the block.  */
-  tree *head_tree_p;
-  tree *end_tree_p;
+  tree stmt_list;
 
   /* The edges into and out of the block.  */
   edge pred, succ;
@@ -287,6 +289,10 @@ extern varray_type basic_block_info;
 
 #define BASIC_BLOCK(N)  (VARRAY_BB (basic_block_info, (N)))
 
+/* The root of statement_lists of basic blocks for the garbage collector.
+   This is a hack; we really should GC the entire CFG structure.  */
+extern varray_type tree_bb_root;
+
 /* For iterating over basic blocks.  */
 #define FOR_BB_BETWEEN(BB, FROM, TO, DIR) \
   for (BB = FROM; BB != TO; BB = BB->DIR)
@@ -384,7 +390,6 @@ extern void dump_edge_info (FILE *, edge
 extern void clear_edges (void);
 extern void mark_critical_edges (void);
 extern rtx first_insn_after_basic_block_note (basic_block);
-extern basic_block create_bb (basic_block);
 
 /* Dominator information for basic blocks.  */
 
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.344.2.47
diff -u -p -r1.344.2.47 c-common.c
--- c-common.c	31 Oct 2003 07:29:41 -0000	1.344.2.47
+++ c-common.c	9 Nov 2003 09:10:19 -0000
@@ -5969,50 +5969,66 @@ c_decl_uninit (tree t)
 void
 c_warn_unused_result (tree *top_p)
 {
+  tree t = *top_p;
   tree_stmt_iterator i;
   tree fdecl, ftype;
 
-  for (i = tsi_start (top_p); !tsi_end_p (i); tsi_next (&i))
+  switch (TREE_CODE (t))
     {
-      tree t = tsi_stmt (i);
+    case STATEMENT_LIST:
+      for (i = tsi_start (*top_p); !tsi_end_p (i); tsi_next (&i))
+	c_warn_unused_result (tsi_stmt_ptr (i));
+      break;
 
-      switch (TREE_CODE (t))
+    case COND_EXPR:
+      c_warn_unused_result (&COND_EXPR_THEN (t));
+      c_warn_unused_result (&COND_EXPR_ELSE (t));
+      break;
+    case BIND_EXPR:
+      c_warn_unused_result (&BIND_EXPR_BODY (t));
+      break;
+    case TRY_FINALLY_EXPR:
+    case TRY_CATCH_EXPR:
+      c_warn_unused_result (&TREE_OPERAND (t, 0));
+      c_warn_unused_result (&TREE_OPERAND (t, 1));
+      break;
+    case CATCH_EXPR:
+      c_warn_unused_result (&CATCH_BODY (t));
+      break;
+    case EH_FILTER_EXPR:
+      c_warn_unused_result (&EH_FILTER_FAILURE (t));
+      break;
+
+    case CALL_EXPR:
+      /* This is a naked call, as opposed to a CALL_EXPR nested inside
+	 a MODIFY_EXPR.  All calls whose value is ignored should be 
+	 represented like this.  Look for the attribute.  */
+      fdecl = get_callee_fndecl (t);
+      if (fdecl)
+	ftype = TREE_TYPE (fdecl);
+      else
 	{
-	case BIND_EXPR:
-	  c_warn_unused_result (&BIND_EXPR_BODY (t));
-	  break;
+	  ftype = TREE_TYPE (TREE_OPERAND (t, 0));
+	  /* Look past pointer-to-function to the function type itself.  */
+	  ftype = TREE_TYPE (ftype);
+	}
 
-	case CALL_EXPR:
-	  /* This is a naked call, as opposed to a CALL_EXPR nested inside
-	     a MODIFY_EXPR.  All calls whose value is ignored should be 
-	     represented like this.  Look for the attribute.  */
-	  fdecl = get_callee_fndecl (t);
+      if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+	{
 	  if (fdecl)
-	    ftype = TREE_TYPE (fdecl);
+	    warning ("%Hignoring return value of `%D', "
+		     "declared with attribute warn_unused_result",
+		     EXPR_LOCUS (t), fdecl);
 	  else
-	    {
-	      ftype = TREE_TYPE (TREE_OPERAND (t, 0));
-	      /* Look past pointer-to-function to the function type itself.  */
-	      ftype = TREE_TYPE (ftype);
-	    }
-
-	  if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
-	    {
-	      if (fdecl)
-		warning ("%Hignoring return value of `%D', "
-			 "declared with attribute warn_unused_result",
-			 EXPR_LOCUS (t), fdecl);
-	      else
-		warning ("%Hignoring return value of function "
-			 "declared with attribute warn_unused_result",
-			 EXPR_LOCUS (t));
-	    }
-	  break;
-
-	default:
-	  /* Not a container, not a call, or a call whose value is used.  */
-	  break;
+	    warning ("%Hignoring return value of function "
+		     "declared with attribute warn_unused_result",
+		     EXPR_LOCUS (t));
 	}
+      break;
+
+    default:
+      /* Not a container, not a call, or a call whose value is used.  */
+      break;
     }
 }
 
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.43.2.25
diff -u -p -r1.43.2.25 c-semantics.c
--- c-semantics.c	30 Oct 2003 02:49:40 -0000	1.43.2.25
+++ c-semantics.c	9 Nov 2003 09:10:20 -0000
@@ -190,22 +190,42 @@ finish_stmt_tree (tree *t)
 tree
 build_stmt (enum tree_code code, ...)
 {
-  tree t;
-  int length;
-  int i;
+  tree ret;
+  int length, i;
   va_list p;
+  bool side_effects;
 
   va_start (p, code);
 
-  t = make_node (code);
+  ret = make_node (code);
   length = TREE_CODE_LENGTH (code);
-  STMT_LINENO (t) = input_line;
+  STMT_LINENO (ret) = input_line;
+
+  /* Most statements have implicit side effects all on their own, 
+     such as control transfer.  For those that do, we'll compute
+     the real value of TREE_SIDE_EFFECTS from its arguments.  */
+  switch (code)
+    {
+    case EXPR_STMT:
+      side_effects = false;
+      break;
+    default:
+      side_effects = true;
+      break;
+    }
 
   for (i = 0; i < length; i++)
-    TREE_OPERAND (t, i) = va_arg (p, tree);
+    {
+      tree t = va_arg (p, tree);
+      if (t)
+        side_effects |= TREE_SIDE_EFFECTS (t);
+      TREE_OPERAND (ret, i) = t;
+    }
+
+  TREE_SIDE_EFFECTS (ret) = side_effects;
 
   va_end (p);
-  return t;
+  return ret;
 }
 
 /* Some statements, like for-statements or if-statements, require a
Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.78
diff -u -p -r1.1.4.78 c-simplify.c
--- c-simplify.c	31 Oct 2003 07:21:11 -0000	1.1.4.78
+++ c-simplify.c	9 Nov 2003 09:10:21 -0000
@@ -86,7 +86,7 @@ static int is_last_stmt_of_scope (tree);
 #endif
 static void gimplify_block (tree *, tree *);
 static void gimplify_cleanup (tree *, tree *);
-static tree gimplify_c_loop (tree, tree, tree, int);
+static tree gimplify_c_loop (tree, tree, tree, bool);
 static void push_context (void);
 static void pop_context (void);
 static tree c_build_bind_expr (tree, tree);
@@ -204,7 +204,6 @@ c_gimplify_stmt (tree *stmt_p)
       switch (TREE_CODE (stmt))
 	{
 	case COMPOUND_STMT:
-	  c_gimplify_stmt (&COMPOUND_BODY (stmt));
 	  stmt = COMPOUND_BODY (stmt);
 	  break;
 
@@ -291,28 +290,28 @@ c_gimplify_stmt (tree *stmt_p)
 	  if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next))
 	    break;
 
-	  fprintf (stderr, "unhandled statement node in c_gimplify_stmt ():\n");
+	  fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
 	  debug_tree (stmt);
 	  abort ();
 	  break;
 	}
+      gimplify_stmt (&stmt);
 
       /* PRE and POST now contain a list of statements for all the
 	 side-effects in STMT.  */
 
-      add_tree (stmt, &pre);
-      add_tree (post, &pre);
-      pre = rationalize_compound_expr (pre);
+      add_to_statement_list (stmt, &pre);
+      add_to_statement_list (post, &pre);
       annotate_all_with_locus (&pre, stmt_locus);
 
-      add_tree (pre, &outer_pre);
+      add_to_statement_list (pre, &outer_pre);
     cont:
       /* Restore saved state.  */
       current_stmt_tree ()->stmts_are_full_exprs_p
 	= saved_stmts_are_full_exprs_p;
     }
-  add_tree (stmt, &outer_pre);
-  *stmt_p = rationalize_compound_expr (outer_pre);
+  add_to_statement_list (stmt, &outer_pre);
+  *stmt_p = outer_pre;
 }
 
 static void
@@ -363,7 +362,6 @@ c_build_bind_expr (tree block, tree body
 
   bind = build (BIND_EXPR, void_type_node, decls, body, block);
   TREE_SIDE_EFFECTS (bind) = 1;
-  gimplify_stmt (&bind);
 
   return bind;
 }
@@ -543,10 +541,15 @@ finish_bc_block (tree label, tree body)
 
   if (TREE_USED (label))
     {
-      tree expr = build1 (LABEL_EXPR, void_type_node, label);
+      tree t, sl = NULL;
+
       /* Clear the name so flow can delete the label.  */
       DECL_NAME (label) = NULL_TREE;
-      add_tree (expr, &body);
+      t = build1 (LABEL_EXPR, void_type_node, label);
+
+      add_to_statement_list (body, &sl);
+      add_to_statement_list (t, &sl);
+      body = sl;
     }
 
   ctxp->current_bc_label = TREE_CHAIN (label);
@@ -593,7 +596,7 @@ build_bc_goto (enum bc_t bc)
    loop body as in do-while loops.  */
 
 static tree
-gimplify_c_loop (tree cond, tree body, tree incr, int cond_is_first)
+gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
 {
   tree exit, cont_block, break_block, loop;
   location_t stmt_locus;
@@ -601,9 +604,13 @@ gimplify_c_loop (tree cond, tree body, t
 
   stmt_locus = input_location;
 
-  break_block = begin_bc_block (bc_break);
+  /* Detect do { ... } while (0) and don't generate loop construct.  */
+  if (!cond_is_first && cond && integer_zerop (cond))
+    loop = cond = NULL;
+  else
+    loop = build (LOOP_EXPR, void_type_node, NULL_TREE);
 
-  loop = build (LOOP_EXPR, void_type_node, NULL_TREE);
+  break_block = begin_bc_block (bc_break);
 
   if (cond)
     {
@@ -617,7 +624,9 @@ gimplify_c_loop (tree cond, tree body, t
 
   cont_block = begin_bc_block (bc_continue);
 
-  c_gimplify_stmt (&body);
+  gimplify_stmt (&body);
+  if (incr)
+    gimplify_stmt (&incr);
 
   body = finish_bc_block (cont_block, body);
 
@@ -627,52 +636,41 @@ gimplify_c_loop (tree cond, tree body, t
       if (exit)
 	{
 	  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-	  add_tree (body, &stuff);
-	  add_tree (incr, &stuff);
-	  add_tree (entry, &stuff);
-	  add_tree (exit, &stuff);
+	  add_to_statement_list (body, &stuff);
+	  add_to_statement_list (incr, &stuff);
+	  add_to_statement_list (entry, &stuff);
+	  add_to_statement_list (exit, &stuff);
 	}
       else
 	{
-	  add_tree (body, &stuff);
-	  add_tree (incr, &stuff);
+	  add_to_statement_list (body, &stuff);
+	  add_to_statement_list (incr, &stuff);
 	}
     }
   else
     {
-      add_tree (body, &stuff);
-      add_tree (incr, &stuff);
-      add_tree (exit, &stuff);
+      add_to_statement_list (body, &stuff);
+      add_to_statement_list (incr, &stuff);
+      add_to_statement_list (exit, &stuff);
     }
 
   annotate_all_with_locus (&stuff, stmt_locus);
 
-  LOOP_EXPR_BODY (loop) = rationalize_compound_expr (stuff);
+  if (loop)
+    LOOP_EXPR_BODY (loop) = rationalize_compound_expr (stuff);
+  else
+    loop = stuff;
 
   loop = finish_bc_block (break_block, loop);
   if (entry)
     {
-      stuff = build_and_jump (&LABEL_EXPR_LABEL (entry));
-      add_tree (loop, &stuff);
+      tree t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+      stuff = NULL;
+      add_to_statement_list (t, &stuff);
+      add_to_statement_list (loop, &stuff);
       loop = stuff;
     }
 
-  /* This catches do ... while (0) loops and eliminates their looping
-     structure.  Conditions for detecting these loops:
-
-	1. The condition must be last.
-	2. We must have exit code.
-	3. The exit code must be an unconditional jump to the 'break'
-	   label.  The way we construct the exit code above assures that
-	   if the exit code is an unconditional jump, then it will
-	   have the 'break' label as its target.
-	4. The 'continue' label must be unused.  */
-  if (! cond_is_first
-      && exit
-      && TREE_CODE (exit) == GOTO_EXPR
-      && ! TREE_USED (cont_block))
-    TREE_OPERAND (loop, 0) = TREE_OPERAND (TREE_OPERAND (loop, 0), 0);
-
   return loop;
 }
 
@@ -686,7 +684,7 @@ gimplify_for_stmt (tree *stmt_p, tree *p
 
   tree init = FOR_INIT_STMT (stmt);
   c_gimplify_stmt (&init);
-  add_tree (init, pre_p);
+  add_to_statement_list (init, pre_p);
 
   *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
 			     FOR_EXPR (stmt), 1);
@@ -720,56 +718,16 @@ gimplify_if_stmt (tree *stmt_p)
   tree stmt = *stmt_p;
   tree then_ = THEN_CLAUSE (stmt);
   tree else_ = ELSE_CLAUSE (stmt);
-  tree cond = IF_COND (stmt);
-
-  /* Avoid generating silly code.  */
-  if (integer_nonzerop (cond))
-    {
-      /* If there are no reachable statements in the ELSE arm, then
-         we can just emit the THEN arm (skipping the conditional).  */
-      if (! find_reachable_label (else_))
-        {
-	  if (warn_notreached)
-	    {
-	      location_t loc;
-	      loc.file = input_filename;
-	      loc.line = STMT_LINENO (TREE_CODE (else_) == COMPOUND_STMT
-				      ? COMPOUND_BODY (else_)
-				      : else_);
-	      warning ("%Hwill never be executed", &loc);
-	    }
 
-	  c_gimplify_stmt (&then_);
-	  *stmt_p = then_;
-	  return;
-        }
-    }
-  else if (integer_zerop (cond))
-    {
-      /* If there are no reachable statements in the THEN arm, then
-         we can just emit the ELSE arm (skipping the conditional).  */
-      if (! find_reachable_label (then_))
-        {
-	  if (warn_notreached)
-	    {
-	      location_t loc;
-	      loc.file = input_filename;
-	      loc.line = STMT_LINENO (TREE_CODE (then_) == COMPOUND_STMT
-				      ? COMPOUND_BODY (then_)
-				      : then_);
-	      warning ("%Hwill never be executed", &loc);
-	    }
-	  c_gimplify_stmt (&else_);
-	  *stmt_p = else_;
-	  return;
-        }
-    }
+  if (!then_)
+    then_ = build_empty_stmt ();
+  if (!else_)
+    else_ = build_empty_stmt ();
 
-  gimplify_condition (&cond);
-  c_gimplify_stmt (&then_);
-  c_gimplify_stmt (&else_);
+  stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
+  gimplify_condition (& TREE_OPERAND (stmt, 0));
 
-  *stmt_p = build (COND_EXPR, void_type_node, cond, then_, else_);
+  *stmt_p = stmt;
 }
 
 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
@@ -871,7 +829,7 @@ gimplify_decl_stmt (tree *stmt_p)
 	     tree_cons (NULL_TREE,
 			build1 (ADDR_EXPR, pt_type, decl),
 			tree_cons (NULL_TREE, size, NULL_TREE)));
-	  add_tree (alloc, &pre);
+	  add_to_compound_expr (alloc, &pre);
 	}
 
       if (init && init != error_mark_node)
@@ -882,8 +840,7 @@ gimplify_decl_stmt (tree *stmt_p)
 	      init = build (MODIFY_EXPR, void_type_node, decl, init);
 	      if (stmts_are_full_exprs_p ())
 		init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
-	      /* FIXME: Shouldn't we gimplify here?  */
-	      add_tree (init, &pre);
+	      add_to_compound_expr (init, &pre);
 	    }
 	  else
 	    {
@@ -900,7 +857,7 @@ gimplify_decl_stmt (tree *stmt_p)
 	gimple_add_tmp_var (decl);
     }
 
-  add_tree (post, &pre);
+  add_to_compound_expr (post, &pre);
   *stmt_p = pre;
 }
 
@@ -959,13 +916,12 @@ static void
 gimplify_stmt_expr (tree *expr_p)
 {
   tree body = STMT_EXPR_STMT (*expr_p);
+
   if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
-    c_gimplify_stmt (&body);
+      c_gimplify_stmt (&body);
   else
     {
-      tree substmt, last_stmt, last_expr, bind;
-
-      bind = NULL_TREE;	/* [GIMPLE] Avoid uninitialized use warning.  */
+      tree last_stmt, last_expr, substmt;
 
       /* Splice the last expression out of the STMT chain.  */
       last_stmt = NULL_TREE;
@@ -981,7 +937,8 @@ gimplify_stmt_expr (tree *expr_p)
 	  location_t loc;
 	  loc.file = input_filename;
 	  loc.line = STMT_LINENO (last_stmt);
-	  warning ("%Hstatement-expressions should end with a non-void expression", &loc);
+	  warning ("%Hstatement-expressions should end with a "
+		   "non-void expression", &loc);
 	  last_expr = NULL_TREE;
 	}
       else
@@ -1005,27 +962,26 @@ gimplify_stmt_expr (tree *expr_p)
       /* Now retrofit that last expression into the BIND_EXPR.  */
       if (last_expr)
 	{
+	  tree *sub_p;
+
 	  if (!STMT_EXPR_NO_SCOPE (*expr_p))
 	    {
-	      bind = body;
-	      substmt = BIND_EXPR_BODY (bind);
+	      /* Our BIND_EXPR will always be hidden within
+		 a STATEMENT_LIST.  Discard that.  */
+	      body = expr_first (body);
+	      sub_p = &BIND_EXPR_BODY (body);
+
+	      /* Append the last expression to the end of the BIND_EXPR.
+		 We'll now re-process this, and let voidify_wrapper_expr
+		 do its job.  */
+	      add_to_statement_list_force (last_expr, sub_p);
+	      TREE_TYPE (body) = TREE_TYPE (last_expr);
 	    }
 	  else
-	    substmt = body;
-
-	  if (IS_EMPTY_STMT (substmt))
-	    substmt = last_expr;
-	  else
-	    substmt = build (COMPOUND_EXPR, TREE_TYPE (last_expr),
-			    substmt, last_expr);
-
-	  if (!STMT_EXPR_NO_SCOPE (*expr_p))
 	    {
-	      BIND_EXPR_BODY (bind) = substmt;
-	      TREE_TYPE (bind) = TREE_TYPE (body) = TREE_TYPE (last_expr);
+	      /* ??? */
+	      abort ();
 	    }
-	  else
-	    body = substmt;
 	}
     }
 
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.34.2.14
diff -u -p -r1.34.2.14 cfg.c
--- cfg.c	14 Oct 2003 17:31:31 -0000	1.34.2.14
+++ cfg.c	9 Nov 2003 09:10:21 -0000
@@ -97,8 +97,7 @@ varray_type basic_block_info;
 struct basic_block_def entry_exit_blocks[2]
 = {{NULL,			/* head */
     NULL,			/* end */
-    NULL,			/* head_tree */
-    NULL,			/* end_tree */
+    NULL,			/* stmt_list*/
     NULL,			/* pred */
     NULL,			/* succ */
     NULL,			/* local_set */
@@ -120,8 +119,7 @@ struct basic_block_def entry_exit_blocks
   {
     NULL,			/* head */
     NULL,			/* end */
-    NULL,			/* head_tree */
-    NULL,			/* end_tree */
+    NULL,			/* stmt_list */
     NULL,			/* pred */
     NULL,			/* succ */
     NULL,			/* local_set */
@@ -263,12 +261,21 @@ compact_blocks (void)
   FOR_EACH_BB (bb)
     {
       BASIC_BLOCK (i) = bb;
+      if (tree_bb_root)
+	VARRAY_TREE (tree_bb_root, i) = bb->stmt_list;
       bb->index = i;
       i++;
     }
 
   if (i != n_basic_blocks)
     abort ();
+
+  for (; i < last_basic_block; i++)
+    {
+      BASIC_BLOCK (i) = NULL;
+      if (tree_bb_root)
+	VARRAY_TREE (tree_bb_root, i) = NULL_TREE;
+    }
 
   last_basic_block = n_basic_blocks;
 }
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.57.2.16
diff -u -p -r1.57.2.16 cfgrtl.c
--- cfgrtl.c	3 Nov 2003 17:47:35 -0000	1.57.2.16
+++ cfgrtl.c	9 Nov 2003 09:10:23 -0000
@@ -1361,14 +1361,14 @@ insert_insn_on_edge (rtx pattern, edge e
   if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
     abort ();
 
-  if (e->insns == NULL_RTX)
+  if (e->insns.r == NULL_RTX)
     start_sequence ();
   else
-    push_to_sequence (e->insns);
+    push_to_sequence (e->insns.r);
 
   emit_insn (pattern);
 
-  e->insns = get_insns ();
+  e->insns.r = get_insns ();
   end_sequence ();
 }
 
@@ -1476,8 +1476,8 @@ commit_one_edge_insertion (edge e, int w
   basic_block bb = NULL;
 
   /* Pull the insns off the edge now since the edge might go away.  */
-  insns = e->insns;
-  e->insns = NULL_RTX;
+  insns = e->insns.r;
+  e->insns.r = NULL_RTX;
 
   /* Special case -- avoid inserting code between call and storing
      its return value.  */
@@ -1612,10 +1612,10 @@ commit_edge_insertions (void)
       for (e = bb->succ; e; e = next)
 	{
 	  next = e->succ_next;
-	  if (e->insns)
+	  if (e->insns.r)
 	    {
-	       changed = true;
-	       commit_one_edge_insertion (e, false);
+	      changed = true;
+	      commit_one_edge_insertion (e, false);
 	    }
 	}
     }
@@ -1660,7 +1660,7 @@ commit_edge_insertions_watch_calls (void
       for (e = bb->succ; e; e = next)
 	{
 	  next = e->succ_next;
-	  if (e->insns)
+	  if (e->insns.r)
 	    {
 	      changed = true;
 	      commit_one_edge_insertion (e, true);
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.379.2.29
diff -u -p -r1.379.2.29 dwarf2out.c
--- dwarf2out.c	28 Oct 2003 14:56:15 -0000	1.379.2.29
+++ dwarf2out.c	9 Nov 2003 09:10:33 -0000
@@ -10918,14 +10918,15 @@ gen_label_die (tree decl, dw_die_ref con
     equate_decl_number_to_die (decl, lbl_die);
   else
     {
-      insn = DECL_RTL (decl);
+      insn = DECL_RTL_IF_SET (decl);
 
       /* Deleted labels are programmer specified labels which have been
 	 eliminated because of various optimizations.  We still emit them
 	 here so that it is possible to put breakpoints on them.  */
-      if (GET_CODE (insn) == CODE_LABEL
-	  || ((GET_CODE (insn) == NOTE
-	       && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
+      if (insn
+	  && (GET_CODE (insn) == CODE_LABEL
+	      || ((GET_CODE (insn) == NOTE
+	           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))))
 	{
 	  /* When optimization is enabled (via -O) some parts of the compiler
 	     (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.61
diff -u -p -r1.467.2.61 expr.c
--- expr.c	3 Nov 2003 13:12:34 -0000	1.467.2.61
+++ expr.c	9 Nov 2003 09:10:41 -0000
@@ -47,6 +47,8 @@ Software Foundation, 59 Temple Place - S
 #include "langhooks.h"
 #include "intl.h"
 #include "tm_p.h"
+#include "tree-iterator.h"
+
 
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
@@ -8387,6 +8389,18 @@ expand_expr_1 (tree exp, rtx target, enu
 	}
       return expand_expr (exp, (ignore ? const0_rtx : target), VOIDmode,
 	                  modifier);
+
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator iter;
+
+	if (!ignore)
+	  abort ();
+
+	for (iter = tsi_start (exp); !tsi_end_p (iter); tsi_next (&iter))
+	  expand_expr (tsi_stmt (iter), const0_rtx, VOIDmode, modifier);
+      }
+      return const0_rtx;
 
     case COND_EXPR:
       /* If it's void, we don't need to worry about computing a value.  */
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.205.2.25
diff -u -p -r1.205.2.25 gcse.c
--- gcse.c	28 Oct 2003 14:56:17 -0000	1.205.2.25
+++ gcse.c	9 Nov 2003 09:10:46 -0000
@@ -4721,7 +4721,7 @@ reg_killed_on_edge (rtx reg, edge e)
 {
   rtx insn;
 
-  for (insn = e->insns; insn; insn = NEXT_INSN (insn))
+  for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn) && reg_set_p (reg, insn))
       return true;
 
@@ -4798,7 +4798,7 @@ bypass_block (basic_block bb, rtx setcc,
 	    continue;
 
 	  /* Check the data flow is valid after edge insertions.  */
-	  if (e->insns && reg_killed_on_edge (reg_used->reg_rtx, e))
+	  if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e))
 	    continue;
 
 	  src = SET_SRC (pc_set (jump));
@@ -4819,14 +4819,14 @@ bypass_block (basic_block bb, rtx setcc,
 	  if (new == pc_rtx)
 	    {
 	      edest = FALLTHRU_EDGE (bb);
-	      dest = edest->insns ? NULL : edest->dest;
+	      dest = edest->insns.r ? NULL : edest->dest;
 	    }
 	  else if (GET_CODE (new) == LABEL_REF)
 	    {
 	      dest = BLOCK_FOR_INSN (XEXP (new, 0));
 	      /* Don't bypass edges containing instructions.  */
 	      for (edest = bb->succ; edest; edest = edest->succ_next)
-		if (edest->dest == dest && edest->insns)
+		if (edest->dest == dest && edest->insns.r)
 		  {
 		    dest = NULL;
 		    break;
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.4.7
diff -u -p -r1.1.4.7 gimple-low.c
--- gimple-low.c	8 Nov 2003 09:49:19 -0000	1.1.4.7
+++ gimple-low.c	9 Nov 2003 09:10:47 -0000
@@ -51,13 +51,13 @@ static void lower_stmt_body (tree *, str
 static void lower_stmt (tree_stmt_iterator *, struct lower_data *);
 static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
 static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
+static bool find_simple_goto_p (tree *);
 
 /* Lowers the BODY.  */
 void
 lower_function_body (tree *body)
 {
   struct lower_data data;
-  tree root;
 
   if (TREE_CODE (*body) != BIND_EXPR)
     abort ();
@@ -67,15 +67,13 @@ lower_function_body (tree *body)
   BLOCK_CHAIN (data.block) = NULL_TREE;
 
   record_vars (BIND_EXPR_VARS (*body));
-  root = BIND_EXPR_BODY (*body);
-  lower_stmt_body (&root, &data);
+  *body = BIND_EXPR_BODY (*body);
+  lower_stmt_body (body, &data);
 
   if (data.block != DECL_INITIAL (current_function_decl))
     abort ();
-  BLOCK_SUBBLOCKS (data.block) =
-	  blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
-
-  *body = root;
+  BLOCK_SUBBLOCKS (data.block)
+    = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
 }
 
 /* Lowers the EXPR.  Unlike gimplification the statements are not relowered
@@ -87,7 +85,7 @@ lower_stmt_body (tree *expr, struct lowe
 {
   tree_stmt_iterator tsi;
 
-  for (tsi = tsi_start (expr); !tsi_end_p (tsi); )
+  for (tsi = tsi_start (*expr); !tsi_end_p (tsi); )
     lower_stmt (&tsi, data);
 }
 
@@ -104,9 +102,7 @@ lower_stmt (tree_stmt_iterator *tsi, str
     {
     case BIND_EXPR:
       lower_bind_expr (tsi, data);
-      /* Avoid moving the tsi -- it has already been moved by delinking the
-	 statement.  */
-      return;
+      break;
 
     case COMPOUND_EXPR:
       abort ();
@@ -121,18 +117,18 @@ lower_stmt (tree_stmt_iterator *tsi, str
     case VA_ARG_EXPR:
     case RESX_EXPR:
     case SWITCH_EXPR:
+      tsi_next (tsi);
       break;
 
     case COND_EXPR:
       lower_cond_expr (tsi, data);
+      tsi_next (tsi);
       break;
 
     default:
-      print_node_brief (stderr, "", tsi_stmt (*tsi), 0);
+      print_node_brief (stderr, "", stmt, 0);
       abort ();
     }
-
-  tsi_next (tsi);
 }
 
 /* Record the variables in VARS.  */
@@ -190,10 +186,32 @@ lower_bind_expr (tree_stmt_iterator *tsi
 
   /* The BIND_EXPR no longer carries any useful information, so get rid
      of it.  */
-  tsi_link_chain_before (tsi, BIND_EXPR_BODY (stmt), TSI_SAME_STMT);
+  tsi_link_before (tsi, BIND_EXPR_BODY (stmt), TSI_SAME_STMT);
   tsi_delink (tsi);
 }
 
+/* If *EXPR_P is a simple goto, possibly wrapped in a statement list,
+   make sure it's in *EXPR_P and return it.  */
+
+static bool
+find_simple_goto_p (tree *expr_p)
+{
+  tree expr = *expr_p;
+
+  /* If we've a statement_list of a single statement, then we can
+     unwrap the contained statement.  */
+  if (TREE_CODE (expr) == STATEMENT_LIST)
+    {
+      tree f = expr_first (expr);
+      tree l = expr_last (expr);
+      if (!f || f != l)
+	return false;
+      *expr_p = expr = f;
+    }
+
+  return simple_goto_p (*expr_p);
+}
+
 /* Lowers a cond_expr TSI.  DATA is passed through the recursion.  */
 
 static void
@@ -201,43 +219,55 @@ lower_cond_expr (tree_stmt_iterator *tsi
 {
   tree stmt = tsi_stmt (*tsi);
   bool then_is_goto, else_is_goto;
-  tree then_branch, else_branch, then_label, else_label, end_label;
+  tree then_branch, else_branch, then_label, else_label, end_label, t;
   
   lower_stmt_body (&COND_EXPR_THEN (stmt), data);
   lower_stmt_body (&COND_EXPR_ELSE (stmt), data);
 
-  /* Find out whether the branches are ordinary local gotos.  */
-  then_branch = COND_EXPR_THEN (stmt);
-  else_branch = COND_EXPR_ELSE (stmt);
-
-  then_is_goto = simple_goto_p (then_branch);
-  else_is_goto = simple_goto_p (else_branch);
+  then_is_goto = find_simple_goto_p (&COND_EXPR_THEN (stmt));
+  else_is_goto = find_simple_goto_p (&COND_EXPR_ELSE (stmt));
 
   if (then_is_goto && else_is_goto)
     return;
+
+  then_branch = COND_EXPR_THEN (stmt);
+  else_branch = COND_EXPR_ELSE (stmt);
+
+  then_label = NULL_TREE;
+  else_label = NULL_TREE;
+  end_label = NULL_TREE;
  
   /* Replace the cond_expr with explicit gotos.  */
   if (!then_is_goto)
     {
-      then_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-      COND_EXPR_THEN (stmt) = build_and_jump (&LABEL_EXPR_LABEL (then_label));
+      t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+      if (TREE_SIDE_EFFECTS (then_branch))
+	then_label = t;
+      else
+	end_label = t;
+      COND_EXPR_THEN (stmt) = build_and_jump (&LABEL_EXPR_LABEL (t));
     }
-  else
-    then_label = NULL_TREE;
 
   if (!else_is_goto)
     {
-      else_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-      COND_EXPR_ELSE (stmt) = build_and_jump (&LABEL_EXPR_LABEL (else_label));
+      t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+      if (TREE_SIDE_EFFECTS (else_branch))
+	else_label = t;
+      else
+	{
+	  /* Both THEN and ELSE are noops?  If so, remove_useless_stmts
+	     did not do its job.  */
+	  if (end_label)
+	    abort ();
+	  end_label = t;
+	}
+      COND_EXPR_ELSE (stmt) = build_and_jump (&LABEL_EXPR_LABEL (t));
     }
-  else
-    else_label = NULL_TREE;
 
-  end_label = NULL_TREE;
   if (then_label)
     {
       tsi_link_after (tsi, then_label, TSI_CONTINUE_LINKING);
-      tsi_link_chain_after (tsi, then_branch, TSI_CONTINUE_LINKING);
+      tsi_link_after (tsi, then_branch, TSI_CONTINUE_LINKING);
   
       if (else_label)
 	{
@@ -250,7 +280,7 @@ lower_cond_expr (tree_stmt_iterator *tsi
   if (else_label)
     {
       tsi_link_after (tsi, else_label, TSI_CONTINUE_LINKING);
-      tsi_link_chain_after (tsi, else_branch, TSI_CONTINUE_LINKING);
+      tsi_link_after (tsi, else_branch, TSI_CONTINUE_LINKING);
     }
 
   if (end_label)
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.106
diff -u -p -r1.1.2.106 gimplify.c
--- gimplify.c	5 Nov 2003 13:39:23 -0000	1.1.2.106
+++ gimplify.c	9 Nov 2003 09:10:49 -0000
@@ -170,41 +170,61 @@ gimple_pop_condition (tree *pre_p)
   int conds = --(gimplify_ctxp->conditions);
   if (conds == 0)
     {
-      add_tree (gimplify_ctxp->conditional_cleanups, pre_p);
+      add_to_statement_list (gimplify_ctxp->conditional_cleanups, pre_p);
       gimplify_ctxp->conditional_cleanups = NULL_TREE;
     }
   else if (conds < 0)
     abort ();
 }
 
-/* Add STMT to EXISTING if possible, otherwise create a new
-   COMPOUND_EXPR and add STMT to it. */
+/* LIST_P is, or may become, a STATEMENT_LIST.  If T is a single statement
+   or a STATEMENT_LIST itself, it is appended to LIST_P.  T as a variable
+   must be considered dead after this function.  */
 
-static tree
-add_stmt_to_compound (tree existing, tree stmt)
+static void
+add_to_statement_list_1 (tree t, tree *list_p, bool side_effects)
 {
-  /* If we previously had nothing, allow an empty statement.  */
-  if (!existing && stmt && IS_EMPTY_STMT (stmt))
-    return stmt;
-  if (!stmt || !TREE_SIDE_EFFECTS (stmt))
-    return existing;
-  else if (existing && TREE_SIDE_EFFECTS (existing))
-    return build (COMPOUND_EXPR, void_type_node, existing, stmt);
-  else
-    return stmt;
+  tree list = *list_p;
+  tree_stmt_iterator i;
+
+  if (!list)
+    {
+      if (t && TREE_CODE (t) == STATEMENT_LIST)
+	{
+	  *list_p = t;
+	  return;
+	}
+      *list_p = list = alloc_stmt_list ();
+    }
+
+  if (!side_effects)
+    return;
+
+  i = tsi_last (list);
+  tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
 }
 
-/*  Add T to the list container pointed by LIST_P.  If T is a TREE_LIST
-    node, it is linked-in directly.  If T is an expression with no effects,
-    it is ignored.
+void
+add_to_statement_list (tree t, tree *list_p)
+{
+  add_to_statement_list_1 (t, list_p, t && TREE_SIDE_EFFECTS (t));
+}
 
-    Return the newly added list node or NULL_TREE if T was not added to
-    LIST_P.  */
+void
+add_to_statement_list_force (tree t, tree *list_p)
+{
+  add_to_statement_list_1 (t, list_p, t != NULL);
+}
 
 void
-add_tree (tree t, tree *list_p)
+add_to_compound_expr (tree t, tree *list_p)
 {
-  *list_p = add_stmt_to_compound (*list_p, t);
+  if (!t)
+    return;
+  if (!*list_p)
+    *list_p = t;
+  else
+    *list_p = build (COMPOUND_EXPR, TREE_TYPE (t), *list_p, t);
 }
 
 /* Strip off a legitimate source ending from the input string NAME of
@@ -433,7 +453,7 @@ internal_get_tmp_var (tree val, tree *pr
     annotate_with_locus (mod, input_location);
   /* gimplify_modify_expr might want to reduce this further.  */
   gimplify_stmt (&mod);
-  add_tree (mod, pre_p);
+  add_to_statement_list (mod, pre_p);
 
   return t;
 }
@@ -511,29 +531,6 @@ gimple_add_tmp_var (tree tmp)
     declare_tmp_vars (tmp, DECL_SAVED_TREE (current_function_decl));
 }
 
-/* Apply FN to each statement under *STMT_P, which may be a COMPOUND_EXPR
-   or a single statement expr.  */
-
-void
-foreach_stmt (tree *stmt_p, foreach_stmt_fn *fn)
-{
-  if (*stmt_p == NULL_TREE)
-    return;
-
-  for (; TREE_CODE (*stmt_p) == COMPOUND_EXPR;
-       stmt_p = &TREE_OPERAND (*stmt_p, 1))
-    {
-      tree *sub_p = &TREE_OPERAND (*stmt_p, 0);
-      if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
-	foreach_stmt (sub_p, fn);
-      else
-	fn (sub_p);
-    }
-  fn (stmt_p);
-}
-
-static location_t wfl_locus;
-
 /* Determines whether to assign a locus to the statement STMT.  */
 
 static bool
@@ -552,20 +549,31 @@ should_carry_locus_p (tree stmt)
   return true;
 }
 
-static void
-annotate_all_with_locus_1 (tree *stmt_p)
-{
-  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (*stmt_p)))
-      && ! EXPR_LOCUS (*stmt_p)
-      && should_carry_locus_p (*stmt_p))
-    annotate_with_locus (*stmt_p, wfl_locus);
-}
-
 void
 annotate_all_with_locus (tree *stmt_p, location_t locus)
 {
-  wfl_locus = locus;
-  foreach_stmt (stmt_p, annotate_all_with_locus_1);
+  tree_stmt_iterator i;
+
+  if (!*stmt_p)
+    return;
+
+  for (i = tsi_start (*stmt_p); !tsi_end_p (i); tsi_next (&i))
+    {
+      tree t = tsi_stmt (i);
+
+#ifdef ENABLE_CHECKING
+	  /* Assuming we've already been gimplified, we shouldn't
+	     see nested chaining constructs anymore.  */
+	  if (TREE_CODE (t) == STATEMENT_LIST
+	      || TREE_CODE (t) == COMPOUND_EXPR)
+	    abort ();
+#endif
+
+      if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t)))
+	  && ! EXPR_LOCUS (t)
+	  && should_carry_locus_p (t))
+	annotate_with_locus (t, locus);
+    }
 }
 
 /* Similar to copy_tree_r() but do not copy SAVE_EXPR nodes.  These nodes
@@ -661,9 +669,16 @@ mark_not_gimple (tree *expr_p)
 tree
 gimple_build_eh_filter (tree body, tree allowed, tree failure)
 {
+  tree t;
+
   /* FIXME should the allowed types go in TREE_TYPE?  */
-  tree filter = build (EH_FILTER_EXPR, void_type_node, allowed, failure);
-  return build (TRY_CATCH_EXPR, void_type_node, body, filter);
+  t = build (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
+  add_to_statement_list (failure, &EH_FILTER_FAILURE (t));
+
+  t = build (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
+  add_to_statement_list (body, &TREE_OPERAND (t, 0));
+
+  return t;
 }
 
 
@@ -693,13 +708,26 @@ voidify_wrapper_expr (tree wrapper)
 	  break;
 	}
 
-      for (; TREE_CODE (*p) == COMPOUND_EXPR;
-	   p = &TREE_OPERAND (*p, 1))
+      /* Advance.  Set up the substatements appropriately for what we
+	 will have when we're done.  */
+      if (TREE_CODE (*p) == STATEMENT_LIST)
 	{
-	  /* Advance.  Set up the COMPOUND_EXPRs appropriately for what we
-	     will have when we're done.  */
-	  TREE_SIDE_EFFECTS (*p) = 1;
-	  TREE_TYPE (*p) = void_type_node;
+	  tree_stmt_iterator i;
+	  for (i = tsi_start (*p); !tsi_one_before_end_p (i); tsi_next (&i))
+	    {
+	      tree t = tsi_stmt (i);
+	      TREE_SIDE_EFFECTS (t) = 1;
+	      TREE_TYPE (t) = void_type_node;
+	    }
+	  p = tsi_stmt_ptr (i);
+	}
+      else
+	{ 
+	  for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
+	    {
+	      TREE_SIDE_EFFECTS (*p) = 1;
+	      TREE_TYPE (*p) = void_type_node;
+	    }
 	}
 
       if (TREE_CODE (*p) == INIT_EXPR)
@@ -772,7 +800,8 @@ gimplify_bind_expr (tree *expr_p, tree *
   gimple_push_bind_expr (bind_expr);
   gimplify_ctxp->save_stack = false;
 
-  gimplify_stmt (&BIND_EXPR_BODY (bind_expr));
+  gimplify_to_stmt_list (&BIND_EXPR_BODY (bind_expr));
+
   if (gimplify_ctxp->save_stack)
     {
       tree stack_save, stack_restore;
@@ -780,12 +809,14 @@ gimplify_bind_expr (tree *expr_p, tree *
       /* Save stack on entry and restore it on exit.  Add a try_finally
 	 block to achieve this.  */
       build_stack_save_restore (&stack_save, &stack_restore);
-      BIND_EXPR_BODY (bind_expr) =
-	  build (COMPOUND_EXPR, void_type_node,
-		 stack_save,
-		 build (TRY_FINALLY_EXPR, void_type_node,
-			BIND_EXPR_BODY (bind_expr),
-			stack_restore));
+
+      t = build (TRY_FINALLY_EXPR, void_type_node,
+		 BIND_EXPR_BODY (bind_expr), NULL_TREE);
+      add_to_statement_list (stack_restore, &TREE_OPERAND (t, 1));
+
+      BIND_EXPR_BODY (bind_expr) = NULL_TREE;
+      add_to_statement_list (stack_save, &BIND_EXPR_BODY (bind_expr));
+      add_to_statement_list (t, &BIND_EXPR_BODY (bind_expr));
     }
 
   gimplify_ctxp->save_stack = old_save_stack;
@@ -794,7 +825,7 @@ gimplify_bind_expr (tree *expr_p, tree *
   if (temp)
     {
       *expr_p = temp;
-      add_tree (bind_expr, pre_p);
+      add_to_statement_list (bind_expr, pre_p);
       return GS_OK;
     }
   else
@@ -812,7 +843,6 @@ static enum gimplify_status
 gimplify_return_expr (tree stmt, tree *pre_p)
 {
   tree ret_expr = TREE_OPERAND (stmt, 0);
-  tree_stmt_iterator si;
   tree result;
 
   if (!ret_expr || TREE_CODE (ret_expr) == RESULT_DECL)
@@ -849,30 +879,29 @@ gimplify_return_expr (tree stmt, tree *p
 	 gimplification, find it so we can put it in the RETURN_EXPR.  */
       tree ret = NULL_TREE;
 
-      for (si = tsi_start (&ret_expr); !tsi_end_p (si); tsi_next (&si))
-	{
-	  tree sub = tsi_stmt (si);
-	  if (TREE_CODE (sub) == MODIFY_EXPR
-	      && TREE_OPERAND (sub, 0) == result)
-	    {
-	      ret = sub;
-	      break;
-	    }
-	}
-
-      if (ret)
+      if (TREE_CODE (ret_expr) == STATEMENT_LIST)
 	{
-	  if (tsi_one_before_end_p (si))
-	    /* If the MODIFY_EXPR was the last thing in the GIMPLE
-	       form, pull it out.  */
-	    tsi_delink (&si);
-	  else
+	  tree_stmt_iterator si;
+	  for (si = tsi_start (ret_expr); !tsi_end_p (si); tsi_next (&si))
 	    {
-	      /* If there were posteffects after the MODIFY_EXPR, we
-		 need a temporary.  */
-	      tree tmp = create_tmp_var (TREE_TYPE (result), "retval");
-	      TREE_OPERAND (ret, 0) = tmp;
-	      ret = build (MODIFY_EXPR, TREE_TYPE (result), result, tmp);
+	      tree sub = tsi_stmt (si);
+	      if (TREE_CODE (sub) == MODIFY_EXPR
+		  && TREE_OPERAND (sub, 0) == result)
+		{
+		  ret = sub;
+		  if (tsi_one_before_end_p (si))
+		    tsi_delink (&si);
+		  else
+		    {
+		      /* If there were posteffects after the MODIFY_EXPR,
+			 we need a temporary.  */
+		      tree tmp = create_tmp_var (TREE_TYPE (result), "retval");
+		      TREE_OPERAND (ret, 0) = tmp;
+		      ret = build (MODIFY_EXPR, TREE_TYPE (result),
+				   result, tmp);
+		    }
+		  break;
+		}
 	    }
 	}
 
@@ -884,7 +913,7 @@ gimplify_return_expr (tree stmt, tree *p
 	TREE_OPERAND (stmt, 0) = result;
     }
 
-  add_tree (ret_expr, pre_p);
+  add_to_statement_list (ret_expr, pre_p);
   return GS_ALL_DONE;
 }
 
@@ -893,24 +922,26 @@ gimplify_return_expr (tree stmt, tree *p
    EXIT_EXPR, we need to append a label for it to jump to.  */
 
 static enum gimplify_status
-gimplify_loop_expr (tree *expr_p)
+gimplify_loop_expr (tree *expr_p, tree *pre_p)
 {
   tree saved_label = gimplify_ctxp->exit_label;
   tree start_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+  tree jump_stmt = build_and_jump (&LABEL_EXPR_LABEL (start_label));
+
+  add_to_statement_list (start_label, pre_p);
 
   gimplify_ctxp->exit_label = NULL_TREE;
 
   gimplify_stmt (&LOOP_EXPR_BODY (*expr_p));
-  *expr_p = LOOP_EXPR_BODY (*expr_p);
+  add_to_statement_list (LOOP_EXPR_BODY (*expr_p), pre_p);
 
-  add_tree (build_and_jump (&LABEL_EXPR_LABEL (start_label)), expr_p);
-  *expr_p = add_stmt_to_compound (start_label, *expr_p);
   if (gimplify_ctxp->exit_label)
     {
-      tree expr = build1 (LABEL_EXPR, void_type_node,
-			  gimplify_ctxp->exit_label);
-      add_tree (expr, expr_p);
+      add_to_statement_list (jump_stmt, pre_p);
+      *expr_p = build1 (LABEL_EXPR, void_type_node, gimplify_ctxp->exit_label);
     }
+  else
+    *expr_p = jump_stmt;
 
   gimplify_ctxp->exit_label = saved_label;
 
@@ -950,7 +981,7 @@ gimplify_switch_expr (tree *expr_p, tree
       saved_labels = gimplify_ctxp->case_labels;
       VARRAY_TREE_INIT (gimplify_ctxp->case_labels, 8, "case_labels");
 
-      gimplify_stmt (&SWITCH_BODY (switch_expr));
+      gimplify_to_stmt_list (&SWITCH_BODY (switch_expr));
 
       labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = saved_labels;
@@ -974,7 +1005,7 @@ gimplify_switch_expr (tree *expr_p, tree
       for (i = 0; i < len; ++i)
 	TREE_VEC_ELT (label_vec, i) = VARRAY_TREE (labels, i);
 
-      add_tree (switch_expr, pre_p);
+      add_to_statement_list (switch_expr, pre_p);
 
       /* If the switch has no default label, add one, so that we jump
 	 around the switch body.  */
@@ -983,7 +1014,7 @@ gimplify_switch_expr (tree *expr_p, tree
 	  t = build (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
 		     NULL_TREE, create_artificial_label ());
 	  TREE_VEC_ELT (label_vec, len) = t;
-	  add_tree (SWITCH_BODY (switch_expr), pre_p);
+	  add_to_statement_list (SWITCH_BODY (switch_expr), pre_p);
 	  *expr_p = build (LABEL_EXPR, void_type_node, CASE_LABEL (t));
 	}
       else
@@ -1157,7 +1188,7 @@ gimplify_init_constructor (tree *expr_p,
 	  if (cleared)
 	    {
 	      CONSTRUCTOR_ELTS (ctor) = NULL_TREE;
-	      add_tree (*expr_p, pre_p);
+	      add_to_statement_list (*expr_p, pre_p);
 	    }
 
 	  for (i = 0; elt_list; i++, elt_list = TREE_CHAIN (elt_list))
@@ -1184,7 +1215,7 @@ gimplify_init_constructor (tree *expr_p,
 	      init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
 	      /* Each member initialization is a full-expression.  */
 	      gimplify_stmt (&init);
-	      add_tree (init, pre_p);
+	      add_to_statement_list (init, pre_p);
 	    }
 
 	  if (want_value)
@@ -1580,7 +1611,7 @@ gimplify_self_mod_expr (tree *expr_p, tr
   if (postfix)
     {
       gimplify_stmt (&t1);
-      add_tree (t1, post_p);
+      add_to_statement_list (t1, post_p);
       *expr_p = lhs;
       return GS_ALL_DONE;
     }
@@ -1734,7 +1765,7 @@ static tree
 shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p)
 {
   tree local_label = NULL_TREE;
-  tree one, two, expr;
+  tree t, expr = NULL;
 
   /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
      retain the shortcut semantics.  Just insert the gotos here;
@@ -1750,10 +1781,12 @@ shortcut_cond_r (tree pred, tree *true_l
       if (false_label_p == NULL)
 	false_label_p = &local_label;
 
-      one = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p);
-      two = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-			     false_label_p);
-      expr = add_stmt_to_compound (one, two);
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p);
+      add_to_statement_list (t, &expr);
+
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
+			   false_label_p);
+      add_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
     {
@@ -1766,10 +1799,12 @@ shortcut_cond_r (tree pred, tree *true_l
       if (true_label_p == NULL)
 	true_label_p = &local_label;
 
-      one = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL);
-      two = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-			     false_label_p);
-      expr = add_stmt_to_compound (one, two);
+      t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL);
+      add_to_statement_list (t, &expr);
+
+      t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
+			   false_label_p);
+      add_to_statement_list (t, &expr);
     }
   else if (TREE_CODE (pred) == COND_EXPR)
     {
@@ -1778,12 +1813,11 @@ shortcut_cond_r (tree pred, tree *true_l
 	   if (b) goto yes; else goto no;
 	 else
 	   if (c) goto yes; else goto no;  */
-      one = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
-			     false_label_p);
-      two = shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
-			     false_label_p);
       expr = build (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
-		    one, two);
+		    shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
+				     false_label_p),
+		    shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
+				     false_label_p));
     }
   else
     {
@@ -1793,7 +1827,10 @@ shortcut_cond_r (tree pred, tree *true_l
     }
 
   if (local_label)
-    add_tree (build1 (LABEL_EXPR, void_type_node, local_label), &expr);
+    {
+      t = build1 (LABEL_EXPR, void_type_node, local_label);
+      add_to_statement_list (t, &expr);
+    }
 
   return expr;
 }
@@ -1804,11 +1841,10 @@ shortcut_cond_expr (tree expr)
   tree pred = TREE_OPERAND (expr, 0);
   tree then_ = TREE_OPERAND (expr, 1);
   tree else_ = TREE_OPERAND (expr, 2);
-  tree true_label, false_label, end_label;
+  tree true_label, false_label, end_label, t;
   tree *true_label_p;
   tree *false_label_p;
   bool emit_end, emit_false;
-  tree_stmt_iterator si;
 
   /* First do simple transformations.  */
   if (!TREE_SIDE_EFFECTS (else_))
@@ -1856,21 +1892,19 @@ shortcut_cond_expr (tree expr)
 
   /* If our arms just jump somewhere, hijack those labels so we don't
      generate jumps to jumps.  */
-  si = tsi_start (&then_);
-  expr = tsi_stmt (si);
-  if (TREE_CODE (expr) == GOTO_EXPR
-      && TREE_CODE (GOTO_DESTINATION (expr)) == LABEL_DECL)
-    {
-      true_label = GOTO_DESTINATION (expr);
-      tsi_delink (&si);
-    }
-  si = tsi_start (&else_);
-  expr = tsi_stmt (si);
-  if (TREE_CODE (expr) == GOTO_EXPR
-      && TREE_CODE (GOTO_DESTINATION (expr)) == LABEL_DECL)
+
+  if (TREE_CODE (then_) == GOTO_EXPR
+      && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
     {
-      false_label = GOTO_DESTINATION (expr);
-      tsi_delink (&si);
+      true_label = GOTO_DESTINATION (then_);
+      then_ = build_empty_stmt ();
+    }
+
+  if (TREE_CODE (else_) == GOTO_EXPR
+      && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
+    {
+      false_label = GOTO_DESTINATION (else_);
+      else_ = build_empty_stmt ();
     }
 
   /* If we aren't hijacking a label for the 'then' branch, it falls through. */
@@ -1906,18 +1940,28 @@ shortcut_cond_expr (tree expr)
   emit_end = (end_label == NULL_TREE);
   emit_false = (false_label == NULL_TREE);
 
-  expr = shortcut_cond_r (pred, true_label_p, false_label_p);
+  pred = shortcut_cond_r (pred, true_label_p, false_label_p);
 
-  add_tree (then_, &expr);
+  expr = NULL;
+  add_to_statement_list (pred, &expr);
+
+  add_to_statement_list (then_, &expr);
   if (TREE_SIDE_EFFECTS (else_))
     {
-      add_tree (build_and_jump (&end_label), &expr);
+      t = build_and_jump (&end_label);
+      add_to_statement_list (t, &expr);
       if (emit_false)
-	add_tree (build1 (LABEL_EXPR, void_type_node, false_label), &expr);
-      add_tree (else_, &expr);
+	{
+	  t = build1 (LABEL_EXPR, void_type_node, false_label);
+	  add_to_statement_list (t, &expr);
+	}
+      add_to_statement_list (else_, &expr);
     }
   if (emit_end && end_label)
-    add_tree (build1 (LABEL_EXPR, void_type_node, end_label), &expr);
+    {
+      t = build1 (LABEL_EXPR, void_type_node, end_label);
+      add_to_statement_list (t, &expr);
+    }
 
   return expr;
 }
@@ -2016,7 +2060,7 @@ gimplify_cond_expr (tree *expr_p, tree *
 
       /* Move the COND_EXPR to the prequeue and use the temp in its place.  */
       gimplify_stmt (&expr);
-      add_tree (expr, pre_p);
+      add_to_statement_list (expr, pre_p);
       *expr_p = tmp;
 
       return ret;
@@ -2053,8 +2097,9 @@ gimplify_cond_expr (tree *expr_p, tree *
 
   gimple_push_condition ();
 
-  gimplify_stmt (&TREE_OPERAND (expr, 1));
-  gimplify_stmt (&TREE_OPERAND (expr, 2));
+  gimplify_to_stmt_list (&TREE_OPERAND (expr, 1));
+  gimplify_to_stmt_list (&TREE_OPERAND (expr, 2));
+  recalculate_side_effects (expr);
 
   gimple_pop_condition (pre_p);
 
@@ -2171,7 +2216,7 @@ gimplify_modify_expr (tree *expr_p, tree
 
   if (want_value)
     {
-      add_tree (*expr_p, pre_p);
+      add_to_statement_list (*expr_p, pre_p);
       *expr_p = *to_p;
     }
 
@@ -2203,29 +2248,72 @@ gimplify_boolean_expr (tree *expr_p)
   return GS_OK;
 }
 
-/*  Gimplifies an expression sequence.  This function gimplifies each
-    expression and re-writes the original expression with the last
-    expression of the sequence in GIMPLE form.
+/* Gimplifies an expression sequence.  This function gimplifies each
+   expression and re-writes the original expression with the last
+   expression of the sequence in GIMPLE form.
+
+   PRE_P points to the list where the side effects for all the
+       expressions in the sequence will be emitted.
+    
+   WANT_VALUE is true when the result of the last COMPOUND_EXPR is used.  */
+/* ??? Should rearrange to share the pre-queue with all the indirect
+   invocations of gimplify_expr.  Would probably save on creations 
+   of statement_list nodes.  */
+
+static enum gimplify_status
+gimplify_compound_expr (tree *expr_p, tree *pre_p, bool want_value)
+{
+  tree t = *expr_p;
+
+  do
+    {
+      tree *sub_p = &TREE_OPERAND (t, 0);
 
-    PRE_P points to the list where the side effects for all the expressions
-	in the sequence will be emitted.
+      if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
+	gimplify_compound_expr (sub_p, pre_p, false);
+      else
+        gimplify_stmt (sub_p);
+      add_to_statement_list (*sub_p, pre_p);
+
+      t = TREE_OPERAND (t, 1);
+    }
+  while (TREE_CODE (t) == COMPOUND_EXPR);
 
-    POST_P points to the list where the post side effects for the last
-        expression in the sequence are emitted.  */
+  *expr_p = t;
+  if (want_value)
+    return GS_OK;
+  else
+    {
+      gimplify_stmt (expr_p);
+      return GS_ALL_DONE;
+    }
+}
+
+/* Gimplifies a statement list.  These may be created either by an
+   enlightend front-end, or by shortcut_cond_expr.  */
 
 static enum gimplify_status
-gimplify_compound_expr (tree *expr_p, tree *pre_p)
+gimplify_statement_list (tree *expr_p)
 {
-  tree t;
-  for (t = *expr_p; TREE_CODE (t) == COMPOUND_EXPR; t = TREE_OPERAND (t, 1))
+  tree_stmt_iterator i = tsi_start (*expr_p);
+
+  while (!tsi_end_p (i))
     {
-      tree sub = TREE_OPERAND (t, 0);
-      gimplify_stmt (&sub);
-      add_tree (sub, pre_p);
+      tree t;
+
+      gimplify_stmt (tsi_stmt_ptr (i));
+
+      t = tsi_stmt (i);
+      if (TREE_CODE (t) == STATEMENT_LIST)
+	{
+	  tsi_link_before (&i, t, TSI_SAME_STMT);
+	  tsi_delink (&i);
+	}
+      else
+	tsi_next (&i);
     }
 
-  *expr_p = t;
-  return GS_OK;
+  return GS_ALL_DONE;
 }
 
 /*  Gimplify a SAVE_EXPR node.  EXPR_P points to the expression to
@@ -2259,7 +2347,7 @@ gimplify_save_expr (tree *expr_p, tree *
     {
       tree body = TREE_OPERAND (*expr_p, 0);
       ret = gimplify_expr (& body, pre_p, post_p, is_gimple_stmt, fb_none);
-      add_tree (body, pre_p);
+      add_to_statement_list (body, pre_p);
       *expr_p = build_empty_stmt ();
     }
   else
@@ -2332,8 +2420,6 @@ gimplify_addr_expr (tree *expr_p, tree *
 			   is_gimple_addr_expr_arg, fb_either);
       if (ret != GS_ERROR)
 	{
-	  TREE_SIDE_EFFECTS (expr)
-	    = TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0));
 	  /* Mark the RHS addressable.  */
 	  (*lang_hooks.mark_addressable) (TREE_OPERAND (expr, 0));
 	}
@@ -2464,27 +2550,33 @@ gimplify_cleanup_point_expr (tree *expr_
   gimplify_ctxp->conditions = 0;
 
   body = TREE_OPERAND (*expr_p, 0);
-  gimplify_stmt (&body);
+  gimplify_to_stmt_list (&body);
 
   gimplify_ctxp->conditions = old_conds;
 
-  for (iter = tsi_start (&body); !tsi_end_p (iter); )
+  for (iter = tsi_start (body); !tsi_end_p (iter); )
     {
-      tree wce = tsi_stmt (iter);
-      if (wce && TREE_CODE (wce) == WITH_CLEANUP_EXPR)
-	{
-	  tree *container = tsi_container (iter);
-	  tree next, tfe;
+      tree *wce_p = tsi_stmt_ptr (iter);
+      tree wce = *wce_p;
 
-	  if (TREE_CODE (*container) == COMPOUND_EXPR)
-	    next = TREE_OPERAND (*container, 1);
+      if (TREE_CODE (wce) == WITH_CLEANUP_EXPR)
+	{
+	  if (tsi_one_before_end_p (iter))
+	    {
+	      *wce_p = TREE_OPERAND (wce, 1);
+	      tsi_next (&iter);
+	    }
 	  else
-	    next = build_empty_stmt ();
+	    {
+	      tree sl, tfe;
 
-	  tfe = build (TRY_FINALLY_EXPR, void_type_node,
-		       next, TREE_OPERAND (wce, 1));
-	  *container = tfe;
-	  iter = tsi_start (&TREE_OPERAND (tfe, 0));
+	      sl = tsi_split_statement_list_after (&iter);
+	      tfe = build (TRY_FINALLY_EXPR, void_type_node, sl, NULL_TREE);
+	      add_to_statement_list (TREE_OPERAND (wce, 1),
+				     &TREE_OPERAND (tfe, 1));
+	      *wce_p = tfe;
+	      iter = tsi_start (sl);
+	    }
 	}
       else
 	tsi_next (&iter);
@@ -2493,7 +2585,7 @@ gimplify_cleanup_point_expr (tree *expr_
   if (temp)
     {
       *expr_p = temp;
-      add_tree (body, pre_p);
+      add_to_statement_list (body, pre_p);
       return GS_OK;
     }
   else
@@ -2548,15 +2640,15 @@ gimple_push_cleanup (tree cleanup, tree 
 		       build_empty_stmt ());
       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
 		   cleanup, NULL_TREE);
-      add_tree (ffalse, &gimplify_ctxp->conditional_cleanups);
-      add_tree (wce, &gimplify_ctxp->conditional_cleanups);
-      add_tree (ftrue, pre_p);
+      add_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups);
+      add_to_statement_list (wce, &gimplify_ctxp->conditional_cleanups);
+      add_to_statement_list (ftrue, pre_p);
     }
   else
     {
       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
 		   cleanup, NULL_TREE);
-      add_tree (wce, pre_p);
+      add_to_statement_list (wce, pre_p);
     }
 }
 
@@ -2580,7 +2672,7 @@ gimplify_target_expr (tree *expr_p, tree
   if (ret == GS_ERROR)
     return GS_ERROR;
 
-  add_tree (init, pre_p);
+  add_to_statement_list (init, pre_p);
 
   /* If needed, push the cleanup for the temp.  */
   if (TARGET_EXPR_CLEANUP (targ))
@@ -2602,6 +2694,22 @@ void
 gimplify_stmt (tree *stmt_p)
 {
   gimplify_expr (stmt_p, NULL, NULL, is_gimple_stmt, fb_none);
+  if (!*stmt_p)
+    *stmt_p = alloc_stmt_list ();
+}
+
+/* Similarly, but force the result to be a STATEMENT_LIST.  */
+
+void
+gimplify_to_stmt_list (tree *stmt_p)
+{
+  gimplify_stmt (stmt_p);
+  if (TREE_CODE (*stmt_p) != STATEMENT_LIST)
+    {
+      tree t = *stmt_p;
+      *stmt_p = NULL;
+      add_to_statement_list (t, stmt_p);
+    }
 }
 
 /*  Gimplifies the expression tree pointed by EXPR_P.  Return 0 if
@@ -2726,13 +2834,7 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  abort ();
 
 	case COMPOUND_EXPR:
-	  if (is_statement)
-	    {
-	      foreach_stmt (expr_p, (foreach_stmt_fn *)gimplify_stmt);
-	      ret = GS_ALL_DONE;
-	    }
-	  else
-	    ret = gimplify_compound_expr (expr_p, pre_p);
+	  ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
 	  break;
 
 	case REALPART_EXPR:
@@ -2832,7 +2934,7 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  break;
 
 	case LOOP_EXPR:
-	  ret = gimplify_loop_expr (expr_p);
+	  ret = gimplify_loop_expr (expr_p, pre_p);
 	  break;
 
 	case SWITCH_EXPR:
@@ -2929,8 +3031,8 @@ gimplify_expr (tree *expr_p, tree *pre_p
 
 	case TRY_FINALLY_EXPR:
 	case TRY_CATCH_EXPR:
-	  gimplify_stmt (&TREE_OPERAND (*expr_p, 0));
-	  gimplify_stmt (&TREE_OPERAND (*expr_p, 1));
+	  gimplify_to_stmt_list (&TREE_OPERAND (*expr_p, 0));
+	  gimplify_to_stmt_list (&TREE_OPERAND (*expr_p, 1));
 	  ret = GS_ALL_DONE;
 	  break;
 
@@ -2943,12 +3045,12 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  break;
 
 	case CATCH_EXPR:
-	  gimplify_stmt (&CATCH_BODY (*expr_p));
+	  gimplify_to_stmt_list (&CATCH_BODY (*expr_p));
 	  ret = GS_ALL_DONE;
 	  break;
 
 	case EH_FILTER_EXPR:
-	  gimplify_stmt (&EH_FILTER_FAILURE (*expr_p));
+	  gimplify_to_stmt_list (&EH_FILTER_FAILURE (*expr_p));
 	  ret = GS_ALL_DONE;
 	  break;
 
@@ -2973,6 +3075,10 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  ret = GS_ALL_DONE;
 	  break;
 
+	case STATEMENT_LIST:
+	  ret = gimplify_statement_list (expr_p);
+	  break;
+
         case VAR_DECL:
 	  /* ??? If this is a local variable, and it has not been seen in any
 	     outer BIND_EXPR, then it's probably the result of a duplicate
@@ -3052,6 +3158,8 @@ gimplify_expr (tree *expr_p, tree *pre_p
     abort ();
 #endif
 
+  if (!*expr_p)
+    *expr_p = build_empty_stmt ();
   if (fallback == fb_none && !is_gimple_stmt (*expr_p))
     {
       /* We aren't looking for a value, and we don't have a valid
@@ -3080,13 +3188,10 @@ gimplify_expr (tree *expr_p, tree *pre_p
      gimplified form.  */
   if (is_statement)
     {
-      add_tree (*expr_p, pre_p);
-      annotate_all_with_locus (&internal_post, input_location);
-      add_tree (internal_post, pre_p);
-      tmp = rationalize_compound_expr (internal_pre);
-      annotate_all_with_locus (&tmp, input_location);
-      *expr_p = tmp;
-
+      add_to_statement_list (*expr_p, &internal_pre);
+      add_to_statement_list (internal_post, &internal_pre);
+      annotate_all_with_locus (&internal_pre, input_location);
+      *expr_p = internal_pre;
       goto out;
     }
 
@@ -3158,7 +3263,7 @@ gimplify_expr (tree *expr_p, tree *pre_p
   if (internal_post)
     {
       annotate_all_with_locus (&internal_post, input_location);
-      add_tree (internal_post, pre_p);
+      add_to_statement_list (internal_post, pre_p);
     }
 
  out:
@@ -3192,9 +3297,12 @@ gimplify_body (tree *body_p, tree fndecl
   /* If there isn't an outer BIND_EXPR, add one.  */
   if (TREE_CODE (*body_p) != BIND_EXPR)
     {
-      *body_p = build (BIND_EXPR, void_type_node, NULL_TREE,
-		       *body_p, NULL_TREE);
-      TREE_SIDE_EFFECTS (*body_p) = 1;
+      tree t = *body_p;
+      tree b = build (BIND_EXPR, void_type_node, NULL_TREE,
+		      NULL_TREE, NULL_TREE);
+      TREE_SIDE_EFFECTS (b) = 1;
+      add_to_statement_list (t, &BIND_EXPR_BODY (b));
+      *body_p = b;
     }
 
   /* Declare the new temporary variables.  */
Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.93.2.22
diff -u -p -r1.93.2.22 profile.c
--- profile.c	28 Oct 2003 14:56:20 -0000	1.93.2.22
+++ profile.c	9 Nov 2003 09:10:50 -0000
@@ -157,7 +157,7 @@ instrument_edges (struct edge_list *el)
 			 EDGE_CRITICAL_P (e) ? " (and split)" : "");
 	      edge_profile = gen_edge_profiler (num_instr_edges++);
 	      insert_insn_on_edge (edge_profile, e);
-	      rebuild_jump_labels (e->insns);
+	      rebuild_jump_labels (e->insns.r);
 	    }
 	}
     }
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.135.2.16
diff -u -p -r1.135.2.16 rtlanal.c
--- rtlanal.c	28 Oct 2003 14:56:21 -0000	1.135.2.16
+++ rtlanal.c	9 Nov 2003 09:10:53 -0000
@@ -3695,17 +3695,17 @@ hoist_insn_to_edge (rtx insn, edge e, rt
 
   /* Do not use emit_insn_on_edge as we want to preserve notes and similar
      stuff.  We also emit CALL_INSNS and firends.  */
-  if (e->insns == NULL_RTX)
+  if (e->insns.r == NULL_RTX)
     {
       start_sequence ();
       emit_note (NOTE_INSN_DELETED);
     }
   else
-    push_to_sequence (e->insns);
+    push_to_sequence (e->insns.r);
 
   new_insn = hoist_insn_after (insn, get_last_insn (), val, new);
 
-  e->insns = get_insns ();
+  e->insns.r = get_insns ();
   end_sequence ();
   return new_insn;
 }
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.200
diff -u -p -r1.1.4.200 tree-cfg.c
--- tree-cfg.c	8 Nov 2003 18:17:28 -0000	1.1.4.200
+++ tree-cfg.c	9 Nov 2003 09:10:55 -0000
@@ -85,15 +85,19 @@ static tree factored_computed_goto_label
    the destination of computed gotos when unfactoring them.  */
 static tree factored_computed_goto;
 
+/* The root of statement_lists of basic blocks for the garbage collector.
+   This is a hack; we really should GC the entire CFG structure.  */
+varray_type tree_bb_root;
+
 /* Basic blocks and flowgraphs.  */
+static basic_block create_bb (tree, basic_block);
 static void create_blocks_annotations (void);
 static void create_block_annotation (basic_block);
 static void free_blocks_annotations (void);
 static void clear_blocks_annotations (void);
-static basic_block make_blocks (tree *, basic_block);
-static inline void append_stmt_to_bb (tree *, basic_block);
-static inline void prepend_stmt_to_bb (tree *, basic_block);
+static void make_blocks (tree);
 static void factor_computed_gotos (void);
+static tree tree_block_label (basic_block bb);
 
 /* Edges.  */
 static void make_edges (void);
@@ -102,9 +106,10 @@ static void make_exit_edges (basic_block
 static void make_cond_expr_edges (basic_block);
 static void make_switch_expr_edges (basic_block);
 static void make_goto_expr_edges (basic_block);
+static edge tree_redirect_edge_and_branch_1 (edge, basic_block, bool);
+static edge tree_redirect_edge_and_branch (edge, basic_block);
 
 /* Various helpers.  */
-static tree *first_exec_stmt (tree *);
 static inline bool stmt_starts_bb_p (tree, tree);
 static inline bool stmt_ends_bb_p (tree);
 static int tree_verify_flow_info (void);
@@ -117,27 +122,14 @@ static bool tree_forwarder_block_p (basi
 /* Flowgraph optimization and cleanup.  */
 
 static void remove_bb (basic_block);
-static void remove_stmt (tree *, bool);
 static bool cleanup_control_flow (void);
 static edge find_taken_edge_cond_expr (basic_block, tree);
 static edge find_taken_edge_switch_expr (basic_block, tree);
 static tree find_case_label_for_value (tree, tree);
-static void replace_stmt (tree *, tree *);
 static int phi_alternatives_equal (basic_block, edge, edge);
 
-/* Block iterator helpers.  */
-static void remove_bsi_from_block (block_stmt_iterator *, bool);
-static block_stmt_iterator bsi_init (tree *, basic_block);
-static inline void bsi_update_from_tsi (block_stmt_iterator *,
-					tree_stmt_iterator);
-static tree_stmt_iterator bsi_link_after (tree_stmt_iterator *, tree,
-					  basic_block);
-
 /* Location to track pending stmt for edge insertion.  */
-#define PENDING_STMT(e)	((tree)(e->insns))
-
-/* Set the pending stmt field.  */
-#define SET_PENDING_STMT(e, t)	((e->insns) = (rtx)t)
+#define PENDING_STMT(e)	(e->insns.t)
 
 /*---------------------------------------------------------------------------
 			      Create basic blocks
@@ -149,8 +141,6 @@ static tree_stmt_iterator bsi_link_after
 void
 build_tree_cfg (tree *fnbody)
 {
-  tree *first_p;
-
   timevar_push (TV_TREE_CFG);
 
   /* Register specific tree functions.  */
@@ -162,6 +152,8 @@ build_tree_cfg (tree *fnbody)
   VARRAY_BB_INIT (basic_block_info, initial_cfg_capacity, "basic_block_info");
   memset ((void *) &cfg_stats, 0, sizeof (cfg_stats));
 
+  VARRAY_TREE_INIT (tree_bb_root, initial_cfg_capacity, "tree_bb_root");
+
   /* Build a mapping of labels to their associated blocks.  */
   VARRAY_BB_INIT (label_to_block_map, initial_cfg_capacity,
 		  "label to block map");
@@ -169,31 +161,28 @@ build_tree_cfg (tree *fnbody)
   ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
   EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
 
-  first_p = first_exec_stmt (fnbody);
-  if (first_p)
-    {
-      found_computed_goto = 0;
-      make_blocks (first_p, NULL);
+  found_computed_goto = 0;
+  make_blocks (*fnbody);
 
-      /* Computed gotos are hell to deal with, especially if there are
-	 lots of them with a large number of destinations.  So we factor
-	 them to a common computed goto location before we build the
-	 edge list.  After we convert back to normal form, we will un-factor
-	 the computed gotos since factoring introduces an unwanted jump.  */
-      if (found_computed_goto)
-	factor_computed_gotos ();
-
-      if (n_basic_blocks > 0)
-	{
-	  /* Adjust the size of the array.  */
-	  VARRAY_GROW (basic_block_info, n_basic_blocks);
+  /* Computed gotos are hell to deal with, especially if there are
+     lots of them with a large number of destinations.  So we factor
+     them to a common computed goto location before we build the
+     edge list.  After we convert back to normal form, we will un-factor
+     the computed gotos since factoring introduces an unwanted jump.  */
+  if (found_computed_goto)
+    factor_computed_gotos ();
+
+  if (n_basic_blocks > 0)
+    {
+      /* Adjust the size of the array.  */
+      VARRAY_GROW (basic_block_info, n_basic_blocks);
+      VARRAY_GROW (tree_bb_root, n_basic_blocks);
 
-	  /* Create block annotations.  */
-	  create_blocks_annotations ();
+      /* Create block annotations.  */
+      create_blocks_annotations ();
 
-	  /* Create the edges of the flowgraph.  */
-	  make_edges ();
-	}
+      /* Create the edges of the flowgraph.  */
+      make_edges ();
     }
 
 #if 0
@@ -253,8 +242,12 @@ factor_computed_gotos (void)
 	
   FOR_EACH_BB (bb)
     {
-      tree *last_p = last_stmt_ptr (bb);
-      tree last = *last_p;
+      block_stmt_iterator bsi = bsi_last (bb);
+      tree last;
+
+      if (bsi_end_p (bsi))
+	continue;
+      last = bsi_stmt (bsi);
 
       /* Ignore the computed goto we create when we factor the original
 	 computed gotos.  */
@@ -265,15 +258,14 @@ factor_computed_gotos (void)
       if (computed_goto_p (last))
 	{
 	  tree assignment;
-	  block_stmt_iterator bsi = bsi_last (bb);
 
 	  /* The first time we find a computed goto we need to create
 	     the factored goto block and the variable each original
 	     computed goto will use for their goto destination.  */
 	  if (! factored_computed_goto)
 	    {
-	      tree compound;
-	      tree_stmt_iterator tsi = tsi_from_bsi (bsi);
+	      basic_block new_bb = create_bb (NULL, bb);
+	      block_stmt_iterator new_bsi = bsi_start (new_bb);
 
 	      /* Create the destination of the factored goto.  Each original
 		 computed goto will put its desired destination into this
@@ -286,48 +278,26 @@ factor_computed_gotos (void)
 	      factored_label_decl = create_artificial_label ();
 	      factored_computed_goto_label
 		= build1 (LABEL_EXPR, void_type_node, factored_label_decl);
-	      modify_stmt (factored_computed_goto_label);
+	      bsi_insert_after (&new_bsi, factored_computed_goto_label,
+				BSI_NEW_STMT);
 
 	      /* Build our new computed goto.  */
 	      factored_computed_goto = build1 (GOTO_EXPR, void_type_node, var);
-	      modify_stmt (factored_computed_goto);
-
-	      /* Cram the new label and the computed goto into a container.  */
-	      compound = build (COMPOUND_EXPR, void_type_node,
-				factored_computed_goto_label,
-				factored_computed_goto);
-
-	      /* Ugh.  We want to pass the address of the container to
-		 make_blocks call below.  But we certainly don't want to
-		 to pass along the address of a global.  There's got to be
-		 a better way to do this than to create a dummy container.  */
-	      compound = build (COMPOUND_EXPR, void_type_node, compound, NULL);
-
-	      /* Put the new statements into a new basic block.  This must
-		 be done before we link them into the statement chain!  */
-	      make_blocks (&TREE_OPERAND (compound, 0), NULL);
-
-	      /* Now it is safe to link in the new statements.  */
-	      tsi_link_chain_after (&tsi,
-				    TREE_OPERAND (compound, 0),
-				    TSI_CHAIN_START);
+	      bsi_insert_after (&new_bsi, factored_computed_goto,
+				BSI_NEW_STMT);
 	    }
 
 	  /* Copy the original computed goto's destination into VAR.  */
           assignment = build (MODIFY_EXPR, ptr_type_node,
 			      var, GOTO_DESTINATION (last));
-	  modify_stmt (assignment);
+	  bsi_insert_before (&bsi, assignment, BSI_SAME_STMT);
 
-	  /* Insert that assignment just before the original computed
-	     goto.  */
-          set_bb_for_stmt (assignment, bb);
-	  bsi_insert_before (&bsi, assignment, BSI_NEW_STMT);
-
-	  /* And revector the computed goto to the new destination.  */
+	  /* And re-vector the computed goto to the new destination.  */
           GOTO_DESTINATION (last) = factored_label_decl;
 	}
     }
 }
+
 /* Create annotations for all the basic blocks.  */
 
 static void create_blocks_annotations (void)
@@ -385,34 +355,20 @@ clear_blocks_annotations (void)
     bb->tree_annotations = NULL;
 }
 
-/* Build a flowgraph for the statements starting at the statement pointed
-   by FIRST_P.
-
-   BB is the block where the statements should be added to.  If BB is NULL,
-      a new basic block will be created for the statements.
-
-   Return the last basic block added to the graph.  This is used to know if
-   a recursive invocation built a sub-graph whose last block can accept
-   more statements or not.  */
+/* Build a flowgraph for the statement_list STMT_LIST.  */
 
-static basic_block
-make_blocks (tree *first_p, basic_block bb)
+static void
+make_blocks (tree stmt_list)
 {
-  tree_stmt_iterator i;
-  tree stmt, last;
-  bool start_new_block;
-
-  if (first_p == NULL
-      || *first_p == error_mark_node)
-    return NULL;
+  tree_stmt_iterator i = tsi_start (stmt_list);
+  tree stmt = NULL;
+  bool start_new_block = true;
+  bool first_stmt_of_list = true;
+  basic_block bb = ENTRY_BLOCK_PTR;
 
-  start_new_block = (bb == NULL);
-  stmt = last = NULL;
-  for (i = tsi_start (first_p); !tsi_end_p (i); tsi_next (&i))
+  while (!tsi_end_p (i))
     {
-      enum tree_code code;
       tree prev_stmt;
-      tree *stmt_p = tsi_container (i);
 
       prev_stmt = stmt;
       stmt = tsi_stmt (i);
@@ -422,72 +378,35 @@ make_blocks (tree *first_p, basic_block 
 	 so now.  */
       if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
 	{
-	  bb = create_bb (NULL);
+	  if (!first_stmt_of_list)
+	    stmt_list = tsi_split_statement_list_before (&i);
+	  bb = create_bb (stmt_list, bb);
 	  start_new_block = false;
 	}
 
-      code = TREE_CODE (stmt);
-
       /* Now add STMT to BB and create the subgraphs for special statement
 	 codes.  */
-      append_stmt_to_bb (stmt_p, bb);
+      set_bb_for_stmt (stmt, bb);
 
-      if (computed_goto_p (*stmt_p))
+      if (computed_goto_p (stmt))
 	found_computed_goto = true;
 
-      /* All BIND_EXPRs except for the outermost one are lowered already.  */
-      if (code == BIND_EXPR)
-	abort ();
-
       /* If STMT is a basic block terminator, set START_NEW_BLOCK for the
-	 next iteration.  Also compute any reachable exception handlers
-	 for STMT.  */
-      if (stmt && stmt_ends_bb_p (stmt))
+	 next iteration.  */
+      if (stmt_ends_bb_p (stmt))
 	start_new_block = true;
 
-      last = stmt;
+      tsi_next (&i);
+      first_stmt_of_list = false;
     }
-
-  if (last)
-    return bb_for_stmt (last);
-
-  return NULL;
-}
-
-
-static inline void
-append_stmt_to_bb (tree *stmt_p, basic_block bb)
-{
-  set_bb_for_stmt (*stmt_p, bb);
-
-  /* Update the head and tail of the block.  */
-  if (bb->head_tree_p == NULL)
-    bb->head_tree_p = stmt_p;
-
-  bb->end_tree_p = stmt_p;
-}
-
-
-/* Add statement pointed by STMT_P to basic block BB and update BB's
-   boundaries accordingly.  */
-
-static inline void
-prepend_stmt_to_bb (tree *stmt_p, basic_block bb)
-{
-  set_bb_for_stmt (*stmt_p, bb);
-
-  /* Update the head and tail of the block.  */
-  bb->head_tree_p = stmt_p;
-
-  if (bb->end_tree_p == NULL)
-    bb->end_tree_p = stmt_p;
 }
 
 
-/* Create and return a new basic block after bb AFTER.  */
+/* Create and return a new basic block after bb AFTER.  Use STMT_LIST for
+   the body if non-null, otherwise create a new statement list.  */
 
-basic_block
-create_bb (basic_block after)
+static basic_block
+create_bb (tree stmt_list, basic_block after)
 {
   basic_block bb;
 
@@ -497,18 +416,23 @@ create_bb (basic_block after)
 
   bb->index = last_basic_block;
   bb->flags = BB_NEW;
+  bb->stmt_list = stmt_list ? stmt_list : alloc_stmt_list ();
 
   /* Add the new block to the linked list of blocks.  */
-  if (!after)
-    after = EXIT_BLOCK_PTR->prev_bb;
   link_block (bb, after);
 
   /* Grow the basic block array if needed.  */
   if ((size_t) n_basic_blocks == VARRAY_SIZE (basic_block_info))
-    VARRAY_GROW (basic_block_info, n_basic_blocks + (n_basic_blocks + 3) / 4);
+    {
+      size_t new_size = n_basic_blocks + (n_basic_blocks + 3) / 4;
+      VARRAY_GROW (basic_block_info, new_size);
+      VARRAY_GROW (tree_bb_root, new_size);
+    }
 
   /* Add the newly created block to the array.  */
   BASIC_BLOCK (n_basic_blocks) = bb;
+  VARRAY_TREE (tree_bb_root, bb->index) = bb->stmt_list;
+
   n_basic_blocks++;
   last_basic_block++;
 
@@ -528,7 +452,7 @@ make_edges (void)
 
   /* Create an edge from entry to the first block with executable
      statements in it.  */
-  make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), 0);
+  make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
 
   /* Traverse basic block array placing edges.  */
   FOR_EACH_BB (bb)
@@ -784,8 +708,9 @@ make_goto_expr_edges (basic_block bb)
 	      /* Computed GOTOs.  Make an edge to every label block that has
 		 been marked as a potential target for a computed goto.  */
 	      (FORCED_LABEL (LABEL_EXPR_LABEL (target)) && for_call == 0)
-	      /* Nonlocal GOTO target.  Make an edge to every label block that has
-		 been marked as a potential target for a nonlocal goto.  */
+	      /* Nonlocal GOTO target.  Make an edge to every label block
+		 that has been marked as a potential target for a nonlocal
+		 goto.  */
 	      || (NONLOCAL_LABEL (LABEL_EXPR_LABEL (target)) && for_call == 1))
 	    {
 	      make_edge (bb, target_bb, edge_flags);
@@ -843,8 +768,7 @@ cleanup_tree_cfg (void)
   timevar_pop (TV_TREE_CLEANUP_CFG);
 }
 
-/* Walk the function tree removing unnecessary statements and
-   variables.
+/* Walk the function tree removing unnecessary statements.
 
      * Empty statement nodes are removed
 
@@ -861,39 +785,46 @@ cleanup_tree_cfg (void)
    BIND_EXPR, or TRY block, we will need to repeat this optimization pass
    to ensure we eliminate all the useless code.  */
 
-struct rusv_data
+struct rus_data
 {
+  tree *last_goto;
   bool repeat;
-  bool remove_unused_vars;
   bool may_throw;
   bool may_branch;
 };
 
-static void remove_useless_stmts_and_vars_1 (tree *, struct rusv_data *);
+static void remove_useless_stmts_1 (tree *, struct rus_data *);
 
 static void
-remove_useless_stmts_and_vars_cond (tree *stmt_p, struct rusv_data *data)
+remove_useless_stmts_cond (tree *stmt_p, struct rus_data *data)
 {
   tree then_clause, else_clause, cond;
 
-  remove_useless_stmts_and_vars_1 (&COND_EXPR_THEN (*stmt_p), data);
-  remove_useless_stmts_and_vars_1 (&COND_EXPR_ELSE (*stmt_p), data);
+  remove_useless_stmts_1 (&COND_EXPR_THEN (*stmt_p), data);
+  remove_useless_stmts_1 (&COND_EXPR_ELSE (*stmt_p), data);
 
   then_clause = COND_EXPR_THEN (*stmt_p);
   else_clause = COND_EXPR_ELSE (*stmt_p);
   cond = COND_EXPR_COND (*stmt_p);
 
+  /* If neither arm does anything at all, we can remove the whole IF.  */
+  if (!TREE_SIDE_EFFECTS (then_clause) && !TREE_SIDE_EFFECTS (else_clause))
+    {
+      *stmt_p = build_empty_stmt ();
+      data->repeat = true;
+    }
+
   /* We may not have been able to completely optimize away the condition
      previously due to the existence of a label in one arm.  If the label
      has since become unreachable then we may be able to zap the entire
      conditional here.  If so, replace the COND_EXPR and set up to repeat
      this optimization pass.  */
-  if (integer_nonzerop (cond) && IS_EMPTY_STMT (else_clause))
+  else if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_clause))
     {
       *stmt_p = then_clause;
        data->repeat = true;
     }
-  else if (integer_zerop (cond) && IS_EMPTY_STMT (then_clause))
+  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_clause))
     {
       *stmt_p = else_clause;
       data->repeat = true;
@@ -938,7 +869,7 @@ remove_useless_stmts_and_vars_cond (tree
 }
 
 static void
-remove_useless_stmts_and_vars_tf (tree *stmt_p, struct rusv_data *data)
+remove_useless_stmts_tf (tree *stmt_p, struct rus_data *data)
 {
   bool save_may_branch, save_may_throw;
   bool this_may_branch, this_may_throw;
@@ -949,18 +880,18 @@ remove_useless_stmts_and_vars_tf (tree *
   data->may_branch = false;
   data->may_throw = false;
 
-  remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 0), data);
+  remove_useless_stmts_1 (&TREE_OPERAND (*stmt_p, 0), data);
 
   this_may_branch = data->may_branch;
   this_may_throw = data->may_throw;
   data->may_branch |= save_may_branch;
   data->may_throw |= save_may_throw;
 
-  remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 1), data);
+  remove_useless_stmts_1 (&TREE_OPERAND (*stmt_p, 1), data);
 
   /* If the body is empty, then we can emit the FINALLY block without
      the enclosing TRY_FINALLY_EXPR.  */
-  if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
+  if (!TREE_SIDE_EFFECTS (TREE_OPERAND (*stmt_p, 0)))
     {
       *stmt_p = TREE_OPERAND (*stmt_p, 1);
       data->repeat = true;
@@ -968,21 +899,25 @@ remove_useless_stmts_and_vars_tf (tree *
 
   /* If the handler is empty, then we can emit the TRY block without
      the enclosing TRY_FINALLY_EXPR.  */
-  else if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
+  else if (!TREE_SIDE_EFFECTS (TREE_OPERAND (*stmt_p, 1)))
     {
       *stmt_p = TREE_OPERAND (*stmt_p, 0);
       data->repeat = true;
     }
 
-  /* If the body neither throws, nor branches, then we can safely string
-     the TRY and FINALLY blocks together.  We'll reassociate this in the
-     main body of remove_useless_stmts_and_vars.  */
+  /* If the body neither throws, nor branches, then we can safely
+     string the TRY and FINALLY blocks together.  */
   else if (!this_may_branch && !this_may_throw)
-    TREE_SET_CODE (*stmt_p, COMPOUND_EXPR);
+    {
+      tree stmt = *stmt_p;
+      *stmt_p = TREE_OPERAND (stmt, 0);
+      add_to_statement_list (TREE_OPERAND (stmt, 1), stmt_p);
+      data->repeat = true;
+    }
 }
 
 static void
-remove_useless_stmts_and_vars_tc (tree *stmt_p, struct rusv_data *data)
+remove_useless_stmts_tc (tree *stmt_p, struct rus_data *data)
 {
   bool save_may_throw, this_may_throw;
   tree_stmt_iterator i;
@@ -992,7 +927,7 @@ remove_useless_stmts_and_vars_tc (tree *
   save_may_throw = data->may_throw;
   data->may_throw = false;
 
-  remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 0), data);
+  remove_useless_stmts_1 (&TREE_OPERAND (*stmt_p, 0), data);
 
   this_may_throw = data->may_throw;
   data->may_throw = save_may_throw;
@@ -1009,7 +944,7 @@ remove_useless_stmts_and_vars_tc (tree *
      no exceptions propagate past this point.  */
 
   this_may_throw = true;
-  i = tsi_start (&TREE_OPERAND (*stmt_p, 1));
+  i = tsi_start (TREE_OPERAND (*stmt_p, 1));
   stmt = tsi_stmt (i);
 
   switch (TREE_CODE (stmt))
@@ -1022,7 +957,7 @@ remove_useless_stmts_and_vars_tc (tree *
 	     propagate exceptions past this point.  */
 	  if (CATCH_TYPES (stmt) == NULL)
 	    this_may_throw = false;
-	  remove_useless_stmts_and_vars_1 (&CATCH_BODY (stmt), data);
+	  remove_useless_stmts_1 (&CATCH_BODY (stmt), data);
 	}
       break;
 
@@ -1031,16 +966,16 @@ remove_useless_stmts_and_vars_tc (tree *
 	this_may_throw = false;
       else if (EH_FILTER_TYPES (stmt) == NULL)
 	this_may_throw = false;
-      remove_useless_stmts_and_vars_1 (&EH_FILTER_FAILURE (stmt), data);
+      remove_useless_stmts_1 (&EH_FILTER_FAILURE (stmt), data);
       break;
 
     default:
       /* Otherwise this is a cleanup.  */
-      remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 1), data);
+      remove_useless_stmts_1 (&TREE_OPERAND (*stmt_p, 1), data);
 
       /* If the cleanup is empty, then we can emit the TRY block without
 	 the enclosing TRY_CATCH_EXPR.  */
-      if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
+      if (!TREE_SIDE_EFFECTS (TREE_OPERAND (*stmt_p, 1)))
 	{
 	  *stmt_p = TREE_OPERAND (*stmt_p, 0);
 	  data->repeat = true;
@@ -1051,12 +986,12 @@ remove_useless_stmts_and_vars_tc (tree *
 }
 
 static void
-remove_useless_stmts_and_vars_bind (tree *stmt_p, struct rusv_data *data)
+remove_useless_stmts_bind (tree *stmt_p, struct rus_data *data)
 {
   tree block;
 
   /* First remove anything underneath the BIND_EXPR.  */
-  remove_useless_stmts_and_vars_1 (&BIND_EXPR_BODY (*stmt_p), data);
+  remove_useless_stmts_1 (&BIND_EXPR_BODY (*stmt_p), data);
 
   /* If the BIND_EXPR has no variables, then we can pull everything
      up one level and remove the BIND_EXPR, unless this is the toplevel
@@ -1075,191 +1010,128 @@ remove_useless_stmts_and_vars_bind (tree
       *stmt_p = BIND_EXPR_BODY (*stmt_p);
       data->repeat = true;
     }
-  else if (data->remove_unused_vars)
-    {
-      /* If we were unable to completely eliminate the BIND_EXPR,
-	 go ahead and prune out any unused variables.  We do not
-	 want to expand them as that is a waste of time.  If we
-	 happen to remove all the variables, then we may be able
-	 to eliminate the BIND_EXPR as well.  */
-      tree vars, prev_var;
-
-      /* Walk all the variables associated with the BIND_EXPR.  */
-      for (prev_var = NULL, vars = BIND_EXPR_VARS (*stmt_p);
-	   vars;
-	   vars = TREE_CHAIN (vars))
-	{
-	  struct var_ann_d *ann;
-	  tree  var = vars;
-
-	  /* We could have function declarations and the like
-	     on this list.  Ignore them.  Also we do not deal with
-	     static variables yet.   */
-	  if (TREE_CODE (var) != VAR_DECL)
-	    {
-	      prev_var = vars;
-	      continue;
-	    }
-
-	  /* Unlike for normal expressions, the tree-inline duplicates
-	     static variables for BIND_EXPR in order to get debug info right.
-	     We must work out the original expression.  */
-	  if (TREE_STATIC (var) && DECL_ABSTRACT_ORIGIN (var))
-	    var = DECL_ABSTRACT_ORIGIN (var);
-
-	  /* Remove all unused, unaliased temporaries.  Also remove
-	     unused, unaliased local variables during highly
-	     optimizing compilations.  */
-	  ann = var_ann (var);
-	  if (ann
-	      && ! ann->may_aliases
-	      && ! ann->used
-	      && ! ann->has_hidden_use
-	      && ! TREE_ADDRESSABLE (var)
-	      && (DECL_ARTIFICIAL (var) || optimize >= 2))
-	    {
-	      /* Remove the variable from the BLOCK structures.  */
-	      if (block)
-		remove_decl (vars,
-			     (block
-			      ? block
-			      : DECL_INITIAL (current_function_decl)));
-
-	      /* And splice the variable out of BIND_EXPR_VARS.  */
-	      if (prev_var)
-		TREE_CHAIN (prev_var) = TREE_CHAIN (vars);
-	      else
-		BIND_EXPR_VARS (*stmt_p) = TREE_CHAIN (vars);
-	    }
-	  else
-	    prev_var = vars;
-	}
-
-      /* If there are no variables left after removing unused
-	 variables, then go ahead and remove this BIND_EXPR.  */
-      if (BIND_EXPR_VARS (*stmt_p) == NULL_TREE
-	  && *stmt_p != DECL_SAVED_TREE (current_function_decl)
-	  && (! block
-	      || ! BLOCK_ABSTRACT_ORIGIN (block)
-	      || (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
-		  != FUNCTION_DECL)))
-	{
-	  *stmt_p = BIND_EXPR_BODY (*stmt_p);
-	  data->repeat = true;
-	}
-    }
 }
 
 static void
-remove_useless_stmts_and_vars_goto (tree_stmt_iterator i, tree *stmt_p,
-				    struct rusv_data *data)
+remove_useless_stmts_goto (tree *stmt_p, struct rus_data *data)
 {
-  tree_stmt_iterator tsi = i;
+  tree dest = GOTO_DESTINATION (*stmt_p);
+
+  data->may_branch = true;
 
+  /* ??? Why bother putting this back together when rtl is just
+     about to take it apart again?  */
   if (factored_computed_goto_label
-      && (GOTO_DESTINATION (*stmt_p)
-	  == LABEL_EXPR_LABEL (factored_computed_goto_label)))
+      && (dest == LABEL_EXPR_LABEL (factored_computed_goto_label)))
     {
       GOTO_DESTINATION (*stmt_p) = GOTO_DESTINATION (factored_computed_goto);
       return;
     }
 
-  /* Step past the GOTO_EXPR statement.  */
-  tsi_next (&tsi);
-  if (! tsi_end_p (tsi))
-    {
-      /* If we are not at the end of this tree, then see if
-	 we are at the target label.  If so, then this jump
-	 is not needed.  */
-      tree label;
-
-      label = tsi_stmt (tsi);
-      if (TREE_CODE (label) == LABEL_EXPR
-	  && LABEL_EXPR_LABEL (label) == GOTO_DESTINATION (*stmt_p))
-	{
-	  data->repeat = true;
-	  *stmt_p = build_empty_stmt ();
-	  return;
-	}
+  /* Record the last goto expr, so that we can delete it if unnecessary.  */
+  if (TREE_CODE (dest) == LABEL_DECL)
+    data->last_goto = stmt_p;
+}
+
+static void
+remove_useless_stmts_label (tree *stmt_p, struct rus_data *data)
+{
+  if (data->last_goto
+      && GOTO_DESTINATION (*data->last_goto) == LABEL_EXPR_LABEL (*stmt_p))
+    {
+      *data->last_goto = build_empty_stmt ();
+      data->repeat = true;
     }
 
-  data->may_branch = true;
+  /* ??? Add something here to delete unused labels.  */
 }
 
 static void
-remove_useless_stmts_and_vars_1 (tree *first_p, struct rusv_data *data)
+remove_useless_stmts_1 (tree *tp, struct rus_data *data)
 {
-  tree_stmt_iterator i;
-
-  for (i = tsi_start (first_p); !tsi_end_p (i); tsi_next (&i))
+  tree t = *tp;
+  switch (TREE_CODE (t))
     {
-      tree *container_p = tsi_container (i);
-      tree *stmt_p;
-      enum tree_code code;
-
-      while (TREE_CODE (*container_p) == COMPOUND_EXPR)
-	{
-	  /* If either operand of a COMPOUND_EXPR is an empty statement,
-	     then remove the empty statement and the COMPOUND_EXPR itself.  */
-	  if (IS_EMPTY_STMT (TREE_OPERAND (*container_p, 1)))
-	    *container_p = TREE_OPERAND (*container_p, 0);
-	  else if (IS_EMPTY_STMT (TREE_OPERAND (*container_p, 0)))
-	    *container_p = TREE_OPERAND (*container_p, 1);
-	  else
-	    break;
-	}
+    case COND_EXPR:
+      data->last_goto = NULL;
+      remove_useless_stmts_cond (tp, data);
+      break;
 
-      /* Dive into control structures.  */
-      stmt_p = tsi_stmt_ptr (i);
-      code = TREE_CODE (*stmt_p);
-      switch (code)
-	{
-	case COND_EXPR:
-	  remove_useless_stmts_and_vars_cond (stmt_p, data);
-	  break;
-	case TRY_FINALLY_EXPR:
-	  remove_useless_stmts_and_vars_tf (stmt_p, data);
-	  break;
-	case TRY_CATCH_EXPR:
-	  remove_useless_stmts_and_vars_tc (stmt_p, data);
-	  break;
-	case BIND_EXPR:
-	  remove_useless_stmts_and_vars_bind (stmt_p, data);
-	  break;
-	case GOTO_EXPR:
-	  remove_useless_stmts_and_vars_goto (i, stmt_p, data);
-	  break;
-	case RETURN_EXPR:
-	  data->may_branch = true;
-	  break;
-	case MODIFY_EXPR:
-	case CALL_EXPR:
-	  if (tree_could_throw_p (*stmt_p))
-	    data->may_throw = true;
-	  break;
-	default:
-	  break;
-	}
+    case TRY_FINALLY_EXPR:
+      data->last_goto = NULL;
+      remove_useless_stmts_tf (tp, data);
+      break;
+
+    case TRY_CATCH_EXPR:
+      data->last_goto = NULL;
+      remove_useless_stmts_tc (tp, data);
+      break;
+
+    case BIND_EXPR:
+      remove_useless_stmts_bind (tp, data);
+      break;
+
+    case GOTO_EXPR:
+      data->last_goto = NULL;
+      remove_useless_stmts_goto (tp, data);
+      break;
+
+    case LABEL_EXPR:
+      remove_useless_stmts_label (tp, data);
+      break;
+
+    case RETURN_EXPR:
+      data->last_goto = NULL;
+      data->may_branch = true;
+      break;
+
+    case MODIFY_EXPR:
+    case CALL_EXPR:
+      data->last_goto = NULL;
+      if (tree_could_throw_p (t))
+        data->may_throw = true;
+      break;
+
+    case STATEMENT_LIST:
+      {
+        tree_stmt_iterator i = tsi_start (t);
+	while (!tsi_end_p (i))
+	  {
+	    t = tsi_stmt (i);
+	    if (IS_EMPTY_STMT (t))
+	      {
+		tsi_delink (&i);
+		continue;
+	      }
+	    
+	    remove_useless_stmts_1 (tsi_stmt_ptr (i), data);
+
+	    t = tsi_stmt (i);
+	    if (TREE_CODE (t) == STATEMENT_LIST)
+	      {
+		tsi_link_before (&i, t, TSI_SAME_STMT);
+		tsi_delink (&i);
+	      }
+	    else
+	      tsi_next (&i);
+	  }
+      }
+      break;
 
-      /* We need to keep the tree in gimple form, so we may have to
-	 re-rationalize COMPOUND_EXPRs.  */
-      if (TREE_CODE (*container_p) == COMPOUND_EXPR
-	  && TREE_CODE (TREE_OPERAND (*container_p, 0)) == COMPOUND_EXPR)
-	*container_p = rationalize_compound_expr (*container_p);
+    default:
+      data->last_goto = NULL;
+      break;
     }
 }
 
 void
-remove_useless_stmts_and_vars (tree *first_p, bool remove_unused_vars)
+remove_useless_stmts (tree *first_p)
 {
-  struct rusv_data data;
+  struct rus_data data;
   do
     {
       memset (&data, 0, sizeof (data));
-      data.remove_unused_vars = remove_unused_vars;
-      remove_unused_vars = false;
-
-      remove_useless_stmts_and_vars_1 (first_p, &data);
+      remove_useless_stmts_1 (first_p, &data);
     }
   while (data.repeat);
 
@@ -1330,9 +1202,7 @@ static void
 remove_bb (basic_block bb)
 {
   block_stmt_iterator i;
-  bsi_list_p stack;
-  location_t loc;
-  bool empty = true;
+  location_t *loc = NULL;
 
   dump_file = dump_begin (TDI_cfg, &dump_flags);
   if (dump_file)
@@ -1344,39 +1214,27 @@ remove_bb (basic_block bb)
       dump_file = NULL;
     }
 
-  /* Remove all the instructions in the block.  Do so in reverse order
-     so that we remove all the containing COMPOUND_EXPRs as well.  */
-  FOR_EACH_BSI_IN_REVERSE (stack, bb, i)
+  /* Remove all the instructions in the block.  */
+  for (i = bsi_start (bb); !bsi_end_p (i); bsi_remove (&i))
     {
       tree stmt = bsi_stmt (i);
 
       set_bb_for_stmt (stmt, NULL);
 
-      if (get_lineno (stmt) != -1
-	  /* Don't warn for removed gotos.  Gotos are often removed due to jump threading,
-	     thus resulting into bogus warnings.  Not great, since this way we lose warnings
-	     for gotos in the original program that are indeed unreachable.  */
-	  && TREE_CODE (stmt) != GOTO_EXPR)
-	{
-	  loc.file = get_filename (stmt);
-	  loc.line = get_lineno (stmt);
-	  empty = false;
-	}
-      bsi_remove (&i);
+      /* Don't warn for removed gotos.  Gotos are often removed due to
+	 jump threading, thus resulting into bogus warnings.  Not great,
+	 since this way we lose warnings for gotos in the original program
+	 that are indeed unreachable.  */
+      if (TREE_CODE (stmt) != GOTO_EXPR && EXPR_LOCUS (stmt) && !loc)
+	loc = EXPR_LOCUS (stmt);
     }
 
   /* If requested, give a warning that the first statement in the
      block is unreachable.  We walk statements backwards in the
      loop above, so the last statement we process is the first statement
      in the block.  */
-  if (warn_notreached && !empty)
-    warning ("%Hwill never be executed", &loc);
-
-  if (bb->head_tree_p)
-    set_bb_for_stmt (*bb->head_tree_p, NULL);
-
-  if (bb->end_tree_p)
-    set_bb_for_stmt (*bb->end_tree_p, NULL);
+  if (warn_notreached && loc)
+    warning ("%Hwill never be executed", loc);
 
   remove_phi_nodes_and_edges_for_unreachable_block (bb);
 
@@ -1385,211 +1243,12 @@ remove_bb (basic_block bb)
   if (pdom_info)
     delete_from_dominance_info (pdom_info, bb);
 
+  VARRAY_TREE (tree_bb_root, bb->index) = NULL_TREE;
+
   /* Remove the basic block from the array.  */
   expunge_block (bb);
 }
 
-/* Remove statement pointed by iterator I.
-
-    Note that this function will wipe out control statements that
-    may span multiple basic blocks.  Make sure that you really
-    want to remove the whole control structure before calling this
-    function.  Remove the annotations if REMOVE_ANNOTATIONS is true.  */
-
-static void
-remove_bsi_from_block (block_stmt_iterator *i, bool remove_annotations)
-{
-  tree t = *(i->tp);
-
-  if (is_exec_stmt (t))
-    {
-      if (TREE_CODE (t) == COMPOUND_EXPR)
-	{
-	  basic_block op0_bb = bb_for_stmt (TREE_OPERAND (t, 0));
-	  basic_block op1_bb = bb_for_stmt (TREE_OPERAND (t, 1));
-
-	  remove_stmt (&TREE_OPERAND (t, 0), remove_annotations);
-
-	  /* If both operands are empty and they are not associated
-	     with different basic blocks, then delete the whole
-	     COMPOUND_EXPR.  */
-	  if (IS_EMPTY_STMT (TREE_OPERAND (t, 1))
-	      && (op0_bb == NULL
-		  || op1_bb == NULL
-		  || op0_bb == op1_bb))
-	    remove_stmt (i->tp, remove_annotations);
-	}
-      else
-	remove_stmt (i->tp, remove_annotations);
-    }
-  
-  bsi_next (i);
-}
-
-void
-bsi_remove (block_stmt_iterator *i)
-{
-  remove_bsi_from_block (i, true);
-}
-
-/* Move the statement at FROM so it comes right after the statement at
-   TO.  */
-void 
-bsi_move_after (block_stmt_iterator from, block_stmt_iterator to)
-{
-  tree stmt = bsi_stmt (from);
-  remove_bsi_from_block (&from, false);
-  bsi_insert_after (&to, stmt, BSI_SAME_STMT);
-} 
-
-/* Move the statement at FROM so it comes right before the statement
-   at TO.  */
-void 
-bsi_move_before (block_stmt_iterator from, block_stmt_iterator to)
-{
-  tree stmt = bsi_stmt (from);
-  remove_bsi_from_block (&from, false);
-  bsi_insert_before (&to, stmt, BSI_SAME_STMT);
-}
-
-/* Move the statement at FROM to the end of basic block BB, */
-void
-bsi_move_to_bb_end (block_stmt_iterator from, basic_block bb)
-{
-  block_stmt_iterator last = bsi_last (bb);
-  
-  /* Have to check bsi_end_p because it could be an empty block.  */
-  if (!bsi_end_p (last)
-      && is_ctrl_stmt (bsi_stmt (last)))
-    {
-      bsi_move_before (from, last);
-    }
-  else
-    {
-      bsi_move_after (from, last);
-    }
-}
-
-/* Replace the contents of a stmt with another. The replacement cannot be
-   a COMPOUND_EXPR node, only a gimple stmt.  */
-
-void
-bsi_replace (block_stmt_iterator bsi, tree stmt)
-{
-  if (TREE_CODE (stmt) == COMPOUND_EXPR)
-    abort ();
-
-  replace_stmt (bsi.tp, &stmt);
-  modify_stmt (bsi_stmt (bsi));
-}
-
-/* Remove statement *STMT_P.
-
-   Update all references associated with it.  Note that this function will
-   wipe out control statements that may span multiple basic blocks.  Make
-   sure that you really want to remove the whole control structure before
-   calling this function.
-   Reset the annotations if REMOVE_ANNOTATIONS is true.  */
-
-static void
-remove_stmt (tree *stmt_p, bool remove_annotations)
-{
-  varray_type vdefs;
-  size_t i;
-  varray_type defs;
-  tree stmt = *stmt_p;
-  basic_block bb = bb_for_stmt (stmt);
-  int update_head = 0;
-  int update_end = 0;
-
-  /* If the statement is a LABEL_EXPR, remove the LABEL_DECL from
-     the symbol table.  */
-  if (TREE_CODE (stmt) == LABEL_EXPR)
-    remove_decl (LABEL_EXPR_LABEL (stmt), DECL_INITIAL (current_function_decl));
-
-  if (remove_annotations)
-    {
-      /* If the statement is already in SSA form, mark all the
-	 definitions made in the statement invalid.
-	 
-	 FIXME: We should probably traverse all the def-use edges
-	 originating at this statement to update each use of the
-	 definitions made here, but that is expensive and can easily
-	 be checked by every pass by checking if SSA_NAME_DEF_STMT is
-	 a nop.  */ 
-      stmt_ann_t ann = stmt_ann (stmt);
-      defs = def_ops (ann);
-      for (i = 0; defs && i < VARRAY_ACTIVE_SIZE (defs); i++)
-	{
-	  tree *def_p = VARRAY_TREE_PTR (defs, i);
-	  if (TREE_CODE (*def_p) == SSA_NAME)
-	    SSA_NAME_DEF_STMT (*def_p) = build_empty_stmt ();
-	}
-      
-      vdefs = vdef_ops (ann);
-      for (i = 0; vdefs && i < VARRAY_ACTIVE_SIZE (vdefs); i++)
-	{
-	  tree vdef = VDEF_RESULT (VARRAY_TREE (vdefs, i));
-	  if (TREE_CODE (vdef) == SSA_NAME)
-	    SSA_NAME_DEF_STMT (vdef) = build_empty_stmt ();
-	}
-      
-      stmt->common.ann = NULL;
-    }
-
-  /* The RHS of a MODIFY_EXPR has an annotation for the benefit of
-     SSA-PRE.  Make sure to remove that annotation as well.
-
-     We're somewhat conservative here in that we do not remove all
-     annotations on the RHS of the MODIFY_EXPR, just those of type
-     TREE_ANN_COMMON.  If the annotation had another type such
-     as VAR_ANN other code may still need it and it'll get removed
-     when we remove all the VAR_ANNs as we tear down the SSA form.  */
-  if (TREE_CODE (stmt) == MODIFY_EXPR
-      && TREE_OPERAND (stmt, 1)->common.ann
-      && TREE_OPERAND (stmt, 1)->common.ann->common.type == TREE_ANN_COMMON)
-    TREE_OPERAND (stmt, 1)->common.ann = NULL;
-
-  /* If we are removing a COMPOUND_EXPR, we may need to update block
-     head/tail pointers which point into operands of the COMPOUND_EXPR.  */
-  if (TREE_CODE (stmt) == COMPOUND_EXPR)
-    {
-      basic_block op0_bb = bb_for_stmt (TREE_OPERAND (stmt, 0));
-      basic_block op1_bb = bb_for_stmt (TREE_OPERAND (stmt, 1));
-
-#ifdef ENABLE_CHECKING
-      if (op0_bb && op1_bb && op0_bb != op1_bb)
-	abort ();
-#endif
-
-      if (op0_bb)
-	bb = op0_bb;
-      else
-	bb = op1_bb;
-
-      if (bb
-	  && (&TREE_OPERAND (stmt, 0) == bb->head_tree_p
-	      || &TREE_OPERAND (stmt, 1) == bb->head_tree_p))
-	update_head = 1;
-
-      if (bb
-	  && (&TREE_OPERAND (stmt, 0) == bb->end_tree_p
-	      || &TREE_OPERAND (stmt, 1) == bb->end_tree_p))
-	update_end = 1;
-    }
-
-  /* Replace STMT with an empty statement.  */
-  *stmt_p = build_empty_stmt ();
-  if (bb)
-    set_bb_for_stmt (*stmt_p, bb);
-
-  if (update_head)
-    bb->head_tree_p = stmt_p;
-
-  if (update_end)
-    bb->end_tree_p = stmt_p;
-}
-
 /* Examine BB to determine if it is a forwarding block (a block which only
    transfers control to a new destination).  If BB is a forwarding block,
    then return the ultimate destination.  */
@@ -1599,6 +1258,7 @@ tree_block_forwards_to (basic_block bb)
 {
   block_stmt_iterator bsi;
   bb_ann_t ann = bb_ann (bb);
+  tree stmt;
 
   /* If this block is not forwardable, then avoid useless work.  */
   if (! ann->forwardable)
@@ -1624,56 +1284,35 @@ tree_block_forwards_to (basic_block bb)
 
   /* Walk past any labels or empty statements at the start of this block.  */
   bsi = bsi_start (bb);
-  while (! bsi_end_p (bsi)
-	 && (IS_EMPTY_STMT (bsi_stmt (bsi))
-	     || TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR))
-    bsi_next (&bsi);
+  while (1)
+    {
+      stmt = NULL;
+      if (bsi_end_p (bsi))
+	break;
+      stmt = bsi_stmt (bsi);
+      if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
+	bsi_next (&bsi);
+      else
+	break;
+    }
 
   /* If we reached the end of this block, or hit a GOTO_EXPR to an known
      location, then we may be able to optimize this case.  */
-  if (bsi_end_p (bsi)
-      || (bsi_stmt (bsi)
-	  && TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR
-	  && TREE_CODE (GOTO_DESTINATION (bsi_stmt (bsi))) == LABEL_DECL))
+  if (!stmt
+      || (TREE_CODE (stmt) == GOTO_EXPR
+	  && TREE_CODE (GOTO_DESTINATION (stmt)) == LABEL_DECL))
     {
       basic_block dest;
 
       /* Recursive call to pick up chains of forwarding blocks.  */
       dest = tree_block_forwards_to (bb->succ->dest);
-      if (dest)
-	{
-	  ann->forwardable = 1;
-	  return dest;
-	}
-
-      /* If we hit the end of the block, then we may need to insert a label
-	 at this block's destination.  */
-      if (bsi_end_p (bsi))
-	{
-	  tree stmt;
-
-	  bsi = bsi_start (bb->succ->dest);
-
-	  /* It's not clear if we can safely insert the label in this case.  */
-          if (bsi_end_p (bsi))
-	    return NULL;
-
-	  stmt = bsi_stmt (bsi);
 
-	  /* If our new destination does not start with a label,
-	     then add one.  */
-	  if (TREE_CODE (stmt) != LABEL_EXPR)
-	    {
-	      /* DEST does not start with a label, add one.  */
-	      stmt = create_artificial_label ();
-	      stmt = build1 (LABEL_EXPR, void_type_node, stmt);
-	      bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
-	    }
-	}
+      /* If none found, we forward to bb->succ->dest at minimum.  */
+      if (!dest)
+	dest = bb->succ->dest;
 
-      /* This block forwards to bb->succ->dest.  */
       ann->forwardable = 1;
-      return bb->succ->dest;
+      return dest;
     }
 
   /* No forwarding possible.  */
@@ -1747,9 +1386,9 @@ cleanup_cond_expr_graph (basic_block bb,
     taken_edge = bb->succ;
 
   if (taken_edge->flags & EDGE_TRUE_VALUE)
-    bsi_replace (bsi, COND_EXPR_THEN (cond_expr));
+    bsi_replace (&bsi, COND_EXPR_THEN (cond_expr));
   else if (taken_edge->flags & EDGE_FALSE_VALUE)
-    bsi_replace (bsi, COND_EXPR_ELSE (cond_expr));
+    bsi_replace (&bsi, COND_EXPR_ELSE (cond_expr));
   else
     abort ();
 
@@ -1813,7 +1452,7 @@ cleanup_switch_expr_graph (basic_block b
 
   /* Simplify the SWITCH_EXPR itself.  */
   taken_case = build (GOTO_EXPR, void_type_node, CASE_LABEL (taken_case));
-  bsi_replace (bsi, taken_case);
+  bsi_replace (&bsi, taken_case);
 
   return retval;
 }
@@ -2014,11 +1653,10 @@ tree_dump_bb (basic_block bb, FILE *outf
 
   for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
     {
-      fprintf (outf, "%s%d  ", s_indent, get_lineno (bsi_stmt (si)));
-      print_generic_stmt (outf, bsi_stmt (si),
-			  (TREE_CODE (bsi_stmt (si)) == BIND_EXPR
-			   ? TDF_SLIM
-			   : 0));
+      tree stmt = bsi_stmt (si);
+      fprintf (outf, "%s%d  ", s_indent, get_lineno (stmt));
+      print_generic_stmt (outf, stmt,
+			  (TREE_CODE (stmt) == BIND_EXPR ? TDF_SLIM : 0));
     }
 }
 
@@ -2130,34 +1768,32 @@ dump_cfg_function_to_file (tree fn, FILE
     {
       if (show_bb_headers)
 	{
-	  fprintf (file, "# BLOCK %d\n ", bb->index);
+	  fprintf (file, "# BLOCK %d\n", bb->index);
 	  fprintf (file, "# PRED");
 	  for (e = bb->pred; e; e = e->pred_next)
 	    dump_edge_info (file, e, 0);
 	  putc ('\n', file);
+
+	  fprintf (file, "# SUCC");
+	  for (e = bb->succ; e; e = e->succ_next)
+	    dump_edge_info (file, e, 1);
+	  fprintf (file, "\n");
 	}
+
       for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
 	{
-	  fprintf (file, "\t# ");
+	  fprintf (file, "# ");
 	  print_generic_stmt (file, phi, flags);
-	  fprintf (file, "\n");
 	}
 
       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
 	{
-	  fprintf (file, "%d\t", get_lineno (bsi_stmt (si)));
-	  print_generic_stmt (file, bsi_stmt (si), flags);
-	  fprintf (file, "\n");
-	}
-
-      if (show_bb_headers)
-	{
-	  fprintf (file, "# SUCC");
-	  for (e = bb->succ; e; e = e->succ_next)
-	    dump_edge_info (file, e, 1);
-	  fprintf (file, "\n\n");
+	  tree stmt = bsi_stmt (si);
+	  print_generic_stmt (file, stmt, flags);
 	}
+      fprintf (file, "\n");
     }
+
   fprintf (file, "}\n\n");
 }
 
@@ -2273,7 +1909,7 @@ tree_cfg2dot (FILE *file)
         {
 	  head_code = TREE_CODE (first);
 	  head_name = tree_code_name[head_code];
-	  head_line = get_lineno (*(bb->head_tree_p));
+	  head_line = get_lineno (first);
 	}
       else
         head_name = "no-statement";
@@ -2282,12 +1918,11 @@ tree_cfg2dot (FILE *file)
         {
 	  end_code = TREE_CODE (last);
 	  end_name = tree_code_name[end_code];
-	  end_line = get_lineno (*(bb->end_tree_p));
+	  end_line = get_lineno (last);
 	}
       else
         end_name = "no-statement";
 
-
       fprintf (file, "\t%d [label=\"#%d\\n%s (%d)\\n%s (%d)\"];\n",
 	       bb->index, bb->index, head_name, head_line, end_name,
 	       end_line);
@@ -2372,9 +2007,8 @@ is_ctrl_altering_stmt (tree t)
   return tree_can_throw_internal (t);
 }
 
-
-/* Return flags associated with the function called by T (see ECF_* in
-   rtl.h)  */
+/* Return flags associated with the function called by T
+   (see ECF_* in rtl.h).  */
 
 int
 call_expr_flags (tree t)
@@ -2393,7 +2027,6 @@ call_expr_flags (tree t)
   return flags;
 }
 
-
 /* Return true if T is a computed goto.  */
 
 bool
@@ -2471,8 +2104,7 @@ stmt_starts_bb_p (tree t, tree prev_t)
 static inline bool
 stmt_ends_bb_p (tree t)
 {
-  return (is_ctrl_stmt (t)
-	  || is_ctrl_altering_stmt (t));
+  return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t);
 }
 
 
@@ -2483,299 +2115,54 @@ delete_tree_cfg (void)
 {
   if (n_basic_blocks > 0)
     free_blocks_annotations ();
-
   free_basic_block_vars (0);
+  tree_bb_root = NULL;
 }
 
-
-/* Return a pointer to the first executable statement starting at ENTRY_P.  */
-
-static tree *
-first_exec_stmt (tree *entry_p)
-{
-  tree_stmt_iterator i;
-  tree stmt;
-
-  for (i = tsi_start (entry_p); !tsi_end_p (i); tsi_next (&i))
-    {
-      stmt = tsi_stmt (i);
-      if (!stmt)
-        continue;
-
-      /* Note that we actually return the container for the executable
-	 statement, not the statement itself.  This is to allow the caller to
-	 start iterating from this point.  */
-      if (is_exec_stmt (stmt))
-	return tsi_container (i);
-    }
-
-  return NULL;
-}
-
-/* Return the first statement in basic block BB, stripped of any NOP
-   containers.  */
+/* Return the first statement in basic block BB, stripped of any NOP
+   containers.  */
 
 tree
 first_stmt (basic_block bb)
 {
-  block_stmt_iterator i;
-
-  i = bsi_start (bb);
-  return (!bsi_end_p (i)) ? bsi_stmt (i) : NULL_TREE;
+  block_stmt_iterator i = bsi_start (bb);
+  return !bsi_end_p (i) ? bsi_stmt (i) : NULL_TREE;
 }
 
 /* Return the last statement in basic block BB, stripped of any NOP
-   containers.
-
-   empty statement nodes are never returned. NULL is returned if there are
-   no such statements.  */
+   containers.  */
 
 tree
 last_stmt (basic_block bb)
 {
-  block_stmt_iterator b;
-
-  b = bsi_last (bb);
-  return (!bsi_end_p (b)) ? bsi_stmt (b) : NULL_TREE;
+  block_stmt_iterator b = bsi_last (bb);
+  return !bsi_end_p (b) ? bsi_stmt (b) : NULL_TREE;
 }
 
-
 /* Return a pointer to the last statement in block BB.  */
 
 tree *
 last_stmt_ptr (basic_block bb)
 {
-  block_stmt_iterator last;
-
-  last = bsi_last (bb);
-  return (!bsi_end_p (last)) ? bsi_stmt_ptr (last) : NULL;
-}
-
-
-/* Initialize a block stmt iterator with a container that contains stmt's
-   in a specified basic block. If the first real stmt is not in the
-   specified basic block, then return an empty iterator.  */
-
-static block_stmt_iterator
-bsi_init (tree *tp, basic_block bb)
-{
-  block_stmt_iterator i;
-  tree stmt;
-
-  i.tp = tp;
-  i.context = NULL_TREE;
-  /* If the first statement is empty, get the next non-empty one.  */
-  if (i.tp != NULL)
-    {
-      stmt = bsi_stmt (i);
-      if (stmt == NULL_TREE)
-	bsi_next_in_bb (&i, bb);
-    }
-
-  /* Now check that its the right basic block.  */
-  if (i.tp != NULL)
-    {
-      stmt = bsi_stmt (i);
-      if (bb_for_stmt (stmt) != bb)
-        i.tp = NULL;
-    }
-
-  return i;
-}
-
-/* Similar to tsi_step() but stops at basic block boundaries and ignores
-   empty statement nodes inside a basic block.  */
-
-void
-bsi_next_in_bb (block_stmt_iterator *i, basic_block bb)
-{
-  tree t, stmt = NULL_TREE;
-
-  /* Go to the next statement skipping over empty statements we may find.  */
-  do
-    {
-      t = *(i->tp);
-      if (TREE_CODE (t) == COMPOUND_EXPR)
-	i->tp = &(TREE_OPERAND (t, 1));
-      else
-	{
-	  /* We ran out of statements.  Clear the iterator and stop
-	     searching.  */
-	  i->tp = NULL;
-	  break;
-	}
-
-      stmt = bsi_stmt (*i);
-    }
-  while (IS_EMPTY_STMT (stmt));
-
-  if (i->tp && bb_for_stmt (stmt) != bb)
-    i->tp = NULL;
-
-  if (i->tp == NULL && i->context != NULL_TREE)
-    {
-      /* If we haven't got a statement, and we have context, pop the state and
-         traverse to the next statement.  */
-      i->tp = (tree *)TREE_VALUE (i->context);
-      i->context = TREE_PURPOSE (i->context);
-
-      /* FIXME.  Hack to recover BB for cases when we are stepping out of a
-	 removed statement.  If bsi_remove() has been called on the
-	 last statement of a BIND_EXPR body, the next call to
-	 bsi_next() will retrieve a NULL basic block from the just deleted
-	 statement, so that BB will be NULL.  We restore BB using the
-	 BIND_EXPR node itself.  */
-      bb = bb_for_stmt (*(i->tp));
-
-      bsi_next_in_bb (i, bb);
-    }
-}
-
-/* Similar to tsi_start() but initializes the iterator at the first
-   statement in basic block BB which isn't an empty statement node.
-
-   NULL is returned if there are no such statements.  */
-
-block_stmt_iterator
-bsi_start (basic_block bb)
-{
-  block_stmt_iterator i;
-  tree t;
-
-  if (bb && bb->index != INVALID_BLOCK)
-    {
-      tree *tp = bb->head_tree_p;
-      i = bsi_init (tp, bb);
-      if (i.tp != NULL)
-	{
-	  /* If we get back a statement which is not within this basic
-	     block, that is wrong!  */
-	  t = bsi_stmt (i);
-	  if (t != NULL_TREE && bb_for_stmt (t) != bb)
-	    abort ();
-	}
-      }
-    else
-      i.tp = NULL;
-
-  /* If there are no stmts in the block, set the context to point to the
-     basic block in case we try to insert a stmt with this iterator.  */
-
-  if (i.tp == NULL)
-    i.context = (tree) bb;
-
-  return i;
-}
-
-/* This routine will return a block iterator which points to the last stmt in
-   a basic block, if there is one.  */
-
-block_stmt_iterator
-bsi_last (basic_block bb)
-{
-  block_stmt_iterator b, tmp;
-
-  if (bb == NULL || bb->index == INVALID_BLOCK)
-    {
-      b.tp = NULL;
-      return b;
-    }
-
-  b = bsi_init (bb->end_tree_p, bb);
-
-  /* If the last stmt pointer isn't something a BSI can represent (ie, an
-     empty statement node), then find the last stmt the slow way.  */
-  if (b.tp == NULL)
-    {
-      for (tmp = b = bsi_start (bb); !bsi_end_p (tmp); bsi_next (&tmp))
-        b = tmp;
-    }
-
-  return b;
+  block_stmt_iterator last = bsi_last (bb);
+  return !bsi_end_p (last) ? bsi_stmt_ptr (last) : NULL;
 }
 
-
-/* Find the previous iterator value.  */
+/* Insert statement T into basic block BB.  */
 
 void
-bsi_prev (block_stmt_iterator *i)
+set_bb_for_stmt (tree t, basic_block bb)
 {
-  block_stmt_iterator bi, next;
-
-  bi = bsi_start (bb_for_stmt (bsi_stmt (*i)));
-  if (bi.tp != i->tp)
+  if (TREE_CODE (t) == STATEMENT_LIST)
     {
-      for ( ; !bsi_end_p (bi); bi = next)
-	{
-	  next = bi;
-	  bsi_next (&next);
-	  if (next.tp == i->tp)
-	    {
-	      i->tp = bi.tp;
-	      i->context = bi.context;
-	      return;
-	    }
-	}
+      tree_stmt_iterator i;
+      for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+	set_bb_for_stmt (tsi_stmt (i), bb);
     }
-
-  i->tp = NULL;
-  bi.context = NULL_TREE;
-  return;
-}
-
-
-/* Initialize a block_stmt_iterator with a statement pointed to by a tree
-   iterator. If this cannot be done, a NULL iterator is returned.  */
-
-block_stmt_iterator
-bsi_from_tsi (tree_stmt_iterator ti)
-{
-  basic_block bb;
-  tree stmt;
-  block_stmt_iterator bi;
-
-  stmt = tsi_stmt (ti);
-  if (stmt)
+  else
     {
-      bb = bb_for_stmt (stmt);
-      if (bb)
-        {
-	  for (bi = bsi_start (bb); !bsi_end_p (bi); bsi_next (&bi))
-	    if (bi.tp == ti.tp)
-	      return bi;
-	}
-    }
-
-  bi.tp = NULL;
-  bi.context = NULL_TREE;
-  return bi;
-}
-
+      stmt_ann_t ann;
 
-/* This is a more efficient version of bsi_from_tsi which can be used when
-   we are changing a bsi in a known way. Specifically, we know that the tsi
-   is located in the same 'context' area (ie, within the same BIND_EXPR),
-   so that the context doesn't have to be re-evaluated. This is primarily for
-   the insert routines which know what they are doing.  */
-
-static inline void
-bsi_update_from_tsi (block_stmt_iterator *bsi, tree_stmt_iterator tsi)
-{
-  /* Pretty simple right now, but its better to have this in an interface
-     rather than exposed right in the insert routine.  */
-  bsi->tp = tsi.tp;
-}
-
-
-/* Insert statement T into basic block BB.  */
-
-void
-set_bb_for_stmt (tree t, basic_block bb)
-{
-  stmt_ann_t ann;
-
-  do
-    {
       /* If the statement is a label, add the label to block-to-labels map
 	 so that we can speed up edge creation for GOTO_EXPRs.  */
       if (TREE_CODE (t) == LABEL_EXPR)
@@ -2787,524 +2174,150 @@ set_bb_for_stmt (tree t, basic_block bb)
 
       ann = get_stmt_ann (t);
       ann->bb = bb;
-      t = (TREE_CODE (t) == COMPOUND_EXPR) ? TREE_OPERAND (t, 0) : NULL_TREE;
     }
-  while (t);
 }
 
+/* Insert a statement, or statement list, before the given pointer.  */
 
-/* Insert routines.  */
-
-/* Because of the way containers and CE nodes are maintained, linking a new
-   stmt in can have significant consequences on the basic block information.
-   The basic block structure maintains the head and tail pointers as
-   containers, or pointers to the pointer to a node.
-
-   Linking a new stmt after the last stmt in a block changes not only the
-   tail pointer of this block, but the container for the head of the next block
-   is now contained in a new node, so the head pointer must be updated in
-   a that different block. If it is the only statement in that block, then
-   the end pointer needs to be updated too.
-
-   Linking a stmt after the penultimate (next to last) stmt in a block adds
-   a node which has the container to the end block stmt, so the block end must
-   be updated in this case.
-
-   And the third case is the simple one when we are adding a new stmt to the
-   end of a chain which also ends a block.  */
-
-/* This routine returns a tree stmt iterator which points to the original
-   stmt before we did an insert.  The first parameter is a tree stmt iterator
-   which is updated to point to the new stmt.  */
-
-static tree_stmt_iterator
-bsi_link_after (tree_stmt_iterator *this_tsi, tree t, basic_block curr_bb)
+void
+bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
 {
-  enum link_after_cases { NO_UPDATE,
-			  END_OF_CHAIN,
-			  PENULTIMATE_STMT,
-			  AFTER_LAST_STMT,
-			  JUST_UPDATE };
-  enum link_after_cases update_form = NO_UPDATE;
-  basic_block bb;
-  tree_stmt_iterator same_tsi, next_tsi;
-  tree *this_container;
-
-  this_container = tsi_container (*this_tsi);
-  same_tsi = next_tsi = *this_tsi;
-  tsi_next (&next_tsi);
-  if (tsi_end_p (next_tsi))
-    update_form = END_OF_CHAIN;
-  /* This is the penultimate case. The next stmt is actually the last stmt
-     in the block, so we need to update the tail pointer to be the new
-     container for that stmt after we link in the new one.  */
-  else if (tsi_container (next_tsi) == curr_bb->end_tree_p)
-    update_form = PENULTIMATE_STMT;
-  /* The ugly case which requires updating pointers in a different
-     basic block.  */
-  else if (this_container == curr_bb->end_tree_p)
-    {
-      /* Double check to make sure the next stmt is indeed the head of
-	 a different block.  */
-      bb = bb_for_stmt (*tsi_container (next_tsi));
-      if (bb
-	  && bb != curr_bb
-	  && bb->head_tree_p == tsi_container (next_tsi))
-	update_form = AFTER_LAST_STMT;
-      else
-	/* There are nops between the end of this block and the beginning
-	   of the next, so we only need to update our end pointer.  */
-	update_form = JUST_UPDATE;
-    }
-
-  tsi_link_after (&same_tsi, t, TSI_SAME_STMT);
-  if (update_form == END_OF_CHAIN)
-    {
-      /* If the stmt was added to the end of a chain, the linking routines
-	 created a new CE node to be a container for what use to be the
-	 last stmt in the chain.  This container needs to have the BB info
-	 set for it as well.  */
-      set_bb_for_stmt (*tsi_container (same_tsi), curr_bb);
-    }
-  *this_tsi = same_tsi;
-  tsi_next (this_tsi);
-  set_bb_for_stmt (*tsi_container (*this_tsi), curr_bb);
-
-  switch (update_form)
-    {
-    case END_OF_CHAIN:
-    case JUST_UPDATE:
-      if (this_container == curr_bb->end_tree_p)
-	curr_bb->end_tree_p = tsi_container (*this_tsi);
-      break;
-
-    case PENULTIMATE_STMT:
-      next_tsi = *this_tsi;
-      tsi_next (&next_tsi);
-      curr_bb->end_tree_p = tsi_container (next_tsi);
-      break;
-
-    case AFTER_LAST_STMT:
-      /* This is now the end of block.  */
-      curr_bb->end_tree_p = tsi_container (*this_tsi);
-
-      /* And the next basic block's head needs updating too.  */
-      next_tsi = *this_tsi;
-      tsi_next (&next_tsi);
-      bb = bb_for_stmt (tsi_stmt (next_tsi));
-      /* Oh, and we also need to check if this is both the head *and* the
-	 end of the next block.  */
-      if (bb->end_tree_p == bb->head_tree_p)
-	bb->end_tree_p = tsi_container (next_tsi);
-      bb->head_tree_p = tsi_container (next_tsi);
-      break;
-
-    default:
-      break;
-    }
-
-  return same_tsi;
+  set_bb_for_stmt (t, i->bb);
+  modify_stmt (t);
+  tsi_link_before (&i->tsi, t, m);
 }
 
-
-/* This routine inserts a stmt after the stmt iterator passed in.
-   The final parameter determines whether the statement iterator
-   is updated to point to the new stmt, or left pointing to the original
-   statement.  (Which may have a different container, by the way.)  */
-
 void
-bsi_insert_after (block_stmt_iterator *curr_bsi, tree t,
-		  enum bsi_iterator_update mode)
+bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
 {
-  tree_stmt_iterator inserted_tsi, same_tsi;
-  basic_block curr_bb;
-  tree *curr_container;
-  tree curr_stmt, inserted_stmt;
-
-  curr_container = bsi_container (*curr_bsi);
-  if (curr_container)
-    {
-      curr_stmt = bsi_stmt (*curr_bsi);
-      curr_bb = bb_for_stmt (curr_stmt);
-    }
-  else
-    {
-      curr_stmt = NULL_TREE;
-
-      /* bsi_start () will initialize the context pointer to the basic block
-         if the the block is completely devoid of instructions, except
-	 for possibly an empty statement node.  */
-      if (curr_bsi->tp == NULL && curr_bsi->context != NULL)
-        curr_bb = (basic_block)(curr_bsi->context);
-      else
-        abort ();
-    }
-
-  /* Some blocks are empty. The block iterator points to an empty statement
-     node in those cases only.  */
-  if (curr_stmt == NULL_TREE)
-    {
-      inserted_tsi = tsi_start (curr_bb->head_tree_p);
-      tsi_link_before (&inserted_tsi, t, TSI_NEW_STMT);
-      prepend_stmt_to_bb (tsi_container (inserted_tsi), curr_bb);
-
-      /* In this case, we will *always* return the new stmt since BSI_SAME_STMT
-         doesn't really exist.  */
-      *curr_bsi = bsi_from_tsi (inserted_tsi);
-    }
-  else
-    {
-      inserted_tsi = tsi_from_bsi (*curr_bsi);
+  set_bb_for_stmt (t, i->bb);
+  modify_stmt (t);
+  tsi_link_after (&i->tsi, t, m);
+}
 
-      same_tsi = bsi_link_after (&inserted_tsi, t, curr_bb);
-      bsi_update_from_tsi (curr_bsi, same_tsi);
-      if (mode == BSI_NEW_STMT)
-        bsi_next (curr_bsi);
-    }
+/* Move the statement at FROM so it comes right after the statement at TO.  */
 
-  inserted_stmt = tsi_stmt (inserted_tsi);
+void 
+bsi_move_after (block_stmt_iterator *from, block_stmt_iterator *to)
+{
+  tree stmt = bsi_stmt (*from);
+  bsi_remove (from);
+  bsi_insert_after (to, stmt, BSI_SAME_STMT);
+} 
 
-  /* Now update the required SSA bits.  */
-  modify_stmt (inserted_stmt);
+/* Move the statement at FROM so it comes right before the statement at TO.  */
 
-  return;
+void 
+bsi_move_before (block_stmt_iterator *from, block_stmt_iterator *to)
+{
+  tree stmt = bsi_stmt (*from);
+  bsi_remove (from);
+  bsi_insert_before (to, stmt, BSI_SAME_STMT);
 }
 
+/* Move the statement at FROM to the end of basic block BB.  */
 
-/* This routine inserts a stmt before the stmt iterator passed in.
-   The final parameter determines whether the statement iterator
-   is updated to point to the new stmt, or left pointing to the original
-   statement.  (Which will have a different container.)  */
 void
-bsi_insert_before (block_stmt_iterator *curr_bsi, tree t,
-		   enum bsi_iterator_update mode)
+bsi_move_to_bb_end (block_stmt_iterator *from, basic_block bb)
 {
-  tree_stmt_iterator inserted_tsi, same_tsi;
-  basic_block curr_bb;
-  tree *curr_container;
-  tree curr_stmt, inserted_stmt;
-
-  curr_container = bsi_container (*curr_bsi);
-
-  /* If this block is empty, let bsi_insert_after() handle it.  */
-  if (curr_container == NULL || bsi_stmt (*curr_bsi) == NULL_TREE)
-    bsi_insert_after (curr_bsi, t, mode);
-
-  curr_stmt = bsi_stmt (*curr_bsi);
-  curr_bb = bb_for_stmt (curr_stmt);
-  inserted_tsi = tsi_from_bsi (*curr_bsi);
-
-  /* The only case that needs attention is when the insert is before
-     the last stmt in a block. In this case, we have to update the
-     container of the end pointer.  */
-  tsi_link_before (&inserted_tsi, t, TSI_NEW_STMT);
-  set_bb_for_stmt (*tsi_container (inserted_tsi), curr_bb);
-
-  same_tsi = inserted_tsi;
-  tsi_next (&same_tsi);
-
-  /* The end block pointer can be modified when we insert before the last stmt
-     in a block.  This occurs because we insert a new container for the last
-     stmt.  */
-
-  if (curr_container == curr_bb->end_tree_p)
-    curr_bb->end_tree_p = tsi_container (same_tsi);
-
-  if (mode == BSI_SAME_STMT)
-    bsi_update_from_tsi (curr_bsi, same_tsi);
+  block_stmt_iterator last = bsi_last (bb);
+  
+  /* Have to check bsi_end_p because it could be an empty block.  */
+  if (!bsi_end_p (last) && is_ctrl_stmt (bsi_stmt (last)))
+    bsi_move_before (from, &last);
   else
-    bsi_update_from_tsi (curr_bsi, inserted_tsi);
-
-  inserted_stmt = tsi_stmt (inserted_tsi);
-
-  /* Now update the required SSA bits.  */
-  modify_stmt (inserted_stmt);
-
-  return;
+    bsi_move_after (from, &last);
 }
 
-/* This routine inserts a stmt on an edge. Every attempt is made to place the
-   stmt in an existing basic block, but sometimes that isn't possible.  When
-   it isn't possible, a new basic block is created, edges updated, and the
-   stmt is added to the new block.  An iterator to the new stmt is returned.
-   If a pointer to a BSI is passed in, and the stmt is inserted before or after
-   an existing stmt in a block, old_bsi will be returned with an iterator for
-   that stmt (The equivalent of BSI_SAME_STMT on an insert_before or after.
-   If a created_block is passed in, and the edge is split, the new block is
-   returned through this parameter.  */
-
-block_stmt_iterator
-bsi_insert_on_edge_immediate (edge e, tree stmt, block_stmt_iterator *old_bsi,
-			      basic_block *created_block)
-{
-  basic_block src, dest, new_bb;
-  block_stmt_iterator bsi, tmp;
-  tree_stmt_iterator tsi;
-  int num_exit, num_entry;
-  tree last, label, gto, old_gto;
-  bb_ann_t ann;
-  edge e2;
-
-  if (old_bsi)
-    old_bsi->tp = (tree *)NULL;
-  if (created_block)
-    *created_block = (basic_block)NULL;
+/* Replace the contents of a stmt with another.  */
 
-  src = e->src;
-  dest = e->dest;
-
-  /* Cannot insert on an abnormal edge.  */
-  if (e->flags & EDGE_ABNORMAL)
-    abort ();
-
-  /* No immediate edge insertion if there are already pending inserts.  */
-  if (PENDING_STMT (e))
-    abort ();
-
-  num_exit = num_entry = 0;
+void
+bsi_replace (const block_stmt_iterator *bsi, tree stmt)
+{
+  *bsi_stmt_ptr (*bsi) = stmt;
+  modify_stmt (stmt);
+}
 
-  for (e2 = src->succ; e2; e2 = e2->succ_next)
-    num_exit++;
+/* This routine locates a place to insert a statement on an edge.  Every
+   attempt is made to place the stmt in an existing basic block, but
+   sometimes that isn't possible.  When it isn't possible, the edge is
+   split and the stmt is added to the new block.
+
+   In all cases, the returned *BSI points to the correct location.  The
+   return value is true if insertion should be done after the location,
+   or false if before the location.  */
 
-  for (e2 = dest->pred; e2; e2 = e2->pred_next)
-    num_entry++;
+static bool
+tree_find_edge_insert_loc (edge e, block_stmt_iterator *bsi)
+{
+  basic_block dest, src;
+  tree tmp;
 
-  /* If src is a single-exit block, and it isn't the entry block, then
-     insert at the end of the block, if we can.  */
+  dest = e->dest;
+ restart:
 
-  if (num_exit == 1 && src != ENTRY_BLOCK_PTR)
+  /* If the destination has one predecessor, insert there.  Except
+     for the exit block.  */
+  if (dest->pred->pred_next == NULL && dest != EXIT_BLOCK_PTR)
     {
-      bsi = bsi_last (src);
-      /* If it is an empty block, simply insert after this bsi, and the
-	 new stmt will become the only stmt in the block.  */
-      if (bsi_end_p (bsi))
-	{
-	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
-	  return bsi;
-	}
+      *bsi = bsi_start (dest);
+      if (bsi_end_p (*bsi))
+	return true;
 
-      /* If this is a fallthrough edge, then we can simply append this stmt
-	 to the basic block.  */
-      if (e->flags & EDGE_FALLTHRU)
+      /* Make sure we insert after any leading labels.  */
+      tmp = bsi_stmt (*bsi);
+      while (TREE_CODE (tmp) == LABEL_EXPR)
 	{
-#ifdef ENABLE_CHECKING
-	  /* Control statement edges should not be marked FALLTHRU.  */
-	  if (is_ctrl_stmt (bsi_stmt (bsi)))
-	    abort ();
-#endif
-
-	  if (src->head_tree_p == src->end_tree_p 
-	      && IS_EMPTY_STMT (*src->head_tree_p))
-	    {
-	      bsi_replace (bsi, stmt);
-	      if (old_bsi)
-		*old_bsi = bsi;
-	      return bsi;
-	    }
-	  else
-	    {
-	      bsi_insert_after (&bsi, stmt, BSI_SAME_STMT);
-	      if (old_bsi)
-		*old_bsi = bsi;
-	      bsi_next (&bsi);
-	      return bsi;
-	    }
+	  bsi_next (bsi);
+	  if (bsi_end_p (*bsi))
+	    break;
+	  tmp = bsi_stmt (*bsi);
 	}
 
-      /* Otherwise, the last stmt is a control altering stmt, so we need to
-	 insert before it.  */
-      else
+      if (bsi_end_p (*bsi))
 	{
-#ifdef ENABLE_CHECKING
-	  /* A block with a normal non-FALLTHRU edge should end with a
-	     control statement.  */
-	  if (!is_ctrl_stmt (bsi_stmt (bsi)))
-	    abort ();
-#endif
-
-	  bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
-	  if (old_bsi)
-	    {
-	      *old_bsi = bsi;
-	      bsi_next (old_bsi);
-	    }
-	  return bsi;
+	  *bsi = bsi_last (dest);
+	  return true;
 	}
+      else
+	return false;
     }
 
-  /* If dest is a single entry destination, and it isn't the exit block, the
-     new stmt can be inserted at the beginning of the destination block.  */
-
-  if (num_entry == 1 && dest != EXIT_BLOCK_PTR)
+  /* If the source has one successor and the edge is not abnormal,
+     insert there.  Except for the entry block.  */
+  src = e->src;
+  if ((e->flags & EDGE_ABNORMAL) == 0
+      && src->succ->succ_next == NULL
+      && src != ENTRY_BLOCK_PTR)
     {
-      bsi = bsi_start (dest);
-      /* If it is an empty block, simply insert after this bsi, and the new stmt
-	 will become the only stmt in the block.  */
-      if (bsi_end_p (bsi))
-	{
-	  bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
-	  return bsi;
-	}
-
-      /* Skip any labels, and insert before the first non-label.  */
-      for (tmp = bsi, bsi_next (&bsi); !bsi_end_p (bsi); bsi_next (&bsi))
-	{
-	  if (!is_label_stmt (bsi_stmt (bsi)))
-	    {
-	      bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
-	      if (old_bsi)
-		{
-		  *old_bsi = bsi;
-		  bsi_next (old_bsi);
-		}
-	      return bsi;
-	    }
-	  tmp = bsi;
-	}
+      *bsi = bsi_last (src);
+      if (bsi_end_p (*bsi))
+	return true;
 
-      /* If this point is reached, then the block consists of nothing but
-	 labels, and tmp points to the last one. Insert after it.  */
-      bsi_insert_after (&tmp, stmt, BSI_SAME_STMT);
-      if (old_bsi)
-	*old_bsi = tmp;
-      bsi_next (&tmp);
-      return tmp;
+      /* Make sure we insert before a final goto statement.  */
+      tmp = bsi_stmt (*bsi);
+      return !is_ctrl_stmt (tmp);
     }
 
   /* Otherwise, create a new basic block, and split this edge.  */
-  new_bb = split_edge (e);
-  ann = bb_ann (new_bb);
-
-  if (created_block)
-    *created_block = new_bb;
-
-  bsi = bsi_last (src);
-  if (!bsi_end_p (bsi))
-    {
-      bool fixup;
-
-      last = bsi_stmt (bsi);
-      label = old_gto = NULL;
-      tsi = tsi_start (src->end_tree_p);
-
-      switch (TREE_CODE (last))
-	{
-	case COND_EXPR:
-	  e = find_edge (src, new_bb);
-	  if (!e)
-	    abort ();
-
-	  label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-	  gto = build_and_jump (&LABEL_EXPR_LABEL (label));
-	  if (e->flags & EDGE_TRUE_VALUE)
-	    {
-	      old_gto = COND_EXPR_THEN (last);
-	      COND_EXPR_THEN (last) = gto;
-	    }
-	  else
-	    {
-	      old_gto = COND_EXPR_ELSE (last);
-	      COND_EXPR_ELSE (last) = gto;
-	    }
-	  break;
-
-	case SWITCH_EXPR:
-	  {
-	    tree vec = SWITCH_LABELS (last);
-	    size_t i, n = TREE_VEC_LENGTH (vec);
-	    tree dest_label = NULL;
-
-	    label = create_artificial_label ();
-	    for (i = 0; i < n; ++i)
-	      {
-		tree elt = TREE_VEC_ELT (vec, i);
-		if (label_to_block (CASE_LABEL (elt)) == dest)
-		  {
-		    dest_label = CASE_LABEL (elt);
-		    CASE_LABEL (elt) = label;
-		  }
-	      }
-
-	    label = build1 (LABEL_EXPR, void_type_node, label);
-	    old_gto = build_and_jump (&dest_label);
-	  }
-	  break;
-
-	case CALL_EXPR:
-	case MODIFY_EXPR:
-	  /* The block ends in a CALL which has abnormal edges.  In
-	     that case, we simply create a new block right after this
-	     one, and then fall through to the destination block.  */
-	  e = find_edge (new_bb, dest);
-	  if (!e)
-	    abort ();
-	  e->flags |= EDGE_FALLTHRU;
-	  break;
-
-	default:
-	  /* All cases ought to have been covered by now.  */
-	  abort ();
-	}
-
-      /* When insertting our first statement, we may well create a new
-	 COMPOUND_EXPR container, and so we'll need to update the end
-	 of the old src block.  */
-      fixup = false;
-
-      if (label)
-	{
-	  tsi_link_after (&tsi, label, TSI_SAME_STMT);
-	  src->end_tree_p = tsi_container (tsi);
-	  fixup = true;
-	  tsi_next (&tsi);
-          append_stmt_to_bb (tsi_container (tsi), new_bb);
-	}
-
-      tsi_link_after (&tsi, stmt, fixup ? TSI_NEW_STMT : TSI_SAME_STMT);
-      if (!fixup)
-	{
-	  src->end_tree_p = tsi_container (tsi);
-	  fixup = true;
-	  tsi_next (&tsi);
-	}
-      append_stmt_to_bb (tsi_container (tsi), new_bb);
-
-      if (old_gto)
-	{
-          tsi_link_after (&tsi, old_gto, TSI_NEW_STMT);
-          append_stmt_to_bb (tsi_container (tsi), new_bb);
-	}
-
-      /* For the same reason of new containers, we have to wait until the
-	 end to initialize our return bsi value.  Fortunately we don't 
-	 need to search far to get it pointed to the real statement that
-	 we added.  */
-      bsi = bsi_start (new_bb);
-      if (label)
-	bsi_next (&bsi);
-    }
-
-  /* Now update the required SSA bits.  */
-  modify_stmt (stmt);
-
-  return bsi;
+  dest = tree_split_edge (e);
+  e = dest->pred;
+  goto restart;
 }
 
 /* This routine will commit all pending edge insertions, creating any new
-   basic blocks which are necessary. The number of edges which were inserted
-   is returned.  If the flag update_annotations is true, then new bitmaps are
-   created for the dominator children, and they are updated.  If specified,
-   new_blocks returned a count of the number of new basic blocks which were
-   created.  */
+   basic blocks which are necessary.
 
-int
-bsi_commit_edge_inserts (int update_annotations, int *new_blocks)
+   If UPDATE_ANNOTATIONS is true, then new bitmaps are created for the
+   dominator children, and they are updated.  If specified, NEW_BLOCKS
+   returns a count of the number of new basic blocks which were created.  */
+
+void
+bsi_commit_edge_inserts (bool update_annotations, int *new_blocks)
 {
   basic_block bb;
-  block_stmt_iterator bsi;
   edge e;
-  tree stmt, next_stmt;
-  int blocks, count = 0;
+  int blocks;
 
   blocks = n_basic_blocks;
 
@@ -3313,21 +2326,15 @@ bsi_commit_edge_inserts (int update_anno
       for (e = bb->succ; e; e = e->succ_next)
         if (PENDING_STMT (e))
 	  {
-	    stmt = PENDING_STMT (e);
-	    SET_PENDING_STMT (e, NULL_TREE);
-	    next_stmt = TREE_CHAIN (stmt);
-	    /* The first insert will create a new basic block if needed.  */
-	    bsi = bsi_insert_on_edge_immediate (e, stmt, NULL, NULL);
-	    count++;
-	    stmt = next_stmt;
-	    for ( ; stmt; stmt = next_stmt)
-	      {
-	        /* All further inserts can simply follow the first one.  */
-		next_stmt = TREE_CHAIN (stmt);
-		bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
-		count++;
-	      }
+	    block_stmt_iterator bsi;
+	    tree stmt = PENDING_STMT (e);
+
+	    PENDING_STMT (e) = NULL_TREE;
 
+	    if (tree_find_edge_insert_loc (e, &bsi))
+	      bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+	    else
+	      bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
 	  }
     }
 
@@ -3338,9 +2345,8 @@ bsi_commit_edge_inserts (int update_anno
   if (update_annotations && blocks != n_basic_blocks)
     {
       /* TODO. Unimplemented at the moment.  */
+      abort ();
     }
-
-  return count;
 }
 
 /* This routine adds a stmt to the pending list on an edge. No actual
@@ -3349,98 +2355,24 @@ bsi_commit_edge_inserts (int update_anno
 void
 bsi_insert_on_edge (edge e, tree stmt)
 {
-  tree t;
-
-  t = PENDING_STMT (e);
-  if (!t)
-    SET_PENDING_STMT (e, stmt);
-  else
-    {
-      for ( ; TREE_CHAIN (t); t = TREE_CHAIN (t))
-        continue;
-      TREE_CHAIN (t) = stmt;
-      TREE_CHAIN (stmt) = NULL_TREE;
-    }
-
+  add_to_statement_list (stmt, &PENDING_STMT (e));
 }
 
-/* These 2 routines are used to process BSI's in reverse within a block.
-   When there is a decent implementation of bsi_prev, we can get rid of
-   these forever!  */
+/* Similar to bsi_insert_on_edge+bsi_commit_edge_inserts.  */
+/* ??? Why in the world do we need this?  Only PRE uses it.  */
 
-/* Push another block_stmt_iterator onto the stack.  */
 void
-push_bsi (bsi_list_p *list, block_stmt_iterator bsi)
-{
-  bsi_list_p tmp;
-  if (*list == NULL)
-    {
-      *list = new_bsi_list ();
-      (*list)->bsi[0] = bsi;
-    }
-  else
-    {
-      if ((*list)->curr_index == (BSI_NUM_ELEMENTS - 1))
-        {
-	  tmp = new_bsi_list ();
-	  tmp->bsi[0] = bsi;
-	  tmp->next = *list;
-	  *list = tmp;
-	}
-      else
-        {
-	  (*list)->bsi[++((*list)->curr_index)] = bsi;
-	}
-    }
-}
-
-/* Pop a block_stmt_iterator off the stack.  */
-block_stmt_iterator
-pop_bsi (bsi_list_p *list)
+bsi_insert_on_edge_immediate (edge e, tree stmt)
 {
   block_stmt_iterator bsi;
-  bsi_list_p tmp;
-  if (!list)
-    abort ();
-
-  tmp = *list;
-  bsi = tmp->bsi[(tmp->curr_index)--];
-  if (tmp->curr_index< 0)
-    {
-      tmp = *list;
-      *list = (*list)->next;
-      free (tmp);
-    }
-  return bsi;
-}
-
-
-/* Replace the statement pointed by TP1 with the statement pointed by TP2.
-   Note that this function will not replace COMPOUND_EXPR nodes, only
-   individual statements.
-
-   If TP1 is pointing to a COMPOUND_EXPR node, only its LHS operand will be
-   replaced. TP2 may not point to a COMPOUND_EXPR.  */
-
-void
-replace_stmt (tree *tp1, tree *tp2)
-{
-  tree t;
 
-  if (TREE_CODE (*tp2) == COMPOUND_EXPR)
+  if (PENDING_STMT (e))
     abort ();
-      
-  t = *tp2;
 
-  /* Relocate annotations for the replacement statement.  */
-  SET_EXPR_LOCUS (t, EXPR_LOCUS (*tp1));
-  set_bb_for_stmt (t, bb_for_stmt (*tp1));
-
-  /* Don't replace COMPOUND_EXPRs.  Only their operands.  */
-  if (TREE_CODE (*tp1) == COMPOUND_EXPR)
-    TREE_OPERAND (*tp1, 0) = t;
+  if (tree_find_edge_insert_loc (e, &bsi))
+    bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
   else
-    *tp1 = t;
+    bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
 }
 
 /*---------------------------------------------------------------------------
@@ -3453,7 +2385,7 @@ replace_stmt (tree *tp1, tree *tp2)
 basic_block
 tree_split_edge (edge edge_in)
 {
-  basic_block new_bb, dest;
+  basic_block new_bb, after_bb, dest;
   edge new_edge;
   tree phi;
   int i, num_elem;
@@ -3463,11 +2395,71 @@ tree_split_edge (edge edge_in)
     abort ();
 
   dest = edge_in->dest;
-  new_bb = create_bb (edge_in->src);
+
+  /* Place the new block in the block list.  Try to keep the new block
+     near its "logical" location.  This is of most help to humans looking
+     at debugging dumps.  */
+  if (edge_in->flags & EDGE_FALLTHRU)
+    after_bb = edge_in->src;
+  else
+    {
+      edge e;
+
+      for (e = dest->pred; e ; e = e->pred_next)
+	if (e->flags & EDGE_FALLTHRU)
+	  break;
+      if (!e)
+	after_bb = dest->prev_bb;
+      else
+	{
+	  after_bb = EXIT_BLOCK_PTR->prev_bb;
+	  for (e = after_bb->succ; e ; e = e->succ_next)
+	    if (e->flags & EDGE_FALLTHRU)
+	      break;
+	  if (e)
+	    {
+	      block_stmt_iterator bsi;
+	      tree x;
+
+	      /* We have a fallthru to exit out of the last block.
+		 Transform this to a return statement.  */
+	      /* ??? Can we have multiple outgoing edges here?  COND_EXPR
+		 always has two gotos, and I can't think how one would have
+		 achived this via EH.  */
+	      if (e != after_bb->succ || e->succ_next)
+		abort ();
+	
+	      x = build (RETURN_EXPR, void_type_node, NULL_TREE);
+	      bsi = bsi_last (after_bb);
+	      bsi_insert_after (&bsi, x, BSI_NEW_STMT);
+
+	      e->flags &= ~EDGE_FALLTHRU;
+	    }
+	}
+    }
+
+  new_bb = create_bb (NULL, after_bb);
   create_block_annotation (new_bb);
-  redirect_edge_succ  (edge_in, new_bb);
   new_edge = make_edge (new_bb, dest, 0);
 
+  if (edge_in->flags & EDGE_FALLTHRU)
+    {
+      new_edge->flags = EDGE_FALLTHRU;
+      redirect_edge_succ (edge_in, new_bb);
+    }
+  else
+    {
+      block_stmt_iterator i;
+      tree x;
+
+      if (!tree_redirect_edge_and_branch_1 (edge_in, new_bb, true))
+	abort ();
+
+      x = build (GOTO_EXPR, void_type_node, tree_block_label (dest));
+      i = bsi_last (new_bb);
+      bsi_insert_after (&i, x, BSI_NEW_STMT);
+    }
+
   /* Find all the PHI arguments on the original edge, and change them to
      the new edge.  */
   for (phi = phi_nodes (dest); phi; phi = TREE_CHAIN (phi))
@@ -3491,10 +2483,9 @@ static int
 tree_verify_flow_info (void)
 {
   int err = 0;
-  basic_block bb, abb;
+  basic_block bb;
   block_stmt_iterator bsi;
   tree stmt;
-  tree_stmt_iterator tsi;
 
   FOR_EACH_BB (bb)
     {
@@ -3518,34 +2509,6 @@ tree_verify_flow_info (void)
 	}
     }
 
-  /* Check that order of basic blocks is the same as the order of code.  */
-  bb = ENTRY_BLOCK_PTR->next_bb;
-  if (bb == EXIT_BLOCK_PTR
-      || !bb->head_tree_p)
-    return err;
-
-  for (tsi = tsi_start (bb->head_tree_p); !tsi_end_p (tsi); tsi_next (&tsi))
-    {
-      if (IS_EMPTY_STMT (tsi_stmt (tsi)))
-	continue;
- 
-      abb = bb_for_stmt (tsi_stmt (tsi));
-      if (!abb)
-	continue;
-
-      if (abb != bb)
-	{
-	  if (abb != bb->next_bb)
-	    {
-	      fprintf (stderr, "Block missordering after bb %d\n",
-		       bb->index);
-	      err = 1;
-	    }
-
-	  bb = abb;
-	}
-    }
-
   return err;
 }
 
@@ -3564,13 +2527,11 @@ tree_make_forwarder_block (basic_block b
   basic_block dummy;
 
   /* Create the new basic block.  */
-  dummy = create_bb (NULL);
+  dummy = create_bb (NULL, bb->prev_bb);
   create_block_annotation (dummy);
   dummy->count = bb->count;
   dummy->frequency = bb->frequency;
   dummy->loop_depth = bb->loop_depth;
-  dummy->head_tree_p = NULL;
-  dummy->end_tree_p = NULL;
 
   /* Redirect the incoming edges.  */
   dummy->pred = bb->pred;
@@ -3578,7 +2539,7 @@ tree_make_forwarder_block (basic_block b
   for (e = dummy->pred; e; e = e->pred_next)
     e->dest = dummy;
 
-  fallthru = make_edge (dummy, bb, 0);
+  fallthru = make_edge (dummy, bb, EDGE_FALLTHRU);
 
   HEADER_BLOCK (dummy) = 0;
   HEADER_BLOCK (bb) = 1;
@@ -3740,16 +2701,6 @@ tree_forwarder_block_p (basic_block bb)
 	}
     }
 
-  /* Now check the target for a couple special cases.  */
-  bsi = bsi_start (bb->succ->dest);
-
-  /* It's not clear if we can safely insert the label in this case.  */
-  if (bsi_end_p (bsi))
-    {
-      bb_ann (bb)->forwardable = 0;
-      return false; 
-    }
-
   return true;
 }
 
@@ -3860,7 +2811,7 @@ thread_jumps (void)
 
 	  /* Perform the redirection.  */
 	  retval = true;
-	  e = redirect_edge_and_branch (e, dest);
+	  e = tree_redirect_edge_and_branch (e, dest);
 	  if (!old)
 	    {
 	      /* Update phi nodes.   We know that the new argument should
@@ -3897,7 +2848,7 @@ tree_block_label (basic_block bb)
       block_stmt_iterator iterator = bsi_start (bb);
       tree label = create_artificial_label ();
       stmt = build1 (LABEL_EXPR, void_type_node, label);
-      bsi_insert_before (&iterator, stmt, BSI_SAME_STMT);
+      bsi_insert_before (&iterator, stmt, BSI_NEW_STMT);
       return label;
     }
   else
@@ -3931,7 +2882,8 @@ tree_try_redirect_by_replacing_jump (edg
     return NULL;
   stmt = bsi_stmt (b);
 
-  if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR
+  if (TREE_CODE (stmt) == COND_EXPR
+      || TREE_CODE (stmt) == SWITCH_EXPR
       || (TREE_CODE (stmt) == GOTO_EXPR && target == src->next_bb))
     {
       if (target == src->next_bb)
@@ -3943,12 +2895,13 @@ tree_try_redirect_by_replacing_jump (edg
 	{
 	  flags = 0;
           stmt = build1 (GOTO_EXPR, void_type_node, tree_block_label (target));
-          bsi_replace (b, stmt);
+          bsi_replace (&b, stmt);
 	}
       e = ssa_redirect_edge (e, target);
       e->flags = flags;
       return e;
     }
+
   return NULL;
 }
 
@@ -3956,11 +2909,12 @@ tree_try_redirect_by_replacing_jump (edg
    branch otherwise  */
 
 static edge
-tree_redirect_edge_and_branch (edge e, basic_block dest)
+tree_redirect_edge_and_branch_1 (edge e, basic_block dest, bool splitting)
 {
+  basic_block bb = e->src;
+  block_stmt_iterator bsi;
   edge ret;
   tree label, stmt;
-  basic_block bb = e->src, new_bb;
   int flags;
 
   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
@@ -3978,8 +2932,8 @@ tree_redirect_edge_and_branch (edge e, b
   /* If our block does not end with a GOTO, then create one.
      Otherwise redirect the existing GOTO_EXPR to LABEL.  */
 
-  stmt = last_stmt (bb);
-  new_bb = NULL;
+  bsi = bsi_last (bb);
+  stmt = bsi_end_p (bsi) ? NULL : bsi_stmt (bsi);
   flags = 0;
 
   switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
@@ -4009,24 +2963,50 @@ tree_redirect_edge_and_branch (edge e, b
       }
       break;
 
-    default:
-      stmt = build1 (GOTO_EXPR, void_type_node, label);
-      bsi_insert_on_edge_immediate (e, stmt, NULL, &new_bb);
+    case CALL_EXPR:
+    case MODIFY_EXPR:
+      /* If this block ends with a statement that can alter control flow,
+	 e.g. via throw or longjmp, then we can't just append to the 
+	 current block.  We have to create a new block just to contain
+	 the goto statement.  */
       /* ??? In RTL equivalent we never create new basic blocks here.
 	 Hopefully this will be just a temporary side case before we switch
 	 to cfg_layout style mode with no explicit GOTO statements.  */
-      if (new_bb)
-	e = new_bb->succ;
+      if (is_ctrl_altering_stmt (stmt))
+	{
+	  bb = tree_split_edge (e);
+	  bsi = bsi_last (bb);
+	  e = bb->succ;
+	}
+      /* FALLTHRU */
+
+    default:
+      /* Otherwise we can just append a goto to this block.  */
+      stmt = build1 (GOTO_EXPR, void_type_node, label);
+      bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
       e->flags &= ~EDGE_FALLTHRU;
       break;
     }
 
   /* Update/insert PHI nodes as necessary.  */
 
-  /* Now update the edges in the CFG.  */
-  e = ssa_redirect_edge (e, dest);
-  e->flags |= flags;
+  /* Now update the edges in the CFG.  When splitting edges, we do not 
+     want to remove PHI arguments.  */
+  if (splitting)
+    redirect_edge_succ (e, dest);
+  else
+    {
+      e = ssa_redirect_edge (e, dest);
+      e->flags |= flags;
+    }
+
   return e;
+}
+
+static edge
+tree_redirect_edge_and_branch (edge e, basic_block dest)
+{
+  return tree_redirect_edge_and_branch_1 (e, dest, false);
 }
 
 /* Simple wrapper as we always can redirect fallthru edges.  */
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-eh.c,v
retrieving revision 1.1.2.11
diff -u -p -r1.1.2.11 tree-eh.c
--- tree-eh.c	2 Nov 2003 09:59:54 -0000	1.1.2.11
+++ tree-eh.c	9 Nov 2003 09:10:56 -0000
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "tree-inline.h"
+#include "tree-iterator.h"
 #include "timevar.h"
 #include "langhooks.h"
 
@@ -167,7 +168,6 @@ tailrecurse:
     case BIND_EXPR:
       collect_finally_tree (BIND_EXPR_BODY (t), region);
       break;
-    case COMPOUND_EXPR:
     case TRY_CATCH_EXPR:
       collect_finally_tree (TREE_OPERAND (t, 0), region);
       t = TREE_OPERAND (t, 1);
@@ -179,6 +179,14 @@ tailrecurse:
       collect_finally_tree (EH_FILTER_FAILURE (t), region);
       break;
 
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator i;
+	for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+	  collect_finally_tree (tsi_stmt (i), region);
+      }
+      break;
+
     default:
       /* A type, a decl, or some kind of statement that we're not
 	 interested in.  Don't walk them.  */
@@ -308,60 +316,55 @@ find_goto_replacement (struct leh_tf_sta
    nature of these COMPOUND_EXPRs is such that we can't store
    a pointer to a statement and hope to be able to replace it
    later, when the tree has been restructured.  */
+/* ??? We now have a reasonable connection mechansim.  Update.  */
 
 static tree
-replace_goto_queue_1 (tree *tp, int *walk_subtrees, void *data)
+replace_goto_queue_1 (tree t, struct leh_tf_state *tf)
 {
-  struct leh_tf_state *tf = data;
-  tree t = *tp, sub;
-
   switch (TREE_CODE (t))
     {
     case GOTO_EXPR:
     case RETURN_EXPR:
-      t = find_goto_replacement (tf, t);
-      if (t)
-	*tp = t;
-      *walk_subtrees = 0;
-      break;
+      return find_goto_replacement (tf, t);
 
-    case COMPOUND_EXPR:
-      sub = TREE_OPERAND (t, 0);
-      if (TREE_CODE (sub) == GOTO_EXPR || TREE_CODE (sub) == RETURN_EXPR)
-	{
-	  sub = find_goto_replacement (tf, sub);
-	  if (sub)
-	    {
-	      if (TREE_CODE (sub) == COMPOUND_EXPR)
-		{
-		  tree_stmt_iterator i = tsi_start (tp);
-		  tsi_link_chain_before (&i, sub, TSI_SAME_STMT);
-		  tsi_delink (&i);
-	          walk_tree (tsi_container (i), replace_goto_queue_1, tf, NULL);
-		}
-	      else
-		{
-		  TREE_OPERAND (t, 0) = sub;
-	          walk_tree (&TREE_OPERAND (t, 1), replace_goto_queue_1,
-			     tf, NULL);
-		}
-	      *walk_subtrees = 0;
-	    }
-	}
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator i = tsi_start (t);
+	while (!tsi_end_p (i))
+	  {
+	    t = replace_goto_queue_1 (tsi_stmt (i), tf);
+	    if (t)
+	      {
+		tsi_link_before (&i, t, TSI_SAME_STMT);
+		tsi_delink (&i);
+	      }
+	    else
+	      tsi_next (&i);
+	  }
+      }
       break;
 
     case COND_EXPR:
+      replace_goto_queue_1 (COND_EXPR_THEN (t), tf);
+      replace_goto_queue_1 (COND_EXPR_ELSE (t), tf);
+      break;
     case BIND_EXPR:
+      replace_goto_queue_1 (BIND_EXPR_BODY (t), tf);
+      break;
     case TRY_FINALLY_EXPR:
     case TRY_CATCH_EXPR:
+      replace_goto_queue_1 (TREE_OPERAND (t, 0), tf);
+      replace_goto_queue_1 (TREE_OPERAND (t, 1), tf);
+      break;
     case CATCH_EXPR:
+      replace_goto_queue_1 (CATCH_BODY (t), tf);
+      break;
     case EH_FILTER_EXPR:
-      /* Only need to look down statement containers.  */
+      replace_goto_queue_1 (EH_FILTER_FAILURE (t), tf);
       break;
 
     default:
       /* These won't have gotos in them.  */
-      *walk_subtrees = 0;
       break;
     }
 
@@ -371,9 +374,7 @@ replace_goto_queue_1 (tree *tp, int *wal
 static void
 replace_goto_queue (struct leh_tf_state *tf)
 {
-  /* Note that since we only look through statement containers,
-     we cannot possibly see duplicates.  Barring bugs of course.  */
-  walk_tree (tf->top_p, replace_goto_queue_1, tf, NULL);
+  replace_goto_queue_1 (*tf->top_p, tf);
 }
 
 /* For any GOTO_EXPR or RETURN_EXPR, decide whether it leaves a try_finally
@@ -491,10 +492,8 @@ do_return_redirection (struct goto_queue
 		       tree *return_value_p)
 {
   tree ret_expr = TREE_OPERAND (q->stmt, 0);
-  tree_stmt_iterator i;
   tree x;
 
-  i = tsi_start (&q->repl_stmt);
   if (ret_expr)
     {
       /* The nasty part about redirecting the return value is that the
@@ -542,7 +541,7 @@ do_return_redirection (struct goto_queue
 	    new = *return_value_p;
 
 	  x = build (MODIFY_EXPR, TREE_TYPE (new), new, old);
-	  tsi_link_after (&i, x, TSI_NEW_STMT);
+	  add_to_statement_list (x, &q->repl_stmt);
 
 	  x = build (MODIFY_EXPR, TREE_TYPE (new),
 		     TREE_OPERAND (ret_expr, 0), new);
@@ -558,10 +557,10 @@ do_return_redirection (struct goto_queue
     }
 
   if (mod)
-    tsi_link_after (&i, mod, TSI_NEW_STMT);
+    add_to_statement_list (mod, &q->repl_stmt);
 
   x = build1 (GOTO_EXPR, void_type_node, finlab);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
+  add_to_statement_list (x, &q->repl_stmt);
 }
 
 /* Similar, but easier, for GOTO_EXPR.  */
@@ -569,15 +568,14 @@ do_return_redirection (struct goto_queue
 static void
 do_goto_redirection (struct goto_queue_node *q, tree finlab, tree mod)
 {
-  tree_stmt_iterator i = tsi_start (&q->repl_stmt);
   tree x;
 
   q->cont_stmt = q->stmt;
   if (mod)
-    tsi_link_after (&i, mod, TSI_NEW_STMT);
+    add_to_statement_list (mod, &q->repl_stmt);
 
   x = build1 (GOTO_EXPR, void_type_node, finlab);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
+  add_to_statement_list (x, &q->repl_stmt);
 }
 
 /* Try to determine if we can fall out of the bottom of BLOCK.  This guess
@@ -586,8 +584,10 @@ do_goto_redirection (struct goto_queue_n
    If we're wrong, we'll just delete the extra code later.  */
 
 static bool
-block_may_fallthru_last (tree stmt)
+block_may_fallthru (tree block)
 {
+  tree stmt = expr_last (block);
+
   switch (TREE_CODE (stmt))
     {
     case GOTO_EXPR:
@@ -609,19 +609,11 @@ block_may_fallthru_last (tree stmt)
       return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
 
     default:
-      /* ??? Could search back through other composite structures.
-	 Wouldn't need to check COMPOUND_EXPR because of how
-	 tsi_last is implemented.  */
+      /* ??? Could search back through other composite structures.  */
       return true;
     }
 }
 
-static bool
-block_may_fallthru (tree *block_p)
-{
-  return block_may_fallthru_last (tsi_stmt (tsi_last (block_p)));
-}
-
 /* We want to transform
 	try { body; } catch { stuff; }
    to
@@ -634,33 +626,31 @@ block_may_fallthru (tree *block_p)
 static void
 frob_into_branch_around (tree *tp, tree lab, tree over)
 {
-  tree_stmt_iterator i;
   tree x, op1;
 
   op1 = TREE_OPERAND (*tp, 1);
   *tp = TREE_OPERAND (*tp, 0);
-  i = tsi_last (tp);
 
-  if (block_may_fallthru_last (tsi_stmt (i)))
+  if (block_may_fallthru (*tp))
     {
       if (!over)
 	over = create_artificial_label ();
       x = build1 (GOTO_EXPR, void_type_node, over);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tp);
     }
 
   if (lab)
     {
       x = build1 (LABEL_EXPR, void_type_node, lab);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tp);
     }
 
-  tsi_link_chain_after (&i, op1, TSI_CHAIN_END);
+  add_to_statement_list (op1, tp);
 
   if (over)
     {
       x = build1 (LABEL_EXPR, void_type_node, over);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tp);
     }
 }
 
@@ -739,7 +729,7 @@ honor_protect_cleanup_actions (struct le
     be used (via fallthru from the finally) we handle the eh case here,
     whether or not protect_cleanup_actions is active.  */
 
-  finally_may_fallthru = block_may_fallthru (&finally);
+  finally_may_fallthru = block_may_fallthru (finally);
   if (!finally_may_fallthru && !protect_cleanup_actions)
     return;
 
@@ -758,34 +748,34 @@ honor_protect_cleanup_actions (struct le
       save_eptr = create_tmp_var (ptr_type_node, "save_eptr");
       save_filt = create_tmp_var (integer_type_node, "save_filt");
 
-      i = tsi_start (&finally);
+      i = tsi_start (finally);
       x = build (EXC_PTR_EXPR, ptr_type_node);
       x = build (MODIFY_EXPR, void_type_node, save_eptr, x);
-      tsi_link_before (&i, x, TSI_NEW_STMT);
+      tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
 
       x = build (FILTER_EXPR, integer_type_node);
       x = build (MODIFY_EXPR, void_type_node, save_filt, x);
-      tsi_link_before (&i, x, TSI_NEW_STMT);
+      tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
 
-      i = tsi_last (&finally);
+      i = tsi_last (finally);
       x = build (EXC_PTR_EXPR, ptr_type_node);
       x = build (MODIFY_EXPR, void_type_node, x, save_eptr);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
       x = build (FILTER_EXPR, integer_type_node);
       x = build (MODIFY_EXPR, void_type_node, x, save_filt);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
       x = build1 (RESX_EXPR, void_type_node,
 		  build_int_2 (get_eh_region_number (tf->region), 0));
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
     }
 
   /* Wrap the block with protect_cleanup_actions as the action.  */
   if (protect_cleanup_actions)
     {
-      x = build (EH_FILTER_EXPR, void_type_node, NULL,
-		 protect_cleanup_actions);
+      x = build (EH_FILTER_EXPR, void_type_node, NULL, NULL);
+      add_to_statement_list (protect_cleanup_actions, &EH_FILTER_FAILURE (x));
       EH_FILTER_MUST_NOT_THROW (x) = 1;
       finally = build (TRY_CATCH_EXPR, void_type_node, finally, x);
       lower_eh_filter (outer_state, &finally);
@@ -797,14 +787,14 @@ honor_protect_cleanup_actions (struct le
      previously fell through the end, we'll have to branch around.
      This means adding a new goto, and adding it to the queue.  */
 
-  i = tsi_last (&TREE_OPERAND (*tf->top_p, 0));
+  i = tsi_last (TREE_OPERAND (*tf->top_p, 0));
 
   if (tf->may_fallthru)
     {
       if (!tf->fallthru_label)
 	tf->fallthru_label = create_artificial_label ();
       x = build1 (GOTO_EXPR, void_type_node, tf->fallthru_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
 
       if (this_state)
         maybe_record_in_goto_queue (this_state, x);
@@ -813,9 +803,8 @@ honor_protect_cleanup_actions (struct le
     }
 
   x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
-
-  tsi_link_chain_after (&i, finally, TSI_CHAIN_START);
+  tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
+  tsi_link_after (&i, finally, TSI_CONTINUE_LINKING);
 
   /* Having now been handled, EH isn't to be considered with
      the rest of the outgoing edges.  */
@@ -832,7 +821,6 @@ lower_try_finally_nofallthru (struct leh
 {
   tree x, finally, lab, return_val;
   struct goto_queue_node *q, *qe;
-  tree_stmt_iterator i;
 
   if (tf->may_throw)
     lab = tf->eh_label;
@@ -842,9 +830,8 @@ lower_try_finally_nofallthru (struct leh
   finally = TREE_OPERAND (*tf->top_p, 1);
   *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
 
-  i = tsi_last (tf->top_p);
   x = build1 (LABEL_EXPR, void_type_node, lab);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
+  add_to_statement_list (x, tf->top_p);
 
   return_val = NULL;
   q = tf->goto_queue;
@@ -858,7 +845,7 @@ lower_try_finally_nofallthru (struct leh
   replace_goto_queue (tf);
 
   lower_eh_constructs_1 (state, &finally);
-  tsi_link_chain_after (&i, finally, TSI_SAME_STMT);
+  add_to_statement_list (finally, tf->top_p);
 }
 
 /* A subroutine of lower_try_finally.  We have determined that there is
@@ -869,12 +856,10 @@ static void
 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
 {
   struct goto_queue_node *q, *qe;
-  tree_stmt_iterator i;
   tree x, finally, finally_label;
 
   finally = TREE_OPERAND (*tf->top_p, 1);
   *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
-  i = tsi_last (tf->top_p);
 
   lower_eh_constructs_1 (state, &finally);
 
@@ -884,13 +869,13 @@ lower_try_finally_onedest (struct leh_st
          the head of the FINALLY block.  Append a RESX at the end.  */
 
       x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tf->top_p);
 
-      tsi_link_chain_after (&i, finally, TSI_CHAIN_END);
+      add_to_statement_list (finally, tf->top_p);
       
       x = build1 (RESX_EXPR, void_type_node,
 		  build_int_2 (get_eh_region_number (tf->region), 0));
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tf->top_p);
 
       return;
     }
@@ -899,15 +884,15 @@ lower_try_finally_onedest (struct leh_st
     {
       /* Only reachable via the fallthru edge.  Do nothing but let
 	 the two blocks run together; we'll fall out the bottom.  */
-      tsi_link_chain_after (&i, finally, TSI_SAME_STMT);
+      add_to_statement_list (finally, tf->top_p);
       return;
     }
 
   finally_label = create_artificial_label ();
   x = build1 (LABEL_EXPR, void_type_node, finally_label);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
+  add_to_statement_list (x, tf->top_p);
 
-  tsi_link_chain_after (&i, finally, TSI_CHAIN_END);
+  add_to_statement_list (finally, tf->top_p);
 
   q = tf->goto_queue;
   qe = q + tf->goto_queue_active;
@@ -937,7 +922,7 @@ lower_try_finally_onedest (struct leh_st
 	}
     }
 
-  tsi_link_after (&i, tf->goto_queue[0].cont_stmt, TSI_NEW_STMT);
+  add_to_statement_list (tf->goto_queue[0].cont_stmt, tf->top_p);
   maybe_record_in_goto_queue (state, tf->goto_queue[0].cont_stmt);
 }
 
@@ -949,39 +934,37 @@ static void
 lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
 {
   tree finally, new_stmt;
-  tree_stmt_iterator i;
   tree x;
 
   finally = TREE_OPERAND (*tf->top_p, 1);
   *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
 
-  new_stmt = NULL;
-  i = tsi_start (&new_stmt);
+  new_stmt = NULL_TREE;
 
   if (tf->may_fallthru)
     {
       x = lower_try_finally_dup_block (finally, state);
       lower_eh_constructs_1 (state, &x);
-      tsi_link_chain_after (&i, x, TSI_CHAIN_END);
+      add_to_statement_list (x, &new_stmt);
 
       if (!tf->fallthru_label)
 	tf->fallthru_label = create_artificial_label ();
       x = build1 (GOTO_EXPR, void_type_node, tf->fallthru_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &new_stmt);
     }
 
   if (tf->may_throw)
     {
       x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &new_stmt);
 
       x = lower_try_finally_dup_block (finally, state);
       lower_eh_constructs_1 (state, &x);
-      tsi_link_chain_after (&i, x, TSI_CHAIN_END);
+      add_to_statement_list (x, &new_stmt);
 
       x = build1 (RESX_EXPR, void_type_node,
 		  build_int_2 (get_eh_region_number (tf->region), 0));
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &new_stmt);
     }
 
   if (tf->goto_queue)
@@ -1019,13 +1002,13 @@ lower_try_finally_copy (struct leh_state
 	  if (build_p)
 	    {
 	      x = build1 (LABEL_EXPR, void_type_node, lab);
-	      tsi_link_after (&i, x, TSI_NEW_STMT);
+	      add_to_statement_list (x, &new_stmt);
 
 	      x = lower_try_finally_dup_block (finally, state);
 	      lower_eh_constructs_1 (state, &x);
-	      tsi_link_chain_after (&i, x, TSI_CHAIN_END);
+	      add_to_statement_list (x, &new_stmt);
 
-	      tsi_link_after (&i, q->cont_stmt, TSI_NEW_STMT);
+	      add_to_statement_list (q->cont_stmt, &new_stmt);
 	      maybe_record_in_goto_queue (state, q->cont_stmt);
 	    }
 	}
@@ -1035,8 +1018,7 @@ lower_try_finally_copy (struct leh_state
 
   /* Need to link new stmts after running replace_goto_queue due
      to not wanting to process the same goto stmts twice.  */
-  i = tsi_last (tf->top_p);
-  tsi_link_chain_after (&i, new_stmt, TSI_SAME_STMT);
+  add_to_statement_list (new_stmt, tf->top_p);
 }
 
 /* A subroutine of lower_try_finally.  There are multiple edges incoming
@@ -1050,7 +1032,6 @@ lower_try_finally_switch (struct leh_sta
   struct goto_queue_node *q, *qe;
   tree return_val = NULL;
   tree finally, finally_tmp, finally_label;
-  tree_stmt_iterator i, i2;
   int return_index, eh_index, fallthru_index;
   int nlabels, ndests, j, last_case_index;
   tree case_label_vec, switch_stmt, last_case, switch_body;
@@ -1059,7 +1040,6 @@ lower_try_finally_switch (struct leh_sta
   /* Mash the TRY block to the head of the chain.  */
   finally = TREE_OPERAND (*tf->top_p, 1);
   *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
-  i = tsi_last (tf->top_p);
 
   /* Lower the finally block itself.  */
   lower_eh_constructs_1 (state, &finally);
@@ -1081,7 +1061,6 @@ lower_try_finally_switch (struct leh_sta
   switch_stmt = build (SWITCH_EXPR, integer_type_node, finally_tmp,
 		       NULL_TREE, case_label_vec);
   switch_body = NULL;
-  i2 = tsi_start (&switch_body);
   last_case = NULL;
   last_case_index = 0;
 
@@ -1093,12 +1072,12 @@ lower_try_finally_switch (struct leh_sta
     {
       x = build (MODIFY_EXPR, void_type_node, finally_tmp,
 		 build_int_2 (fallthru_index, 0));
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tf->top_p);
 
       if (tf->may_throw)
 	{
 	  x = build1 (GOTO_EXPR, void_type_node, finally_label);
-	  tsi_link_after (&i, x, TSI_NEW_STMT);
+	  add_to_statement_list (x, tf->top_p);
 	}
 
       if (!tf->fallthru_label)
@@ -1111,19 +1090,19 @@ lower_try_finally_switch (struct leh_sta
       last_case_index++;
 
       x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
-      tsi_link_after (&i2, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &switch_body);
       x = build1 (GOTO_EXPR, void_type_node, tf->fallthru_label);
-      tsi_link_after (&i2, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &switch_body);
     }
 
   if (tf->may_throw)
     {
       x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tf->top_p);
 
       x = build (MODIFY_EXPR, void_type_node, finally_tmp,
 		 build_int_2 (eh_index, 0));
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tf->top_p);
 
       last_case = build (CASE_LABEL_EXPR, void_type_node,
 			 build_int_2 (eh_index, 0), NULL,
@@ -1132,16 +1111,16 @@ lower_try_finally_switch (struct leh_sta
       last_case_index++;
 
       x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
-      tsi_link_after (&i2, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &switch_body);
       x = build1 (RESX_EXPR, void_type_node,
 		  build_int_2 (get_eh_region_number (tf->region), 0));
-      tsi_link_after (&i2, x, TSI_NEW_STMT);
+      add_to_statement_list (x, &switch_body);
     }
 
   x = build1 (LABEL_EXPR, void_type_node, finally_label);
-  tsi_link_after (&i, x, TSI_NEW_STMT);
+  add_to_statement_list (x, tf->top_p);
 
-  tsi_link_chain_after (&i, finally, TSI_CHAIN_END);
+  add_to_statement_list (finally, tf->top_p);
 
   /* Redirect each incomming goto edge.  */
   q = tf->goto_queue;
@@ -1177,22 +1156,21 @@ lower_try_finally_switch (struct leh_sta
 	  TREE_VEC_ELT (case_label_vec, case_index) = last_case;
 
 	  x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
-	  tsi_link_after (&i2, x, TSI_NEW_STMT);
-	  tsi_link_after (&i2, q->cont_stmt, TSI_NEW_STMT);
+	  add_to_statement_list (x, &switch_body);
+	  add_to_statement_list (q->cont_stmt, &switch_body);
 	  maybe_record_in_goto_queue (state, q->cont_stmt);
 	}
     }
   replace_goto_queue (tf);
   last_case_index += nlabels;
 
+  /* Make sure that we have a default label, as one is required.  */
+  CASE_LOW (last_case) = NULL;
+
   /* Need to link switch_stmt after running replace_goto_queue due
      to not wanting to process the same goto stmts twice.  */
-  tsi_link_after (&i, switch_stmt, TSI_NEW_STMT);
-  tsi_link_chain_after (&i, switch_body, TSI_CHAIN_END);
-
-  /* Make sure that we have a default label, so that we don't 
-     confuse flow analysis.  */
-  CASE_LOW (last_case) = NULL;
+  add_to_statement_list (switch_stmt, tf->top_p);
+  add_to_statement_list (switch_body, tf->top_p);
 }
 
 /* Decide whether or not we are going to duplicate the finally block.
@@ -1253,7 +1231,8 @@ lower_try_finally (struct leh_state *sta
   this_tf.try_finally_expr = *tp;
   this_tf.top_p = tp;
   if (using_eh_for_cleanups_p)
-    this_tf.region = gen_eh_region_cleanup (state->cur_region, state->prev_try);
+    this_tf.region
+      = gen_eh_region_cleanup (state->cur_region, state->prev_try);
   else
     this_tf.region = NULL;
 
@@ -1264,7 +1243,7 @@ lower_try_finally (struct leh_state *sta
   lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
 
   /* Determine if the try block is escaped through the bottom.  */
-  this_tf.may_fallthru = block_may_fallthru (&TREE_OPERAND (*tp, 0));
+  this_tf.may_fallthru = block_may_fallthru (TREE_OPERAND (*tp, 0));
 
   /* Determine if any exceptions are possible within the try block.  */
   if (using_eh_for_cleanups_p)
@@ -1300,7 +1279,7 @@ lower_try_finally (struct leh_state *sta
   /* If the finally block doesn't fall through, then any destination
      we might try to impose there isn't reached either.  There may be
      some minor amount of cleanup and redirection still needed.  */
-  else if (!block_may_fallthru (&TREE_OPERAND (*tp, 1)))
+  else if (!block_may_fallthru (TREE_OPERAND (*tp, 1)))
     lower_try_finally_nofallthru (state, &this_tf);
 
   /* We can easily special-case redirection to a single destination.  */
@@ -1316,9 +1295,8 @@ lower_try_finally (struct leh_state *sta
      block, do so.  */
   if (this_tf.fallthru_label)
     {
-      tree_stmt_iterator i = tsi_last (tp);
       tree x = build1 (LABEL_EXPR, void_type_node, this_tf.fallthru_label);
-      tsi_link_after (&i, x, TSI_NEW_STMT);
+      add_to_statement_list (x, tp);
     }
 
   if (this_tf.goto_queue)
@@ -1351,10 +1329,9 @@ lower_catch (struct leh_state *state, tr
     }
 
   out_label = NULL;
-  for (i = tsi_start (&TREE_OPERAND (*tp, 1)); !tsi_end_p (i); )
+  for (i = tsi_start (TREE_OPERAND (*tp, 1)); !tsi_end_p (i); )
     {
       struct eh_region *catch_region;
-      tree_stmt_iterator j;
       tree catch, x, eh_label;
 
       catch = tsi_stmt (i);
@@ -1365,21 +1342,19 @@ lower_catch (struct leh_state *state, tr
       eh_label = create_artificial_label ();
       set_eh_region_tree_label (catch_region, eh_label);
 
-      j = tsi_start (&CATCH_BODY (catch));
       x = build1 (LABEL_EXPR, void_type_node, eh_label);
-      tsi_link_before (&j, x, TSI_SAME_STMT);
+      tsi_link_before (&i, x, TSI_SAME_STMT);
 
-      if (block_may_fallthru (&CATCH_BODY (catch)))
+      if (block_may_fallthru (CATCH_BODY (catch)))
 	{
 	  if (!out_label)
 	    out_label = create_artificial_label ();
 
-	  j = tsi_last (&CATCH_BODY (catch));
 	  x = build1 (GOTO_EXPR, void_type_node, out_label);
-	  tsi_link_after (&j, x, TSI_SAME_STMT);
+	  add_to_statement_list (x, &CATCH_BODY (catch));
 	}
 
-      tsi_link_chain_before (&i, CATCH_BODY (catch), TSI_SAME_STMT);
+      tsi_link_before (&i, CATCH_BODY (catch), TSI_SAME_STMT);
       tsi_delink (&i);
     }
 
@@ -1458,7 +1433,7 @@ lower_cleanup (struct leh_state *state, 
   memset (&fake_tf, 0, sizeof (fake_tf));
   fake_tf.top_p = tp;
   fake_tf.region = this_region;
-  fake_tf.may_fallthru = block_may_fallthru (&TREE_OPERAND (*tp, 0));
+  fake_tf.may_fallthru = block_may_fallthru (TREE_OPERAND (*tp, 0));
   fake_tf.may_throw = true;
 
   fake_tf.eh_label = create_artificial_label ();
@@ -1481,9 +1456,8 @@ lower_cleanup (struct leh_state *state, 
       *tp = TREE_OPERAND (*tp, 0);
       if (fake_tf.fallthru_label)
 	{
-	  tree_stmt_iterator i = tsi_last (tp);
 	  tree x = build1 (LABEL_EXPR, void_type_node, fake_tf.fallthru_label);
-	  tsi_link_after (&i, x, TSI_NEW_STMT);
+	  add_to_statement_list (x, tp);
 	}
     }
 }
@@ -1491,98 +1465,92 @@ lower_cleanup (struct leh_state *state, 
 /* Main loop for lowering eh constructs.  */
 
 static void
-lower_eh_constructs_1 (struct leh_state *state, tree *top_p)
+lower_eh_constructs_1 (struct leh_state *state, tree *tp)
 {
-  tree_stmt_iterator i, j;
+  tree_stmt_iterator i;
+  tree t = *tp;
 
-  for (i = tsi_start (top_p); !tsi_end_p (i); tsi_next (&i))
+  switch (TREE_CODE (t))
     {
-      tree *tp = tsi_stmt_ptr (i);
-      tree t = *tp;
+    case COND_EXPR:
+      lower_eh_constructs_1 (state, &COND_EXPR_THEN (t));
+      lower_eh_constructs_1 (state, &COND_EXPR_ELSE (t));
+      break;
+    case BIND_EXPR:
+      lower_eh_constructs_1 (state, &BIND_EXPR_BODY (t));
+      break;
 
-      switch (TREE_CODE (t))
+    case CALL_EXPR:
+      /* Look for things that can throw exceptions, and record them.  */
+      if (state->cur_region && tree_could_throw_p (t))
 	{
-	case COND_EXPR:
-	  lower_eh_constructs_1 (state, &COND_EXPR_THEN (t));
-	  lower_eh_constructs_1 (state, &COND_EXPR_ELSE (t));
-	  break;
-	case BIND_EXPR:
-	  lower_eh_constructs_1 (state, &BIND_EXPR_BODY (t));
-	  break;
+	  record_stmt_eh_region (state->cur_region, t);
+	  note_eh_region_may_contain_throw (state->cur_region);
+	}
+      break;
 
-	case CALL_EXPR:
-	  /* Look for things that can throw exceptions, and record them.  */
-	  if (state->cur_region && tree_could_throw_p (t))
-	    {
-	      record_stmt_eh_region (state->cur_region, t);
-	      note_eh_region_may_contain_throw (state->cur_region);
-	    }
-	  break;
+    case MODIFY_EXPR:
+      /* Look for things that can throw exceptions, and record them.  */
+      if (state->cur_region && tree_could_throw_p (t))
+	{
+	  record_stmt_eh_region (state->cur_region, t);
+	  note_eh_region_may_contain_throw (state->cur_region);
 
-	case MODIFY_EXPR:
-	  /* Look for things that can throw exceptions, and record them.  */
-	  if (state->cur_region && tree_could_throw_p (t))
-	    {
-	      record_stmt_eh_region (state->cur_region, t);
-	      note_eh_region_may_contain_throw (state->cur_region);
+	  /* ??? For the benefit of calls.c, converting all this to rtl, 
+	     we need to record the call expression, not just the outer
+	     modify statement.  */
+	  if (TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
+	    record_stmt_eh_region (state->cur_region, TREE_OPERAND (t, 1));
+	}
+      break;
 
-	      /* ??? For the benefit of calls.c, converting all this to rtl, 
-		 we need to record the call expression, not just the outer
-		 modify statement.  */
-	      if (TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
-		record_stmt_eh_region (state->cur_region, TREE_OPERAND (t, 1));
-	    }
-	  break;
+    case GOTO_EXPR:
+    case RETURN_EXPR:
+      maybe_record_in_goto_queue (state, t);
+      break;
+    case SWITCH_EXPR:
+      verify_norecord_switch_expr (state, t);
+      break;
 
-	case GOTO_EXPR:
-	case RETURN_EXPR:
-	  maybe_record_in_goto_queue (state, t);
-	  break;
+    case TRY_FINALLY_EXPR:
+      lower_try_finally (state, tp);
+      break;
 
-	case SWITCH_EXPR:
-	  verify_norecord_switch_expr (state, t);
+    case TRY_CATCH_EXPR:
+      i = tsi_start (TREE_OPERAND (t, 1));
+      switch (TREE_CODE (tsi_stmt (i)))
+	{
+	case CATCH_EXPR:
+	  lower_catch (state, tp);
 	  break;
+	case EH_FILTER_EXPR:
+	  lower_eh_filter (state, tp);
+	  break;
+	default:
+	  lower_cleanup (state, tp);
+	  break;
+	}
+      break;
 
-	case TRY_FINALLY_EXPR:
-	  lower_try_finally (state, tp);
-	  goto cleanup;
-
-	case TRY_CATCH_EXPR:
-	  j = tsi_start (&TREE_OPERAND (t, 1));
-	  switch (TREE_CODE (tsi_stmt (j)))
-	    {
-	    case CATCH_EXPR:
-	      lower_catch (state, tp);
-	      break;
-	    case EH_FILTER_EXPR:
-	      lower_eh_filter (state, tp);
-	      break;
-	    default:
-	      lower_cleanup (state, tp);
-	      break;
-	    }
-
-	cleanup:
-	  /* The last right-hand node of a compound_expr, once lowered,
-	     would look like more code.  We could notice this case by
-	     doing tsi_next before replacement, but this seems cheaper.  */
-	  if (tsi_container (i) == tp)
-	    return;
-
-	  /* Need to make sure that the compound_exprs are righted.  */
-	  if (TREE_CODE (*tp) == COMPOUND_EXPR)
+    case STATEMENT_LIST:
+      for (i = tsi_start (t); !tsi_end_p (i); )
+	{
+	  lower_eh_constructs_1 (state, tsi_stmt_ptr (i));
+	  t = tsi_stmt (i);
+	  if (TREE_CODE (t) == STATEMENT_LIST)
 	    {
-	      t = *tp;
+	      tsi_link_before (&i, t, TSI_SAME_STMT);
 	      tsi_delink (&i);
-	      tsi_link_chain_before (&i, t, TSI_CHAIN_END);
 	    }
-	  break;
-
-	default:
-	  /* A type, a decl, or some kind of statement that we're not
-	     interested in.  Don't walk them.  */
-	  break;
+	  else
+	    tsi_next (&i);
 	}
+      break;
+
+    default:
+      /* A type, a decl, or some kind of statement that we're not
+	 interested in.  Don't walk them.  */
+      break;
     }
 }
 
@@ -1617,7 +1585,6 @@ lower_eh_constructs (tree *tp)
 
   timevar_pop (TV_TREE_EH);
 }
-
 
 
 /* Construct EH edges for STMT.  */
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.56
diff -u -p -r1.1.2.56 tree-flow-inline.h
--- tree-flow-inline.h	1 Nov 2003 20:27:15 -0000	1.1.2.56
+++ tree-flow-inline.h	9 Nov 2003 09:10:56 -0000
@@ -347,58 +347,6 @@ dom_children (basic_block bb)
 /*  -----------------------------------------------------------------------  */
 
 static inline bool
-bsi_end_p (block_stmt_iterator i)
-{
-  return (i.tp == NULL || bsi_stmt (i) == NULL_TREE);
-}
-
-/* Similar to tsi_next() but stops at basic block boundaries.  Assumes stmt
-   has bb_for_stmt() set (can't be an empty statement node).  */
-
-static inline void
-bsi_next (block_stmt_iterator *i)
-{
-  extern void bsi_next_in_bb (block_stmt_iterator *, basic_block);
-
-  basic_block bb = bb_for_stmt (*(i->tp));
-  bsi_next_in_bb (i, bb);
-}
-
-static inline tree *
-bsi_stmt_ptr (block_stmt_iterator i)
-{
-#if defined ENABLE_CHECKING
-  if (i.tp == NULL || *i.tp == NULL_TREE)
-    abort ();
-#endif
-
-  if (TREE_CODE ((*i.tp)) == COMPOUND_EXPR)
-    return &TREE_OPERAND ((*i.tp), 0);
-  else
-    return i.tp;
-}
-
-static inline tree
-bsi_stmt (block_stmt_iterator i)
-{
-  return *(bsi_stmt_ptr (i));
-}
-
-static inline tree *
-bsi_container (block_stmt_iterator i)
-{
-  return i.tp;
-}
-
-/* Return a tree_stmt_iterator for the stmt a block iterator refers to.  */
-
-static inline tree_stmt_iterator
-tsi_from_bsi (block_stmt_iterator bi)
-{
-  return tsi_start (bi.tp);
-}
-
-static inline bool
 is_exec_stmt (tree t)
 {
   return (t && !IS_EMPTY_STMT (t) && t != error_mark_node);
@@ -423,105 +371,6 @@ is_label_stmt (tree t)
   return false;
 }
 
-/* Routines to allow a block to be walked backwards reasonably efficiently.
-   Once a decent implementation of bsi_prev() is implemented, this can
-   be removed.  */
-
-#define BSI_NUM_ELEMENTS	50
-
-typedef struct bsi_list_d {
-  block_stmt_iterator bsi[BSI_NUM_ELEMENTS];
-  int curr_index;
-  struct bsi_list_d *next;
-} *bsi_list_p;
-
-
-static inline bsi_list_p new_bsi_list (void);
-static inline int empty_bsi_stack (bsi_list_p);
-extern void push_bsi (bsi_list_p *, block_stmt_iterator);
-extern block_stmt_iterator pop_bsi (bsi_list_p *);
-
-
-/* Allocate a bsi_list structure.  */
-static inline bsi_list_p
-new_bsi_list (void)
-{
-  bsi_list_p b;
-  b = (bsi_list_p) xmalloc (sizeof (struct bsi_list_d));
-  b->curr_index = 0;
-  b->next = NULL;
-
-  return b;
-}
-
-/* Is the iterator stack empty?  */
-static inline int
-empty_bsi_stack (bsi_list_p list)
-{
-  if (!list || (list->curr_index < 0 && list->next == NULL))
-    return 1;
-  return 0;
-}
-
-
-/* Process an entire block of bsi's in reverse by pushing them on a stack
-   as they are encountered, and then popping them off as they are needed.
-   There are a couple of odd things. Since the last loop is a for loop,
-   a dummy entry is pushed on the beginning of the stack, this allows the first
-   item pushed on the stack to be processed in the final for loop, as well
-   as guaranteeing there will be at least one to pop off.
-
-   usage:
-     bsi_list_p  stack;
-     block_stmt_iterator bsi;
-     basic_block bb;
-
-     FOR_EACH_BSI_IN_REVERSE (stack, bb, bsi)
-       {
-         ...
-       }
-*/
-#define FOR_EACH_BSI_IN_REVERSE(bsi_stack, bb, bsi)		\
-  bsi_stack = new_bsi_list ();					\
-  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))	\
-    push_bsi (&bsi_stack, bsi);					\
-  bsi = pop_bsi (&bsi_stack);					\
-  for ( ; !empty_bsi_stack (bsi_stack); bsi = pop_bsi (&bsi_stack))
-
-
-
-/* This macro can be used if all that is ever examined is the stmt nodes
-   of bsi. Ie, if the usage is
-      FOR_EACH_BSI_IN_REVERSE (stack, bb, bsi)
-        {
-	  tree stmt = bsi_stmt (bsi);
-	  ...
-  Then less overhead exists to simply use this macro.
-
-  usage:
-    varray_type stmt_stack;
-    basic_block bb;
-    tree stmt;
-
-    FOR_EACH_STMT_IN_REVERSE (stmt_stack, bb, stmt)
-      {
-        ...
-      }
-*/
-#define FOR_EACH_STMT_IN_REVERSE(stmt_stack, bb, stmt)		\
-  VARRAY_TREE_INIT (stmt_stack, 50, "stmt_stack");		\
-  VARRAY_PUSH_TREE (stmt_stack, NULL_TREE);			\
-  {								\
-    block_stmt_iterator bsi;					\
-    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))	\
-      VARRAY_PUSH_TREE (stmt_stack, bsi_stmt (bsi));		\
-  }								\
-  stmt = VARRAY_TOP_TREE (stmt_stack);				\
-  VARRAY_POP (stmt_stack);					\
-  for ( ; VARRAY_ACTIVE_SIZE (stmt_stack) > 0 ;		\
-	      stmt = VARRAY_TOP_TREE (stmt_stack), VARRAY_POP (stmt_stack))
-
-
 static inline bool
 may_propagate_copy (tree dest, tree orig)
 {
@@ -608,6 +457,82 @@ phi_ssa_name_p (tree t)
     abort ();
 #endif
   return false;
+}
+
+/*  -----------------------------------------------------------------------  */
+
+static inline block_stmt_iterator
+bsi_start (basic_block bb)
+{
+  block_stmt_iterator bsi;
+  if (bb->stmt_list)
+    bsi.tsi = tsi_start (bb->stmt_list);
+  else
+    {
+#ifdef ENABLE_CHECKING
+      if (bb->index >= 0)
+	abort ();
+#endif
+      bsi.tsi.ptr = NULL;
+      bsi.tsi.container = NULL;
+    }
+  bsi.bb = bb;
+  return bsi;
+}
+
+static inline block_stmt_iterator
+bsi_last (basic_block bb)
+{
+  block_stmt_iterator bsi;
+  if (bb->stmt_list)
+    bsi.tsi = tsi_last (bb->stmt_list);
+  else
+    {
+#ifdef ENABLE_CHECKING
+      if (bb->index >= 0)
+	abort ();
+#endif
+      bsi.tsi.ptr = NULL;
+      bsi.tsi.container = NULL;
+    }
+  bsi.bb = bb;
+  return bsi;
+}
+
+static inline bool
+bsi_end_p (block_stmt_iterator i)
+{
+  return tsi_end_p (i.tsi);
+}
+
+static inline void
+bsi_next (block_stmt_iterator *i)
+{
+  tsi_next (&i->tsi);
+}
+
+static inline void
+bsi_prev (block_stmt_iterator *i)
+{
+  tsi_prev (&i->tsi);
+}
+
+static inline tree
+bsi_stmt (block_stmt_iterator i)
+{
+  return tsi_stmt (i.tsi);
+}
+
+static inline tree *
+bsi_stmt_ptr (block_stmt_iterator i)
+{
+  return tsi_stmt_ptr (i.tsi);
+}
+
+static inline void
+bsi_remove (block_stmt_iterator *i)
+{
+  tsi_delink (&i->tsi);
 }
 
 #endif /* _TREE_FLOW_INLINE_H  */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.142
diff -u -p -r1.1.4.142 tree-flow.h
--- tree-flow.h	8 Nov 2003 09:49:19 -0000	1.1.4.142
+++ tree-flow.h	9 Nov 2003 09:10:57 -0000
@@ -340,57 +340,6 @@ static inline tree phi_nodes (basic_bloc
 static inline void add_dom_child (basic_block, basic_block);
 static inline bitmap dom_children (basic_block);
 
-
-/*---------------------------------------------------------------------------
-		 Iterators for statements inside a basic block
----------------------------------------------------------------------------*/
-
-/* Iterator object for traversing over BASIC BLOCKs.  */
-
-typedef struct {
-  tree *tp;
-  tree context;		/* Stack for descending into BIND_EXPR's.  */
-} block_stmt_iterator;
-
-extern block_stmt_iterator bsi_start (basic_block);
-extern block_stmt_iterator bsi_last (basic_block);
-static inline bool bsi_end_p (block_stmt_iterator);
-static inline void bsi_next (block_stmt_iterator *);
-extern void bsi_prev (block_stmt_iterator *);
-static inline tree bsi_stmt (block_stmt_iterator);
-static inline tree *bsi_stmt_ptr (block_stmt_iterator);
-static inline tree *bsi_container (block_stmt_iterator);
-
-extern block_stmt_iterator bsi_from_tsi (tree_stmt_iterator);
-static inline tree_stmt_iterator tsi_from_bsi (block_stmt_iterator);
-
-extern void bsi_remove (block_stmt_iterator *);
-
-enum bsi_iterator_update
-{
-  BSI_NEW_STMT,
-  BSI_SAME_STMT
-};
-
-/* Single stmt insertion routines.  */
-
-extern void bsi_insert_before (block_stmt_iterator *, tree, enum bsi_iterator_update);
-extern void bsi_insert_after (block_stmt_iterator *, tree, enum bsi_iterator_update);
-extern void bsi_insert_on_edge (edge, tree);
-extern int bsi_commit_edge_inserts (int, int *);
-extern block_stmt_iterator bsi_insert_on_edge_immediate
- (edge, tree, block_stmt_iterator *, basic_block *);
-
-extern void bsi_replace (block_stmt_iterator, tree);
-
-/* Stmt list insertion routines.  */
-
-extern void bsi_insert_list_before (block_stmt_iterator *, tree_stmt_anchor);
-extern void bsi_insert_list_after (block_stmt_iterator *, tree_stmt_anchor);
-extern block_stmt_iterator bsi_insert_list_on_edge (edge, tree_stmt_anchor);
-
-void bsi_next_in_bb (block_stmt_iterator *, basic_block);
-
 /*---------------------------------------------------------------------------
 			      Global declarations
 ---------------------------------------------------------------------------*/
@@ -423,6 +372,41 @@ extern GTY(()) varray_type call_clobbere
 
 
 /*---------------------------------------------------------------------------
+			      Block iterators
+---------------------------------------------------------------------------*/
+
+typedef struct {
+  tree_stmt_iterator tsi;
+  basic_block bb;
+} block_stmt_iterator;
+
+static inline block_stmt_iterator bsi_start (basic_block);
+static inline block_stmt_iterator bsi_last (basic_block);
+static inline bool bsi_end_p (block_stmt_iterator);
+static inline void bsi_next (block_stmt_iterator *);
+static inline void bsi_prev (block_stmt_iterator *);
+static inline tree bsi_stmt (block_stmt_iterator);
+static inline tree * bsi_stmt_ptr (block_stmt_iterator);
+
+extern void bsi_move_before (block_stmt_iterator *, block_stmt_iterator *);
+extern void bsi_move_after (block_stmt_iterator *, block_stmt_iterator *);
+extern void bsi_move_to_bb_end (block_stmt_iterator *, basic_block);
+
+enum bsi_iterator_update
+{
+  /* Note that these are intentionally in the same order as TSI_FOO.  */
+  BSI_NEW_STMT,
+  BSI_SAME_STMT
+};
+
+extern void bsi_insert_before (block_stmt_iterator *, tree,
+			       enum bsi_iterator_update);
+extern void bsi_insert_after (block_stmt_iterator *, tree,
+			      enum bsi_iterator_update);
+
+extern void bsi_replace (const block_stmt_iterator *, tree);
+
+/*---------------------------------------------------------------------------
 			      Function prototypes
 ---------------------------------------------------------------------------*/
 /* In tree-cfg.c  */
@@ -450,11 +434,8 @@ extern tree last_stmt (basic_block);
 extern tree *last_stmt_ptr (basic_block);
 extern edge find_taken_edge (basic_block, tree);
 extern int call_expr_flags (tree);
-extern void remove_useless_stmts_and_vars (tree *, bool);
+extern void remove_useless_stmts (tree *);
 extern basic_block tree_split_edge (edge);
-extern void bsi_move_before (block_stmt_iterator, block_stmt_iterator);
-extern void bsi_move_after (block_stmt_iterator, block_stmt_iterator);
-extern void bsi_move_to_bb_end (block_stmt_iterator, basic_block);
 extern edge thread_edge (edge, basic_block);
 extern basic_block label_to_block (tree);
 extern bool cleanup_cond_expr_graph (basic_block, block_stmt_iterator);
@@ -462,6 +443,9 @@ extern bool cleanup_switch_expr_graph (b
 extern void tree_optimize_tail_calls (void);
 extern basic_block tree_block_forwards_to (basic_block bb);
 extern void dump_cfg_function_to_file (tree, FILE *, int);
+extern void bsi_insert_on_edge (edge, tree);
+extern void bsi_commit_edge_inserts (bool, int *);
+extern void bsi_insert_on_edge_immediate (edge, tree);
 
 /* In tree-dfa.c  */
 void find_referenced_vars (tree);
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.26.2.58
diff -u -p -r1.26.2.58 tree-inline.c
--- tree-inline.c	2 Nov 2003 09:59:54 -0000	1.26.2.58
+++ tree-inline.c	9 Nov 2003 09:10:58 -0000
@@ -130,9 +130,7 @@ static tree remap_decl (tree, inline_dat
 static tree remap_type (tree, inline_data *);
 static tree initialize_inlined_parameters (inline_data *, tree, tree, tree);
 static void remap_block (tree *, inline_data *);
-static tree add_stmt_to_compound (tree, tree, tree);
 static tree remap_decls (tree, inline_data *);
-static tree add_stmt_to_compound (tree, tree, tree);
 static void copy_bind_expr (tree *, int *, inline_data *);
 static tree mark_local_for_remap_r (tree *, int *, void *);
 static tree unsave_r (tree *, int *, void *);
@@ -401,6 +399,21 @@ remap_block (tree *block, inline_data *i
 }
 
 static void
+copy_statement_list (tree *tp)
+{
+  tree_stmt_iterator oi, ni;
+  tree new;
+
+  new = alloc_stmt_list ();
+  ni = tsi_start (new);
+  oi = tsi_start (*tp);
+  *tp = new;
+
+  for (; !tsi_end_p (oi); tsi_next (&oi))
+    tsi_link_after (&ni, tsi_stmt (oi), TSI_NEW_STMT);
+}
+
+static void
 copy_bind_expr (tree *tp, int *walk_subtrees, inline_data *id)
 {
   tree block = BIND_EXPR_BLOCK (*tp);
@@ -461,10 +474,10 @@ copy_body_r (tree *tp, int *walk_subtree
 	    if (TREE_CODE (assignment) == RESULT_DECL)
 	      gimplify_stmt (&assignment);
 
-	  *tp = build (BIND_EXPR, void_type_node, NULL_TREE,
-		       build (COMPOUND_EXPR, void_type_node,
-			      assignment, goto_stmt),
+	  *tp = build (BIND_EXPR, void_type_node, NULL_TREE, NULL_TREE,
 		       make_node (BLOCK));
+	  add_to_statement_list (assignment, &BIND_EXPR_BODY (*tp));
+	  add_to_statement_list (goto_stmt, &BIND_EXPR_BODY (*tp));
         }
       /* If we're not returning anything just do the jump.  */
       else
@@ -491,6 +504,8 @@ copy_body_r (tree *tp, int *walk_subtree
 	   && DECL_CONTEXT (*tp) != VARRAY_TREE (id->fns, 0))
     abort ();
 #endif
+  else if (TREE_CODE (*tp) == STATEMENT_LIST)
+    copy_statement_list (tp);
   else if (TREE_CODE (*tp) == SAVE_EXPR)
     remap_save_expr (tp, id->decl_map, VARRAY_TREE (id->fns, 0),
 		     walk_subtrees);
@@ -749,8 +764,7 @@ initialize_inlined_parameters (inline_da
 	  /* We want to use MODIFY_EXPR, not INIT_EXPR here so that we
 	     keep our trees in gimple form.  */
 	  init_stmt = build (MODIFY_EXPR, TREE_TYPE (var), var, rhs);
-	  init_stmts = add_stmt_to_compound (init_stmts, void_type_node,
-					     init_stmt);
+	  add_to_statement_list (init_stmt, &init_stmts);
 
 	  /* If the conversion needed to assign VALUE to VAR is not a
 	     GIMPLE expression, flag that we will need to gimplify
@@ -780,12 +794,7 @@ initialize_inlined_parameters (inline_da
   for (; a; a = TREE_CHAIN (a))
     {
       tree value = TREE_VALUE (a);
-
-      if (! value || ! TREE_SIDE_EFFECTS (value))
-	continue;
-
-      init_stmts = add_stmt_to_compound (init_stmts, void_type_node,
-					 value);
+      add_to_statement_list (value, &init_stmts);
     }
 
   if (gimplify_init_stmts_p && lang_hooks.gimple_before_inlining)
@@ -1439,9 +1448,7 @@ expand_call_inline (tree *tp, int *walk_
       id->tsi = save_tsi;
 
       /* And add them to the tree.  */
-      BIND_EXPR_BODY (expr) = add_stmt_to_compound (BIND_EXPR_BODY (expr),
-						    void_type_node, 
-						    arg_inits);
+      add_to_statement_list (arg_inits, &BIND_EXPR_BODY (expr));
     }
 
   /* Record the function we are about to inline so that we can avoid
@@ -1478,9 +1485,7 @@ expand_call_inline (tree *tp, int *walk_
 
   /* After we've initialized the parameters, we insert the body of the
      function itself.  */
-  BIND_EXPR_BODY (expr)
-    = add_stmt_to_compound (BIND_EXPR_BODY (expr), 
-			    void_type_node, copy_body (id));
+  add_to_statement_list (copy_body (id), &BIND_EXPR_BODY (expr));
   inlined_body = &BIND_EXPR_BODY (expr);
 
   /* After the body of the function comes the RET_LABEL.  This must come
@@ -1489,16 +1494,14 @@ expand_call_inline (tree *tp, int *walk_
   if (TREE_USED (id->ret_label))
     {
       tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label);
-      BIND_EXPR_BODY (expr)
-	= add_stmt_to_compound (BIND_EXPR_BODY (expr), void_type_node, label);
+      add_to_statement_list (label, &BIND_EXPR_BODY (expr));
     }
 
   /* Finally, mention the returned value so that the value of the
      statement-expression is the returned value of the function.  */
   if (use_retvar)
-    BIND_EXPR_BODY (expr) 
-      = add_stmt_to_compound (BIND_EXPR_BODY (expr), 
-			      TREE_TYPE (use_retvar), use_retvar);
+    /* Set TREE_TYPE on BIND_EXPR?  */
+    add_to_statement_list_force (use_retvar, &BIND_EXPR_BODY (expr));
 
   /* Clean up.  */
   splay_tree_delete (id->decl_map);
@@ -1515,7 +1518,8 @@ expand_call_inline (tree *tp, int *walk_
       tree save_decl;
 
       /* Keep the new trees in gimple form.  */
-      BIND_EXPR_BODY (expr) = rationalize_compound_expr (BIND_EXPR_BODY (expr));
+      BIND_EXPR_BODY (expr)
+	= rationalize_compound_expr (BIND_EXPR_BODY (expr));
 
       /* We want to create a new variable to hold the result of the
 	 inlined body.  This new variable needs to be added to the
@@ -1530,37 +1534,9 @@ expand_call_inline (tree *tp, int *walk_
 	 then we're going to need to splice in a MODIFY_EXPR.  Otherwise
 	 the call was a standalone statement and we can just replace it
 	 with the BIND_EXPR inline representation of the called function.  */
-      if (TREE_CODE (*tsi_stmt_ptr (id->tsi)) != CALL_EXPR)
+      if (TREE_CODE (tsi_stmt (id->tsi)) != CALL_EXPR)
 	{
-	  tree *container_p = tsi_container (id->tsi);
-	  tree container = *container_p;
-
-	  if (TREE_CODE (container) != COMPOUND_EXPR)
-	    {
-	      /* If the container is not a COMPOUND_EXPR, then simply
-		 calling add_stmt_to_compound property insert the BIND_EXPR
-		 into the proper location.  */
-	      *container_p
-		= add_stmt_to_compound (expr, TREE_TYPE (expr), container);
-	    }
-	  else
-	    {
-	      /* Insertion of our new COMPOUND_EXPR is slightly more
-	         complex in this case.  We build a the new COMPOUND_EXPR
-		 and set its operands to the contents of the original
-		 COMPOUND_EXPR.  */
-	      tree new_ce = build (COMPOUND_EXPR, TREE_TYPE (expr), 
-				   TREE_OPERAND (container, 0),
-				   TREE_OPERAND (container, 1));
-
-	      /* Then we reset the operands of the original
-	         COMPOUND_EXPR to the new BIND_EXPR and the new
-		 COMPOUND_EXPR.  */
-	      TREE_OPERAND (container, 0) = expr;
-	      TREE_OPERAND (container, 1) = new_ce;
-	    }
-
-	  /* Replace the RHS of the MODIFY_EXPR.  */
+	  tsi_link_before (&id->tsi, expr, TSI_SAME_STMT);
 	  *tp = inline_result;
 	}
       else
@@ -1625,14 +1601,81 @@ expand_call_inline (tree *tp, int *walk_
   return NULL_TREE;
 }
 
+static void
+gimple_expand_calls_inline (tree *stmt_p, inline_data *id)
+{
+  tree stmt = *stmt_p;
+  enum tree_code code = TREE_CODE (stmt); 
+  int dummy;
+
+  switch (code)
+    {
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator i;
+	tree new;
+
+	for (i = tsi_start (stmt); !tsi_end_p (i); )
+	  {
+	    id->tsi = i;
+	    gimple_expand_calls_inline (tsi_stmt_ptr (i), id);
+
+	    new = tsi_stmt (i);
+	    if (TREE_CODE (new) == STATEMENT_LIST)
+	      {
+		tsi_link_before (&i, new, TSI_SAME_STMT);
+		tsi_delink (&i);
+	      }
+	    else
+	      tsi_next (&i);
+	  }
+      }
+      break;
+
+    case COND_EXPR:
+      gimple_expand_calls_inline (&COND_EXPR_THEN (stmt), id);
+      gimple_expand_calls_inline (&COND_EXPR_ELSE (stmt), id);
+      break;
+    case CATCH_EXPR:
+      gimple_expand_calls_inline (&CATCH_BODY (stmt), id);
+      break;
+    case EH_FILTER_EXPR:
+      gimple_expand_calls_inline (&EH_FILTER_FAILURE (stmt), id);
+      break;
+    case TRY_CATCH_EXPR:
+    case TRY_FINALLY_EXPR:
+      gimple_expand_calls_inline (&TREE_OPERAND (stmt, 0), id);
+      gimple_expand_calls_inline (&TREE_OPERAND (stmt, 1), id);
+      break;
+    case BIND_EXPR:
+      gimple_expand_calls_inline (&BIND_EXPR_BODY (stmt), id);
+      break;
+
+    case COMPOUND_EXPR:
+      /* We're gimple.  We should have gotten rid of all these.  */
+      abort ();
+
+    case MODIFY_EXPR:
+      stmt_p = &TREE_OPERAND (stmt, 1);
+      stmt = *stmt_p;
+      if (TREE_CODE (stmt) != CALL_EXPR)
+	break;
+      /* FALLTHRU */
+    case CALL_EXPR:
+      expand_call_inline (stmt_p, &dummy, id);
+      break;
+
+    default:
+      break;
+    }
+}
+
 /* Walk over the entire tree *TP, replacing CALL_EXPRs with inline
    expansions as appropriate.  */
 
 static void
 expand_calls_inline (tree *tp, inline_data *id)
 {
-  tree_stmt_iterator i;
-
   /* If we are not in gimple form, then we want to walk the tree
      recursively as we do not know anything about the structure
      of the tree.  */
@@ -1647,71 +1690,8 @@ expand_calls_inline (tree *tp, inline_da
      the statements, inlining calls in each statement.  By walking
      the statements, we have enough information to keep the tree
      in gimple form as we insert inline bodies.  */
-  for (i = tsi_start (tp); !tsi_end_p (i); tsi_next (&i))
-    {
-      tree *stmt_p = tsi_stmt_ptr (i);
-      enum tree_code code = TREE_CODE (*stmt_p); 
 
-      if (code == LOOP_EXPR)
-	{
-	  /* Dive into the LOOP_EXPR.  */
-	  expand_calls_inline (&LOOP_EXPR_BODY (*stmt_p), id);
-	}
-      else if (code == COND_EXPR)
-        {
-	  /* Dive into the COND_EXPR.  */
-	  expand_calls_inline (&COND_EXPR_COND (*stmt_p), id);
-	  expand_calls_inline (&COND_EXPR_THEN (*stmt_p), id);
-	  expand_calls_inline (&COND_EXPR_ELSE (*stmt_p), id);
-        }
-      else if (code == CATCH_EXPR)
-        {
-	  /* Dive into the CATCH_EXPR.  */
-	  expand_calls_inline (&CATCH_BODY (*stmt_p), id);
-        }
-      else if (code == EH_FILTER_EXPR)
-        {
-	  /* Dive into the EH_FILTER_EXPR.  */
-	  expand_calls_inline (&EH_FILTER_FAILURE (*stmt_p), id);
-        }
-      else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
-        {
-	  /* Dive into TRY_*_EXPRs.  */
-	  expand_calls_inline (&TREE_OPERAND (*stmt_p, 0), id);
-	  expand_calls_inline (&TREE_OPERAND (*stmt_p, 1), id);
-        }
-      else if (code == SWITCH_EXPR)
-        {
-	  /* Dive into the SWITCH_EXPR.  */
-	  expand_calls_inline (&SWITCH_COND (*stmt_p), id);
-	  if (SWITCH_BODY (*stmt_p))
-	    expand_calls_inline (&SWITCH_BODY (*stmt_p), id);
-        }
-      else if (code == BIND_EXPR)
-        {
-	  /* Dive into the BIND_EXPR.  */
-	  expand_calls_inline (&BIND_EXPR_BODY (*stmt_p), id);
-        }
-      else if (code == COMPOUND_EXPR)
-        {
-	  /* Dive into the COMPOUND_EXPR; this should only happen at
-	     the end of a function tree, so the recursion isn't nearly
-	     as bad as you might think.  */
-	  expand_calls_inline (&TREE_OPERAND (*stmt_p, 0), id);
-	  expand_calls_inline (&TREE_OPERAND (*stmt_p, 1), id);
-        }
-      else
-	{
-          /* Search through *TP, replacing all calls to inline functions by
-	     appropriate equivalents.  Use walk_tree in no-duplicates mode
- 	     to avoid exponential time complexity.  (We can't just use
-	     walk_tree_without_duplicates, because of the special TARGET_EXPR
-	     handling in expand_calls.  The hash table is set up in
-	     optimize_function.  */
-	  id->tsi = i;
-	  walk_tree (stmt_p, expand_call_inline, id, id->tree_pruner);
-	}
-    }
+  gimple_expand_calls_inline (tp, id);
 }
 
 /* Expand calls to inline functions in the body of FN.  */
@@ -2024,6 +2004,14 @@ walk_tree (tree *tp, walk_tree_fn func, 
 	case SAVE_EXPR:
 	  WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
 
+	case STATEMENT_LIST:
+	  {
+	    tree_stmt_iterator i;
+	    for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+	      WALK_SUBTREE (*tsi_stmt_ptr (i));
+	  }
+	  break;
+
 	default:
 	  abort ();
 	}
@@ -2087,6 +2075,8 @@ copy_tree_r (tree *tp, int *walk_subtree
     *walk_subtrees = 0;
   else if (TREE_CODE_CLASS (code) == 'd')
     *walk_subtrees = 0;
+  else if (code == STATEMENT_LIST)
+    abort ();
 
   return NULL_TREE;
 }
@@ -2131,20 +2121,6 @@ remap_save_expr (tree *tp, void *st_, tr
   *tp = (tree) n->value;
 }
 
-/* Add STMT to EXISTING if possible, otherwise create a new
-   COMPOUND_EXPR and add STMT to it.  */
-
-static tree
-add_stmt_to_compound (tree existing, tree type, tree stmt)
-{
-  if (!stmt)
-    return existing;
-  else if (existing)
-    return build (COMPOUND_EXPR, type, existing, stmt);
-  else
-    return stmt;
-}
-
 /* Called via walk_tree.  If *TP points to a DECL_STMT for a local
    declaration, copies the declaration and enters it in the splay_tree
    in DATA (which is really an `inline_data *').  */
@@ -2211,6 +2187,8 @@ unsave_r (tree *tp, int *walk_subtrees, 
       if (n)
 	*tp = (tree) n->value;
     }
+  else if (TREE_CODE (*tp) == STATEMENT_LIST)
+    copy_statement_list (tp);
   else if (TREE_CODE (*tp) == BIND_EXPR)
     copy_bind_expr (tp, walk_subtrees, id);
   else if (TREE_CODE (*tp) == SAVE_EXPR)
Index: tree-iterator.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-iterator.h,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 tree-iterator.h
--- tree-iterator.h	18 Oct 2003 03:09:47 -0000	1.1.2.9
+++ tree-iterator.h	9 Nov 2003 09:10:59 -0000
@@ -23,129 +23,76 @@ Boston, MA 02111-1307, USA.  */
 /* This file is dependent upon the implementation of tree's. It provides an
    abstract interface to the tree objects such that if all tree creation and
    manipulations are done through this interface, we can easily change the
-   implementation of tree's, and not impact other code.
+   implementation of tree's, and not impact other code.  */
 
-   In particular, we wish to replace the current linking scheme which uses
-   COMPOUND_EXPR nodes to link statements. We'd like to either use doubly
-   linked lists, or another mechanism which takes the links completely out
-   of the tree nodes all together. Before this can be done, the front end
-   will have to be modified to use these routines to build up the initial
-   GENERIC representation of the function tree.  */
-
-/** @file tree-iterator.c
-    @brief Routines for manipulating tree statements. */
-
-#ifndef _TREE_ITERATOR_H
-#define _TREE_ITERATOR_H 1
+#ifndef GCC_TREE_ITERATOR_H
+#define GCC_TREE_ITERATOR_H 1
 
 /* Iterator object for GENERIC or GIMPLE TREE statements.  */
 
 typedef struct {
-  tree *tp;
+  struct tree_statement_list_node *ptr;
+  tree container;
 } tree_stmt_iterator;
 
-static inline tree_stmt_iterator tsi_start (tree *);
-static inline tree_stmt_iterator tsi_last (tree *);
-static inline bool tsi_end_p (tree_stmt_iterator);
-static inline bool tsi_one_before_end_p (tree_stmt_iterator);
-static inline void tsi_next (tree_stmt_iterator *);
-static inline void tsi_prev (tree_stmt_iterator *);
-static inline tree tsi_stmt (tree_stmt_iterator);
-static inline tree *tsi_stmt_ptr (tree_stmt_iterator);
-static inline tree *tsi_container (tree_stmt_iterator);
-
-
 static inline tree_stmt_iterator
-tsi_start (tree *tp)
+tsi_start (tree t)
 {
   tree_stmt_iterator i;
-  i.tp = tp;
+
+  i.ptr = STATEMENT_LIST_HEAD (t);
+  i.container = t;
+
   return i;
 }
 
-/* Return an iterator pointing to the last stmt in a chain.  */
 static inline tree_stmt_iterator
-tsi_last (tree *tp)
+tsi_last (tree t)
 {
   tree_stmt_iterator i;
 
-  while (TREE_CODE (*tp) == COMPOUND_EXPR)
-    tp = &TREE_OPERAND (*tp, 1);
+  i.ptr = STATEMENT_LIST_TAIL (t);
+  i.container = t;
 
-  i.tp = tp;
   return i;
 }
 
 static inline bool
 tsi_end_p (tree_stmt_iterator i)
 {
-  return (i.tp == NULL || *(i.tp) == error_mark_node);
+  return i.ptr == NULL;
 }
 
-static inline void
-tsi_next (tree_stmt_iterator *i)
+static inline bool
+tsi_one_before_end_p (tree_stmt_iterator i)
 {
-  tree t = *(i->tp);
-  if (TREE_CODE (t) == COMPOUND_EXPR)
-    i->tp = &(TREE_OPERAND (t, 1));
-  else
-    i->tp = NULL;
+  return i.ptr != NULL && i.ptr->next == NULL;
 }
 
 static inline void
-tsi_prev (tree_stmt_iterator *i)
+tsi_next (tree_stmt_iterator *i)
 {
-  printf (" tsi_prev (%p) is not implemented yet\n",(void *)i);
-  abort();
+  i->ptr = i->ptr->next;
 }
 
-static inline bool
-tsi_one_before_end_p (tree_stmt_iterator i)
+static inline void
+tsi_prev (tree_stmt_iterator *i)
 {
-  tsi_next (&i);
-  return tsi_end_p (i);
+  i->ptr = i->ptr->prev;
 }
 
 static inline tree *
 tsi_stmt_ptr (tree_stmt_iterator i)
 {
-  tree t;
-
-#if defined ENABLE_CHECKING
-  if (i.tp == NULL || *i.tp == NULL_TREE)
-    abort ();
-#endif
-
-  t = *(i.tp);
-
-  if (TREE_CODE (t) == COMPOUND_EXPR)
-    return &TREE_OPERAND (t, 0);
-  else
-    return i.tp;
+  return &i.ptr->stmt;
 }
 
 static inline tree
 tsi_stmt (tree_stmt_iterator i)
 {
-  tree t = *(tsi_stmt_ptr (i));
-  if (t == error_mark_node)
-    t = NULL_TREE;
-  return t;
+  return i.ptr->stmt;
 }
 
-static inline tree *
-tsi_container (tree_stmt_iterator i)
-{
-  return i.tp;
-}
-
-
-/* Abstract interface for linking and chaining stmts.  Declared in tree.c.  */
-
-/* A tree_stmt_anchor is used as the root of a stmt list.  */
-typedef tree tree_stmt_anchor;
-#define EMPTY_ANCHOR	NULL_TREE
-
 enum tsi_iterator_update
 {
   TSI_NEW_STMT,		/* Leave the iterator at the same statement.  */
@@ -160,12 +107,14 @@ enum tsi_iterator_update
 			   the same direction.  */
 };
 
-void tsi_link_before (tree_stmt_iterator *, tree, enum tsi_iterator_update);
-void tsi_link_after (tree_stmt_iterator *, tree, enum tsi_iterator_update);
-void tsi_link_chain_before (tree_stmt_iterator *, tree, enum tsi_iterator_update);
-void tsi_link_chain_after (tree_stmt_iterator *, tree, enum tsi_iterator_update);
+extern void tsi_link_before (tree_stmt_iterator *, tree,
+			     enum tsi_iterator_update);
+extern void tsi_link_after (tree_stmt_iterator *, tree,
+			    enum tsi_iterator_update);
+
 void tsi_delink (tree_stmt_iterator *);
-tree_stmt_iterator tsi_new_stmt_list (tree, tree_stmt_anchor *);
-tree_stmt_iterator tsi_stmt_list_head (tree_stmt_anchor);
 
-#endif /* _TREE_ITERATOR_H  */
+tree tsi_split_statement_list_after (const tree_stmt_iterator *);
+tree tsi_split_statement_list_before (tree_stmt_iterator *);
+
+#endif /* GCC_TREE_ITERATOR_H  */
Index: tree-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-mudflap.c,v
retrieving revision 1.1.2.55
diff -u -p -r1.1.2.55 tree-mudflap.c
--- tree-mudflap.c	18 Oct 2003 03:09:47 -0000	1.1.2.55
+++ tree-mudflap.c	9 Nov 2003 09:10:59 -0000
@@ -226,16 +226,15 @@ mf_decl_cache_locals (tree* body)
   TREE_CHAIN (mf_cache_shift_decl_l) = mf_cache_mask_decl_l;
 
   /* Build initialization nodes for them.  */
-  add_tree (build (INIT_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
-		   mf_cache_shift_decl_l, mf_cache_shift_decl),
-	    & init_exprs);
-  add_tree (build (INIT_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
-		   mf_cache_mask_decl_l, mf_cache_mask_decl),
-	    & init_exprs);
+  add_to_statement_list (build (INIT_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
+				mf_cache_shift_decl_l, mf_cache_shift_decl),
+			 & init_exprs);
+  add_to_statement_list (build (INIT_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
+				mf_cache_mask_decl_l, mf_cache_mask_decl),
+			 & init_exprs);
 
   /* Add the function body to the end. */
-  add_tree (*body, & init_exprs);
-  init_exprs = rationalize_compound_expr (init_exprs);
+  add_to_statement_list (*body, & init_exprs);
 
   *body = build (BIND_EXPR, TREE_TYPE (init_exprs),
 		 mf_cache_shift_decl_l, init_exprs,
@@ -1122,8 +1121,8 @@ mx_register_decls (tree decl, tree *comp
 				 register_fncall_params);
 
 	  /* Accumulate the two calls.  */
-	  add_tree (register_fncall, & initially_stmts);
-	  add_tree (unregister_fncall, & finally_stmts);
+	  add_to_statement_list (register_fncall, & initially_stmts);
+	  add_to_statement_list (unregister_fncall, & finally_stmts);
 
 	  mf_mark (decl);
 	}
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.68
diff -u -p -r1.1.4.68 tree-optimize.c
--- tree-optimize.c	5 Nov 2003 13:39:23 -0000	1.1.4.68
+++ tree-optimize.c	9 Nov 2003 09:11:00 -0000
@@ -51,7 +51,7 @@ Boston, MA 02111-1307, USA.  */
 /* Main entry point to the tree SSA transformation routines.  FNDECL is the
    FUNCTION_DECL node for the function to optimize.  */
 
-void
+static void
 optimize_function_tree (tree fndecl, tree *chain)
 {
   /* Don't bother doing anything if the program has errors.  */
@@ -169,9 +169,19 @@ optimize_function_tree (tree fndecl, tre
       /* Rewrite the function out of SSA form.  */
       rewrite_out_of_ssa (fndecl, TDI_optimized);
 
+      /* Flush out flow graph and SSA data.  */
       sbitmap_free (vars_to_rename);
     }
 
+  /* Re-chain the statements from the blocks.  */
+  {
+    basic_block bb;
+
+    *chain = NULL;
+    FOR_EACH_BB (bb)
+      add_to_statement_list_force (bb->stmt_list, chain);
+  }
+
   delete_tree_cfg ();
 }
 
@@ -281,7 +291,7 @@ tree_rest_of_compilation (tree fndecl, b
 
   /* Run a pass over the statements deleting any obviously useless
      statements before we build the CFG.  */
-  remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), false);
+  remove_useless_stmts (&DECL_SAVED_TREE (fndecl));
   dump_function (TDI_useless, fndecl);
 
   /* Run a pass to lower magic exception handling constructs into,
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.56
diff -u -p -r1.1.2.56 tree-pretty-print.c
--- tree-pretty-print.c	5 Nov 2003 16:28:10 -0000	1.1.2.56
+++ tree-pretty-print.c	9 Nov 2003 09:11:01 -0000
@@ -41,7 +41,6 @@ static void newline_and_indent (pretty_p
 static void maybe_init_pretty_print (FILE *);
 static void print_declaration (pretty_printer *, tree, int, int);
 static void print_struct_decl (pretty_printer *, tree, int);
-static void dump_block_info (pretty_printer *, basic_block, int, int);
 static void do_niy (pretty_printer *, tree);
 static void dump_vops (pretty_printer *, tree, int);
 
@@ -143,7 +142,6 @@ dump_generic_node (pretty_printer *buffe
   tree type;
   tree op0, op1;
   const char* str;
-  tree_stmt_iterator si;
 
   if (node == NULL_TREE)
     return spc;
@@ -153,9 +151,6 @@ dump_generic_node (pretty_printer *buffe
     {
       basic_block curr_bb = bb_for_stmt (node);
 
-      if ((flags & TDF_BLOCKS) && curr_bb && curr_bb != last_bb)
-	dump_block_info (buffer, curr_bb, spc, flags);
-
       if ((flags & TDF_VOPS) && stmt_ann (node))
 	dump_vops (buffer, node, spc);
 
@@ -664,35 +659,78 @@ dump_generic_node (pretty_printer *buffe
       break;
 
     case COMPOUND_EXPR:
-      if (dumping_stmts)
-	{
-	  dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags);
-	  if (flags & TDF_SLIM)
+      {
+	tree *tp;
+	if (flags & TDF_SLIM)
+	  {
+            pp_string (buffer, "<COMPOUND_EXPR>");
 	    break;
+	  }
+
+        pp_string (buffer, "This is a COMPOUND_EXPR:");
+	newline_and_indent (buffer, spc);
+
+	dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags);
+	if (dumping_stmts)
+	  {
+	    pp_character (buffer, ';');
+	    newline_and_indent (buffer, spc);
+	  }
+	else
+	  {
+	    pp_character (buffer, ',');
+	    pp_space (buffer);
+	  }
+
+	for (tp = &TREE_OPERAND (node, 1);
+	     TREE_CODE (*tp) == COMPOUND_EXPR;
+	     tp = &TREE_OPERAND (*tp, 1))
+	  {
+	    dump_generic_node (buffer, TREE_OPERAND (*tp, 0), spc, flags);
+	    if (dumping_stmts)
+	      {
+	        pp_character (buffer, ';');
+	        newline_and_indent (buffer, spc);
+	      }
+	    else
+	      {
+	        pp_character (buffer, ',');
+	        pp_space (buffer);
+	      }
+	  }
+
+	dump_generic_node (buffer, *tp, spc, flags);
+	if (dumping_stmts)
 	  pp_character (buffer, ';');
+      }
+      break;
 
-	  for (si = tsi_start (&TREE_OPERAND (node, 1));
-	       !tsi_end_p (si);
-	       tsi_next (&si))
-	    {
-	      newline_and_indent (buffer, spc);
-	      dump_generic_node (buffer, tsi_stmt (si), spc, flags);
-	      pp_character (buffer, ';');
-	    }
-	}
-      else
-	{
-	  dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags);
+    case STATEMENT_LIST:
+      {
+	tree_stmt_iterator si;
+	bool first = true;
 
-	  for (si = tsi_start (&TREE_OPERAND (node, 1));
-	       !tsi_end_p (si);
-	       tsi_next (&si))
-	    {
-	      pp_character (buffer, ',');
-	      pp_space (buffer);
-	      dump_generic_node (buffer, tsi_stmt (si), spc, flags);
-	    }
-	}
+	if ((flags & TDF_SLIM) || !dumping_stmts)
+	  {
+            pp_string (buffer, "<STATEMENT_LIST>");
+	    break;
+	  }
+	  
+        pp_string (buffer, "This is a STATEMENT_LIST:");
+        if (!TREE_SIDE_EFFECTS (node))
+	  pp_string (buffer, " (no side effects)");
+	newline_and_indent (buffer, spc);
+
+	for (si = tsi_start (node); !tsi_end_p (si); tsi_next (&si))
+	  {
+	    if (!first)
+	      newline_and_indent (buffer, spc);
+	    else
+	      first = false;
+	    dump_generic_node (buffer, tsi_stmt (si), spc, flags);
+	    pp_character (buffer, ';');
+	  }
+      }
       break;
 
     case MODIFY_EXPR:
@@ -717,7 +755,18 @@ dump_generic_node (pretty_printer *buffe
 	  pp_string (buffer, "if (");
 	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags);
 	  pp_character (buffer, ')');
-	  if (!(flags & TDF_SLIM))
+	  /* The lowered cond_exprs should always be printed in full.  */
+	  if (COND_EXPR_THEN (node)
+	      && TREE_CODE (COND_EXPR_THEN (node)) == GOTO_EXPR
+	      && COND_EXPR_ELSE (node)
+	      && TREE_CODE (COND_EXPR_ELSE (node)) == GOTO_EXPR)
+	    {
+	      pp_space (buffer);
+	      dump_generic_node (buffer, COND_EXPR_THEN (node), 0, flags);
+	      pp_string (buffer, " else ");
+	      dump_generic_node (buffer, COND_EXPR_ELSE (node), 0, flags);
+	    }
+	  else if (!(flags & TDF_SLIM))
 	    {
 	      /* Output COND_EXPR_THEN.  */
 	      if (COND_EXPR_THEN (node))
@@ -1982,79 +2031,13 @@ newline_and_indent (pretty_printer *buff
   INDENT (spc);
 }
 
-
-static void
-dump_block_info (pretty_printer *buffer, basic_block bb, int spc, int flags)
-{
-  if (bb)
-    {
-      edge e;
-      tree *stmt_p = bb->head_tree_p;
-      int lineno;
-
-      newline_and_indent (buffer, spc);
-      pp_scalar (buffer, "# block %d", bb->index);
-
-      if (stmt_p
-	  && is_exec_stmt (*stmt_p)
-	  && (lineno = get_lineno (*stmt_p)) > 0
-	  && (flags & TDF_LINENO))
-	{
-	  pp_string (buffer, " (");
-	  pp_string (buffer, get_filename (*stmt_p));
-	  pp_scalar (buffer, ":%d", lineno);
-	  pp_string (buffer, ")");
-	}
-
-      pp_string (buffer, ".  pred:");
-      for (e = bb->pred; e; e = e->pred_next)
-	if (e->src)
-	  {
-	    pp_scalar (buffer, " %d", e->src->index);
-	    if (e->flags & EDGE_ABNORMAL)
-	      pp_string (buffer, "(ab)");
-	  }
-
-      pp_string (buffer, ".  succ:");
-      for (e = bb->succ; e; e = e->succ_next)
-	if (e->dest)
-	  {
-	    pp_scalar (buffer, " %d", e->dest->index);
-	    if (e->flags & EDGE_ABNORMAL)
-	      pp_string (buffer, "(ab)");
-	  }
-
-      pp_character (buffer, '.');
-
-      newline_and_indent (buffer, spc);
-    }
-}
-
-
 static void
 dump_vops (pretty_printer *buffer, tree stmt, int spc)
 {
   size_t i;
-  basic_block bb;
   stmt_ann_t ann = stmt_ann (stmt);
   varray_type vdefs = vdef_ops (ann);
   varray_type vuses = vuse_ops (ann);
-
-  bb = bb_for_stmt (stmt);
-  if (bb && bb != last_bb && bb->tree_annotations)
-    {
-      tree phi;
-
-      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
-	{
-	  pp_string (buffer, "#   ");
-	  dump_generic_node (buffer, phi, spc, 0);
-	  newline_and_indent (buffer, spc);
-	}
-    }
-
-  if (vdefs || vuses)
-    newline_and_indent (buffer, spc);
 
   if (vdefs)
     for (i = 0; i < VARRAY_ACTIVE_SIZE (vdefs); i++)
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.59
diff -u -p -r1.1.4.59 tree-simple.c
--- tree-simple.c	21 Oct 2003 14:51:55 -0000	1.1.4.59
+++ tree-simple.c	9 Nov 2003 09:11:01 -0000
@@ -314,38 +314,10 @@ int
 is_gimple_stmt (tree t)
 {
   enum tree_code code = TREE_CODE (t);
-  char class = TREE_CODE_CLASS (code);
 
   if (IS_EMPTY_STMT (t))
     return 1;
 
-  switch (class)
-    {
-    case 'r':
-    case '1':
-    case '2':
-    case '<':
-    case 'd':
-    case 'c':
-      /* These should never appear at statement level.  */
-      return 0;
-
-    case 'e':
-    case 's':
-      /* Might be OK.  */
-      break;
-
-    case 'x':
-      if (code == PHI_NODE)
-	return 1;
-      else
-	return 0;
-
-    default:
-      /* Not an expression?!?  */
-      return 0;
-    }
-
   switch (code)
     {
     case BIND_EXPR:
@@ -364,6 +336,8 @@ is_gimple_stmt (tree t)
     case CATCH_EXPR:
     case ASM_EXPR:
     case RESX_EXPR:
+    case PHI_NODE:
+    case STATEMENT_LIST:
       /* These are always void.  */
       return 1;
 
Index: tree-simple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.h,v
retrieving revision 1.1.4.37
diff -u -p -r1.1.4.37 tree-simple.h
--- tree-simple.h	24 Oct 2003 07:41:31 -0000	1.1.4.37
+++ tree-simple.h	9 Nov 2003 09:11:02 -0000
@@ -75,11 +75,9 @@ int is_gimple_constructor_elt (tree);
 
 void recalculate_side_effects (tree);
 
-typedef void foreach_stmt_fn (tree *);
-void foreach_stmt (tree *, foreach_stmt_fn *);
-
-/* FIXME this needs a better name.  */
-void add_tree (tree, tree *);
+void add_to_statement_list (tree, tree *);
+void add_to_statement_list_force (tree, tree *);
+void add_to_compound_expr (tree, tree *);
 
 /* FIXME we should deduce this from the predicate.  */
 typedef enum fallback_t {
@@ -100,6 +98,7 @@ enum gimplify_status {
 enum gimplify_status gimplify_expr (tree *, tree *, tree *,
 				    int (*) (tree), fallback_t);
 void gimplify_stmt (tree *);
+void gimplify_to_stmt_list (tree *);
 void gimplify_body (tree *, tree);
 
 /* Miscellaneous helpers.  */
@@ -113,6 +112,7 @@ void unshare_all_trees (tree);
 tree voidify_wrapper_expr (tree);
 tree gimple_build_eh_filter (tree, tree, tree);
 tree build_and_jump (tree *);
-
+tree alloc_stmt_list (void);
+void free_stmt_list (tree);
 
 #endif /* _TREE_SIMPLE_H  */
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.64
diff -u -p -r1.1.2.64 tree-ssa-dce.c
--- tree-ssa-dce.c	5 Nov 2003 13:39:23 -0000	1.1.2.64
+++ tree-ssa-dce.c	9 Nov 2003 09:11:02 -0000
@@ -88,7 +88,7 @@ static void find_useful_stmts (void);
 static bool stmt_useful_p (tree);
 static void process_worklist (void);
 static void remove_dead_stmts (void);
-static void remove_dead_stmt (block_stmt_iterator *);
+static bool should_remove_dead_stmt (tree);
 static void remove_dead_phis (basic_block);
 
 #define NECESSARY(stmt)	   stmt->common.asm_written_flag
@@ -392,24 +392,29 @@ static void
 remove_dead_stmts (void)
 {
   basic_block bb;
-  tree t;
   block_stmt_iterator i;
 
   FOR_EACH_BB_REVERSE (bb)
     {
-      bsi_list_p stack;
       /* Remove dead PHI nodes.  */
       remove_dead_phis (bb);
 
       /* Remove dead statements.  */
-      FOR_EACH_BSI_IN_REVERSE (stack, bb, i)
+      for (i = bsi_last (bb); !bsi_end_p (i) ; )
 	{
-	  t = bsi_stmt (i);
+	  tree t = bsi_stmt (i);
+
 	  stats.total++;
 
 	  /* If `i' is not in `necessary' then remove from B.  */
-	  if (!necessary_p (t))
-	    remove_dead_stmt (&i);
+	  if (!necessary_p (t) && should_remove_dead_stmt (t))
+	    {
+	      block_stmt_iterator j = i;
+	      bsi_prev (&i);
+	      bsi_remove (&j);
+	    }
+	  else
+	    bsi_prev (&i);
 	}
     }
 }
@@ -454,13 +459,9 @@ remove_dead_phis (basic_block bb)
 
 /* Remove dead statement pointed by iterator I.  */
 
-static void
-remove_dead_stmt (block_stmt_iterator *i)
+static bool
+should_remove_dead_stmt (tree t)
 {
-  tree t;
-
-  t = bsi_stmt (*i);
-
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "Deleting : ");
@@ -484,7 +485,7 @@ remove_dead_stmt (block_stmt_iterator *i
 	  fprintf (dump_file, "\n");
 	}
 
-      return;
+      return false;
     }
 
 #ifdef ENABLE_CHECKING
@@ -492,7 +493,7 @@ remove_dead_stmt (block_stmt_iterator *i
     abort ();
 #endif
 
-  bsi_remove (i);
+  return true;
 }
 
 /* Main routine to eliminate dead code.
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.c,v
retrieving revision 1.1.2.23
diff -u -p -r1.1.2.23 tree-ssa-live.c
--- tree-ssa-live.c	22 Oct 2003 20:28:25 -0000	1.1.2.23
+++ tree-ssa-live.c	9 Nov 2003 09:11:03 -0000
@@ -1301,9 +1301,7 @@ build_tree_conflict_graph (tree_live_inf
   bitmap live;
   int num, x, y, i;
   basic_block bb;
-  varray_type stmt_stack, ops, partition_link, tpa_to_clear, tpa_nodes;
-  stmt_ann_t ann;
-  tree stmt, *var_p;
+  varray_type ops, partition_link, tpa_to_clear, tpa_nodes;
   unsigned l;
 
   map = live_var_map (liveinfo);
@@ -1320,12 +1318,16 @@ build_tree_conflict_graph (tree_live_inf
 
   FOR_EACH_BB (bb)
     {
+      block_stmt_iterator bsi;
+
       /* Start with live on exit temporaries.  */
       bitmap_copy (live, live_on_exit (liveinfo, bb));
 
-      FOR_EACH_STMT_IN_REVERSE (stmt_stack, bb, stmt)
+      for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
         {
 	  tree important_copy_rhs_partition = NULL_TREE;
+	  tree stmt = bsi_stmt (bsi);
+	  stmt_ann_t ann;
 
 	  get_stmt_operands (stmt);
 	  ann = stmt_ann (stmt);
@@ -1376,6 +1378,8 @@ build_tree_conflict_graph (tree_live_inf
 
 	  if (!important_copy_rhs_partition)
 	    {
+	      tree *var_p;
+
 	      ops = def_ops (ann);
 	      num = ((ops) ? VARRAY_ACTIVE_SIZE (ops) : 0);
 	      for (x = 0; x < num; x++)
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.99
diff -u -p -r1.1.4.99 tree-ssa-pre.c
--- tree-ssa-pre.c	7 Nov 2003 06:17:45 -0000	1.1.4.99
+++ tree-ssa-pre.c	9 Nov 2003 09:11:05 -0000
@@ -1940,18 +1940,18 @@ reaching_def (tree var, tree currstmt, b
 
   /* We can't walk BB's backwards right now, so we have to walk *all*
      the statements, and choose the last name we find. */
-  bsi = bsi_start (bb);
-  for (; !bsi_end_p (bsi); bsi_next (&bsi))
+  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
     {
+      tree stmt = bsi_stmt (bsi);
       tree *def;
       varray_type defs;
       size_t i;
 
-      if (bsi_stmt (bsi) == currstmt)
+      if (stmt == currstmt)
 	break;
 
-      get_stmt_operands (bsi_stmt (bsi));
-      defs = def_ops (stmt_ann (bsi_stmt (bsi)));
+      get_stmt_operands (stmt);
+      defs = def_ops (stmt_ann (stmt));
       for (i = 0; defs && i < VARRAY_ACTIVE_SIZE (defs); i++)
 	{
 	  def = VARRAY_TREE_PTR (defs, i);
@@ -1976,21 +1976,19 @@ reaching_def (tree var, tree currstmt, b
     return curruse;
   return reaching_def (var, currstmt, dom, ignore);
 }
+
 /* Insert one ephi operand that doesn't currently exist as a use.  */
 
 static void
 insert_one_operand (struct expr_info *ei, tree ephi, int opnd_indx, 
 		    tree x, edge succ)
 {
-  
   tree expr;
   tree temp = ei->temp;
   tree copy;
   tree newtemp;
   basic_block bb = bb_for_stmt (x);
-  edge e = NULL;
-  block_stmt_iterator bsi;
-  
+
   /* Insert definition of expr at end of BB containing x. */
   copy = TREE_OPERAND (EREF_STMT (ephi), 1);
   copy = unshare_expr (copy);
@@ -2011,19 +2009,16 @@ insert_one_operand (struct expr_info *ei
       fprintf (dump_file, " (on edge), because of EPHI");
       fprintf (dump_file, " in BB %d\n", bb_for_stmt (ephi)->index);
     }
-  set_bb_for_stmt (expr, bb);
-		      
-  /* Find the edge to insert on. */
-  e = succ;
-  if (e == NULL)
-    abort ();
 		      
   /* Do the insertion.  */
-  bsi = bsi_start (bb);
-  bsi_insert_on_edge_immediate (e, expr, NULL, NULL);
-  
-  EPHI_ARG_DEF (ephi, opnd_indx) = create_expr_ref (ei, ei->expr, EUSE_NODE,
-						    bb, 0);
+  /* ??? Previously we did bizzare searching, presumably to get
+     around bugs elsewhere in the infrastructure.  I'm not sure
+     if we really should be using bsi_insert_on_edge_immediate,
+     or just bsi_insert_after at the end of BB.  */
+  bsi_insert_on_edge_immediate (succ, expr);
+
+  EPHI_ARG_DEF (ephi, opnd_indx)
+    = create_expr_ref (ei, ei->expr, EUSE_NODE, bb, 0);
   EUSE_DEF (x) = EPHI_ARG_DEF (ephi, opnd_indx);
   append_eref_to_block (EPHI_ARG_DEF (ephi, opnd_indx), bb);
   EREF_TEMP (EUSE_DEF (x)) = newtemp;
@@ -2534,8 +2529,7 @@ do_proper_save (tree use, tree expr, int
   basic_block bb = bb_for_stmt (use);
   block_stmt_iterator bsi;
 
-  bsi = bsi_start (bb);
-  for (; !bsi_end_p (bsi); bsi_next (&bsi))
+  for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
     {
       if (bsi_stmt (bsi) == use)
 	{
@@ -2543,7 +2537,7 @@ do_proper_save (tree use, tree expr, int
 	    bsi_insert_before (&bsi, expr, BSI_SAME_STMT);
 	  else
 	    bsi_insert_after (&bsi, expr, BSI_SAME_STMT);
-	  return bsi_stmt (bsi);
+	  return use;
 	}
     }
   abort ();
@@ -3137,9 +3131,9 @@ collect_expressions (basic_block block, 
   
   for (j = bsi_start (block); !bsi_end_p (j); bsi_next (&j))
     {
-      tree expr = bsi_stmt (j);
-      tree orig_expr = bsi_stmt (j);
       tree stmt = bsi_stmt (j);
+      tree expr = stmt;
+      tree orig_expr = expr;
       stmt_ann_t ann;
       struct expr_info *slot = NULL;
       
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.146
diff -u -p -r1.1.4.146 tree-ssa.c
--- tree-ssa.c	8 Nov 2003 18:17:28 -0000	1.1.4.146
+++ tree-ssa.c	9 Nov 2003 09:11:07 -0000
@@ -1886,10 +1886,6 @@ rewrite_out_of_ssa (tree fndecl, enum tr
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
 
-  /* Do some cleanups which reduce the amount of data the
-     tree->rtl expanders deal with.  */
-  remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), true);
-
   /* Debugging dumps.  */
   if (dump_file)
     {
@@ -1902,7 +1898,6 @@ rewrite_out_of_ssa (tree fndecl, enum tr
   delete_var_map (map);
   timevar_pop (TV_TREE_SSA_TO_NORMAL);
 }
-
 
 /* Remove edge E and remove the corresponding arguments from the PHI nodes
    in E's destination block.  */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.263.2.65
diff -u -p -r1.263.2.65 tree.c
--- tree.c	28 Oct 2003 14:56:21 -0000	1.263.2.65
+++ tree.c	9 Nov 2003 09:11:11 -0000
@@ -204,6 +204,8 @@ tree_size (tree node)
 	case EKILL_NODE:
 	case EEXIT_NODE: 	return sizeof (struct tree_eref_common);
 
+	case STATEMENT_LIST:	return sizeof (struct tree_statement_list);
+
 	default:
 	  return (*lang_hooks.tree_size) (code);
 	}
@@ -371,6 +373,11 @@ copy_node (tree node)
   enum tree_code code = TREE_CODE (node);
   size_t length;
 
+#ifdef ENABLE_CHECKING
+  if (code == STATEMENT_LIST)
+    abort ();
+#endif
+
   length = tree_size (node);
   t = ggc_alloc_tree (length);
   memcpy (t, node, length);
@@ -1083,44 +1090,6 @@ tree_cons (tree purpose, tree value, tre
   return node;
 }
 
-/* Return the first expression in a sequence of COMPOUND_EXPRs.  */
-
-tree
-expr_first (tree expr)
-{
-  if (expr == NULL_TREE)
-    return expr;
-  while (TREE_CODE (expr) == COMPOUND_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-  return expr;
-}
-
-/* Return the last expression in a sequence of COMPOUND_EXPRs.  */
-
-tree
-expr_last (tree expr)
-{
-  if (expr == NULL_TREE)
-    return expr;
-  while (TREE_CODE (expr) == COMPOUND_EXPR)
-    expr = TREE_OPERAND (expr, 1);
-  return expr;
-}
-
-/* Return the number of subexpressions in a sequence of COMPOUND_EXPRs.  */
-
-int
-expr_length (tree expr)
-{
-  int len = 0;
-
-  if (expr == NULL_TREE)
-    return 0;
-  for (; TREE_CODE (expr) == COMPOUND_EXPR; expr = TREE_OPERAND (expr, 1))
-    len += expr_length (TREE_OPERAND (expr, 0));
-  ++len;
-  return len;
-}
 
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -1536,6 +1505,7 @@ tree_node_structure (tree t)
     case EEXIT_NODE:            return TS_EREF_NODE;
     case SSA_NAME:		return TS_SSA_NAME;
     case PLACEHOLDER_EXPR:	return TS_COMMON;
+    case STATEMENT_LIST:	return TS_STATEMENT_LIST;
 
     default:
       abort ();
@@ -5279,300 +5249,6 @@ build_empty_stmt (void)
   return build1 (NOP_EXPR, void_type_node, size_zero_node);
 }
 
-
-/* Links a stmt before the current stmt.  */
-
-void
-tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
-{
-  tree ce;
-
-  if (mode == TSI_CHAIN_START || mode == TSI_CHAIN_END)
-    abort ();
-  if (mode == TSI_CONTINUE_LINKING)
-    mode = TSI_NEW_STMT;
-
-  /* Build a new CE which points to the current node.  */
-  ce = build (COMPOUND_EXPR, void_type_node, t, *i->tp);
-
-  /* Make the parent pointer point to this new node.  At this point, the
-     iterator will be pointing to the new node we just inserted.  */
-  *i->tp = ce;
-
-  /* Update the iterator to points to the address of the next ptr in our new 
-     node, which is the current stmt again.  */
-  if (mode == TSI_SAME_STMT)
-    i->tp = &TREE_OPERAND (ce, 1);
-}
-
-/* Links a stmt after the current stmt.  */
-
-void
-tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
-{
-  tree ce;
-  tree next, cur = *i->tp;
-
-  if (mode == TSI_CHAIN_START || mode == TSI_CHAIN_END)
-    abort ();
-  if (mode == TSI_CONTINUE_LINKING)
-    mode = TSI_NEW_STMT;
-
-  /* If this node is empty, we can just add it.  */
-  if (cur == NULL)
-    {
-      *i->tp = t;
-    }
-
-  /* If this node isnt a COMPUND_EXPR, we need to insert a CE node. */
-  else if (TREE_CODE (cur) != COMPOUND_EXPR)
-    {
-      /* Create a new node with the current stmt on the left, and the new
-	 stmt on the right.  */
-      ce = build (COMPOUND_EXPR, void_type_node, cur, t);
-
-      /* Update link to point to this CE node.  */
-      *i->tp = ce;
-
-      /* Change new iterator to point to the new stmt.  */
-      if (mode == TSI_NEW_STMT)
-	i->tp = &TREE_OPERAND (ce, 1);
-    }
-  else
-    {
-      next = TREE_OPERAND (cur, 1);
-
-      /* Create a new node with the same 'next' link as the current one.  */
-      ce = build (COMPOUND_EXPR, void_type_node, t, next);
-
-      /* If the 'next' statement is a COMPOUND_EXPR and was the first
-	 statement of a basic block, we need to adjust the 'head_tree_p'
-	 field of that block because we are about to move the statement one
-	 position down in the CE chain.  */
-      {
-	basic_block bb = bb_for_stmt (next);
-	if (bb && bb->head_tree_p == &TREE_OPERAND (cur, 1))
-	  {
-	    /* We may also need to update end_tree_p.  */
-	    if (bb->head_tree_p == bb->end_tree_p)
-	      bb->end_tree_p = &TREE_OPERAND (ce, 1);
-	    bb->head_tree_p = &TREE_OPERAND (ce, 1);
-	  }
-      }
-
-      /* Make the current one's 'next' link point to our new stmt.  */
-      TREE_OPERAND (cur, 1) = ce;
-
-      /* Update the iterator to the new stmt.  */
-      if (mode == TSI_NEW_STMT)
-	i->tp = &TREE_OPERAND (cur, 1);
-    }
-}
-
-/* Links a chain of statements T before the current stmt.  */
-
-void
-tsi_link_chain_before (tree_stmt_iterator *i, tree t,
-		       enum tsi_iterator_update mode)
-{
-  tree *last;
-
-  if (mode == TSI_NEW_STMT)
-    abort ();
-  if (mode == TSI_CONTINUE_LINKING)
-    mode = TSI_CHAIN_START;
-
-  for (last = &t;
-       TREE_CODE (*last) == COMPOUND_EXPR;
-       last = &TREE_OPERAND (*last, 1))
-    continue;
-
-  /* Build a new CE which points to the current node.  */
-  *last = build (COMPOUND_EXPR, void_type_node, *last, *i->tp);
-
-  /* Make the parent pointer point to this new node.  At this point, the
-     iterator will be pointing to the new node we just inserted.  */
-  *i->tp = t;
-
-  /* Update the iterator to points to the address of the next ptr in our new 
-     node, which is the current stmt again.  */
-  if (mode == TSI_SAME_STMT)
-    i->tp = &TREE_OPERAND (*last, 1);
-  else if (mode == TSI_CHAIN_END)
-    i->tp = last != &t ? last : i->tp;
-}
-
-/* Links a chain of statements T after the current stmt.  */
-
-void
-tsi_link_chain_after (tree_stmt_iterator *i, tree t,
-		      enum tsi_iterator_update mode)
-{
-  tree ce;
-  tree next, *nextp;
-  tree *last;
-  tree cur = *i->tp;
-
-  if (mode == TSI_NEW_STMT)
-    abort ();
-  if (mode == TSI_CONTINUE_LINKING)
-    mode = TSI_CHAIN_END;
-
-  /* If this node is empty, we can just add it.  */
-  if (cur == NULL)
-    {
-      *i->tp = t;
-
-      if (mode == TSI_CHAIN_END)
-	{
-	  cur = t;
-	  last = i->tp;
-	  while (TREE_CODE (cur) == COMPOUND_EXPR)
-	    {
-	      last = &TREE_OPERAND (cur, 1);
-	      cur = *last;
-	    }
-	  i->tp = last;
-	}
-    }
-
-  /* If this node isnt a COMPUND_EXPR, we need to insert a CE node. */
-  else if (TREE_CODE (cur) != COMPOUND_EXPR)
-    {
-      /* Create a new node with the current stmt on the left, and the new
-	 stmt on the right.  */
-      ce = build (COMPOUND_EXPR, void_type_node, cur, t);
-
-      /* Update link to point to this CE node.  */
-      *i->tp = ce;
-
-      /* Change new iterator to point to the new stmt.  */
-      if (mode == TSI_CHAIN_START)
-	i->tp = &TREE_OPERAND (ce, 1);
-      else if (mode == TSI_CHAIN_END)
-	{
-	  cur = ce;
-	  last = i->tp;
-	  while (TREE_CODE (cur) == COMPOUND_EXPR)
-	    {
-	      last = &TREE_OPERAND (cur, 1);
-	      cur = *last;
-	    }
-	  i->tp = last;
-	}
-    }
-  else
-    {
-      for (last = &t;
-	   TREE_CODE (*last) == COMPOUND_EXPR;
-	   last = &TREE_OPERAND (*last, 1))
-	continue;
-
-      nextp = &TREE_OPERAND (cur, 1);
-      next = *nextp;
-
-      /* Create a new node with the same 'next' link as the current one.  */
-      ce = build (COMPOUND_EXPR, void_type_node, *last, next);
-
-      /* If the 'next' statement is a COMPOUND_EXPR and was the first
-	 statement of a basic block, we need to adjust the 'head_tree_p'
-	 field of that block because we are about to move the statement one
-	 position down in the CE chain.  */
-      {
-	basic_block bb = bb_for_stmt (next);
-	if (bb && bb->head_tree_p == nextp)
-	  {
-	    /* We may also need to update end_tree_p.  */
-	    if (bb->head_tree_p == bb->end_tree_p)
-	      bb->end_tree_p = &TREE_OPERAND (ce, 1);
-	    bb->head_tree_p = &TREE_OPERAND (ce, 1);
-	  }
-      }
-
-      *last = ce;
-      TREE_OPERAND (cur, 1) = t;
-
-      /* Update the iterator to the new stmt.  */
-      if (mode == TSI_CHAIN_START)
-	i->tp = nextp;
-      else if (mode == TSI_CHAIN_END)
-	i->tp = (last != &t ? last : nextp);
-    }
-}
-
-/* Remove a stmt from the tree list.  The iterator is updated to point to
-   the next stmt.  */
-
-void
-tsi_delink (tree_stmt_iterator *i)
-{
-  tree cur = *i->tp;
-
-  if (TREE_CODE (cur) == COMPOUND_EXPR)
-    {
-      /* All that is needed here is to change the parent to point to the next 
-	 stmt in the chain.  */
-      *i->tp = TREE_OPERAND (cur, 1);
-    }
-  else
-    {
-      /* This stmt is the last link in the CE chain, but we're screwed because
-         there isn't access to the node itself. the choices are either adding a
-	 NULL link to the right side of the CE node, which is bad, or replacing
-	 this node with an empty statement. Choose the latter for now, and 
-	 make the iterator return NULL, so that no further iterating takes 
-	 place.  */
-      *i->tp = build_empty_stmt ();
-      i->tp = NULL;
-    }
-}
-
-/* Create a new stmt list beginning with this stmt.  The anchor is used mostly
-   to keep the garbage collector from collecting the root node, and to give 
-   the list a place to start.  */
-
-tree_stmt_iterator 
-tsi_new_stmt_list (tree t, tree_stmt_anchor *anchor)
-{
-  tree_stmt_iterator i;
-
-  *anchor = t;
-  i.tp = anchor;
-
-  return i;
-}
-
-/* Return an iterator which begins at this anchor.  */
-
-tree_stmt_iterator
-tsi_stmt_list_head (tree_stmt_anchor anchor)
-{
-  tree_stmt_iterator i;
-
-  if (anchor == EMPTY_ANCHOR)
-    i.tp = NULL;
-  else
-    i.tp = &anchor;
-
-  return i;
-}
-
-/* Return true if the chain of statements starting with T is empty.  */
-
-bool
-body_is_empty (tree t)
-{
-  tree_stmt_iterator i;
-
-  if (IS_EMPTY_STMT (t))
-    return true;
-
-  for (i = tsi_start (&t); !tsi_end_p (i); tsi_next (&i))
-    if (tsi_stmt (i))
-      return false;
-
-  return true;
-}
 bool
 is_essa_node (tree t)
 {
Index: tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.52.2.18
diff -u -p -r1.52.2.18 tree.def
--- tree.def	30 Oct 2003 02:49:41 -0000	1.52.2.18
+++ tree.def	9 Nov 2003 09:11:12 -0000
@@ -901,6 +901,10 @@ DEFTREECODE (CATCH_EXPR, "catch_expr", '
    expanding.  */
 DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", 's', 2)
 
+/* Used to chain children of container statements together.
+   Use the interface in tree-interator.h to access this node.  */
+DEFTREECODE (STATEMENT_LIST, "statement_list", 'x', 0)
+
 /*
 Local variables:
 mode:c
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.122
diff -u -p -r1.342.2.122 tree.h
--- tree.h	5 Nov 2003 13:39:24 -0000	1.342.2.122
+++ tree.h	9 Nov 2003 09:11:15 -0000
@@ -2141,6 +2141,34 @@ struct tree_decl GTY(())
   /* Points to a structure whose details depend on the language in use.  */
   struct lang_decl *lang_specific;
 };
+
+
+/* A STATEMENT_LIST chains statements together in GENERIC and GIMPLE.
+   To reduce overhead, the nodes containing the statements are not trees.
+   This avoids the overhead of tree_common on all linked list elements.
+
+   Use the interface in tree-interator.h to access this node.  */
+
+#define STATEMENT_LIST_HEAD(NODE) \
+  (STATEMENT_LIST_CHECK (NODE)->stmt_list.head)
+#define STATEMENT_LIST_TAIL(NODE) \
+  (STATEMENT_LIST_CHECK (NODE)->stmt_list.tail)
+
+struct tree_statement_list_node
+  GTY ((chain_next ("%h.next"), chain_prev ("%h.prev")))
+{
+  struct tree_statement_list_node *prev;
+  struct tree_statement_list_node *next;
+  tree stmt;
+};
+
+struct tree_statement_list
+  GTY(())
+{
+  struct tree_common common;
+  struct tree_statement_list_node *head;
+  struct tree_statement_list_node *tail;
+};
 
 enum tree_node_structure_enum {
   TS_COMMON,
@@ -2161,6 +2189,7 @@ enum tree_node_structure_enum {
   TS_EUSE_NODE,
   TS_EREF_NODE,
   TS_BLOCK,
+  TS_STATEMENT_LIST,
   LAST_TS_ENUM
 };
 
@@ -2189,7 +2218,8 @@ union tree_node GTY ((ptr_alias (union l
   struct tree_ephi_node GTY ((tag ("TS_EPHI_NODE"))) ephi;
   struct tree_euse_node GTY ((tag ("TS_EUSE_NODE"))) euse;
   struct tree_block GTY ((tag ("TS_BLOCK"))) block;
- };
+  struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
+};
 
 /* Standard named or nameless data types of the C compiler.  */
 
@@ -2821,7 +2851,6 @@ extern tree convert (tree, tree);
 extern unsigned int expr_align (tree);
 extern tree expr_first (tree);
 extern tree expr_last (tree);
-extern int expr_length (tree);
 extern tree size_in_bytes (tree);
 extern HOST_WIDE_INT int_size_in_bytes (tree);
 extern tree bit_position (tree);
@@ -3288,8 +3317,6 @@ extern void init_ttree (void);
 extern void build_common_tree_nodes (int);
 extern void build_common_tree_nodes_2 (int);
 extern tree build_range_type (tree, tree, tree);
-extern tree add_to_compound_expr (tree, tree);
-extern bool body_is_empty (tree);
 
 /* In function.c */
 extern void setjmp_protect_args (void);
@@ -3439,9 +3466,6 @@ extern void expand_start_case_dummy (voi
 extern void declare_nonlocal_label (tree);
 extern int containing_blocks_have_cleanups_or_stack_level (void);
 
-/* In tree-optimize.c.  */
-void optimize_function_tree (tree, tree *);
-
 /* In gimplify.c.  */
 extern void gimplify_function_tree (tree);
 extern const char *get_name (tree);
@@ -3512,7 +3536,7 @@ enum tree_dump_index
   TDI_alias,			/* dump aliasing information.  */
 
   /* Optimization passes.  The ordering and numbering of these phases must
-     be the same as the one in optimize_function_tree().  */
+     be the same as the one in optimize_function_tree.  */
   TDI_ssa_1,
   TDI_thread_jumps,
   TDI_dom_1,


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