From cfaab3a92418d34e14bb0fa447c052fce9f6057b Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo@redhat.com>
Date: Mon, 11 Dec 2006 20:15:53 +0000
Subject: [PATCH] tree-ssa-operands.h (create_ssa_artificial_load_stmt): Rename
 from create_ssa_artficial_load_stmt.

	* tree-ssa-operands.h (create_ssa_artificial_load_stmt):
	Rename from create_ssa_artficial_load_stmt.  Update all users.
	* tree-into-ssa.c (register_new_def): Make static.
	* tree.c (is_global_var): Handle SSA_NAMEs.
	* tree.h (SSA_NAME_IS_DEFAULT_DEF): Define.  Update all users
	that used to call gimple_default_def.
	* tree-ssa-operands.c (push_stmt_changes): New.
	(pop_stmt_changes): New.  Update every pass that modifies
	statements to bracket modifications with
	push_stmt_changes/pop_stmt_changes.
	(discard_stmt_changes): New.
	* tree-ssa-dom.c (stmts_to_rescan): Change to stack of
	'tree *' instead of 'tree'.  Update all users.
	* tree-flow-inline.h (zero_imm_uses_p): New.
	(symbol_mem_tag): New.  Update every function that used
	to access the annotation directly.
	(set_symbol_mem_tag): Likewise.
	* tree-dfa.c (dump_variable): Always show the escape mask.
	(mark_symbols_for_renaming): Rename from
	mark_new_vars_to_rename.  Update all users.
	Only mark to rename naked symbols in real and virtual
	operands.

From-SVN: r119746
---
 gcc/ChangeLog               |  25 ++++
 gcc/passes.c                |   1 +
 gcc/tree-cfg.c              |  15 ++-
 gcc/tree-data-ref.c         |  11 +-
 gcc/tree-dfa.c              | 124 ++++++------------
 gcc/tree-flow-inline.h      |  38 +++++-
 gcc/tree-flow.h             |  36 +++---
 gcc/tree-into-ssa.c         |   2 +-
 gcc/tree-outof-ssa.c        |   2 +-
 gcc/tree-scalar-evolution.c |   3 +-
 gcc/tree-ssa-ccp.c          |  28 ++--
 gcc/tree-ssa-dom.c          |  57 ++++++---
 gcc/tree-ssa-forwprop.c     |  13 +-
 gcc/tree-ssa-loop-ivopts.c  |  12 +-
 gcc/tree-ssa-operands.c     | 248 +++++++++++++++++++++++++++++++++++-
 gcc/tree-ssa-operands.h     |   5 +-
 gcc/tree-ssa-pre.c          |   8 +-
 gcc/tree-ssa-propagate.c    |  16 ++-
 gcc/tree-ssa-reassoc.c      |   2 +-
 gcc/tree-ssanames.c         |   3 +-
 gcc/tree-vect-transform.c   |   6 +-
 gcc/tree-vrp.c              |   2 +-
 gcc/tree.c                  |   3 +
 gcc/tree.h                  |   8 ++
 24 files changed, 498 insertions(+), 170 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3f740eeb4833..f01ef1077879 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2006-12-11  Diego Novillo  <dnovillo@redhat.com>
+
+	* tree-ssa-operands.h (create_ssa_artificial_load_stmt):
+	Rename from create_ssa_artficial_load_stmt.  Update all users.
+	* tree-into-ssa.c (register_new_def): Make static.
+	* tree.c (is_global_var): Handle SSA_NAMEs.
+	* tree.h (SSA_NAME_IS_DEFAULT_DEF): Define.  Update all users
+	that used to call gimple_default_def.
+	* tree-ssa-operands.c (push_stmt_changes): New.
+	(pop_stmt_changes): New.  Update every pass that modifies
+	statements to bracket modifications with
+	push_stmt_changes/pop_stmt_changes.
+	(discard_stmt_changes): New.
+	* tree-ssa-dom.c (stmts_to_rescan): Change to stack of
+	'tree *' instead of 'tree'.  Update all users.
+	* tree-flow-inline.h (zero_imm_uses_p): New.
+	(symbol_mem_tag): New.  Update every function that used
+	to access the annotation directly.
+	(set_symbol_mem_tag): Likewise.
+	* tree-dfa.c (dump_variable): Always show the escape mask.
+	(mark_symbols_for_renaming): Rename from
+	mark_new_vars_to_rename.  Update all users.
+	Only mark to rename naked symbols in real and virtual
+	operands.
+
 2006-12-11  Andreas Schwab  <schwab@suse.de>
 
 	* varasm.c (elf_record_gcc_switches): Cast second argument of
diff --git a/gcc/passes.c b/gcc/passes.c
index e5faaa464f39..8bacb08d5117 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -885,6 +885,7 @@ execute_one_pass (struct tree_opt_pass *pass)
       free ((char *) dump_file_name);
       dump_file_name = NULL;
     }
+
   if (dump_file)
     {
       dump_end (pass->static_pass_number, dump_file);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index f738d409d533..48893d4f214b 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -1248,6 +1248,9 @@ replace_uses_by (tree name, tree val)
 
   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
     {
+      if (TREE_CODE (stmt) != PHI_NODE)
+	push_stmt_changes (&stmt);
+
       FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
         {
 	  replace_exp (use, val);
@@ -1265,21 +1268,25 @@ replace_uses_by (tree name, tree val)
 		}
 	    }
 	}
+
       if (TREE_CODE (stmt) != PHI_NODE)
 	{
 	  tree rhs;
 
 	  fold_stmt_inplace (stmt);
+
+	  /* FIXME.  This should go in pop_stmt_changes.  */
 	  rhs = get_rhs (stmt);
 	  if (TREE_CODE (rhs) == ADDR_EXPR)
 	    recompute_tree_invariant_for_addr_expr (rhs);
 
 	  maybe_clean_or_replace_eh_stmt (stmt, stmt);
-	  mark_new_vars_to_rename (stmt);
+
+	  pop_stmt_changes (&stmt);
 	}
     }
 
-  gcc_assert (num_imm_uses (name) == 0);
+  gcc_assert (zero_imm_uses_p (name));
 
   /* Also update the trees stored in loop structures.  */
   if (current_loops)
@@ -3996,7 +4003,7 @@ tree_make_forwarder_block (edge fallthru)
   if (single_pred_p (bb))
     return;
 
