[committed] mainline: remove PENDING_STMT hijack

Aldy Hernandez aldyh@redhat.com
Wed Mar 5 17:15:00 GMT 2008


Hi folks.

This patch had been approved for mainline in October, but was waiting
for mainline to re-open.

http://gcc.gnu.org/ml/gcc-patches/2007-10/msg00510.html

I have merged the patch with small changes that happened in mainline,
and have retested it on x86-64 Linux with no regressions.  Below is the
updated patch which I am committing.

Aldy

        * cfg.c: Include tree-flow.h.
        (remove_edge_raw): Call redirect_edge_var_map_clear.
        (redirect_edge_succ_nodup): Call redirect_edge_var_map_dup.
        * tree-flow-inline.h (redirect_edge_var_map_def): New.
        (redirect_edge_var_map_result): New.
        * tree-cfgcleanup.c (remove_forwarder_block_with_phi): Replace
        PENDING_STMT use with redirect_edge_var_map_*.
        * tree-ssa.c (edge_var_maps): New definition.
        (redirect_edge_var_map_add): New.
        (redirect_edge_var_map_clear): New.
        (redirect_edge_var_map_dup): New.
        (redirect_edge_var_map_vector): New.
        (redirect_edge_var_map_destroy): New.
        (ssa_redirect_edge): Replace PENDING_STMT use with
        redirect_edge_var_map_*.
        (flush_pending_stmts): Same.
        (delete_tree_ssa): Destroy edge var map.
        * tree-flow.h (struct _edge_var_map): New.
        Define edge_var_map vector type.
        Declare redirect_edge_var_map_* prototypes.
        * Makefile.in (cfg.o): Depend on TREE_FLOW_H.
        * tree-cfg.c (reinstall_phi_args): Replace
        PENDING_STMT use with redirect_edge_var_map_*.

Index: cfg.c
===================================================================
--- cfg.c	(revision 132869)
+++ cfg.c	(working copy)
@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3.  
 #include "alloc-pool.h"
 #include "df.h"
 #include "cfgloop.h"
+#include "tree-flow.h"
 
 /* The obstack on which the flow graph components are allocated.  */
 
@@ -359,6 +360,9 @@ remove_edge_raw (edge e)
   disconnect_src (e);
   disconnect_dest (e);
 
+  /* This is probably not needed, but it doesn't hurt.  */
+  redirect_edge_var_map_clear (e);
+
   free_edge (e);
 }
 
@@ -395,6 +399,7 @@ redirect_edge_succ_nodup (edge e, basic_
 	s->probability = REG_BR_PROB_BASE;
       s->count += e->count;
       remove_edge (e);
+      redirect_edge_var_map_dup (s, e);
       e = s;
     }
   else
