OSDN Git Service

* gcse.c (expr_hash_table_size, n_exprs, set_hash_table_size,
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Aug 2002 19:10:14 +0000 (19:10 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Aug 2002 19:10:14 +0000 (19:10 +0000)
n_sets): Removed.
(expr_hash_table, set_hash_table): Type changed to ...
(struct hash_table): New type.
(hash_scan_insn, hash_scan_set, hash_scan_clobber, hash_scan_call,
insert_expr_in_table, insert_set_in_table, compute_hash_table,
dump_hash_table, lookup_expr, lookup_set, compute_local_properties,
compute_ae_gen, compute_ae_kill): Modified to pass the table explicitly.
(alloc_set_hash_table, alloc_expr_hash_table): Merged to ...
(alloc_hash_table): New.
(free_set_hash_table, free_expr_hash_table): Merged to ...
(free_hash_table): New.
(compute_set_hash_table, compute_expr_hash_table): Merged to ...
(compute_hash_table_work): New.
(classic_gcse, one_classic_gcse_pass, compute_cprop_data,
find_avail_set, one_cprop_pass, find_bypass_set, compute_pre_data,
pre_edge_insert, pre_insert_copies, pre_delete, pre_gcse,
one_pre_gcse_pass, compute_transpout, compute_code_hoist_vbeinout,
hoist_code, one_code_hoisting_pass,
trim_ld_motion_mems): Altered due to changed type of hash tables.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55940 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gcse.c

index d6c2ddc..103e591 100644 (file)
@@ -1,3 +1,26 @@
+2002-08-01  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * gcse.c (expr_hash_table_size, n_exprs, set_hash_table_size,
+       n_sets): Removed.
+       (expr_hash_table, set_hash_table): Type changed to ...
+       (struct hash_table): New type.
+       (hash_scan_insn, hash_scan_set, hash_scan_clobber, hash_scan_call,
+       insert_expr_in_table, insert_set_in_table, compute_hash_table,
+       dump_hash_table, lookup_expr, lookup_set, compute_local_properties,
+       compute_ae_gen, compute_ae_kill): Modified to pass the table explicitly.
+       (alloc_set_hash_table, alloc_expr_hash_table): Merged to ...
+       (alloc_hash_table): New.
+       (free_set_hash_table, free_expr_hash_table): Merged to ...
+       (free_hash_table): New.
+       (compute_set_hash_table, compute_expr_hash_table): Merged to ...
+       (compute_hash_table_work): New.
+       (classic_gcse, one_classic_gcse_pass, compute_cprop_data,
+       find_avail_set, one_cprop_pass, find_bypass_set, compute_pre_data,
+       pre_edge_insert, pre_insert_copies, pre_delete, pre_gcse,
+       one_pre_gcse_pass, compute_transpout, compute_code_hoist_vbeinout,
+       hoist_code, one_code_hoisting_pass,
+       trim_ld_motion_mems): Altered due to changed type of hash tables.
+
 2002-08-01  Zack Weinberg  <zack@codesourcery.com>
 
        * final.c (output_alternate_entry_point):
index 3ad8a75..b079895 100644 (file)
@@ -362,19 +362,27 @@ struct occr
    [one could build a mapping table without holes afterwards though].
    Someday I'll perform the computation and figure it out.  */
 
-/* Total size of the expression hash table, in elements.  */
-static unsigned int expr_hash_table_size;
+struct hash_table
+{
+  /* The table itself.
+     This is an array of `expr_hash_table_size' elements.  */
+  struct expr **table;
+
+  /* Size of the hash table, in elements.  */
+  unsigned int size;
 
-/* The table itself.
-   This is an array of `expr_hash_table_size' elements.  */
-static struct expr **expr_hash_table;
+  /* Number of hash table elements.  */
+  unsigned int n_elems;
 
-/* Total size of the copy propagation hash table, in elements.  */
-static unsigned int set_hash_table_size;
+  /* Whether the table is expression of copy propagation one.  */
+  int set_p;
+};
 
-/* The table itself.
-   This is an array of `set_hash_table_size' elements.  */
-static struct expr **set_hash_table;
+/* Expression hash table.  */
+static struct hash_table expr_hash_table;
+
+/* Copy propagation hash table.  */
+static struct hash_table set_hash_table;
 
 /* Mapping of uids to cuids.
    Only real insns get cuids.  */
@@ -404,12 +412,6 @@ static rtx *cuid_insn;
    This is named with "gcse" to not collide with global of same name.  */
 static unsigned int max_gcse_regno;
 
-/* Maximum number of cse-able expressions found.  */
-static int n_exprs;
-
-/* Maximum number of assignments for copy propagation found.  */
-static int n_sets;
-
 /* Table of registers that are modified.
 
    For each register, each element is a list of places where the pseudo-reg
@@ -560,17 +562,17 @@ static int get_bitmap_width     PARAMS ((int, int, int));
 static void record_one_set     PARAMS ((int, rtx));
 static void record_set_info    PARAMS ((rtx, rtx, void *));
 static void compute_sets       PARAMS ((rtx));
-static void hash_scan_insn     PARAMS ((rtx, int, int));
-static void hash_scan_set      PARAMS ((rtx, rtx, int));
-static void hash_scan_clobber  PARAMS ((rtx, rtx));
-static void hash_scan_call     PARAMS ((rtx, rtx));
+static void hash_scan_insn     PARAMS ((rtx, struct hash_table *, int));
+static void hash_scan_set      PARAMS ((rtx, rtx, struct hash_table *));
+static void hash_scan_clobber  PARAMS ((rtx, rtx, struct hash_table *));
+static void hash_scan_call     PARAMS ((rtx, rtx, struct hash_table *));
 static int want_to_gcse_p      PARAMS ((rtx));
 static int oprs_unchanged_p    PARAMS ((rtx, rtx, int));
 static int oprs_anticipatable_p PARAMS ((rtx, rtx));
 static int oprs_available_p    PARAMS ((rtx, rtx));
 static void insert_expr_in_table PARAMS ((rtx, enum machine_mode, rtx,
-                                         int, int));
-static void insert_set_in_table PARAMS ((rtx, rtx));
+                                         int, int, struct hash_table *));
+static void insert_set_in_table PARAMS ((rtx, rtx, struct hash_table *));
 static unsigned int hash_expr  PARAMS ((rtx, enum machine_mode, int *, int));
 static unsigned int hash_expr_1 PARAMS ((rtx, enum machine_mode, int *));
 static unsigned int hash_string_1 PARAMS ((const char *));
@@ -579,17 +581,14 @@ static int expr_equiv_p           PARAMS ((rtx, rtx));
 static void record_last_reg_set_info PARAMS ((rtx, int));
 static void record_last_mem_set_info PARAMS ((rtx));
 static void record_last_set_info PARAMS ((rtx, rtx, void *));
-static void compute_hash_table PARAMS ((int));
-static void alloc_set_hash_table PARAMS ((int));
-static void free_set_hash_table PARAMS ((void));
-static void compute_set_hash_table PARAMS ((void));
-static void alloc_expr_hash_table PARAMS ((unsigned int));
-static void free_expr_hash_table PARAMS ((void));
-static void compute_expr_hash_table PARAMS ((void));
-static void dump_hash_table    PARAMS ((FILE *, const char *, struct expr **,
-                                        int, int));
-static struct expr *lookup_expr        PARAMS ((rtx));
-static struct expr *lookup_set PARAMS ((unsigned int, rtx));
+static void compute_hash_table PARAMS ((struct hash_table *));
+static void alloc_hash_table PARAMS ((int, struct hash_table *, int));
+static void free_hash_table PARAMS ((struct hash_table *));
+static void compute_hash_table_work PARAMS ((struct hash_table *));
+static void dump_hash_table    PARAMS ((FILE *, const char *,
+                                       struct hash_table *));
+static struct expr *lookup_expr        PARAMS ((rtx, struct hash_table *));
+static struct expr *lookup_set PARAMS ((unsigned int, rtx, struct hash_table *));
 static struct expr *next_set   PARAMS ((unsigned int, struct expr *));
 static void reset_opr_set_tables PARAMS ((void));
 static int oprs_not_set_p      PARAMS ((rtx, rtx));
@@ -602,7 +601,7 @@ static void free_cprop_mem  PARAMS ((void));
 static void compute_transp     PARAMS ((rtx, int, sbitmap *, int));
 static void compute_transpout  PARAMS ((void));
 static void compute_local_properties PARAMS ((sbitmap *, sbitmap *, sbitmap *,
-                                             int));
+                                             struct hash_table *));
 static void compute_cprop_data PARAMS ((void));
 static void find_used_regs     PARAMS ((rtx *, void *));
 static int try_replace_reg     PARAMS ((rtx, rtx, rtx));
@@ -645,9 +644,9 @@ static void compute_kill_rd PARAMS ((void));
 static void compute_rd         PARAMS ((void));
 static void alloc_avail_expr_mem PARAMS ((int, int));
 static void free_avail_expr_mem PARAMS ((void));
-static void compute_ae_gen     PARAMS ((void));
+static void compute_ae_gen     PARAMS ((struct hash_table *));
 static int expr_killed_p       PARAMS ((rtx, basic_block));
-static void compute_ae_kill    PARAMS ((sbitmap *, sbitmap *));
+static void compute_ae_kill    PARAMS ((sbitmap *, sbitmap *, struct hash_table *));
 static int expr_reaches_here_p PARAMS ((struct occr *, struct expr *,
                                         basic_block, int));
 static rtx computing_insn      PARAMS ((struct expr *, rtx));
@@ -1114,25 +1113,23 @@ get_bitmap_width (n, x, y)
    properties.  If NULL, then it is not necessary to compute or record that
    particular property.
 
-   SETP controls which hash table to look at.  If zero, this routine looks at
-   the expr hash table; if nonzero this routine looks at the set hash table.
-   Additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
+   TABLE controls which hash table to look at.  If it is  set hash table,
+   additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
    ABSALTERED.  */
 
 static void
-compute_local_properties (transp, comp, antloc, setp)
+compute_local_properties (transp, comp, antloc, table)
      sbitmap *transp;
      sbitmap *comp;
      sbitmap *antloc;
-     int setp;
+     struct hash_table *table;
 {
-  unsigned int i, hash_table_size;
-  struct expr **hash_table;
+  unsigned int i;
 
   /* Initialize any bitmaps that were passed in.  */
   if (transp)
     {
-      if (setp)
+      if (table->set_p)
        sbitmap_vector_zero (transp, last_basic_block);
       else
        sbitmap_vector_ones (transp, last_basic_block);
@@ -1143,17 +1140,11 @@ compute_local_properties (transp, comp, antloc, setp)
   if (antloc)
     sbitmap_vector_zero (antloc, last_basic_block);
 
-  /* We use the same code for cprop, pre and hoisting.  For cprop
-     we care about the set hash table, for pre and hoisting we
-     care about the expr hash table.  */
-  hash_table_size = setp ? set_hash_table_size : expr_hash_table_size;
-  hash_table = setp ? set_hash_table : expr_hash_table;
-
-  for (i = 0; i < hash_table_size; i++)
+  for (i = 0; i < table->size; i++)
     {
       struct expr *expr;
 
-      for (expr = hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+      for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
        {
          int indx = expr->bitmap_index;
          struct occr *occr;
@@ -1162,7 +1153,7 @@ compute_local_properties (transp, comp, antloc, setp)
             We start by assuming all are transparent [none are killed], and
             then reset the bits for those that are.  */
          if (transp)
-           compute_transp (expr->expr, indx, transp, setp);
+           compute_transp (expr->expr, indx, transp, table->set_p);
 
          /* The occurrences recorded in antic_occr are exactly those that
             we want to set to non-zero in ANTLOC.  */
@@ -1938,7 +1929,7 @@ expr_equiv_p (x, y)
   return 1;
 }
 
-/* Insert expression X in INSN in the hash table.
+/* Insert expression X in INSN in the hash TABLE.
    If it is already present, record it as the last occurrence in INSN's
    basic block.
 
@@ -1949,11 +1940,12 @@ expr_equiv_p (x, y)
    AVAIL_P is non-zero if X is an available expression.  */
 
 static void
-insert_expr_in_table (x, mode, insn, antic_p, avail_p)
+insert_expr_in_table (x, mode, insn, antic_p, avail_p, table)
      rtx x;
      enum machine_mode mode;
      rtx insn;
      int antic_p, avail_p;
+     struct hash_table *table;
 {
   int found, do_not_record_p;
   unsigned int hash;
@@ -1961,7 +1953,7 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
   struct occr *antic_occr, *avail_occr;
   struct occr *last_occr = NULL;
 
-  hash = hash_expr (x, mode, &do_not_record_p, expr_hash_table_size);
+  hash = hash_expr (x, mode, &do_not_record_p, table->size);
 
   /* Do not insert expression in table if it contains volatile operands,
      or if hash_expr determines the expression is something we don't want
@@ -1969,7 +1961,7 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
   if (do_not_record_p)
     return;
 
-  cur_expr = expr_hash_table[hash];
+  cur_expr = table->table[hash];
   found = 0;
 
   while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
@@ -1984,16 +1976,16 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
     {
       cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
       bytes_used += sizeof (struct expr);
-      if (expr_hash_table[hash] == NULL)
+      if (table->table[hash] == NULL)
        /* This is the first pattern that hashed to this index.  */
-       expr_hash_table[hash] = cur_expr;
+       table->table[hash] = cur_expr;
       else
        /* Add EXPR to end of this hash chain.  */
        last_expr->next_same_hash = cur_expr;
 
       /* Set the fields of the expr element.  */
       cur_expr->expr = x;
-      cur_expr->bitmap_index = n_exprs++;
+      cur_expr->bitmap_index = table->n_elems++;
       cur_expr->next_same_hash = NULL;
       cur_expr->antic_occr = NULL;
       cur_expr->avail_occr = NULL;
@@ -2077,9 +2069,10 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
    basic block.  */
 
 static void
-insert_set_in_table (x, insn)
+insert_set_in_table (x, insn, table)
      rtx x;
      rtx insn;
+     struct hash_table *table;
 {
   int found;
   unsigned int hash;
@@ -2090,9 +2083,9 @@ insert_set_in_table (x, insn)
       || GET_CODE (SET_DEST (x)) != REG)
     abort ();
 
-  hash = hash_set (REGNO (SET_DEST (x)), set_hash_table_size);
+  hash = hash_set (REGNO (SET_DEST (x)), table->size);
 
-  cur_expr = set_hash_table[hash];
+  cur_expr = table->table[hash];
   found = 0;
 
   while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
@@ -2107,9 +2100,9 @@ insert_set_in_table (x, insn)
     {
       cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
       bytes_used += sizeof (struct expr);
-      if (set_hash_table[hash] == NULL)
+      if (table->table[hash] == NULL)
        /* This is the first pattern that hashed to this index.  */
-       set_hash_table[hash] = cur_expr;
+       table->table[hash] = cur_expr;
       else
        /* Add EXPR to end of this hash chain.  */
        last_expr->next_same_hash = cur_expr;
@@ -2118,7 +2111,7 @@ insert_set_in_table (x, insn)
         We must copy X because it can be modified when copy propagation is
         performed on its operands.  */
       cur_expr->expr = copy_rtx (x);
-      cur_expr->bitmap_index = n_sets++;
+      cur_expr->bitmap_index = table->n_elems++;
       cur_expr->next_same_hash = NULL;
       cur_expr->antic_occr = NULL;
       cur_expr->avail_occr = NULL;
@@ -2158,21 +2151,20 @@ insert_set_in_table (x, insn)
     }
 }
 
-/* Scan pattern PAT of INSN and add an entry to the hash table.  If SET_P is
-   non-zero, this is for the assignment hash table, otherwise it is for the
-   expression hash table.  */
+/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or
+   expression one).  */
 
 static void
-hash_scan_set (pat, insn, set_p)
+hash_scan_set (pat, insn, table)
      rtx pat, insn;
-     int set_p;
+     struct hash_table *table;
 {
   rtx src = SET_SRC (pat);
   rtx dest = SET_DEST (pat);
   rtx note;
 
   if (GET_CODE (src) == CALL)
-    hash_scan_call (src, insn);
+    hash_scan_call (src, insn, table);
 
   else if (GET_CODE (dest) == REG)
     {
@@ -2181,12 +2173,12 @@ hash_scan_set (pat, insn, set_p)
 
       /* If this is a single set and we are doing constant propagation,
         see if a REG_NOTE shows this equivalent to a constant.  */
-      if (set_p && (note = find_reg_equal_equiv_note (insn)) != 0
+      if (table->set_p && (note = find_reg_equal_equiv_note (insn)) != 0
          && CONSTANT_P (XEXP (note, 0)))
        src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
 
       /* Only record sets of pseudo-regs in the hash table.  */
-      if (! set_p
+      if (! table->set_p
          && regno >= FIRST_PSEUDO_REGISTER
          /* Don't GCSE something if we can't do a reg/reg copy.  */
          && can_copy_p [GET_MODE (dest)]
@@ -2217,11 +2209,11 @@ hash_scan_set (pat, insn, set_p)
          int avail_p = (oprs_available_p (src, insn)
                         && ! JUMP_P (insn));
 
-         insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p);
+         insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
        }
 
       /* Record sets for constant/copy propagation.  */
-      else if (set_p
+      else if (table->set_p
               && regno >= FIRST_PSEUDO_REGISTER
               && ((GET_CODE (src) == REG
                    && REGNO (src) >= FIRST_PSEUDO_REGISTER
@@ -2234,20 +2226,22 @@ hash_scan_set (pat, insn, set_p)
               && (insn == BLOCK_END (BLOCK_NUM (insn))
                   || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
                       && oprs_available_p (pat, tmp))))
-       insert_set_in_table (pat, insn);
+       insert_set_in_table (pat, insn, table);
     }
 }
 
 static void
-hash_scan_clobber (x, insn)
+hash_scan_clobber (x, insn, table)
      rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
+     struct hash_table *table ATTRIBUTE_UNUSED;
 {
   /* Currently nothing to do.  */
 }
 
 static void
-hash_scan_call (x, insn)
+hash_scan_call (x, insn, table)
      rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
+     struct hash_table *table ATTRIBUTE_UNUSED;
 {
   /* Currently nothing to do.  */
 }
@@ -2266,9 +2260,9 @@ hash_scan_call (x, insn)
    not record any expressions.  */
 
 static void
-hash_scan_insn (insn, set_p, in_libcall_block)
+hash_scan_insn (insn, table, in_libcall_block)
      rtx insn;
-     int set_p;
+     struct hash_table *table;
      int in_libcall_block;
 {
   rtx pat = PATTERN (insn);
@@ -2281,32 +2275,31 @@ hash_scan_insn (insn, set_p, in_libcall_block)
      what's been modified.  */
 
   if (GET_CODE (pat) == SET)
-    hash_scan_set (pat, insn, set_p);
+    hash_scan_set (pat, insn, table);
   else if (GET_CODE (pat) == PARALLEL)
     for (i = 0; i < XVECLEN (pat, 0); i++)
       {
        rtx x = XVECEXP (pat, 0, i);
 
        if (GET_CODE (x) == SET)
-         hash_scan_set (x, insn, set_p);
+         hash_scan_set (x, insn, table);
        else if (GET_CODE (x) == CLOBBER)
-         hash_scan_clobber (x, insn);
+         hash_scan_clobber (x, insn, table);
        else if (GET_CODE (x) == CALL)
-         hash_scan_call (x, insn);
+         hash_scan_call (x, insn, table);
       }
 
   else if (GET_CODE (pat) == CLOBBER)
-    hash_scan_clobber (pat, insn);
+    hash_scan_clobber (pat, insn, table);
   else if (GET_CODE (pat) == CALL)
-    hash_scan_call (pat, insn);
+    hash_scan_call (pat, insn, table);
 }
 
 static void
-dump_hash_table (file, name, table, table_size, total_size)
+dump_hash_table (file, name, table)
      FILE *file;
      const char *name;
-     struct expr **table;
-     int table_size, total_size;
+     struct hash_table *table;
 {
   int i;
   /* Flattened out table, so it's printed in proper order.  */
@@ -2315,20 +2308,20 @@ dump_hash_table (file, name, table, table_size, total_size)
   struct expr *expr;
 
   flat_table
-    = (struct expr **) xcalloc (total_size, sizeof (struct expr *));
-  hash_val = (unsigned int *) xmalloc (total_size * sizeof (unsigned int));
+    = (struct expr **) xcalloc (table->n_elems, sizeof (struct expr *));
+  hash_val = (unsigned int *) xmalloc (table->n_elems * sizeof (unsigned int));
 
-  for (i = 0; i < table_size; i++)
-    for (expr = table[i]; expr != NULL; expr = expr->next_same_hash)
+  for (i = 0; i < (int) table->size; i++)
+    for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
       {
        flat_table[expr->bitmap_index] = expr;
        hash_val[expr->bitmap_index] = i;
       }
 
   fprintf (file, "%s hash table (%d buckets, %d entries)\n",
-          name, table_size, total_size);
+          name, table->size, table->n_elems);
 
-  for (i = 0; i < total_size; i++)
+  for (i = 0; i < (int) table->n_elems; i++)
     if (flat_table[i] != 0)
       {
        expr = flat_table[i];
@@ -2479,11 +2472,11 @@ record_last_set_info (dest, setter, data)
    Currently src must be a pseudo-reg or a const_int.
 
    F is the first insn.
-   SET_P is non-zero for computing the assignment hash table.  */
+   TABLE is the table computed.  */
 
 static void
-compute_hash_table (set_p)
-     int set_p;
+compute_hash_table_work (table)
+     struct hash_table *table;
 {
   unsigned int i;
 
@@ -2549,10 +2542,10 @@ compute_hash_table (set_p)
          {
            if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
              in_libcall_block = 1;
-           else if (set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+           else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
              in_libcall_block = 0;
-           hash_scan_insn (insn, set_p, in_libcall_block);
-           if (!set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+           hash_scan_insn (insn, table, in_libcall_block);
+           if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
              in_libcall_block = 0;
          }
     }
@@ -2561,111 +2554,76 @@ compute_hash_table (set_p)
   reg_avail_info = NULL;
 }
 
-/* Allocate space for the set hash table.
+/* Allocate space for the set/expr hash TABLE.
    N_INSNS is the number of instructions in the function.
-   It is used to determine the number of buckets to use.  */
+   It is used to determine the number of buckets to use.
+   SET_P determines whether set or expression table will
+   be created.  */
 
 static void
-alloc_set_hash_table (n_insns)
+alloc_hash_table (n_insns, table, set_p)
      int n_insns;
+     struct hash_table *table;
+     int set_p;
 {
   int n;
 
-  set_hash_table_size = n_insns / 4;
-  if (set_hash_table_size < 11)
-    set_hash_table_size = 11;
-
-  /* Attempt to maintain efficient use of hash table.
-     Making it an odd number is simplest for now.
-     ??? Later take some measurements.  */
-  set_hash_table_size |= 1;
-  n = set_hash_table_size * sizeof (struct expr *);
-  set_hash_table = (struct expr **) gmalloc (n);
-}
-
-/* Free things allocated by alloc_set_hash_table.  */
-
-static void
-free_set_hash_table ()
-{
-  free (set_hash_table);
-}
-
-/* Compute the hash table for doing copy/const propagation.  */
-
-static void
-compute_set_hash_table ()
-{
-  /* Initialize count of number of entries in hash table.  */
-  n_sets = 0;
-  memset ((char *) set_hash_table, 0,
-         set_hash_table_size * sizeof (struct expr *));
-
-  compute_hash_table (1);
-}
-
-/* Allocate space for the expression hash table.
-   N_INSNS is the number of instructions in the function.
-   It is used to determine the number of buckets to use.  */
-
-static void
-alloc_expr_hash_table (n_insns)
-     unsigned int n_insns;
-{
-  int n;
-
-  expr_hash_table_size = n_insns / 2;
-  /* Make sure the amount is usable.  */
-  if (expr_hash_table_size < 11)
-    expr_hash_table_size = 11;
+  table->size = n_insns / 4;
+  if (table->size < 11)
+    table->size = 11;
 
   /* Attempt to maintain efficient use of hash table.
      Making it an odd number is simplest for now.
      ??? Later take some measurements.  */
-  expr_hash_table_size |= 1;
-  n = expr_hash_table_size * sizeof (struct expr *);
-  expr_hash_table = (struct expr **) gmalloc (n);
+  table->size |= 1;
+  n = table->size * sizeof (struct expr *);
+  table->table = (struct expr **) gmalloc (n);
+  table->set_p = set_p;
 }
 
-/* Free things allocated by alloc_expr_hash_table.  */
+/* Free things allocated by alloc_hash_table.  */
 
 static void
-free_expr_hash_table ()
+free_hash_table (table)
+     struct hash_table *table;
 {
-  free (expr_hash_table);
+  free (table->table);
 }
 
-/* Compute the hash table for doing GCSE.  */
+/* Compute the hash TABLE for doing copy/const propagation or
+   expression hash table.  */
 
 static void
-compute_expr_hash_table ()
+compute_hash_table (table)
+    struct hash_table *table;
 {
   /* Initialize count of number of entries in hash table.  */
-  n_exprs = 0;
-  memset ((char *) expr_hash_table, 0,
-         expr_hash_table_size * sizeof (struct expr *));
+  table->n_elems = 0;
+  memset ((char *) table->table, 0,
+         table->size * sizeof (struct expr *));
 
-  compute_hash_table (0);
+  compute_hash_table_work (table);
 }
 \f
 /* Expression tracking support.  */
 
-/* Lookup pattern PAT in the expression table.
+/* Lookup pattern PAT in the expression TABLE.
    The result is a pointer to the table entry, or NULL if not found.  */
 
 static struct expr *
-lookup_expr (pat)
+lookup_expr (pat, table)
      rtx pat;
+     struct hash_table *table;
 {
   int do_not_record_p;
   unsigned int hash = hash_expr (pat, GET_MODE (pat), &do_not_record_p,
-                                expr_hash_table_size);
+                                table->size);
   struct expr *expr;
 
   if (do_not_record_p)
     return NULL;
 
-  expr = expr_hash_table[hash];
+  expr = table->table[hash];
 
   while (expr && ! expr_equiv_p (expr->expr, pat))
     expr = expr->next_same_hash;
@@ -2673,19 +2631,20 @@ lookup_expr (pat)
   return expr;
 }
 
-/* Lookup REGNO in the set table.  If PAT is non-NULL look for the entry that
+/* Lookup REGNO in the set TABLE.  If PAT is non-NULL look for the entry that
    matches it, otherwise return the first entry for REGNO.  The result is a
    pointer to the table entry, or NULL if not found.  */
 
 static struct expr *
-lookup_set (regno, pat)
+lookup_set (regno, pat, table)
      unsigned int regno;
      rtx pat;
+     struct hash_table *table;
 {
-  unsigned int hash = hash_set (regno, set_hash_table_size);
+  unsigned int hash = hash_set (regno, table->size);
   struct expr *expr;
 
-  expr = set_hash_table[hash];
+  expr = table->table[hash];
 
   if (pat)
     {
@@ -3091,7 +3050,8 @@ free_avail_expr_mem ()
 /* Compute the set of available expressions generated in each basic block.  */
 
 static void
-compute_ae_gen ()
+compute_ae_gen (expr_hash_table)
+     struct hash_table *expr_hash_table;
 {
   unsigned int i;
   struct expr *expr;
@@ -3101,8 +3061,8 @@ compute_ae_gen ()
      This is all we have to do because an expression is not recorded if it
      is not available, and the only expressions we want to work with are the
      ones that are recorded.  */
-  for (i = 0; i < expr_hash_table_size; i++)
-    for (expr = expr_hash_table[i]; expr != 0; expr = expr->next_same_hash)
+  for (i = 0; i < expr_hash_table->size; i++)
+    for (expr = expr_hash_table->table[i]; expr != 0; expr = expr->next_same_hash)
       for (occr = expr->avail_occr; occr != 0; occr = occr->next)
        SET_BIT (ae_gen[BLOCK_NUM (occr->insn)], expr->bitmap_index);
 }
@@ -3173,16 +3133,17 @@ expr_killed_p (x, bb)
 /* Compute the set of available expressions killed in each basic block.  */
 
 static void
-compute_ae_kill (ae_gen, ae_kill)
+compute_ae_kill (ae_gen, ae_kill, expr_hash_table)
      sbitmap *ae_gen, *ae_kill;
+     struct hash_table *expr_hash_table;
 {
   basic_block bb;
   unsigned int i;
   struct expr *expr;
 
   FOR_EACH_BB (bb)
-    for (i = 0; i < expr_hash_table_size; i++)
-      for (expr = expr_hash_table[i]; expr; expr = expr->next_same_hash)
+    for (i = 0; i < expr_hash_table->size; i++)
+      for (expr = expr_hash_table->table[i]; expr; expr = expr->next_same_hash)
        {
          /* Skip EXPR if generated in this block.  */
          if (TEST_BIT (ae_gen[bb->index], expr->bitmap_index))
@@ -3637,7 +3598,7 @@ classic_gcse ()
 
              if (want_to_gcse_p (src)
                  /* Is the expression recorded?  */
-                 && ((expr = lookup_expr (src)) != NULL)
+                 && ((expr = lookup_expr (src, &expr_hash_table)) != NULL)
                  /* Is the expression available [at the start of the
                     block]?  */
                  && TEST_BIT (ae_in[bb->index], expr->bitmap_index)
@@ -3670,27 +3631,26 @@ one_classic_gcse_pass (pass)
   gcse_subst_count = 0;
   gcse_create_count = 0;
 
-  alloc_expr_hash_table (max_cuid);
+  alloc_hash_table (max_cuid, &expr_hash_table, 0);
   alloc_rd_mem (last_basic_block, max_cuid);
-  compute_expr_hash_table ();
+  compute_hash_table (&expr_hash_table);
   if (gcse_file)
-    dump_hash_table (gcse_file, "Expression", expr_hash_table,
-                    expr_hash_table_size, n_exprs);
+    dump_hash_table (gcse_file, "Expression", &expr_hash_table);
 
-  if (n_exprs > 0)
+  if (expr_hash_table.n_elems > 0)
     {
       compute_kill_rd ();
       compute_rd ();
-      alloc_avail_expr_mem (last_basic_block, n_exprs);
-      compute_ae_gen ();
-      compute_ae_kill (ae_gen, ae_kill);
+      alloc_avail_expr_mem (last_basic_block, expr_hash_table.n_elems);
+      compute_ae_gen (&expr_hash_table);
+      compute_ae_kill (ae_gen, ae_kill, &expr_hash_table);
       compute_available (ae_gen, ae_kill, ae_out, ae_in);
       changed = classic_gcse ();
       free_avail_expr_mem ();
     }
 
   free_rd_mem ();
-  free_expr_hash_table ();
+  free_hash_table (&expr_hash_table);
 
   if (gcse_file)
     {
@@ -3882,7 +3842,7 @@ compute_transp (x, indx, bmap, set_p)
 static void
 compute_cprop_data ()
 {
-  compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, 1);
+  compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
   compute_available (cprop_pavloc, cprop_absaltered,
                     cprop_avout, cprop_avin);
 }
@@ -4027,7 +3987,7 @@ find_avail_set (regno, insn)
   while (1)
     {
       rtx src;
-      struct expr *set = lookup_set (regno, NULL_RTX);
+      struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
 
       /* Find a set that is available at the start of the block
         which contains INSN.  */
@@ -4443,14 +4403,13 @@ one_cprop_pass (pass, alter_jumps)
 
   local_cprop_pass (alter_jumps);
 
-  alloc_set_hash_table (max_cuid);
-  compute_set_hash_table ();
+  alloc_hash_table (max_cuid, &set_hash_table, 1);
+  compute_hash_table (&set_hash_table);
   if (gcse_file)
-    dump_hash_table (gcse_file, "SET", set_hash_table, set_hash_table_size,
-                    n_sets);
-  if (n_sets > 0)
+    dump_hash_table (gcse_file, "SET", &set_hash_table);
+  if (set_hash_table.n_elems > 0)
     {
-      alloc_cprop_mem (last_basic_block, n_sets);
+      alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
       compute_cprop_data ();
       changed = cprop (alter_jumps);
       if (alter_jumps)
@@ -4458,7 +4417,7 @@ one_cprop_pass (pass, alter_jumps)
       free_cprop_mem ();
     }
 
-  free_set_hash_table ();
+  free_hash_table (&set_hash_table);
 
   if (gcse_file)
     {
@@ -4487,7 +4446,7 @@ find_bypass_set (regno, bb)
   for (;;)
     {
       rtx src;
-      struct expr *set = lookup_set (regno, NULL_RTX);
+      struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
 
       while (set)
        {
@@ -4762,16 +4721,16 @@ compute_pre_data ()
   basic_block bb;
   unsigned int ui;
 
-  compute_local_properties (transp, comp, antloc, 0);
+  compute_local_properties (transp, comp, antloc, &expr_hash_table);
   sbitmap_vector_zero (ae_kill, last_basic_block);
 
   /* Collect expressions which might trap.  */
-  trapping_expr = sbitmap_alloc (n_exprs);
+  trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
   sbitmap_zero (trapping_expr);
-  for (ui = 0; ui < expr_hash_table_size; ui++)
+  for (ui = 0; ui < expr_hash_table.size; ui++)
     {
       struct expr *e;
-      for (e = expr_hash_table[ui]; e != NULL; e = e->next_same_hash)
+      for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
        if (may_trap_p (e->expr))
          SET_BIT (trapping_expr, e->bitmap_index);
     }
@@ -4802,7 +4761,7 @@ compute_pre_data ()
       sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
     }
 
-  edge_list = pre_edge_lcm (gcse_file, n_exprs, transp, comp, antloc,
+  edge_list = pre_edge_lcm (gcse_file, expr_hash_table.n_elems, transp, comp, antloc,
                            ae_kill, &pre_insert_map, &pre_delete_map);
   sbitmap_vector_free (antloc);
   antloc = NULL;
@@ -5075,7 +5034,7 @@ pre_edge_insert (edge_list, index_map)
 
   set_size = pre_insert_map[0]->size;
   num_edges = NUM_EDGES (edge_list);
-  inserted = sbitmap_vector_alloc (num_edges, n_exprs);
+  inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
   sbitmap_vector_zero (inserted, num_edges);
 
   for (e = 0; e < num_edges; e++)
@@ -5087,7 +5046,7 @@ pre_edge_insert (edge_list, index_map)
        {
          SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
 
-         for (j = indx; insert && j < n_exprs; j++, insert >>= 1)
+         for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
            if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
              {
                struct expr *expr = index_map[j];
@@ -5192,8 +5151,8 @@ pre_insert_copies ()
      ??? The current algorithm is rather brute force.
      Need to do some profiling.  */
 
-  for (i = 0; i < expr_hash_table_size; i++)
-    for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+  for (i = 0; i < expr_hash_table.size; i++)
+    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
       {
        /* If the basic block isn't reachable, PPOUT will be TRUE.  However,
           we don't want to insert a copy here because the expression may not
@@ -5280,8 +5239,8 @@ pre_delete ()
   struct occr *occr;
 
   changed = 0;
-  for (i = 0; i < expr_hash_table_size; i++)
-    for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+  for (i = 0; i < expr_hash_table.size; i++)
+    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
       {
        int indx = expr->bitmap_index;
 
@@ -5360,9 +5319,9 @@ pre_gcse ()
   /* Compute a mapping from expression number (`bitmap_index') to
      hash table entry.  */
 
-  index_map = (struct expr **) xcalloc (n_exprs, sizeof (struct expr *));
-  for (i = 0; i < expr_hash_table_size; i++)
-    for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+  index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
+  for (i = 0; i < expr_hash_table.size; i++)
+    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
       index_map[expr->bitmap_index] = expr;
 
   /* Reset bitmap used to track which insns are redundant.  */
@@ -5405,20 +5364,19 @@ one_pre_gcse_pass (pass)
   gcse_subst_count = 0;
   gcse_create_count = 0;
 
-  alloc_expr_hash_table (max_cuid);
+  alloc_hash_table (max_cuid, &expr_hash_table, 0);
   add_noreturn_fake_exit_edges ();
   if (flag_gcse_lm)
     compute_ld_motion_mems ();
 
-  compute_expr_hash_table ();
+  compute_hash_table (&expr_hash_table);
   trim_ld_motion_mems ();
   if (gcse_file)
-    dump_hash_table (gcse_file, "Expression", expr_hash_table,
-                    expr_hash_table_size, n_exprs);
+    dump_hash_table (gcse_file, "Expression", &expr_hash_table);
 
-  if (n_exprs > 0)
+  if (expr_hash_table.n_elems > 0)
     {
-      alloc_pre_mem (last_basic_block, n_exprs);
+      alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
       compute_pre_data ();
       changed |= pre_gcse ();
       free_edge_list (edge_list);
@@ -5427,7 +5385,7 @@ one_pre_gcse_pass (pass)
 
   free_ldst_mems ();
   remove_fake_edges ();
-  free_expr_hash_table ();
+  free_hash_table (&expr_hash_table);
 
   if (gcse_file)
     {
@@ -5516,8 +5474,8 @@ compute_transpout ()
       if (GET_CODE (bb->end) != CALL_INSN)
        continue;
 
-      for (i = 0; i < expr_hash_table_size; i++)
-       for (expr = expr_hash_table[i]; expr ; expr = expr->next_same_hash)
+      for (i = 0; i < expr_hash_table.size; i++)
+       for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
          if (GET_CODE (expr->expr) == MEM)
            {
              if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
@@ -5932,7 +5890,7 @@ compute_code_hoist_vbeinout ()
 static void
 compute_code_hoist_data ()
 {
-  compute_local_properties (transp, comp, antloc, 0);
+  compute_local_properties (transp, comp, antloc, &expr_hash_table);
   compute_transpout ();
   compute_code_hoist_vbeinout ();
   dominators = calculate_dominance_info (CDI_DOMINATORS);
@@ -6019,9 +5977,9 @@ hoist_code ()
   /* Compute a mapping from expression number (`bitmap_index') to
      hash table entry.  */
 
-  index_map = (struct expr **) xcalloc (n_exprs, sizeof (struct expr *));
-  for (i = 0; i < expr_hash_table_size; i++)
-    for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+  index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
+  for (i = 0; i < expr_hash_table.size; i++)
+    for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
       index_map[expr->bitmap_index] = expr;
 
   /* Walk over each basic block looking for potentially hoistable
@@ -6175,21 +6133,20 @@ one_code_hoisting_pass ()
 {
   int changed = 0;
 
-  alloc_expr_hash_table (max_cuid);
-  compute_expr_hash_table ();
+  alloc_hash_table (max_cuid, &expr_hash_table, 0);
+  compute_hash_table (&expr_hash_table);
   if (gcse_file)
-    dump_hash_table (gcse_file, "Code Hosting Expressions", expr_hash_table,
-                    expr_hash_table_size, n_exprs);
+    dump_hash_table (gcse_file, "Code Hosting Expressions", &expr_hash_table);
 
-  if (n_exprs > 0)
+  if (expr_hash_table.n_elems > 0)
     {
-      alloc_code_hoist_mem (last_basic_block, n_exprs);
+      alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
       compute_code_hoist_data ();
       hoist_code ();
       free_code_hoist_mem ();
     }
 
-  free_expr_hash_table ();
+  free_hash_table (&expr_hash_table);
 
   return changed;
 }
@@ -6509,9 +6466,9 @@ trim_ld_motion_mems ()
 
          del = 1;
          /* Delete if we cannot find this mem in the expression list.  */
-         for (i = 0; i < expr_hash_table_size && del; i++)
+         for (i = 0; i < expr_hash_table.size && del; i++)
            {
-             for (expr = expr_hash_table[i];
+             for (expr = expr_hash_table.table[i];
                   expr != NULL;
                   expr = expr->next_same_hash)
                if (expr_equiv_p (expr->expr, ptr->pattern))