-  /* If we redirected a branch we must create new phi nodes at the
+  /* If we redirected a branch we must create new PHI nodes at the
      start of BB.  */
   for (phi = phi_nodes (dummy); phi; phi = PHI_CHAIN (phi))
     {
@@ -5684,7 +5691,7 @@ gimplify_val (block_stmt_iterator *bsi, tree type, tree exp)
 
   bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
   if (gimple_in_ssa_p (cfun))
-    mark_new_vars_to_rename (new_stmt);
+    mark_symbols_for_renaming (new_stmt);
 
   return t;
 }
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index fdaaaafac931..4d60da027bb9 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -149,7 +149,7 @@ ptr_decl_may_alias_p (tree ptr, tree decl,
   if (pi)
     tag = pi->name_mem_tag;
   if (!tag)
-    tag = get_var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
+    tag = symbol_mem_tag (SSA_NAME_VAR (ptr));
   if (!tag)
     tag = DR_MEMTAG (ptr_dr);
   if (!tag)
@@ -180,13 +180,13 @@ ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
     }
   else
     {
-      tag_a = get_var_ann (SSA_NAME_VAR (ptr_a))->symbol_mem_tag;
+      tag_a = symbol_mem_tag (SSA_NAME_VAR (ptr_a));
       if (!tag_a)
 	tag_a = DR_MEMTAG (dra);
       if (!tag_a)
 	return false;
       
-      tag_b = get_var_ann (SSA_NAME_VAR (ptr_b))->symbol_mem_tag;
+      tag_b = symbol_mem_tag (SSA_NAME_VAR (ptr_b));
       if (!tag_b)
 	tag_b = DR_MEMTAG (drb);
       if (!tag_b)
@@ -1729,10 +1729,9 @@ object_analysis (tree memref, tree stmt, bool is_read,
       switch (TREE_CODE (base_address))
 	{
 	case SSA_NAME:
-	  *memtag = get_var_ann (SSA_NAME_VAR (base_address))->symbol_mem_tag;
+	  *memtag = symbol_mem_tag (SSA_NAME_VAR (base_address));
 	  if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME)
-	    *memtag = get_var_ann (
-		      SSA_NAME_VAR (TREE_OPERAND (memref, 0)))->symbol_mem_tag;
+	    *memtag = symbol_mem_tag (SSA_NAME_VAR (TREE_OPERAND (memref, 0)));
 	  break;
 	case ADDR_EXPR:
 	  *memtag = TREE_OPERAND (base_address, 0);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index b2d09f4b031b..9c7afceccab6 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -334,33 +334,30 @@ dump_variable (FILE *file, tree var)
 
   if (is_call_clobbered (var))
     {
+      var_ann_t va = var_ann (var);
+      unsigned int escape_mask = va->escape_mask;
+
       fprintf (file, ", call clobbered");
-      if (dump_flags & TDF_DETAILS)
-	{
-	  var_ann_t va = var_ann (var);
-	  unsigned int escape_mask = va->escape_mask;
-	  
-	  fprintf (file, " (");
-	  if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
-	    fprintf (file, ", stored in global");
-	  if (escape_mask & ESCAPE_TO_ASM)
-	    fprintf (file, ", goes through ASM");
-	  if (escape_mask & ESCAPE_TO_CALL)
-	    fprintf (file, ", passed to call");
-	  if (escape_mask & ESCAPE_BAD_CAST)
-	    fprintf (file, ", bad cast");
-	  if (escape_mask & ESCAPE_TO_RETURN)
-	    fprintf (file, ", returned from func");
-	  if (escape_mask & ESCAPE_TO_PURE_CONST)
-	    fprintf (file, ", passed to pure/const");
-	  if (escape_mask & ESCAPE_IS_GLOBAL)
-	    fprintf (file, ", is global var");
-	  if (escape_mask & ESCAPE_IS_PARM)
-	    fprintf (file, ", is incoming pointer");
-	  if (escape_mask & ESCAPE_UNKNOWN)
-	    fprintf (file, ", unknown escape");
-	  fprintf (file, " )");
-	}
+      fprintf (file, " (");
+      if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
+	fprintf (file, ", stored in global");
+      if (escape_mask & ESCAPE_TO_ASM)
+	fprintf (file, ", goes through ASM");
+      if (escape_mask & ESCAPE_TO_CALL)
+	fprintf (file, ", passed to call");
+      if (escape_mask & ESCAPE_BAD_CAST)
+	fprintf (file, ", bad cast");
+      if (escape_mask & ESCAPE_TO_RETURN)
+	fprintf (file, ", returned from func");
+      if (escape_mask & ESCAPE_TO_PURE_CONST)
+	fprintf (file, ", passed to pure/const");
+      if (escape_mask & ESCAPE_IS_GLOBAL)
+	fprintf (file, ", is global var");
+      if (escape_mask & ESCAPE_IS_PARM)
+	fprintf (file, ", is incoming pointer");
+      if (escape_mask & ESCAPE_UNKNOWN)
+	fprintf (file, ", unknown escape");
+      fprintf (file, " )");
     }
 
   if (gimple_default_def (cfun, var))
@@ -688,8 +685,12 @@ set_default_def (tree var, tree def)
    else
     {
       h = (struct int_tree_map *) *loc;
+      SSA_NAME_IS_DEFAULT_DEF (h->to) = false;
       h->to = def;
     }
+
+   /* Mark DEF as the default definition for VAR.  */
+   SSA_NAME_IS_DEFAULT_DEF (def) = true;
 }
 
 /* Add VAR to the list of referenced variables if it isn't already there.  */
@@ -751,72 +752,27 @@ get_virtual_var (tree var)
   return var;
 }
 
-/* Mark all the non-SSA variables found in STMT's operands to be
-   processed by update_ssa.  */
+/* Mark all the naked symbols in STMT for SSA renaming.
+   
+   NOTE: This function should only be used for brand new statements.
+   If the caller is modifying an existing statement, it should use the
+   combination push_stmt_changes/pop_stmt_changes.  */
 
 void
