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]

PATCH for CSE speedup



This patch reduces the CSE time for one 100K-register function on my
PPro from 518 seconds to 16 seconds (a 32X speedup).

The culprit was the large reg_tick, reg_in_table, and reg_qty arrays
which were reinitialized at the start of each basic block, making the
algorithm dependent on the total number of registers in the function,
rather than the number in any particular basic block.  I replaced the
arrays with splay-trees, retaining quick lookup but reducing
initialization cost.  As a bonus, we also reduce memory usage, which
in this case, was roughly half a megabyte of alloca'd storage.

May I check this in?

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

Sun Mar 28 22:31:58 1999  Mark Mitchell  <mark@codesourcery.com>

	* alias.c (alias_set_compare): Remove.
	(record_alias_subset): Use splay_tree_compare_ints instaed of
	alias_set_compare.
	(init_alias_once): Likewise.
	* cse.c: Include splay-tree.h.
	(reg_qty): Remove.
	(reg_tick): Likewise.
	(reg_table): Likewise.
	(cse_reg_info): New structure.
	(cse_reg_info_free_list): New variable.
	(cse_reg_info_tree): Likewise.
	(cached_regno): Likewise.
	(cached_cse_reg_info): Likewise.
	(all_minus_one): Remove.
	(consec_ints): Likewise.
	(GET_CSE_REG_INFO): New macro.
	(REG_TICK): Likewise.  Use throughout instead of reg_tick.
	(REG_IN_TABLE): Likewise.  Use throughout instead of reg_in_table.
	(REG_QTY): Likewise.  Use throughout instead of reg_qty.
	(get_cse_reg_info): New function.
	(free_cse_reg_info): Likewise.
	(new_basic_block): Reinitialize cse_reg_info_tree instead of
	reg_tick, all_minus_one, and consec_ints.
	* Makefile.in (cse.o): Depend on splay-tree.h

1999-03-28  Mark Mitchell  <mark@codesourcery.com>

	* splay-tree.h (splay_tree_compare_ints): Declare.
	* splay-tree.c (splay_tree_compare_ints): Define.

Index: gcc/Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/Makefile.in,v
retrieving revision 1.249
diff -c -p -r1.249 Makefile.in
*** Makefile.in	1999/03/26 22:55:34	1.249
--- Makefile.in	1999/03/29 06:26:23
*************** stupid.o : stupid.c $(CONFIG_H) system.h
*** 1515,1521 ****
     $(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h
  
  cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
!    real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h
  gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
     real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h
  resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h system.h \
--- 1515,1522 ----
     $(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h
  
  cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
!    real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h \
!    $(srcdir)/../include/splay-tree.h
  gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
     real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h
  resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h system.h \
Index: gcc/alias.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/alias.c,v
retrieving revision 1.51
diff -c -p -r1.51 alias.c
*** alias.c	1999/02/14 23:44:39	1.51
--- alias.c	1999/03/29 06:26:24
*************** static int base_alias_check		PROTO((rtx,
*** 83,90 ****
  					       enum machine_mode));
  static rtx find_base_value		PROTO((rtx));
  static int mems_in_disjoint_alias_sets_p PROTO((rtx, rtx));
- static int alias_set_compare            PROTO((splay_tree_key, 
- 					       splay_tree_key));
  static int insert_subset_children       PROTO((splay_tree_node,
  					       void*));
  static alias_set_entry get_alias_set_entry PROTO((int));
--- 83,88 ----
*************** static int copying_arguments;
*** 169,193 ****
  
  static splay_tree alias_sets;
  
- /* Returns -1, 0, 1 according to whether SET1 is less than, equal to,
-    or greater than SET2.  */
- 
- static int
- alias_set_compare (set1, set2)
-      splay_tree_key set1;
-      splay_tree_key set2;
- {
-   int s1 = (int) set1;
-   int s2 = (int) set2;
- 
-   if (s1 < s2)
-     return -1;
-   else if (s1 > s2)
-     return 1;
-   else 
-     return 0;
- }
- 
  /* Returns a pointer to the alias set entry for ALIAS_SET, if there is
     such an entry, or NULL otherwise.  */
  
--- 167,172 ----
*************** record_alias_subset (superset, subset)
*** 305,311 ****
  	(alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
        superset_entry->alias_set = superset;
        superset_entry->children 
! 	= splay_tree_new (alias_set_compare, 0, 0);
        splay_tree_insert (alias_sets, 
  			 (splay_tree_key) superset,
  			 (splay_tree_value) superset_entry);
--- 284,290 ----
  	(alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
        superset_entry->alias_set = superset;
        superset_entry->children 
! 	= splay_tree_new (splay_tree_compare_ints, 0, 0);
        splay_tree_insert (alias_sets, 
  			 (splay_tree_key) superset,
  			 (splay_tree_value) superset_entry);
*************** init_alias_once ()
*** 1329,1335 ****
  	&& HARD_REGNO_MODE_OK (i, Pmode))
        SET_HARD_REG_BIT (argument_registers, i);
  
!   alias_sets = splay_tree_new (alias_set_compare, 0, 0);
  }
  
  void
--- 1308,1314 ----
  	&& HARD_REGNO_MODE_OK (i, Pmode))
        SET_HARD_REG_BIT (argument_registers, i);
  
!   alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
  }
  
  void
Index: gcc/cse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cse.c,v
retrieving revision 1.69
diff -c -p -r1.69 cse.c
*** cse.c	1999/03/22 13:55:22	1.69
--- cse.c	1999/03/29 06:26:29
*************** Boston, MA 02111-1307, USA.  */
*** 34,39 ****
--- 34,40 ----
  #include "expr.h"
  #include "toplev.h"
  #include "output.h"
+ #include "splay-tree.h"
  
  /* The basic idea of common subexpression elimination is to go
     through the code, keeping a record of expressions that would
*************** static rtx prev_insn;
*** 274,284 ****
  
  static rtx this_insn;
  
- /* Index by register number, gives the quantity number
-    of the register's current contents.  */
- 
- static int *reg_qty;
- 
  /* Index by register number, gives the number of the next (or
     previous) register in the chain of registers sharing the same
     value.
--- 275,280 ----
*************** static int *reg_qty;
*** 290,309 ****
  static int *reg_next_eqv;
  static int *reg_prev_eqv;
  
! /* Index by register number, gives the number of times
!    that register has been altered in the current basic block.  */
  
! static int *reg_tick;
  
