diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd86cb8130f73ddd1dc2ff4c3276883365ed76af..7611f01ad35cf8de8ff17f42618709365b315380 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,7 +1,259 @@
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* coretypes.h (gimple_seq, const_gimple_seq): Typedef as gimple.
+	* gimple.h (struct gimple_seq_node_d, struct gimple_seq_d): Remove.
+	(const_gimple_seq_node): Remove.
+	(gimple_seq_node): Typedef as gimple.
+	(struct gimple_statement_base): Add next and prev members,
+	adjust all WORD markers in using structs.
+	(union gimple_statement_d): Link via gsbase.next field for GC and PCH.
+	(gimple_seq_first, gimple_seq_first_stmt, gimple_seq_last,
+	gimple_seq_last_stmt): Adjust as gimple_seq, gimple_seq_node and
+	gimple are the same.
+	(gimple_seq_set_last, gimple_seq_set_first): Don't allocate
+	gimple_seq, adjust.
+	(gimple_init_singleton): New function.
+	(gsi_start_1, gsi_last_1, gsi_end_p, gsi_one_before_end_p): Adjust.
+	(gsi_next, gsi_prev): Adjust, handle prev cyclic list correctly.
+	(gsi_stmt): Adjust.
+	(gsi_stmt_ptr): Remove.
+	(enum gimple_alloc_kind): Remove gimple_alloc_kind_seq member.
+
+	* gimple-iterator.c (update_bb_for_stmts): Take last parameter
+	again, adjust for above changes.
+	(update_call_edge_frequencies): Adjust for above changes.
+	(gsi_insert_seq_nodes_before): Rewrite for new data structure.
+	(gsi_insert_seq_nodes_after): Ditto.
+	(gsi_split_seq_after): Ditto.
+	(gsi_set_stmt): Ditto.
+	(gsi_split_seq_before): Ditto.
+	(gsi_remove): Ditto.
+	(gsi_insert_seq_before_without_update): Don't free sequence.
+	(gsi_insert_seq_after_without_update): Ditto.
+	(gsi_replace): Assert some more invariants.
+	(gsi_insert_before_without_update, gsi_insert_after_without_update):
+	Tidy.
+	(gsi_for_stmt): Don't search for stmt.
+	(gsi_insert_on_edge_immediate): Tidy.
+
+	* gimple.c (gimple_alloc_k): Remove "sequences".
+	(gimple_seq_cache): Remove.
+	(gimple_alloc_stat): Make stmt a singleton sequence.
+	(gimple_seq_alloc, gimple_seq_free): Remove.
+	(gimple_assign_set_rhs_with_ops_1): Ensure new stmt is a singleton.
+	(gimple_copy): Ditto.
+	* gimplify.c (gimplify_cleanup_point_expr): Use gsi_set_stmt,
+	create iterator from correct sequence.
+	* tree-phinodes.c (make_phi_node): Make stmt a singleton.
+
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* gimple.h (gimple_stmt_iterator <seq>): Make it be pointer to
+	gimple_seq.
+	(gimple_seq_set_last, gimple_seq_set_first): Take pointer to
+	sequence, lazily allocate it.
+	(bb_seq_addr): New function.
+	(gsi_start_1): Rename from gsi_start, but take pointer to sequence.
+	(gsi_start): Macro to wrap gsi_start_1 taking pointer of argument.
+	(gsi_none): New function.
+	(gsi_start_bb): Adjust.
+	(gsi_last_1): Rename from gsi_last, but take pointer to sequence.
+	(gsi_last): Macro to wrap gsi_last_1 taking pointer of argument.
+	(gsi_last_bb): Adjust.
+	(gsi_seq): Adjust.
+	* tree-flow-inline.h (phi_nodes_ptr): New function.
+
+	* gimple-iterator.c (gsi_insert_seq_nodes_before): Adjust to 
+	datastructure and interface change.
+	(gsi_insert_seq_before_without_update): Ditto.
+	(gsi_insert_seq_nodes_after): Ditto.
+	(gsi_insert_seq_after_without_update): Ditto.
+	(gsi_split_seq_after): Ditto, don't use gimple_seq_alloc.
+	(gsi_split_seq_before): Ditto.
+	(gsi_start_phis): Adjust.
+	* tree-vect-loop.c (vect_determine_vectorization_factor): Use
+	gsi_none.
+	(vect_transform_loop): Ditto.
+	* gimple.c (gimple_seq_add_stmt, gimple_seq_add_seq,
+	gimple_seq_copy): Don't use gimple_seq_alloc.
+	* gimplify.c (gimple_seq_add_stmt_without_update): Ditto.
+	(gimplify_seq_add_seq): Ditto.
+	* lto-streamer-in.c (make_new_block): Ditto.
+	* tree-cfg.c (create_bb): Ditto.
+	* tree-sra.c (initialize_parameter_reductions): Ditto.
+
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* gimple.h (gimple_seq_first, gimple_seq_first_stmt, gimple_seq_last,
+	gimple_seq_last_stmt, gimple_seq_set_last, gimple_seq_set_first,
+	gimple_seq_empty_p, gimple_seq_alloc_with_stmt, bb_seq,
+	set_bb_seq): Move down to after gimple_statement_d definition.
+
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* gimple-fold.c (gimplify_and_update_call_from_tree): Use
+	gsi_replace_with_seq, instead of inserting itself.
+	* gimple-iterator.c (gsi_replace_with_seq): New function.
+	* tree-ssa-forwprop.c (forward_propagate_comparison): Take
+	iterator instead of statement, advance it.
+	(ssa_forward_propagate_and_combine): Adjust call to above.
+
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* tree-phinodes.c (add_phi_node_to_bb): Tidy, don't use
+	gimple_seq_alloc.
+	* omp-low.c (finalize_task_copyfn): Don't use gimple_seq_alloc.
+	* tree-nested.c (walk_gimple_omp_for): Ditto.
+	* trans-mem.c (lower_transaction): Ditto.
+	* tree-eh.c (do_return_redirection): Ditto.
+	(do_goto_redirection): Ditto.
+	(lower_try_finally_switch): Ditto.
+	* gimplify.c (gimplify_stmt): Ditto.
+	(gimplify_scan_omp_clauses): Ditto.
+	(gimplify_omp_for): Ditto.
+	(gimplify_function_tree): Ditto.
+	* gimple-fold.c (gimplify_and_update_call_from_tree): Ditto.
+	* tree-mudflap.c (mf_decl_cache_locals): Ditto.
+	(mf_build_check_statement_for): Ditto.
+	(mx_register_decls): Ditto.
+	* graphite-sese-to-poly.c (remove_invariant_phi): Ditto,
+	and don't use itertors to append.
+	(insert_stmts): Ditto.
+	(insert_out_of_ssa_copy): Ditto.
+	(insert_out_of_ssa_copy_on_edge): Ditto.
+
+2012-05-02  Michael Matz  <matz@suse.de>
+
+	* gimple.h (gimple_bind_body_ptr): New function.
+	(gimple_bind_body): Use it.
+	(gimple_catch_handler): Use gimple_catch_handler_ptr.
+	(gimple_eh_filter_failure_ptr): New function.
+	(gimple_eh_filter_failure): Use it.
+	(gimple_eh_else_n_body_ptr): New function.
+	(gimple_eh_else_n_body): Use it.
+	(gimple_eh_else_e_body_ptr): New function.
+	(gimple_eh_else_e_body): Use it.
+	(gimple_try_eval_ptr): New function.
+	(gimple_try_eval): Use it.
+	(gimple_try_cleanup_ptr): New function.
+	(gimple_try_cleanup): Use it.
+	(gimple_wce_cleanup_ptr): New function.
+	(gimple_wce_cleanup): Use it.
+	(gimple_omp_body_ptr): New function.
+	(gimple_omp_body): Use it.
+	(gimple_omp_for_pre_body_ptr): New function.
+	(gimple_omp_for_pre_body): Use it.
+	(gimple_transaction_body_ptr): New function.
+	(gimple_transaction_body): Use it.
+	(gsi_split_seq_before): Adjust to return nothing and take pointer
+	to sequence.
+	(gsi_set_stmt): Declare.
+	(gsi_replace_with_seq): Declare.
+	(walk_gimple_seq_mod): Declare.
+	* function.h (struct function <gimple_body>): Use typedef gimple_seq.
+
+	* gimple-iterator.c (gsi_set_stmt): New function.
+	(gsi_split_seq_before): Return new sequence via pointer argument.
+	(gsi_replace): Use gsi_set_stmt.
+
+	* tree-ssa-loop-im.c (move_computations_stmt): First remove
+	then insert stmt.
+	* tree-complex.c (update_complex_components_on_edge): Don't
+	copy gsi.
+	* tree-phinodes.c (resize_phi_node): Don't resize stmt in-place,
+	return new stmt.
+	(reserve_phi_args_for_new_edge): Change call to above,
+	use gsi_set_stmt.
+
+	* omp-low.c (lower_omp): Change prototype to take pointer to
+	sequence.
+	(lower_rec_input_clauses): Use gimple_seq_add_seq instead of
+	iterators.  Adjust call to lower_omp.
+	(lower_lastprivate_clauses): Adjust call to lower_omp.
+	(lower_reduction_clauses): Ditto.
+	(expand_omp_taskreg): Nullify non-cfg body of child_fn.
+	(lower_omp_sections): Don't explicitely count sequence length,
+	nullify lowered bodies earlier, ensure stmts are part of only
+	one sequence, adjust call to lower_omp.
+	(lower_omp_single): Ensure stmts are part of only one sequence,
+	adjust call to lower_omp.
+	(lower_omp_master): Ditto.
+	(lower_omp_ordered): Ditto.
+	(lower_omp_critical): Ditto.
+	(lower_omp_for): Ditto.
+	(lower_omp_taskreg): Ditto, tidy.
+	(lower_omp_1): Adjust calls to lower_omp.
+	(execute_lower_omp): Ditto.
+	(lower_omp): Adjust to take pointer to sequence.
+	(diagnose_sb_2): Use walk_gimple_seq_mod.
+	(diagnose_omp_structured_block_errors): Ditto and set possibly
+	changed function body.
+	* gimple-low.c (lower_function_body): Set function body after
+	it stabilizes.
+	(lower_sequence): Adjust to take pointer to sequence.
+	(lower_omp_directive): Ensure stmt isn't put twice into the
+	sequence, adjust call to lower_sequence.
+	(lower_stmt): Adjust calls to lower_sequence.
+	(lower_gimple_bind): Ditto.
+	(gimple_try_catch_may_fallthru): Call gsi_start with lvalue.
+	* tree-nested.c (walk_body): Take pointer to sequence, use
+	walk_gimple_seq_mod.
+	(walk_function): Adjust call to walk_body, set possibly changed
+	body.
+	(walk_gimple_omp_for): Adjust calls to walk_body.
+	(convert_nonlocal_omp_clauses): Ditto.
+	(convert_nonlocal_reference_stmt): Ditto.
+	(convert_local_omp_clauses): Ditto.
+	(convert_local_reference_stmt): Ditto.
+	(convert_tramp_reference_stmt): Ditto.
+	(convert_gimple_call): Ditto.
+	(convert_nl_goto_reference): Use local iterator copy.
+	* gimple.c (walk_gimple_seq_mod): Renamed from walk_gimple_seq,
+	but taking pointer to sequence, ensure gsi_start is called with
+	callers lvalue.
+	(walk_gimple_seq): New wrapper around walk_gimple_seq_mod,
+	asserting that the sequence head didn't change.
+	(walk_gimple_stmt): Replace all calls to walk_gimple_seq with
+	walk_gimple_seq_mod.
+	* trans-mem.c (lower_transaction): Use walk_gimple_seq_mod.
+	(execute_lower_tm): Ditto, and set possibly changed body.
+	* tree-eh.c (lower_eh_constructs_1): Take pointer to sequence,
+	call gsi_start with that lvalue.
+	(replace_goto_queue_stmt_list): Ditto.
+	(replace_goto_queue_1): Adjust calls to replace_goto_queue_stmt_list.
+	(replace_goto_queue): Ditto.
+	(lower_try_finally_nofallthru): Adjust calls to lower_eh_constructs_1.
+	(lower_try_finally_onedest): Ditto.
+	(lower_try_finally_copy): Ditto.
+	(lower_try_finally_switch): Ditto.
+	(lower_try_finally): Ditto.
+	(lower_eh_filter): Ditto.
+	(lower_eh_must_not_throw): Ditto.
+	(lower_cleanup): Ditto.
+	(lower_eh_constructs_2): Ditto.
+	(lower_catch): Ditto, and ensure gsi_start is called with lvalue.
+	(lower_eh_constructs): Adjust calls to lower_eh_constructs_1, and
+	set possibly changed body.
+	(optimize_double_finally): Call gsi_start with lvalue.
+
+	* tree-cfg.c (make_blocks): Adjust call to gsi_split_seq_before.
+	(gimple_split_block): Ditto.
+	(gimple_merge_blocks): Use gsi_start_phis.
+	(move_stmt_r): Use walk_gimple_seq_mod.
+	* tree-ssa-dse.c (dse_enter_block): Use gsi_last_bb.
+	* cgraphbuild.c (build_cgraph_edges): Use gsi_start_phis.
+	(rebuild_cgraph_edges): Ditto.
+	(cgraph_rebuild_references): Ditto.
+	* ipa-prop.c (ipa_analyze_params_uses): Ditto.
+	* tree-inline.c (copy_phis_for_bb): Ditto.
+	* tree-ssa-dce.c: Ditto.
+
+	* cgraphunit.c (cgraph_analyze_function): Use gimple_has_body_p.
+
 2012-05-02  Kirill Yukhin  <kirill.yukhin@intel.com>
 	    Andi Kleen <ak@linux.intel.com>
 
-	* coretypes (MEMMODEL_MASK): New.
+	* coretypes.h (MEMMODEL_MASK): New.
 	* builtins.c (get_memmodel): Add val. Call target.memmodel_check
 	and return new variable.
 	(expand_builtin_atomic_exchange):  Mask memmodel values.
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index a847980c663ae1b2da270adf64e194b0b44569a3..3abf869684eb9de18d81d3c1646814afb264f3f6 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -348,7 +348,7 @@ build_cgraph_edges (void)
 				      IPA_REF_ADDR, stmt);
 	    }
 	}
-      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
 				       mark_load, mark_store, mark_address);
    }
@@ -440,7 +440,7 @@ rebuild_cgraph_edges (void)
 					 mark_store, mark_address);
 
 	}
-      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
 				       mark_load, mark_store, mark_address);
     }
@@ -474,7 +474,7 @@ cgraph_rebuild_references (void)
 					 mark_store, mark_address);
 
 	}
-      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
 				       mark_load, mark_store, mark_address);
     }
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index ee69afa0e8cd92f5abe7e2118cf168f410ca88fe..cfb94149ed4be6af284bbd3998355f5e14a0d528 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -646,7 +646,7 @@ cgraph_analyze_function (struct cgraph_node *node)
 	 function we lower it, which will require gimplified nested
 	 functions, so we can end up here with an already gimplified
 	 body.  */
-      if (!gimple_body (decl))
+      if (!gimple_has_body_p (decl))
 	gimplify_function_tree (decl);
       dump_function (TDI_generic, decl);
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 0e16b7b6a2f47f87262ba0af4e6b55b8ddceb34e..813b0c349aa476a12c40e2d5fe9739762df3576e 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -72,9 +72,8 @@ struct cl_decoded_option;
 struct cl_option_handlers;
 struct diagnostic_context;
 typedef struct diagnostic_context diagnostic_context;
-struct gimple_seq_d;
-typedef struct gimple_seq_d *gimple_seq;
-typedef const struct gimple_seq_d *const_gimple_seq;
+typedef gimple gimple_seq;
+typedef gimple const_gimple_seq;
 
 /* Address space number for named address space support.  */
 typedef unsigned char addr_space_t;
diff --git a/gcc/function.h b/gcc/function.h
index 5aaba74dc0baec5c38505f6140d88be27afb80a4..34efb3157abe1c349f462c6b6f2deef0a26a4b5b 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -507,7 +507,7 @@ struct GTY(()) function {
   struct control_flow_graph *cfg;
 
   /* GIMPLE body for this function.  */
-  struct gimple_seq_d *gimple_body;
+  gimple_seq gimple_body;
 
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 49505ee94944125a823ec8ad8dead25d3aec7386..90405e67e0fdf57cdf3b0d7696e681b0d7b1ccad 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -549,9 +549,8 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
   tree lhs;
   gimple stmt, new_stmt;
   gimple_stmt_iterator i;
-  gimple_seq stmts = gimple_seq_alloc();
+  gimple_seq stmts = NULL;
   struct gimplify_ctx gctx;
-  gimple last;
   gimple laststore;
   tree reaching_vuse;
 
@@ -620,17 +619,9 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
 
   /* Second iterate over the statements forward, assigning virtual
      operands to their uses.  */
-  last = NULL;
   reaching_vuse = gimple_vuse (stmt);
   for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
     {
-      /* Do not insert the last stmt in this loop but remember it
-         for replacing the original statement.  */
-      if (last)
-	{
-	  gsi_insert_before (si_p, last, GSI_NEW_STMT);
-	  gsi_next (si_p);
-	}
       new_stmt = gsi_stmt (i);
       /* The replacement can expose previously unreferenced variables.  */
       if (gimple_in_ssa_p (cfun))
@@ -642,7 +633,6 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
       gimple_set_modified (new_stmt, true);
       if (gimple_vdef (new_stmt))
 	reaching_vuse = gimple_vdef (new_stmt);
-      last = new_stmt;
     }
 
   /* If the new sequence does not do a store release the virtual
@@ -659,8 +649,8 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
 	}
     }
 
-  /* Finally replace rhe original statement with the last.  */
-  gsi_replace (si_p, last, false);
+  /* Finally replace the original statement with the sequence.  */
+  gsi_replace_with_seq (si_p, stmts, false);
 }
 
 /* Return the string length, maximum string length or maximum value of
diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index e387c16e31a451e79fedb908a165ca43d62c0565..dd78faa323897782d122638d4203e0c2041a6560 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -57,12 +57,17 @@ update_modified_stmts (gimple_seq seq)
    starting at FIRST and LAST.  */
 
 static void
