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]

Re: [patch] Rewrite building of virtual operands


Hello,

> > I use bitmaps, not sbitmaps.  Sbitmaps are slow to iterate over, so
> > their use definitely is not appropriate.
> 
> Sorry, I misread. bitmaps are going to be way worse in the pathological
> cases.. it never even occurred to me you'd use bitmaps since this is
> going to be a very sparse usage. we have cases which have hundreds of
> thousands or more ssa_names... 

bitmaps should be more efficient than sbitmaps for sparse usage; the
real problem is that they turn out to be quite inefficient in almost
any case.  I have run some tests -- basically, the only workload where they
beat sbitmaps is for small sets taken from huge range (less then 10^3
elements from more than 10^5), even on tests that heavily use the
advantages of bitmaps (fast iteration over elements).

Up to these tests I could not imagine using sbitmaps for this might be a
good idea, but I will probably give it a try, just to see the numbers
(although even if they are good on typical code, which they probably
would be, there most likely exist pathological examples that would
prevent their usage).

> timings of your patch. I never wrote one with bitmaps of any sort.
> notice those are timing of *just* the operand cache, not overall time,
> and on my 3Ghz P4.

How do you measure them? TV_TREE_OPS seems to basically measure noise,
given the precision it uses.

> The opfinalize.h routines are for the sake of
> speed, and other than a bit of ugly appearance (where are C templates
> when you need them anyway :-), they are pretty clean.  They rarely need
> to be touched.  I also don't find them that difficult to work with, but
> feel free to expand them inline if you do.  

here is the patch that expands the functions.  To make it simpler to
review, it makes no functional changes (i.e., all cleanups enabled by
the specialization will be in followup patches).

Bootstrapped & regtested on i686.

Zdenek

	* tree-ssa-opfinalize.h: Removed.
	* Makefile.in (tree-ssa-operands.o): Remove tree-ssa-opfinalize.h
	dependency.
	* tree-ssa-operands.c: Do not include tree-ssa-opfinalize.h.
	(ALLOC_OPTYPE, APPEND_OP_AFTER, MOVE_HEAD_AFTER, MOVE_HEAD_TO_FREELIST,
	INITIALIZE_USE, add_def_op, add_use_op, add_vuse_op, add_maydef_op,
	add_mustdef_op, finalize_ssa_def_ops, finalize_ssa_use_ops,
	finalize_ssa_v_may_def_ops, finalize_ssa_vuse_ops,
	finalize_ssa_v_must_def_ops): New.