! /* Index by register number, gives the reg_tick value at which
!    rtx's containing this register are valid in the hash table.
!    If this does not equal the current reg_tick value, such expressions
!    existing in the hash table are invalid.
!    If this is -1, no expressions containing this register have been
!    entered in the table.  */
  
! static int *reg_in_table;
  
  /* A HARD_REG_SET containing all the hard registers for which there is 
     currently a REG expression in the hash table.  Note the difference
     from the above variables, which indicate if the REG is mentioned in some
--- 286,322 ----
  static int *reg_next_eqv;
  static int *reg_prev_eqv;
  
! struct cse_reg_info {
!   union {
!     /* The number of times the register has been altered in the current
!        basic block.  */
!     int reg_tick;
!     
!     /* The next cse_reg_info structure in the free list.  */
!     struct cse_reg_info* next;
!   } variant;
! 
!   /* The REG_TICK value at which rtx's containing this register are
!      valid in the hash table.  If this does not equal the current
!      reg_tick value, such expressions existing in the hash table are
!      invalid.  */
!   int reg_in_table;
  
!   /* The quantity number of the register's current contents.  */
!   int reg_qty;
! };
  
! /* A free list of cse_reg_info entries.  */
! static struct cse_reg_info *cse_reg_info_free_list;
  
! /* A mapping from registers to cse_reg_info data structures.  */
! static splay_tree cse_reg_info_tree;
  
+ /* The last lookup we did into the cse_reg_info_tree.  This allows us
+    to cache repeated lookups.  */
+ static int cached_regno;
+ static struct cse_reg_info *cached_cse_reg_info;
+ 
  /* A HARD_REG_SET containing all the hard registers for which there is 
     currently a REG expression in the hash table.  Note the difference
     from the above variables, which indicate if the REG is mentioned in some
*************** static HARD_REG_SET hard_regs_in_table;
*** 316,329 ****
  
  static HARD_REG_SET regs_invalidated_by_call;
  
- /* Two vectors of ints:
-    one containing max_reg -1's; the other max_reg + 500 (an approximation
-    for max_qty) elements where element i contains i.
-    These are used to initialize various other vectors fast.  */
- 
- static int *all_minus_one;
- static int *consec_ints;
- 
  /* CUID of insn that starts the basic block currently being cse-processed.  */
  
  static int cse_basic_block_start;
--- 329,334 ----
*************** struct table_elt
*** 447,453 ****
  
  #define HASH(X, M)	\
   (GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER	\
!   ? (((unsigned) REG << 7) + (unsigned) reg_qty[REGNO (X)]) % NBUCKETS	\
    : canon_hash (X, M) % NBUCKETS)
  
  /* Determine whether register number N is considered a fixed register for CSE.
--- 452,458 ----
  
  #define HASH(X, M)	\
   (GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER	\
!   ? (((unsigned) REG << 7) + (unsigned) REG_QTY (REGNO (X))) % NBUCKETS	\
    : canon_hash (X, M) % NBUCKETS)
  
  /* Determine whether register number N is considered a fixed register for CSE.
*************** struct table_elt
*** 492,501 ****
        : 2)								\
     : notreg_cost(X))
  
  /* Determine if the quantity number for register X represents a valid index
     into the `qty_...' variables.  */
  
! #define REGNO_QTY_VALID_P(N) (reg_qty[N] != (N))
  
  #ifdef ADDRESS_COST
  /* The ADDRESS_COST macro does not deal with ADDRESSOF nodes.  But,
--- 497,525 ----
        : 2)								\
     : notreg_cost(X))
  
+ /* Get the info associated with register N.  */
+ 
+ #define GET_CSE_REG_INFO(N) 			\
+   (((N) == cached_regno && cached_cse_reg_info)	\
+    ? cached_cse_reg_info : get_cse_reg_info ((N)))
+ 
+ /* Get the number of times this register has been updated in this
+    basic block.  */
+ 
+ #define REG_TICK(N) ((GET_CSE_REG_INFO (N))->variant.reg_tick)
+ 
+ /* Get the point at which REG was recorded in the table.  */
+ 
+ #define REG_IN_TABLE(N) ((GET_CSE_REG_INFO (N))->reg_in_table)
+ 
+ /* Get the quantity number for REG.  */
+ 
+ #define REG_QTY(N) ((GET_CSE_REG_INFO (N))->reg_qty)
+ 
  /* Determine if the quantity number for register X represents a valid index
     into the `qty_...' variables.  */
  
! #define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (N))
  
  #ifdef ADDRESS_COST
  /* The ADDRESS_COST macro does not deal with ADDRESSOF nodes.  But,
*************** static rtx cse_basic_block	PROTO((rtx, r
*** 665,670 ****
--- 689,696 ----
  static void count_reg_usage	PROTO((rtx, int *, rtx, int));
  extern void dump_class          PROTO((struct table_elt*));
  static void check_fold_consts	PROTO((PTR));
+ static struct cse_reg_info* get_cse_reg_info PROTO((int));
+ static void free_cse_reg_info   PROTO((splay_tree_value));
  
  extern int rtx_equal_function_value_matters;
  
*************** rtx_cost (x, outer_code)
*** 808,813 ****
--- 834,890 ----
    return total;
  }
  
+ static struct cse_reg_info *
+ get_cse_reg_info (regno)
+      int regno;
+ {
+   struct cse_reg_info *cri;
+   splay_tree_node n;
+ 
+   /* See if we already have this entry.  */
+   n = splay_tree_lookup (cse_reg_info_tree, 
+ 			(splay_tree_key) regno);
+   if (n)
+     cri = (struct cse_reg_info *) (n->value);
+   else 
+     {
+       /* Get a new cse_reg_info structure.  */
+       if (cse_reg_info_free_list) 
+ 	{
+ 	  cri = cse_reg_info_free_list;
+ 	  cse_reg_info_free_list = cri->variant.next;
+ 	}
+       else
+ 	cri = (struct cse_reg_info *) xmalloc (sizeof (struct cse_reg_info));
+ 
+       /* Initialize it.  */
+       cri->variant.reg_tick = 0;
+       cri->reg_in_table = -1;
+       cri->reg_qty = regno;
+ 
+       splay_tree_insert (cse_reg_info_tree, 
+ 			 (splay_tree_key) regno, 
+ 			 (splay_tree_value) cri);
+     }
+ 
+   /* Cache this lookup; we tend to be looking up information about the
+      same register several times in a row.  */
+   cached_regno = regno;
+   cached_cse_reg_info = cri;
+ 
+   return cri;
+ }
+ 
+ static void
+ free_cse_reg_info (v)
+      splay_tree_value v;
+ {
+   struct cse_reg_info *cri = (struct cse_reg_info *) v;
+   
+   cri->variant.next = cse_reg_info_free_list;
+   cse_reg_info_free_list = cri;
+ }
+ 
  /* Clear the hash table and initialize each register with its own quantity,
     for a new basic block.  */
  
