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


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

[mem-ssa] Support virtual operators with multiple operands


For memory SSA to work, we need to support multiple operands on the RHS
of VUSEs and V_MAY_DEFs to implement the notion of multiple names
reaching a single load/store.

Andrew agreed to change the virtual operator API to support this idea
(thanks!).  I will be adding documentation to doc/tree-ssa.texi after I
get more familiar with the new API.  This is a first rough description
from Andrew:

> This reads the current use and def from a maydef, and then makes it 4 in size
> and sets them all to the same value.
> 
> 
>   tree d,u;
>   struct maydef_optype_d *ptr1, *ptr2, *ptr3;
> 
> 
>   ptr1 = MAYDEF_OPS (stmt);
>   if (ptr1 == NULL)
>     return;
> 
>   d = MAYDEF_RESULT (ptr1);
>   u = MAYDEF_OP (ptr1, 0);
> 
>   ptr2 = realloc_maydef (ptr1, 4);
>   SET_DEF (MAYDEF_RESULT_PTR (ptr2), d);
>   SET_USE (MAYDEF_OP_PTR (ptr2, 0), u);
>   SET_USE (MAYDEF_OP_PTR (ptr2, 1), u);
>   SET_USE (MAYDEF_OP_PTR (ptr2, 2), u);
>   SET_USE (MAYDEF_OP_PTR (ptr2, 3), u);
> 
> 
> Note that VUSE_OP, VUSE_OP_PTR,  MAYDEF_OP and MAYDEF_OP_PTR have an extra
> parameter added which indicates which use you want.
> MAYDEF_NUM(ptr)  and VUSE_NUM(ptr) tell you how many there are.
> 
> I currently have asserts in many places where it changed and mattered to
> assert that the number is just one.


Bootstrapped and tested on x86.
2006-03-08  Andrew Macleod  <amacleod@redhat.com>

	* tree-ssa-operands.h (struct vuse_element_d): Declare.
	(vuse_element_t): Declare.
	(struct vuse_vec_d): Declare.
	(vuse_vec_p): Declare.
	(VUSE_VECT_NUM_ELEM): Define.
	(VUSE_VECT_ELEMENT_NC): Define.
	(VUSE_ELEMENT_PTR_NC): Define.
	(VUSE_ELEMENT_VAR_NC): Define.
	(VUSE_VECT_ELEMENT): Define.
	(VUSE_ELEMENT_PTR): Define.
	(VUSE_ELEMENT_VAR): Define.
	(struct maydef_optype_d) <use_var>: Remove.
	<use_ptr>: Remove.
	<usev>: Add.
	(struct vuse_optype_d) <kill_var>: Remove.
	<use_ptr>: Remove.
	<usev>: Add.
	(struct mustdef_optype_d) <kill_var>: Remove.
	<use_ptr>: Remove.
	<usev>: Add.
	(VUSE_OP_PTR): Add argument.  Use VUSE_ELEMENT_PTR.
	(VUSE_OP): Add argument.  Use VUSE_ELEMENT_PTR.
	(VUSE_NUM): Define.
	(VUSE_VECT): Define.
	(MAYDEF_OP_PTR): Add argument.  Use VUSE_OP_PTR.
	(MAYDEF_OP): Add argument.  Use VUSE_OP.
	(MAYDEF_NUM): Define.
	(MAYDEF_VECT): Define.
	(MUSTDEF_KILL_PTR): Use VUSE_OP_PTR.
	(MUSTDEF_KILL): Use VUSE_OP.
	(MUSTDEF_NUM): Define.
	(MUSTDEF_VECT): Define.
	(realloc_maydef): Declare.
	(realloc_vuse): Declare.
	(struct ssa_operand_iterator_d) <vuse_index>: Add.
	<mayuse_index>: Add.
	(FOR_EACH_SSA_MUSTDEF_OPERAND): Call op_iter_next_mustdef.
	* tree-into-ssa.c: Adapt for multi-operand V_MAY_DEF and VUSE
	operators.
	* tree-pretty-print.c: Likewise.
	* tree-ssa-dse.c: Likewise.
	* tree-flow-inline.h: Likewise.
	(op_iter_next_mustdef): New.
	* tree-ssa-operands.c: Likewise.
	(ALLOC_OPTYPE): Remove.
	Update all users.
	(alloc_def): New.
	(alloc_use): New.
	(alloc_maydef): New.
	(alloc_vuse): New.
	(alloc_mustdef): New.
	(realloc_maydef): New.
	(realloc_vuse): New.

Index: tree-ssa-operands.h
===================================================================
--- tree-ssa-operands.h	(revision 111858)
+++ tree-ssa-operands.h	(working copy)
@@ -50,13 +50,48 @@ struct use_optype_d 
 };
 typedef struct use_optype_d *use_optype_p;
 
