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]

[rtlopt] improvements of variable tracking


Hi,

this patch contains many improvements:
now hash table of link lists instead of one link list is used for memory
locations.
The memories with the same ALIAS_SET were considered identical before,
now the memories must have same MEM_EXPR.
Only the named variables are tracked now.
And maybe some more.

This is not the last version, I plan more minor improvements.

Bootstrapped i386.

Josef


2003-01-16  Josef Zlomek  <zlomekj@suse.cz>

	* var-tracking.c (IN_OUT_SIZE): Deleted.
	(MEMORY_VAR): Deleted.
	(struct var_tracking_info_def): Add new fields (hash tables).
	(VARIABLE_P): New test for DECL_NAME.
	(attrs_list_member_alias): Delete.
	(attrs_list_delete_alias): Delete.
	(attrs_list_different_alias): Delete.
	(MEM_HASH_VAL): New macro.
	(mem_htab_hash): New function.
	(mem_htab_eq): New function.
	(attrs_list_union): New function.
	(attrs_htab_insert): New function.
	(attrs_htab_delete): New function.
	(attrs_htab_different_1): New function.
	(attrs_htab_different): New function.
	(attrs_htab_copy_1): New function.
	(attrs_htab_copy): New function.
	(attrs_htab_union_1): New function.
	(attrs_htab_union): New function.
	(attrs_htab_clear): New function.
	(attrs_htab_cleanup): New function.
	(dump_attrs_list): New function.
	(dump_mem_attrs_list): New function.
	(process_bb_delete): New function.
	(mark_variables_for_deletion): New function.
	(add_and_unmark_variables): New function.
	(scan_for_locations): Scan SET_SRC before SET_DEST.
	(*): Use hash tables from MEMs.

*** gcc-rtlopt/gcc/var-tracking.c	Wed Jan 15 15:47:43 2003
--- var-tracking.c	Thu Jan 16 18:50:55 2003
***************
*** 22,44 ****
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
- 
  #include "rtl.h"
- #include "basic-block.h"
  #include "tree.h"
  #include "output.h"
  #include "sbitmap.h"
  #include "fibheap.h"
  #include "hashtab.h"
  
! #define IN_OUT_SIZE (FIRST_PSEUDO_REGISTER + 1)
! #define MEMORY_VAR FIRST_PSEUDO_REGISTER
! 
! #define DEBUG_REG_LOC 1
! #define DEBUG_MEM_LOC 1
! 
! #define VARIABLE_P(DECL) (TREE_CODE (DECL) == VAR_DECL		\
! 			  || TREE_CODE (DECL) == PARM_DECL)
  
  /* The purpose that the location (REG or MEM) has in RTL.  */
  enum location_type
--- 22,38 ----
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
  #include "rtl.h"
  #include "tree.h"
+ #include "basic-block.h"
  #include "output.h"
  #include "sbitmap.h"
  #include "fibheap.h"
  #include "hashtab.h"
  
! #define DEBUG_REG_LOC 0
! #define DEBUG_MEM_LOC 0
! /*#define DEBUG_LENGTH 10*/
  
  /* The purpose that the location (REG or MEM) has in RTL.  */
  enum location_type
*************** typedef struct emit_note_data_def
*** 104,112 ****
  /* The variables that are stored in a register are remembered in a link-list
     because there should not be many variables in one register so
     the link-list would be the fastest solution.  */
! /* The variables stored in memory are NOW also remembered in a link-list.
!    This will be changed to some better data structure because there can be
!    many variables in function (stored in memory).  */
  
  /* The node of the link-list for describing the attributes of a variable.  */
  typedef struct attrs_list_def
--- 98,106 ----
  /* The variables that are stored in a register are remembered in a link-list
     because there should not be many variables in one register so
     the link-list would be the fastest solution.  */
! /* The variables stored in memory are remembered in a hash table, locations for
!    each variable are remembered in a link-list.  */
! /* TODO: Replace the link-lists by splay-trees?  */
  
  /* The node of the link-list for describing the attributes of a variable.  */
  typedef struct attrs_list_def
*************** typedef struct var_tracking_info_def
*** 134,149 ****
    /* The array of locations.  */
    location *locs;
  
!   /* Input attributes (lists of attrs).  */
!   attrs_list in[IN_OUT_SIZE];
  
!   /* Output attributes.  */
!   attrs_list out[IN_OUT_SIZE];
! } *var_tracking_info;
  
! #define VTI(BB) ((var_tracking_info) (BB)->aux)
  
! #define MAX_LOC 16
  
  /* Structure for description of one part of variable location.  */
  typedef struct location_part_def
--- 128,145 ----
    /* The array of locations.  */
    location *locs;
  
!   /* Input attributes for registers (lists of attrs).  */
!   attrs_list in[FIRST_PSEUDO_REGISTER];
  
!   /* Input attributes for memory.  */
!   htab_t mem_in;
  
!   /* Output attributes for registers.  */
!   attrs_list out[FIRST_PSEUDO_REGISTER];
  
!   /* Output attributes for memory.  */
!   htab_t mem_out;
! } *var_tracking_info;
  
  /* Structure for description of one part of variable location.  */
  typedef struct location_part_def
*************** typedef struct location_part_def
*** 158,163 ****
--- 154,162 ----
    bool delete_p;
  } location_part;
  
+ /* Maximum number of location parts.  */
+ #define MAX_LOC_PARTS 16
+ 
  /* Structure for description where the variable is located.  */
  typedef struct variable_def
  {
*************** typedef struct variable_def
*** 168,174 ****
    int n_location_parts;
  
    /* The locations.  */
!   location_part location_part[MAX_LOC];
  
    /* Changed?  */
    bool changed;
--- 167,173 ----
    int n_location_parts;
  
    /* The locations.  */
!   location_part location_part[MAX_LOC_PARTS];
  
    /* Changed?  */
    bool changed;
*************** typedef struct variable_def
*** 177,231 ****
  /* The hashtable of STRUCT VARIABLE_DEF.  */
  static htab_t variable_htab;
  
  /* Local function prototypes.  */
  static void init_attrs_list_set		PARAMS ((attrs_list *));
  static void attrs_list_clear		PARAMS ((attrs_list *));
  static attrs_list attrs_list_member	PARAMS ((attrs_list, tree,
  						 HOST_WIDE_INT));
- static attrs_list attrs_list_member_alias	PARAMS ((attrs_list,
- 							 HOST_WIDE_INT,
- 							 HOST_WIDE_INT));
  static void attrs_list_insert		PARAMS ((attrs_list *, tree,
!                                                HOST_WIDE_INT, rtx));
  static void attrs_list_delete		PARAMS ((attrs_list *, tree,
!                                                HOST_WIDE_INT));
! static void attrs_list_delete_alias	PARAMS ((attrs_list *, HOST_WIDE_INT,
!                                                HOST_WIDE_INT));
  static void attrs_list_copy		PARAMS ((attrs_list *, attrs_list));
  static bool attrs_list_different	PARAMS ((attrs_list, attrs_list));
! static bool attrs_list_different_alias	PARAMS ((attrs_list, attrs_list));
  
  static int scan_for_locations		PARAMS ((rtx *, void *));
  static bool compute_bb_dataflow		PARAMS ((basic_block));
  static void hybrid_search		PARAMS ((basic_block, sbitmap,
!                                                sbitmap));
  static void iterative_dataflow		PARAMS ((int *));
  static void dump_attrs_list_sets	PARAMS ((void));
  
- static hashval_t variable_htab_hash	PARAMS ((const void *));
- static int variable_htab_eq		PARAMS ((const void *, const void *));
  static void note_insn_var_location_emit	PARAMS ((rtx, enum where_emit_note,
!                                                variable));
  static void set_location_part		PARAMS ((tree, HOST_WIDE_INT, rtx,
!                                                rtx, enum where_emit_note));
  static void delete_location_part	PARAMS ((tree, HOST_WIDE_INT, rtx,
!                                                enum where_emit_note));
  static int process_location_parts	PARAMS ((void **, void *));
  static void emit_note_if_var_changed	PARAMS ((void **, void *));
  static void process_bb			PARAMS ((basic_block));
  static void var_tracking_emit_notes	PARAMS ((void));
  
  static void var_tracking_initialize	PARAMS ((void));
  static void var_tracking_finalize	PARAMS ((void));
  
  /* Initialize the set (array) SET of the attrs_lists to empty lists.  */
  
! static void init_attrs_list_set (set)
       attrs_list *set;
  {
    int i;
  
!   for (i = 0; i < IN_OUT_SIZE; i++)
      set[i] = NULL;
  }
  
--- 176,310 ----
  /* The hashtable of STRUCT VARIABLE_DEF.  */
  static htab_t variable_htab;
  
+ /* Is DECL a named variable or parameter of function?  */
+ #define VARIABLE_P(DECL) ((TREE_CODE (DECL) == VAR_DECL			\
+ 			   || TREE_CODE (DECL) == PARM_DECL)		\
+ 			  && DECL_NAME (DECL))
+ 
+ /* Hash function for MEM_IN and MEM_OUT.  */
+ #define MEM_HASH_VAL(mem) ((size_t) MEM_ALIAS_SET (mem))
+ 
+ /* Hash function for VARIABLE_HTAB.  */
+ #define VARIABLE_HASH_VAL(decl) ((size_t) decl)
+ 
+ /* Get the pointer to the BB's information specific to var-tracking pass.  */
+ #define VTI(BB) ((var_tracking_info) (BB)->aux)
+ 
  /* Local function prototypes.  */