*************** new_basic_block ()
*** 817,828 ****
    register int i;
  
    next_qty = max_reg;
  
!   bzero ((char *) reg_tick, max_reg * sizeof (int));
  
-   bcopy ((char *) all_minus_one, (char *) reg_in_table,
- 	 max_reg * sizeof (int));
-   bcopy ((char *) consec_ints, (char *) reg_qty, max_reg * sizeof (int));
    CLEAR_HARD_REG_SET (hard_regs_in_table);
  
    /* The per-quantity values used to be initialized here, but it is
--- 894,909 ----
    register int i;
  
    next_qty = max_reg;
+ 
+   if (cse_reg_info_tree) 
+     {
+       splay_tree_delete (cse_reg_info_tree);
+       cached_cse_reg_info = 0;
+     }
  
!   cse_reg_info_tree = splay_tree_new (splay_tree_compare_ints, 0, 
! 				      free_cse_reg_info);
  
    CLEAR_HARD_REG_SET (hard_regs_in_table);
  
    /* The per-quantity values used to be initialized here, but it is
*************** make_new_qty (reg)
*** 859,865 ****
    if (next_qty >= max_qty)
      abort ();
  
!   q = reg_qty[reg] = next_qty++;
    qty_first_reg[q] = reg;
    qty_last_reg[q] = reg;
    qty_const[q] = qty_const_insn[q] = 0;
--- 940,946 ----
    if (next_qty >= max_qty)
      abort ();
  
!   q = REG_QTY (reg) = next_qty++;
    qty_first_reg[q] = reg;
    qty_last_reg[q] = reg;
    qty_const[q] = qty_const_insn[q] = 0;
*************** make_regs_eqv (new, old)
*** 876,888 ****
       register int new, old;
  {
    register int lastr, firstr;
!   register int q = reg_qty[old];
  
    /* Nothing should become eqv until it has a "non-invalid" qty number.  */
    if (! REGNO_QTY_VALID_P (old))
      abort ();
  
!   reg_qty[new] = q;
    firstr = qty_first_reg[q];
    lastr = qty_last_reg[q];
  
--- 957,969 ----
       register int new, old;
  {
    register int lastr, firstr;
!   register int q = REG_QTY (old);
  
    /* Nothing should become eqv until it has a "non-invalid" qty number.  */
    if (! REGNO_QTY_VALID_P (old))
      abort ();
  
!   REG_QTY (new) = q;
    firstr = qty_first_reg[q];
    lastr = qty_last_reg[q];
  
*************** static void
*** 936,942 ****
  delete_reg_equiv (reg)
       register int reg;
  {
!   register int q = reg_qty[reg];
    register int p, n;
  
    /* If invalid, do nothing.  */
--- 1017,1023 ----
  delete_reg_equiv (reg)
       register int reg;
  {
!   register int q = REG_QTY (reg);
    register int p, n;
  
    /* If invalid, do nothing.  */
*************** delete_reg_equiv (reg)
*** 955,961 ****
    else
      qty_first_reg[q] = n;
  
!   reg_qty[reg] = reg;
  }
  
  /* Remove any invalid expressions from the hash table
--- 1036,1042 ----
    else
      qty_first_reg[q] = n;
  
!   REG_QTY (reg) = reg;
  }
  
  /* Remove any invalid expressions from the hash table
*************** mention_regs (x)
*** 993,1002 ****
  
        for (i = regno; i < endregno; i++)
  	{
! 	  if (reg_in_table[i] >= 0 && reg_in_table[i] != reg_tick[i])
  	    remove_invalid_refs (i);
  
! 	  reg_in_table[i] = reg_tick[i];
  	}
  
        return 0;
--- 1074,1083 ----
  
        for (i = regno; i < endregno; i++)
  	{
! 	  if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
  	    remove_invalid_refs (i);
  
! 	  REG_IN_TABLE (i) = REG_TICK (i);
  	}
  
        return 0;
*************** mention_regs (x)
*** 1010,1028 ****
      {
        int i = REGNO (SUBREG_REG (x));
  
!       if (reg_in_table[i] >= 0 && reg_in_table[i] != reg_tick[i])
  	{
  	  /* If reg_tick has been incremented more than once since
  	     reg_in_table was last set, that means that the entire
  	     register has been set before, so discard anything memorized
  	     for the entrire register, including all SUBREG expressions.  */
! 	  if (reg_in_table[i] != reg_tick[i] - 1)
  	    remove_invalid_refs (i);
  	  else
  	    remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
  	}
  
!       reg_in_table[i] = reg_tick[i];
        return 0;
      }
  
--- 1091,1109 ----
      {
        int i = REGNO (SUBREG_REG (x));
  
!       if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
  	{
  	  /* If reg_tick has been incremented more than once since
  	     reg_in_table was last set, that means that the entire
  	     register has been set before, so discard anything memorized
  	     for the entrire register, including all SUBREG expressions.  */
! 	  if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
  	    remove_invalid_refs (i);
  	  else
  	    remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
  	}
  
!       REG_IN_TABLE (i) = REG_TICK (i);
        return 0;
      }
  
*************** insert_regs (x, classp, modified)
*** 1090,1096 ****
  	 wrong mode for that equivalence, don't do anything here.  */
  
        if (REGNO_QTY_VALID_P (regno)
! 	  && qty_mode[reg_qty[regno]] != GET_MODE (x))
  	return 0;
  
        if (modified || ! REGNO_QTY_VALID_P (regno))
--- 1171,1177 ----
  	 wrong mode for that equivalence, don't do anything here.  */
  
        if (REGNO_QTY_VALID_P (regno)
! 	  && qty_mode[REG_QTY (regno)] != GET_MODE (x))
  	return 0;
  
        if (modified || ! REGNO_QTY_VALID_P (regno))
*************** insert_regs (x, classp, modified)
*** 1107,1113 ****
  		}
  
  	  make_new_qty (regno);