+typedef struct vuse_element_d
+{
+  tree use_var;
+  struct ssa_use_operand_d use_ptr;
+} vuse_element_t;
+
+typedef struct vuse_vec_d
+{
+  int num_vuse;
+  vuse_element_t uses[1];
+} vuse_vec_t;
+typedef struct vuse_vec_d *vuse_vec_p;
+
+#define VUSE_VECT_NUM_ELEM(V)	(V).num_vuse
+#define VUSE_VECT_ELEMENT_NC(V,X)	(V).uses[(X)]
+#define VUSE_ELEMENT_PTR_NC(V,X)	(&(VUSE_VECT_ELEMENT_NC ((V),(X)).use_ptr))
+#define VUSE_ELEMENT_VAR_NC(V,X)	(VUSE_VECT_ELEMENT_NC ((V),(X)).use_var)
+
+#if 0 
+#ifdef ENABLE_CHECKING
+#define VUSE_VECT_ELEMENT(V,X)	(gcc_assert ((X) >= 0 && (X) < 		\
+					    VUSE_VECT_NUM_ELEM (V)),	\
+				 VUSE_VECT_ELEMENT_NC (V,X))
+#define VUSE_ELEMENT_PTR(V,X)	(gcc_assert ((X) >= 0 && (X) < 		\
+					    VUSE_VECT_NUM_ELEM (V)),	\
+				 VUSE_ELEMENT_PTR_NC (V, X))
+#else
+#define VUSE_VECT_ELEMENT(V,X)	VUSE_VECT_ELEMENT_NC(V,X)
+#define VUSE_ELEMENT_PTR(V,X)	VUSE_ELEMENT_PTR_NC(V,X)
+#endif
+#endif
+
+#define VUSE_VECT_ELEMENT(V,X)	VUSE_VECT_ELEMENT_NC(V,X)
+#define VUSE_ELEMENT_PTR(V,X)	VUSE_ELEMENT_PTR_NC(V,X)
+#define VUSE_ELEMENT_VAR(V,X)	(VUSE_VECT_ELEMENT ((V),(X)).use_var)
+
 /* This represents the MAY_DEFS for a stmt.  */
 struct maydef_optype_d
 {
   struct maydef_optype_d *next;
   tree def_var;
-  tree use_var;
-  struct ssa_use_operand_d use_ptr;
+  vuse_vec_t usev;
 };
 typedef struct maydef_optype_d *maydef_optype_p;
 
@@ -64,8 +99,7 @@ typedef struct maydef_optype_d *maydef_o
 struct vuse_optype_d
 {
   struct vuse_optype_d *next;
-  tree use_var;
-  struct ssa_use_operand_d use_ptr;
+  vuse_vec_t usev;
 };
 typedef struct vuse_optype_d *vuse_optype_p;
                                                                               
@@ -74,8 +108,7 @@ struct mustdef_optype_d
 {
   struct mustdef_optype_d *next;
   tree def_var;
-  tree kill_var;
-  struct ssa_use_operand_d use_ptr;
+  vuse_vec_t usev;
 };
 typedef struct mustdef_optype_d *mustdef_optype_p;
 
@@ -123,18 +156,24 @@ typedef struct stmt_operands_d *stmt_ope
 #define DEF_OP_PTR(OP)		((OP)->def_ptr)
 #define DEF_OP(OP)		(DEF_FROM_PTR (DEF_OP_PTR (OP)))
 
-#define VUSE_OP_PTR(OP)		USE_OP_PTR(OP)
-#define VUSE_OP(OP)		((OP)->use_var)
+#define VUSE_OP_PTR(OP,X)	VUSE_ELEMENT_PTR ((OP)->usev, (X)) 
+#define VUSE_OP(OP,X)		VUSE_ELEMENT_VAR ((OP)->usev, (X))
+#define VUSE_NUM(OP)		VUSE_VECT_NUM_ELEM ((OP)->usev)
+#define VUSE_VECT(OP)		&((OP)->usev)
 
 #define MAYDEF_RESULT_PTR(OP)	(&((OP)->def_var))
 #define MAYDEF_RESULT(OP)	((OP)->def_var)
-#define MAYDEF_OP_PTR(OP)	USE_OP_PTR (OP)
-#define MAYDEF_OP(OP)		((OP)->use_var)
+#define MAYDEF_OP_PTR(OP,X)	VUSE_OP_PTR (OP, X)
+#define MAYDEF_OP(OP,X)		VUSE_OP (OP, X)
+#define MAYDEF_NUM(OP)		VUSE_VECT_NUM_ELEM ((OP)->usev)
+#define MAYDEF_VECT(OP)		&((OP)->usev)
 
 #define MUSTDEF_RESULT_PTR(OP)	(&((OP)->def_var))
 #define MUSTDEF_RESULT(OP)	((OP)->def_var)
-#define MUSTDEF_KILL_PTR(OP)	USE_OP_PTR (OP)
-#define MUSTDEF_KILL(OP)	((OP)->kill_var)
+#define MUSTDEF_KILL_PTR(OP)	VUSE_OP_PTR (OP, 0)
+#define MUSTDEF_KILL(OP)	VUSE_OP (OP, 0)
+#define MUSTDEF_NUM(OP)		VUSE_VECT_NUM_ELEM ((OP)->usev)
+#define MUSTDEF_VECT(OP)	&((OP)->usev)
 
 #define PHI_RESULT_PTR(PHI)	get_phi_result_ptr (PHI)
 #define PHI_RESULT(PHI)		DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