+ static hashval_t mem_htab_hash		PARAMS ((const void *));
+ static int mem_htab_eq			PARAMS ((const void *, const void *));
+ static hashval_t variable_htab_hash	PARAMS ((const void *));
+ static int variable_htab_eq		PARAMS ((const void *, const void *));
+ 
  static void init_attrs_list_set		PARAMS ((attrs_list *));
  static void attrs_list_clear		PARAMS ((attrs_list *));
  static attrs_list attrs_list_member	PARAMS ((attrs_list, tree,
  						 HOST_WIDE_INT));
  static void attrs_list_insert		PARAMS ((attrs_list *, tree,
! 						 HOST_WIDE_INT, rtx));
  static void attrs_list_delete		PARAMS ((attrs_list *, tree,
! 						 HOST_WIDE_INT));
  static void attrs_list_copy		PARAMS ((attrs_list *, attrs_list));
+ static void attrs_list_union		PARAMS ((attrs_list *,attrs_list));
  static bool attrs_list_different	PARAMS ((attrs_list, attrs_list));
! 
! static void attrs_htab_insert		PARAMS ((htab_t, rtx));
! static void attrs_htab_delete		PARAMS ((htab_t, rtx));
! static int attrs_htab_different_1	PARAMS ((void **, void *));
! static bool attrs_htab_different	PARAMS ((htab_t, htab_t));
! static int attrs_htab_copy_1		PARAMS ((void **, void *));
! static void attrs_htab_copy		PARAMS ((htab_t, htab_t));
! static int attrs_htab_union_1		PARAMS ((void **, void *));
! static void attrs_htab_union		PARAMS ((htab_t, htab_t));
! static void attrs_htab_clear		PARAMS ((htab_t));
! static void attrs_htab_cleanup		PARAMS ((void *));
  
  static int scan_for_locations		PARAMS ((rtx *, void *));
  static bool compute_bb_dataflow		PARAMS ((basic_block));
  static void hybrid_search		PARAMS ((basic_block, sbitmap,
! 						 sbitmap));
  static void iterative_dataflow		PARAMS ((int *));
+ static inline void dump_attrs_list	PARAMS ((attrs_list));
+ static int dump_mem_attrs_list		PARAMS ((void **, void *));
  static void dump_attrs_list_sets	PARAMS ((void));
  
  static void note_insn_var_location_emit	PARAMS ((rtx, enum where_emit_note,
! 						 variable));
  static void set_location_part		PARAMS ((tree, HOST_WIDE_INT, rtx,
! 						 rtx, enum where_emit_note));
  static void delete_location_part	PARAMS ((tree, HOST_WIDE_INT, rtx,
! 						 enum where_emit_note));
  static int process_location_parts	PARAMS ((void **, void *));
  static void emit_note_if_var_changed	PARAMS ((void **, void *));
+ static inline void process_bb_delete	PARAMS ((attrs_list *, htab_t, int,
+ 						 rtx, rtx,
+ 						 enum where_emit_note));
  static void process_bb			PARAMS ((basic_block));
+ static int mark_variables_for_deletion	PARAMS ((void **, void *));
+ static int add_and_unmark_variables	PARAMS ((void **, void *));
  static void var_tracking_emit_notes	PARAMS ((void));
  
  static void var_tracking_initialize	PARAMS ((void));
  static void var_tracking_finalize	PARAMS ((void));
  
+ /* Return the hash value for X.  */
+ 
+ static hashval_t
+ mem_htab_hash (x)
+      const void *x;
+ {
+   const attrs_list list = (const attrs_list) x;
+ 
+   return (MEM_HASH_VAL (list->loc));
+ }
+ 
+ /* Shall X and Y go to the same hash slot?  */
+ 
+ static int
+ mem_htab_eq (x, y)
+      const void *x;
+      const void *y;
+ {
+   const attrs_list list = (const attrs_list) x;
+   const rtx mem = (const rtx) y;
+ 
+   return (MEM_HASH_VAL (list->loc) == MEM_HASH_VAL (mem));
+ }
+ 
+ /* The hash function for variable_htab, computes the hash value
+    of the variable X declaration.  */
+ 
+ static hashval_t
+ variable_htab_hash (x)
+      const void *x;
+ {
+   const variable v = (const variable) x;
+ 
+   return (VARIABLE_HASH_VAL (v->decl));
+ }
+ 
+ /* Compare the declaration of variable X with declaration Y.  */
+ 
+ static int
+ variable_htab_eq (x, y)
+      const void *x;
+      const void *y;
+ {
+   const variable v = (const variable) x;
+   const tree decl = (const tree) y;
+ 
+   return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
+ }
+ 
  /* Initialize the set (array) SET of the attrs_lists to empty lists.  */
  
! static void
! init_attrs_list_set (set)
       attrs_list *set;
  {
    int i;
  
!   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      set[i] = NULL;
  }
  
*************** attrs_list_member (list, decl, offset)
*** 259,279 ****
    return NULL;
  }
  
- /* Return true if there is a node in the list LIST that has the memory alias
-    set of node->loc same as ALIAS and the offset equal to OFFSET.  */
- 
- static attrs_list
- attrs_list_member_alias (list, alias, offset)
-      attrs_list list;
-      HOST_WIDE_INT alias;
-      HOST_WIDE_INT offset;
- {
-   for (; list; list = list->next)
-     if (MEM_ALIAS_SET (list->loc) == alias && list->offset == offset)
-       return list;
-   return NULL;
- }
- 
  /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
  
  static void
--- 338,343 ----
*************** attrs_list_delete (listp, decl, offset)
*** 319,351 ****
      }
  }
  