Index: tree-ssa-opfinalize.h
===================================================================
*** tree-ssa-opfinalize.h	(revision 111787)
--- tree-ssa-opfinalize.h	(working copy)
***************
*** 1,174 ****
- /* SSA operand allocation and finalizing.
-    Copyright (C) 2005 Free Software Foundation, Inc.
- 
- This file is part of GCC.
- 
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2, or (at your option) any later
- version.
- 
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- for more details.
- 
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING.  If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.  */
- 
- 
- /* This file contains common code which is used by each of the 5 operand 
-    types.  Macros are defined to specify the varying components.
- 
-    FINALIZE_FUNC - name of finalize function.
-    FINALIZE_ALLOC - name of allocation routine.
-    FINALIZE_FREE - name of free list.
-    FINALIZE_TYPE - type of node.
-    FINALIZE_OPS - Lead element in list.
-    FINALIZE_USE_PTR - How to get the use_operand_p, if this is a use operand.
-    FINALIZE_INITIALIZE - How to initialize an element.
-    FINALIZE_ELEM - How to retrieve an element.
-    FINALIZE_BASE - How to retrieve the base variable of an element.
-    FINALIZE_BASE_TYPE - Type of the base variable.
-    FINALIZE_OPBUILD - Opbuild array for these nodes.
-    FINALIZE_OPBUILD_ELEM - How to get an element from the opbuild list.
-    FINALIZE_OPBUILD_BASE - How to get an element base from the opbuild list.
-    FINALIZE_BASE_ZERO - How to zero an element.  */
- 
- 
- /* This routine will either pick up a node from the free list, or allocate a
-    new one if need be.  */
- 
- static inline FINALIZE_TYPE *
- FINALIZE_ALLOC (void)
- {
-   FINALIZE_TYPE *ret;
-   if (FINALIZE_FREE)
-     {
-       ret = FINALIZE_FREE;
-       FINALIZE_FREE = FINALIZE_FREE->next;
-     }
-   else
-     ret = (FINALIZE_TYPE *)ssa_operand_alloc (sizeof (FINALIZE_TYPE));
-   return ret;
- }
- 
- 
- 
- /* This routine will take the new operands from FINALIZE_OPBUILD and turn them
-    into the new operands for STMT.  All required linking and deleting is u
-    performed here.  */
- static inline void
- FINALIZE_FUNC (tree stmt)
- {
-   unsigned new_i;
-   FINALIZE_TYPE *old_ops, *ptr, *last;
-   FINALIZE_BASE_TYPE old_base;
-   FINALIZE_TYPE new_list;
- 
-   new_list.next = NULL;
-   last = &new_list;
- 
-   old_ops = FINALIZE_OPS (stmt);
-   if (old_ops)
-     old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops));
-   else
-     old_base = FINALIZE_BASE_ZERO;
- 
-   new_i = 0;
-   while (old_ops && new_i < VEC_length (tree, FINALIZE_OPBUILD))
-     {
-       FINALIZE_BASE_TYPE new_base = FINALIZE_OPBUILD_BASE (new_i);
-       if (old_base == new_base)
-         {
- 	  /* if variables are the same, reuse this node.  */
- 	  last->next = old_ops;
- 	  last = old_ops;
- #ifdef FINALIZE_CORRECT_USE
- 	  FINALIZE_CORRECT_USE (FINALIZE_USE_PTR (last), stmt);
- #endif
- 	  old_ops = old_ops->next;
- 	  new_i++;
- 	}
-       else
-         if (old_base < new_base)
- 	  {
- 	    /* if old is less than new, old goes to the free list.  */
- #ifdef FINALIZE_USE_PTR
- 	    use_operand_p use_p = FINALIZE_USE_PTR (old_ops);
- 	    delink_imm_use (use_p);
- #endif
- 	    ptr = old_ops;
- 	    old_ops = old_ops->next;
- 	    ptr->next = FINALIZE_FREE;
- 	    FINALIZE_FREE = ptr;
- 	  }
- 	else
- 	  {
- 	    /* This is a new operand.  */
- 	    ptr = FINALIZE_ALLOC ();
- 	    FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt);
- 	    last->next = ptr;
- 	    last = ptr;
- 	    new_i++;
- 	  }
-       if (old_ops)
-         old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops));
-     }
- 
-   /* If there is anything remaining in the opbuild list, simply emit them.  */
-   for ( ; new_i < VEC_length (tree, FINALIZE_OPBUILD); new_i++)
-     {
-       ptr = FINALIZE_ALLOC ();
-       FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt);
-       last->next = ptr;
-       last = ptr;
-     }
- 
-   last->next = NULL;
- 
-   /* If there is anything in the old list, free them.  */
-   if (old_ops)
-     {
- #ifdef FINALIZE_USE_PTR
-       for (ptr = old_ops; ptr; ptr = ptr->next)
- 	{
- 	  use_operand_p use_p = FINALIZE_USE_PTR (ptr);
- 	  delink_imm_use (use_p);
- 	}
- #endif
-       old_ops->next = FINALIZE_FREE;
-       FINALIZE_FREE = old_ops;
-     }
- 
-   /* NOw set the stmt's operands.  */
-   FINALIZE_OPS (stmt) = new_list.next;
- 
- #ifdef ENABLE_CHECKING
-   {
-     unsigned x = 0;
-     for (ptr = FINALIZE_OPS (stmt); ptr; ptr = ptr->next)
-       x++;
- 
-     gcc_assert (x == VEC_length (tree, FINALIZE_OPBUILD));
-   }
- #endif
- }
- 
- #undef FINALIZE_FUNC
- #undef FINALIZE_ALLOC
- #undef FINALIZE_FREE
- #undef FINALIZE_TYPE
- #undef FINALIZE_OPS
- #undef FINALIZE_USE_PTR
- #undef FINALIZE_INITIALIZE
- #undef FINALIZE_ELEM
- #undef FINALIZE_BASE
- #undef FINALIZE_BASE_TYPE
- #undef FINALIZE_OPBUILD
- #undef FINALIZE_OPBUILD_ELEM
- #undef FINALIZE_OPBUILD_BASE
- #undef FINALIZE_BASE_ZERO
- #undef FINALIZE_CORRECT_USE
--- 0 ----
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 111787)
--- Makefile.in	(working copy)
*************** tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $
*** 1945,1952 ****
  tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TREE_INLINE_H) \
     $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) tree-pass.h toplev.h \