@@ -151,6 +190,9 @@ typedef struct stmt_operands_d *stmt_ope
 #define PHI_ARG_INDEX_FROM_USE(USE)   phi_arg_index_from_use (USE)
 
 
+extern struct maydef_optype_d *realloc_maydef (struct maydef_optype_d *, int);
+extern struct vuse_optype_d *realloc_vuse (struct vuse_optype_d *, int);
+
 extern void init_ssa_operands (void);
 extern void fini_ssa_operands (void);
 extern void free_ssa_operands (stmt_operands_p);
@@ -195,6 +237,8 @@ typedef struct ssa_operand_iterator_d
   int num_phi;
   tree phi_stmt;
   bool done;
+  int vuse_index;
+  int mayuse_index;
 } ssa_op_iter;
 
 /* These flags are used to determine which operands are returned during 
@@ -257,7 +301,7 @@ typedef struct ssa_operand_iterator_d
 #define FOR_EACH_SSA_MUSTDEF_OPERAND(DEFVAR, KILLVAR, STMT, ITER)	\
   for (op_iter_init_mustdef (&(ITER), STMT, &(KILLVAR), &(DEFVAR));	\
        !op_iter_done (&(ITER));					\
-       op_iter_next_maymustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
+       op_iter_next_mustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
 
 /* This macro executes a loop over the V_{MUST,MAY}_DEF of STMT.  The def
    and kill for each V_{MUST,MAY}_DEF is returned in DEFVAR and KILLVAR. 
Index: tree-into-ssa.c
===================================================================
--- tree-into-ssa.c	(revision 111858)
+++ tree-into-ssa.c	(working copy)
@@ -637,6 +637,7 @@ mark_def_sites (struct dom_walk_data *wa
   use_operand_p use_p;
   def_operand_p def_p;
   ssa_op_iter iter;
+  vuse_vec_p vv;
 
   stmt = bsi_stmt (bsi);
   update_stmt_if_modified (stmt);
@@ -661,9 +662,12 @@ mark_def_sites (struct dom_walk_data *wa
      variable.  However, the operand of a virtual definitions is a use
      of the variable, so it may cause the variable to be considered
      live-on-entry.  */
-  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
+  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, vv, stmt, iter)
     {
-      tree sym = USE_FROM_PTR (use_p);
+      tree sym;
+      gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
+      use_p = VUSE_ELEMENT_PTR (*vv, 0);
+      sym = USE_FROM_PTR (use_p);
       gcc_assert (DECL_P (sym));
       set_livein_block (sym, bb);
       set_def_block (sym, bb, false);
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 111858)
+++ tree-pretty-print.c	(working copy)
@@ -2573,12 +2573,15 @@ dump_vops (pretty_printer *buffer, tree 
   def_operand_p def_p;
   use_operand_p kill_p;
   ssa_op_iter iter;
+  vuse_vec_p vv;
 
   if (!ssa_operands_active ())
     return;
 
-  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
+  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, vv, stmt, iter)
     {
+      gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
+      use_p = VUSE_ELEMENT_PTR (*vv, 0);
       pp_string (buffer, "#   ");
       dump_generic_node (buffer, DEF_FROM_PTR (def_p),
                          spc + 2, flags, false);
Index: tree-ssa-dse.c
===================================================================
--- tree-ssa-dse.c	(revision 111858)
+++ tree-ssa-dse.c	(working copy)
@@ -255,6 +255,7 @@ dse_optimize_stmt (struct dom_walk_data 
       use_operand_p var2;
       def_operand_p var1;
       ssa_op_iter op_iter;
+      vuse_vec_p vv;
 
       /* We want to verify that each virtual definition in STMT has
 	 precisely one use and that all the virtual definitions are
@@ -262,8 +263,10 @@ dse_optimize_stmt (struct dom_walk_data 
 	 want USE_STMT to refer to the one statement which uses
 	 all of the virtual definitions from STMT.  */
       use_stmt = NULL;
-      FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, var2, stmt, op_iter)
+      FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, vv, stmt, op_iter)
 	{
+	  gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
+	  var2 = VUSE_ELEMENT_PTR (*vv, 0);
 	  defvar = DEF_FROM_PTR (var1);
 	  usevar = USE_FROM_PTR (var2);
 
@@ -345,8 +348,10 @@ dse_optimize_stmt (struct dom_walk_data 
               fprintf (dump_file, "'\n");
             }
 	  /* Then we need to fix the operand of the consuming stmt.  */
-	  FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, var2, stmt, op_iter)
+	  FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, vv, stmt, op_iter)
 	    {
+	      gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
+	      var2 = VUSE_ELEMENT_PTR (*vv, 0);
 	      single_imm_use (DEF_FROM_PTR (var1), &use_p, &temp);
 	      SET_USE (use_p, USE_FROM_PTR (var2));
 	    }