-update_bb_for_stmts (gimple_seq_node first, basic_block bb)
+update_bb_for_stmts (gimple_seq_node first, gimple_seq_node last,
+		     basic_block bb)
 {
   gimple_seq_node n;
 
-  for (n = first; n; n = n->next)
-    gimple_set_bb (n->stmt, bb);
+  for (n = first; n; n = n->gsbase.next)
+    {
+      gimple_set_bb (n, bb);
+      if (n == last)
+	break;
+    }
 }
 
 /* Set the frequencies for the cgraph_edges for each of the calls
@@ -75,8 +80,8 @@ update_call_edge_frequencies (gimple_seq_node first, basic_block bb)
   int bb_freq = 0;
   gimple_seq_node n;
 
-  for (n = first; n ; n = n->next)
-    if (is_gimple_call (n->stmt))
+  for (n = first; n ; n = n->gsbase.next)
+    if (is_gimple_call (n))
       {
 	struct cgraph_edge *e;
 
@@ -89,7 +94,7 @@ update_call_edge_frequencies (gimple_seq_node first, basic_block bb)
 		       (current_function_decl, bb));
 	  }
 
-	e = cgraph_edge (cfun_node, n->stmt);
+	e = cgraph_edge (cfun_node, n);
 	if (e != NULL)
 	  e->frequency = bb_freq;
       }
@@ -113,32 +118,37 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
+  gcc_assert (!cur || cur->gsbase.prev);
+
   if ((bb = gsi_bb (*i)) != NULL)
-    update_bb_for_stmts (first, bb);
+    update_bb_for_stmts (first, last, bb);
 
   /* Link SEQ before CUR in the sequence.  */
   if (cur)
     {
-      first->prev = cur->prev;
-      if (first->prev)
-	first->prev->next = first;
+      first->gsbase.prev = cur->gsbase.prev;
+      if (first->gsbase.prev->gsbase.next)
+	first->gsbase.prev->gsbase.next = first;
       else
 	gimple_seq_set_first (i->seq, first);
-      last->next = cur;
-      cur->prev = last;
+      last->gsbase.next = cur;
+      cur->gsbase.prev = last;
     }
   else
     {
-      gimple_seq_node itlast = gimple_seq_last (i->seq);
+      gimple_seq_node itlast = gimple_seq_last (*i->seq);
 
       /* If CUR is NULL, we link at the end of the sequence (this case happens
 	 when gsi_after_labels is called for a basic block that contains only
 	 labels, so it returns an iterator after the end of the block, and
 	 we need to insert before it; it might be cleaner to add a flag to the
 	 iterator saying whether we are at the start or end of the list).  */
-      first->prev = itlast;
+      last->gsbase.next = NULL;
       if (itlast)
-	itlast->next = first;
+	{
+	  first->gsbase.prev = itlast;
+	  itlast->gsbase.next = first;
+	}
       else
 	gimple_seq_set_first (i->seq, first);
       gimple_seq_set_last (i->seq, last);
@@ -178,15 +188,11 @@ gsi_insert_seq_before_without_update (gimple_stmt_iterator *i, gimple_seq seq,
     return;
 
   /* Don't allow inserting a sequence into itself.  */
-  gcc_assert (seq != i->seq);
+  gcc_assert (seq != *i->seq);
 
   first = gimple_seq_first (seq);
   last = gimple_seq_last (seq);
 
-  gimple_seq_set_first (seq, NULL);
-  gimple_seq_set_last (seq, NULL);
-  gimple_seq_free (seq);
-
   /* Empty sequences need no work.  */
   if (!first || !last)
     {
@@ -230,25 +236,30 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
+  gcc_assert (!cur || cur->gsbase.prev);
+
   /* If the iterator is inside a basic block, we need to update the
      basic block information for all the nodes between FIRST and LAST.  */
   if ((bb = gsi_bb (*i)) != NULL)
-    update_bb_for_stmts (first, bb);
+    update_bb_for_stmts (first, last, bb);
 
   /* Link SEQ after CUR.  */
   if (cur)
     {
-      last->next = cur->next;
-      if (last->next)
-	last->next->prev = last;
+      last->gsbase.next = cur->gsbase.next;
+      if (last->gsbase.next)
+	{
+	  last->gsbase.next->gsbase.prev = last;
+	}
       else
 	gimple_seq_set_last (i->seq, last);
-      first->prev = cur;
-      cur->next = first;
+      first->gsbase.prev = cur;
+      cur->gsbase.next = first;
     }
   else
     {
-      gcc_assert (!gimple_seq_last (i->seq));
+      gcc_assert (!gimple_seq_last (*i->seq));
+      last->gsbase.next = NULL;
       gimple_seq_set_first (i->seq, first);
       gimple_seq_set_last (i->seq, last);
     }
@@ -289,15 +300,11 @@ gsi_insert_seq_after_without_update (gimple_stmt_iterator *i, gimple_seq seq,
     return;
 
   /* Don't allow inserting a sequence into itself.  */
-  gcc_assert (seq != i->seq);
+  gcc_assert (seq != *i->seq);
 
   first = gimple_seq_first (seq);
   last = gimple_seq_last (seq);
 
-  gimple_seq_set_first (seq, NULL);
-  gimple_seq_set_last (seq, NULL);
-  gimple_seq_free (seq);
-
   /* Empty sequences need no work.  */
   if (!first || !last)
     {
@@ -329,59 +336,81 @@ gimple_seq
 gsi_split_seq_after (gimple_stmt_iterator i)
 {
   gimple_seq_node cur, next;
-  gimple_seq old_seq, new_seq;
+  gimple_seq *pold_seq, new_seq;
 
   cur = i.ptr;
 
   /* How can we possibly split after the end, or before the beginning?  */
-  gcc_assert (cur && cur->next);
-  next = cur->next;
+  gcc_assert (cur && cur->gsbase.next);
+  next = cur->gsbase.next;
 
-  old_seq = i.seq;
-  new_seq = gimple_seq_alloc ();
+  pold_seq = i.seq;
 
-  gimple_seq_set_first (new_seq, next);
-  gimple_seq_set_last (new_seq, gimple_seq_last (old_seq));
-  gimple_seq_set_last (old_seq, cur);
-  cur->next = NULL;
-  next->prev = NULL;
+  gimple_seq_set_first (&new_seq, next);
+  gimple_seq_set_last (&new_seq, gimple_seq_last (*pold_seq));
+  gimple_seq_set_last (pold_seq, cur);
+  cur->gsbase.next = NULL;
 
   return new_seq;
 }
 
 
+/* Set the statement to which GSI points to STMT.  This only updates
+   the iterator and the gimple sequence, it doesn't do the bookkeeping
+   of gsi_replace.  */
+
+void
+gsi_set_stmt (gimple_stmt_iterator *gsi, gimple stmt)
+{
+  gimple orig_stmt = gsi_stmt (*gsi);
+  gimple prev, next;
+
+  stmt->gsbase.next = next = orig_stmt->gsbase.next;
+  stmt->gsbase.prev = prev = orig_stmt->gsbase.prev;
+  /* Note how we don't clear next/prev of orig_stmt.  This is so that
+     copies of *GSI our callers might still hold (to orig_stmt)
+     can be advanced as if they too were replaced.  */
+  if (prev->gsbase.next)
+    prev->gsbase.next = stmt;
+  else
+    gimple_seq_set_first (gsi->seq, stmt);
+  if (next)
+    next->gsbase.prev = stmt;
+  else
+    gimple_seq_set_last (gsi->seq, stmt);
+
+  gsi->ptr = stmt;
+}
+
+
 /* Move all statements in the sequence before I to a new sequence.
    Return this new sequence.  I is set to the head of the new list.  */
 
-gimple_seq
-gsi_split_seq_before (gimple_stmt_iterator *i)
+void
+gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 {
   gimple_seq_node cur, prev;
-  gimple_seq old_seq, new_seq;
+  gimple_seq old_seq;
 
   cur = i->ptr;
 
   /* How can we possibly split after the end?  */
   gcc_assert (cur);
-  prev = cur->prev;
+  prev = cur->gsbase.prev;
 
-  old_seq = i->seq;
-  new_seq = gimple_seq_alloc ();
-  i->seq = new_seq;
+  old_seq = *i->seq;
+  if (!prev->gsbase.next)
+    *i->seq = NULL;
+  i->seq = pnew_seq;
 
   /* Set the limits on NEW_SEQ.  */
-  gimple_seq_set_first (new_seq, cur);
-  gimple_seq_set_last (new_seq, gimple_seq_last (old_seq));
+  gimple_seq_set_first (pnew_seq, cur);
+  gimple_seq_set_last (pnew_seq, gimple_seq_last (old_seq));
 
   /* Cut OLD_SEQ before I.  */
-  gimple_seq_set_last (old_seq, prev);
-  cur->prev = NULL;
-  if (prev)
-    prev->next = NULL;
-  else
-    gimple_seq_set_first (old_seq, NULL);
-
-  return new_seq;
+  gimple_seq_set_last (&old_seq, prev);
+  if (prev->gsbase.next)
+    prev->gsbase.next = NULL;
 }
 
 
@@ -416,12 +445,38 @@ gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
   gimple_remove_stmt_histograms (cfun, orig_stmt);
   delink_stmt_imm_use (orig_stmt);
 
-  *gsi_stmt_ptr (gsi) = stmt;
+  gsi_set_stmt (gsi, stmt);
   gimple_set_modified (stmt, true);
   update_modified_stmt (stmt);
 }
 
 
+/* Replace the statement pointed-to by GSI with the sequence SEQ.
+   If UPDATE_EH_INFO is true, the exception handling information of
+   the original statement is moved to the last statement of the new
+   sequence.  If the old statement is an assignment, then so must
+   be the last statement of the new sequence, and they must have the
+   same LHS.  */
+
+void
+gsi_replace_with_seq (gimple_stmt_iterator *gsi, gimple_seq seq,
+		      bool update_eh_info)
+{
+  gimple_stmt_iterator seqi;
+  gimple last;
+  if (gimple_seq_empty_p (seq))
+    {
+      gsi_remove (gsi, true);
+      return;
+    }
+  seqi = gsi_last (seq);
+  last = gsi_stmt (seqi);
+  gsi_remove (&seqi, false);
+  gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+  gsi_replace (gsi, last, update_eh_info);
+}
+
+
 /* Insert statement STMT before the statement pointed-to by iterator I.
    M specifies how to update iterator I after insertion (see enum
    gsi_iterator_update).
@@ -435,12 +490,7 @@ void
 gsi_insert_before_without_update (gimple_stmt_iterator *i, gimple stmt,
                                   enum gsi_iterator_update m)
 {
-  gimple_seq_node n;
-
-  n = ggc_alloc_gimple_seq_node_d ();
-  n->prev = n->next = NULL;
-  n->stmt = stmt;
-  gsi_insert_seq_nodes_before (i, n, n, m);
+  gsi_insert_seq_nodes_before (i, stmt, stmt, m);
 }
 
 /* Insert statement STMT before the statement pointed-to by iterator I.
@@ -470,12 +520,7 @@ void
 gsi_insert_after_without_update (gimple_stmt_iterator *i, gimple stmt,
                                  enum gsi_iterator_update m)
 {
-  gimple_seq_node n;
-
-  n = ggc_alloc_gimple_seq_node_d ();
-  n->prev = n->next = NULL;
-  n->stmt = stmt;
-  gsi_insert_seq_nodes_after (i, n, n, m);
+  gsi_insert_seq_nodes_after (i, stmt, stmt, m);
 }
 
 
@@ -525,19 +570,24 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
 
   /* Update the iterator and re-wire the links in I->SEQ.  */
   cur = i->ptr;
-  next = cur->next;
-  prev = cur->prev;
-
-  if (prev)
-    prev->next = next;
-  else
-    gimple_seq_set_first (i->seq, next);
+  next = cur->gsbase.next;
+  prev = cur->gsbase.prev;
+  /* See gsi_set_stmt for why we don't reset prev/next of STMT.  */
 
   if (next)
-    next->prev = prev;
-  else
+    /* Cur is not last.  */
+    next->gsbase.prev = prev;
+  else if (prev->gsbase.next)
+    /* Cur is last but not first.  */
     gimple_seq_set_last (i->seq, prev);
 
+  if (prev->gsbase.next)
+    /* Cur is not first.  */
+    prev->gsbase.next = next;
+  else
+    /* Cur is first.  */
+    *i->seq = next;
+
   i->ptr = next;
 
   return require_eh_edge_purge;
@@ -557,11 +607,8 @@ gsi_for_stmt (gimple stmt)
   else
     i = gsi_start_bb (bb);
 
-  for (; !gsi_end_p (i); gsi_next (&i))
-    if (gsi_stmt (i) == stmt)
-      return i;
-
-  gcc_unreachable ();
+  i.ptr = stmt;
+  return i;
 }
 
 
@@ -727,7 +774,6 @@ basic_block
 gsi_insert_on_edge_immediate (edge e, gimple stmt)
 {
   gimple_stmt_iterator gsi;
-  struct gimple_seq_node_d node;
   basic_block new_bb = NULL;
   bool ins_after;
 
@@ -735,9 +781,7 @@ gsi_insert_on_edge_immediate (edge e, gimple stmt)
 
   ins_after = gimple_find_edge_insert_loc (e, &gsi, &new_bb);
 
-  node.stmt = stmt;
-  node.prev = node.next = NULL;
-  update_call_edge_frequencies (&node, gsi.bb);
+  update_call_edge_frequencies (stmt, gsi.bb);
 
   if (ins_after)
     gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
@@ -820,5 +864,7 @@ gsi_commit_one_edge_insert (edge e, basic_block *new_bb)
 gimple_stmt_iterator
 gsi_start_phis (basic_block bb)
 {
-  return gsi_start (phi_nodes (bb));
+  gimple_seq *pseq = phi_nodes_ptr (bb);
+  /* XXX check only necessary because ENTRY/EXIT blocks don't have il.gimple */
+  return pseq ? gsi_start_1 (pseq) : gsi_none ();
 }
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 4a1ae0bfa9ad8d755eb7e48f0a4680e704ac81b5..04d4275f75b7ec47676d1f85465c727541a10254 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -112,10 +112,6 @@ lower_function_body (void)
   i = gsi_start (lowered_body);
   lower_gimple_bind (&i, &data);
 
-  /* Once the old body has been lowered, replace it with the new
-     lowered sequence.  */
-  gimple_set_body (current_function_decl, lowered_body);
-
   i = gsi_last (lowered_body);
 
   /* If the function falls off the end, we need a null return statement.
@@ -179,6 +175,10 @@ lower_function_body (void)
       gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
     }
 
+  /* Once the old body has been lowered, replace it with the new
+     lowered sequence.  */
+  gimple_set_body (current_function_decl, lowered_body);
+
   gcc_assert (data.block == DECL_INITIAL (current_function_decl));
   BLOCK_SUBBLOCKS (data.block)
     = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
@@ -305,11 +305,11 @@ gimple_check_call_matching_types (gimple call_stmt, tree callee)
    do it explicitly.  DATA is passed through the recursion.  */
 
 static void
-lower_sequence (gimple_seq seq, struct lower_data *data)
+lower_sequence (gimple_seq *seq, struct lower_data *data)
 {
   gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
+  for (gsi = gsi_start (*seq); !gsi_end_p (gsi); )
     lower_stmt (&gsi, data);
 }
 
@@ -324,11 +324,10 @@ lower_omp_directive (gimple_stmt_iterator *gsi, struct lower_data *data)
 
   stmt = gsi_stmt (*gsi);
 
-  lower_sequence (gimple_omp_body (stmt), data);
-  gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
-  gsi_insert_seq_before (gsi, gimple_omp_body (stmt), GSI_SAME_STMT);
+  lower_sequence (gimple_omp_body_ptr (stmt), data);
+  gsi_insert_seq_after (gsi, gimple_omp_body (stmt), GSI_CONTINUE_LINKING);
   gimple_omp_set_body (stmt, NULL);
-  gsi_remove (gsi, false);
+  gsi_next (gsi);
 }
 
 
@@ -376,10 +375,10 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
     case GIMPLE_TRY:
       {
 	bool try_cannot_fallthru;
-	lower_sequence (gimple_try_eval (stmt), data);
+	lower_sequence (gimple_try_eval_ptr (stmt), data);
 	try_cannot_fallthru = data->cannot_fallthru;
 	data->cannot_fallthru = false;
-	lower_sequence (gimple_try_cleanup (stmt), data);
+	lower_sequence (gimple_try_cleanup_ptr (stmt), data);
 	/* See gimple_stmt_may_fallthru for the rationale.  */
 	if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
 	  {
@@ -392,17 +391,17 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
 
     case GIMPLE_CATCH:
       data->cannot_fallthru = false;
-      lower_sequence (gimple_catch_handler (stmt), data);
+      lower_sequence (gimple_catch_handler_ptr (stmt), data);
       break;
 
     case GIMPLE_EH_FILTER:
       data->cannot_fallthru = false;
-      lower_sequence (gimple_eh_filter_failure (stmt), data);
+      lower_sequence (gimple_eh_filter_failure_ptr (stmt), data);
       break;
 
     case GIMPLE_EH_ELSE:
-      lower_sequence (gimple_eh_else_n_body (stmt), data);
-      lower_sequence (gimple_eh_else_e_body (stmt), data);
+      lower_sequence (gimple_eh_else_n_body_ptr (stmt), data);
+      lower_sequence (gimple_eh_else_e_body_ptr (stmt), data);
       break;
 
     case GIMPLE_NOP:
@@ -456,7 +455,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
       return;
 
     case GIMPLE_TRANSACTION:
-      lower_sequence (gimple_transaction_body (stmt), data);
+      lower_sequence (gimple_transaction_body_ptr (stmt), data);
       break;
 
     default:
@@ -505,7 +504,7 @@ lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data)
     }
 
   record_vars (gimple_bind_vars (stmt));
-  lower_sequence (gimple_bind_body (stmt), data);
+  lower_sequence (gimple_bind_body_ptr (stmt), data);
 
   if (new_block)
     {
@@ -585,7 +584,7 @@ gimple_try_catch_may_fallthru (gimple stmt)
   if (gimple_seq_may_fallthru (gimple_try_eval (stmt)))
     return true;
 
-  i = gsi_start (gimple_try_cleanup (stmt));
+  i = gsi_start (*gimple_try_cleanup_ptr (stmt));
   switch (gimple_code (gsi_stmt (i)))
     {
     case GIMPLE_CATCH:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 95d79dc1e025475febb1e5500ab5bb3677973a0b..e8841ec65ae369d482b1b84dd5ea23bfd15d6a99 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -90,16 +90,11 @@ static const char * const gimple_alloc_kind_names[] = {
     "assignments",
     "phi nodes",
     "conditionals",
-    "sequences",
     "everything else"
 };
 
 #endif /* GATHER_STATISTICS */
 
-/* A cache of gimple_seq objects.  Sequences are created and destroyed
-   fairly often during gimplification.  */
-static GTY ((deletable)) struct gimple_seq_d *gimple_seq_cache;
-
 /* Private API manipulation functions shared only with some
    other files.  */
 extern void gimple_set_stored_syms (gimple, bitmap, bitmap_obstack *);
@@ -154,6 +149,7 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
   /* Do not call gimple_set_modified here as it has other side
      effects and this tuple is still not completely built.  */
   stmt->gsbase.modified = 1;
+  gimple_init_singleton (stmt);
 
   return stmt;
 }
@@ -1201,53 +1197,6 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
 #endif /* ENABLE_GIMPLE_CHECKING */
 
 
-/* Allocate a new GIMPLE sequence in GC memory and return it.  If
-   there are free sequences in GIMPLE_SEQ_CACHE return one of those
-   instead.  */
-
-gimple_seq
-gimple_seq_alloc (void)
-{
-  gimple_seq seq = gimple_seq_cache;
-  if (seq)
-    {
-      gimple_seq_cache = gimple_seq_cache->next_free;
-      gcc_assert (gimple_seq_cache != seq);
-      memset (seq, 0, sizeof (*seq));
-    }
-  else
-    {
-      seq = ggc_alloc_cleared_gimple_seq_d ();
-#ifdef GATHER_STATISTICS
-      gimple_alloc_counts[(int) gimple_alloc_kind_seq]++;
-      gimple_alloc_sizes[(int) gimple_alloc_kind_seq] += sizeof (*seq);
-#endif
-    }
-
-  return seq;
-}
-
-/* Return SEQ to the free pool of GIMPLE sequences.  */
-
-void
-gimple_seq_free (gimple_seq seq)
-{
-  if (seq == NULL)
-    return;
-
-  gcc_assert (gimple_seq_first (seq) == NULL);
-  gcc_assert (gimple_seq_last (seq) == NULL);
-
-  /* If this triggers, it's a sign that the same list is being freed
-     twice.  */
-  gcc_assert (seq != gimple_seq_cache || gimple_seq_cache == NULL);
-
-  /* Add SEQ to the pool of free sequences.  */
-  seq->next_free = gimple_seq_cache;
-  gimple_seq_cache = seq;
-}
-
-
 /* Link gimple statement GS to the end of the sequence *SEQ_P.  If
    *SEQ_P is NULL, a new sequence is allocated.  */
 
@@ -1255,13 +1204,9 @@ void
 gimple_seq_add_stmt (gimple_seq *seq_p, gimple gs)
 {
   gimple_stmt_iterator si;
-
   if (gs == NULL)
     return;
 
-  if (*seq_p == NULL)
-    *seq_p = gimple_seq_alloc ();
-
   si = gsi_last (*seq_p);
   gsi_insert_after (&si, gs, GSI_NEW_STMT);
 }
@@ -1274,13 +1219,9 @@ void
 gimple_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
 {
   gimple_stmt_iterator si;
-
   if (src == NULL)
     return;
 
-  if (*dst_p == NULL)
-    *dst_p = gimple_seq_alloc ();
-
   si = gsi_last (*dst_p);
   gsi_insert_seq_after (&si, src, GSI_NEW_STMT);
 }
@@ -1324,7 +1265,7 @@ gimple_seq
 gimple_seq_copy (gimple_seq src)
 {
   gimple_stmt_iterator gsi;
-  gimple_seq new_seq = gimple_seq_alloc ();
+  gimple_seq new_seq = NULL;
   gimple stmt;
 
   for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -1337,7 +1278,7 @@ gimple_seq_copy (gimple_seq src)
 }
 
 
-/* Walk all the statements in the sequence SEQ calling walk_gimple_stmt
+/* Walk all the statements in the sequence *PSEQ calling walk_gimple_stmt
    on each one.  WI is as in walk_gimple_stmt.
 
    If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
@@ -1349,12 +1290,12 @@ gimple_seq_copy (gimple_seq src)
    Otherwise, all the statements are walked and NULL returned.  */
 
 gimple
-walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
-		 walk_tree_fn callback_op, struct walk_stmt_info *wi)
+walk_gimple_seq_mod (gimple_seq *pseq, walk_stmt_fn callback_stmt,
+		     walk_tree_fn callback_op, struct walk_stmt_info *wi)
 {
   gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
+  for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
     {
       tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
       if (ret)
@@ -1378,6 +1319,20 @@ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
 }
 
 
+/* Like walk_gimple_seq_mod, but ensure that the head of SEQ isn't
+   changed by the callbacks.  */
+
+gimple
+walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
+		 walk_tree_fn callback_op, struct walk_stmt_info *wi)
+{
+  gimple_seq seq2 = seq;
+  gimple ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
+  gcc_assert (seq2 == seq);
+  return ret;
+}
+
+
 /* Helper function for walk_gimple_stmt.  Walk operands of a GIMPLE_ASM.  */
 
 static tree
@@ -1808,51 +1763,51 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
   switch (gimple_code (stmt))
     {
     case GIMPLE_BIND:
-      ret = walk_gimple_seq (gimple_bind_body (stmt), callback_stmt,
-	                     callback_op, wi);
+      ret = walk_gimple_seq_mod (gimple_bind_body_ptr (stmt), callback_stmt,
+				 callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_CATCH:
-      ret = walk_gimple_seq (gimple_catch_handler (stmt), callback_stmt,
-	                     callback_op, wi);
+      ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (stmt), callback_stmt,
+				 callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_EH_FILTER:
-      ret = walk_gimple_seq (gimple_eh_filter_failure (stmt), callback_stmt,
+      ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
 		             callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_EH_ELSE:
-      ret = walk_gimple_seq (gimple_eh_else_n_body (stmt),
+      ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (stmt),
 			     callback_stmt, callback_op, wi);
       if (ret)
 	return wi->callback_result;
-      ret = walk_gimple_seq (gimple_eh_else_e_body (stmt),
+      ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (stmt),
 			     callback_stmt, callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_TRY:
-      ret = walk_gimple_seq (gimple_try_eval (stmt), callback_stmt, callback_op,
+      ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
 	                     wi);
       if (ret)
 	return wi->callback_result;
 
-      ret = walk_gimple_seq (gimple_try_cleanup (stmt), callback_stmt,
+      ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
 	                     callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_OMP_FOR:
-      ret = walk_gimple_seq (gimple_omp_for_pre_body (stmt), callback_stmt,
+      ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
 		             callback_op, wi);
       if (ret)
 	return wi->callback_result;
@@ -1866,21 +1821,21 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
     case GIMPLE_OMP_TASK:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
-      ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt,
+      ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
 			     callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_WITH_CLEANUP_EXPR:
-      ret = walk_gimple_seq (gimple_wce_cleanup (stmt), callback_stmt,
+      ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
 			     callback_op, wi);
       if (ret)
 	return wi->callback_result;
       break;
 
     case GIMPLE_TRANSACTION:
-      ret = walk_gimple_seq (gimple_transaction_body (stmt),
+      ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
 			     callback_stmt, callback_op, wi);
       if (ret)
 	return wi->callback_result;
@@ -2181,6 +2136,7 @@ gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code
       tree lhs = gimple_assign_lhs (stmt);
       gimple new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
       memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
+      gimple_init_singleton (new_stmt);
       gsi_replace (gsi, new_stmt, true);
       stmt = new_stmt;
 
@@ -2270,7 +2226,8 @@ gimple_replace_lhs (gimple stmt, tree nlhs)
 
 /* Return a deep copy of statement STMT.  All the operands from STMT
    are reallocated and copied using unshare_expr.  The DEF, USE, VDEF
-   and VUSE operand arrays are set to empty in the new copy.  */
+   and VUSE operand arrays are set to empty in the new copy.  The new
+   copy isn't part of any sequence.  */
 
 gimple
 gimple_copy (gimple stmt)
@@ -2282,6 +2239,7 @@ gimple_copy (gimple stmt)
 
   /* Shallow copy all the fields from STMT.  */
   memcpy (copy, stmt, gimple_size (code));
+  gimple_init_singleton (copy);
 
   /* If STMT has sub-statements, deep-copy them as well.  */
   if (gimple_has_substatements (stmt))
diff --git a/gcc/gimple.h b/gcc/gimple.h
index e0f8660fba3c6d267ac759f5161b2bb562326aa3..c40d7c3cc4ec7642321f4cbd01f3aa8b3d860158 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -32,9 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 
-struct gimple_seq_node_d;
-typedef struct gimple_seq_node_d *gimple_seq_node;
-typedef const struct gimple_seq_node_d *const_gimple_seq_node;
+typedef gimple gimple_seq_node;
 
 /* For each block, the PHI nodes that need to be rewritten are stored into
    these vectors.  */
@@ -133,130 +131,6 @@ enum plf_mask {
     GF_PLF_2	= 1 << 1
 };
 
-/* A node in a gimple_seq_d.  */
-struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) gimple_seq_node_d {
-  gimple stmt;
-  struct gimple_seq_node_d *prev;
-  struct gimple_seq_node_d *next;
-};
-
-/* A double-linked sequence of gimple statements.  */
-struct GTY ((chain_next ("%h.next_free"))) gimple_seq_d {
-  /* First and last statements in the sequence.  */
-  gimple_seq_node first;
-  gimple_seq_node last;
-
-  /* Sequences are created/destroyed frequently.  To minimize
-     allocation activity, deallocated sequences are kept in a pool of
-     available sequences.  This is the pointer to the next free
-     sequence in the pool.  */
-  gimple_seq next_free;
-};
-
-
-/* Return the first node in GIMPLE sequence S.  */
-
-static inline gimple_seq_node
-gimple_seq_first (const_gimple_seq s)
-{
-  return s ? s->first : NULL;
-}
-
-
-/* Return the first statement in GIMPLE sequence S.  */
-
-static inline gimple
-gimple_seq_first_stmt (const_gimple_seq s)
-{
-  gimple_seq_node n = gimple_seq_first (s);
-  return (n) ? n->stmt : NULL;
-}
-
-
-/* Return the last node in GIMPLE sequence S.  */
-
-static inline gimple_seq_node
-gimple_seq_last (const_gimple_seq s)
-{
-  return s ? s->last : NULL;
-}
-
-
-/* Return the last statement in GIMPLE sequence S.  */
-
-static inline gimple
-gimple_seq_last_stmt (const_gimple_seq s)
-{
-  gimple_seq_node n = gimple_seq_last (s);
-  return (n) ? n->stmt : NULL;
-}
-
-
-/* Set the last node in GIMPLE sequence S to LAST.  */
-
-static inline void
-gimple_seq_set_last (gimple_seq s, gimple_seq_node last)
-{
-  s->last = last;
-}
-
-
-/* Set the first node in GIMPLE sequence S to FIRST.  */
-
-static inline void
-gimple_seq_set_first (gimple_seq s, gimple_seq_node first)
-{
-  s->first = first;
-}
-
-
-/* Return true if GIMPLE sequence S is empty.  */
-
-static inline bool
-gimple_seq_empty_p (const_gimple_seq s)
-{
-  return s == NULL || s->first == NULL;
-}
-
-
-void gimple_seq_add_stmt (gimple_seq *, gimple);
-
-/* Link gimple statement GS to the end of the sequence *SEQ_P.  If
-   *SEQ_P is NULL, a new sequence is allocated.  This function is
-   similar to gimple_seq_add_stmt, but does not scan the operands.
-   During gimplification, we need to manipulate statement sequences
-   before the def/use vectors have been constructed.  */
-void gimple_seq_add_stmt_without_update (gimple_seq *, gimple);
-
-/* Allocate a new sequence and initialize its first element with STMT.  */
-
-static inline gimple_seq
-gimple_seq_alloc_with_stmt (gimple stmt)
-{
-  gimple_seq seq = NULL;
-  gimple_seq_add_stmt (&seq, stmt);
-  return seq;
-}
-
-
-/* Returns the sequence of statements in BB.  */
-
-static inline gimple_seq
-bb_seq (const_basic_block bb)
-{
-  return (!(bb->flags & BB_RTL) && bb->il.gimple) ? bb->il.gimple->seq : NULL;
-}
-
-
-/* Sets the sequence of statements in BB to SEQ.  */
-
-static inline void
-set_bb_seq (basic_block bb, gimple_seq seq)
-{
-  gcc_checking_assert (!(bb->flags & BB_RTL));
-  bb->il.gimple->seq = seq;
-}
-
 /* Iterator object for GIMPLE statement sequences.  */
 
 typedef struct
@@ -268,7 +142,7 @@ typedef struct
      are necessary to handle edge cases such as when statement is
      added to an empty basic block or when the last statement of a
      block/sequence is removed.  */
-  gimple_seq seq;
+  gimple_seq *seq;
   basic_block bb;
 } gimple_stmt_iterator;
 
@@ -332,7 +206,16 @@ struct GTY(()) gimple_statement_base {
      Basic block holding this statement.  */
   struct basic_block_def *bb;
 
-  /* [ WORD 4 ]
+  /* [ WORD 4-5 ]
+     Linked lists of gimple statements.  The next pointers form
+     a NULL terminated list, the prev pointers are a cyclic list.
+     A gimple statement is hence also a double-ended list of
+     statements, with the pointer itself being the first element,
+     and the prev pointer being the last.  */
+  gimple next;
+  gimple GTY((skip)) prev;
+
+  /* [ WORD 6 ]
      Lexical block holding this statement.  */
   tree block;
 };
@@ -342,10 +225,10 @@ struct GTY(()) gimple_statement_base {
 
 struct GTY(()) gimple_statement_with_ops_base
 {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5-6 ]
+  /* [ WORD 7-8 ]
      SSA operand vectors.  NOTE: It should be possible to
      amalgamate these vectors with the operand vector OP.  However,
      the SSA operand vectors are organized differently and contain
@@ -359,10 +242,10 @@ struct GTY(()) gimple_statement_with_ops_base
 
 struct GTY(()) gimple_statement_with_ops
 {
-  /* [ WORD 1-6 ]  */
+  /* [ WORD 1-8 ]  */
   struct gimple_statement_with_ops_base opbase;
 
-  /* [ WORD 7 ]
+  /* [ WORD 9 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -374,10 +257,10 @@ struct GTY(()) gimple_statement_with_ops
 
 struct GTY(()) gimple_statement_with_memory_ops_base
 {
-  /* [ WORD 1-6 ]  */
+  /* [ WORD 1-8 ]  */
   struct gimple_statement_with_ops_base opbase;
 
-  /* [ WORD 7-8 ]
+  /* [ WORD 9-10 ]
      Virtual operands for this statement.  The GC will pick them
      up via the ssa_names array.  */
   tree GTY((skip (""))) vdef;
@@ -389,10 +272,10 @@ struct GTY(()) gimple_statement_with_memory_ops_base
 
 struct GTY(()) gimple_statement_with_memory_ops
 {
-  /* [ WORD 1-8 ]  */
+  /* [ WORD 1-10 ]  */
   struct gimple_statement_with_memory_ops_base membase;
 
-  /* [ WORD 9 ]
+  /* [ WORD 11 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -404,20 +287,20 @@ struct GTY(()) gimple_statement_with_memory_ops
 
 struct GTY(()) gimple_statement_call
 {
-  /* [ WORD 1-8 ]  */
+  /* [ WORD 1-10 ]  */
   struct gimple_statement_with_memory_ops_base membase;
 
-  /* [ WORD 9-12 ]  */
+  /* [ WORD 11-14 ]  */
   struct pt_solution call_used;
   struct pt_solution call_clobbered;
 
-  /* [ WORD 13 ]  */
+  /* [ WORD 15 ]  */
   union GTY ((desc ("%1.membase.opbase.gsbase.subcode & GF_CALL_INTERNAL"))) {
     tree GTY ((tag ("0"))) fntype;
     enum internal_fn GTY ((tag ("GF_CALL_INTERNAL"))) internal_fn;
   } u;
 
-  /* [ WORD 14 ]
+  /* [ WORD 16 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -428,10 +311,10 @@ struct GTY(()) gimple_statement_call
 /* OpenMP statements (#pragma omp).  */
 
 struct GTY(()) gimple_statement_omp {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]  */
+  /* [ WORD 7 ]  */
   gimple_seq body;
 };
 
@@ -439,14 +322,14 @@ struct GTY(()) gimple_statement_omp {
 /* GIMPLE_BIND */
 
 struct GTY(()) gimple_statement_bind {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]
+  /* [ WORD 7 ]
      Variables declared in this scope.  */
   tree vars;
 
-  /* [ WORD 6 ]
+  /* [ WORD 8 ]
      This is different than the BLOCK field in gimple_statement_base,
      which is analogous to TREE_BLOCK (i.e., the lexical block holding
      this statement).  This field is the equivalent of BIND_EXPR_BLOCK
@@ -454,7 +337,7 @@ struct GTY(()) gimple_statement_bind {
      gimple-low.c.  */
   tree block;
 
-  /* [ WORD 7 ]  */
+  /* [ WORD 9 ]  */
   gimple_seq body;
 };
 
@@ -462,13 +345,13 @@ struct GTY(()) gimple_statement_bind {
 /* GIMPLE_CATCH */
 
 struct GTY(()) gimple_statement_catch {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]  */
+  /* [ WORD 7 ]  */
   tree types;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 8 ]  */
   gimple_seq handler;
 };
 
@@ -476,14 +359,14 @@ struct GTY(()) gimple_statement_catch {
 /* GIMPLE_EH_FILTER */
 
 struct GTY(()) gimple_statement_eh_filter {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]
+  /* [ WORD 7 ]
      Filter types.  */
   tree types;
 
-  /* [ WORD 6 ]
+  /* [ WORD 8 ]
      Failure actions.  */
   gimple_seq failure;
 };
@@ -491,37 +374,37 @@ struct GTY(()) gimple_statement_eh_filter {
 /* GIMPLE_EH_ELSE */
 
 struct GTY(()) gimple_statement_eh_else {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5,6 ] */
+  /* [ WORD 7,8 ] */
   gimple_seq n_body, e_body;
 };
 
 /* GIMPLE_EH_MUST_NOT_THROW */
 
 struct GTY(()) gimple_statement_eh_mnt {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ] Abort function decl.  */
+  /* [ WORD 7 ] Abort function decl.  */
   tree fndecl;
 };
 
 /* GIMPLE_PHI */
 
 struct GTY(()) gimple_statement_phi {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]  */
+  /* [ WORD 7 ]  */
   unsigned capacity;
   unsigned nargs;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 8 ]  */
   tree result;
 
-  /* [ WORD 7 ]  */
+  /* [ WORD 9 ]  */
   struct phi_arg_d GTY ((length ("%h.nargs"))) args[1];
 };
 
@@ -530,10 +413,10 @@ struct GTY(()) gimple_statement_phi {
 
 struct GTY(()) gimple_statement_eh_ctrl
 {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]
+  /* [ WORD 7 ]
      Exception region number.  */
   int region;
 };
@@ -542,14 +425,14 @@ struct GTY(()) gimple_statement_eh_ctrl
 /* GIMPLE_TRY */
 
 struct GTY(()) gimple_statement_try {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]
+  /* [ WORD 7 ]
      Expression to evaluate.  */
   gimple_seq eval;
 
-  /* [ WORD 6 ]
+  /* [ WORD 8 ]
      Cleanup expression.  */
   gimple_seq cleanup;
 };
@@ -571,7 +454,7 @@ enum gimple_try_flags
 /* GIMPLE_WITH_CLEANUP_EXPR */
 
 struct GTY(()) gimple_statement_wce {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
   /* Subcode: CLEANUP_EH_ONLY.  True if the cleanup should only be
@@ -579,7 +462,7 @@ struct GTY(()) gimple_statement_wce {
 	      scope.  This flag is analogous to the CLEANUP_EH_ONLY flag
 	      in TARGET_EXPRs.  */
 
-  /* [ WORD 5 ]
+  /* [ WORD 7 ]
      Cleanup expression.  */
   gimple_seq cleanup;
 };
@@ -589,21 +472,21 @@ struct GTY(()) gimple_statement_wce {
 
 struct GTY(()) gimple_statement_asm
 {
-  /* [ WORD 1-8 ]  */
+  /* [ WORD 1-10 ]  */
   struct gimple_statement_with_memory_ops_base membase;
 
-  /* [ WORD 9 ]
+  /* [ WORD 11 ]
      __asm__ statement.  */
   const char *string;
 
-  /* [ WORD 10 ]
+  /* [ WORD 12 ]
        Number of inputs, outputs, clobbers, labels.  */
   unsigned char ni;
   unsigned char no;
   unsigned char nc;
   unsigned char nl;
 
-  /* [ WORD 11 ]
+  /* [ WORD 13 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
@@ -613,10 +496,10 @@ struct GTY(()) gimple_statement_asm
 /* GIMPLE_OMP_CRITICAL */
 
 struct GTY(()) gimple_statement_omp_critical {
-  /* [ WORD 1-5 ]  */
+  /* [ WORD 1-7 ]  */
   struct gimple_statement_omp omp;
 
-  /* [ WORD 6 ]
+  /* [ WORD 8 ]
      Critical section name.  */
   tree name;
 };
@@ -642,20 +525,20 @@ struct GTY(()) gimple_omp_for_iter {
 /* GIMPLE_OMP_FOR */
 
 struct GTY(()) gimple_statement_omp_for {
-  /* [ WORD 1-5 ]  */
+  /* [ WORD 1-7 ]  */
   struct gimple_statement_omp omp;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 8 ]  */
   tree clauses;
 
-  /* [ WORD 7 ]
+  /* [ WORD 9 ]
      Number of elements in iter array.  */
   size_t collapse;
 
-  /* [ WORD 8 ]  */
+  /* [ WORD 10 ]  */
   struct gimple_omp_for_iter * GTY((length ("%h.collapse"))) iter;
 
-  /* [ WORD 9 ]
+  /* [ WORD 11 ]
      Pre-body evaluated before the loop body begins.  */
   gimple_seq pre_body;
 };
@@ -664,18 +547,18 @@ struct GTY(()) gimple_statement_omp_for {
 /* GIMPLE_OMP_PARALLEL */
 
 struct GTY(()) gimple_statement_omp_parallel {
-  /* [ WORD 1-5 ]  */
+  /* [ WORD 1-7 ]  */
   struct gimple_statement_omp omp;
 
-  /* [ WORD 6 ]
+  /* [ WORD 8 ]
      Clauses.  */
   tree clauses;
 
-  /* [ WORD 7 ]
+  /* [ WORD 9 ]
      Child function holding the body of the parallel region.  */
   tree child_fn;
 
-  /* [ WORD 8 ]
+  /* [ WORD 10 ]
      Shared data argument.  */
   tree data_arg;
 };
@@ -684,14 +567,14 @@ struct GTY(()) gimple_statement_omp_parallel {
 /* GIMPLE_OMP_TASK */
 
 struct GTY(()) gimple_statement_omp_task {
-  /* [ WORD 1-8 ]  */
+  /* [ WORD 1-10 ]  */
   struct gimple_statement_omp_parallel par;
 
-  /* [ WORD 9 ]
+  /* [ WORD 11 ]
      Child function holding firstprivate initialization if needed.  */
   tree copy_fn;
 
-  /* [ WORD 10-11 ]
+  /* [ WORD 12-13 ]
      Size and alignment in bytes of the argument data block.  */
   tree arg_size;
   tree arg_align;
@@ -705,13 +588,13 @@ struct GTY(()) gimple_statement_omp_task {
 /* GIMPLE_OMP_SECTIONS */
 
 struct GTY(()) gimple_statement_omp_sections {
-  /* [ WORD 1-5 ]  */
+  /* [ WORD 1-7 ]  */
   struct gimple_statement_omp omp;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 8 ]  */
   tree clauses;
 
-  /* [ WORD 7 ]
+  /* [ WORD 9 ]
      The control variable used for deciding which of the sections to
      execute.  */
   tree control;
@@ -723,23 +606,23 @@ struct GTY(()) gimple_statement_omp_sections {
          do not need the body field.  */
 
 struct GTY(()) gimple_statement_omp_continue {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]  */
+  /* [ WORD 7 ]  */
   tree control_def;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 8 ]  */
   tree control_use;
 };
 
 /* GIMPLE_OMP_SINGLE */
 
 struct GTY(()) gimple_statement_omp_single {
-  /* [ WORD 1-5 ]  */
+  /* [ WORD 1-7 ]  */
   struct gimple_statement_omp omp;
 
-  /* [ WORD 6 ]  */
+  /* [ WORD 7 ]  */
   tree clauses;
 };
 
@@ -749,10 +632,10 @@ struct GTY(()) gimple_statement_omp_single {
    contains a sequence, which we don't need here.  */
 
 struct GTY(()) gimple_statement_omp_atomic_load {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5-6 ]  */
+  /* [ WORD 7-8 ]  */
   tree rhs, lhs;
 };
 
@@ -760,10 +643,10 @@ struct GTY(()) gimple_statement_omp_atomic_load {
    See note on GIMPLE_OMP_ATOMIC_LOAD.  */
 
 struct GTY(()) gimple_statement_omp_atomic_store {
-  /* [ WORD 1-4 ]  */
+  /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
-  /* [ WORD 5 ]  */
+  /* [ WORD 7 ]  */
   tree val;
 };
 
@@ -815,7 +698,8 @@ enum gimple_statement_structure_enum {
 /* Define the overall contents of a gimple tuple.  It may be any of the
    structures declared above for various types of tuples.  */
 
-union GTY ((desc ("gimple_statement_structure (&%h)"), variable_size)) gimple_statement_d {
+union GTY ((desc ("gimple_statement_structure (&%h)"),
+	    chain_next ("%h.gsbase.next"), variable_size)) gimple_statement_d {
   struct gimple_statement_base GTY ((tag ("GSS_BASE"))) gsbase;
   struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) gsops;
   struct gimple_statement_with_memory_ops_base GTY ((tag ("GSS_WITH_MEM_OPS_BASE"))) gsmembase;
@@ -1136,6 +1020,115 @@ extern tree tree_ssa_strip_useless_type_conversions (tree);
 extern bool useless_type_conversion_p (tree, tree);
 extern bool types_compatible_p (tree, tree);
 
+/* Return the first node in GIMPLE sequence S.  */
+
+static inline gimple_seq_node
+gimple_seq_first (const_gimple_seq s)
+{
+  return s;
+}
+
+
+/* Return the first statement in GIMPLE sequence S.  */
+
+static inline gimple
+gimple_seq_first_stmt (const_gimple_seq s)
+{
+  gimple_seq_node n = gimple_seq_first (s);
+  return n;
+}
+
+
+/* Return the last node in GIMPLE sequence S.  */
+
+static inline gimple_seq_node
+gimple_seq_last (const_gimple_seq s)
+{
+  return s ? s->gsbase.prev : NULL;
+}
+
+
+/* Return the last statement in GIMPLE sequence S.  */
+
+static inline gimple
+gimple_seq_last_stmt (const_gimple_seq s)
+{
+  gimple_seq_node n = gimple_seq_last (s);
+  return n;
+}
+
+
+/* Set the last node in GIMPLE sequence *PS to LAST.  */
+
+static inline void
+gimple_seq_set_last (gimple_seq *ps, gimple_seq_node last)
+{
+  (*ps)->gsbase.prev = last;
+}
+
+
+/* Set the first node in GIMPLE sequence *PS to FIRST.  */
+
+static inline void
+gimple_seq_set_first (gimple_seq *ps, gimple_seq_node first)
+{
+  *ps = first;
+}
+
+
+/* Return true if GIMPLE sequence S is empty.  */
+
+static inline bool
+gimple_seq_empty_p (const_gimple_seq s)
+{
+  return s == NULL;
+}
+
+
+void gimple_seq_add_stmt (gimple_seq *, gimple);
+
+/* Link gimple statement GS to the end of the sequence *SEQ_P.  If
+   *SEQ_P is NULL, a new sequence is allocated.  This function is
+   similar to gimple_seq_add_stmt, but does not scan the operands.
+   During gimplification, we need to manipulate statement sequences
+   before the def/use vectors have been constructed.  */
+void gimple_seq_add_stmt_without_update (gimple_seq *, gimple);
+
+/* Allocate a new sequence and initialize its first element with STMT.  */
+
+static inline gimple_seq
+gimple_seq_alloc_with_stmt (gimple stmt)
+{
+  gimple_seq seq = NULL;
+  gimple_seq_add_stmt (&seq, stmt);
+  return seq;
+}
+
+
+/* Returns the sequence of statements in BB.  */
+
+static inline gimple_seq
+bb_seq (const_basic_block bb)
+{
+  return (!(bb->flags & BB_RTL) && bb->il.gimple) ? bb->il.gimple->seq : NULL;
+}
+
+static inline gimple_seq *
+bb_seq_addr (const_basic_block bb)
+{
+  return (!(bb->flags & BB_RTL) && bb->il.gimple) ? &bb->il.gimple->seq : NULL;
+}
+
+/* Sets the sequence of statements in BB to SEQ.  */
+
+static inline void
+set_bb_seq (basic_block bb, gimple_seq seq)
+{
+  gcc_checking_assert (!(bb->flags & BB_RTL));
+  bb->il.gimple->seq = seq;
+}
+
+
 /* Return the code for GIMPLE statement G.  */
 
 static inline enum gimple_code
@@ -1358,6 +1351,16 @@ gimple_uid (const_gimple g)
 }
 
 
+/* Make statement G a singleton sequence.  */
+
+static inline void
+gimple_init_singleton (gimple g)
+{
+  g->gsbase.next = NULL;
+  g->gsbase.prev = g;
+}
+
+
 /* Return true if GIMPLE statement G has register or memory operands.  */
 
 static inline bool
@@ -2819,13 +2822,19 @@ gimple_bind_append_vars (gimple gs, tree vars)
 }
 
 
+static inline gimple_seq *
+gimple_bind_body_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_BIND);
+  return &gs->gimple_bind.body;
+}
+
 /* Return the GIMPLE sequence contained in the GIMPLE_BIND statement GS.  */
 
 static inline gimple_seq
 gimple_bind_body (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return gs->gimple_bind.body;
+  return *gimple_bind_body_ptr (gs);
 }
 
 
@@ -3108,17 +3117,6 @@ gimple_catch_types_ptr (gimple gs)
 }
 
 
-/* Return the GIMPLE sequence representing the body of the handler of
-   GIMPLE_CATCH statement GS.  */
-
-static inline gimple_seq
-gimple_catch_handler (gimple gs)
-{
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return gs->gimple_catch.handler;
-}
-
-
 /* Return a pointer to the GIMPLE sequence representing the body of
    the handler of GIMPLE_CATCH statement GS.  */
 
@@ -3130,6 +3128,16 @@ gimple_catch_handler_ptr (gimple gs)
 }
 
 
+/* Return the GIMPLE sequence representing the body of the handler of
+   GIMPLE_CATCH statement GS.  */
+
+static inline gimple_seq
+gimple_catch_handler (gimple gs)
+{
+  return *gimple_catch_handler_ptr (gs);
+}
+
+
 /* Set T to be the set of types handled by GIMPLE_CATCH GS.  */
 
 static inline void
@@ -3171,14 +3179,24 @@ gimple_eh_filter_types_ptr (gimple gs)
 }
 
 
+/* Return a pointer to the sequence of statement to execute when
+   GIMPLE_EH_FILTER statement fails.  */
+
+static inline gimple_seq *
+gimple_eh_filter_failure_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
+  return &gs->gimple_eh_filter.failure;
+}
+
+
 /* Return the sequence of statement to execute when GIMPLE_EH_FILTER
    statement fails.  */
 
 static inline gimple_seq
 gimple_eh_filter_failure (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return gs->gimple_eh_filter.failure;
+  return *gimple_eh_filter_failure_ptr (gs);
 }
 
 
@@ -3222,18 +3240,30 @@ gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
 
 /* GIMPLE_EH_ELSE accessors.  */
 
+static inline gimple_seq *
+gimple_eh_else_n_body_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  return &gs->gimple_eh_else.n_body;
+}
+
 static inline gimple_seq
 gimple_eh_else_n_body (gimple gs)
+{
+  return *gimple_eh_else_n_body_ptr (gs);
+}
+
+static inline gimple_seq *
+gimple_eh_else_e_body_ptr (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return gs->gimple_eh_else.n_body;
+  return &gs->gimple_eh_else.e_body;
 }
 
 static inline gimple_seq
 gimple_eh_else_e_body (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return gs->gimple_eh_else.e_body;
+  return *gimple_eh_else_e_body_ptr (gs);
 }
 
 static inline void
@@ -3286,13 +3316,34 @@ gimple_try_catch_is_cleanup (const_gimple gs)
 }
 
 