!    gt-tree-ssa-operands.h coretypes.h langhooks.h tree-ssa-opfinalize.h \
!    $(IPA_REFERENCE_H)
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) except.h langhooks.h \
     $(GGC_H) tree-pass.h coretypes.h $(TIMEVAR_H) $(TM_P_H) \
--- 1945,1951 ----
  tree-ssa-operands.o : tree-ssa-operands.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) errors.h $(TREE_INLINE_H) \
     $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) tree-pass.h toplev.h \
!    gt-tree-ssa-operands.h coretypes.h langhooks.h $(IPA_REFERENCE_H)
  tree-eh.o : tree-eh.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) except.h langhooks.h \
     $(GGC_H) tree-pass.h coretypes.h $(TIMEVAR_H) $(TM_P_H) \
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 111787)
--- tree-ssa-operands.c	(working copy)
*************** static vuse_optype_p free_vuses = NULL;
*** 130,135 ****
--- 130,148 ----
  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.  */
  
*************** set_virtual_use_link (use_operand_p ptr,
*** 368,391 ****
      link_imm_use (ptr, *(ptr->use));
  }
  
  
! #define FINALIZE_OPBUILD		build_defs
! #define FINALIZE_OPBUILD_BASE(I)	(tree *)VEC_index (tree,	\
! 							   build_defs, (I))
! #define FINALIZE_OPBUILD_ELEM(I)	(tree *)VEC_index (tree,	\
! 							   build_defs, (I))
! #define FINALIZE_FUNC			finalize_ssa_def_ops
! #define FINALIZE_ALLOC			alloc_def
! #define FINALIZE_FREE			free_defs
! #define FINALIZE_TYPE			struct def_optype_d
! #define FINALIZE_ELEM(PTR)		((PTR)->def_ptr)
! #define FINALIZE_OPS			DEF_OPS
! #define FINALIZE_BASE(VAR)		VAR
! #define FINALIZE_BASE_TYPE		tree *
! #define FINALIZE_BASE_ZERO		NULL
! #define FINALIZE_INITIALIZE(PTR, VAL, STMT)	FINALIZE_ELEM (PTR) = (VAL)
! #include "tree-ssa-opfinalize.h"
  
  
  /* This routine will create stmt operands for STMT from the def build list.  */
  
--- 381,565 ----
      link_imm_use (ptr, *(ptr->use));
  }
  