-mark_new_vars_to_rename (tree stmt)
+mark_symbols_for_renaming (tree stmt)
 {
+  tree op;
   ssa_op_iter iter;
-  tree val;
-  bitmap vars_in_vops_to_rename;
-  bool found_exposed_symbol = false;
-  int v_may_defs_before, v_may_defs_after;
-  int v_must_defs_before, v_must_defs_after;
-
-  if (TREE_CODE (stmt) == PHI_NODE)
-    return;
-
-  get_stmt_ann (stmt);
-  vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
-
-  /* Before re-scanning the statement for operands, mark the existing
-     virtual operands to be renamed again.  We do this because when new
-     symbols are exposed, the virtual operands that were here before due to
-     aliasing will probably be removed by the call to get_stmt_operand.
-     Therefore, we need to flag them to be renamed beforehand.
-
-     We flag them in a separate bitmap because we don't really want to
-     rename them if there are not any newly exposed symbols in the
-     statement operands.  */
-  v_may_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
-  v_must_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
 
-  FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, 
-			     SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
-    {
-      if (!DECL_P (val))
-	val = SSA_NAME_VAR (val);
-      bitmap_set_bit (vars_in_vops_to_rename, DECL_UID (val));
-    }
-
-  /* Now force an operand re-scan on the statement and mark any newly
-     exposed variables.  */
   update_stmt (stmt);
 
-  v_may_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
-  v_must_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
-
-  FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
-    if (DECL_P (val))
-      {
-	found_exposed_symbol = true;
-	mark_sym_for_renaming (val);
-      }
-
-  /* If we found any newly exposed symbols, or if there are fewer VDEF
-     operands in the statement, add the variables we had set in
-     VARS_IN_VOPS_TO_RENAME to VARS_TO_RENAME.  We need to check for
-     vanishing VDEFs because in those cases, the names that were formerly
-     generated by this statement are not going to be available anymore.  */
-  if (found_exposed_symbol
-      || v_may_defs_before > v_may_defs_after
-      || v_must_defs_before > v_must_defs_after)
-    mark_set_for_renaming (vars_in_vops_to_rename);
-
-  BITMAP_FREE (vars_in_vops_to_rename);
+  /* Mark all the operands for renaming.  */
+  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
+    if (DECL_P (op))
+      mark_sym_for_renaming (op);
 }
 
+
 /* Find all variables within the gimplified statement that were not previously
    visible to the function and add them to the referenced variables list.  */
 
@@ -845,7 +801,7 @@ find_new_referenced_vars (tree *stmt_p)
 }
 
 
-/* If REF is a handled component reference for a structure, return the
+/* If EXP is a handled component reference for a structure, return the
    base variable.  The access range is delimited by bit positions *POFFSET and
    *POFFSET + *PMAX_SIZE.  The access size is *PSIZE bits.  If either
    *PSIZE or *PMAX_SIZE is -1, they could not be determined.  If *PSIZE
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index bc4c3946335b..49be48e1009d 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -587,7 +587,14 @@ num_imm_uses (tree var)
   return num;
 }
 
-
+/* Return true if VAR has no immediate uses.  */
+static inline bool
+zero_imm_uses_p (tree var)
+{
+  ssa_use_operand_t *ptr = &(SSA_NAME_IMM_USE_NODE (var));
+  return (ptr == ptr->next);
+}
+ 
 /* Return the tree pointer to by USE.  */ 
 static inline tree
 get_use_from_ptr (use_operand_p use)
@@ -1712,6 +1719,35 @@ overlap_subvar (unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size,
 
 }
 
+/* Return the memory tag associated with symbol SYM.  */
+
+static inline tree
+symbol_mem_tag (tree sym)
+{
+  tree tag = get_var_ann (sym)->symbol_mem_tag;
+
+#if defined ENABLE_CHECKING
+  if (tag)
+    gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
+#endif
+
+  return tag;
+}
+
+
+/* Set the memory tag associated with symbol SYM.  */
+
+static inline void
+set_symbol_mem_tag (tree sym, tree tag)
+{
+#if defined ENABLE_CHECKING
+  if (tag)
+    gcc_assert (TREE_CODE (tag) == SYMBOL_MEMORY_TAG);
+#endif
+
+  get_var_ann (sym)->symbol_mem_tag = tag;
+}
+
 /* Get the value handle of EXPR.  This is the only correct way to get
    the value handle for a "thing".  If EXPR does not have a value
    handle associated, it returns NULL_TREE.  
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index aa36ad4940de..2a5476422823 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -675,7 +675,7 @@ extern void dump_subvars_for (FILE *, tree);
 extern void debug_subvars_for (tree);
 extern tree get_virtual_var (tree);
 extern void add_referenced_var (tree);
-extern void mark_new_vars_to_rename (tree);
+extern void mark_symbols_for_renaming (tree);
 extern void find_new_referenced_vars (tree *);
 
 extern tree make_rename_temp (tree, const char *);
@@ -733,7 +733,6 @@ extern bool tree_ssa_useless_type_conversion (tree);
 extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
 extern void verify_ssa (bool);
 extern void delete_tree_ssa (void);
-extern void register_new_def (tree, VEC(tree,heap) **);
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 extern bool stmt_references_memory_p (tree);
 
@@ -746,7 +745,7 @@ bool need_ssa_update_p (void);
 bool name_mappings_registered_p (void);
 bool name_registered_for_update_p (tree);
 bitmap ssa_names_to_replace (void);
-void release_ssa_name_after_update_ssa (tree name);
+void release_ssa_name_after_update_ssa (tree);
 void compute_global_livein (bitmap, bitmap);
 tree duplicate_ssa_name (tree, tree);
 void mark_sym_for_renaming (tree);
@@ -906,21 +905,22 @@ extern enum move_pos movement_possibility (tree);
 
 /* The reasons a variable may escape a function.  */
 enum escape_type 
-  {
-    NO_ESCAPE = 0, /* Doesn't escape.  */
-    ESCAPE_STORED_IN_GLOBAL = 1 << 1,
-    ESCAPE_TO_ASM = 1 << 2,  /* Passed by address to an assembly
-				statement.  */
-    ESCAPE_TO_CALL = 1 << 3,  /* Escapes to a function call.  */
-    ESCAPE_BAD_CAST = 1 << 4, /* Cast from pointer to integer */
-    ESCAPE_TO_RETURN = 1 << 5, /* Returned from function.  */
-    ESCAPE_TO_PURE_CONST = 1 << 6, /* Escapes to a pure or constant
-				      function call.  */
-    ESCAPE_IS_GLOBAL = 1 << 7,  /* Is a global variable.  */
-    ESCAPE_IS_PARM = 1 << 8, /* Is an incoming function parameter.  */
-    ESCAPE_UNKNOWN = 1 << 9 /* We believe it escapes for some reason
-			       not enumerated above.  */
-  };
+{
+  NO_ESCAPE = 0,			/* Doesn't escape.  */
+  ESCAPE_STORED_IN_GLOBAL = 1 << 1,
+  ESCAPE_TO_ASM = 1 << 2,		/* Passed by address to an assembly
+					   statement.  */
+  ESCAPE_TO_CALL = 1 << 3,		/* Escapes to a function call.  */
+  ESCAPE_BAD_CAST = 1 << 4,		/* Cast from pointer to integer */
+  ESCAPE_TO_RETURN = 1 << 5,		/* Returned from function.  */
+  ESCAPE_TO_PURE_CONST = 1 << 6,	/* Escapes to a pure or constant
+					   function call.  */
+  ESCAPE_IS_GLOBAL = 1 << 7,		/* Is a global variable.  */
+  ESCAPE_IS_PARM = 1 << 8,		/* Is an incoming function argument.  */
+  ESCAPE_UNKNOWN = 1 << 9		/* We believe it escapes for
+					   some reason not enumerated
+					   above.  */
+};
 
 /* In tree-flow-inline.h  */
 static inline bool is_call_clobbered (tree);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 90f3dd359d3b..fa71f5a5ac76 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1225,7 +1225,7 @@ insert_phi_nodes (bitmap *dfs)
    variable (SSA_NAME_VAR (DEF)) and push VAR's current reaching definition
    into the stack pointed to by BLOCK_DEFS_P.  */
 