+/* Return a pointer to the sequence of statements used as the
+   body for GIMPLE_TRY GS.  */
+
+static inline gimple_seq *
+gimple_try_eval_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRY);
+  return &gs->gimple_try.eval;
+}
+
+
 /* Return the sequence of statements used as the body for GIMPLE_TRY GS.  */
 
 static inline gimple_seq
 gimple_try_eval (gimple gs)
+{
+  return *gimple_try_eval_ptr (gs);
+}
+
+
+/* Return a pointer to the sequence of statements used as the cleanup body for
+   GIMPLE_TRY GS.  */
+
+static inline gimple_seq *
+gimple_try_cleanup_ptr (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return gs->gimple_try.eval;
+  return &gs->gimple_try.cleanup;
 }
 
 
@@ -3302,8 +3353,7 @@ gimple_try_eval (gimple gs)
 static inline gimple_seq
 gimple_try_cleanup (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return gs->gimple_try.cleanup;
+  return *gimple_try_cleanup_ptr (gs);
 }
 
 
@@ -3342,13 +3392,22 @@ gimple_try_set_cleanup (gimple gs, gimple_seq cleanup)
 }
 
 
+/* Return a pointer to the cleanup sequence for cleanup statement GS.  */
+
+static inline gimple_seq *
+gimple_wce_cleanup_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
+  return &gs->gimple_wce.cleanup;
+}
+
+
 /* Return the cleanup sequence for cleanup statement GS.  */
 
 static inline gimple_seq
 gimple_wce_cleanup (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  return gs->gimple_wce.cleanup;
+  return *gimple_wce_cleanup_ptr (gs);
 }
 
 