+ /* Appends ELT after TO, and moves the TO pointer to ELT.  */
+ 
+ #define APPEND_OP_AFTER(ELT, TO)	\
+   do					\
+     {					\
+       (TO)->next = (ELT);		\
+       (TO) = (ELT);			\
+     } while (0)
+ 
+ /* Appends head of list FROM after TO, and move both pointers
+    to their successors.  */
+ 
+ #define MOVE_HEAD_AFTER(FROM, TO)	\
+   do					\
+     {					\
+       APPEND_OP_AFTER (FROM, TO);	\
+       (FROM) = (FROM)->next;		\
+     } while (0)
+ 
+ /* Moves OP to appropriate freelist.  OP is set to its successor.  */
+ 
+ #define MOVE_HEAD_TO_FREELIST(OP, TYPE)			\
+   do							\
+     {							\
+       TYPE##_optype_p next = (OP)->next;		\
+       (OP)->next = free_##TYPE##s;			\
+       free_##TYPE##s = (OP);				\
+       (OP) = next;					\
+     } while (0)
+ 
+ /* Initializes immediate use at USE_PTR to value VAL, and links it to the list
+    of immeditate uses.  STMT is the current statement.  */
+ 
+ #define INITIALIZE_USE(USE_PTR, VAL, STMT)		\
+   do							\
+     {							\
+       (USE_PTR)->use = (VAL);				\
+       link_imm_use_stmt ((USE_PTR), *(VAL), (STMT));	\
+     } while (0)
+ 
+ /* Adds OP to the list of defs after LAST, and moves
+    LAST to the new element.  */
+ 
+ static inline void
+ add_def_op (tree *op, def_optype_p *last)
+ {
+   def_optype_p new;
+ 
+   ALLOC_OPTYPE (new, def);
+   DEF_OP_PTR (new) = op;
+   APPEND_OP_AFTER (new, *last);  
+ }
+ 
+ /* Adds OP to the list of uses of statement STMT after LAST, and moves
+    LAST to the new element.  */
+ 
+ static inline void
+ add_use_op (tree stmt, tree *op, use_optype_p *last)
+ {
+   use_optype_p new;
+ 
+   ALLOC_OPTYPE (new, use);
+   INITIALIZE_USE (USE_OP_PTR (new), op, stmt);
+   APPEND_OP_AFTER (new, *last);  
+ }
+ 
+ /* 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)
+ {
+   vuse_optype_p new;
+ 
+   ALLOC_OPTYPE (new, vuse);
+   VUSE_OP (new) = op;
+   INITIALIZE_USE (VUSE_OP_PTR (new), &VUSE_OP (new), stmt);
+   APPEND_OP_AFTER (new, *last);  
+ }
+ 
+ /* 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)
! {
!   maydef_optype_p new;
  
+   ALLOC_OPTYPE (new, maydef);
+   MAYDEF_RESULT (new) = op;
+   MAYDEF_OP (new) = op;
+   INITIALIZE_USE (MAYDEF_OP_PTR (new), &MAYDEF_OP (new), stmt);
+   APPEND_OP_AFTER (new, *last);  
+ }
+ 
+ /* Adds OP to the list of mustdefs of statement STMT after LAST, and moves
+    LAST to the new element.  */
+ 
+ static inline void
+ add_mustdef_op (tree stmt, tree op, mustdef_optype_p *last)
+ {
+   mustdef_optype_p new;
+ 
+   ALLOC_OPTYPE (new, mustdef);
+   MUSTDEF_RESULT (new) = op;
+   MUSTDEF_KILL (new) = op;
+   INITIALIZE_USE (MUSTDEF_KILL_PTR (new), &MUSTDEF_KILL (new), stmt);
+   APPEND_OP_AFTER (new, *last);
+ }
+ 
+ /* 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.
+ 	-- Make build_defs VEC of tree *.  */
+ 
+ static inline void
+ finalize_ssa_def_ops (tree stmt)
+ {
+   unsigned new_i;
+   struct def_optype_d new_list;
+   def_optype_p old_ops, ptr, last;
+   tree *old_base;
+ 
+   new_list.next = NULL;
+   last = &new_list;
+ 
+   old_ops = DEF_OPS (stmt);
+ 
+   new_i = 0;
+   while (old_ops && new_i < VEC_length (tree, build_defs))
+     {
+       tree *new_base = (tree *) VEC_index (tree, build_defs, new_i);
+       old_base = DEF_OP_PTR (old_ops);
+ 
+       if (old_base == new_base)
+         {
+ 	  /* if variables are the same, reuse this node.  */
+ 	  MOVE_HEAD_AFTER (old_ops, last);
+ 	  new_i++;
+ 	}
+       else if (old_base < new_base)
+ 	{
+ 	  /* if old is less than new, old goes to the free list.  */
+ 	  MOVE_HEAD_TO_FREELIST (old_ops, def);
+ 	}
+       else
+ 	{
+ 	  /* This is a new operand.  */
+ 	  add_def_op (new_base, &last);
+ 	  new_i++;
+ 	}
+     }
+ 
+   /* If there is anything remaining in the build_defs list, simply emit it.  */
+   for ( ; new_i < VEC_length (tree, build_defs); new_i++)
+     add_def_op ((tree *) VEC_index (tree, build_defs, new_i), &last);
+ 
+   last->next = NULL;
+ 
+   /* If there is anything in the old list, free it.  */
+   if (old_ops)
+     {
+       old_ops->next = free_defs;
+       free_defs = old_ops;
+     }
+ 
+   /* Now set the stmt's operands.  */
+   DEF_OPS (stmt) = new_list.next;
+ 
+ #ifdef ENABLE_CHECKING
+   {
+     unsigned x = 0;
+     for (ptr = DEF_OPS (stmt); ptr; ptr = ptr->next)
+       x++;
+ 
+     gcc_assert (x == VEC_length (tree, build_defs));
+   }
+ #endif
+ }
  
  /* This routine will create stmt operands for STMT from the def build list.  */
  