Index: tree-flow-inline.h
===================================================================
--- tree-flow-inline.h	(revision 111858)
+++ tree-flow-inline.h	(working copy)
@@ -896,14 +896,22 @@ op_iter_next_use (ssa_op_iter *ptr)
     }
   if (ptr->vuses)
     {
-      use_p = VUSE_OP_PTR (ptr->vuses);
-      ptr->vuses = ptr->vuses->next;
+      use_p = VUSE_OP_PTR (ptr->vuses, ptr->vuse_index);
+      if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses))
+        {
+	  ptr->vuse_index = 0;
+	  ptr->vuses = ptr->vuses->next;
+	}
       return use_p;
     }
   if (ptr->mayuses)
     {
-      use_p = MAYDEF_OP_PTR (ptr->mayuses);
-      ptr->mayuses = ptr->mayuses->next;
+      use_p = MAYDEF_OP_PTR (ptr->mayuses, ptr->mayuse_index);
+      if (++(ptr->mayuse_index) >= MAYDEF_NUM (ptr->mayuses))
+        {
+	  ptr->mayuse_index = 0;
+	  ptr->mayuses = ptr->mayuses->next;
+	}
       return use_p;
     }
   if (ptr->mustkills)
@@ -966,14 +974,22 @@ op_iter_next_tree (ssa_op_iter *ptr)
     }
   if (ptr->vuses)
     {
-      val = VUSE_OP (ptr->vuses);
-      ptr->vuses = ptr->vuses->next;
+      val = VUSE_OP (ptr->vuses, ptr->vuse_index);
+      if (++(ptr->vuse_index) >= VUSE_NUM (ptr->vuses))
+        {
+	  ptr->vuse_index = 0;
+	  ptr->vuses = ptr->vuses->next;
+	}
       return val;
     }
   if (ptr->mayuses)
     {
-      val = MAYDEF_OP (ptr->mayuses);
-      ptr->mayuses = ptr->mayuses->next;
+      val = MAYDEF_OP (ptr->mayuses, ptr->mayuse_index);
+      if (++(ptr->mayuse_index) >= MAYDEF_NUM (ptr->mayuses))
+        {
+	  ptr->mayuse_index = 0;
+	  ptr->mayuses = ptr->mayuses->next;
+	}
       return val;
     }
   if (ptr->mustkills)
@@ -1026,6 +1042,8 @@ clear_and_done_ssa_iter (ssa_op_iter *pt
   ptr->num_phi = 0;
   ptr->phi_stmt = NULL_TREE;
   ptr->done = true;
+  ptr->vuse_index = 0;
+  ptr->mayuse_index = 0;
 }
 
 /* Initialize the iterator PTR to the virtual defs in STMT.  */
@@ -1048,6 +1066,8 @@ op_iter_init (ssa_op_iter *ptr, tree stm
   ptr->phi_i = 0;
   ptr->num_phi = 0;
   ptr->phi_stmt = NULL_TREE;
+  ptr->vuse_index = 0;
+  ptr->mayuse_index = 0;
 }
 
 /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