@@ -3747,12 +3806,20 @@ gimple_debug_source_bind_set_value (gimple dbg, tree value)
   gimple_set_op (dbg, 1, value);
 }
 
+/* Return a pointer to the body for the OMP statement GS.  */
+
+static inline gimple_seq *
+gimple_omp_body_ptr (gimple gs)
+{
+  return &gs->omp.body;
+}
+
 /* Return the body for the OMP statement GS.  */
 
 static inline gimple_seq
 gimple_omp_body (gimple gs)
 {
-  return gs->omp.body;
+  return *gimple_omp_body_ptr (gs);
 }
 
 /* Set BODY to be the body for the OMP statement GS.  */
@@ -3966,14 +4033,24 @@ gimple_omp_for_set_incr (gimple gs, size_t i, tree incr)
 }
 
 
+/* Return a pointer to the sequence of statements to execute before the OMP_FOR
+   statement GS starts.  */
+
+static inline gimple_seq *
+gimple_omp_for_pre_body_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+  return &gs->gimple_omp_for.pre_body;
+}
+
+
 /* Return the sequence of statements to execute before the OMP_FOR
    statement GS starts.  */
 
 static inline gimple_seq
 gimple_omp_for_pre_body (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return gs->gimple_omp_for.pre_body;
+  return *gimple_omp_for_pre_body_ptr (gs);
 }
 
 