*************** finalize_ssa_defs (tree stmt)
*** 403,429 ****
    VEC_truncate (tree, build_defs, 0);
  }
  
! #define FINALIZE_OPBUILD	build_uses
! #define FINALIZE_OPBUILD_BASE(I)	(tree *)VEC_index (tree,	\
! 							   build_uses, (I))
! #define FINALIZE_OPBUILD_ELEM(I)	(tree *)VEC_index (tree,	\
! 							   build_uses, (I))
! #define FINALIZE_FUNC		finalize_ssa_use_ops
! #define FINALIZE_ALLOC		alloc_use
! #define FINALIZE_FREE		free_uses
! #define FINALIZE_TYPE		struct use_optype_d
! #define FINALIZE_ELEM(PTR)	((PTR)->use_ptr.use)
! #define FINALIZE_OPS		USE_OPS
! #define FINALIZE_USE_PTR(PTR)	USE_OP_PTR (PTR)
! #define FINALIZE_CORRECT_USE	correct_use_link
! #define FINALIZE_BASE(VAR)	VAR
! #define FINALIZE_BASE_TYPE	tree *
! #define FINALIZE_BASE_ZERO	NULL
! #define FINALIZE_INITIALIZE(PTR, VAL, STMT)				\
! 				(PTR)->use_ptr.use = (VAL);             \
! 				link_imm_use_stmt (&((PTR)->use_ptr),   \
! 						   *(VAL), (STMT))
! #include "tree-ssa-opfinalize.h"
  
  /* Return a new use operand vector for STMT, comparing to OLD_OPS_P.  */
                                                                                
--- 577,655 ----
    VEC_truncate (tree, build_defs, 0);
  }
  
! /* Takes elements from build_uses and turns them into use operands of STMT.
!    TODO -- Given that use operands list is not neccessarily sorted, merging
! 	   the operands this way does not make much sense.
! 	-- Make build_uses VEC of tree *.  */
! 
! static inline void
! finalize_ssa_use_ops (tree stmt)
! {
!   unsigned new_i;
!   struct use_optype_d new_list;
!   use_optype_p old_ops, ptr, last;
!   tree *old_base, *new_base;
! 
!   new_list.next = NULL;
!   last = &new_list;
! 
!   old_ops = USE_OPS (stmt);
! 
!   new_i = 0;
!   while (old_ops && new_i < VEC_length (tree, build_uses))
!     {
!       new_base = (tree *) VEC_index (tree, build_uses, new_i);
!       old_base = USE_OP_PTR (old_ops)->use;
! 
!       if (old_base == new_base)
!         {
! 	  /* if variables are the same, reuse this node.  */
! 	  MOVE_HEAD_AFTER (old_ops, last);
! 	  correct_use_link (USE_OP_PTR (last), 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));
! 	  MOVE_HEAD_TO_FREELIST (old_ops, use);
! 	}
!       else
! 	{
! 	  /* This is a new operand.  */
! 	  add_use_op (stmt, new_base, &last);
! 	  new_i++;
! 	}
!     }
! 
!   /* If there is anything remaining in the build_uses list, simply emit it.  */
!   for ( ; new_i < VEC_length (tree, build_uses); new_i++)
!     add_use_op (stmt, (tree *) VEC_index (tree, build_uses, new_i), &last);
! 
!   last->next = NULL;
! 
!   /* If there is anything in the old list, free it.  */
!   if (old_ops)
!     {
!       for (ptr = old_ops; ptr; ptr = ptr->next)
! 	delink_imm_use (USE_OP_PTR (ptr));
!       old_ops->next = free_uses;
!       free_uses = old_ops;
!     }
! 
!   /* Now set the stmt's operands.  */
!   USE_OPS (stmt) = new_list.next;
! 
! #ifdef ENABLE_CHECKING
!   {
!     unsigned x = 0;
!     for (ptr = USE_OPS (stmt); ptr; ptr = ptr->next)
!       x++;
! 
!     gcc_assert (x == VEC_length (tree, build_uses));
!   }
! #endif
! }
  
  /* Return a new use operand vector for STMT, comparing to OLD_OPS_P.  */
                                                                                