-void
+static void
 register_new_def (tree def, VEC(tree,heap) **block_defs_p)
 {
   tree var = SSA_NAME_VAR (def);
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 8197f1ac9b8b..c65a31a1c0bd 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -125,7 +125,7 @@ create_temp (tree t)
   /* add_referenced_var will create the annotation and set up some
      of the flags in the annotation.  However, some flags we need to
      inherit from our original variable.  */
-  var_ann (tmp)->symbol_mem_tag = var_ann (t)->symbol_mem_tag;
+  set_symbol_mem_tag (tmp, symbol_mem_tag (t));
   if (is_call_clobbered (t))
     mark_call_clobbered (tmp, var_ann (t)->escape_mask);
 
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index bd47befd6796..9ce6f6bd2e8c 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1844,12 +1844,11 @@ pointer_used_p (tree ptr)
   imm_use_iterator imm_iter;
   tree stmt, rhs;
   struct ptr_info_def *pi = get_ptr_info (ptr);
-  var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
 
   /* Check whether the pointer has a memory tag; if it does, it is
      (or at least used to be) dereferenced.  */
   if ((pi != NULL && pi->name_mem_tag != NULL)
-      || v_ann->symbol_mem_tag)
+      || symbol_mem_tag (SSA_NAME_VAR (ptr)))
     return true;
 
   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ptr)
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 1dced7229422..843e056f7c90 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1436,9 +1436,13 @@ struct tree_opt_pass pass_ccp =
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */
-  TODO_cleanup_cfg | TODO_dump_func | TODO_update_ssa
-    | TODO_ggc_collect | TODO_verify_ssa
-    | TODO_verify_stmts | TODO_update_smt_usage, /* todo_flags_finish */
+  TODO_cleanup_cfg
+    | TODO_dump_func
+    | TODO_update_ssa
+    | TODO_ggc_collect
+    | TODO_verify_ssa
+    | TODO_verify_stmts
+    | TODO_update_smt_usage,		/* todo_flags_finish */
   0					/* letter */
 };
 
@@ -1474,10 +1478,13 @@ struct tree_opt_pass pass_store_ccp =
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */
-  TODO_dump_func | TODO_update_ssa
-    | TODO_ggc_collect | TODO_verify_ssa
+  TODO_dump_func
+    | TODO_update_ssa
+    | TODO_ggc_collect
+    | TODO_verify_ssa
     | TODO_cleanup_cfg
-    | TODO_verify_stmts | TODO_update_smt_usage, /* todo_flags_finish */
+    | TODO_verify_stmts
+    | TODO_update_smt_usage,		/* todo_flags_finish */
   0					/* letter */
 };
 
@@ -2512,7 +2519,7 @@ convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr, bool ignore)
       tree new_stmt = tsi_stmt (ti);
       find_new_referenced_vars (tsi_stmt_ptr (ti));
       bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
-      mark_new_vars_to_rename (bsi_stmt (*si_p));
+      mark_symbols_for_renaming (new_stmt);
       bsi_next (si_p);
     }
 
@@ -2574,6 +2581,8 @@ execute_fold_all_builtins (void)
 	      print_generic_stmt (dump_file, *stmtp, dump_flags);
 	    }
 
+	  push_stmt_changes (stmtp);
+
 	  if (!set_rhs (stmtp, result))
 	    {
 	      result = convert_to_gimple_builtin (&i, result,
@@ -2582,11 +2591,12 @@ execute_fold_all_builtins (void)
 	      if (result)
 		{
 		  bool ok = set_rhs (stmtp, result);
-		  
 		  gcc_assert (ok);
 		}
 	    }
-	  mark_new_vars_to_rename (*stmtp);
+
+	  pop_stmt_changes (stmtp);
+
 	  if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
 	      && tree_purge_dead_eh_edges (bb))
 	    cfg_changed = true;
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index dcd4b86b42a6..a2d8f1fecb31 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -101,7 +101,11 @@ static VEC(tree,heap) *avail_exprs_stack;
    expressions are removed from AVAIL_EXPRS.  Else we may change the
    hash code for an expression and be unable to find/remove it from
    AVAIL_EXPRS.  */
-static VEC(tree,heap) *stmts_to_rescan;
+typedef tree *tree_p;
+DEF_VEC_P(tree_p);
+DEF_VEC_ALLOC_P(tree_p,heap);
+
+static VEC(tree_p,heap) *stmts_to_rescan;
 
 /* Structure for entries in the expression hash table.
 
@@ -247,7 +251,7 @@ tree_ssa_dominator_optimize (void)
   avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free);
   avail_exprs_stack = VEC_alloc (tree, heap, 20);
   const_and_copies_stack = VEC_alloc (tree, heap, 20);
-  stmts_to_rescan = VEC_alloc (tree, heap, 20);
+  stmts_to_rescan = VEC_alloc (tree_p, heap, 20);
   need_eh_cleanup = BITMAP_ALLOC (NULL);
 
   /* Setup callbacks for the generic dominator tree walker.  */
@@ -359,7 +363,7 @@ tree_ssa_dominator_optimize (void)
   
   VEC_free (tree, heap, avail_exprs_stack);
   VEC_free (tree, heap, const_and_copies_stack);
-  VEC_free (tree, heap, stmts_to_rescan);
+  VEC_free (tree_p, heap, stmts_to_rescan);
   return 0;
 }
 
@@ -701,16 +705,17 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
 
   /* If we queued any statements to rescan in this block, then
      go ahead and rescan them now.  */