- /* Delete all occurences from the list *LISTP that have the offset equal to
-    OFFSET and memory alias set of node->loc equal to ALIAS.  */
- 
- static void
- attrs_list_delete_alias (listp, alias, offset)
-      attrs_list *listp;
-      HOST_WIDE_INT alias;
-      HOST_WIDE_INT offset;
- {
-   attrs_list list, next_list, prev_list = NULL;
- 
-   for (list = *listp; list; list = next_list)
-     {
-       next_list = list->next;
-       if (MEM_ALIAS_SET (list->loc) == alias && list->offset == offset)
- 	{
- 	  if (prev_list)
- 	    prev_list->next = next_list;
- 	  else
- 	    *listp = next_list;
- 	  free (list);
- 	}
-       else
- 	prev_list = list;
-     }
- }
- 
  /* Make a copy of all nodes from SRC and make a list *DSTP of the copies.  */
  
  static void
--- 383,388 ----
*************** attrs_list_copy (dstp, src)
*** 366,372 ****
        n->next = *dstp;
        *dstp = n;
      }
!   /*printf ("%d\n", i);*/
  }
  
  /* Return true if the lists A and B do not have the same DECL and OFFSET values
--- 403,426 ----
        n->next = *dstp;
        *dstp = n;
      }
! #ifdef DEBUG_LENGTH
!   if (i >= DEBUG_LENGTH)
!     printf ("l=%d\n", i);
! #endif
! }
! 
! /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
! 
! static void
! attrs_list_union (dstp, src)
!      attrs_list *dstp;
!      attrs_list src;
! {
!   for (; src; src = src->next)
!     {
!       if (!attrs_list_member (*dstp, src->decl, src->offset))
! 	attrs_list_insert (dstp, src->decl, src->offset, src->loc);
!     }
  }
  
  /* Return true if the lists A and B do not have the same DECL and OFFSET values
*************** attrs_list_different (a, b)
*** 390,414 ****
    return false;
  }
  
! /* Return true if the lists A and B do not have the same OFFSETs
!    and memory alias sets loc in nodes.  */
  
  static bool
! attrs_list_different_alias (a, b)
!      attrs_list a;
!      attrs_list b;
  {
!   attrs_list i;
  
!   for (i = a; i; i = i->next)
!     if (!attrs_list_member_alias (b, MEM_ALIAS_SET (i->loc), i->offset))
!       return true;
  
!   for (i = b; i; i = i->next)
!     if (!attrs_list_member_alias (a, MEM_ALIAS_SET (i->loc), i->offset))
!       return true;
  
!   return false;
  }
  
  /* Scan rtx X for registers and memory references. Other parameters are
--- 444,686 ----
    return false;
  }
  
! /* Insert MEM attributes to appropriate list in HTAB.  */
! 
! static void
! attrs_htab_insert (htab, mem)
!      htab_t htab;
!      rtx mem;
! {
!   attrs_list list, *listp;
! 
!   listp = (attrs_list *) htab_find_slot_with_hash (htab, mem,
! 						   MEM_HASH_VAL (mem),
! 						   NO_INSERT);
!   if (!listp)
!     {
!       listp = (attrs_list *) htab_find_slot_with_hash (htab, mem,
! 						       MEM_HASH_VAL (mem),
! 						       INSERT);
!     }
! 
!   list = xmalloc (sizeof (*list));
!   list->loc = mem;
!   list->decl = MEM_EXPR (mem);
!   list->offset = MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0;
!   list->next = *listp;
!   *listp = list;
! }
! 
! /* Delete MEM attributes from HTAB.  */
! 
! static void
! attrs_htab_delete (htab, mem)
!      htab_t htab;
!      rtx mem;
! {
!   attrs_list list, next_list, prev_list;
!   attrs_list *listp;
!   HOST_WIDE_INT offset;
!   tree decl;
! 
!   listp = (attrs_list *) htab_find_slot_with_hash (htab, mem,
! 						   MEM_HASH_VAL (mem),
! 						   NO_INSERT);
!   if (!listp)
!     return;
! 
!   offset = MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0;
!   decl = MEM_EXPR (mem);
! 
!   for (list = *listp; list; list = list->next)
!     if (list->decl != decl || list->offset != offset)
!       break;
! 
!   if (list)	/* There is at least 1 node that will not be deleted.  */
!     {
!       prev_list = NULL;
!       for (list = *listp; list; list = next_list)
! 	{
! 	  next_list = list->next;
! 	  if (list->decl == decl && list->offset == offset)
! 	    {
! 	      if (prev_list)
! 		prev_list->next = next_list;
! 	      else
! 		*listp = next_list;
! 	      free (list);
! 	    }
! 	  else
! 	    prev_list = list;
! 	}
!     }
!   else
!     {
!       htab_clear_slot (htab, (void **) listp);
!     }
! }
  
+ /* Flag whether two hash-tables being compared contain different data.  */
  static bool
! attrs_htab_different_value;
! 
! /* Compare one SLOT with the corresponding slot from hash-table DATA.  */
!    
! static int
! attrs_htab_different_1 (slot, data)
!      void **slot;
!      void *data;
  {
!   htab_t htab = (htab_t) data;
!   attrs_list list1, list2, list;
  
!   list1 = *(attrs_list *) slot;
!   list2 = (attrs_list) htab_find_with_hash (htab, list1->loc,
! 					    MEM_HASH_VAL (list1->loc));
  
!   if (!list1)
!     abort ();
!   for (; list1; list1 = list1->next)
!     {
!       for (list = list2; list; list = list->next)
! 	if (list->decl == list1->decl && list->offset == list1->offset)
! 	  break;
!       if (!list)
! 	{
! 	  attrs_htab_different_value = true;
! 	  return 0;
! 	}
!     }
!   return 1;
! }
  
! /* Return true if HTAB1 and HTAB2 contain different data.  */
! 
! static bool
! attrs_htab_different (htab1, htab2)
!      htab_t htab1;
!      htab_t htab2;
! {
!   attrs_htab_different_value = false;
!   htab_traverse (htab1, attrs_htab_different_1, htab2);
!   if (!attrs_htab_different_value)
!     htab_traverse (htab2, attrs_htab_different_1, htab1);
! 
!   return attrs_htab_different_value;
! }
! 
! /* Copy one SLOT to hash-table DATA.  */
! 
! static int
! attrs_htab_copy_1 (slot, data)
!      void **slot;
!      void *data;
! {
!   htab_t dst = (htab_t) data;
!   attrs_list src, *dstp, list;
!   int i;
! 
!   src = *(attrs_list *) slot;
!   dstp = (attrs_list *) htab_find_slot_with_hash (dst, src->loc,
! 						  MEM_HASH_VAL (src->loc),
! 						  INSERT);
!   for (i = 0; src; src = src->next, i++)
!     {
!       list = xmalloc (sizeof (*list));
!       list->loc = src->loc;
!       list->decl = src->decl;
!       list->offset = src->offset;
!       list->next = *dstp;
!       *dstp = list;
!     }
! #ifdef DEBUG_LENGTH
!   if (i >= DEBUG_LENGTH)
!     printf ("L=%d\n", i);
! #endif
!   return 1;
! }
! 
! /* Copy the content of hash-table SRC to DST.  */
! 
! static void
! attrs_htab_copy (dst, src)
!      htab_t dst;
!      htab_t src;
! {
!   attrs_htab_clear (dst);
!   htab_traverse (src, attrs_htab_copy_1, dst);
! }
! 
! /* Add all nodes from list in SLOT which are not in hash DATA to DATA.  */
! 
! static int
! attrs_htab_union_1 (slot, data)
!      void **slot;
!      void *data;
! {
!   htab_t htab = (htab_t) data;
!   attrs_list src, *dstp, list;
! 
!   src = *(attrs_list *) slot;
!   dstp = (attrs_list *) htab_find_slot_with_hash (htab, src->loc,
! 						  MEM_HASH_VAL (src->loc),
! 						  NO_INSERT);
!   if (!dstp)
!     {
!       dstp = (attrs_list *) htab_find_slot_with_hash (htab, src->loc,
! 						      MEM_HASH_VAL (src->loc),
! 						      INSERT);
!     }
!   for (; src; src = src->next)
!     {
!       for (list = *dstp; list; list = list->next)
! 	if (list->decl == src->decl && list->offset == src->offset)
! 	  break;
!       if (!list)
! 	{
! 	  list = xmalloc (sizeof (*list));
! 	  list->loc = src->loc;
! 	  list->decl = src->decl;
! 	  list->offset = src->offset;
! 	  list->next = *dstp;
! 	  *dstp = list;
! 	}
!     }
!   return 1;
! }
! 
! /* Add all nodes from SRC which are not in hash DST to DST.  */
! 
! static void
! attrs_htab_union (dst, src)
!      htab_t dst;
!      htab_t src;
! {
!   htab_traverse (src, attrs_htab_union_1, dst);
! }
! 
! /* Delete all data from HTAB.  */
! 
! static void
! attrs_htab_clear (htab)
!      htab_t htab;
! {
!   htab_empty (htab);
! }
! 
! /* Delete data from SLOT.  */
! 
! static void
! attrs_htab_cleanup (slot)
!      void *slot;
! {
!   attrs_list list, next_list;
! 
!   for (list = (attrs_list) slot; list; list = next_list)
!     {
!       next_list = list->next;
!       free (list);
!     }
  }
  
  /* Scan rtx X for registers and memory references. Other parameters are
*************** scan_for_locations (x, data)
*** 435,442 ****
--- 707,716 ----
  	switch (GET_CODE (*x))
  	  {
  	    case REG:
+ #ifdef ENABLE_CHECKING
  	      if (REGNO (*x) >= FIRST_PSEUDO_REGISTER)
  		abort ();
+ #endif
  	      VTI (bb)->n_locs++;
  	      /* Continue traversing.  */
  	      return 0;
