]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/17503 (quadratic behaviour in invalid_mode_change_p)
authorRichard Henderson <rth@gcc.gnu.org>
Sat, 4 Dec 2004 00:36:38 +0000 (16:36 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 4 Dec 2004 00:36:38 +0000 (16:36 -0800)
        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: r91714

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

index 81bd0c148ceb52b771ec33fada867f984787b543..49df8ee33992cc317835fb7ce0ce246f495cabe4 100644 (file)
@@ -1,3 +1,18 @@
+2004-12-03  Richard Henderson  <rth@redhat.com>
+
+       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-12-03  Roger Sayle  <roger@eyesopen.com>
 
        PR target/9908
@@ -20,7 +35,7 @@
        regs_invalidated_by_call.
 
 2004-11-27  Falk Hueffner  <falk@debian.org>
-            Eric Botcazou  <ebotcazou@libertysurf.fr>
+           Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR optimization/18577
        * unroll.c (unroll_loop): Test both REGNO_LAST_UID and
 
 2004-09-30  Richard Henderson  <rth@redhat.com>
  
-        * config/alpha/qrnnd.asm: Mark for noexecstack.
+       * config/alpha/qrnnd.asm: Mark for noexecstack.
  
 2004-09-30  Richard Henderson  <rth@redhat.com>
   
-        * unwind-dw2.c (_Unwind_GetGR): Honor DWARF_ZERO_REG.
-        * doc/tm.texi (DWARF_ZERO_REG): New.
+       * unwind-dw2.c (_Unwind_GetGR): Honor DWARF_ZERO_REG.
+       * doc/tm.texi (DWARF_ZERO_REG): New.
   
-        * config/alpha/alpha.c (alpha_sa_mask, alpha_expand_prologue,
-        alpha_expand_epilogue): Revert 2003-09-30 change to store zero.
-        * config/alpha/alpha.h (DWARF_ZERO_REG): New.
+       * config/alpha/alpha.c (alpha_sa_mask, alpha_expand_prologue,
+       alpha_expand_epilogue): Revert 2003-09-30 change to store zero.
+       * config/alpha/alpha.h (DWARF_ZERO_REG): New.
 
 2004-09-30  Release Manager
 
 
 2004-09-13  Richard Henderson  <rth@redhat.com>
 
-        PR inline-asm/6806
-        * cselib.c (cselib_invalidate_rtx): Export.  Remove unused args.
-        (cselib_invalidate_rtx_note_stores): New.
-        (cselib_record_sets, cselib_process_insn): Update to match.
-        * cselib.h (cselib_invalidate_rtx): Declare.
-        * reload1.c (reload_cse_simplify): Invalidate asm clobbers.
+       PR inline-asm/6806
+       * cselib.c (cselib_invalidate_rtx): Export.  Remove unused args.
+       (cselib_invalidate_rtx_note_stores): New.
+       (cselib_record_sets, cselib_process_insn): Update to match.
+       * cselib.h (cselib_invalidate_rtx): Declare.
+       * reload1.c (reload_cse_simplify): Invalidate asm clobbers.
 
 2004-08-29  Jonathan Wakely  <redi@gcc.gnu.org>
 
 2004-07-25  Andreas Jaeger  <aj@suse.de>
 
        Backport from mainline:
-        * libgcc-std.ver: Add __unorddf2 and __unordsf2 with version 3.3.4.
+       * libgcc-std.ver: Add __unorddf2 and __unordsf2 with version 3.3.4.
 
 2004-07-25  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        side-effect of having a length greater or equal to 3.
 
 2004-07-13  Eric Botcazou  <ebotcazou@libertysurf.fr>
-            Lloyd Parkes  <lloyd@must-have-coffee.gen.nz>
+           Lloyd Parkes  <lloyd@must-have-coffee.gen.nz>
 
        PR target/15186
        * config/sparc/sol2-bi.h (LINK_ARCH64_SPEC_BASE): Pass
        /usr/ucblib/sparcv9 as -R path when -compat-bsd is specified.
 
 2004-07-13  Eric Botcazou  <ebotcazou@libertysurf.fr>
-            Martin Sebor  <sebor@roguewave.com>
+           Martin Sebor  <sebor@roguewave.com>
 
        PR target/12602
        * doc/invoke.texi (SPARC options): Document -threads
 
        Backport from mainline:
        2004-01-19  Richard Henderson  <rth@redhat.com>
-        * alpha.md (UNSPEC_NT_LDA): Renumber.
-        (UNSPEC_CVTLQ, cvtlq): New.
-        (extendsidi2_1): Rename from extendsidi2_nofix; remove f/f.
-        (extendsidi2_fix): Remove.
-        (extendsidi2 splitter): Use cvtlq.
-        (extendsidi2 fp peepholes): Remove.
-        (cvtql): Use SFmode instead of SImode.
-        (fix_trunc?fsi): Update to match.
-        (floatsisf2_ieee, floatsisf2, floatsidf2_ieee, floatsidf2): New.
-        (movsi): Rename from movsi_nofix, remove f alternatives.
-        (movsi_nt_vms): Similarly.
-        (movsi_fix, movsi_nt_vms_fix): Remove.
+       * alpha.md (UNSPEC_NT_LDA): Renumber.
+       (UNSPEC_CVTLQ, cvtlq): New.
+       (extendsidi2_1): Rename from extendsidi2_nofix; remove f/f.
+       (extendsidi2_fix): Remove.
+       (extendsidi2 splitter): Use cvtlq.
+       (extendsidi2 fp peepholes): Remove.
+       (cvtql): Use SFmode instead of SImode.
+       (fix_trunc?fsi): Update to match.
+       (floatsisf2_ieee, floatsisf2, floatsidf2_ieee, floatsidf2): New.
+       (movsi): Rename from movsi_nofix, remove f alternatives.
+       (movsi_nt_vms): Similarly.
+       (movsi_fix, movsi_nt_vms_fix): Remove.
 
 2004-05-26  Hans-Peter Nilsson  <hp@axis.com>
 
index bc4ee639047cab9fcdafde367c13e58fea4a7b77..c8b5987faab52c16e7905c11a7b02d99bd011fd4 100644 (file)
@@ -10138,13 +10138,8 @@ gen_lowpart_for_combine (mode, x)
 
   result = gen_lowpart_common (mode, x);
 #ifdef CANNOT_CHANGE_MODE_CLASS
-  if (result != 0
-      && GET_CODE (result) == SUBREG
-      && GET_CODE (SUBREG_REG (result)) == REG
-      && 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 11b15dc0ce4d2867e35a856e14a4a1fe41d0fea2..9f5e1924e91add149214ac1eb422c94c68168f11 100644 (file)
@@ -431,9 +431,8 @@ life_analysis (f, file, flags)
   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
 #endif
 
-
 #ifdef CANNOT_CHANGE_MODE_CLASS
-  bitmap_initialize (&subregs_of_mode, 1);
+  init_subregs_of_mode ();
 #endif
 
   if (! optimize)
@@ -3851,11 +3850,7 @@ mark_used_regs (pbi, x, cond, insn)
 
     case SUBREG:
 #ifdef CANNOT_CHANGE_MODE_CLASS
-      if (GET_CODE (SUBREG_REG (x)) == REG
-         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
-       bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
-                                         * MAX_MACHINE_MODE
-                                         + GET_MODE (x));
+      record_subregs_of_mode (x);
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3900,12 +3895,8 @@ mark_used_regs (pbi, x, cond, insn)
               || GET_CODE (testreg) == SUBREG)
          {
 #ifdef CANNOT_CHANGE_MODE_CLASS
-           if (GET_CODE (testreg) == SUBREG
-               && GET_CODE (SUBREG_REG (testreg)) == REG
-               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
-             bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
-                                               * MAX_MACHINE_MODE
-                                               + GET_MODE (testreg));
+           if (GET_CODE (testreg) == SUBREG)
+             record_subregs_of_mode (testreg);
 #endif
 
            /* Modifying a single register in an alternate mode
index e3a8963a594a6b5c29b515866282046a2207ad13..999a0d61f46e84a23ec97cac6c4b19db70b0b1e2 100644 (file)
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "output.h"
 #include "ggc.h"
+#include "hashtab.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(m, x, y) 2
@@ -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];
@@ -2630,6 +2625,77 @@ regset_release_memory ()
 }
 
 #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 PARAMS ((const void *));
+static int som_eq PARAMS ((const void *, const void *));
+
+static hashval_t
+som_hash (x)
+     const void *x;
+{
+  const struct subregs_of_mode_node *a = x;
+  return a->block;
+}
+
+static int
+som_eq (x, y)
+     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 ()
+{
+  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 (subreg)
+     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.  */
 
@@ -2639,42 +2705,50 @@ cannot_change_mode_set_regs (used, from, regno)
      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
    mode.  */
 
 bool
-invalid_mode_change_p (regno, class, from_mode)
+invalid_mode_change_p (regno, class, from)
      unsigned int regno;
-      enum reg_class class;
-     enum machine_mode from_mode;
+     enum reg_class class;
+     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 e823298614de43d9a97651bc34b63ceca21c7d22..1e7ba44195828f332db34591df7171b5b6c492b7 100644 (file)
@@ -69,8 +69,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 715febfddd92a2bf430c0132591831bf60ce199e..ded9c99d46bc542904be809c0ec865cbfdd58671 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2120,6 +2120,8 @@ extern void regclass                      PARAMS ((rtx, int, FILE *));
 extern void reg_scan                   PARAMS ((rtx, unsigned int, int));
 extern void reg_scan_update            PARAMS ((rtx, rtx, unsigned int));
 extern void fix_register               PARAMS ((const char *, int, int));
+extern void init_subregs_of_mode       PARAMS ((void));
+extern void record_subregs_of_mode     PARAMS ((rtx));
 #ifdef HARD_CONST
 extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
                                                 enum machine_mode,