-  while (VEC_length (tree, stmts_to_rescan) > 0)
+  while (VEC_length (tree_p, stmts_to_rescan) > 0)
     {
-      tree stmt = VEC_last (tree, stmts_to_rescan);
+      tree *stmt_p = VEC_last (tree_p, stmts_to_rescan);
+      tree stmt = *stmt_p;
       basic_block stmt_bb = bb_for_stmt (stmt);
 
       if (stmt_bb != bb)
 	break;
 
-      VEC_pop (tree, stmts_to_rescan);
-      mark_new_vars_to_rename (stmt);
+      VEC_pop (tree_p, stmts_to_rescan);
+      pop_stmt_changes (stmt_p);
     }
 }
 
@@ -1557,9 +1562,7 @@ eliminate_redundant_computations (tree stmt)
    Detect and record those equivalences.  */
 
 static void
-record_equivalences_from_stmt (tree stmt,
-			       int may_optimize_p,
-			       stmt_ann_t ann)
+record_equivalences_from_stmt (tree stmt, int may_optimize_p, stmt_ann_t ann)
 {
   tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
   enum tree_code lhs_code = TREE_CODE (lhs);
@@ -1588,6 +1591,7 @@ record_equivalences_from_stmt (tree stmt,
      vops and recording the result in the available expression table,
      we may be able to expose more redundant loads.  */
   if (!ann->has_volatile_ops
+      && stmt_references_memory_p (stmt)
       && (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME
 	  || is_gimple_min_invariant (GIMPLE_STMT_OPERAND (stmt, 1)))
       && !is_gimple_reg (lhs))
@@ -1621,7 +1625,7 @@ record_equivalences_from_stmt (tree stmt,
 	  /* Build a new statement with the RHS and LHS exchanged.  */
 	  new = build2_gimple (GIMPLE_MODIFY_STMT, rhs, lhs);
 
-	  create_ssa_artficial_load_stmt (new, stmt);
+	  create_ssa_artificial_load_stmt (new, stmt);
 
 	  /* Finally enter the statement into the available expression
 	     table.  */
@@ -1741,7 +1745,7 @@ cprop_operand (tree stmt, use_operand_p op_p)
    known value for that SSA_NAME (or NULL if no value is known).  
 
    Propagate values from CONST_AND_COPIES into the uses, vuses and
-   v_may_def_ops of STMT.  */
+   vdef_ops of STMT.  */
 
 static bool
 cprop_into_stmt (tree stmt)
@@ -1793,6 +1797,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
   ann = stmt_ann (stmt);
   opt_stats.num_stmts++;
   may_have_exposed_new_symbols = false;
+  push_stmt_changes (bsi_stmt_ptr (si));
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -1800,7 +1805,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
       print_generic_stmt (dump_file, stmt, TDF_SLIM);
     }
 
-  /* Const/copy propagate into USES, VUSES and the RHS of V_MAY_DEFs.  */
+  /* Const/copy propagate into USES, VUSES and the RHS of VDEFs.  */
   may_have_exposed_new_symbols = cprop_into_stmt (stmt);
 
   /* If the statement has been modified with constant replacements,
@@ -1856,9 +1861,7 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
 
   /* Record any additional equivalences created by this statement.  */
   if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
-    record_equivalences_from_stmt (stmt,
-				   may_optimize_p,
-				   ann);
+    record_equivalences_from_stmt (stmt, may_optimize_p, ann);
 
   /* If STMT is a COND_EXPR and it was modified, then we may know
      where it goes.  If that is the case, then mark the CFG as altered.
@@ -1885,7 +1888,6 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
 
      Ultimately I suspect we're going to need to change the interface
      into the SSA_NAME manager.  */
-
   if (ann->modified)
     {
       tree val = NULL;
@@ -1909,7 +1911,20 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
     }
 
   if (may_have_exposed_new_symbols)
-    VEC_safe_push (tree, heap, stmts_to_rescan, bsi_stmt (si));
+    {
+      /* Queue the statement to be re-scanned after all the
+	 AVAIL_EXPRS have been processed.  The change buffer stack for
+	 all the pushed statements will be processed when this queue
+	 is emptied.  */
+      VEC_safe_push (tree_p, heap, stmts_to_rescan, bsi_stmt_ptr (si));
+    }
+  else
+    {
+      /* Otherwise, just discard the recently pushed change buffer.  If
+	 not, the STMTS_TO_RESCAN queue will get out of synch with the
+	 change buffer stack.  */
+      discard_stmt_changes (bsi_stmt_ptr (si));
+    }
 }
 
 /* Search for an existing instance of STMT in the AVAIL_EXPRS table.  If
@@ -2185,6 +2200,8 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
 	      fprintf (dump_file, "\n");
 	    }
 
+	  push_stmt_changes (&use_stmt);
+
 	  /* Propagate the RHS into this use of the LHS.  */
 	  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
 	    propagate_value (use_p, rhs);
@@ -2219,6 +2236,8 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
 		  tree result = get_lhs_or_phi_result (use_stmt);
 		  bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
 		}
+
+	      discard_stmt_changes (&use_stmt);
 	      continue;
 	    }
 
@@ -2231,7 +2250,7 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
 	  /* Sometimes propagation can expose new operands to the
 	     renamer.  Note this will call update_stmt at the 
 	     appropriate time.  */
-	  mark_new_vars_to_rename (use_stmt);
+	  pop_stmt_changes (&use_stmt);
 
 	  /* Dump details.  */
 	  if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 492c9a0ada41..638224a80356 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -586,7 +586,7 @@ tidy_after_forward_propagate_addr (tree stmt)
   if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR)
      recompute_tree_invariant_for_addr_expr (GIMPLE_STMT_OPERAND (stmt, 1));
 
-  mark_new_vars_to_rename (stmt);
+  mark_symbols_for_renaming (stmt);
 }
 
 /* STMT defines LHS which is contains the address of the 0th element
@@ -856,9 +856,13 @@ forward_propagate_addr_expr (tree stmt, bool *some)
 	  continue;
 	}
       
+      push_stmt_changes (&use_stmt);
+
       result = forward_propagate_addr_expr_1 (stmt, use_stmt, some);
       *some |= result;
       all &= result;
+
+      pop_stmt_changes (&use_stmt);
     }
 
   return all;
@@ -1051,8 +1055,9 @@ struct tree_opt_pass pass_forwprop = {
   0,				/* properties_provided */
   0,				/* properties_destroyed */
   0,				/* todo_flags_start */
-  TODO_dump_func /* todo_flags_finish */
+  TODO_dump_func
   | TODO_ggc_collect