@@ -4627,13 +4704,21 @@ gimple_omp_continue_set_control_use (gimple g, tree use)
   g->gimple_omp_continue.control_use = use;
 }
 
+/* Return a pointer to the body for the GIMPLE_TRANSACTION statement GS.  */
+
+static inline gimple_seq *
+gimple_transaction_body_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return &gs->gimple_transaction.body;
+}
+
 /* Return the body for the GIMPLE_TRANSACTION statement GS.  */
 
 static inline gimple_seq
 gimple_transaction_body (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->gimple_transaction.body;
+  return *gimple_transaction_body_ptr (gs);
 }
 
 /* Return the label associated with a GIMPLE_TRANSACTION.  */
@@ -4858,17 +4943,28 @@ is_gimple_reg_type (tree type)
 /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
 
 static inline gimple_stmt_iterator
-gsi_start (gimple_seq seq)
+gsi_start_1 (gimple_seq *seq)
 {
   gimple_stmt_iterator i;
 
-  i.ptr = gimple_seq_first (seq);
+  i.ptr = gimple_seq_first (*seq);
   i.seq = seq;
-  i.bb = (i.ptr && i.ptr->stmt) ? gimple_bb (i.ptr->stmt) : NULL;
+  i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
 
   return i;
 }
 
+#define gsi_start(x) gsi_start_1(&(x))
+
+static inline gimple_stmt_iterator
+gsi_none (void)
+{
+  gimple_stmt_iterator i;
+  i.ptr = NULL;
+  i.seq = NULL;
+  i.bb = NULL;
+  return i;
+}
 
 /* Return a new iterator pointing to the first statement in basic block BB.  */
 
@@ -4876,12 +4972,23 @@ static inline gimple_stmt_iterator
 gsi_start_bb (basic_block bb)
 {
   gimple_stmt_iterator i;
-  gimple_seq seq;
+  gimple_seq *seq;
 
-  seq = bb_seq (bb);
-  i.ptr = gimple_seq_first (seq);
-  i.seq = seq;
-  i.bb = bb;
+  seq = bb_seq_addr (bb);
+  if (!seq)
+    /* XXX Only necessary because of ENTRY/EXIT block which don't have
+       il.gimple */
+    {
+      i.ptr = NULL;
+      i.seq = NULL;
+      i.bb = NULL;
+    }
+  else
+    {
+      i.ptr = gimple_seq_first (*seq);
+      i.seq = seq;
+      i.bb = bb;
+    }
 
   return i;
 }
@@ -4890,17 +4997,18 @@ gsi_start_bb (basic_block bb)
 /* Return a new iterator initially pointing to GIMPLE_SEQ's last statement.  */
 
 static inline gimple_stmt_iterator
-gsi_last (gimple_seq seq)
+gsi_last_1 (gimple_seq *seq)
 {
   gimple_stmt_iterator i;
 
-  i.ptr = gimple_seq_last (seq);
+  i.ptr = gimple_seq_last (*seq);
   i.seq = seq;
-  i.bb = (i.ptr && i.ptr->stmt) ? gimple_bb (i.ptr->stmt) : NULL;
+  i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
 
   return i;
 }
 
+#define gsi_last(x) gsi_last_1(&(x))
 
 /* Return a new iterator pointing to the last statement in basic block BB.  */
 
@@ -4908,12 +5016,23 @@ static inline gimple_stmt_iterator
 gsi_last_bb (basic_block bb)
 {
   gimple_stmt_iterator i;
-  gimple_seq seq;
+  gimple_seq *seq;
 
-  seq = bb_seq (bb);
-  i.ptr = gimple_seq_last (seq);
-  i.seq = seq;
-  i.bb = bb;
+  seq = bb_seq_addr (bb);
+  if (!seq)
+    /* XXX Only necessary because of ENTRY/EXIT block which don't have
+       il.gimple */
+    {
+      i.ptr = NULL;
+      i.seq = NULL;
+      i.bb = NULL;
+    }
+  else
+    {
+      i.ptr = gimple_seq_last (*seq);
+      i.seq = seq;
+      i.bb = bb;
+    }
 
   return i;
 }
@@ -4933,7 +5052,7 @@ gsi_end_p (gimple_stmt_iterator i)
 static inline bool
 gsi_one_before_end_p (gimple_stmt_iterator i)
 {
-  return i.ptr != NULL && i.ptr->next == NULL;
+  return i.ptr != NULL && i.ptr->gsbase.next == NULL;
 }
 
 
@@ -4942,7 +5061,7 @@ gsi_one_before_end_p (gimple_stmt_iterator i)
 static inline void
 gsi_next (gimple_stmt_iterator *i)
 {
-  i->ptr = i->ptr->next;
+  i->ptr = i->ptr->gsbase.next;
 }
 
 /* Advance the iterator to the previous gimple statement.  */
@@ -4950,7 +5069,11 @@ gsi_next (gimple_stmt_iterator *i)
 static inline void
 gsi_prev (gimple_stmt_iterator *i)
 {
-  i->ptr = i->ptr->prev;
+  gimple prev = i->ptr->gsbase.prev;
+  if (prev->gsbase.next)
+    i->ptr = prev;
+  else
+    i->ptr = NULL;
 }
 
 /* Return the current stmt.  */
@@ -4958,7 +5081,7 @@ gsi_prev (gimple_stmt_iterator *i)
 static inline gimple
 gsi_stmt (gimple_stmt_iterator i)
 {
-  return i.ptr->stmt;
+  return i.ptr;
 }
 
 /* Return a block statement iterator that points to the first non-label
@@ -5027,18 +5150,6 @@ gsi_last_nondebug_bb (basic_block bb)
   return i;
 }
 
-/* Return a pointer to the current stmt.
-
-  NOTE: You may want to use gsi_replace on the iterator itself,
-  as this performs additional bookkeeping that will not be done
-  if you simply assign through a pointer returned by gsi_stmt_ptr.  */
-
-static inline gimple *
-gsi_stmt_ptr (gimple_stmt_iterator *i)
-{
-  return &i->ptr->stmt;
-}
-
 
 /* Return the basic block associated with this iterator.  */
 
@@ -5054,7 +5165,7 @@ gsi_bb (gimple_stmt_iterator i)
 static inline gimple_seq
 gsi_seq (gimple_stmt_iterator i)
 {
-  return i.seq;
+  return *i.seq;
 }
 
 
@@ -5071,8 +5182,10 @@ enum gsi_iterator_update
 /* In gimple-iterator.c  */
 gimple_stmt_iterator gsi_start_phis (basic_block);
 gimple_seq gsi_split_seq_after (gimple_stmt_iterator);
-gimple_seq gsi_split_seq_before (gimple_stmt_iterator *);
+void gsi_split_seq_before (gimple_stmt_iterator *, gimple_seq *);
+void gsi_set_stmt (gimple_stmt_iterator *, gimple);
 void gsi_replace (gimple_stmt_iterator *, gimple, bool);
+void gsi_replace_with_seq (gimple_stmt_iterator *, gimple_seq, bool);
 void gsi_insert_before (gimple_stmt_iterator *, gimple,
 			enum gsi_iterator_update);
 void gsi_insert_before_without_update (gimple_stmt_iterator *, gimple,
@@ -5167,6 +5280,8 @@ typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *,
 
 gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
 		        struct walk_stmt_info *);
+gimple walk_gimple_seq_mod (gimple_seq *, walk_stmt_fn, walk_tree_fn,
+			    struct walk_stmt_info *);
 tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn, walk_tree_fn,
 		       struct walk_stmt_info *);
 tree walk_gimple_op (gimple, walk_tree_fn, struct walk_stmt_info *);
@@ -5179,7 +5294,6 @@ enum gimple_alloc_kind
   gimple_alloc_kind_assign,	/* Assignments.  */
   gimple_alloc_kind_phi,	/* PHI nodes.  */
   gimple_alloc_kind_cond,	/* Conditionals.  */
-  gimple_alloc_kind_seq,	/* Sequences.  */
   gimple_alloc_kind_rest,	/* Everything else.  */
   gimple_alloc_kind_all
 };
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index c021fa1a38672c5b87ffece51a67d40bc4aa2516..d7cbc2489a1b00139f415cdae873892e6101d8f0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -169,11 +169,7 @@ gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
   if (gs == NULL)
     return;
 
-  if (*seq_p == NULL)
-    *seq_p = gimple_seq_alloc ();
-
   si = gsi_last (*seq_p);
-
   gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
 }
 
@@ -200,9 +196,6 @@ gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
   if (src == NULL)
     return;
 
-  if (*dst_p == NULL)
-    *dst_p = gimple_seq_alloc ();
-
   si = gsi_last (*dst_p);
   gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
 }
@@ -5467,8 +5460,8 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
 	      gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
               /* Do not use gsi_replace here, as it may scan operands.
                  We want to do a simple structural modification only.  */
-              *gsi_stmt_ptr (&iter) = gtry;
-	      iter = gsi_start (seq);
+	      gsi_set_stmt (&iter, gtry);
+	      iter = gsi_start (gtry->gimple_try.eval);
 	    }
 	}
       else
@@ -5650,9 +5643,6 @@ gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
 {
   gimple_seq_node last;
 
-  if (!*seq_p)
-    *seq_p = gimple_seq_alloc ();
-
   last = gimple_seq_last (*seq_p);
   gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
   return last != gimple_seq_last (*seq_p);
@@ -6149,8 +6139,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
 	      gimplify_omp_ctxp = ctx;
 	      push_gimplify_context (&gctx);
 
-	      OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = gimple_seq_alloc ();
-	      OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = gimple_seq_alloc ();
+	      OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+	      OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
 
 	      gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
 		  		&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
@@ -6486,7 +6476,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
   gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
   OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
 
-  for_body = gimple_seq_alloc ();
+  for_body = NULL;
   gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
 	      == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
   gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
@@ -8322,7 +8312,7 @@ gimplify_function_tree (tree fndecl)
 
   /* The tree body of the function is no longer needed, replace it
      with the new GIMPLE body.  */
-  seq = gimple_seq_alloc ();
+  seq = NULL;
   gimple_seq_add_stmt (&seq, bind);
   gimple_set_body (fndecl, seq);
 
@@ -8371,7 +8361,7 @@ gimplify_function_tree (tree fndecl)
 
       /* Replace the current function body with the body
          wrapped in the try/finally TF.  */
-      seq = gimple_seq_alloc ();
+      seq = NULL;
       gimple_seq_add_stmt (&seq, new_bind);
       gimple_set_body (fndecl, seq);
     }
diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c
index 4a2ca40ba134e66efbb2c12874be36489cf01bba..cdabd738dc65c7e088d2442bf86ec8828c0d854c 100644
--- a/gcc/graphite-sese-to-poly.c
+++ b/gcc/graphite-sese-to-poly.c
@@ -87,8 +87,7 @@ remove_invariant_phi (sese region, gimple_stmt_iterator *psi)
   edge e = gimple_phi_arg_edge (phi, entry);
   tree var;
   gimple stmt;
-  gimple_seq stmts;
-  gimple_stmt_iterator gsi;
+  gimple_seq stmts = NULL;
 
   if (tree_contains_chrecs (scev, NULL))
     scev = gimple_phi_arg_def (phi, entry);
@@ -97,11 +96,7 @@ remove_invariant_phi (sese region, gimple_stmt_iterator *psi)
   stmt = gimple_build_assign (res, var);
   remove_phi_node (psi, false);
 
-  if (!stmts)
-    stmts = gimple_seq_alloc ();
-
-  gsi = gsi_last (stmts);
-  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+  gimple_seq_add_stmt (&stmts, stmt);
   gsi_insert_seq_on_edge (e, stmts);
   gsi_commit_edge_inserts ();
   SSA_NAME_DEF_STMT (res) = stmt;
@@ -2088,11 +2083,7 @@ insert_stmts (scop_p scop, gimple stmt, gimple_seq stmts,
   gimple_stmt_iterator gsi;
   VEC (gimple, heap) *x = VEC_alloc (gimple, heap, 3);
 
-  if (!stmts)
-    stmts = gimple_seq_alloc ();
-
-  gsi = gsi_last (stmts);
-  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+  gimple_seq_add_stmt (&stmts, stmt);
   for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
     VEC_safe_push (gimple, heap, x, gsi_stmt (gsi));
 
@@ -2107,16 +2098,12 @@ static void
 insert_out_of_ssa_copy (scop_p scop, tree res, tree expr, gimple after_stmt)
 {
   gimple_seq stmts;
-  gimple_stmt_iterator si;
   gimple_stmt_iterator gsi;
   tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
   gimple stmt = gimple_build_assign (res, var);
   VEC (gimple, heap) *x = VEC_alloc (gimple, heap, 3);
 
-  if (!stmts)
-    stmts = gimple_seq_alloc ();
-  si = gsi_last (stmts);
-  gsi_insert_after (&si, stmt, GSI_NEW_STMT);
+  gimple_seq_add_stmt (&stmts, stmt);
   for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
     VEC_safe_push (gimple, heap, x, gsi_stmt (gsi));
 
@@ -2167,17 +2154,13 @@ static void
 insert_out_of_ssa_copy_on_edge (scop_p scop, edge e, tree res, tree expr)
 {
   gimple_stmt_iterator gsi;
-  gimple_seq stmts;
+  gimple_seq stmts = NULL;
   tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
   gimple stmt = gimple_build_assign (res, var);
   basic_block bb;
   VEC (gimple, heap) *x = VEC_alloc (gimple, heap, 3);
 
-  if (!stmts)
-    stmts = gimple_seq_alloc ();
-
-  gsi = gsi_last (stmts);
-  gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+  gimple_seq_add_stmt (&stmts, stmt);
   for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
     VEC_safe_push (gimple, heap, x, gsi_stmt (gsi));
 
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 02d6c3162766d4b1d867bdb26315d21ea3bd4c57..17a431c05bd4c62e7c6c6a0a619f366af0de4f84 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1626,7 +1626,7 @@ ipa_analyze_params_uses (struct cgraph_node *node,
 					 visit_ref_for_mod_analysis,
 					 visit_ref_for_mod_analysis);
 	}
-      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info,
 				       visit_ref_for_mod_analysis,
 				       visit_ref_for_mod_analysis,
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 24d8d4f6025d17b1a2f8ac8e4493b815647fae05..394c3d7093936afa6490dcfeebf77896db1fbd9b 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -602,7 +602,7 @@ make_new_block (struct function *fn, unsigned int index)
   bb->il.gimple = ggc_alloc_cleared_gimple_bb_info ();
   n_basic_blocks_for_function (fn)++;
   bb->flags = 0;
-  set_bb_seq (bb, gimple_seq_alloc ());
+  set_bb_seq (bb, NULL);
   return bb;
 }
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index f6b62438dcecebaf8ef2150c831826d95be51421..21a5188d214bca279d92f6cdd66f12059150f199 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -158,7 +158,7 @@ scan_omp_op (tree *tp, omp_context *ctx)
   return walk_tree (tp, scan_omp_1_op, &wi, NULL);
 }
 
-static void lower_omp (gimple_seq, omp_context *);
+static void lower_omp (gimple_seq *, omp_context *);
 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
 
