re PR middle-end/17503 (quadratic behaviour in invalid_mode_change_p)
authorRichard Henderson <rth@redhat.com>
Fri, 24 Sep 2004 19:47:05 +0000 (12:47 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 24 Sep 2004 19:47:05 +0000 (12:47 -0700)
        PR rtl-opt/17503
        * regclass.c (subregs_of_mode): Turn into an htab.  Make static.
        (som_hash, som_eq): New.
        (init_subregs_of_mode, record_subregs_of_mode): New.
        (cannot_change_mode_set_regs): Rewrite for htab implementation.
        (invalid_mode_change_p): Likewise.
        * combine.c (gen_lowpart_for_combine): Use record_subregs_of_mode.
        * flow.c (mark_used_regs): Likewise.
        (life_analysis): Use init_subregs_of_mode.
        * regs.h (subregs_of_mode): Remove.
        * rtl.h (init_subregs_of_mode, record_subregs_of_mode): Declare.

From-SVN: r88067

gcc/ChangeLog
gcc/combine.c
gcc/flow.c
gcc/regclass.c
gcc/regs.h
gcc/rtl.h

index 74b4a425f54a9cf113dd08fdb65e4c619b40feec..070d85c8254cc3a796a986961944107b631b8238 100644 (file)
@@ -1,3 +1,17 @@
+2004-09-24  Richard Henderson  <rth@redhat.com>
+
+       PR rtl-opt/17503
+       * regclass.c (subregs_of_mode): Turn into an htab.  Make static.
+       (som_hash, som_eq): New.
+       (init_subregs_of_mode, record_subregs_of_mode): New.
+       (cannot_change_mode_set_regs): Rewrite for htab implementation.
+       (invalid_mode_change_p): Likewise.
+       * combine.c (gen_lowpart_for_combine): Use record_subregs_of_mode.
+       * flow.c (mark_used_regs): Likewise.
+       (life_analysis): Use init_subregs_of_mode.
+       * regs.h (subregs_of_mode): Remove.
+       * rtl.h (init_subregs_of_mode, record_subregs_of_mode): Declare.
+
 2004-09-24  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * tree-ssa-phiopt.c (conditional_replacement): Use the correct
index 24ebbc97147db840d82b71b3d20b00c527f8dcda..f0b5b0698dd04c5274fbb3eadafc597e24097c93 100644 (file)
@@ -9327,13 +9327,8 @@ gen_lowpart_for_combine (enum machine_mode mode, rtx x)
 
   result = gen_lowpart_common (mode, x);
 #ifdef CANNOT_CHANGE_MODE_CLASS
-  if (result != 0
-      && GET_CODE (result) == SUBREG
-      && REG_P (SUBREG_REG (result))
-      && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
-    bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result))
-                                     * MAX_MACHINE_MODE
-                                     + GET_MODE (result));
+  if (result != 0 && GET_CODE (result) == SUBREG)
+    record_subregs_of_mode (result);
 #endif
 
   if (result)
index d1e7e2d61c4948683fb8a09e31f5ff834a5391d6..02f7ff215051b7d52f76ebb987d8658675ac589b 100644 (file)
@@ -377,7 +377,7 @@ life_analysis (FILE *file, int flags)
 
 #ifdef CANNOT_CHANGE_MODE_CLASS
   if (flags & PROP_REG_INFO)
-    bitmap_initialize (&subregs_of_mode, 1);
+    init_subregs_of_mode ();
 #endif
 
   if (! optimize)
@@ -3773,12 +3773,8 @@ mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn)
 
     case SUBREG:
 #ifdef CANNOT_CHANGE_MODE_CLASS
-      if ((flags & PROP_REG_INFO)
-         && REG_P (SUBREG_REG (x))
-         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
-       bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
-                                         * MAX_MACHINE_MODE
-                                         + GET_MODE (x));
+      if (flags & PROP_REG_INFO)
+       record_subregs_of_mode (x);
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3823,13 +3819,8 @@ mark_used_regs (struct propagate_block_info *pbi, rtx x, rtx cond, rtx insn)
               || GET_CODE (testreg) == SUBREG)
          {
 #ifdef CANNOT_CHANGE_MODE_CLASS
-           if ((flags & PROP_REG_INFO)
-               && GET_CODE (testreg) == SUBREG
-               && REG_P (SUBREG_REG (testreg))
-               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
-             bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
-                                               * MAX_MACHINE_MODE
-                                               + GET_MODE (testreg));
+           if ((flags & PROP_REG_INFO) && GET_CODE (testreg) == SUBREG)
+             record_subregs_of_mode (testreg);
 #endif
 
            /* Modifying a single register in an alternate mode
index 1d33a0977b2fb164b6606b376b4fc2f58d3d2a93..6d1d975f093bfc893f4a236598aafb8d7800a733 100644 (file)
@@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "ggc.h"
 #include "timevar.h"
+#include "hashtab.h"
 
 static void init_reg_sets_1 (void);
 static void init_reg_autoinc (void);
@@ -235,12 +236,6 @@ static char *in_inc_dec;
 
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
-#ifdef CANNOT_CHANGE_MODE_CLASS
-/* All registers that have been subreged.  Indexed by regno * MAX_MACHINE_MODE
-   + mode.  */
-bitmap_head subregs_of_mode;
-#endif
-
 /* Sample MEM values for use by memory_move_secondary_cost.  */
 
 static GTY(()) rtx top_of_stack[MAX_MACHINE_MODE];
@@ -2594,6 +2589,70 @@ regset_release_memory (void)
 }
 
 #ifdef CANNOT_CHANGE_MODE_CLASS