-  | TODO_update_ssa | TODO_verify_ssa,
-  0					/* letter */
+  | TODO_update_ssa
+  | TODO_verify_ssa,		/* todo_flags_finish */
+  0				/* letter */
 };
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index ca95823f6a23..454374010aa2 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5556,7 +5556,7 @@ get_ref_tag (tree ref, tree orig)
 	}
  
       var = SSA_NAME_VAR (var);
-      tag = var_ann (var)->symbol_mem_tag;
+      tag = symbol_mem_tag (var);
       gcc_assert (tag != NULL_TREE);
       return tag;
     }
@@ -5565,7 +5565,7 @@ get_ref_tag (tree ref, tree orig)
       if (!DECL_P (var))
 	return NULL_TREE;
 
-      tag = var_ann (var)->symbol_mem_tag;
+      tag = symbol_mem_tag (var);
       if (tag)
 	return tag;
 
@@ -5657,9 +5657,10 @@ rewrite_use_compare (struct ivopts_data *data,
 /* Rewrites USE using candidate CAND.  */
 
 static void
-rewrite_use (struct ivopts_data *data,
-	     struct iv_use *use, struct iv_cand *cand)
+rewrite_use (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
 {
+  push_stmt_changes (&use->stmt);
+
   switch (use->type)
     {
       case USE_NONLINEAR_EXPR:
@@ -5677,7 +5678,8 @@ rewrite_use (struct ivopts_data *data,
       default:
 	gcc_unreachable ();
     }
-  mark_new_vars_to_rename (use->stmt);
+
+  pop_stmt_changes (&use->stmt);
 }
 
 /* Rewrite the uses using the selected induction variables.  */
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index c92c0e72a2c7..cac13ebf469c 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -121,6 +121,49 @@ static void get_expr_operands (tree, tree *, int);
 /* Number of functions with initialized ssa_operands.  */
 static int n_initialized = 0;
 
+/* Statement change buffer.  Data structure used to record state
+   information for statements.  This is used to determine what needs
+   to be done in order to update the SSA web after a statement is
+   modified by a pass.  If STMT is a statement that has just been
+   created, or needs to be folded via fold_stmt, or anything that
+   changes its physical structure then the pass should:
+
+   1- Call push_stmt_changes (&stmt) to record the current state of
+      STMT before any modifications are made.
+
+   2- Make all appropriate modifications to the statement.
+
+   3- Call pop_stmt_changes (&stmt) to find new symbols that
+      need to be put in SSA form, SSA name mappings for names that
+      have disappeared, recompute invariantness for address
+      expressions, cleanup EH information, etc.
+
+   If it is possible to determine that the statement was not modified,
+   instead of calling pop_stmt_changes it is quicker to call
+   discard_stmt_changes to avoid the expensive and unnecessary operand
+   re-scan and change comparison.  */
+
+struct scb_d
+{
+  /* Pointer to the statement being modified.  */
+  tree *stmt_p;
+
+  /* If the statement references memory these are the sets of symbols
+     loaded and stored by the statement.  */
+  bitmap loads;
+  bitmap stores;
+};
+
+typedef struct scb_d *scb_t;
+DEF_VEC_P(scb_t);
+DEF_VEC_ALLOC_P(scb_t,heap);
+
+/* Stack of statement change buffers (SCB).  Every call to
+   push_stmt_changes pushes a new buffer onto the stack.  Calls to
+   pop_stmt_changes pop a buffer off of the stack and compute the set
+   of changes for the popped statement.  */
+static VEC(scb_t,heap) *scb_stack;
+
 /* Allocates operand OP of given TYPE from the appropriate free list,
    or of the new value if the list is empty.  */
 
@@ -2277,7 +2320,7 @@ copy_virtual_operands (tree dest, tree src)
    values stored.  */
 
 void
-create_ssa_artficial_load_stmt (tree new_stmt, tree old_stmt)
+create_ssa_artificial_load_stmt (tree new_stmt, tree old_stmt)
 {
   stmt_ann_t ann;
   tree op;
@@ -2567,3 +2610,206 @@ debug_immediate_uses_for (tree var)
 {
   dump_immediate_uses_for (stderr, var);
 }
+
+
+/* Create a new change buffer for the statement pointed by STMT_P and
+   push the buffer into SCB_STACK.  Each change buffer
+   records state information needed to determine what changed in the
+   statement.  Mainly, this keeps track of symbols that may need to be
+   put into SSA form, SSA name replacements and other information
+   needed to keep the SSA form up to date.  */
+
+void
+push_stmt_changes (tree *stmt_p)
+{
+  tree stmt;
+  scb_t buf;
+  
+  stmt = *stmt_p;
+
+  /* It makes no sense to keep track of PHI nodes.  */
+  if (TREE_CODE (stmt) == PHI_NODE)
+    return;
+
+  buf = xmalloc (sizeof *buf);
+  memset (buf, 0, sizeof *buf);
+
+  buf->stmt_p = stmt_p;
+
+  if (stmt_references_memory_p (stmt))
+    {
+      tree op;
+      ssa_op_iter i;
+
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
+	{
+	  tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
+	  if (buf->loads == NULL)
+	    buf->loads = BITMAP_ALLOC (NULL);
+	  bitmap_set_bit (buf->loads, DECL_UID (sym));
+	}
+
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VIRTUAL_DEFS)
+	{
+	  tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
+	  if (buf->stores == NULL)
+	    buf->stores = BITMAP_ALLOC (NULL);
+	  bitmap_set_bit (buf->stores, DECL_UID (sym));
+	}
+    }
+
+  VEC_safe_push (scb_t, heap, scb_stack, buf);
+}
+
+
+/* Given two sets S1 and S2, mark the symbols that differ in S1 and S2
+   for renaming.  The set to mark for renaming is (S1 & ~S2) | (S2 & ~S1).  */
+
+static void
+mark_difference_for_renaming (bitmap s1, bitmap s2)
+{
+  if (s1 == NULL && s2 == NULL)
+    return;
+
+  if (s1 && s2 == NULL)
+    mark_set_for_renaming (s1);
+  else if (s1 == NULL && s2)
+    mark_set_for_renaming (s2);
+  else if (!bitmap_equal_p (s1, s2))
+    {
+      bitmap t1 = BITMAP_ALLOC (NULL);
+      bitmap t2 = BITMAP_ALLOC (NULL);
+
+      bitmap_and_compl (t1, s1, s2);
+      bitmap_and_compl (t2, s2, s1);
+      bitmap_ior_into (t1, t2);
+      mark_set_for_renaming (t1);
+
+      BITMAP_FREE (t1);
+      BITMAP_FREE (t2);
+    }
+}
+
+
+/* Pop the top SCB from SCB_STACK and act on the differences between
+   what was recorded by push_stmt_changes and the current state of
+   the statement.  */
+
+void
+pop_stmt_changes (tree *stmt_p)
+{
+  tree op, stmt;
+  ssa_op_iter iter;
+  bitmap loads, stores;
+  scb_t buf;
+
+  stmt = *stmt_p;
+
+  /* It makes no sense to keep track of PHI nodes.  */
+  if (TREE_CODE (stmt) == PHI_NODE)
+    return;
+
+  buf = VEC_pop (scb_t, scb_stack);
+  gcc_assert (stmt_p == buf->stmt_p);
+
+  /* Force an operand re-scan on the statement and mark any newly
+     exposed variables.  */
+  update_stmt (stmt);
+
+  /* Determine whether any memory symbols need to be renamed.  If the
+     sets of loads and stores are different after the statement is
+     modified, then the affected symbols need to be renamed.
+     
+     Note that it may be possible for the statement to not reference
+     memory anymore, but we still need to act on the differences in
+     the sets of symbols.  */
+  loads = stores = NULL;
+  if (stmt_references_memory_p (stmt))
+    {
+      tree op;
+      ssa_op_iter i;
+
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VUSE)
+	{
+	  tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
+	  if (loads == NULL)
+	    loads = BITMAP_ALLOC (NULL);
+	  bitmap_set_bit (loads, DECL_UID (sym));
+	}
+
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_VIRTUAL_DEFS)
+	{
+	  tree sym = TREE_CODE (op) == SSA_NAME ? SSA_NAME_VAR (op) : op;
+	  if (stores == NULL)
+	    stores = BITMAP_ALLOC (NULL);
+	  bitmap_set_bit (stores, DECL_UID (sym));
+
+	  /* If a V_MAY_DEF turned into a V_MUST_DEF, we will keep
+	     referencing the same symbol, but we still need to mark it
+	     for renaming since the operand scanner stripped its
+	     SSA_NAME.  */
+	  if (op == sym)
+	    mark_sym_for_renaming (sym);
+	}
+    }
+
+  /* If LOADS is different from BUF->LOADS, the affected
+     symbols need to be marked for renaming.  */
+  mark_difference_for_renaming (loads, buf->loads);
+
+  /* Similarly for STORES and BUF->STORES.  */
+  mark_difference_for_renaming (stores, buf->stores);
+
+  /* Mark all the naked GIMPLE register operands for renaming.  */
+  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
+    if (DECL_P (op))
+      mark_sym_for_renaming (op);
+
+  /* FIXME, need to add more finalizers here.  Cleanup EH info,
+     recompute invariants for address expressions, add
+     SSA replacement mappings, etc.  For instance, given
+     testsuite/gcc.c-torture/compile/pr16808.c, we fold a statement of
+     the form:
+
+	  # SMT.4_20 = VDEF <SMT.4_16>
+	  D.1576_11 = 1.0e+0;
+
+     So, the VDEF will disappear, but instead of marking SMT.4 for
+     renaming it would be far more efficient to establish a
+     replacement mapping that would replace every reference of
+     SMT.4_20 with SMT.4_16.  */
+
+  /* Free memory used by the buffer.  */
+  BITMAP_FREE (buf->loads);
+  BITMAP_FREE (buf->stores);
+  BITMAP_FREE (loads);
+  BITMAP_FREE (stores);
+  buf->stmt_p = NULL;
+  free (buf);
+}
+
+
+/* Discard the topmost change buffer from SCB_STACK.  This is useful
+   when the caller realized that it did not actually modified the
+   statement.  It avoids the expensive operand re-scan.  */
+
+void
+discard_stmt_changes (tree *stmt_p)
+{
+  scb_t buf;
+  tree stmt;
+  
+  /* It makes no sense to keep track of PHI nodes.  */
+  stmt = *stmt_p;
+  if (TREE_CODE (stmt) == PHI_NODE)
+    return;
+
+  buf = VEC_pop (scb_t, scb_stack);
+  gcc_assert (stmt_p == buf->stmt_p);
+
+  /* Free memory used by the buffer.  */
+  BITMAP_FREE (buf->loads);
+  BITMAP_FREE (buf->stores);
+  buf->stmt_p = NULL;
+  free (buf);
+}
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index aecbcdc314dc..17c1f6bb8e30 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -171,7 +171,7 @@ extern void update_stmt_operands (tree);
 extern bool verify_imm_links (FILE *f, tree var);
 
 extern void copy_virtual_operands (tree, tree);
-extern void create_ssa_artficial_load_stmt (tree, tree);
+extern void create_ssa_artificial_load_stmt (tree, tree);
 
 extern void dump_immediate_uses (FILE *file);
 extern void dump_immediate_uses_for (FILE *file, tree var);
@@ -181,6 +181,9 @@ extern void debug_immediate_uses_for (tree var);
 extern bool ssa_operands_active (void);
 
 extern void add_to_addressable_set (tree, bitmap *);
+extern void push_stmt_changes (tree *);
+extern void pop_stmt_changes (tree *);
+extern void discard_stmt_changes (tree *);
 
 enum ssa_op_iter_type {
   ssa_op_iter_none = 0,
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index c0c5d5eabfdf..24274619914c 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2616,7 +2616,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
 	  vn_add (forcedname, val);
 	  bitmap_value_replace_in_set (NEW_SETS (block), forcedname);
 	  bitmap_value_replace_in_set (AVAIL_OUT (block), forcedname);
-	  mark_new_vars_to_rename (stmt);
+	  mark_symbols_for_renaming (stmt);
 	}
       tsi = tsi_last (stmts);
       tsi_link_after (&tsi, forced_stmts, TSI_CONTINUE_LINKING);
@@ -2644,7 +2644,9 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
   tsi = tsi_last (stmts);
   tsi_link_after (&tsi, newexpr, TSI_CONTINUE_LINKING);
   VEC_safe_push (tree, heap, inserted_exprs, newexpr);
-  mark_new_vars_to_rename (newexpr);
+
+  /* All the symbols in NEWEXPR should be put into SSA form.  */
+  mark_symbols_for_renaming (newexpr);
 
   /* Add a value handle to the temporary.
      The value may already exist in either NEW_SETS, or AVAIL_OUT, because
@@ -3543,7 +3545,7 @@ insert_fake_stores (void)
 
 	      lhs = make_ssa_name (storetemp, new);
 	      GIMPLE_STMT_OPERAND (new, 0) = lhs;
-	      create_ssa_artficial_load_stmt (new, stmt);
+	      create_ssa_artificial_load_stmt (new, stmt);
 
 	      NECESSARY (new) = 0;
 	      VEC_safe_push (tree, heap, inserted_exprs, new);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index b787aae70ba3..49277a037c2c 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1176,6 +1176,9 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
 	      && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ASSERT_EXPR)
 	    continue;
 
+	  /* Record the state of the statement before replacements.  */
+	  push_stmt_changes (bsi_stmt_ptr (i));
+
 	  /* Replace the statement with its folded version and mark it
 	     folded.  */
 	  did_replace = false;
@@ -1211,10 +1214,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
 	      fold_stmt (bsi_stmt_ptr (i));
 	      stmt = bsi_stmt (i);
 
-	      /* If we folded a builtin function, we'll likely
-		 need to rename VDEFs.  */
-	      mark_new_vars_to_rename (stmt);
-
               /* If we cleaned up EH information from the statement,
                  remove EH edges.  */
 	      if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
@@ -1232,6 +1231,14 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
 		  print_generic_stmt (dump_file, stmt, TDF_SLIM);
 		  fprintf (dump_file, "\n");
 		}