! 	  qty_mode[reg_qty[regno]] = GET_MODE (x);
  	  return 1;
  	}
  
--- 1188,1194 ----
  		}
  
  	  make_new_qty (regno);
! 	  qty_mode[REG_QTY (regno)] = GET_MODE (x);
  	  return 1;
  	}
  
*************** insert_regs (x, classp, modified)
*** 1132,1140 ****
  	 for the full register.  Since we don't invalidate the SUBREG
  	 here first, we might have to bump up REG_TICK so that mention_regs
  	 will do the right thing.  */
!       if (reg_in_table[regno] >= 0
! 	  && reg_tick[regno] == reg_in_table[regno] + 1)
! 	reg_tick[regno]++;
        mention_regs (x);
        return 1;
      }
--- 1213,1221 ----
  	 for the full register.  Since we don't invalidate the SUBREG
  	 here first, we might have to bump up REG_TICK so that mention_regs
  	 will do the right thing.  */
!       if (REG_IN_TABLE (regno) >= 0
! 	  && REG_TICK (regno) == REG_IN_TABLE (regno) + 1)
! 	REG_TICK (regno)++;
        mention_regs (x);
        return 1;
      }
*************** insert (x, classp, hash, mode)
*** 1469,1480 ****
    if (elt->is_const && classp && GET_CODE (classp->exp) == REG
        && GET_CODE (x) != REG)
      {
!       qty_const[reg_qty[REGNO (classp->exp)]]
! 	= gen_lowpart_if_possible (qty_mode[reg_qty[REGNO (classp->exp)]], x);
!       qty_const_insn[reg_qty[REGNO (classp->exp)]] = this_insn;
      }
  
!   else if (GET_CODE (x) == REG && classp && ! qty_const[reg_qty[REGNO (x)]]
  	   && ! elt->is_const)
      {
        register struct table_elt *p;
--- 1550,1561 ----
    if (elt->is_const && classp && GET_CODE (classp->exp) == REG
        && GET_CODE (x) != REG)
      {
!       qty_const[REG_QTY (REGNO (classp->exp))]
! 	= gen_lowpart_if_possible (qty_mode[REG_QTY (REGNO (classp->exp))], x);
!       qty_const_insn[REG_QTY (REGNO (classp->exp))] = this_insn;
      }
  
!   else if (GET_CODE (x) == REG && classp && ! qty_const[REG_QTY (REGNO (x))]
  	   && ! elt->is_const)
      {
        register struct table_elt *p;
*************** insert (x, classp, hash, mode)
*** 1483,1499 ****
  	{
  	  if (p->is_const && GET_CODE (p->exp) != REG)
  	    {
! 	      qty_const[reg_qty[REGNO (x)]]
  		= gen_lowpart_if_possible (GET_MODE (x), p->exp);
! 	      qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
  	      break;
  	    }
  	}
      }
  
!   else if (GET_CODE (x) == REG && qty_const[reg_qty[REGNO (x)]]
! 	   && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]])
!     qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
  
    /* If this is a constant with symbolic value,
       and it has a term with an explicit integer value,
--- 1564,1580 ----
  	{
  	  if (p->is_const && GET_CODE (p->exp) != REG)
  	    {
! 	      qty_const[REG_QTY (REGNO (x))]
  		= gen_lowpart_if_possible (GET_MODE (x), p->exp);
! 	      qty_const_insn[REG_QTY (REGNO (x))] = this_insn;
  	      break;
  	    }
  	}
      }
  
!   else if (GET_CODE (x) == REG && qty_const[REG_QTY (REGNO (x))]
! 	   && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))])
!     qty_const_insn[REG_QTY (REGNO (x))] = this_insn;
  
    /* If this is a constant with symbolic value,
       and it has a term with an explicit integer value,
*************** invalidate (x, full_mode)
*** 1628,1634 ****
  	 overlap these registers.  */
  
        delete_reg_equiv (regno);
!       reg_tick[regno]++;
  
        if (regno >= FIRST_PSEUDO_REGISTER)
  	{
--- 1709,1715 ----
  	 overlap these registers.  */
  
        delete_reg_equiv (regno);
!       REG_TICK (regno)++;
  
        if (regno >= FIRST_PSEUDO_REGISTER)
  	{
*************** invalidate (x, full_mode)
*** 1655,1661 ****
  	      in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, i);
  	      CLEAR_HARD_REG_BIT (hard_regs_in_table, i);
  	      delete_reg_equiv (i);
! 	      reg_tick[i]++;
  	    }
  
  	  if (in_table)
--- 1736,1742 ----
  	      in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, i);
  	      CLEAR_HARD_REG_BIT (hard_regs_in_table, i);
  	      delete_reg_equiv (i);
! 	      REG_TICK (i)++;
  	    }
  
  	  if (in_table)
*************** rehash_using_reg (x)
*** 1804,1811 ****
       valid entries in the table, we have no work to do.  */
  
    if (GET_CODE (x) != REG
!       || reg_in_table[REGNO (x)] < 0
!       || reg_in_table[REGNO (x)] != reg_tick[REGNO (x)])
      return;
  
    /* Scan all hash chains looking for valid entries that mention X.
--- 1885,1892 ----
       valid entries in the table, we have no work to do.  */
  
    if (GET_CODE (x) != REG
!       || REG_IN_TABLE (REGNO (x)) < 0
!       || REG_IN_TABLE (REGNO (x)) != REG_TICK (REGNO (x)))
      return;
  
    /* Scan all hash chains looking for valid entries that mention X.
*************** invalidate_for_call ()
*** 1858,1865 ****
      if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
        {
  	delete_reg_equiv (regno);
! 	if (reg_tick[regno] >= 0)
! 	  reg_tick[regno]++;
  
  	in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
        }
--- 1939,1946 ----
      if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
        {
  	delete_reg_equiv (regno);
! 	if (REG_TICK (regno) >= 0)
! 	  REG_TICK (regno)++;
  
  	in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
        }
*************** canon_hash (x, mode)
*** 2031,2037 ****
  	    do_not_record = 1;
  	    return 0;
  	  }
! 	hash += ((unsigned) REG << 7) + (unsigned) reg_qty[regno];
  	return hash;
        }
  
--- 2112,2118 ----
  	    do_not_record = 1;
  	    return 0;
  	  }
! 	hash += ((unsigned) REG << 7) + (unsigned) REG_QTY (regno);
  	return hash;
        }
  
*************** exp_equiv_p (x, y, validate, equal_value
*** 2223,2237 ****
  	 equivalent.  We only have to validate if Y is a register.  */
        if (CONSTANT_P (x) && GET_CODE (y) == REG
  	  && REGNO_QTY_VALID_P (REGNO (y))
! 	  && GET_MODE (y) == qty_mode[reg_qty[REGNO (y)]]
! 	  && rtx_equal_p (x, qty_const[reg_qty[REGNO (y)]])
! 	  && (! validate || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]))
  	return 1;
  
        if (CONSTANT_P (y) && code == REG
  	  && REGNO_QTY_VALID_P (REGNO (x))
! 	  && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
! 	  && rtx_equal_p (y, qty_const[reg_qty[REGNO (x)]]))
  	return 1;
  
        return 0;