*************** scan_for_locations (x, data)
*** 458,469 ****
  	  {
  	    case SET:
  	      old_type = d->type;
- 	      d->type = LT_SET_DEST;
- 	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
  	      d->type = LT_PARAM;
  	      for_each_rtx (&SET_SRC (*x), scan_for_locations, data);
  	      d->type = old_type;
! 	      /* Stop traversing.  */
  	      return -1;
  
  	    case CLOBBER:
--- 732,743 ----
  	  {
  	    case SET:
  	      old_type = d->type;
  	      d->type = LT_PARAM;
  	      for_each_rtx (&SET_SRC (*x), scan_for_locations, data);
+ 	      d->type = LT_SET_DEST;
+ 	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
  	      d->type = old_type;
! 	      /* Do not traverse sub-expressions.  */
  	      return -1;
  
  	    case CLOBBER:
*************** scan_for_locations (x, data)
*** 471,477 ****
  	      d->type = LT_CLOBBERED;
  	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
  	      d->type = old_type;
! 	      /* Stop traversing.  */
  	      return -1;
  
  	    case REG:
--- 745,751 ----
  	      d->type = LT_CLOBBERED;
  	      for_each_rtx (&SET_DEST (*x), scan_for_locations, data);
  	      d->type = old_type;
! 	      /* Do not traverse sub-expressions.  */
  	      return -1;
  
  	    case REG:
*************** scan_for_locations (x, data)
*** 479,485 ****
  	      l->loc = *x;
  	      l->insn = d->insn;
  	      l->type = d->type;
! 	      /* Stop traversing.  */
  	      return -1;
  
  	    case MEM:
--- 753,759 ----
  	      l->loc = *x;
  	      l->insn = d->insn;
  	      l->type = d->type;
! 	      /* Do not traverse sub-expressions.  */
  	      return -1;
  
  	    case MEM:
*************** scan_for_locations (x, data)
*** 497,503 ****
  		      d->type = LT_PARAM;
  		      for_each_rtx (x, scan_for_locations, data);
  		      d->type = old_type;
! 		      /* Stop traversing.  */
  		      return -1;
  		    }
  		}
--- 771,777 ----
  		      d->type = LT_PARAM;
  		      for_each_rtx (x, scan_for_locations, data);
  		      d->type = old_type;
! 		      /* Do not traverse sub-expressions.  */
  		      return -1;
  		    }
  		}
*************** compute_bb_dataflow (bb)
*** 523,538 ****
    int i, n;
    bool changed;
  
!   attrs_list old_out[IN_OUT_SIZE];
    attrs_list *in = VTI (bb)->in;
    attrs_list *out = VTI (bb)->out;
  
    init_attrs_list_set (old_out);
!   for (i = 0; i < IN_OUT_SIZE; i++)
      {
        attrs_list_copy (&old_out[i], out[i]);
        attrs_list_copy (&out[i], in[i]);
      }
  
    n = VTI (bb)->n_locs;
    for (i = 0; i < n; i++)
--- 797,817 ----
    int i, n;
    bool changed;
  
!   attrs_list old_out[FIRST_PSEUDO_REGISTER];
!   htab_t old_mem_out;
    attrs_list *in = VTI (bb)->in;
    attrs_list *out = VTI (bb)->out;
  
    init_attrs_list_set (old_out);
!   old_mem_out = htab_create (htab_elements (VTI (bb)->mem_out) + 3,
! 			     mem_htab_hash, mem_htab_eq, attrs_htab_cleanup);
!   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
        attrs_list_copy (&old_out[i], out[i]);
        attrs_list_copy (&out[i], in[i]);
      }
+   attrs_htab_copy (old_mem_out, VTI (bb)->mem_out);
+   attrs_htab_copy (VTI (bb)->mem_out, VTI (bb)->mem_in);
  
    n = VTI (bb)->n_locs;
    for (i = 0; i < n; i++)
*************** compute_bb_dataflow (bb)
*** 545,561 ****
  	  if (VTI (bb)->locs[i].type == LT_PARAM
  	      || VTI (bb)->locs[i].type == LT_SET_DEST)
  	    {
! 	      if (REG_EXPR (loc))
  		{
- 		  tree decl = REG_EXPR (loc);
  		  attrs_list_insert (&out[REGNO (loc)], REG_EXPR (loc),
  				     REG_OFFSET (loc), loc);
  #if DEBUG_REG_LOC
  		  if (rtl_dump_file)
  		    {
  		      print_mem_expr (rtl_dump_file, REG_EXPR (loc));
  		      print_rtl_single (rtl_dump_file, loc);
- 		      fprintf (rtl_dump_file, "\n");
  		    }
  #endif
  		}
--- 824,841 ----
  	  if (VTI (bb)->locs[i].type == LT_PARAM
  	      || VTI (bb)->locs[i].type == LT_SET_DEST)
  	    {
! 	      if (REG_EXPR (loc) && VARIABLE_P (REG_EXPR (loc)))
  		{
  		  attrs_list_insert (&out[REGNO (loc)], REG_EXPR (loc),
  				     REG_OFFSET (loc), loc);
  #if DEBUG_REG_LOC
  		  if (rtl_dump_file)
  		    {
+ 		      HOST_WIDE_INT offset = REG_OFFSET (loc);
+ 
  		      print_mem_expr (rtl_dump_file, REG_EXPR (loc));
+ 		      fprintf (rtl_dump_file, " O%ld ", offset);
  		      print_rtl_single (rtl_dump_file, loc);
  		    }
  #endif
  		}
*************** compute_bb_dataflow (bb)
*** 573,591 ****
  	  if (rtl_dump_file)
  	    {
  	      print_mem_expr (rtl_dump_file, decl);
  	      print_rtl_single (rtl_dump_file, loc);
- 	      fprintf (rtl_dump_file, "\n");
  	    }
  #endif
! 	  attrs_list_delete_alias (&out[MEMORY_VAR], MEM_ALIAS_SET (loc),
! 				   offset);
  	  if (VTI (bb)->locs[i].type == LT_PARAM
  	      || VTI (bb)->locs[i].type == LT_SET_DEST)
  	    {
  	      /* The variable is no longer in any register.  */
  	      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
  		attrs_list_delete (&out[j], decl, offset);
! 	      attrs_list_insert (&out[MEMORY_VAR], decl, offset, loc);
  	    }
  	}
      }