+
+	      /* Determine what needs to be done to update the SSA form.  */
+	      pop_stmt_changes (bsi_stmt_ptr (i));
+	    }
+	  else
+	    {
+	      /* The statement was not modified, discard the change buffer.  */
+	      discard_stmt_changes (bsi_stmt_ptr (i));
 	    }
 
 	  /* Some statements may be simplified using ranges.  For
@@ -1242,7 +1249,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
 	     statement.  */
 	  if (use_ranges_p)
 	    simplify_stmt_using_ranges (stmt);
-
 	}
     }
 
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 17c4c6f4a529..5e7826150725 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -264,7 +264,7 @@ get_rank (tree e)
       int i;
 
       if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
-	  && e == gimple_default_def (cfun, SSA_NAME_VAR (e)))
+	  && SSA_NAME_IS_DEFAULT_DEF (e))
 	return find_operand_rank (e)->rank;
 
       stmt = SSA_NAME_DEF_STMT (e);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index a8716dad8d16..5404edded823 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -152,6 +152,7 @@ make_ssa_name (tree var, tree stmt)
   SSA_NAME_DEF_STMT (t) = stmt;
   SSA_NAME_PTR_INFO (t) = NULL;
   SSA_NAME_IN_FREE_LIST (t) = 0;
+  SSA_NAME_IS_DEFAULT_DEF (t) = 0;
   imm = &(SSA_NAME_IMM_USE_NODE (t));
   imm->use = NULL;
   imm->prev = imm;