+
+struct subregs_of_mode_node
+{
+  unsigned int block;
+  unsigned char modes[MAX_MACHINE_MODE];
+};
+
+static htab_t subregs_of_mode;
+
+static hashval_t
+som_hash (const void *x)
+{
+  const struct subregs_of_mode_node *a = x;
+  return a->block;
+}
+
+static int
+som_eq (const void *x, const void *y)
+{
+  const struct subregs_of_mode_node *a = x;
+  const struct subregs_of_mode_node *b = y;
+  return a->block == b->block;
+}
+
+void
+init_subregs_of_mode (void)
+{
+  if (subregs_of_mode)
+    htab_empty (subregs_of_mode);
+  else
+    subregs_of_mode = htab_create (100, som_hash, som_eq, free);
+}
+
+void
+record_subregs_of_mode (rtx subreg)
+{
+  struct subregs_of_mode_node dummy, *node;
+  enum machine_mode mode;
+  unsigned int regno;
+  void **slot;
+
+  if (!REG_P (SUBREG_REG (subreg)))
+    return;
+
+  regno = REGNO (SUBREG_REG (subreg));
+  mode = GET_MODE (subreg);
+
+  if (regno < FIRST_PSEUDO_REGISTER)
+    return;
+
+  dummy.block = regno & -8;
+  slot = htab_find_slot_with_hash (subregs_of_mode, &dummy,
+                                  dummy.block, INSERT);
+  node = *slot;
+  if (node == NULL)
+    {
+      node = xcalloc (1, sizeof (*node));
+      node->block = regno & -8;
+      *slot = node;
+    }
+
+  node->modes[mode] |= 1 << (regno & 7);
+}
+
 /* Set bits in *USED which correspond to registers which can't change
    their mode from FROM to any mode in which REGNO was encountered.  */
 
@@ -2601,19 +2660,23 @@ void
 cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
                             unsigned int regno)
 {
+  struct subregs_of_mode_node dummy, *node;
   enum machine_mode to;
-  int n, i;
-  int start = regno * MAX_MACHINE_MODE;
+  unsigned char mask;
+  unsigned int i;
 
-  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
-    if (n >= MAX_MACHINE_MODE + start)
-      return;
-    to = n - start;
-    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-      if (! TEST_HARD_REG_BIT (*used, i)
-         && REG_CANNOT_CHANGE_MODE_P (i, from, to))
-       SET_HARD_REG_BIT (*used, i);
-  );
+  dummy.block = regno & -8;
+  node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+  if (node == NULL)
+    return;
+
+  mask = 1 << (regno & 7);
+  for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
+    if (node->modes[to] & mask)
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (!TEST_HARD_REG_BIT (*used, i)
+           && REG_CANNOT_CHANGE_MODE_P (i, from, to))
+         SET_HARD_REG_BIT (*used, i);
 }
 
 /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
@@ -2621,20 +2684,24 @@ cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
 
 bool
 invalid_mode_change_p (unsigned int regno, enum reg_class class,
-                      enum machine_mode from_mode)
+                      enum machine_mode from)
 {
-  enum machine_mode to_mode;
-  int n;
-  int start = regno * MAX_MACHINE_MODE;
-
-  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
-    if (n >= MAX_MACHINE_MODE + start)
-      return 0;
-    to_mode = n - start;
-    if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class))
-      return 1;
-  );
-  return 0;
+  struct subregs_of_mode_node dummy, *node;
+  enum machine_mode to;
+  unsigned char mask;
+
+  dummy.block = regno & -8;
+  node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+  if (node == NULL)
+    return false;
+
+  mask = 1 << (regno & 7);
+  for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
+    if (node->modes[to] & mask)
+      if (CANNOT_CHANGE_MODE_CLASS (from, to, class))
+       return true;
+
+  return false;
 }
 #endif /* CANNOT_CHANGE_MODE_CLASS */
 
index 027b0e33c67e5570732301f8bceb1f6dea9a6c81..848c306a3ff35f97502bbc1f506f46de2a05974d 100644 (file)
@@ -68,8 +68,6 @@ typedef struct reg_info_def
 
 extern varray_type reg_n_info;
 
-extern bitmap_head subregs_of_mode;
-
 /* Indexed by n, gives number of times (REG n) is used or set.  */
 
 #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
index d96b3d4c4339194cefe286723a0cb7d569fdc358..8f7274a3c1bbe61f3e8b2c6fd78047c6b59fbe53 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2092,6 +2092,8 @@ extern void regclass (rtx, int, FILE *);
 extern void reg_scan (rtx, unsigned int, int);
 extern void reg_scan_update (rtx, rtx, unsigned int);
 extern void fix_register (const char *, int, int);
+extern void init_subregs_of_mode (void);
+extern void record_subregs_of_mode (rtx);
 #ifdef HARD_CONST
 extern void cannot_change_mode_set_regs (HARD_REG_SET *,
                                         enum machine_mode, unsigned int);