--- 853,870 ----
  	  if (rtl_dump_file)
  	    {
  	      print_mem_expr (rtl_dump_file, decl);
+ 	      fprintf (rtl_dump_file, " A%ld O%ld ", MEM_ALIAS_SET (loc), offset);
  	      print_rtl_single (rtl_dump_file, loc);
  	    }
  #endif
! 	  attrs_htab_delete (VTI (bb)->mem_out, loc);
  	  if (VTI (bb)->locs[i].type == LT_PARAM
  	      || VTI (bb)->locs[i].type == LT_SET_DEST)
  	    {
  	      /* The variable is no longer in any register.  */
  	      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
  		attrs_list_delete (&out[j], decl, offset);
! 	      attrs_htab_insert (VTI (bb)->mem_out, loc);
  	    }
  	}
      }
*************** compute_bb_dataflow (bb)
*** 598,606 ****
  	break;
        }
    if (!changed)
!     changed = attrs_list_different_alias (old_out[MEMORY_VAR],
! 					  out[MEMORY_VAR]);
    attrs_list_clear (old_out);
    return changed;
  }
  
--- 877,887 ----
  	break;
        }
    if (!changed)
!     changed = attrs_htab_different (old_mem_out, VTI (bb)->mem_out);
! 
    attrs_list_clear (old_out);
+   attrs_htab_clear (old_mem_out);
+   htab_delete (old_mem_out);
    return changed;
  }
  
*************** hybrid_search (bb, visited, pending)
*** 623,673 ****
    if (TEST_BIT (pending, bb->index))
      {
        /* Clear the IN list set.  */
!       for (i = 0; i < IN_OUT_SIZE; i++)
  	attrs_list_clear (&VTI (bb)->in[i]);
  
        /* Calculate the union of predecessor outs.  */
        for (e = bb->pred; e; e = e->pred_next)
  	{
  	  attrs_list *bb_in = VTI (bb)->in;
  	  attrs_list *pred_out = VTI (e->src)->out;
- 	  attrs_list l;
  
  	  if (e->src == ENTRY_BLOCK_PTR)
  	    continue;
  
  	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	    {
! 	      for (l = pred_out[i]; l; l = l->next)
! 		{
! 		  if (!attrs_list_member (bb_in[i], l->decl, l->offset))
! 		    attrs_list_insert (&bb_in[i], l->decl, l->offset, l->loc);
! 		}
! 	    }
! 	  for (l = pred_out[MEMORY_VAR]; l; l = l->next)
! 	    {
! 	      if (!attrs_list_member_alias (bb_in[MEMORY_VAR],
! 					    MEM_ALIAS_SET (l->loc), l->offset))
! 		attrs_list_insert (&bb_in[MEMORY_VAR], l->decl, l->offset,
! 				   l->loc);
! 	    }
  	}
  
-       if (0 && rtl_dump_file)
- 	fprintf (rtl_dump_file, "Clearing pending %d\n", bb->index);
- 
        RESET_BIT (pending, bb->index);
        changed = compute_bb_dataflow (bb);
        if (changed)
  	{
- 	  if (0 && rtl_dump_file)
- 	    fprintf (rtl_dump_file, "BB %d changed\n", bb->index);
  	  for (e = bb->succ; e != 0; e = e->succ_next)
  	    {
  	      if (e->dest == EXIT_BLOCK_PTR || e->dest->index == bb->index)
  		continue;
- 	      if (0 && rtl_dump_file)
- 		fprintf (rtl_dump_file, "Setting  pending %d\n", e->dest->index);
  	      SET_BIT (pending, e->dest->index);
  	    }
  	}
--- 904,935 ----
    if (TEST_BIT (pending, bb->index))
      {
        /* Clear the IN list set.  */
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  	attrs_list_clear (&VTI (bb)->in[i]);
+       attrs_htab_clear (VTI (bb)->mem_in);
  
        /* Calculate the union of predecessor outs.  */
        for (e = bb->pred; e; e = e->pred_next)
  	{
  	  attrs_list *bb_in = VTI (bb)->in;
  	  attrs_list *pred_out = VTI (e->src)->out;
  
  	  if (e->src == ENTRY_BLOCK_PTR)
  	    continue;
  
  	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	    attrs_list_union (&bb_in[i], pred_out[i]);
! 	  attrs_htab_union (VTI (bb)->mem_in, VTI (e->src)->mem_out);
  	}
  
        RESET_BIT (pending, bb->index);
        changed = compute_bb_dataflow (bb);
        if (changed)
  	{
  	  for (e = bb->succ; e != 0; e = e->succ_next)
  	    {
  	      if (e->dest == EXIT_BLOCK_PTR || e->dest->index == bb->index)
  		continue;
  	      SET_BIT (pending, e->dest->index);
  	    }
  	}
*************** hybrid_search (bb, visited, pending)
*** 684,690 ****
  /* This function will perform iterative dataflow, producing the in and out
     sets.  It is the same as iterative_dataflow_bitmap in df.c but modified
     for different data structures.
!    BB_ORDER is the order to iterate in (Should map block numbers-> order).
     Because this is a forward dataflow problem we pass in a mapping of block
     number to rc_order (like df->inverse_rc_map).  */
  
--- 946,952 ----
  /* This function will perform iterative dataflow, producing the in and out
     sets.  It is the same as iterative_dataflow_bitmap in df.c but modified
     for different data structures.
!    BB_ORDER is the order to iterate in (Should map block numbers -> order).
     Because this is a forward dataflow problem we pass in a mapping of block
     number to rc_order (like df->inverse_rc_map).  */
  
*************** iterative_dataflow (bb_order)
*** 709,716 ****
      }
    while (sbitmap_first_set_bit (pending) != -1)
      {
-       if (0 && rtl_dump_file)
- 	fprintf (rtl_dump_file, "Iterative dataflow\n");
        while (!fibheap_empty (worklist))
  	{
  	  bb = fibheap_extract_min (worklist);
--- 971,976 ----
*************** iterative_dataflow (bb_order)
*** 735,746 ****
    fibheap_delete (worklist);
  }
  
  /* Print the IN and OUT sets for each basic block to dump file.  */
  
  static void
  dump_attrs_list_sets ()
  {
!   int j;
    basic_block bb;
  
    FOR_EACH_BB (bb)
--- 995,1032 ----
    fibheap_delete (worklist);
  }
  
+ /* Print the content of the LIST to dump file.  */
+ 
+ static inline void
+ dump_attrs_list (list)
+      attrs_list list;
+ {
+   for (; list; list = list->next)
+     {
+       print_mem_expr (rtl_dump_file, list->decl);
+       fprintf (rtl_dump_file, "{%p}[", (void*) list->decl);
+       fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset);
+       fprintf (rtl_dump_file, "], ");
+     }
+ }
+ 
+ /* Print the content of the list in SLOT to dump file.  */
+ 
+ static int
+ dump_mem_attrs_list (slot, data)
+      void **slot;
+      void *data ATTRIBUTE_UNUSED;
+ {
+   dump_attrs_list (*(attrs_list *) slot);
+   return 1;
+ }
+ 
  /* Print the IN and OUT sets for each basic block to dump file.  */
  
  static void
  dump_attrs_list_sets ()
  {
!   int i;
    basic_block bb;
  
    FOR_EACH_BB (bb)
*************** dump_attrs_list_sets ()
*** 748,824 ****
        fprintf (rtl_dump_file, "\nBasic block %d:\n", bb->index);
  
        fprintf (rtl_dump_file, "  IN: ");
!       for (j = 0; j < IN_OUT_SIZE; j++)
  	{
! 	  attrs_list l = VTI (bb)->in[j];
! 
! 	  if (l)
  	    {
! 	      if (j < FIRST_PSEUDO_REGISTER)
! 		fprintf (rtl_dump_file, "Reg %d:", j);
! 	      else
! 		fprintf (rtl_dump_file, "Mem:");
! 	      for (; l; l = l->next)
! 		{
! 		  print_mem_expr (rtl_dump_file, l->decl);
! 		  fprintf (rtl_dump_file, "[%d], ", l->offset);
! 		}
  	      fprintf (rtl_dump_file, "; ");
  	    }
  	}
        fprintf (rtl_dump_file, "\n");
  
        fprintf (rtl_dump_file, "  OUT: ");
!       for (j = 0; j < IN_OUT_SIZE; j++)
  	{
! 	  attrs_list l = VTI (bb)->out[j];
! 
! 	  if (l)
  	    {
! 	      if (j < FIRST_PSEUDO_REGISTER)
! 		fprintf (rtl_dump_file, "Reg %d:", j);
! 	      else
! 		fprintf (rtl_dump_file, "Mem:");
! 	      for (; l; l = l->next)
! 		{
! 		  print_mem_expr (rtl_dump_file, l->decl);
! 		  fprintf (rtl_dump_file, "[%d], ", l->offset);
! 		}
  	      fprintf (rtl_dump_file, "; ");
  	    }
  	}
        fprintf (rtl_dump_file, "\n");
      }
  }
  