@@ -178,7 +179,7 @@ release_ssa_name (tree var)
 
   /* Never release the default definition for a symbol.  It's a
      special SSA name that should always exist once it's created.  */
-  if (var == gimple_default_def (cfun, SSA_NAME_VAR (var)))
+  if (SSA_NAME_IS_DEFAULT_DEF (var))
     return;
 
   /* If VAR has been registered for SSA updating, don't remove it.
diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c
index 56c7adee0f3e..d1caf5c92ebf 100644
--- a/gcc/tree-vect-transform.c
+++ b/gcc/tree-vect-transform.c
@@ -3162,7 +3162,7 @@ vect_permute_load_chain (VEC(tree,heap) *dr_chain,
 	  data_ref = make_ssa_name (perm_dest, perm_stmt);
 	  GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
 	  vect_finish_stmt_generation (stmt, perm_stmt, bsi);
-	  mark_new_vars_to_rename (perm_stmt);
+	  mark_symbols_for_renaming (perm_stmt);
 
 	  VEC_replace (tree, *result_chain, j/2, data_ref);	      
 	      
@@ -3176,7 +3176,7 @@ vect_permute_load_chain (VEC(tree,heap) *dr_chain,
 	  data_ref = make_ssa_name (perm_dest, perm_stmt);
 	  GIMPLE_STMT_OPERAND (perm_stmt, 0) = data_ref;
 	  vect_finish_stmt_generation (stmt, perm_stmt, bsi);
-	  mark_new_vars_to_rename (perm_stmt);
+	  mark_symbols_for_renaming (perm_stmt);
 
 	  VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
 	}
@@ -3540,7 +3540,7 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
 	  GIMPLE_STMT_OPERAND (new_stmt, 0) = new_temp;
 	  vect_finish_stmt_generation (stmt, new_stmt, bsi);
 	  copy_virtual_operands (new_stmt, stmt);
-	  mark_new_vars_to_rename (new_stmt);
+	  mark_symbols_for_renaming (new_stmt);
 
 	  /* 3. Handle explicit realignment if necessary/supported.  */
 	  if (alignment_support_cheme == dr_unaligned_software_pipeline)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 8e9d3cad7a59..483607ec5544 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -273,7 +273,7 @@ get_value_range (tree var)
   /* If VAR is a default definition, the variable can take any value
      in VAR's type.  */
   sym = SSA_NAME_VAR (var);
-  if (var == gimple_default_def (cfun, sym))
+  if (SSA_NAME_IS_DEFAULT_DEF (var))
     {
       /* Try to use the "nonnull" attribute to create ~[0, 0]
 	 anti-ranges for pointers.  Note that this is only valid with
diff --git a/gcc/tree.c b/gcc/tree.c
index 2c6f3b855b09..614de7aab784 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7306,6 +7306,9 @@ is_global_var (tree t)
 bool
 needs_to_live_in_memory (tree t)
 {
+  if (TREE_CODE (t) == SSA_NAME)
+    t = SSA_NAME_VAR (t);
+
   return (TREE_ADDRESSABLE (t)
 	  || is_global_var (t)
 	  || (TREE_CODE (t) == RESULT_DECL
diff --git a/gcc/tree.h b/gcc/tree.h
index 6a000edce83e..a6515517f9bc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1762,6 +1762,14 @@ struct tree_exp GTY(())
 #define SSA_NAME_IN_FREE_LIST(NODE) \
     SSA_NAME_CHECK (NODE)->base.nothrow_flag
 
+/* Nonzero if this SSA_NAME is the default definition for the
+   underlying symbol.  A default SSA name is created for symbol S if
+   the very first reference to S in the function is a read operation.
+   Default definitions are always created by an empty statement and
+   belong to no basic block.  */
+#define SSA_NAME_IS_DEFAULT_DEF(NODE)	\
+    SSA_NAME_CHECK (NODE)->base.volatile_flag
+
 /* Attributes for SSA_NAMEs for pointer-type variables.  */
 #define SSA_NAME_PTR_INFO(N) \
     SSA_NAME_CHECK (N)->ssa_name.ptr_info
-- 
GitLab