@@ -1233,7 +1233,7 @@ finalize_task_copyfn (gimple task_stmt)
 {
   struct function *child_cfun;
   tree child_fn, old_fn;
-  gimple_seq seq, new_seq;
+  gimple_seq seq = NULL, new_seq;
   gimple bind;
 
   child_fn = gimple_omp_task_copy_fn (task_stmt);
@@ -1250,13 +1250,12 @@ finalize_task_copyfn (gimple task_stmt)
   push_cfun (child_cfun);
   current_function_decl = child_fn;
   bind = gimplify_body (child_fn, false);
-  seq = gimple_seq_alloc ();
   gimple_seq_add_stmt (&seq, bind);
   new_seq = maybe_catch_exception (seq);
   if (new_seq != seq)
     {
       bind = gimple_build_bind (NULL, new_seq, NULL);
-      seq = gimple_seq_alloc ();
+      seq = NULL;
       gimple_seq_add_stmt (&seq, bind);
     }
   gimple_set_body (child_fn, seq);
@@ -2231,14 +2230,11 @@ static void
 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 			 omp_context *ctx)
 {
-  gimple_stmt_iterator diter;
   tree c, dtor, copyin_seq, x, ptr;
   bool copyin_by_ref = false;
   bool lastprivate_firstprivate = false;
   int pass;
 
-  *dlist = gimple_seq_alloc ();
-  diter = gsi_start (*dlist);
   copyin_seq = NULL;
 
   /* Do all the fixed sized types in the first pass, and the variable sized
@@ -2427,7 +2423,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 
 		  dtor = x;
 		  gimplify_stmt (&dtor, &tseq);
-		  gsi_insert_seq_before (&diter, tseq, GSI_SAME_STMT);
+		  gimple_seq_add_seq (dlist, tseq);
 		}
 	      break;
 
@@ -2470,7 +2466,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 		    x = build_fold_addr_expr_loc (clause_loc, x);
 		  SET_DECL_VALUE_EXPR (placeholder, x);
 		  DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
-		  lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
+		  lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
 		  gimple_seq_add_seq (ilist,
 				      OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
 		  OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
@@ -2574,7 +2570,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
 
 	  if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
 	    {
-	      lower_omp (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
+	      lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
 	      gimple_seq_add_seq (stmt_list,
 				  OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
 	    }
@@ -2678,7 +2674,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
 	    ref = build_fold_addr_expr_loc (clause_loc, ref);
 	  SET_DECL_VALUE_EXPR (placeholder, ref);
 	  DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
-	  lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
+	  lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
 	  gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
 	  OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
 	  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
@@ -3501,7 +3497,8 @@ expand_omp_taskreg (struct omp_region *region)
 	    && !DECL_EXTERNAL (t))
 	  varpool_finalize_decl (t);
       DECL_SAVED_TREE (child_fn) = NULL;
-      gimple_set_body (child_fn, bb_seq (single_succ (entry_bb)));
+      /* We'll create a CFG for child_fn, so no gimple body is needed.  */
+      gimple_set_body (child_fn, NULL);
       TREE_USED (block) = 1;
 
       /* Reset DECL_CONTEXT on function arguments.  */
@@ -5789,9 +5786,8 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
   tree block, control;
   gimple_stmt_iterator tgsi;
-  unsigned i, len;
   gimple stmt, new_stmt, bind, t;
-  gimple_seq ilist, dlist, olist, new_body, body;
+  gimple_seq ilist, dlist, olist, new_body;
   struct gimplify_ctx gctx;
 
   stmt = gsi_stmt (*gsi_p);
@@ -5803,13 +5799,10 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
       			   &ilist, &dlist, ctx);
 
-  tgsi = gsi_start (gimple_omp_body (stmt));
-  for (len = 0; !gsi_end_p (tgsi); len++, gsi_next (&tgsi))
-    continue;
-
-  tgsi = gsi_start (gimple_omp_body (stmt));
-  body = NULL;
-  for (i = 0; i < len; i++, gsi_next (&tgsi))
+  new_body = gimple_omp_body (stmt);
+  gimple_omp_set_body (stmt, NULL);
+  tgsi = gsi_start (new_body);
+  for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
     {
       omp_context *sctx;
       gimple sec_start;
@@ -5818,32 +5811,33 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       sctx = maybe_lookup_ctx (sec_start);
       gcc_assert (sctx);
 
-      gimple_seq_add_stmt (&body, sec_start);
-
-      lower_omp (gimple_omp_body (sec_start), sctx);
-      gimple_seq_add_seq (&body, gimple_omp_body (sec_start));
+      lower_omp (gimple_omp_body_ptr (sec_start), sctx);
+      gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
+			    GSI_CONTINUE_LINKING);
       gimple_omp_set_body (sec_start, NULL);
 
-      if (i == len - 1)
+      if (gsi_one_before_end_p (tgsi))
 	{
 	  gimple_seq l = NULL;
 	  lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
 				     &l, ctx);
-	  gimple_seq_add_seq (&body, l);
+	  gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
 	  gimple_omp_section_set_last (sec_start);
 	}
 
-      gimple_seq_add_stmt (&body, gimple_build_omp_return (false));
+      gsi_insert_after (&tgsi, gimple_build_omp_return (false),
+			GSI_CONTINUE_LINKING);
     }
 
   block = make_node (BLOCK);
-  bind = gimple_build_bind (NULL, body, block);
+  bind = gimple_build_bind (NULL, new_body, block);
 
   olist = NULL;
   lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
 
   block = make_node (BLOCK);
   new_stmt = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, new_stmt, true);
 
   pop_gimplify_context (new_stmt);
   gimple_bind_append_vars (new_stmt, ctx->block_vars);
@@ -5873,9 +5867,6 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple_seq_add_stmt (&new_body, t);
 
   gimple_bind_set_body (new_stmt, new_body);
-  gimple_omp_set_body (stmt, NULL);
-
-  gsi_replace (gsi_p, new_stmt, true);
 }
 
 
@@ -6008,10 +5999,14 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   push_gimplify_context (&gctx);
 
+  block = make_node (BLOCK);
+  bind = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, bind, true);
   bind_body = NULL;
+  dlist = NULL;
   lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
 			   &bind_body, &dlist, ctx);
-  lower_omp (gimple_omp_body (single_stmt), ctx);
+  lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
 
   gimple_seq_add_stmt (&bind_body, single_stmt);
 
@@ -6030,15 +6025,12 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
         (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
 			    OMP_CLAUSE_NOWAIT));
   gimple_seq_add_stmt (&bind_body, t);
-
-  block = make_node (BLOCK);
-  bind = gimple_build_bind (NULL, bind_body, block);
+  gimple_bind_set_body (bind, bind_body);
 
   pop_gimplify_context (bind);
 
   gimple_bind_append_vars (bind, ctx->block_vars);
   BLOCK_VARS (block) = ctx->block_vars;
-  gsi_replace (gsi_p, bind, true);
   if (BLOCK_VARS (block))
     TREE_USED (block) = 1;
 }
@@ -6058,8 +6050,9 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   push_gimplify_context (&gctx);
 
   block = make_node (BLOCK);
-  bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
-      				 block);
+  bind = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, bind, true);
+  gimple_bind_add_stmt (bind, stmt);
 
   bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
   x = build_call_expr_loc (loc, bfn_decl, 0);
@@ -6069,7 +6062,7 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimplify_and_add (x, &tseq);
   gimple_bind_add_seq (bind, tseq);
 
-  lower_omp (gimple_omp_body (stmt), ctx);
+  lower_omp (gimple_omp_body_ptr (stmt), ctx);
   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
@@ -6082,7 +6075,6 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   gimple_bind_append_vars (bind, ctx->block_vars);
   BLOCK_VARS (block) = ctx->block_vars;
-  gsi_replace (gsi_p, bind, true);
 }
 
 
@@ -6098,14 +6090,15 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   push_gimplify_context (&gctx);
 
   block = make_node (BLOCK);
-  bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
-      				   block);
+  bind = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, bind, true);
+  gimple_bind_add_stmt (bind, stmt);
 
   x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
 			 0);
   gimple_bind_add_stmt (bind, x);
 
-  lower_omp (gimple_omp_body (stmt), ctx);
+  lower_omp (gimple_omp_body_ptr (stmt), ctx);
   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
@@ -6119,7 +6112,6 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   gimple_bind_append_vars (bind, ctx->block_vars);
   BLOCK_VARS (block) = gimple_bind_vars (bind);
-  gsi_replace (gsi_p, bind, true);
 }
 
 
@@ -6195,13 +6187,15 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   push_gimplify_context (&gctx);
 
   block = make_node (BLOCK);
-  bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt), block);
+  bind = gimple_build_bind (NULL, NULL, block);
+  gsi_replace (gsi_p, bind, true);
+  gimple_bind_add_stmt (bind, stmt);
 
   tbody = gimple_bind_body (bind);
   gimplify_and_add (lock, &tbody);
   gimple_bind_set_body (bind, tbody);
 
-  lower_omp (gimple_omp_body (stmt), ctx);
+  lower_omp (gimple_omp_body_ptr (stmt), ctx);
   gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
   gimple_bind_add_seq (bind, gimple_omp_body (stmt));
   gimple_omp_set_body (stmt, NULL);
@@ -6215,7 +6209,6 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   pop_gimplify_context (bind);
   gimple_bind_append_vars (bind, ctx->block_vars);
   BLOCK_VARS (block) = gimple_bind_vars (bind);
-  gsi_replace (gsi_p, bind, true);
 }
 
 
@@ -6283,11 +6276,15 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 
   push_gimplify_context (&gctx);
 
-  lower_omp (gimple_omp_for_pre_body (stmt), ctx);
-  lower_omp (gimple_omp_body (stmt), ctx);
+  lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
+  lower_omp (gimple_omp_body_ptr (stmt), ctx);
 
   block = make_node (BLOCK);
   new_stmt = gimple_build_bind (NULL, NULL, block);
+  /* Replace at gsi right away, so that 'stmt' is no member
+     of a sequence anymore as we're going to add to to a different
+     one below.  */
+  gsi_replace (gsi_p, new_stmt, true);
 
   /* Move declaration of temporaries in the loop body before we make
      it go away.  */
@@ -6357,7 +6354,6 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple_bind_set_body (new_stmt, body);
   gimple_omp_set_body (stmt, NULL);
   gimple_omp_for_set_pre_body (stmt, NULL);
-  gsi_replace (gsi_p, new_stmt, true);
 }
 
 /* Callback for walk_stmts.  Check if the current statement only contains
@@ -6710,7 +6706,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   par_olist = NULL;
   par_ilist = NULL;
   lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
-  lower_omp (par_body, ctx);
+  lower_omp (&par_body, ctx);
   if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
     lower_reduction_clauses (clauses, &par_olist, ctx);
 
@@ -6756,15 +6752,10 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple_omp_set_body (stmt, new_body);
 
   bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
-  gimple_bind_add_stmt (bind, stmt);
-  if (ilist || olist)
-    {
-      gimple_seq_add_stmt (&ilist, bind);
-      gimple_seq_add_seq (&ilist, olist);
-      bind = gimple_build_bind (NULL, ilist, NULL);
-    }
-
   gsi_replace (gsi_p, bind, true);
+  gimple_bind_add_seq (bind, ilist);
+  gimple_bind_add_stmt (bind, stmt);
+  gimple_bind_add_seq (bind, olist);
 
   pop_gimplify_context (NULL);
 }
@@ -6829,17 +6820,17 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 	gimple_regimplify_operands (stmt, gsi_p);
       break;
     case GIMPLE_CATCH:
-      lower_omp (gimple_catch_handler (stmt), ctx);
+      lower_omp (gimple_catch_handler_ptr (stmt), ctx);
       break;
     case GIMPLE_EH_FILTER:
-      lower_omp (gimple_eh_filter_failure (stmt), ctx);
+      lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
       break;
     case GIMPLE_TRY:
-      lower_omp (gimple_try_eval (stmt), ctx);
-      lower_omp (gimple_try_cleanup (stmt), ctx);
+      lower_omp (gimple_try_eval_ptr (stmt), ctx);
+      lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
       break;
     case GIMPLE_BIND:
-      lower_omp (gimple_bind_body (stmt), ctx);
+      lower_omp (gimple_bind_body_ptr (stmt), ctx);
       break;
     case GIMPLE_OMP_PARALLEL:
     case GIMPLE_OMP_TASK:
@@ -6892,11 +6883,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 }
 
 static void
-lower_omp (gimple_seq body, omp_context *ctx)
+lower_omp (gimple_seq *body, omp_context *ctx)
 {
   location_t saved_location = input_location;
-  gimple_stmt_iterator gsi = gsi_start (body);
-  for (gsi = gsi_start (body); !gsi_end_p (gsi); gsi_next (&gsi))
+  gimple_stmt_iterator gsi;
+  for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
     lower_omp_1 (&gsi, ctx);
   input_location = saved_location;
 }
@@ -6926,7 +6917,7 @@ execute_lower_omp (void)
 
       if (task_shared_vars)
 	push_gimplify_context (&gctx);
-      lower_omp (body, NULL);
+      lower_omp (&body, NULL);
       if (task_shared_vars)
 	pop_gimplify_context (NULL);
     }
@@ -7104,7 +7095,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
     case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_CRITICAL:
       wi->info = stmt;
-      walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
+      walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
       wi->info = context;
       break;
 
@@ -7112,9 +7103,9 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
       wi->info = stmt;
       /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
 	 walk them.  */
-      walk_gimple_seq (gimple_omp_for_pre_body (stmt),
-	  	       diagnose_sb_2, NULL, wi);
-      walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
+      walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
+			   diagnose_sb_2, NULL, wi);
+      walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
       wi->info = context;
       break;
 
@@ -7187,7 +7178,9 @@ diagnose_omp_structured_block_errors (void)
 
   memset (&wi, 0, sizeof (wi));
   wi.want_locations = true;
-  walk_gimple_seq (body, diagnose_sb_2, NULL, &wi);
+  walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
+
+  gimple_set_body (current_function_decl, body);
 
   splay_tree_delete (all_labels);
   all_labels = NULL;
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 7d0e3172c3eda3d5ed9e1369b84461c1f44e0371..0a021b421e3748e78389a3931e09c156b758f452 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -1570,8 +1570,8 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
      us some idea of what we're dealing with.  */
   memset (&this_wi, 0, sizeof (this_wi));
   this_wi.info = (void *) &this_state;
-  walk_gimple_seq (gimple_transaction_body (stmt),
-		   lower_sequence_tm, NULL, &this_wi);
+  walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
+		       lower_sequence_tm, NULL, &this_wi);
 
   /* If there was absolutely nothing transaction related inside the
      transaction, we may elide it.  Likewise if this is a nested
@@ -1600,7 +1600,7 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
       gimple_seq n_seq, e_seq;
 
       n_seq = gimple_seq_alloc_with_stmt (g);
-      e_seq = gimple_seq_alloc ();
+      e_seq = NULL;
 
       g = gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER),
 			     1, integer_zero_node);
@@ -1704,13 +1704,15 @@ static unsigned int
 execute_lower_tm (void)
 {
   struct walk_stmt_info wi;
+  gimple_seq body;
 
   /* Transactional clones aren't created until a later pass.  */
   gcc_assert (!decl_is_tm_clone (current_function_decl));
 
+  body = gimple_body (current_function_decl);
   memset (&wi, 0, sizeof (wi));
-  walk_gimple_seq (gimple_body (current_function_decl),
-		   lower_sequence_no_tm, NULL, &wi);
+  walk_gimple_seq_mod (&body, lower_sequence_no_tm, NULL, &wi);
+  gimple_set_body (current_function_decl, body);
 
   return 0;
 }
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index e32daa75e0f09ca118bcd89b62b7aed492fa2f09..7d884c9c926eb3f68927a4846947e85220757545 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -377,7 +377,7 @@ make_blocks (gimple_seq seq)
       if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
 	{
 	  if (!first_stmt_of_seq)
-	    seq = gsi_split_seq_before (&i);
+	    gsi_split_seq_before (&i, &seq);
 	  bb = create_basic_block (seq, NULL, bb);
 	  start_new_block = false;
 	}
@@ -439,7 +439,7 @@ create_bb (void *h, void *e, basic_block after)
   bb->index = last_basic_block;
   bb->flags = BB_NEW;
   bb->il.gimple = ggc_alloc_cleared_gimple_bb_info ();
-  set_bb_seq (bb, h ? (gimple_seq) h : gimple_seq_alloc ());
+  set_bb_seq (bb, h ? (gimple_seq) h : NULL);
 
   /* Add the new block to the linked list of blocks.  */
   link_block (bb, after);
@@ -1655,7 +1655,6 @@ static void
 gimple_merge_blocks (basic_block a, basic_block b)
 {
   gimple_stmt_iterator last, gsi, psi;
-  gimple_seq phis = phi_nodes (b);
 
   if (dump_file)
     fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index);
@@ -1663,7 +1662,7 @@ gimple_merge_blocks (basic_block a, basic_block b)
   /* Remove all single-valued PHI nodes from block B of the form
      V_i = PHI <V_j> by propagating V_j to all the uses of V_i.  */
   gsi = gsi_last_bb (a);
-  for (psi = gsi_start (phis); !gsi_end_p (psi); )
+  for (psi = gsi_start_phis (b); !gsi_end_p (psi); )
     {
       gimple phi = gsi_stmt (psi);
       tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
@@ -5249,7 +5248,7 @@ gimple_split_block (basic_block bb, void *stmt)
      brings ugly quadratic memory consumption in the inliner.
      (We are still quadratic since we need to update stmt BB pointers,
      sadly.)  */
-  list = gsi_split_seq_before (&gsi);
+  gsi_split_seq_before (&gsi, &list);
   set_bb_seq (new_bb, list);
   for (gsi_tgt = gsi_start (list);
        !gsi_end_p (gsi_tgt); gsi_next (&gsi_tgt))
@@ -6085,8 +6084,8 @@ move_stmt_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 	  p->remap_decls_p = false;
 	  *handled_ops_p = true;
 
-	  walk_gimple_seq (gimple_omp_body (stmt), move_stmt_r,
-			   move_stmt_op, wi);
+	  walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), move_stmt_r,
+			       move_stmt_op, wi);
 
 	  p->remap_decls_p = save_remap_decls_p;
 	}
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 0547fcf147fd74aa5e58607a7089bdc470a1b551..928a3f392744b21e496981b919c6dd5abae0e413 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -661,17 +661,16 @@ update_complex_components_on_edge (edge e, tree lhs, tree r, tree i)
 static void
 update_complex_assignment (gimple_stmt_iterator *gsi, tree r, tree i)
 {
-  gimple_stmt_iterator orig_si = *gsi;
   gimple stmt;
 
-  if (gimple_in_ssa_p (cfun))
-    update_complex_components (gsi, gsi_stmt (*gsi), r, i);
-
-  gimple_assign_set_rhs_with_ops (&orig_si, COMPLEX_EXPR, r, i);
-  stmt = gsi_stmt (orig_si);
+  gimple_assign_set_rhs_with_ops (gsi, COMPLEX_EXPR, r, i);
+  stmt = gsi_stmt (*gsi);
   update_stmt (stmt);
   if (maybe_clean_eh_stmt (stmt))
     gimple_purge_dead_eh_edges (gimple_bb (stmt));
+
+  if (gimple_in_ssa_p (cfun))
+    update_complex_components (gsi, gsi_stmt (*gsi), r, i);
 }
 
 
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 0241a5f1bc43b05e34616d4ba8623d231b44875f..ef2b58485695b253738749fa828a4e7645ce5c7b 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -406,7 +406,7 @@ static gimple_seq lower_eh_must_not_throw (struct leh_state *, gimple);
 
 #define LARGE_GOTO_QUEUE 20
 