- /* Computes the hash value for DECL.  */
- #define HASH_VAL(decl) ((size_t) decl)
- 
- /* The hash function for variable_htab, computes the hash value
-    of the variable X declaration.  */
- 
- static hashval_t
- variable_htab_hash (x)
-      const void *x;
- {
-   const variable v = x;
- 
-   return (HASH_VAL (v->decl));
- }
- 
- /* Compare the declaration of variable X with declaration Y.  */
- 
- static int
- variable_htab_eq (x, y)
-      const void *x;
-      const void *y;
- {
-   const variable v = x;
-   const tree decl = y;
- 
-   return (v->decl == decl);
- }
- 
  /* Emit the NOTE_INSN_VAR_LOCATION for variable VAR. WHERE specifies
     whether the note shall be emited before of after instruction INSN.  */
  
--- 1034,1074 ----
        fprintf (rtl_dump_file, "\nBasic block %d:\n", bb->index);
  
        fprintf (rtl_dump_file, "  IN: ");
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  	{
! 	  if (VTI (bb)->in[i])
  	    {
! 	      fprintf (rtl_dump_file, "Reg %d:", i);
! 	      dump_attrs_list (VTI (bb)->in[i]);
  	      fprintf (rtl_dump_file, "; ");
  	    }
  	}
+       if (htab_elements (VTI (bb)->mem_in) > 0)
+ 	{
+ 	  fprintf (rtl_dump_file, "Mem:");
+ 	  htab_traverse (VTI (bb)->mem_in, dump_mem_attrs_list, NULL);
+ 	}
        fprintf (rtl_dump_file, "\n");
  
        fprintf (rtl_dump_file, "  OUT: ");
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  	{
! 	  if (VTI (bb)->out[i])
  	    {
! 	      fprintf (rtl_dump_file, "Reg %d:", i);
! 	      dump_attrs_list (VTI (bb)->out[i]);
  	      fprintf (rtl_dump_file, "; ");
  	    }
  	}
+       if (htab_elements (VTI (bb)->mem_out) > 0)
+ 	{
+ 	  fprintf (rtl_dump_file, "Mem:");
+ 	  htab_traverse (VTI (bb)->mem_out, dump_mem_attrs_list, NULL);
+ 	}
        fprintf (rtl_dump_file, "\n");
      }
  }
  
  /* Emit the NOTE_INSN_VAR_LOCATION for variable VAR. WHERE specifies
     whether the note shall be emited before of after instruction INSN.  */
  