--- 2304,2318 ----
  	 equivalent.  We only have to validate if Y is a register.  */
        if (CONSTANT_P (x) && GET_CODE (y) == REG
  	  && REGNO_QTY_VALID_P (REGNO (y))
! 	  && GET_MODE (y) == qty_mode[REG_QTY (REGNO (y))]
! 	  && rtx_equal_p (x, qty_const[REG_QTY (REGNO (y))])
! 	  && (! validate || REG_IN_TABLE (REGNO (y)) == REG_TICK (REGNO (y))))
  	return 1;
  
        if (CONSTANT_P (y) && code == REG
  	  && REGNO_QTY_VALID_P (REGNO (x))
! 	  && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))]
! 	  && rtx_equal_p (y, qty_const[REG_QTY (REGNO (x))]))
  	return 1;
  
        return 0;
*************** exp_equiv_p (x, y, validate, equal_value
*** 2268,2281 ****
  	   equivalent.  If there are and we are not to validate, they
  	   are equivalent.  Otherwise, ensure all regs are up-to-date.  */
  
! 	if (reg_qty[REGNO (x)] != reg_qty[regno])
  	  return 0;
  
  	if (! validate)
  	  return 1;
  
  	for (i = regno; i < endregno; i++)
! 	  if (reg_in_table[i] != reg_tick[i])
  	    return 0;
  
  	return 1;
--- 2349,2362 ----
  	   equivalent.  If there are and we are not to validate, they
  	   are equivalent.  Otherwise, ensure all regs are up-to-date.  */
  
! 	if (REG_QTY (REGNO (x)) != REG_QTY (regno))
  	  return 0;
  
  	if (! validate)
  	  return 1;
  
  	for (i = regno; i < endregno; i++)
! 	  if (REG_IN_TABLE (i) != REG_TICK (i))
  	    return 0;
  
  	return 1;
*************** set_nonvarying_address_components (addr,
*** 2434,2453 ****
    if (GET_CODE (base) == REG
        && qty_const != 0
        && REGNO_QTY_VALID_P (REGNO (base))
!       && qty_mode[reg_qty[REGNO (base)]] == GET_MODE (base)
!       && qty_const[reg_qty[REGNO (base)]] != 0)
!     base = qty_const[reg_qty[REGNO (base)]];
    else if (GET_CODE (base) == PLUS
  	   && GET_CODE (XEXP (base, 1)) == CONST_INT
  	   && GET_CODE (XEXP (base, 0)) == REG
  	   && qty_const != 0
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
! 	   && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
  	       == GET_MODE (XEXP (base, 0)))
! 	   && qty_const[reg_qty[REGNO (XEXP (base, 0))]])
      {
        start = INTVAL (XEXP (base, 1));
!       base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
      }
    /* This can happen as the result of virtual register instantiation,
       if the initial offset is too large to be a valid address.  */
--- 2515,2534 ----
    if (GET_CODE (base) == REG
        && qty_const != 0
        && REGNO_QTY_VALID_P (REGNO (base))
!       && qty_mode[REG_QTY (REGNO (base))] == GET_MODE (base)
!       && qty_const[REG_QTY (REGNO (base))] != 0)
!     base = qty_const[REG_QTY (REGNO (base))];
    else if (GET_CODE (base) == PLUS
  	   && GET_CODE (XEXP (base, 1)) == CONST_INT
  	   && GET_CODE (XEXP (base, 0)) == REG
  	   && qty_const != 0
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
! 	   && (qty_mode[REG_QTY (REGNO (XEXP (base, 0)))]
  	       == GET_MODE (XEXP (base, 0)))
! 	   && qty_const[REG_QTY (REGNO (XEXP (base, 0)))])
      {
        start = INTVAL (XEXP (base, 1));
!       base = qty_const[REG_QTY (REGNO (XEXP (base, 0)))];
      }
    /* This can happen as the result of virtual register instantiation,
       if the initial offset is too large to be a valid address.  */
*************** set_nonvarying_address_components (addr,
*** 2456,2471 ****
  	   && GET_CODE (XEXP (base, 1)) == REG
  	   && qty_const != 0
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
! 	   && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
  	       == GET_MODE (XEXP (base, 0)))
! 	   && qty_const[reg_qty[REGNO (XEXP (base, 0))]]
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 1)))
! 	   && (qty_mode[reg_qty[REGNO (XEXP (base, 1))]]
  	       == GET_MODE (XEXP (base, 1)))
! 	   && qty_const[reg_qty[REGNO (XEXP (base, 1))]])
      {
!       rtx tem = qty_const[reg_qty[REGNO (XEXP (base, 1))]];
!       base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
  
        /* One of the two values must be a constant.  */
        if (GET_CODE (base) != CONST_INT)
--- 2537,2552 ----
  	   && GET_CODE (XEXP (base, 1)) == REG
  	   && qty_const != 0
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
! 	   && (qty_mode[REG_QTY (REGNO (XEXP (base, 0)))]
  	       == GET_MODE (XEXP (base, 0)))
! 	   && qty_const[REG_QTY (REGNO (XEXP (base, 0)))]
  	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 1)))
! 	   && (qty_mode[REG_QTY (REGNO (XEXP (base, 1)))]
  	       == GET_MODE (XEXP (base, 1)))