Index: tree-flow-inline.h
===================================================================
--- tree-flow-inline.h	(revision 132869)
+++ tree-flow-inline.h	(working copy)
@@ -1842,4 +1842,20 @@ gimple_mem_ref_stats (const struct funct
 {
   return &fn->gimple_df->mem_ref_stats;
 }
+
+/* Given an edge_var_map V, return the PHI arg definition.  */
+
+static inline tree
+redirect_edge_var_map_def (edge_var_map *v)
+{
+  return v->def;
+}
+
+/* Given an edge_var_map V, return the PHI result.  */
+
+static inline tree
+redirect_edge_var_map_result (edge_var_map *v)
+{
+  return v->result;
+}
 #endif /* _TREE_FLOW_INLINE_H  */
Index: tree-cfgcleanup.c
===================================================================
--- tree-cfgcleanup.c	(revision 132869)
+++ tree-cfgcleanup.c	(working copy)
@@ -748,7 +748,7 @@ remove_forwarder_block_with_phi (basic_b
 	  if (phi_alternatives_equal (dest, s, succ))
 	    {
 	      e = redirect_edge_and_branch (e, dest);
-	      PENDING_STMT (e) = NULL_TREE;
+	      redirect_edge_var_map_clear (e);
 	      continue;
 	    }
 
@@ -771,15 +771,18 @@ remove_forwarder_block_with_phi (basic_b
 
 	  if (TREE_CODE (def) == SSA_NAME)
 	    {
-	      tree var;
+	      edge_var_map_vector head;
+	      edge_var_map *vm;
+	      size_t i;
 
 	      /* If DEF is one of the results of PHI nodes removed during
 		 redirection, replace it with the PHI argument that used
 		 to be on E.  */
-	      for (var = PENDING_STMT (e); var; var = TREE_CHAIN (var))
+	      head = redirect_edge_var_map_vector (e);
+	      for (i = 0; VEC_iterate (edge_var_map, head, i, vm); ++i)
 		{
-		  tree old_arg = TREE_PURPOSE (var);
-		  tree new_arg = TREE_VALUE (var);
+		  tree old_arg = redirect_edge_var_map_result (vm);
+		  tree new_arg = redirect_edge_var_map_def (vm);
 
 		  if (def == old_arg)
 		    {
@@ -792,7 +795,7 @@ remove_forwarder_block_with_phi (basic_b
 	  add_phi_arg (phi, def, s);
 	}
 
-      PENDING_STMT (e) = NULL;
+      redirect_edge_var_map_clear (e);
     }
 
   /* Update the dominators.  */
Index: tree-ssa.c
===================================================================
--- tree-ssa.c	(revision 132869)
+++ tree-ssa.c	(working copy)
@@ -45,32 +45,147 @@ along with GCC; see the file COPYING3.  
 #include "tree-pass.h"
 #include "toplev.h"
 
+/* Pointer map of variable mappings, keyed by edge.  */
+static struct pointer_map_t *edge_var_maps;
+
+
+/* Add a mapping with PHI RESULT and PHI DEF associated with edge E.  */
+
+void
+redirect_edge_var_map_add (edge e, tree result, tree def)
+{
+  void **slot;
+  edge_var_map_vector old_head, head;
+  edge_var_map new_node;
+
+  if (edge_var_maps == NULL)
+    edge_var_maps = pointer_map_create ();
+
+  slot = pointer_map_insert (edge_var_maps, e);
+  old_head = head = *slot;
+  if (!head)
+    {
+      head = VEC_alloc (edge_var_map, heap, 5);
+      *slot = head;
+    }
+  new_node.def = def;
+  new_node.result = result;
+
+  VEC_safe_push (edge_var_map, heap, head, &new_node);
+  if (old_head != head)
+    {
+      /* The push did some reallocation.  Update the pointer map.  */
+      *slot = head;
+    }
+}
+
+
+/* Clear the var mappings in edge E.  */
+
+void
+redirect_edge_var_map_clear (edge e)
+{
+  void **slot;
+  edge_var_map_vector head;
+
+  if (!edge_var_maps)
+    return;
+
+  slot = pointer_map_contains (edge_var_maps, e);
+
+  if (slot)
+    {
+      head = *slot;
+      VEC_free (edge_var_map, heap, head);
+      *slot = NULL;
+    }
+}
+
+
+/* Duplicate the redirected var mappings in OLDE in NEWE.
+
+   Since we can't remove a mapping, let's just duplicate it.  This assumes a
+   pointer_map can have multiple edges mapping to the same var_map (many to
+   one mapping), since we don't remove the previous mappings.  */
+
+void
+redirect_edge_var_map_dup (edge newe, edge olde)
+{
+  void **new_slot, **old_slot; edge_var_map_vector head;
+
+  if (!edge_var_maps)
+    return;
+
+  new_slot = pointer_map_insert (edge_var_maps, newe);
+  old_slot = pointer_map_contains (edge_var_maps, olde);
+  if (!old_slot)
+    return;
+  head = *old_slot;
+
+  if (head)
+    *new_slot = VEC_copy (edge_var_map, heap, head);
+  else
+    *new_slot = VEC_alloc (edge_var_map, heap, 5);
+}
+
+
+/* Return the varable mappings for a given edge.  If there is none, return
+   NULL.  */
+
+edge_var_map_vector
+redirect_edge_var_map_vector (edge e)
+{
+  void **slot;
+
+  /* Hey, what kind of idiot would... you'd be surprised.  */
+  if (!edge_var_maps)
+    return NULL;
+
+  slot = pointer_map_contains (edge_var_maps, e);
+  if (!slot)
+    return NULL;
+
+  return (edge_var_map_vector) *slot;
+}
+
+
+/* Clear the edge variable mappings.  */
+
+void
+redirect_edge_var_map_destroy (void)
+{
+  if (edge_var_maps)
+    {
+      pointer_map_destroy (edge_var_maps);
+      edge_var_maps = NULL;
+    }
+}
+
+
 /* Remove the corresponding arguments from the PHI nodes in E's
    destination block and redirect it to DEST.  Return redirected edge.
-   The list of removed arguments is stored in PENDING_STMT (e).  */
+   The list of removed arguments is stored in a vector accessed
+   through edge_var_maps.  */
 
 edge
 ssa_redirect_edge (edge e, basic_block dest)
 {
   tree phi;
-  tree list = NULL, *last = &list;
-  tree src, dst, node;
+
+  redirect_edge_var_map_clear (e);
 
   /* Remove the appropriate PHI arguments in E's destination block.  */
   for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
     {
-      if (PHI_ARG_DEF (phi, e->dest_idx) == NULL_TREE)
+      tree def = PHI_ARG_DEF (phi, e->dest_idx);
+
+      if (def == NULL_TREE)
 	continue;
 
-      src = PHI_ARG_DEF (phi, e->dest_idx);
-      dst = PHI_RESULT (phi);
-      node = build_tree_list (dst, src);
-      *last = node;
-      last = &TREE_CHAIN (node);
+      redirect_edge_var_map_add (e, PHI_RESULT (phi), def);
     }
 
   e = redirect_edge_succ_nodup (e, dest);
-  PENDING_STMT (e) = list;
 
   return e;
 }
@@ -81,20 +196,24 @@ ssa_redirect_edge (edge e, basic_block d
 void
 flush_pending_stmts (edge e)
 {
-  tree phi, arg;
+  tree phi;
+  edge_var_map_vector v;
+  edge_var_map *vm;
+  int i;
 
-  if (!PENDING_STMT (e))
+  v = redirect_edge_var_map_vector (e);
+  if (!v)
     return;
 
-  for (phi = phi_nodes (e->dest), arg = PENDING_STMT (e);
-       phi;
-       phi = PHI_CHAIN (phi), arg = TREE_CHAIN (arg))
+  for (phi = phi_nodes (e->dest), i = 0;
+       phi && VEC_iterate (edge_var_map, v, i, vm);
+       phi = PHI_CHAIN (phi), i++)
     {
-      tree def = TREE_VALUE (arg);
+      tree def = redirect_edge_var_map_def (vm);
       add_phi_arg (phi, def, e);
     }
 
-  PENDING_STMT (e) = NULL;
+  redirect_edge_var_map_clear (e);
 }
 
 /* Return true if SSA_NAME is malformed and mark it visited.
@@ -920,6 +1039,9 @@ delete_tree_ssa (void)
   delete_mem_ref_stats (cfun);
 
   cfun->gimple_df = NULL;
+
+  /* We no longer need the edge variable maps.  */
+  redirect_edge_var_map_destroy ();
 }
 
 /* Helper function for useless_type_conversion_p.  */
Index: tree-flow.h
===================================================================
--- tree-flow.h	(revision 132869)
+++ tree-flow.h	(working copy)
@@ -879,7 +879,30 @@ typedef bool (*walk_use_def_chains_fn) (
 /* In tree-ssa-alias-warnings.c  */
 extern void strict_aliasing_warning_backend (void);
 
+
 /* In tree-ssa.c  */
+
+/* Mapping for redirected edges.  */
+struct _edge_var_map GTY(())
+{
+  tree result;			/* PHI result.  */
+  tree def;			/* PHI arg definition.  */
+};
+typedef struct _edge_var_map edge_var_map;
+
+DEF_VEC_O(edge_var_map);
+DEF_VEC_ALLOC_O(edge_var_map, heap);
+
+/* A vector of var maps.  */
+typedef VEC(edge_var_map, heap) *edge_var_map_vector;
+
+extern void redirect_edge_var_map_add (edge, tree, tree);
+extern void redirect_edge_var_map_clear (edge);
+extern void redirect_edge_var_map_dup (edge, edge);
+extern edge_var_map_vector redirect_edge_var_map_vector (edge);
+extern void redirect_edge_var_map_destroy (void);
+
+
 extern void init_tree_ssa (void);
 extern edge ssa_redirect_edge (edge, basic_block);
 extern void flush_pending_stmts (edge);
@@ -892,6 +915,7 @@ extern void walk_use_def_chains (tree, w
 extern bool stmt_references_memory_p (tree);
 extern bool ssa_undefined_value_p (tree);
 
+
 /* In tree-into-ssa.c  */
 void update_ssa (unsigned);
 void delete_update_ssa (void);
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 132869)
+++ Makefile.in	(working copy)
@@ -2643,7 +2643,7 @@ auto-inc-dec.o : auto-inc-dec.c $(CONFIG
 cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
    $(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \
    $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h \
-   $(HASHTAB_H) $(DF_H) $(CFGLOOP_H)
+   $(HASHTAB_H) $(DF_H) $(CFGLOOP_H) $(TREE_FLOW_H)
 cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(CFGLOOP_H)
 cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 132869)
+++ tree-cfg.c	(working copy)
@@ -3031,24 +3031,28 @@ bsi_insert_on_edge_immediate (edge e, tr
 static void
 reinstall_phi_args (edge new_edge, edge old_edge)
 {
-  tree var, phi;
+  tree phi;
+  edge_var_map_vector v;
+  edge_var_map *vm;
+  int i;
 
-  if (!PENDING_STMT (old_edge))
+  v = redirect_edge_var_map_vector (old_edge);
+  if (!v)
     return;
 
-  for (var = PENDING_STMT (old_edge), phi = phi_nodes (new_edge->dest);
-       var && phi;
-       var = TREE_CHAIN (var), phi = PHI_CHAIN (phi))
+  for (i = 0, phi = phi_nodes (new_edge->dest);
+       VEC_iterate (edge_var_map, v, i, vm) && phi;
+       i++, phi = PHI_CHAIN (phi))
     {
-      tree result = TREE_PURPOSE (var);
-      tree arg = TREE_VALUE (var);
+      tree result = redirect_edge_var_map_result (vm);
+      tree arg = redirect_edge_var_map_def (vm);
 
       gcc_assert (result == PHI_RESULT (phi));
 
       add_phi_arg (phi, arg, new_edge);
     }
 
-  PENDING_STMT (old_edge) = NULL;
+  redirect_edge_var_map_clear (old_edge);
 }
 
 /* Returns the basic block after which the new basic block created



More information about the Gcc-patches mailing list