*************** note_insn_var_location_emit (insn, where
*** 830,837 ****
--- 1080,1090 ----
  {
    rtx note;
  
+ #ifdef ENABLE_CHECKING
    if (!var->decl)
      abort ();
+ #endif
+ 
    if (where == EMIT_NOTE_AFTER_INSN)
      note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
    else
*************** note_insn_var_location_emit (insn, where
*** 849,855 ****
    else if (var->n_location_parts)
      {
        int i;
!       rtx argp[MAX_LOC];
        rtx parallel;
        rtx var_location;
  
--- 1102,1108 ----
    else if (var->n_location_parts)
      {
        int i;
!       rtx argp[MAX_LOC_PARTS];
        rtx parallel;
        rtx var_location;
  
*************** set_location_part (decl, offset, loc, in
*** 880,886 ****
       enum where_emit_note where;
  {
    int k;
!   variable var = htab_find_with_hash (variable_htab, decl, HASH_VAL (decl));
    if (!var)
      {
        void **slot;
--- 1133,1140 ----
       enum where_emit_note where;
  {
    int k;
!   variable var = htab_find_with_hash (variable_htab, decl,
! 				      VARIABLE_HASH_VAL (decl));
    if (!var)
      {
        void **slot;
*************** set_location_part (decl, offset, loc, in
*** 889,898 ****
        var->decl = decl;
        var->n_location_parts = 0;
  
!       slot = htab_find_slot_with_hash (variable_htab, decl, HASH_VAL (decl),
! 				       INSERT);
        if (*slot)
  	abort ();
        *slot = (void *) var;
        k = 0;
      }
--- 1143,1154 ----
        var->decl = decl;
        var->n_location_parts = 0;
  
!       slot = htab_find_slot_with_hash (variable_htab, decl,
! 				       VARIABLE_HASH_VAL (decl), INSERT);
! #ifdef ENABLE_CHECKING
        if (*slot)
  	abort ();
+ #endif
        *slot = (void *) var;
        k = 0;
      }
*************** set_location_part (decl, offset, loc, in
*** 906,917 ****
    if (k == var->n_location_parts)
      {
        /* Did not find the part, create new one.  */
!       if (var->n_location_parts >= MAX_LOC)
  	return;
        var->n_location_parts++;
        var->location_part[k].offset = offset;
        var->location_part[k].loc = NULL;
      }
    var->location_part[k].delete_p = false;
    if (var->location_part[k].loc != loc)
      {
--- 1162,1175 ----
    if (k == var->n_location_parts)
      {
        /* Did not find the part, create new one.  */
!       if (var->n_location_parts >= MAX_LOC_PARTS)
  	return;
        var->n_location_parts++;
        var->location_part[k].offset = offset;
        var->location_part[k].loc = NULL;
      }
+ 
+   /* Mark the location part that it should not be deleted.  */
    var->location_part[k].delete_p = false;
    if (var->location_part[k].loc != loc)
      {
*************** delete_location_part (decl, offset, insn
*** 938,948 ****
       enum where_emit_note where;
  {
    int i;
!   void **slot = htab_find_slot_with_hash (variable_htab, decl, HASH_VAL (decl),
! 					  NO_INSERT);
    if (slot && *slot)
      {
!       variable var = *slot;
        /* Delete the location part.  */
        for (i = 0; i < var->n_location_parts; i++)
  	if (var->location_part[i].offset == offset)
--- 1196,1207 ----
       enum where_emit_note where;
  {
    int i;
!   void **slot = htab_find_slot_with_hash (variable_htab, decl,
! 					  VARIABLE_HASH_VAL (decl), NO_INSERT);
    if (slot && *slot)
      {
!       variable var = (variable) *slot;
! 
        /* Delete the location part.  */
        for (i = 0; i < var->n_location_parts; i++)
  	if (var->location_part[i].offset == offset)
*************** emit_note_if_var_changed (slot, aux)
*** 995,1002 ****
--- 1254,1263 ----
  {
    variable var = *slot;
    emit_note_data *data = (emit_note_data *) aux;
+ 
    if (var->n_location_parts == 0)
      var->changed = false;
+ 
    if (var->changed)
      {
        var->changed = false;
*************** emit_note_if_var_changed (slot, aux)
*** 1006,1011 ****
--- 1267,1311 ----
      htab_clear_slot (variable_htab, slot);
  }
  
+ /* Delete the location part of variable corresponding to LOC from all
+    register locations (in LISTS) and memory locations (in HTAB) and emit
+    notes before/after (parameter WHERE) INSN. The location part which
+    has the same decl and offset as LOC is deleted from HTAB only when
+    DELETE_LOC_FROM_HTAB is true.  */
+ 
+ static inline void
+ process_bb_delete (lists, htab, delete_loc_from_htab, loc, insn, where)
+      attrs_list *lists;
+      htab_t htab;
+      int delete_loc_from_htab;
+      rtx loc;
+      rtx insn;
+      enum where_emit_note where;
+ {
+   attrs_list list;
+   int i;
+ 
+   tree decl = MEM_EXPR (loc);
+   HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
+ 
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     {
+       for (list = lists[i]; list; list = list->next)
+ 	if (list->offset == offset && list->decl == decl)
+ 	  delete_location_part (list->decl, list->offset, insn, where);
+       attrs_list_delete (&lists[i], decl, offset);
+     }
+ 
+   if (delete_loc_from_htab)
+     {
+       list = (attrs_list) htab_find_with_hash (htab, loc, MEM_HASH_VAL (loc));
+       for (; list; list = list->next)
+ 	if (list->offset == offset && list->decl == decl)
+ 	  delete_location_part (list->decl, list->offset, insn, where);
+       attrs_htab_delete (htab, loc);
+     }
+ }
+ 
  /* Emit the notes for changes of location parts of a variable in the basic
     block BB.  */
  
*************** process_bb (bb)
*** 1014,1024 ****
       basic_block bb;
  {
    int i, n;
!   attrs_list attrs[IN_OUT_SIZE];
  
!   init_attrs_list_set (attrs);
!   for (i = 0; i < IN_OUT_SIZE; i++)
!     attrs_list_copy (&attrs[i], VTI (bb)->in[i]);
  
    n = VTI (bb)->n_locs;
    for (i = 0; i < n; i++)
--- 1314,1328 ----
       basic_block bb;
  {
    int i, n;
!   attrs_list reg[FIRST_PSEUDO_REGISTER];
!   htab_t mem;
  
!   init_attrs_list_set (reg);
!   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     attrs_list_copy (&reg[i], VTI (bb)->in[i]);
!   mem = htab_create (htab_elements (VTI (bb)->mem_in) + 3, mem_htab_hash,
! 			   mem_htab_eq, attrs_htab_cleanup);
!   attrs_htab_copy (mem, VTI (bb)->mem_in);
  
    n = VTI (bb)->n_locs;
    for (i = 0; i < n; i++)
*************** process_bb (bb)
*** 1038,1059 ****
  	      case LT_PARAM:
  		where = EMIT_NOTE_BEFORE_INSN;
  	      case LT_SET_DEST:
! 		for (l = attrs[REGNO (loc)]; l; l = l->next)
  		  if (l->decl != decl || l->offset != offset)
  		    delete_location_part (l->decl, l->offset, insn, where);
! 		attrs_list_clear (&attrs[REGNO (loc)]);
! 		if (decl)
  		  {
  		    set_location_part (decl, offset, loc, insn, where);
! 		    attrs_list_insert (&attrs[REGNO (loc)], decl, offset, loc);
  		  }
  		break;
  
  	      case LT_CLOBBERED:
! 		for (l = attrs[REGNO (loc)]; l; l = l->next)
  		  delete_location_part (l->decl, l->offset, insn,
  					EMIT_NOTE_AFTER_INSN);
! 		attrs_list_clear (&attrs[REGNO (loc)]);
  		break;
  	    }
  	}
--- 1342,1365 ----
  	      case LT_PARAM:
  		where = EMIT_NOTE_BEFORE_INSN;
  	      case LT_SET_DEST:
! 		for (l = reg[REGNO (loc)]; l; l = l->next)
  		  if (l->decl != decl || l->offset != offset)
  		    delete_location_part (l->decl, l->offset, insn, where);
! 		attrs_list_clear (&reg[REGNO (loc)]);
! 		if (decl && VARIABLE_P (decl))
  		  {
  		    set_location_part (decl, offset, loc, insn, where);
! 		    attrs_list_insert (&reg[REGNO (loc)], decl, offset, loc);
  		  }
+ 		else
+ 		  delete_location_part (decl, offset, insn, where);
  		break;
  
  	      case LT_CLOBBERED:
! 		for (l = reg[REGNO (loc)]; l; l = l->next)
  		  delete_location_part (l->decl, l->offset, insn,
  					EMIT_NOTE_AFTER_INSN);
! 		attrs_list_clear (&reg[REGNO (loc)]);
  		break;
  	    }
  	}
*************** process_bb (bb)
*** 1061,1096 ****
  	       && MEM_EXPR (loc)
  	       && VARIABLE_P (MEM_EXPR (loc)))
  	{
! 	  attrs_list l;
  	  tree decl = MEM_EXPR (loc);
- 	  HOST_WIDE_INT alias = MEM_ALIAS_SET (loc);
  	  HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
- 	  enum where_emit_note where = EMIT_NOTE_AFTER_INSN;
  
  	  switch (VTI (bb)->locs[i].type)
  	    {
  	      case LT_PARAM:
  		where = EMIT_NOTE_BEFORE_INSN;
  	      case LT_SET_DEST:
! 		for (l = attrs[MEMORY_VAR]; l; l = l->next)
! 		  if (MEM_ALIAS_SET (l->loc) == alias && l->offset == offset
! 		      && l->decl != decl)
! 		    delete_location_part (l->decl, l->offset, insn, where);
! 		attrs_list_delete_alias (&attrs[MEMORY_VAR], alias, offset);
  		set_location_part (decl, offset, loc, insn, where);
! 		attrs_list_insert (&attrs[MEMORY_VAR], decl, offset, loc);
  		break;
  
  	      case LT_CLOBBERED:
! 		for (l = attrs[MEMORY_VAR]; l; l = l->next)
! 		  if (MEM_ALIAS_SET (l->loc) == alias && l->offset == offset)
! 		    delete_location_part (l->decl, l->offset, insn,
! 					  EMIT_NOTE_AFTER_INSN);
! 		attrs_list_delete_alias (&attrs[MEMORY_VAR], alias, offset);
  		break;
  	    }
  	}
      }
  }
  
  /* Emit notes for the whole function.  */
--- 1367,1441 ----
  	       && MEM_EXPR (loc)
  	       && VARIABLE_P (MEM_EXPR (loc)))
  	{
! 	  enum where_emit_note where = EMIT_NOTE_AFTER_INSN;
  	  tree decl = MEM_EXPR (loc);
  	  HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
  
  	  switch (VTI (bb)->locs[i].type)
  	    {
  	      case LT_PARAM:
  		where = EMIT_NOTE_BEFORE_INSN;
  	      case LT_SET_DEST:
! 		process_bb_delete (reg, mem, false, loc, insn, where);
  		set_location_part (decl, offset, loc, insn, where);
! 		attrs_htab_insert (mem, loc);
  		break;
  
  	      case LT_CLOBBERED:
! 		process_bb_delete (reg, mem, true, loc, insn,
! 				   EMIT_NOTE_AFTER_INSN);
  		break;
  	    }
  	}
      }
+   htab_delete (mem);
+ }
+ 
+ /* Mark the location parts for the variables from the list *SLOT
+    to be deleted.  */
+ 
+ static int
+ mark_variables_for_deletion (slot, data)
+      void **slot;
+      void *data ATTRIBUTE_UNUSED;
+ {
+   attrs_list l;
+ 
+   for (l = *(attrs_list *) slot; l; l = l->next)
+     {
+       variable var = htab_find_with_hash (variable_htab, l->decl,
+ 					  VARIABLE_HASH_VAL (l->decl));
+       if (var)
+ 	{
+ 	  int k;
+ 	  for (k = 0; k < var->n_location_parts; k++)
+ 	    if (var->location_part[k].offset == l->offset)
+ 	      {
+ 		var->location_part[k].delete_p = true;
+ 		break;
+ 	      }
+ 	}
+     }
+   return 1;
+ }
+ 
+ /* Add the location parts for variables from the list *SLOT and emit notes
+    before insn DATA.  */
+ 
+ static int
+ add_and_unmark_variables (slot, data)
+      void **slot;
+      void *data;
+ {
+   attrs_list l;
+   rtx insn = (rtx) data;
+ 
+   for (l = *(attrs_list *) slot; l; l = l->next)
+     {
+       set_location_part (l->decl, l->offset, l->loc, insn,
+ 			 EMIT_NOTE_BEFORE_INSN);
+     }
+   return 1;
  }
  
  /* Emit notes for the whole function.  */
*************** process_bb (bb)
*** 1098,1144 ****
  static void
  var_tracking_emit_notes ()
  {
-   int j;
-   attrs_list *last_out, *in;
-   attrs_list empty[IN_OUT_SIZE];
    basic_block bb;
  
    init_attrs_list_set (empty);
    last_out = empty;
  
    FOR_EACH_BB (bb)
      {
-       attrs_list l;
        emit_note_data emit_note_data;
  
        /* Emit the notes for changes of variable locations between two
  	 sequential basic blocks.  */
        /* Mark the variables of previous OUT set.  */
!       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 	for (l = last_out[j]; l; l = l->next)
! 	  {
! 	    variable var = htab_find_with_hash (variable_htab, l->decl,
! 						HASH_VAL (l->decl));
! 	    if (var)
! 	      {
! 		int k;
! 		for (k = 0; k < var->n_location_parts; k++)
! 		  if (var->location_part[k].offset == last_out[j]->offset)
! 		    {
! 		      var->location_part[k].delete_p = true;
! 		      break;
! 		    }
! 	      }
! 	  }
        /* Add the variables of IN set and unmark them.  */
        in = VTI (bb)->in;
!       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
! 	for (l = in[j]; l; l = l->next)
! 	  {
! 	    set_location_part (l->decl, l->offset, l->loc, bb->head,
! 			       EMIT_NOTE_BEFORE_INSN);
! 	  }
!       /* Emit the notes and delete the marked location parts.  */
        emit_note_data.insn = bb->head;
        emit_note_data.where = EMIT_NOTE_BEFORE_INSN;
        htab_traverse (variable_htab, process_location_parts, &emit_note_data);
--- 1443,1476 ----
  static void
  var_tracking_emit_notes ()
  {
    basic_block bb;
+   int i;
+   attrs_list *last_out, *in;
+   attrs_list empty[FIRST_PSEUDO_REGISTER];
+   htab_t last_htab;
  
    init_attrs_list_set (empty);
    last_out = empty;
+   last_htab = htab_create (7, mem_htab_hash, mem_htab_eq, attrs_htab_cleanup);
  
    FOR_EACH_BB (bb)
      {
        emit_note_data emit_note_data;
  
        /* Emit the notes for changes of variable locations between two
  	 sequential basic blocks.  */
        /* Mark the variables of previous OUT set.  */
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	mark_variables_for_deletion ((void **) &last_out[i], NULL);
!       htab_traverse (last_htab, mark_variables_for_deletion, NULL);
! 
        /* Add the variables of IN set and unmark them.  */
        in = VTI (bb)->in;
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! 	add_and_unmark_variables ((void **) &in[i], bb->head);
!       htab_traverse (last_htab, add_and_unmark_variables, bb->head);
! 
!       /* Delete the marked location parts and emit the notes.  */
        emit_note_data.insn = bb->head;
        emit_note_data.where = EMIT_NOTE_BEFORE_INSN;
        htab_traverse (variable_htab, process_location_parts, &emit_note_data);
*************** var_tracking_emit_notes ()
*** 1147,1153 ****
--- 1479,1487 ----
        process_bb (bb);
  
        last_out = VTI (bb)->out;
+       attrs_htab_copy (last_htab, VTI (bb)->mem_out);
      }
+   htab_delete (last_htab);
  }
  
  /* Allocate and initialize the data structures for variable tracking
*************** var_tracking_initialize ()
*** 1194,1201 ****
  	      data.insn = insn;
  	      n1 = VTI (bb)->n_locs;
  	      for_each_rtx (&PATTERN (insn), scan_for_locations, &data);
- 
  	      n2 = VTI (bb)->n_locs - 1;
  	      /* Order the locations so that the locations of type LT_PARAM are
  		 before others.  */
  	      while (n1 < n2)
--- 1528,1535 ----
  	      data.insn = insn;
  	      n1 = VTI (bb)->n_locs;
  	      for_each_rtx (&PATTERN (insn), scan_for_locations, &data);
  	      n2 = VTI (bb)->n_locs - 1;
+ 
  	      /* Order the locations so that the locations of type LT_PARAM are
  		 before others.  */
  	      while (n1 < n2)
*************** var_tracking_initialize ()
*** 1212,1217 ****
--- 1546,1552 ----
  		      VTI (bb)->locs[n2] = sw;
  		    }
  		}
+ 
  	      /* Now the LT_PARAMs are first, order the rest so that the
  		 LT_SET_DESTs are before LT_CLOBBEREDs.  */
  	      n2 = VTI (bb)->n_locs - 1;
*************** var_tracking_initialize ()
*** 1235,1240 ****
--- 1570,1579 ----
        /* Init the IN and OUT arrays.  */
        init_attrs_list_set (VTI (bb)->in);
        init_attrs_list_set (VTI (bb)->out);
+       VTI (bb)->mem_in = htab_create (7, mem_htab_hash, mem_htab_eq,
+ 				      attrs_htab_cleanup);
+       VTI (bb)->mem_out = htab_create (7, mem_htab_hash, mem_htab_eq,
+ 				       attrs_htab_cleanup);
      }
  
    variable_htab = htab_create (37, variable_htab_hash, variable_htab_eq, free);
*************** var_tracking_finalize ()
*** 1252,1262 ****
      {
        free (VTI (bb)->locs);
  
!       for (i = 0; i < IN_OUT_SIZE; i++)
  	{
  	  attrs_list_clear (&VTI (bb)->in[i]);
  	  attrs_list_clear (&VTI (bb)->out[i]);
  	}
      }
    free_aux_for_blocks ();
  }
--- 1591,1603 ----
      {
        free (VTI (bb)->locs);
  
!       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
  	{
  	  attrs_list_clear (&VTI (bb)->in[i]);
  	  attrs_list_clear (&VTI (bb)->out[i]);
  	}
+       htab_delete (VTI (bb)->mem_in);
+       htab_delete (VTI (bb)->mem_out);
      }
    free_aux_for_blocks ();
  }


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