! 	   && qty_const[REG_QTY (REGNO (XEXP (base, 1)))])
      {
!       rtx tem = qty_const[REG_QTY (REGNO (XEXP (base, 1)))];
!       base = qty_const[REG_QTY (REGNO (XEXP (base, 0)))];
  
        /* One of the two values must be a constant.  */
        if (GET_CODE (base) != CONST_INT)
*************** cse_rtx_varies_p (x)
*** 2567,2574 ****
  
    if (GET_CODE (x) == REG
        && REGNO_QTY_VALID_P (REGNO (x))
!       && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
!       && qty_const[reg_qty[REGNO (x)]] != 0)
      return 0;
  
    if (GET_CODE (x) == PLUS
--- 2648,2655 ----
  
    if (GET_CODE (x) == REG
        && REGNO_QTY_VALID_P (REGNO (x))
!       && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))]
!       && qty_const[REG_QTY (REGNO (x))] != 0)
      return 0;
  
    if (GET_CODE (x) == PLUS
*************** cse_rtx_varies_p (x)
*** 2576,2583 ****
        && GET_CODE (XEXP (x, 0)) == REG
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
        && (GET_MODE (XEXP (x, 0))
! 	  == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
!       && qty_const[reg_qty[REGNO (XEXP (x, 0))]])
      return 0;
  
    /* This can happen as the result of virtual register instantiation, if
--- 2657,2664 ----
        && GET_CODE (XEXP (x, 0)) == REG
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
        && (GET_MODE (XEXP (x, 0))
! 	  == qty_mode[REG_QTY (REGNO (XEXP (x, 0)))])
!       && qty_const[REG_QTY (REGNO (XEXP (x, 0)))])
      return 0;
  
    /* This can happen as the result of virtual register instantiation, if
*************** cse_rtx_varies_p (x)
*** 2590,2601 ****
        && GET_CODE (XEXP (x, 1)) == REG
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
        && (GET_MODE (XEXP (x, 0))
! 	  == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
!       && qty_const[reg_qty[REGNO (XEXP (x, 0))]]
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))
        && (GET_MODE (XEXP (x, 1))
! 	  == qty_mode[reg_qty[REGNO (XEXP (x, 1))]])
!       && qty_const[reg_qty[REGNO (XEXP (x, 1))]])
      return 0;
  
    return rtx_varies_p (x);
--- 2671,2682 ----
        && GET_CODE (XEXP (x, 1)) == REG
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
        && (GET_MODE (XEXP (x, 0))
! 	  == qty_mode[REG_QTY (REGNO (XEXP (x, 0)))])
!       && qty_const[REG_QTY (REGNO (XEXP (x, 0)))]
        && REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))
        && (GET_MODE (XEXP (x, 1))
! 	  == qty_mode[REG_QTY (REGNO (XEXP (x, 1)))])
!       && qty_const[REG_QTY (REGNO (XEXP (x, 1)))])
      return 0;
  
    return rtx_varies_p (x);
*************** canon_reg (x, insn)
*** 2651,2660 ****
  	    || ! REGNO_QTY_VALID_P (REGNO (x)))
  	  return x;
  
! 	first = qty_first_reg[reg_qty[REGNO (x)]];
  	return (first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
  		: REGNO_REG_CLASS (first) == NO_REGS ? x
! 		: gen_rtx_REG (qty_mode[reg_qty[REGNO (x)]], first));
        }
        
      default:
--- 2732,2741 ----
  	    || ! REGNO_QTY_VALID_P (REGNO (x)))
  	  return x;
  
! 	first = qty_first_reg[REG_QTY (REGNO (x))];
  	return (first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
  		: REGNO_REG_CLASS (first) == NO_REGS ? x
! 		: gen_rtx_REG (qty_mode[REG_QTY (REGNO (x))], first));
        }
        
      default:
*************** fold_rtx (x, insn)
*** 5227,5235 ****
  
  	if (GET_CODE (addr) == REG
  	    && REGNO_QTY_VALID_P (REGNO (addr))
! 	    && GET_MODE (addr) == qty_mode[reg_qty[REGNO (addr)]]
! 	    && qty_const[reg_qty[REGNO (addr)]] != 0)
! 	  addr = qty_const[reg_qty[REGNO (addr)]];
  
  	/* If address is constant, split it into a base and integer offset.  */
  	if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
--- 5308,5316 ----
  
  	if (GET_CODE (addr) == REG
  	    && REGNO_QTY_VALID_P (REGNO (addr))
! 	    && GET_MODE (addr) == qty_mode[REG_QTY (REGNO (addr))]
! 	    && qty_const[REG_QTY (REGNO (addr))] != 0)
! 	  addr = qty_const[REG_QTY (REGNO (addr))];
  
  	/* If address is constant, split it into a base and integer offset.  */
  	if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
*************** fold_rtx (x, insn)
*** 5371,5382 ****
  	    /* This is the same as calling equiv_constant; it is duplicated
  	       here for speed.  */
  	    if (REGNO_QTY_VALID_P (REGNO (arg))
! 		&& qty_const[reg_qty[REGNO (arg)]] != 0
! 		&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != REG
! 		&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != PLUS)
  	      const_arg
  		= gen_lowpart_if_possible (GET_MODE (arg),
! 					   qty_const[reg_qty[REGNO (arg)]]);
  	    break;
  
  	  case CONST:
--- 5452,5463 ----
  	    /* This is the same as calling equiv_constant; it is duplicated
  	       here for speed.  */
  	    if (REGNO_QTY_VALID_P (REGNO (arg))
! 		&& qty_const[REG_QTY (REGNO (arg))] != 0
! 		&& GET_CODE (qty_const[REG_QTY (REGNO (arg))]) != REG
! 		&& GET_CODE (qty_const[REG_QTY (REGNO (arg))]) != PLUS)
  	      const_arg
  		= gen_lowpart_if_possible (GET_MODE (arg),
! 					   qty_const[REG_QTY (REGNO (arg))]);
  	    break;
  
  	  case CONST:
*************** fold_rtx (x, insn)
*** 5599,5606 ****
  		  && (folded_arg0 == folded_arg1
  		      || (GET_CODE (folded_arg0) == REG
  			  && GET_CODE (folded_arg1) == REG
! 			  && (reg_qty[REGNO (folded_arg0)]
! 			      == reg_qty[REGNO (folded_arg1)]))
  		      || ((p0 = lookup (folded_arg0,
  					(safe_hash (folded_arg0, mode_arg0)
  					 % NBUCKETS), mode_arg0))
--- 5680,5687 ----
  		  && (folded_arg0 == folded_arg1
  		      || (GET_CODE (folded_arg0) == REG
  			  && GET_CODE (folded_arg1) == REG
! 			  && (REG_QTY (REGNO (folded_arg0))
! 			      == REG_QTY (REGNO (folded_arg1))))
  		      || ((p0 = lookup (folded_arg0,
  					(safe_hash (folded_arg0, mode_arg0)
  					 % NBUCKETS), mode_arg0))
*************** fold_rtx (x, insn)
*** 5617,5623 ****
  		 (we only check the reverse if not floating-point).  */
  	      else if (GET_CODE (folded_arg0) == REG)
  		{
! 		  int qty = reg_qty[REGNO (folded_arg0)];
  
  		  if (REGNO_QTY_VALID_P (REGNO (folded_arg0))
  		      && (comparison_dominates_p (qty_comparison_code[qty], code)
--- 5698,5704 ----
  		 (we only check the reverse if not floating-point).  */
  	      else if (GET_CODE (folded_arg0) == REG)
  		{
! 		  int qty = REG_QTY (REGNO (folded_arg0));
  
  		  if (REGNO_QTY_VALID_P (REGNO (folded_arg0))
  		      && (comparison_dominates_p (qty_comparison_code[qty], code)
*************** fold_rtx (x, insn)
*** 5629,5635 ****
  			      && rtx_equal_p (qty_comparison_const[qty],
  					      const_arg1))
  			  || (GET_CODE (folded_arg1) == REG
! 			      && (reg_qty[REGNO (folded_arg1)]
  				  == qty_comparison_qty[qty]))))
  		    return (comparison_dominates_p (qty_comparison_code[qty],
  						    code)
--- 5710,5716 ----
  			      && rtx_equal_p (qty_comparison_const[qty],
  					      const_arg1))
  			  || (GET_CODE (folded_arg1) == REG
! 			      && (REG_QTY (REGNO (folded_arg1))
  				  == qty_comparison_qty[qty]))))
  		    return (comparison_dominates_p (qty_comparison_code[qty],
  						    code)
*************** equiv_constant (x)
*** 5924,5931 ****
  {
    if (GET_CODE (x) == REG
        && REGNO_QTY_VALID_P (REGNO (x))
!       && qty_const[reg_qty[REGNO (x)]])
!     x = gen_lowpart_if_possible (GET_MODE (x), qty_const[reg_qty[REGNO (x)]]);
  
    if (x == 0 || CONSTANT_P (x))
      return x;
--- 6005,6012 ----
  {
    if (GET_CODE (x) == REG
        && REGNO_QTY_VALID_P (REGNO (x))
!       && qty_const[REG_QTY (REGNO (x))])
!     x = gen_lowpart_if_possible (GET_MODE (x), qty_const[REG_QTY (REGNO (x))]);
  
    if (x == 0 || CONSTANT_P (x))
      return x;
*************** record_jump_cond (code, mode, op0, op1, 
*** 6204,6210 ****
  	  op0_elt->in_struct = op0_in_struct;
  	}
  
!       qty_comparison_code[reg_qty[REGNO (op0)]] = code;
        if (GET_CODE (op1) == REG)
  	{
  	  /* Look it up again--in case op0 and op1 are the same.  */
--- 6285,6291 ----
  	  op0_elt->in_struct = op0_in_struct;
  	}
  
!       qty_comparison_code[REG_QTY (REGNO (op0))] = code;
        if (GET_CODE (op1) == REG)
  	{
  	  /* Look it up again--in case op0 and op1 are the same.  */
*************** record_jump_cond (code, mode, op0, op1, 
*** 6224,6236 ****
  	      op1_elt->in_struct = op1_in_struct;
  	    }
  
! 	  qty_comparison_qty[reg_qty[REGNO (op0)]] = reg_qty[REGNO (op1)];
! 	  qty_comparison_const[reg_qty[REGNO (op0)]] = 0;
  	}
        else
  	{
! 	  qty_comparison_qty[reg_qty[REGNO (op0)]] = -1;
! 	  qty_comparison_const[reg_qty[REGNO (op0)]] = op1;
  	}
  
        return;
--- 6305,6317 ----
  	      op1_elt->in_struct = op1_in_struct;
  	    }
  
! 	  qty_comparison_qty[REG_QTY (REGNO (op0))] = REG_QTY (REGNO (op1));
! 	  qty_comparison_const[REG_QTY (REGNO (op0))] = 0;
  	}
        else
  	{
! 	  qty_comparison_qty[REG_QTY (REGNO (op0))] = -1;
! 	  qty_comparison_const[REG_QTY (REGNO (op0))] = op1;
  	}
  
        return;
*************** cse_insn (insn, libcall_insn)
*** 7155,7162 ****
  	 their lifetimes will likely abut instead of overlapping.  */
        if (GET_CODE (dest) == REG
  	  && REGNO_QTY_VALID_P (REGNO (dest))
! 	  && qty_mode[reg_qty[REGNO (dest)]] == GET_MODE (dest)
! 	  && qty_first_reg[reg_qty[REGNO (dest)]] != REGNO (dest)
  	  && GET_CODE (src) == REG && REGNO (src) == REGNO (dest)
  	  /* Don't do this if the original insn had a hard reg as
  	     SET_SRC.  */
--- 7236,7243 ----
  	 their lifetimes will likely abut instead of overlapping.  */
        if (GET_CODE (dest) == REG
  	  && REGNO_QTY_VALID_P (REGNO (dest))
! 	  && qty_mode[REG_QTY (REGNO (dest))] == GET_MODE (dest)
! 	  && qty_first_reg[REG_QTY (REGNO (dest))] != REGNO (dest)
  	  && GET_CODE (src) == REG && REGNO (src) == REGNO (dest)
  	  /* Don't do this if the original insn had a hard reg as
  	     SET_SRC.  */
*************** cse_insn (insn, libcall_insn)
*** 7165,7171 ****
  	/* We can't call canon_reg here because it won't do anything if
  	   SRC is a hard register.  */
  	{
! 	  int first = qty_first_reg[reg_qty[REGNO (src)]];
  	  rtx new_src
  	    = (first >= FIRST_PSEUDO_REGISTER
  	       ? regno_reg_rtx[first] : gen_rtx_REG (GET_MODE (src), first));
--- 7246,7252 ----
  	/* We can't call canon_reg here because it won't do anything if
  	   SRC is a hard register.  */
  	{
! 	  int first = qty_first_reg[REG_QTY (REGNO (src))];
  	  rtx new_src
  	    = (first >= FIRST_PSEUDO_REGISTER
  	       ? regno_reg_rtx[first] : gen_rtx_REG (GET_MODE (src), first));
*************** cse_insn (insn, libcall_insn)
*** 7239,7249 ****
  	     the last set for this quantity was for this register.  */
  
  	  if (REGNO_QTY_VALID_P (REGNO (dest))
! 	      && qty_const[reg_qty[REGNO (dest)]] == const0_rtx)
  	    {
  	      /* See if we previously had a REG_WAS_0 note.  */
  	      rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
! 	      rtx const_insn = qty_const_insn[reg_qty[REGNO (dest)]];
  
  	      if ((tem = single_set (const_insn)) != 0
  		  && rtx_equal_p (SET_DEST (tem), dest))
--- 7320,7330 ----
  	     the last set for this quantity was for this register.  */
  
  	  if (REGNO_QTY_VALID_P (REGNO (dest))
! 	      && qty_const[REG_QTY (REGNO (dest))] == const0_rtx)
  	    {
  	      /* See if we previously had a REG_WAS_0 note.  */
  	      rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
! 	      rtx const_insn = qty_const_insn[REG_QTY (REGNO (dest))];
  
  	      if ((tem = single_set (const_insn)) != 0
  		  && rtx_equal_p (SET_DEST (tem), dest))
*************** cse_insn (insn, libcall_insn)
*** 7605,7614 ****
  
  	      for (i = regno; i < endregno; i++)
  		{
! 		  if (reg_in_table[i] >= 0)
  		    {
  		      remove_invalid_refs (i);
! 		      reg_in_table[i] = -1;
  		    }
  		}
  	    }
--- 7686,7695 ----
  
  	      for (i = regno; i < endregno; i++)
  		{
! 		  if (REG_IN_TABLE (i) >= 0)
  		    {
  		      remove_invalid_refs (i);
! 		      REG_IN_TABLE (i) = -1;
  		    }
  		}
  	    }
*************** cse_insn (insn, libcall_insn)
*** 7813,7819 ****
        && GET_CODE (SET_SRC (sets[0].rtl)) == REG
        && REGNO (SET_SRC (sets[0].rtl)) >= FIRST_PSEUDO_REGISTER
        && REGNO_QTY_VALID_P (REGNO (SET_SRC (sets[0].rtl)))
!       && (qty_first_reg[reg_qty[REGNO (SET_SRC (sets[0].rtl))]]
  	  == REGNO (SET_DEST (sets[0].rtl)))
        && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
      {
--- 7894,7900 ----
        && GET_CODE (SET_SRC (sets[0].rtl)) == REG
        && REGNO (SET_SRC (sets[0].rtl)) >= FIRST_PSEUDO_REGISTER
        && REGNO_QTY_VALID_P (REGNO (SET_SRC (sets[0].rtl)))
!       && (qty_first_reg[REG_QTY (REGNO (SET_SRC (sets[0].rtl)))]
  	  == REGNO (SET_DEST (sets[0].rtl)))
        && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
      {
*************** note_mem_written (addr)
*** 7917,7924 ****
        && GET_CODE (XEXP (addr, 0)) == REG
        && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
      {
!       if (reg_tick[STACK_POINTER_REGNUM] >= 0)
! 	reg_tick[STACK_POINTER_REGNUM]++;
  
        /* This should be *very* rare.  */
        if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
--- 7998,8005 ----
        && GET_CODE (XEXP (addr, 0)) == REG
        && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
      {
!       if (REG_TICK (STACK_POINTER_REGNUM) >= 0)
! 	REG_TICK (STACK_POINTER_REGNUM)++;
  
        /* This should be *very* rare.  */
        if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
*************** cse_process_notes (x, object)
*** 8027,8033 ****
        }
  
      case REG:
!       i = reg_qty[REGNO (x)];
  
        /* Return a constant or a constant register.  */
        if (REGNO_QTY_VALID_P (REGNO (x))
--- 8108,8114 ----
        }
  
      case REG:
!       i = REG_QTY (REGNO (x));
  
        /* Return a constant or a constant register.  */
        if (REGNO_QTY_VALID_P (REGNO (x))
*************** cse_main (f, nregs, after_loop, file)
*** 8585,8604 ****
  
    max_insn_uid = get_max_uid ();
  
-   all_minus_one = (int *) alloca (nregs * sizeof (int));
-   consec_ints = (int *) alloca (nregs * sizeof (int));
- 
-   for (i = 0; i < nregs; i++)
-     {
-       all_minus_one[i] = -1;
-       consec_ints[i] = i;
-     }
- 
    reg_next_eqv = (int *) alloca (nregs * sizeof (int));
    reg_prev_eqv = (int *) alloca (nregs * sizeof (int));
-   reg_qty = (int *) alloca (nregs * sizeof (int));
-   reg_in_table = (int *) alloca (nregs * sizeof (int));
-   reg_tick = (int *) alloca (nregs * sizeof (int));
  
  #ifdef LOAD_EXTEND_OP
  
--- 8666,8673 ----
Index: include/splay-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/include/splay-tree.h,v
retrieving revision 1.6
diff -c -p -r1.6 splay-tree.h
*** splay-tree.h	1999/01/11 13:53:51	1.6
--- splay-tree.h	1999/03/29 06:34:23
*************** extern splay_tree_node splay_tree_lookup
*** 104,109 ****
--- 104,111 ----
  extern int splay_tree_foreach           PARAMS((splay_tree,
  					        splay_tree_foreach_fn,
  					        void*));
+ extern int splay_tree_compare_ints      PARAMS((splay_tree_key,
+ 						splay_tree_key));
  					       
  #ifdef __cplusplus
  }
Index: libiberty/splay-tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libiberty/splay-tree.c,v
retrieving revision 1.7
diff -c -p -r1.7 splay-tree.c
*** splay-tree.c	1999/01/12 19:09:02	1.7
--- splay-tree.c	1999/03/29 06:34:23
*************** splay_tree_foreach (sp, fn, data)
*** 335,338 ****
--- 335,353 ----
       void *data;
  {
    return splay_tree_foreach_helper (sp, sp->root, fn, data);
+ }
+ 
+ /* Splay-tree comparison function, treating the keys as ints.  */
+ 
+ int
+ splay_tree_compare_ints (k1, k2)
+      splay_tree_key k1;
+      splay_tree_key k2;
+ {
+   if ((int) k1 < (int) k2)
+     return -1;
+   else if ((int) k1 > (int) k2)
+     return 1;
+   else 
+     return 0;
  }


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