@@ -1085,7 +1105,7 @@ op_iter_init_tree (ssa_op_iter *ptr, tre
 /* Get the next iterator mustdef value for PTR, returning the mustdef values in
    KILL and DEF.  */
 static inline void
-op_iter_next_maymustdef (use_operand_p *use, def_operand_p *def, 
+op_iter_next_maymustdef (vuse_vec_p *use, def_operand_p *def, 
 			 ssa_op_iter *ptr)
 {
 #ifdef ENABLE_CHECKING
@@ -1094,7 +1114,7 @@ op_iter_next_maymustdef (use_operand_p *
   if (ptr->mayuses)
     {
       *def = MAYDEF_RESULT_PTR (ptr->mayuses);
-      *use = MAYDEF_OP_PTR (ptr->mayuses);
+      *use = MAYDEF_VECT (ptr->mayuses);
       ptr->mayuses = ptr->mayuses->next;
       return;
     }
@@ -1102,22 +1122,37 @@ op_iter_next_maymustdef (use_operand_p *
   if (ptr->mustkills)
     {
       *def = MUSTDEF_RESULT_PTR (ptr->mustkills);
-      *use = MUSTDEF_KILL_PTR (ptr->mustkills);
+      *use = MUSTDEF_VECT (ptr->mustkills);
       ptr->mustkills = ptr->mustkills->next;
       return;
     }
 
   *def = NULL_DEF_OPERAND_P;
-  *use = NULL_USE_OPERAND_P;
+  *use = NULL;
   ptr->done = true;
   return;
 }
 
 
+static inline void
+op_iter_next_mustdef (use_operand_p *use, def_operand_p *def, 
+			 ssa_op_iter *ptr)
+{
+  vuse_vec_p vp;
+  op_iter_next_maymustdef (&vp, def, ptr);
+  if (vp != NULL)
+    {
+      gcc_assert (VUSE_VECT_NUM_ELEM (*vp) == 1);
+      *use = VUSE_ELEMENT_PTR (*vp, 0);
+    }
+  else
+    *use = NULL_USE_OPERAND_P;
+}
+
 /* Initialize iterator PTR to the operands in STMT.  Return the first operands
    in USE and DEF.  */
 static inline void
-op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use, 
+op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, vuse_vec_p *use, 
 		     def_operand_p *def)
 {
   gcc_assert (TREE_CODE (stmt) != PHI_NODE);
@@ -1134,18 +1169,26 @@ static inline void
 op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill, 
 		     def_operand_p *def)
 {
+  vuse_vec_p vp;
   gcc_assert (TREE_CODE (stmt) != PHI_NODE);
 
   op_iter_init (ptr, stmt, SSA_OP_VMUSTKILL);
   ptr->iter_type = ssa_op_iter_maymustdef;
-  op_iter_next_maymustdef (kill, def, ptr);
+  op_iter_next_maymustdef (&vp, def, ptr);
+  if (vp != NULL)
+    {
+      gcc_assert (VUSE_VECT_NUM_ELEM (*vp) == 1);
+      *kill = VUSE_ELEMENT_PTR (*vp, 0);
+    }
+  else
+    *kill = NULL_USE_OPERAND_P;
 }
 
 /* Initialize iterator PTR to the operands in STMT.  Return the first operands
    in KILL and DEF.  */
 static inline void
 op_iter_init_must_and_may_def (ssa_op_iter *ptr, tree stmt,
-			       use_operand_p *kill, def_operand_p *def)
+			       vuse_vec_p *kill, def_operand_p *def)
 {
   gcc_assert (TREE_CODE (stmt) != PHI_NODE);
 
Index: tree-ssa-operands.c
===================================================================
--- tree-ssa-operands.c	(revision 111858)
+++ tree-ssa-operands.c	(working copy)
@@ -130,19 +130,6 @@ static vuse_optype_p free_vuses = NULL;
 static maydef_optype_p free_maydefs = NULL;
 static mustdef_optype_p free_mustdefs = NULL;
 
-/* Allocates operand OP of given TYPE from the appropriate free list,
-   or of the new value if the list is empty.  */
-
-#define ALLOC_OPTYPE(OP, TYPE)				\
-  do							\
-    {							\
-      TYPE##_optype_p ret = free_##TYPE##s;		\
-      if (ret)						\
-	free_##TYPE##s = ret->next;			\
-      else						\
-	ret = ssa_operand_alloc (sizeof (*ret));	\
-      (OP) = ret;					\
-    } while (0) 
 
 /* Return the DECL_UID of the base variable of T.  */
 
@@ -325,6 +312,101 @@ ssa_operand_alloc (unsigned size)
 }
 
 
+static inline struct def_optype_d *
+alloc_def (void)
+{
+  struct def_optype_d *ret;
+  if (free_defs)
+    {
+      ret = free_defs;
+      free_defs = free_defs->next;
+    }
+  else
+    ret = (struct def_optype_d *)
+		      ssa_operand_alloc (sizeof (struct def_optype_d));
+  return ret;
+}
+
+
+static inline struct use_optype_d *
+alloc_use (void)
+{
+  struct use_optype_d *ret;
+  if (free_uses)
+    {
+      ret = free_uses;
+      free_uses = free_uses->next;
+    }
+  else
+    ret = (struct use_optype_d *)ssa_operand_alloc (sizeof (struct use_optype_d));
+  return ret;
+}
+
+
+
+
+static inline struct maydef_optype_d *
+alloc_maydef (int num)
+{
+  struct maydef_optype_d *ret;
+  /* Eliminate free list for the moment.  */
+#if 0
+  if (free_maydefs)
+    {
+      ret = free_maydefs;
+      free_maydefs = free_maydefs->next;
+    }
+  else
+#endif
+    ret = (struct maydef_optype_d *)ssa_operand_alloc (
+	sizeof (struct maydef_optype_d) + (num - 1) * sizeof (vuse_element_t));
+  VUSE_VECT_NUM_ELEM (ret->usev) = num;
+  return ret;
+}
+
+
+
+
+static inline struct vuse_optype_d *
+alloc_vuse (int num)
+{
+  struct vuse_optype_d *ret;
+/* No free list for the moment.  */
+#if 0    
+  if (free_vuses)
+    {
+      ret = free_vuses;
+      free_vuses = free_vuses->next;
+    }
+  else
+#endif
+    ret = (struct vuse_optype_d *)ssa_operand_alloc (
+	sizeof (struct vuse_optype_d) + (num - 1) * sizeof (vuse_element_t));
+  VUSE_VECT_NUM_ELEM (ret->usev) = num;
+  return ret;
+}
+
+
+
+
+
+static inline struct mustdef_optype_d *
+alloc_mustdef (void)
+{
+  struct mustdef_optype_d *ret;
+  if (free_mustdefs)
+    {
+      ret = free_mustdefs;
+      free_mustdefs = free_mustdefs->next;
+    }
+  else
+    ret = (struct mustdef_optype_d *)ssa_operand_alloc (sizeof (struct mustdef_optype_d));
+  VUSE_VECT_NUM_ELEM (ret->usev) = 1;
+  return ret;
+}
+
+
+
 /* Make sure PTR is in the correct immediate use list.  Since uses are simply
    pointers into the stmt TREE, there is no way of telling if anyone has
    changed what this pointer points to via TREE_OPERANDS (exp, 0) = <...>.
@@ -424,73 +506,206 @@ set_virtual_use_link (use_operand_p ptr,
 /* Adds OP to the list of defs after LAST, and moves
    LAST to the new element.  */
 
-static inline void
+static inline def_optype_p 
 add_def_op (tree *op, def_optype_p *last)
 {
   def_optype_p new;
 
-  ALLOC_OPTYPE (new, def);
+  new = alloc_def ();
   DEF_OP_PTR (new) = op;
   APPEND_OP_AFTER (new, *last);  
+  return new;
 }
 
 /* Adds OP to the list of uses of statement STMT after LAST, and moves
    LAST to the new element.  */
 
-static inline void
+static inline use_optype_p
 add_use_op (tree stmt, tree *op, use_optype_p *last)
 {
   use_optype_p new;
 
-  ALLOC_OPTYPE (new, use);
+  new = alloc_use ();
   INITIALIZE_USE (USE_OP_PTR (new), op, stmt);
   APPEND_OP_AFTER (new, *last);  
+  return new;
 }
 
 /* Adds OP to the list of vuses of statement STMT after LAST, and moves
    LAST to the new element.  */
 
-static inline void
-add_vuse_op (tree stmt, tree op, vuse_optype_p *last)
+static inline vuse_optype_p
+add_vuse_op (tree stmt, tree op, int num, vuse_optype_p *last)
 {
   vuse_optype_p new;
+  int x;
 
-  ALLOC_OPTYPE (new, vuse);
-  VUSE_OP (new) = op;
-  INITIALIZE_USE (VUSE_OP_PTR (new), &VUSE_OP (new), stmt);
+  new = alloc_vuse (num);
+  for (x = 0; x < num; x++)
+    {
+      VUSE_OP (new, x) = op;
+      INITIALIZE_USE (VUSE_OP_PTR (new, x), &(VUSE_OP (new, x)), stmt);
+    }
   APPEND_OP_AFTER (new, *last);  
+  return new;
 }
 
 /* Adds OP to the list of maydefs of statement STMT after LAST, and moves
    LAST to the new element.  */
 
-static inline void
-add_maydef_op (tree stmt, tree op, maydef_optype_p *last)
+static inline maydef_optype_p
+add_maydef_op (tree stmt, tree op, int num, maydef_optype_p *last)
 {
+  int x;
   maydef_optype_p new;
 
-  ALLOC_OPTYPE (new, maydef);
+  new = alloc_maydef (num);
   MAYDEF_RESULT (new) = op;
-  MAYDEF_OP (new) = op;
-  INITIALIZE_USE (MAYDEF_OP_PTR (new), &MAYDEF_OP (new), stmt);
+  for (x = 0; x < num; x++)
+    {
+      MAYDEF_OP (new, x) = op;
+      INITIALIZE_USE (MAYDEF_OP_PTR (new, x), &(MAYDEF_OP (new, x)), stmt);
+    }
   APPEND_OP_AFTER (new, *last);  
+  return new;
 }
 
 /* Adds OP to the list of mustdefs of statement STMT after LAST, and moves
    LAST to the new element.  */
 
-static inline void
+static inline mustdef_optype_p
 add_mustdef_op (tree stmt, tree op, mustdef_optype_p *last)
 {
   mustdef_optype_p new;
 
-  ALLOC_OPTYPE (new, mustdef);
+  new = alloc_mustdef ();
   MUSTDEF_RESULT (new) = op;
   MUSTDEF_KILL (new) = op;
   INITIALIZE_USE (MUSTDEF_KILL_PTR (new), &MUSTDEF_KILL (new), stmt);
   APPEND_OP_AFTER (new, *last);
+  return new;
+}
+
+
+struct maydef_optype_d *
+realloc_maydef (struct maydef_optype_d *ptr, int num_elem)
+{
+  int x, lim;
+  tree val, stmt;
+  struct maydef_optype_d *ret, *tmp;
+
+  if (VUSE_VECT_NUM_ELEM (ptr->usev) == num_elem)
+    return ptr; 
+  
+  val = MAYDEF_RESULT (ptr);
+  if (TREE_CODE (val) == SSA_NAME)
+    val = SSA_NAME_VAR (val);
+
+  stmt = USE_STMT (MAYDEF_OP_PTR (ptr, 0));
+
+  /* Delink all the existing uses.  */
+
+  for (x = 0; x < VUSE_VECT_NUM_ELEM (ptr->usev); x++)
+    {
+      use_operand_p use_p = MAYDEF_OP_PTR (ptr, x);
+      delink_imm_use (use_p);
+    }
+
+  /* If we want less space, simply use this one, and shrink the size.  */
+  if (VUSE_VECT_NUM_ELEM (ptr->usev) > num_elem)
+    {
+      VUSE_VECT_NUM_ELEM (ptr->usev) = num_elem;
+      return ptr;
+    }
+
+  /* its growing. Allocate a new one and replace the old one.  */
+  tmp = ptr;;
+  ret = add_maydef_op (stmt, val, num_elem, &ptr);
+  ptr = tmp;
+
+  lim = VUSE_VECT_NUM_ELEM (ptr->usev);
+  memset (ptr, 0, sizeof (struct maydef_optype_d) + sizeof (vuse_element_t) * (lim- 1));
+  /* Now simply remove the old one.  */
+  if (MAYDEF_OPS (stmt) == ptr)
+    {
+      MAYDEF_OPS (stmt) = ret;
+      return ret;
+    }
+  else
+    for (tmp = MAYDEF_OPS (stmt); 
+	 tmp != NULL && tmp->next != ptr; 
+	 tmp = tmp->next)
+      {
+	tmp->next = ret;
+	return ret;
+      }
+  /* The pointer passed in isnt in the stmt's maydef lists.  */
+  gcc_unreachable ();
+
+}
+
+
+
+struct vuse_optype_d *
+realloc_vuse (struct vuse_optype_d *ptr, int num_elem)
+{
+  int x, lim;
+  tree val, stmt;
+  struct vuse_optype_d *ret, *tmp;
+
+  if (VUSE_VECT_NUM_ELEM (ptr->usev) == num_elem)
+    return ptr; 
+  
+  val = VUSE_OP (ptr, 0);
+  if (TREE_CODE (val) == SSA_NAME)
+    val = SSA_NAME_VAR (val);
+
+  stmt = USE_STMT (VUSE_OP_PTR (ptr, 0));
+
+  /* Delink all the existing uses.  */
+
+  for (x = 0; x < VUSE_VECT_NUM_ELEM (ptr->usev); x++)
+    {
+      use_operand_p use_p = VUSE_OP_PTR (ptr, x);
+      delink_imm_use (use_p);
+    }
+
+  /* If we want less space, simply use this one, and shrink the size.  */
+  if (VUSE_VECT_NUM_ELEM (ptr->usev) > num_elem)
+    {
+      VUSE_VECT_NUM_ELEM (ptr->usev) = num_elem;
+      return ptr;
+    }
+
+  /* its growing. Allocate a new one and reaplce the old one.  */
+  tmp = ptr;
+  ret = add_vuse_op (stmt, val, num_elem, &ptr);
+  ptr = tmp;
+
+  lim = VUSE_VECT_NUM_ELEM (ptr->usev);
+  memset (ptr, 0, 
+	  sizeof (struct vuse_optype_d) + sizeof (vuse_element_t) * (lim - 1));
+  /* No wsimply link it in, find the node which points to this one.  */
+  if (VUSE_OPS (stmt) == ptr)
+    {
+      VUSE_OPS (stmt) = ret;
+      return ret;
+    }
+  else
+    for (tmp = VUSE_OPS (stmt); 
+	 tmp != NULL && tmp->next != ptr; 
+	 tmp = tmp->next)
+      {
+	tmp->next = ret;
+	return ret;
+      }
+  /* The pointer passed in isnt in the stmt's maydef lists.  */
+  gcc_unreachable ();
+
 }
 
+
+
 /* Takes elements from build_defs and turns them into def operands of STMT.
    TODO -- Given that def operands list is not neccessarily sorted, merging
 	   the operands this way does not make much sense.
@@ -681,6 +896,7 @@ finalize_ssa_uses (tree stmt)
 static inline void
 finalize_ssa_v_may_def_ops (tree stmt)
 {
+  int x;
   unsigned new_i;
   struct maydef_optype_d new_list;
   maydef_optype_p old_ops, ptr, last;
@@ -697,32 +913,34 @@ finalize_ssa_v_may_def_ops (tree stmt)
     {
       act = VEC_index (tree, build_v_may_defs, new_i);
       new_base = get_name_decl (act);
-      old_base = get_name_decl (MAYDEF_OP (old_ops));
+      old_base = get_name_decl (MAYDEF_RESULT (old_ops));
 
       if (old_base == new_base)
         {
 	  /* if variables are the same, reuse this node.  */
 	  MOVE_HEAD_AFTER (old_ops, last);
-	  set_virtual_use_link (MAYDEF_OP_PTR (last), stmt);
+	  for (x = 0; x < VUSE_VECT_NUM_ELEM (last->usev); x++)
+	    set_virtual_use_link (MAYDEF_OP_PTR (last, x), stmt);
 	  new_i++;
 	}
       else if (old_base < new_base)
 	{
 	  /* if old is less than new, old goes to the free list.  */
-	  delink_imm_use (MAYDEF_OP_PTR (old_ops));
+	  for (x = 0; x < VUSE_VECT_NUM_ELEM (old_ops->usev); x++)
+	    delink_imm_use (MAYDEF_OP_PTR (old_ops, x));
 	  MOVE_HEAD_TO_FREELIST (old_ops, maydef);
 	}
       else
 	{
 	  /* This is a new operand.  */
-	  add_maydef_op (stmt, act, &last);
+	  add_maydef_op (stmt, act, 1, &last);
 	  new_i++;
 	}
     }
 
   /* If there is anything remaining in the build_v_may_defs list, simply emit it.  */
   for ( ; new_i < VEC_length (tree, build_v_may_defs); new_i++)