*************** finalize_ssa_uses (tree stmt)
*** 446,478 ****
    finalize_ssa_use_ops (stmt);
    VEC_truncate (tree, build_uses, 0);
  }
!                                                                               
!                                                                               
! /* Return a new V_MAY_DEF operand vector for STMT, comparing to OLD_OPS_P.  */                                                                                
! #define FINALIZE_OPBUILD	build_v_may_defs
! #define FINALIZE_OPBUILD_ELEM(I)	VEC_index (tree, build_v_may_defs, (I))
! #define FINALIZE_OPBUILD_BASE(I)	get_name_decl (VEC_index (tree,	\
! 							build_v_may_defs, (I)))
! #define FINALIZE_FUNC		finalize_ssa_v_may_def_ops
! #define FINALIZE_ALLOC		alloc_maydef
! #define FINALIZE_FREE		free_maydefs
! #define FINALIZE_TYPE		struct maydef_optype_d
! #define FINALIZE_ELEM(PTR)	MAYDEF_RESULT (PTR)
! #define FINALIZE_OPS		MAYDEF_OPS
! #define FINALIZE_USE_PTR(PTR)	MAYDEF_OP_PTR (PTR)
! #define FINALIZE_CORRECT_USE	set_virtual_use_link
! #define FINALIZE_BASE_ZERO	0
! #define FINALIZE_BASE(VAR)	get_name_decl (VAR)
! #define FINALIZE_BASE_TYPE	unsigned
! #define FINALIZE_INITIALIZE(PTR, VAL, STMT)				\
! 				(PTR)->def_var = (VAL);			\
! 				(PTR)->use_var = (VAL);			\
! 				(PTR)->use_ptr.use = &((PTR)->use_var);	\
! 				link_imm_use_stmt (&((PTR)->use_ptr),	\
! 						   (VAL), (STMT))
! #include "tree-ssa-opfinalize.h"
!                                                                               
!                                                                               
  static void
  finalize_ssa_v_may_defs (tree stmt)
  {
--- 672,753 ----
    finalize_ssa_use_ops (stmt);
    VEC_truncate (tree, build_uses, 0);
  }
! 
! 
! /* Takes elements from build_v_may_defs and turns them into maydef operands of
!    STMT.  */
! 
! static inline void
! finalize_ssa_v_may_def_ops (tree stmt)
! {
!   unsigned new_i;
!   struct maydef_optype_d new_list;
!   maydef_optype_p old_ops, ptr, last;
!   tree act;
!   unsigned old_base, new_base;
! 
!   new_list.next = NULL;
!   last = &new_list;
! 
!   old_ops = MAYDEF_OPS (stmt);
! 
!   new_i = 0;
!   while (old_ops && new_i < VEC_length (tree, build_v_may_defs))
!     {
!       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));
! 
!       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);
! 	  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));
! 	  MOVE_HEAD_TO_FREELIST (old_ops, maydef);
! 	}
!       else
! 	{
! 	  /* This is a new operand.  */
! 	  add_maydef_op (stmt, act, &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);
! 
!   last->next = NULL;
! 
!   /* If there is anything in the old list, free it.  */
!   if (old_ops)
!     {
!       for (ptr = old_ops; ptr; ptr = ptr->next)
! 	delink_imm_use (MAYDEF_OP_PTR (ptr));
!       old_ops->next = free_maydefs;
!       free_maydefs = old_ops;
!     }
! 
!   /* Now set the stmt's operands.  */
!   MAYDEF_OPS (stmt) = new_list.next;
! 
! #ifdef ENABLE_CHECKING
!   {
!     unsigned x = 0;
!     for (ptr = MAYDEF_OPS (stmt); ptr; ptr = ptr->next)
!       x++;
! 
!     gcc_assert (x == VEC_length (tree, build_v_may_defs));
!   }
! #endif
! }
! 
  static void
  finalize_ssa_v_may_defs (tree stmt)
  {
*************** cleanup_v_may_defs (void)
*** 500,529 ****
    VEC_truncate (tree, build_v_may_defs, 0);
  }                                                                             
  