-static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq seq);
+static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq *seq);
 
 static gimple_seq
 find_goto_replacement (struct leh_tf_state *tf, treemple stmt)
@@ -481,7 +481,7 @@ replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf,
 /* The real work of replace_goto_queue.  Returns with TSI updated to
    point to the next statement.  */
 
-static void replace_goto_queue_stmt_list (gimple_seq, struct leh_tf_state *);
+static void replace_goto_queue_stmt_list (gimple_seq *, struct leh_tf_state *);
 
 static void
 replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf,
@@ -511,18 +511,18 @@ replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf,
       break;
 
     case GIMPLE_TRY:
-      replace_goto_queue_stmt_list (gimple_try_eval (stmt), tf);
-      replace_goto_queue_stmt_list (gimple_try_cleanup (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_try_eval_ptr (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_try_cleanup_ptr (stmt), tf);
       break;
     case GIMPLE_CATCH:
-      replace_goto_queue_stmt_list (gimple_catch_handler (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_catch_handler_ptr (stmt), tf);
       break;
     case GIMPLE_EH_FILTER:
-      replace_goto_queue_stmt_list (gimple_eh_filter_failure (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_eh_filter_failure_ptr (stmt), tf);
       break;
     case GIMPLE_EH_ELSE:
-      replace_goto_queue_stmt_list (gimple_eh_else_n_body (stmt), tf);
-      replace_goto_queue_stmt_list (gimple_eh_else_e_body (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (stmt), tf);
       break;
 
     default:
@@ -536,9 +536,9 @@ replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf,
 /* A subroutine of replace_goto_queue.  Handles GIMPLE_SEQ.  */
 
 static void
-replace_goto_queue_stmt_list (gimple_seq seq, struct leh_tf_state *tf)
+replace_goto_queue_stmt_list (gimple_seq *seq, struct leh_tf_state *tf)
 {
-  gimple_stmt_iterator gsi = gsi_start (seq);
+  gimple_stmt_iterator gsi = gsi_start (*seq);
 
   while (!gsi_end_p (gsi))
     replace_goto_queue_1 (gsi_stmt (gsi), tf, &gsi);
@@ -551,8 +551,8 @@ replace_goto_queue (struct leh_tf_state *tf)
 {
   if (tf->goto_queue_active == 0)
     return;
-  replace_goto_queue_stmt_list (tf->top_p_seq, tf);
-  replace_goto_queue_stmt_list (eh_seq, tf);
+  replace_goto_queue_stmt_list (&tf->top_p_seq, tf);
+  replace_goto_queue_stmt_list (&eh_seq, tf);
 }
 
 /* Add a new record to the goto queue contained in TF. NEW_STMT is the
@@ -731,9 +731,6 @@ do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod)
 
   q->cont_stmt = q->stmt.g;
 
-  if (!q->repl_stmt)
-    q->repl_stmt = gimple_seq_alloc ();
-
   if (mod)
     gimple_seq_add_seq (&q->repl_stmt, mod);
 
@@ -750,8 +747,6 @@ do_goto_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod,
   gimple x;
 
   gcc_assert (q->is_label);
-  if (!q->repl_stmt)
-    q->repl_stmt = gimple_seq_alloc ();
 
   q->cont_stmt = gimple_build_goto (VEC_index (tree, tf->dest_array, q->index));
 
@@ -1050,13 +1045,13 @@ lower_try_finally_nofallthru (struct leh_state *state,
   if (eh_else)
     {
       finally = gimple_eh_else_n_body (eh_else);
-      lower_eh_constructs_1 (state, finally);
+      lower_eh_constructs_1 (state, &finally);
       gimple_seq_add_seq (&tf->top_p_seq, finally);
 
       if (tf->may_throw)
 	{
 	  finally = gimple_eh_else_e_body (eh_else);
-	  lower_eh_constructs_1 (state, finally);
+	  lower_eh_constructs_1 (state, &finally);
 
 	  emit_post_landing_pad (&eh_seq, tf->region);
 	  gimple_seq_add_seq (&eh_seq, finally);
@@ -1064,7 +1059,7 @@ lower_try_finally_nofallthru (struct leh_state *state,
     }
   else
     {
-      lower_eh_constructs_1 (state, finally);
+      lower_eh_constructs_1 (state, &finally);
       gimple_seq_add_seq (&tf->top_p_seq, finally);
 
       if (tf->may_throw)
@@ -1105,7 +1100,7 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
 	finally = gimple_eh_else_n_body (x);
     }
 
-  lower_eh_constructs_1 (state, finally);
+  lower_eh_constructs_1 (state, &finally);
 
   if (tf->may_throw)
     {
@@ -1193,7 +1188,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
   if (tf->may_fallthru)
     {
       seq = lower_try_finally_dup_block (finally, state);
-      lower_eh_constructs_1 (state, seq);
+      lower_eh_constructs_1 (state, &seq);
       gimple_seq_add_seq (&new_stmt, seq);
 
       tmp = lower_try_finally_fallthru_label (tf);
@@ -1209,7 +1204,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
 	seq = gimple_eh_else_e_body (eh_else);
       else
 	seq = lower_try_finally_dup_block (finally, state);
-      lower_eh_constructs_1 (state, seq);
+      lower_eh_constructs_1 (state, &seq);
 
       emit_post_landing_pad (&eh_seq, tf->region);
       gimple_seq_add_seq (&eh_seq, seq);
@@ -1259,7 +1254,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
           gimple_seq_add_stmt (&new_stmt, x);
 
 	  seq = lower_try_finally_dup_block (finally, state);
-	  lower_eh_constructs_1 (state, seq);
+	  lower_eh_constructs_1 (state, &seq);
           gimple_seq_add_seq (&new_stmt, seq);
 
           gimple_seq_add_stmt (&new_stmt, q->cont_stmt);
@@ -1306,7 +1301,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   int nlabels, ndests, j, last_case_index;
   tree last_case;
   VEC (tree,heap) *case_label_vec;
-  gimple_seq switch_body;
+  gimple_seq switch_body = NULL;
   gimple x, eh_else;
   tree tmp;
   gimple switch_stmt;
@@ -1317,7 +1312,6 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
   /* The location of the finally block.  */
   location_t finally_loc;
 
-  switch_body = gimple_seq_alloc ();
   finally = gimple_try_cleanup (tf->top_p);
   eh_else = get_eh_else (finally);
 
@@ -1331,7 +1325,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
     : tf_loc;
 
   /* Lower the finally block itself.  */
-  lower_eh_constructs_1 (state, finally);
+  lower_eh_constructs_1 (state, &finally);
 
   /* Prepare for switch statement generation.  */
   nlabels = VEC_length (tree, tf->dest_array);
@@ -1382,7 +1376,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
       if (tf->may_throw)
 	{
 	  finally = gimple_eh_else_e_body (eh_else);
-	  lower_eh_constructs_1 (state, finally);
+	  lower_eh_constructs_1 (state, &finally);
 
 	  emit_post_landing_pad (&eh_seq, tf->region);
 	  gimple_seq_add_seq (&eh_seq, finally);
@@ -1426,12 +1420,10 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
      entrance through a particular edge. */
   for (; q < qe; ++q)
     {
-      gimple_seq mod;
+      gimple_seq mod = NULL;
       int switch_id;
       unsigned int case_index;
 
-      mod = gimple_seq_alloc ();
-
       if (q->index < 0)
 	{
 	  x = gimple_build_assign (finally_tmp,
@@ -1623,7 +1615,7 @@ lower_try_finally (struct leh_state *state, gimple tp)
   old_eh_seq = eh_seq;
   eh_seq = NULL;
 
-  lower_eh_constructs_1 (&this_state, gimple_try_eval(tp));
+  lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
 
   /* Determine if the try block is escaped through the bottom.  */
   this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
@@ -1706,7 +1698,7 @@ lower_catch (struct leh_state *state, gimple tp)
   struct leh_state this_state = *state;
   gimple_stmt_iterator gsi;
   tree out_label;
-  gimple_seq new_seq;
+  gimple_seq new_seq, cleanup;
   gimple x;
   location_t try_catch_loc = gimple_location (tp);
 
@@ -1716,7 +1708,7 @@ lower_catch (struct leh_state *state, gimple tp)
       this_state.cur_region = try_region;
     }
 
-  lower_eh_constructs_1 (&this_state, gimple_try_eval (tp));
+  lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
 
   if (!eh_region_may_contain_throw (try_region))
     return gimple_try_eval (tp);
@@ -1729,7 +1721,8 @@ lower_catch (struct leh_state *state, gimple tp)
   this_state.ehp_region = try_region;
 
   out_label = NULL;
-  for (gsi = gsi_start (gimple_try_cleanup (tp));
+  cleanup = gimple_try_cleanup (tp);
+  for (gsi = gsi_start (cleanup);
        !gsi_end_p (gsi);
        gsi_next (&gsi))
     {
@@ -1741,7 +1734,7 @@ lower_catch (struct leh_state *state, gimple tp)
       c = gen_eh_region_catch (try_region, gimple_catch_types (gcatch));
 
       handler = gimple_catch_handler (gcatch);
-      lower_eh_constructs_1 (&this_state, handler);
+      lower_eh_constructs_1 (&this_state, &handler);
 
       c->label = create_artificial_label (UNKNOWN_LOCATION);
       x = gimple_build_label (c->label);
@@ -1787,7 +1780,7 @@ lower_eh_filter (struct leh_state *state, gimple tp)
       this_state.cur_region = this_region;
     }
 
-  lower_eh_constructs_1 (&this_state, gimple_try_eval (tp));
+  lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
 
   if (!eh_region_may_contain_throw (this_region))
     return gimple_try_eval (tp);
@@ -1803,7 +1796,7 @@ lower_eh_filter (struct leh_state *state, gimple tp)
   x = gimple_build_label (this_region->u.allowed.label);
   gimple_seq_add_stmt (&new_seq, x);
 
-  lower_eh_constructs_1 (&this_state, gimple_eh_filter_failure (inner));
+  lower_eh_constructs_1 (&this_state, gimple_eh_filter_failure_ptr (inner));
   gimple_seq_add_seq (&new_seq, gimple_eh_filter_failure (inner));
 
   gimple_try_set_cleanup (tp, new_seq);
@@ -1838,7 +1831,7 @@ lower_eh_must_not_throw (struct leh_state *state, gimple tp)
       this_state.cur_region = this_region;
     }
 
-  lower_eh_constructs_1 (&this_state, gimple_try_eval (tp));
+  lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
 
   return gimple_try_eval (tp);
 }
@@ -1861,7 +1854,7 @@ lower_cleanup (struct leh_state *state, gimple tp)
       this_state.cur_region = this_region;
     }
 
-  lower_eh_constructs_1 (&this_state, gimple_try_eval (tp));
+  lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
 
   if (cleanup_dead || !eh_region_may_contain_throw (this_region))
     return gimple_try_eval (tp);
@@ -1881,7 +1874,7 @@ lower_cleanup (struct leh_state *state, gimple tp)
     {
       /* In this case honor_protect_cleanup_actions had nothing to do,
 	 and we should process this normally.  */
-      lower_eh_constructs_1 (state, gimple_try_cleanup (tp));
+      lower_eh_constructs_1 (state, gimple_try_cleanup_ptr (tp));
       result = frob_into_branch_around (tp, this_region,
                                         fake_tf.fallthru_label);
     }
@@ -2010,7 +2003,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 	  if (!x)
 	    {
 	      replace = gimple_try_eval (stmt);
-	      lower_eh_constructs_1 (state, replace);
+	      lower_eh_constructs_1 (state, &replace);
 	    }
 	  else
 	    switch (gimple_code (x))
@@ -2057,10 +2050,10 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
 /* A helper to unwrap a gimple_seq and feed stmts to lower_eh_constructs_2. */
 
 static void
-lower_eh_constructs_1 (struct leh_state *state, gimple_seq seq)
+lower_eh_constructs_1 (struct leh_state *state, gimple_seq *pseq)
 {
   gimple_stmt_iterator gsi;
-  for (gsi = gsi_start (seq); !gsi_end_p (gsi);)
+  for (gsi = gsi_start (*pseq); !gsi_end_p (gsi);)
     lower_eh_constructs_2 (state, &gsi);
 }
 
@@ -2079,7 +2072,8 @@ lower_eh_constructs (void)
   memset (&null_state, 0, sizeof (null_state));
 
   collect_finally_tree_1 (bodyp, NULL);
-  lower_eh_constructs_1 (&null_state, bodyp);
+  lower_eh_constructs_1 (&null_state, &bodyp);
+  gimple_set_body (current_function_decl, bodyp);
 
   /* We assume there's a return statement, or something, at the end of
      the function, and thus ploping the EH sequence afterward won't
@@ -2874,8 +2868,10 @@ optimize_double_finally (gimple one, gimple two)
 {
   gimple oneh;
   gimple_stmt_iterator gsi;
+  gimple_seq cleanup;
 
-  gsi = gsi_start (gimple_try_cleanup (one));
+  cleanup = gimple_try_cleanup (one);
+  gsi = gsi_start (cleanup);
   if (!gsi_one_before_end_p (gsi))
     return;
 
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 56edae9fef3ec37ca3a7cf2530498589bdff5b6a..066e9ad89cd454208cd4b1957493a34f5db41820 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -511,6 +511,15 @@ phi_nodes (const_basic_block bb)
   return bb->il.gimple->phi_nodes;
 }
 
+static inline gimple_seq *
+phi_nodes_ptr (const_basic_block bb)
+{
+  gcc_checking_assert (!(bb->flags & BB_RTL));
+  if (!bb->il.gimple)
+    return NULL;
+  return &bb->il.gimple->phi_nodes;
+}
+
 /* Set PHI nodes of a basic block BB to SEQ.  */
 
 static inline void
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 2ba95f509fe32d4329d9a269ca46cbaff6f98b8b..ef0346581abdd6dda369fc6bac1549e3f1a21076 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1996,7 +1996,7 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id)
   edge new_edge;
   bool inserted = false;
 
-  for (si = gsi_start (phi_nodes (bb)); !gsi_end_p (si); gsi_next (&si))
+  for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
     {
       tree res, new_res;
       gimple new_phi;
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index cc8b98d1ea40c59b1b05dfd82644b8a78b3b1015..edd7755a701c28ed1d067ac88254e1c1052d5f06 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -472,7 +472,7 @@ static void
 mf_decl_cache_locals (void)
 {
   gimple g;
-  gimple_seq seq = gimple_seq_alloc ();
+  gimple_seq seq = NULL;
 
   /* Build the cache vars.  */
   mf_cache_shift_decl_l
@@ -572,7 +572,7 @@ mf_build_check_statement_for (tree base, tree limit,
   mf_limit = make_rename_temp (mf_uintptr_type, "__mf_limit");
 
   /* Build: __mf_base = (uintptr_t) <base address expression>.  */
-  seq = gimple_seq_alloc ();
+  seq = NULL;
   t = fold_convert_loc (location, mf_uintptr_type,
 			unshare_expr (base));
   t = force_gimple_operand (t, &stmts, false, NULL_TREE);
@@ -683,7 +683,7 @@ mf_build_check_statement_for (tree base, tree limit,
 
      This is the body of the conditional.  */
 
-  seq = gimple_seq_alloc ();
+  seq = NULL;
   /* u is a string, so it is already a gimple value.  */
   u = mf_file_function_line_tree (location);
   /* NB: we pass the overall [base..limit] range to mf_check.  */
@@ -704,7 +704,7 @@ mf_build_check_statement_for (tree base, tree limit,
 	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
 	  e = split_block (then_bb, g);
 	  then_bb = e->dest;
-	  seq = gimple_seq_alloc ();
+	  seq = NULL;
 	}
 
       g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl);
@@ -1114,7 +1114,7 @@ mx_register_decls (tree decl, gimple_seq seq, location_t location)
   if (finally_stmts != NULL)
     {
       gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY);
-      gimple_seq new_seq = gimple_seq_alloc ();
+      gimple_seq new_seq = NULL;
 
       gimple_seq_add_stmt (&new_seq, stmt);
       return new_seq;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 042137f09ad9bc9ca690e2cf75be8b8514c4066f..b5d37e98e35366e1050cd39d579fc23d21d4c999 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -577,18 +577,18 @@ get_nl_goto_field (struct nesting_info *info)
   return field;
 }
 
-/* Invoke CALLBACK on all statements of GIMPLE sequence SEQ.  */
+/* Invoke CALLBACK on all statements of GIMPLE sequence *PSEQ.  */
 
 static void
 walk_body (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
-	   struct nesting_info *info, gimple_seq seq)
+	   struct nesting_info *info, gimple_seq *pseq)
 {
   struct walk_stmt_info wi;
 
   memset (&wi, 0, sizeof (wi));
   wi.info = info;
   wi.val_only = true;
-  walk_gimple_seq (seq, callback_stmt, callback_op, &wi);
+  walk_gimple_seq_mod (pseq, callback_stmt, callback_op, &wi);
 }
 
 
@@ -598,7 +598,9 @@ static inline void
 walk_function (walk_stmt_fn callback_stmt, walk_tree_fn callback_op,
 	       struct nesting_info *info)
 {
-  walk_body (callback_stmt, callback_op, info, gimple_body (info->context));
+  gimple_seq body = gimple_body (info->context);
+  walk_body (callback_stmt, callback_op, info, &body);
+  gimple_set_body (info->context, body);
 }
 
 /* Invoke CALLBACK on a GIMPLE_OMP_FOR's init, cond, incr and pre-body.  */
@@ -613,9 +615,9 @@ walk_gimple_omp_for (gimple for_stmt,
   tree t;
   size_t i;
 
-  walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body (for_stmt));
+  walk_body (callback_stmt, callback_op, info, gimple_omp_for_pre_body_ptr (for_stmt));
 
-  seq = gimple_seq_alloc ();
+  seq = NULL;
   memset (&wi, 0, sizeof (wi));
   wi.info = info;
   wi.gsi = gsi_last (seq);
@@ -644,9 +646,8 @@ walk_gimple_omp_for (gimple for_stmt,
       walk_tree (&TREE_OPERAND (t, 1), callback_op, &wi, NULL);
     }
 
-  if (gimple_seq_empty_p (seq))
-    gimple_seq_free (seq);
-  else
+  seq = gsi_seq (wi.gsi);
+  if (!gimple_seq_empty_p (seq))
     {
       gimple_seq pre_body = gimple_omp_for_pre_body (for_stmt);
       annotate_all_with_location (seq, gimple_location (for_stmt));
@@ -1136,10 +1137,10 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 		= info->context;
 	      walk_body (convert_nonlocal_reference_stmt,
 			 convert_nonlocal_reference_op, info,
-			 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
+			 &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
 	      walk_body (convert_nonlocal_reference_stmt,
 			 convert_nonlocal_reference_op, info,
-			 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
+			 &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
 	      DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
 		= old_context;
 	    }
@@ -1148,7 +1149,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 	case OMP_CLAUSE_LASTPRIVATE:
 	  walk_body (convert_nonlocal_reference_stmt,
 		     convert_nonlocal_reference_op, info,
-		     OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+		     &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
 	  break;
 
 	default:
@@ -1261,7 +1262,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->new_local_var_chain = NULL;
 
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-	         info, gimple_omp_body (stmt));
+	         info, gimple_omp_body_ptr (stmt));
 
       if (info->new_local_var_chain)
 	declare_vars (info->new_local_var_chain,
@@ -1277,7 +1278,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt,
 	  		   convert_nonlocal_reference_op, info);
       walk_body (convert_nonlocal_reference_stmt,
-	  	 convert_nonlocal_reference_op, info, gimple_omp_body (stmt));
+	  	 convert_nonlocal_reference_op, info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1285,7 +1286,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-	         info, gimple_omp_body (stmt));
+	         info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1293,7 +1294,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_nonlocal_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-	         info, gimple_omp_body (stmt));
+	         info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1301,7 +1302,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
       walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
-	         info, gimple_omp_body (stmt));
+	         info, gimple_omp_body_ptr (stmt));
       break;
 
     case GIMPLE_BIND:
@@ -1635,10 +1636,10 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 		= info->context;
 	      walk_body (convert_local_reference_stmt,
 			 convert_local_reference_op, info,
-			 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
+			 &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
 	      walk_body (convert_local_reference_stmt,
 			 convert_local_reference_op, info,
-			 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
+			 &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
 	      DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
 		= old_context;
 	    }
@@ -1647,7 +1648,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
 	case OMP_CLAUSE_LASTPRIVATE:
 	  walk_body (convert_local_reference_stmt,
 		     convert_local_reference_op, info,
-		     OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+		     &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
 	  break;
 
 	default:
@@ -1692,7 +1693,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       info->new_local_var_chain = NULL;
 
       walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
-	         gimple_omp_body (stmt));
+	         gimple_omp_body_ptr (stmt));
 
       if (info->new_local_var_chain)
 	declare_vars (info->new_local_var_chain,
@@ -1707,7 +1708,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       walk_gimple_omp_for (stmt, convert_local_reference_stmt,
 			   convert_local_reference_op, info);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-		 info, gimple_omp_body (stmt));
+		 info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1715,7 +1716,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-		 info, gimple_omp_body (stmt));
+		 info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1723,7 +1724,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
       save_suppress = info->suppress_expansion;
       convert_local_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-		 info, gimple_omp_body (stmt));
+		 info, gimple_omp_body_ptr (stmt));
       info->suppress_expansion = save_suppress;
       break;
 
@@ -1731,7 +1732,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
       walk_body (convert_local_reference_stmt, convert_local_reference_op,
-		 info, gimple_omp_body (stmt));
+		 info, gimple_omp_body_ptr (stmt));
       break;
 
     case GIMPLE_COND:
@@ -1809,12 +1810,12 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
   /* Build: __builtin_nl_goto(new_label, &chain->nl_goto_field).  */
   field = get_nl_goto_field (i);
-  x = get_frame_field (info, target_context, field, &wi->gsi);
+  x = get_frame_field (info, target_context, field, gsi);
   x = build_addr (x, target_context);
-  x = gsi_gimplify_val (info, x, &wi->gsi);
+  x = gsi_gimplify_val (info, x, gsi);
   call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
 			    2, build_addr (new_label, target_context), x);
-  gsi_replace (&wi->gsi, call, false);
+  gsi_replace (gsi, call, false);
 
   /* We have handled all of STMT's operands, no need to keep going.  */
   *handled_ops_p = true;
@@ -1979,7 +1980,7 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 	save_local_var_chain = info->new_local_var_chain;
 	info->new_local_var_chain = NULL;
         walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op,
-		   info, gimple_omp_body (stmt));
+		   info, gimple_omp_body_ptr (stmt));
 	if (info->new_local_var_chain)
 	  declare_vars (info->new_local_var_chain,
 			gimple_seq_first_stmt (gimple_omp_body (stmt)),
@@ -2035,7 +2036,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_TASK:
       save_static_chain_added = info->static_chain_added;
       info->static_chain_added = 0;
-      walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       for (i = 0; i < 2; i++)
 	{
 	  tree c, decl;
@@ -2065,7 +2066,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
     case GIMPLE_OMP_FOR:
       walk_body (convert_gimple_call, NULL, info,
-	  	 gimple_omp_for_pre_body (stmt));
+	  	 gimple_omp_for_pre_body_ptr (stmt));
       /* FALLTHRU */
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SECTION:
@@ -2073,7 +2074,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
     case GIMPLE_OMP_CRITICAL:
-      walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+      walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
       break;
 
     default:
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 218a5515a3875e8a02928db6e7800d42715c5046..bac9b52abcd2fd8997873beae07993d408257801 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -221,6 +221,7 @@ make_phi_node (tree var, int len)
 		   - sizeof (struct phi_arg_d)
 		   + sizeof (struct phi_arg_d) * len));
   phi->gsbase.code = GIMPLE_PHI;
+  gimple_init_singleton (phi);
   phi->gimple_phi.nargs = len;
   phi->gimple_phi.capacity = capacity;
   if (TREE_CODE (var) == SSA_NAME)
@@ -269,29 +270,29 @@ release_phi_node (gimple phi)
 /* Resize an existing PHI node.  The only way is up.  Return the
    possibly relocated phi.  */
 
-static void
-resize_phi_node (gimple *phi, size_t len)
+static gimple
+resize_phi_node (gimple phi, size_t len)
 {
   size_t old_size, i;
   gimple new_phi;
 
-  gcc_assert (len > gimple_phi_capacity (*phi));
+  gcc_assert (len > gimple_phi_capacity (phi));
 
   /* The garbage collector will not look at the PHI node beyond the
      first PHI_NUM_ARGS elements.  Therefore, all we have to copy is a
      portion of the PHI node currently in use.  */
   old_size = sizeof (struct gimple_statement_phi)
-	     + (gimple_phi_num_args (*phi) - 1) * sizeof (struct phi_arg_d);
+	     + (gimple_phi_num_args (phi) - 1) * sizeof (struct phi_arg_d);
 
   new_phi = allocate_phi_node (len);
 
-  memcpy (new_phi, *phi, old_size);
+  memcpy (new_phi, phi, old_size);
 
   for (i = 0; i < gimple_phi_num_args (new_phi); i++)
     {
       use_operand_p imm, old_imm;
       imm = gimple_phi_arg_imm_use_ptr (new_phi, i);
-      old_imm = gimple_phi_arg_imm_use_ptr (*phi, i);
+      old_imm = gimple_phi_arg_imm_use_ptr (phi, i);
       imm->use = gimple_phi_arg_def_ptr (new_phi, i);
       relink_imm_use_stmt (imm, old_imm, new_phi);
     }
@@ -310,7 +311,7 @@ resize_phi_node (gimple *phi, size_t len)
       imm->loc.stmt = new_phi;
     }
 
-  *phi = new_phi;
+  return new_phi;
 }
 
 /* Reserve PHI arguments for a new edge to basic block BB.  */
@@ -324,18 +325,18 @@ reserve_phi_args_for_new_edge (basic_block bb)
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple *loc = gsi_stmt_ptr (&gsi);
+      gimple stmt = gsi_stmt (gsi);
 
-      if (len > gimple_phi_capacity (*loc))
+      if (len > gimple_phi_capacity (stmt))
 	{
-	  gimple old_phi = *loc;
-
-	  resize_phi_node (loc, cap);
+	  gimple new_phi = resize_phi_node (stmt, cap);
 
 	  /* The result of the PHI is defined by this PHI node.  */
-	  SSA_NAME_DEF_STMT (gimple_phi_result (*loc)) = *loc;
+	  SSA_NAME_DEF_STMT (gimple_phi_result (new_phi)) = new_phi;
+	  gsi_set_stmt (&gsi, new_phi);
 
-	  release_phi_node (old_phi);
+	  release_phi_node (stmt);
+	  stmt = new_phi;
 	}
 
       /* We represent a "missing PHI argument" by placing NULL_TREE in
@@ -345,9 +346,9 @@ reserve_phi_args_for_new_edge (basic_block bb)
 	 example, the loop optimizer duplicates several basic blocks,
 	 redirects edges, and then fixes up PHI arguments later in
 	 batch.  */
-      SET_PHI_ARG_DEF (*loc, len - 1, NULL_TREE);
+      SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE);
 
-      (*loc)->gimple_phi.nargs++;
+      stmt->gimple_phi.nargs++;
     }
 }
 
@@ -356,13 +357,15 @@ reserve_phi_args_for_new_edge (basic_block bb)
 void
 add_phi_node_to_bb (gimple phi, basic_block bb)
 {
-  gimple_stmt_iterator gsi;
+  gimple_seq seq = phi_nodes (bb);
   /* Add the new PHI node to the list of PHI nodes for block BB.  */
-  if (phi_nodes (bb) == NULL)
-    set_phi_nodes (bb, gimple_seq_alloc ());
-
-  gsi = gsi_last (phi_nodes (bb));
-  gsi_insert_after (&gsi, phi, GSI_NEW_STMT);
+  if (seq == NULL)
+    set_phi_nodes (bb, gimple_seq_alloc_with_stmt (phi));
+  else
+    {
+      gimple_seq_add_stmt (&seq, phi);
+      gcc_assert (seq == phi_nodes (bb));
+    }
 
   /* Associate BB to the PHI node.  */
   gimple_set_bb (phi, bb);
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 110990a211a5351aac1df8d0d843d2def7f58ad4..de99b305e3c74ea4613c631da40887bcb69d9b6b 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -3192,6 +3192,7 @@ initialize_parameter_reductions (void)
   gimple_seq seq = NULL;
   tree parm;
 
+  gsi = gsi_start (seq);
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm;
        parm = DECL_CHAIN (parm))
@@ -3205,12 +3206,6 @@ initialize_parameter_reductions (void)
       if (!access_vec)
 	continue;
 
-      if (!seq)
-	{
-	  seq = gimple_seq_alloc ();
-	  gsi = gsi_start (seq);
-	}
-
       for (access = VEC_index (access_p, access_vec, 0);
 	   access;
 	   access = access->next_grp)
@@ -3218,6 +3213,7 @@ initialize_parameter_reductions (void)
 				 EXPR_LOCATION (parm));
     }
 
+  seq = gsi_seq (gsi);
   if (seq)
     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
 }
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index d954f3b43e3ed32d9aa4c39e0d8e2b4c519c18d8..1d72e06fe7697652848857707f74786b70cc7394 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1042,12 +1042,10 @@ static bool
 remove_dead_phis (basic_block bb)
 {
   bool something_changed = false;
-  gimple_seq phis;
   gimple phi;
   gimple_stmt_iterator gsi;
-  phis = phi_nodes (bb);
 
-  for (gsi = gsi_start (phis); !gsi_end_p (gsi);)
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);)
     {
       stats.total_phis++;
       phi = gsi_stmt (gsi);
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index a8599420763ee8533060fdd583b3e1a43a758233..bf4458065e99cadeff2890953c55c809d0ba9098 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -277,7 +277,7 @@ dse_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
 {
   gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_last (bb_seq (bb)); !gsi_end_p (gsi); gsi_prev (&gsi))
+  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
     dse_optimize_stmt (gsi);
 }
 
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index d3e9f98a06980ea212b9866f3c28afac6ca94b44..e14627d9f3a1ed2f27f9ef5d8000dcd62a2ad666 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1202,16 +1202,18 @@ forward_propagate_addr_expr (tree name, tree rhs)
 }
 
 
-/* Forward propagate the comparison defined in STMT like
+/* Forward propagate the comparison defined in *DEFGSI like
    cond_1 = x CMP y to uses of the form
      a_1 = (T')cond_1
      a_1 = !cond_1
      a_1 = cond_1 != 0
-   Returns true if stmt is now unused.  */
+   Returns true if stmt is now unused.  Advance DEFGSI to the next
+   statement.  */
 
 static bool
-forward_propagate_comparison (gimple stmt)
+forward_propagate_comparison (gimple_stmt_iterator *defgsi)
 {
+  gimple stmt = gsi_stmt (*defgsi);
   tree name = gimple_assign_lhs (stmt);
   gimple use_stmt;
   tree tmp = NULL_TREE;
@@ -1224,18 +1226,18 @@ forward_propagate_comparison (gimple stmt)
        && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
       || (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME
         && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs2 (stmt))))
-    return false;
+    goto bailout;
 
   /* Do not un-cse comparisons.  But propagate through copies.  */
   use_stmt = get_prop_dest_stmt (name, &name);
   if (!use_stmt
       || !is_gimple_assign (use_stmt))
-    return false;
+    goto bailout;
 
   code = gimple_assign_rhs_code (use_stmt);
   lhs = gimple_assign_lhs (use_stmt);
   if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
-    return false;
+    goto bailout;
 
   /* We can propagate the condition into a statement that
      computes the logical negation of the comparison result.  */
@@ -1249,13 +1251,13 @@ forward_propagate_comparison (gimple stmt)
       enum tree_code inv_code;
       inv_code = invert_tree_comparison (gimple_assign_rhs_code (stmt), nans);
       if (inv_code == ERROR_MARK)
-	return false;
+	goto bailout;
 
       tmp = build2 (inv_code, TREE_TYPE (lhs), gimple_assign_rhs1 (stmt),
 		    gimple_assign_rhs2 (stmt));
     }
   else
-    return false;
+    goto bailout;
 
   gsi = gsi_for_stmt (use_stmt);
   gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (tmp));
@@ -1271,8 +1273,16 @@ forward_propagate_comparison (gimple stmt)
       fprintf (dump_file, "'\n");
     }
 
+  /* When we remove stmt now the iterator defgsi goes off it's current
+     sequence, hence advance it now.  */
+  gsi_next (defgsi);
+
   /* Remove defining statements.  */
   return remove_prop_source_from_use (name);
+
+bailout:
+  gsi_next (defgsi);
+  return false;
 }
 
 
@@ -2752,9 +2762,8 @@ ssa_forward_propagate_and_combine (void)
 	    }
 	  else if (TREE_CODE_CLASS (code) == tcc_comparison)
 	    {
-	      if (forward_propagate_comparison (stmt))
+	      if (forward_propagate_comparison (&gsi))
 	        cfg_changed = true;
-	      gsi_next (&gsi);
 	    }
 	  else
 	    gsi_next (&gsi);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index ce5eb208850c60f96ed880e1430b1ff6b6212354..5a01e618da556717661d183ac81ba24f327a119f 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1328,8 +1328,8 @@ move_computations_stmt (struct dom_walk_data *dw_data,
 	}
 
       mark_virtual_ops_for_renaming (stmt);
-      gsi_insert_on_edge (loop_preheader_edge (level), stmt);
       gsi_remove (&bsi, false);
+      gsi_insert_on_edge (loop_preheader_edge (level), stmt);
     }
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index fa38c524f09eeabb9fe0570b63bf58dcede787a4..82866033f618924c9f48e916d802e133e0d83acf 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -183,7 +183,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
   HOST_WIDE_INT dummy;
   gimple stmt, pattern_stmt = NULL;
   gimple_seq pattern_def_seq = NULL;
-  gimple_stmt_iterator pattern_def_si = gsi_start (NULL);
+  gimple_stmt_iterator pattern_def_si = gsi_none ();
   bool analyze_pattern_stmt = false;
 
   if (vect_print_dump_info (REPORT_DETAILS))
@@ -336,7 +336,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
 		    }
 		  else
 		    {
-		      pattern_def_si = gsi_start (NULL);
+		      pattern_def_si = gsi_none ();
 		      analyze_pattern_stmt = false;
 		    }
 		}
@@ -5231,7 +5231,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
   gimple_seq cond_expr_stmt_list = NULL;
   gimple stmt, pattern_stmt;
   gimple_seq pattern_def_seq = NULL;
-  gimple_stmt_iterator pattern_def_si = gsi_start (NULL);
+  gimple_stmt_iterator pattern_def_si = gsi_none ();
   bool transform_pattern_stmt = false;
 
   if (vect_print_dump_info (REPORT_DETAILS))
@@ -5409,7 +5409,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
 		    }
 		  else
 		    {
-		      pattern_def_si = gsi_start (NULL);
+		      pattern_def_si = gsi_none ();
 		      transform_pattern_stmt = false;
 		    }
 		}