-    add_maydef_op (stmt, VEC_index (tree, build_v_may_defs, new_i), &last);
+    add_maydef_op (stmt, VEC_index (tree, build_v_may_defs, new_i), 1, &last);
 
   last->next = NULL;
 
@@ -730,7 +948,8 @@ finalize_ssa_v_may_def_ops (tree stmt)
   if (old_ops)
     {
       for (ptr = old_ops; ptr; ptr = ptr->next)
-	delink_imm_use (MAYDEF_OP_PTR (ptr));
+	for (x = 0; x < VUSE_VECT_NUM_ELEM (ptr->usev); x++)
+	  delink_imm_use (MAYDEF_OP_PTR (ptr, x));
       old_ops->next = free_maydefs;
       free_maydefs = old_ops;
     }
@@ -783,6 +1002,7 @@ cleanup_v_may_defs (void)
 static inline void
 finalize_ssa_vuse_ops (tree stmt)
 {
+  int x;
   unsigned new_i;
   struct vuse_optype_d new_list;
   vuse_optype_p old_ops, ptr, last;
@@ -799,32 +1019,34 @@ finalize_ssa_vuse_ops (tree stmt)
     {
       act = VEC_index (tree, build_vuses, new_i);
       new_base = get_name_decl (act);
-      old_base = get_name_decl (VUSE_OP (old_ops));
+      old_base = get_name_decl (VUSE_OP (old_ops, 0));
 
       if (old_base == new_base)
         {
 	  /* if variables are the same, reuse this node.  */
 	  MOVE_HEAD_AFTER (old_ops, last);
-	  set_virtual_use_link (VUSE_OP_PTR (last), stmt);
+	  for (x = 0; x < VUSE_VECT_NUM_ELEM (last->usev); x++)
+	    set_virtual_use_link (VUSE_OP_PTR (last, x), stmt);
 	  new_i++;
 	}
       else if (old_base < new_base)
 	{
 	  /* if old is less than new, old goes to the free list.  */
-	  delink_imm_use (USE_OP_PTR (old_ops));
+	  for (x = 0; x < VUSE_VECT_NUM_ELEM (old_ops->usev); x++)
+	    delink_imm_use (VUSE_OP_PTR (old_ops, x));
 	  MOVE_HEAD_TO_FREELIST (old_ops, vuse);
 	}
       else
 	{
 	  /* This is a new operand.  */
-	  add_vuse_op (stmt, act, &last);
+	  add_vuse_op (stmt, act, 1, &last);
 	  new_i++;
 	}
     }
 
   /* If there is anything remaining in the build_vuses list, simply emit it.  */
   for ( ; new_i < VEC_length (tree, build_vuses); new_i++)
-    add_vuse_op (stmt, VEC_index (tree, build_vuses, new_i), &last);
+    add_vuse_op (stmt, VEC_index (tree, build_vuses, new_i), 1, &last);
 
   last->next = NULL;
 
@@ -832,7 +1054,8 @@ finalize_ssa_vuse_ops (tree stmt)
   if (old_ops)
     {
       for (ptr = old_ops; ptr; ptr = ptr->next)
-	delink_imm_use (VUSE_OP_PTR (ptr));
+	for (x = 0; x < VUSE_VECT_NUM_ELEM (ptr->usev); x++)
+	  delink_imm_use (VUSE_OP_PTR (ptr, x));
       old_ops->next = free_vuses;
       free_vuses = old_ops;
     }
@@ -2256,6 +2479,7 @@ copy_virtual_operands (tree dest, tree s
   tree t;
   ssa_op_iter iter, old_iter;
   use_operand_p use_p, u2;
+  vuse_vec_p u3, u4;
   def_operand_p def_p, d2;
 
   build_ssa_operands (dest);
@@ -2288,23 +2512,31 @@ copy_virtual_operands (tree dest, tree s
     }
   gcc_assert (op_iter_done (&old_iter));
 
-  op_iter_init_maydef (&old_iter, src, &u2, &d2);
-  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, dest, iter)
+  op_iter_init_maydef (&old_iter, src, &u3, &d2);
+  FOR_EACH_SSA_MAYDEF_OPERAND (def_p, u4, dest, iter)
     {
       gcc_assert (!op_iter_done (&old_iter));
-      SET_USE (use_p, USE_FROM_PTR (u2));
+      gcc_assert (VUSE_VECT_NUM_ELEM (*u3) == 1);
+      gcc_assert (VUSE_VECT_NUM_ELEM (*u4) == 1);
+      SET_USE (VUSE_ELEMENT_PTR_NC (*u4, 0), VUSE_ELEMENT_VAR (*u3, 0));
       SET_DEF (def_p, DEF_FROM_PTR (d2));
-      op_iter_next_maymustdef (&u2, &d2, &old_iter);
+      op_iter_next_maymustdef (&u3, &d2, &old_iter);
     }
   gcc_assert (op_iter_done (&old_iter));
 
   op_iter_init_mustdef (&old_iter, src, &u2, &d2);
+  u3 = NULL;
   FOR_EACH_SSA_MUSTDEF_OPERAND (def_p, use_p, dest, iter)
     {
+      if (u3 != NULL)
+        {
+	  gcc_assert (VUSE_VECT_NUM_ELEM (*u3) == 1);
+	  u2 = VUSE_ELEMENT_PTR (*u3, 0);
+	}
       gcc_assert (!op_iter_done (&old_iter));
       SET_USE (use_p, USE_FROM_PTR (u2));
       SET_DEF (def_p, DEF_FROM_PTR (d2));
-      op_iter_next_maymustdef (&u2, &d2, &old_iter);
+      op_iter_next_maymustdef (&u3, &d2, &old_iter);
     }
   gcc_assert (op_iter_done (&old_iter));
 

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