-                                                                               
- #define FINALIZE_OPBUILD	build_vuses
- #define FINALIZE_OPBUILD_ELEM(I)	VEC_index (tree, build_vuses, (I))
- #define FINALIZE_OPBUILD_BASE(I)	get_name_decl (VEC_index (tree,	\
- 							build_vuses, (I)))
- #define FINALIZE_FUNC		finalize_ssa_vuse_ops
- #define FINALIZE_ALLOC		alloc_vuse
- #define FINALIZE_FREE		free_vuses
- #define FINALIZE_TYPE		struct vuse_optype_d
- #define FINALIZE_ELEM(PTR)	VUSE_OP (PTR)
- #define FINALIZE_OPS		VUSE_OPS
- #define FINALIZE_USE_PTR(PTR)	VUSE_OP_PTR (PTR)
- #define FINALIZE_CORRECT_USE	set_virtual_use_link
- #define FINALIZE_BASE_ZERO	0
- #define FINALIZE_BASE(VAR)	get_name_decl (VAR)
- #define FINALIZE_BASE_TYPE	unsigned
- #define FINALIZE_INITIALIZE(PTR, VAL, STMT)				\
- 				(PTR)->use_var = (VAL);			\
- 				(PTR)->use_ptr.use = &((PTR)->use_var);	\
- 				link_imm_use_stmt (&((PTR)->use_ptr),	\
- 						   (VAL), (STMT))
- #include "tree-ssa-opfinalize.h"
  
  
  /* Return a new VUSE operand vector, comparing to OLD_OPS_P.  */
                                                                                
  static void
--- 775,855 ----
    VEC_truncate (tree, build_v_may_defs, 0);
  }                                                                             
  
  
+ /* Takes elements from build_vuses and turns them into vuse operands of
+    STMT.  */
+ 
+ static inline void
+ finalize_ssa_vuse_ops (tree stmt)
+ {
+   unsigned new_i;
+   struct vuse_optype_d new_list;
+   vuse_optype_p old_ops, ptr, last;
+   tree act;
+   unsigned old_base, new_base;
  
+   new_list.next = NULL;
+   last = &new_list;
+ 
+   old_ops = VUSE_OPS (stmt);
+ 
+   new_i = 0;
+   while (old_ops && new_i < VEC_length (tree, build_vuses))
+     {
+       act = VEC_index (tree, build_vuses, new_i);
+       new_base = get_name_decl (act);
+       old_base = get_name_decl (VUSE_OP (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 (VUSE_OP_PTR (last), 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));
+ 	  MOVE_HEAD_TO_FREELIST (old_ops, vuse);
+ 	}
+       else
+ 	{
+ 	  /* This is a new operand.  */
+ 	  add_vuse_op (stmt, act, &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);
+ 
+   last->next = NULL;
+ 
+   /* If there is anything in the old list, free it.  */
+   if (old_ops)
+     {
+       for (ptr = old_ops; ptr; ptr = ptr->next)
+ 	delink_imm_use (VUSE_OP_PTR (ptr));
+       old_ops->next = free_vuses;
+       free_vuses = old_ops;
+     }
+ 
+   /* Now set the stmt's operands.  */
+   VUSE_OPS (stmt) = new_list.next;
+ 
+ #ifdef ENABLE_CHECKING
+   {
+     unsigned x = 0;
+     for (ptr = VUSE_OPS (stmt); ptr; ptr = ptr->next)
+       x++;
+ 
+     gcc_assert (x == VEC_length (tree, build_vuses));
+   }
+ #endif
+ }
+                                                                               
  /* Return a new VUSE operand vector, comparing to OLD_OPS_P.  */
                                                                                
  static void
*************** finalize_ssa_vuses (tree stmt)
*** 590,621 ****
    VEC_truncate (tree, build_vuses, 0);
  
  }
-                                                                               
- /* Return a new V_MUST_DEF operand vector for STMT, comparing to OLD_OPS_P.  */
-                                                                               
- #define FINALIZE_OPBUILD	build_v_must_defs
- #define FINALIZE_OPBUILD_ELEM(I)	VEC_index (tree, build_v_must_defs, (I))
- #define FINALIZE_OPBUILD_BASE(I)	get_name_decl (VEC_index (tree,	\
- 							build_v_must_defs, (I)))
- #define FINALIZE_FUNC		finalize_ssa_v_must_def_ops
- #define FINALIZE_ALLOC		alloc_mustdef
- #define FINALIZE_FREE		free_mustdefs
- #define FINALIZE_TYPE		struct mustdef_optype_d
- #define FINALIZE_ELEM(PTR)	MUSTDEF_RESULT (PTR)
- #define FINALIZE_OPS		MUSTDEF_OPS
- #define FINALIZE_USE_PTR(PTR)	MUSTDEF_KILL_PTR (PTR)
- #define FINALIZE_CORRECT_USE	set_virtual_use_link
- #define FINALIZE_BASE_ZERO	0
- #define FINALIZE_BASE(VAR)	get_name_decl (VAR)
- #define FINALIZE_BASE_TYPE	unsigned
- #define FINALIZE_INITIALIZE(PTR, VAL, STMT)				\
- 				(PTR)->def_var = (VAL);			\
- 				(PTR)->kill_var = (VAL);		\
- 				(PTR)->use_ptr.use = &((PTR)->kill_var);\
- 				link_imm_use_stmt (&((PTR)->use_ptr),	\
- 						   (VAL), (STMT))
- #include "tree-ssa-opfinalize.h"
  
  
  static void
  finalize_ssa_v_must_defs (tree stmt)
--- 916,995 ----
    VEC_truncate (tree, build_vuses, 0);
  
  }
  
+ /* Takes elements from build_v_must_defs and turns them into mustdef operands of
+    STMT.  */
+ 
+ static inline void
+ finalize_ssa_v_must_def_ops (tree stmt)
+ {
+   unsigned new_i;
+   struct mustdef_optype_d new_list;
+   mustdef_optype_p old_ops, ptr, last;
+   tree act;
+   unsigned old_base, new_base;
+ 
+   new_list.next = NULL;
+   last = &new_list;
+ 
+   old_ops = MUSTDEF_OPS (stmt);
+ 
+   new_i = 0;
+   while (old_ops && new_i < VEC_length (tree, build_v_must_defs))
+     {
+       act = VEC_index (tree, build_v_must_defs, new_i);
+       new_base = get_name_decl (act);
+       old_base = get_name_decl (MUSTDEF_KILL (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 (MUSTDEF_KILL_PTR (last), stmt);
+ 	  new_i++;
+ 	}
+       else if (old_base < new_base)
+ 	{
+ 	  /* If old is less than new, old goes to the free list.  */
+ 	  delink_imm_use (MUSTDEF_KILL_PTR (old_ops));
+ 	  MOVE_HEAD_TO_FREELIST (old_ops, mustdef);
+ 	}
+       else
+ 	{
+ 	  /* This is a new operand.  */
+ 	  add_mustdef_op (stmt, act, &last);
+ 	  new_i++;
+ 	}
+     }
+ 
+   /* If there is anything remaining in the build_v_must_defs list, simply emit it.  */
+   for ( ; new_i < VEC_length (tree, build_v_must_defs); new_i++)
+     add_mustdef_op (stmt, VEC_index (tree, build_v_must_defs, new_i), &last);
+ 
+   last->next = NULL;
+ 
+   /* If there is anything in the old list, free it.  */
+   if (old_ops)
+     {
+       for (ptr = old_ops; ptr; ptr = ptr->next)
+ 	delink_imm_use (MUSTDEF_KILL_PTR (ptr));
+       old_ops->next = free_mustdefs;
+       free_mustdefs = old_ops;
+     }
+ 
+   /* Now set the stmt's operands.  */
+   MUSTDEF_OPS (stmt) = new_list.next;
+ 
+ #ifdef ENABLE_CHECKING
+   {
+     unsigned x = 0;
+     for (ptr = MUSTDEF_OPS (stmt); ptr; ptr = ptr->next)
+       x++;
+ 
+     gcc_assert (x == VEC_length (tree, build_v_must_defs));
+   }
+ #endif
+ }
  
  static void
  finalize_ssa_v_must_defs (tree stmt)


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