hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.
authorAldy Hernandez <aldyh@redhat.com>
Mon, 4 Nov 2002 16:58:39 +0000 (16:58 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Mon, 4 Nov 2002 16:58:39 +0000 (16:58 +0000)
2002-11-04  Aldy Hernandez  <aldyh@redhat.com>

* hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.

* config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Remove.
(CLASS_CANNOT_CHANGE_MODE): Remove.
(CANNOT_CHANGE_MODE_CLASS): New.

* config/alpha/alpha.h: Same.

* config/ia64/ia64.h: Same.

* config/mips/mips.h: Same.

* config/s390/s390.h: Same.

* config/sh/sh.h: Same.

* config/pa/pa64-regs.h: Same.

* config/sh/sh-protos.h (sh_cannot_change_mode_class): Add prototype.

* config/sh/sh.c (sh_cannot_change_mode_class): New.

* config/mips/mips-protos.h (mips_cannot_change_mode_class): Add
prototype.

* config/mips/mips.c (mips_cannot_change_mode_class): New.

* doc/tm.texi (Register Classes): Remove
CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P.
Document CANNOT_CHANGE_MODE_CLASS.

* reload.c (push_reload): Use CANNOT_CHANGE_MODE_CLASS.
(push_reload): Same.

* simplify-rtx.c (simplify_subreg): Same.

* reload1.c (choose_reload_regs): Same.

* recog.c (register_operand): Same.

* regrename.c (mode_change_ok): Change to use new
CANNOT_CHANGE_MODE_CLASS infrastructure.

* regclass.c (cannot_change_mode_set_regs): New.
Declare subregs_of_mode.
(regclass): Use subregs_of_mode.
Remove references to reg_changes_mode.
(init_reg_sets_1): Remove class_can_change_mode and
reg_changes_mode code.
(invalid_mode_change_p): New.
(dump_regclass): Use invalid_mode_change_p instead of
class_can_change_mode.
(regclass): Same.
(record_operand_costs): Do not set reg_changes_mode.

* local-alloc.c (struct qty): Remove changes_mode field.
(alloc_qty): Remove changes_mode initialization.
(update_qty_class): Remove set of changes_mode.
(find_free_reg): Use subregs_of_mode.

* global.c (find_reg): Use subregs_of_mode info.

* rtl.h (cannot_change_mode_set_regs): New prototype.
(invalid_mode_change_p): Same.
(REG_CANNOT_CHANGE_MODE_P): New macro.

* flow.c (mark_used_regs): Calculate subregs_of_mode.  Remove
REG_CHANGES_MODE.
(life_analysis): Clear subregs_of_mode.

* combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
Remove use of CLASS_CANNOT_CHANGE_MODE.
(simplify_set): Same.
(gen_lowpart_for_combine): Calculate subregs_of_mode.  Remove
REG_CHANGES_MODE.

* regs.h: Add extern for subregs_of_mode;
Include hard-reg-set and basic-block.
(REG_CHANGES_MODE): Delete.

From-SVN: r58794

26 files changed:
gcc/ChangeLog
gcc/combine.c
gcc/config/alpha/alpha.h
gcc/config/ia64/ia64.h
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/pa/pa64-regs.h
gcc/config/rs6000/rs6000.h
gcc/config/s390/s390.h
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/doc/tm.texi
gcc/flow.c
gcc/global.c
gcc/hard-reg-set.h
gcc/local-alloc.c
gcc/recog.c
gcc/regclass.c
gcc/regrename.c
gcc/regs.h
gcc/reload.c
gcc/reload1.c
gcc/rtl.h
gcc/simplify-rtx.c

index 0e0f0eea8f17d22fa549fd13e94ce8d4193a4e50..9b4c1439034e6e6709f39f23d62eb5bdabfdbf98 100644 (file)
@@ -1,3 +1,85 @@
+2002-11-04  Aldy Hernandez  <aldyh@redhat.com>
+
+       * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.
+
+       * config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Remove.
+       (CLASS_CANNOT_CHANGE_MODE): Remove.
+       (CANNOT_CHANGE_MODE_CLASS): New.
+
+       * config/alpha/alpha.h: Same.
+
+       * config/ia64/ia64.h: Same.
+
+       * config/mips/mips.h: Same.
+
+       * config/s390/s390.h: Same.
+
+       * config/sh/sh.h: Same.
+
+       * config/pa/pa64-regs.h: Same.
+
+       * config/sh/sh-protos.h (sh_cannot_change_mode_class): Add prototype.
+       
+       * config/sh/sh.c (sh_cannot_change_mode_class): New.
+
+       * config/mips/mips-protos.h (mips_cannot_change_mode_class): Add
+       prototype.
+
+       * config/mips/mips.c (mips_cannot_change_mode_class): New.
+
+       * doc/tm.texi (Register Classes): Remove
+       CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P.
+       Document CANNOT_CHANGE_MODE_CLASS.
+
+       * reload.c (push_reload): Use CANNOT_CHANGE_MODE_CLASS.
+       (push_reload): Same.
+
+       * simplify-rtx.c (simplify_subreg): Same.
+
+       * reload1.c (choose_reload_regs): Same.
+
+       * recog.c (register_operand): Same.
+
+       * regrename.c (mode_change_ok): Change to use new
+       CANNOT_CHANGE_MODE_CLASS infrastructure.
+
+       * regclass.c (cannot_change_mode_set_regs): New.
+       Declare subregs_of_mode.
+       (regclass): Use subregs_of_mode.
+       Remove references to reg_changes_mode.
+       (init_reg_sets_1): Remove class_can_change_mode and
+       reg_changes_mode code.
+       (invalid_mode_change_p): New.
+       (dump_regclass): Use invalid_mode_change_p instead of
+       class_can_change_mode.
+       (regclass): Same.
+       (record_operand_costs): Do not set reg_changes_mode.
+
+       * local-alloc.c (struct qty): Remove changes_mode field.
+       (alloc_qty): Remove changes_mode initialization.
+       (update_qty_class): Remove set of changes_mode.
+       (find_free_reg): Use subregs_of_mode.
+
+       * global.c (find_reg): Use subregs_of_mode info.
+
+       * rtl.h (cannot_change_mode_set_regs): New prototype.
+       (invalid_mode_change_p): Same.
+       (REG_CANNOT_CHANGE_MODE_P): New macro.
+
+       * flow.c (mark_used_regs): Calculate subregs_of_mode.  Remove
+       REG_CHANGES_MODE.
+       (life_analysis): Clear subregs_of_mode.
+
+       * combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
+       Remove use of CLASS_CANNOT_CHANGE_MODE.
+       (simplify_set): Same.
+       (gen_lowpart_for_combine): Calculate subregs_of_mode.  Remove
+       REG_CHANGES_MODE.
+       
+       * regs.h: Add extern for subregs_of_mode;
+       Include hard-reg-set and basic-block.
+       (REG_CHANGES_MODE): Delete.
+
 2002-11-03  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * jump.c (never_reached_warning): Don't set contains_insn until the
index d6dfdf68d171d35348e0873b90e74a550c27610f..8ce9d10eb1d013b69781ad58bf72eaf56748a6a2 100644 (file)
@@ -3519,15 +3519,13 @@ subst (x, from, to, in_dest, unique_copy)
                      )
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
                  if (code == SUBREG
                      && GET_CODE (to) == REG
                      && REGNO (to) < FIRST_PSEUDO_REGISTER
-                     && (TEST_HARD_REG_BIT
-                         (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                          REGNO (to)))
-                     && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
-                                                    GET_MODE (x)))
+                     && REG_CANNOT_CHANGE_MODE_P (REGNO (to),
+                                                  GET_MODE (to),
+                                                  GET_MODE (x)))
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 #endif
 
@@ -5198,13 +5196,11 @@ simplify_set (x)
       && (GET_MODE_SIZE (GET_MODE (src))
          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
-           && (TEST_HARD_REG_BIT
-               (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                REGNO (dest)))
-           && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
-                                          GET_MODE (SUBREG_REG (src))))
+           && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
+                                        GET_MODE (src), 
+                                        GET_MODE (SUBREG_REG (src))))
 #endif
       && (GET_CODE (dest) == REG
          || (GET_CODE (dest) == SUBREG
@@ -9937,14 +9933,13 @@ gen_lowpart_for_combine (mode, x)
     }
 
   result = gen_lowpart_common (mode, x);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#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
-      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
-                                    GET_MODE (SUBREG_REG (result))))
-    REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
+      && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
+    SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
+                      REGNO (SUBREG_REG (result)));
 #endif
 
   if (result)
index 39973770d7114d5067983526c3b64a46adfd053a..9e39a40395b6a645f97e09fafdfb2abf4bac2979 100644 (file)
@@ -857,15 +857,10 @@ enum reg_class {
 #define CLASS_MAX_NREGS(CLASS, MODE)                           \
  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* If defined, gives a class of registers that cannot be used as the
-   operand of a SUBREG that changes the mode of the object illegally.  */
+/* Return the class of registers that cannot change mode from FROM to TO.  */
 
-#define CLASS_CANNOT_CHANGE_MODE       FLOAT_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
 
 /* Define the cost of moving between registers of various classes.  Moving
    between FLOAT_REGS and anything else except float regs is expensive. 
index 578e354664434646e1c3da2eb5ad0be704d9c3bd..59d6e230366550bd8135aa7b52c2bc3b4fa12984 100644 (file)
@@ -1008,17 +1008,11 @@ enum reg_class
    : ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1              \
    : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* If defined, gives a class of registers that cannot be used as the
-   operand of a SUBREG that changes the mode of the object illegally.  */
-
-#define CLASS_CANNOT_CHANGE_MODE        FR_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
-   In FP regs, we can't change FP values to integer values and vice
+/* In FP regs, we can't change FP values to integer values and vice
    versa, but we can change e.g. DImode to SImode.  */
 
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)     \
+  (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) ? FR_REGS : NO_REGS)
 
 /* A C expression that defines the machine-dependent operand constraint
    letters (`I', `J', `K', .. 'P') that specify particular ranges of
index df943afb3f54decb71f95c65bc5363d2ca587235..d92f7e573b3a653d3703449f0d8dc4f904b85410 100644 (file)
@@ -122,6 +122,8 @@ extern int              mips_adjust_insn_length PARAMS ((rtx, int));
 extern enum reg_class  mips_secondary_reload_class PARAMS ((enum reg_class,
                                                             enum machine_mode,
                                                             rtx, int));
+extern enum reg_class  mips_cannot_change_mode_class 
+                         PARAMS ((enum machine_mode, enum machine_mode));
 extern int              mips_class_max_nregs PARAMS ((enum reg_class,
                                                      enum machine_mode));
 extern int              mips_register_move_cost PARAMS ((enum machine_mode,
index dafa9207cad70dd83da0bdfc9598ddf5e4a63221..d58affff1c2f0037893062d5955f1ef3ecc0140d 100644 (file)
@@ -8399,6 +8399,23 @@ function_arg_pass_by_reference (cum, mode, type, named)
   return size == -1 || size > UNITS_PER_WORD;
 }
 
+/* Return the class of registers for which a mode change from FROM to TO
+   is invalid.  */
+enum reg_class
+mips_cannot_change_mode_class (from, to)
+     enum machine_mode from, to;
+{
+  if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
+    {
+      if (TARGET_BIG_ENDIAN)
+        return FP_REGS;
+      if (TARGET_FLOAT64)
+        return HI_AND_FP_REGS;
+      return HI_REG;
+    }
+  return NO_REGS;
+}
+
 /* This function returns the register class required for a secondary
    register when copying between one of the registers in CLASS, and X,
    using MODE.  If IN_P is nonzero, the copy is going from X to the
index 87513a2bda047ca5c8b3f23e435e0d4c9f72cd15..bc37a145e284997b8a9bed2d3c565b9bfd9ec0af 100644 (file)
@@ -2343,14 +2343,8 @@ extern enum reg_class mips_char_to_class[256];
    We can't allow 64-bit float registers to change from a 32-bit
    mode to a 64-bit mode.  */
 
-#define CLASS_CANNOT_CHANGE_MODE                                       \
-  (TARGET_BIG_ENDIAN ? FP_REGS                                         \
-   : (TARGET_FLOAT64 ? HI_AND_FP_REGS : HI_REG))
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
+  mips_cannot_change_mode_class (FROM, TO)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index 0af4c5fb2706cd9d104f4c330dfaf7a7293e3d93..2d0ebe3d17264b23035dee556f1a916e41d7db85 100644 (file)
@@ -232,12 +232,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
   {0x00000000, 0x10000000},    /* SHIFT_REGS */                \
   {0xfffffffe, 0x1fffffff}}    /* ALL_REGS */
 
-/* If defined, gives a class of registers that cannot be used as the
-   operand of a SUBREG that changes the mode of the object illegally.  */
-
-#define CLASS_CANNOT_CHANGE_MODE       (FP_REGS)
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
+/* Defines invalid mode changes.
 
    SImode loads to floating-point registers are not zero-extended.
    The definition for LOAD_EXTEND_OP specifies that integer loads
@@ -245,8 +240,9 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
    we inhibit changes from SImode unless they are to a mode that is
    identical in size.  */
 
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO)                            \
-  ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)                     \
+  ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)       \
+   ? FP_REGS : NO_REGS)
 
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
index 55805490d44ddc3eccdf991da0aa53aa3d790e88..39ef154f04636f017df11ed7f59f0f131ac862a6 100644 (file)
@@ -1314,16 +1314,14 @@ enum reg_class
   ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* If defined, gives a class of registers that cannot be used as the
-   operand of a SUBREG that changes the mode of the object illegally.  */
 
-#define CLASS_CANNOT_CHANGE_MODE        FLOAT_REGS
+/* Return a class of registers that cannot change FROM mode to TO mode.  */
 
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)                              \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS              \
+   : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 ? GENERAL_REGS \
+   : NO_REGS)
 
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
-\f
 /* Stack layout; function entry, exit and calling.  */
 
 /* Enumeration to give which calling sequence to use.  */
index 009f8a4bcf9992c24c8fff2306fe84e97f7a6285..268ee2f3445467c064700d9812d232bcb57fc9d6 100644 (file)
@@ -330,10 +330,8 @@ do                                                         \
 /* If a 4-byte value is loaded into a FPR, it is placed into the
    *upper* half of the register, not the lower.  Therefore, we
    cannot use SUBREGs to switch between modes in FP registers.  */
-#define CLASS_CANNOT_CHANGE_MODE FP_REGS
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
-
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)             \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FP_REGS : NO_REGS)
 
 /* Register classes.  */
  
index a2152efa2f41c8f4c39284eb0c912a8c1109fab5..a729462393eed3a5cafd867ae41b4cb2dad7afc3 100644 (file)
@@ -126,6 +126,8 @@ extern int sh_pr_n_sets PARAMS ((void));
 extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int));
 extern int sh_cfun_interrupt_handler_p PARAMS ((void));
 extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx));
+extern enum reg_class sh_cannot_change_mode_class
+             PARAMS ((enum machine_mode, enum machine_mode));
 
 #ifdef HARD_CONST
 extern void fpscr_set_from_mem PARAMS ((int, HARD_REG_SET));
index 4e6981bfbe4b3676a3ca5c696534ee06f51a67f8..d2cc47186d9e9fe168be6ca0f20570aca90daffb 100644 (file)
@@ -7733,4 +7733,26 @@ sh_expand_binop_v2sf (code, op0, op1, op2)
   emit_insn ((*fn) (op0, op1, op2, op, sel1, sel1, sel1));
 }
 
+/* Return the class of registers for which a mode change from FROM to TO
+   is invalid.  */
+enum reg_class 
+sh_cannot_change_mode_class (from, to)
+     enum machine_mode from, to;
+{
+  if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
+    {
+       if (TARGET_LITTLE_ENDIAN)
+         {
+          if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
+            return DF_REGS;
+        }
+       else
+        {
+          if (GET_MODE_SIZE (from) < 8)
+            return DF_HI_REGS;
+        }
+    }
+  return NO_REGS;
+}
+
 #include "gt-sh.h"
index d0bbbdf0805cf1ba1f0cf570d857d922431fce3e..feadbb7d841bd0ef847ed95af5589c7cc3b4616b 100644 (file)
@@ -1372,14 +1372,8 @@ extern const enum reg_class reg_class_from_letter[];
 /* ??? We need to renumber the internal numbers for the frnn registers
    when in little endian in order to allow mode size changes.  */
 
-#define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_REGS)
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
-   && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) \
-       || GET_MODE_SIZE (FROM) < 8))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)                         \
+  sh_cannot_change_mode_class (FROM, TO)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index 5ca0836de07aa021a0039b0e949e535bc16f3899..b8f2b934671aceae1e88a52372b454c7f6a3a96e 100644 (file)
@@ -2561,25 +2561,22 @@ should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno},
 This macro helps control the handling of multiple-word values
 in the reload pass.
 
-@item CLASS_CANNOT_CHANGE_MODE
-If defined, a C expression for a class that contains registers for
-which the compiler may not change modes arbitrarily.
-
-@item CLASS_CANNOT_CHANGE_MODE_P(@var{from}, @var{to})
-A C expression that is true if, for a register in
-@code{CLASS_CANNOT_CHANGE_MODE}, the requested mode punning is invalid.
+@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to})
+If defined, a C expression that returns a register class for which
+a change from mode @var{from} to mode @var{to} is invalid, otherwise the
+macro returns @code{NO_REGS}.
 
 For the example, loading 32-bit integer or floating-point objects into
 floating-point registers on the Alpha extends them to 64 bits.
 Therefore loading a 64-bit object and then storing it as a 32-bit object
 does not store the low-order 32 bits, as would be the case for a normal
-register.  Therefore, @file{alpha.h} defines @code{CLASS_CANNOT_CHANGE_MODE}
-as @code{FLOAT_REGS} and @code{CLASS_CANNOT_CHANGE_MODE_P} restricts
-mode changes to same-size modes.
+register.  Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS}
+as below:
 
-Compare this to IA-64, which extends floating-point values to 82-bits,
-and stores 64-bit integers in a different format than 64-bit doubles.
-Therefore @code{CLASS_CANNOT_CHANGE_MODE_P} is always true.
+@example
+#define CANNOT_CHANGE_MODE_CLASS \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
+@end example
 @end table
 
 Three other special macros describe which operands fit which constraint
index d9e3ae3ce4022cd36ab16996868bf93a1bbdab08..180796268c67d2d702657d154e0ba84ef44a914e 100644 (file)
@@ -414,8 +414,8 @@ life_analysis (f, file, flags)
      FILE *file;
      int flags;
 {
-#ifdef ELIMINABLE_REGS
   int i;
+#ifdef ELIMINABLE_REGS
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
 
@@ -431,6 +431,13 @@ life_analysis (f, file, flags)
   SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
 #endif
 
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  if (flags & PROP_REG_INFO)
+    for (i=0; i < NUM_MACHINE_MODES; ++i)
+      INIT_REG_SET (&subregs_of_mode[i]);
+#endif
+
   if (! optimize)
     flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
 
@@ -3813,12 +3820,11 @@ mark_used_regs (pbi, x, cond, insn)
       break;
 
     case SUBREG:
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       if (GET_CODE (SUBREG_REG (x)) == REG
-         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
-         && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
-                                        GET_MODE (SUBREG_REG (x))))
-       REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
+         && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
+       SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
+                          REGNO (SUBREG_REG (x)));
 #endif
 
       /* While we're here, optimize this case.  */
@@ -3862,13 +3868,12 @@ mark_used_regs (pbi, x, cond, insn)
               || GET_CODE (testreg) == SIGN_EXTRACT
               || GET_CODE (testreg) == SUBREG)
          {
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
            if (GET_CODE (testreg) == SUBREG
                && GET_CODE (SUBREG_REG (testreg)) == REG
-               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
-               && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
-                                              GET_MODE (testreg)))
-             REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
+               && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
+             SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
+                                REGNO (SUBREG_REG (testreg)));
 #endif
 
            /* Modifying a single register in an alternate mode
index a100096238043e132b04d3ae6d8b4d7b1efdecf6..dfbe0388d018fb96a3ea4d84e4e125f7f30826dd 100644 (file)
@@ -974,10 +974,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
      int retrying;
 {
   int i, best_reg, pass;
-#ifdef HARD_REG_SET
-  register             /* Declare it register if it's a scalar.  */
-#endif
-    HARD_REG_SET used, used1, used2;
+  HARD_REG_SET used, used1, used2;
 
   enum reg_class class = (alt_regs_p
                          ? reg_alternate_class (allocno[num].reg)
@@ -1001,10 +998,8 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
 
   IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  if (REG_CHANGES_MODE (allocno[num].reg))
-    IOR_HARD_REG_SET (used1,
-                     reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
 #endif
 
   /* Try each hard reg to see if it fits.  Do this in two passes.
@@ -1200,11 +1195,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
              && (allocno[num].calls_crossed == 0
                  || accept_call_clobbered
                  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-#ifdef CLASS_CANNOT_CHANGE_MODE
-             && ! (REG_CHANGES_MODE (allocno[num].reg)
-                   && (TEST_HARD_REG_BIT
-                       (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                        regno)))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+             && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
+                                         mode)
 #endif
              )
            {
index 9cdd96835c94616568d4450bb139be86bd4a47b4..712a26791f31fa52969593d91b2774375050a3b7 100644 (file)
@@ -488,4 +488,11 @@ extern int n_non_fixed_regs;
 
 extern const char * reg_names[FIRST_PSEUDO_REGISTER];
 
+/* Given a hard REGN a FROM mode and a TO mode, return non-zero if
+   REGN cannot change modes between the specified modes.  */
+#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO)                          \
+        (TEST_HARD_REG_BIT                                                \
+          (reg_class_contents[(int) CANNOT_CHANGE_MODE_CLASS (FROM, TO)],  \
+           REGN))
+
 #endif /* ! GCC_HARD_REG_SET_H */
index 9c94924aec92e896023bad355b785451dd524d85..c2d6c0c610b49799e6ce6c6939eccdd7f001fe80 100644 (file)
@@ -61,10 +61,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "hard-reg-set.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "regs.h"
 #include "function.h"
@@ -144,12 +144,6 @@ struct qty
      or -1 if none was found.  */
 
   short phys_reg;
-
-  /* Nonzero if this quantity has been used in a SUBREG in some
-     way that is illegal.  */
-
-  char changes_mode;
-
 };
 
 static struct qty *qty;
@@ -328,7 +322,6 @@ alloc_qty (regno, mode, size, birth)
   qty[qtyno].alternate_class = reg_alternate_class (regno);
   qty[qtyno].n_refs = REG_N_REFS (regno);
   qty[qtyno].freq = REG_FREQ (regno);
-  qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
 }
 \f
 /* Main entry point of this file.  */
@@ -2026,9 +2019,6 @@ update_qty_class (qtyno, reg)
   rclass = reg_alternate_class (reg);
   if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
     qty[qtyno].alternate_class = rclass;
-
-  if (REG_CHANGES_MODE (reg))
-    qty[qtyno].changes_mode = 1;
 }
 \f
 /* Handle something which alters the value of an rtx REG.
@@ -2182,11 +2172,7 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
      int born_index, dead_index;
 {
   int i, ins;
-#ifdef HARD_REG_SET
-  /* Declare it register if it's a scalar.  */
-  register
-#endif
-    HARD_REG_SET used, first_used;
+  HARD_REG_SET first_used, used;
 #ifdef ELIMINABLE_REGS
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
@@ -2234,10 +2220,8 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
   SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
 #endif
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  if (qty[qtyno].changes_mode)
-    IOR_HARD_REG_SET (used,
-                     reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
 #endif
 
   /* Normally, the registers that can be used for the first register in
index 6b6117fa5c5ecb59bff972c5e76c6c5c406320fe..b40867bf7a312fbb1b5d1bfdb22db392aedee6a8 100644 (file)
@@ -1083,13 +1083,10 @@ register_operand (op, mode)
       if (! reload_completed && GET_CODE (sub) == MEM)
        return general_operand (op, mode);
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       if (GET_CODE (sub) == REG
          && REGNO (sub) < FIRST_PSEUDO_REGISTER
-         && (TEST_HARD_REG_BIT
-             (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-              REGNO (sub)))
-         && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
+         && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub))
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
        return 0;
index 28c2a6f10811dd230ab25ce0d43c2aa6fbfcedef..20c7d3b03d1a06528a4ec6f4c26c6f3b806d19bc 100644 (file)
@@ -26,10 +26,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "hard-reg-set.h"
 #include "rtl.h"
 #include "expr.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "flags.h"
 #include "basic-block.h"
 #include "regs.h"
@@ -227,20 +227,11 @@ static char *in_inc_dec;
 
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-
-/* These are the classes containing only registers that can be used in
-   a SUBREG expression that changes the mode of the register in some
-   way that is illegal.  */
-
-static int class_can_change_mode[N_REG_CLASSES];
-
-/* Registers, including pseudos, which change modes in some way that
-   is illegal.  */
-
-static regset reg_changes_mode;
-
-#endif /* CLASS_CANNOT_CHANGE_MODE */
+#ifdef CANNOT_CHANGE_MODE_CLASS
+/* All registers that have been subreged.  Indexed by mode, where each
+   entry is a regset of registers.  */
+regset_head subregs_of_mode [NUM_MACHINE_MODES];
+#endif
 
 /* Sample MEM values for use by memory_move_secondary_cost.  */
 
@@ -549,22 +540,6 @@ init_reg_sets_1 ()
                may_move_out_cost[m][i][j] = 65536;
              }
       }
-
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  {
-    HARD_REG_SET c;
-    COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]);
-
-    for (i = 0; i < N_REG_CLASSES; i++)
-      {
-       GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class);
-       class_can_change_mode [i] = 0;
-       continue;
-      ok_class:
-       class_can_change_mode [i] = 1;
-      }
-    }
-#endif /* CLASS_CANNOT_CHANGE_MODE */
 }
 
 /* Compute the table of register modes.
@@ -952,9 +927,9 @@ dump_regclass (dump)
                && (!in_inc_dec[i]
                    || !forbidden_inc_dec_class[(enum reg_class) class])
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
-               && (!REGNO_REG_SET_P (reg_changes_mode, i)
-                    || class_can_change_mode [(enum reg_class) class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+               && ! invalid_mode_change_p (i, (enum reg_class) class,
+                                           PSEUDO_REGNO_MODE (i))
 #endif
                )
            fprintf (dump, " %s:%i", reg_class_names[class],
@@ -994,15 +969,7 @@ record_operand_costs (insn, op_costs, reg_pref)
       op_costs[i] = init_cost;
 
       if (GET_CODE (recog_data.operand[i]) == SUBREG)
-       {
-         rtx inner = SUBREG_REG (recog_data.operand[i]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
-         if (GET_CODE (inner) == REG
-             && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner)))
-           SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner));
-#endif
-         recog_data.operand[i] = inner;
-       }
+       recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
 
       if (GET_CODE (recog_data.operand[i]) == MEM)
        record_address_regs (XEXP (recog_data.operand[i], 0),
@@ -1193,10 +1160,6 @@ regclass (f, nregs, dump)
 
   costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  reg_changes_mode = BITMAP_XMALLOC ();
-#endif
-
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 
   in_inc_dec = (char *) xmalloc (nregs);
@@ -1329,9 +1292,9 @@ regclass (f, nregs, dump)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
-                 || (REGNO_REG_SET_P (reg_changes_mode, i)
-                     && ! class_can_change_mode [class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                 || invalid_mode_change_p (i, (enum reg_class) class,
+                                           PSEUDO_REGNO_MODE (i))
 #endif
                  )
                ;
@@ -1359,9 +1322,9 @@ regclass (f, nregs, dump)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
-                 && ! (REGNO_REG_SET_P (reg_changes_mode, i)
-                       && ! class_can_change_mode [class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                 && ! invalid_mode_change_p (i, (enum reg_class) class,
+                                             PSEUDO_REGNO_MODE (i))
 #endif
                  )
                alt = reg_class_subunion[(int) alt][class];
@@ -1394,9 +1357,6 @@ regclass (f, nregs, dump)
 
 #ifdef FORBIDDEN_INC_DEC_CLASSES
   free (in_inc_dec);
-#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  BITMAP_XFREE (reg_changes_mode);
 #endif
   free (costs);
 }
@@ -2643,4 +2603,46 @@ regset_release_memory ()
   bitmap_release_memory ();
 }
 
+#ifdef CANNOT_CHANGE_MODE_CLASS
+/* Set bits in *USED which correspond to registers which can't change
+   their mode from FROM to any mode in which REGNO was encountered.  */
+
+void
+cannot_change_mode_set_regs (used, from, regno)
+     HARD_REG_SET *used;
+     enum machine_mode from;
+     unsigned int regno;
+{
+  enum machine_mode to;
+  enum reg_class class;
+
+  for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
+    if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
+      {
+        class = CANNOT_CHANGE_MODE_CLASS (from, to);
+        if (class != NO_REGS)
+          IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
+      }
+}
+
+/* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
+   mode.  */
+
+bool
+invalid_mode_change_p (regno, class, from_mode)
+     unsigned int regno;
+      enum reg_class class;
+     enum machine_mode from_mode;
+{
+  enum machine_mode to_mode;
+
+  for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
+    if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
+       && reg_classes_intersect_p 
+            (class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode)))
+      return 1;
+  return 0;
+}
+#endif /* CANNOT_CHANGE_MODE_CLASS */
+
 #include "gt-regclass.h"
index ac1043d38b959653045356a44390a6cae746accf..9b7dfd6d3c5ad1edae449893701d284fa3778aeb 100644 (file)
@@ -1313,10 +1313,8 @@ mode_change_ok (orig_mode, new_mode, regno)
   if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
     return false;
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  if (TEST_HARD_REG_BIT (reg_class_contents[CLASS_CANNOT_CHANGE_MODE], regno)
-      && CLASS_CANNOT_CHANGE_MODE_P (orig_mode, new_mode))
-    return false;
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
 #endif
 
   return true;
index 0b35f07dee0aab1949b98a220154c5cf08a81a91..4a78212ec805ad60a859c6f1b8a8dccb8c6d67b9 100644 (file)
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 
 #include "varray.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
 
 #define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
 
@@ -64,6 +66,8 @@ typedef struct reg_info_def
 
 extern varray_type reg_n_info;
 
+extern regset_head subregs_of_mode [NUM_MACHINE_MODES];
+
 /* 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)
@@ -104,13 +108,6 @@ extern varray_type reg_n_info;
 
 #define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths)
 
-/* Indexed by N; says whether a pseudo register N was ever used
-   within a SUBREG that changes the mode of the reg in some way
-   that is illegal for a given class (usually floating-point)
-   of registers.  */
-
-#define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode)
-
 /* Get the number of consecutive words required to hold pseudo-reg N.  */
 
 #define PSEUDO_REGNO_SIZE(N) \
index 97b35218caa1751b9a5762ed31d8665ce80c7b2f..2b119886d4be3768b7fee63f05a9cc92a977ebfc 100644 (file)
@@ -967,9 +967,10 @@ push_reload (in, out, inloc, outloc, class,
 
   if (in != 0 && GET_CODE (in) == SUBREG
       && (subreg_lowpart_p (in) || strict_low)
-#ifdef CLASS_CANNOT_CHANGE_MODE
-      && (class != CLASS_CANNOT_CHANGE_MODE
-         || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+      && !reg_classes_intersect_p 
+          (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)),
+                                            inmode))
 #endif
       && (CONSTANT_P (SUBREG_REG (in))
          || GET_CODE (SUBREG_REG (in)) == PLUS
@@ -1016,14 +1017,11 @@ push_reload (in, out, inloc, outloc, class,
                                                SUBREG_REG (in))
                  == NO_REGS))
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
          || (GET_CODE (SUBREG_REG (in)) == REG
              && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
-             && (TEST_HARD_REG_BIT
-                 (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                  REGNO (SUBREG_REG (in))))
-             && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
-                                            inmode))
+             && REG_CANNOT_CHANGE_MODE_P
+             (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
 #endif
          ))
     {
@@ -1081,10 +1079,10 @@ push_reload (in, out, inloc, outloc, class,
      and in that case the constraint should label it input-output.)  */
   if (out != 0 && GET_CODE (out) == SUBREG
       && (subreg_lowpart_p (out) || strict_low)
-#ifdef CLASS_CANNOT_CHANGE_MODE
-      && (class != CLASS_CANNOT_CHANGE_MODE
-         || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
-                                          outmode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+      && !reg_classes_intersect_p 
+           (class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)),
+                                             outmode))
 #endif
       && (CONSTANT_P (SUBREG_REG (out))
          || strict_low
@@ -1118,14 +1116,12 @@ push_reload (in, out, inloc, outloc, class,
                                                 SUBREG_REG (out))
                  == NO_REGS))
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
          || (GET_CODE (SUBREG_REG (out)) == REG
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
-             && (TEST_HARD_REG_BIT
-                 (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                  REGNO (SUBREG_REG (out))))
-             && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
-                                            outmode))
+             && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
+                                          GET_MODE (SUBREG_REG (out)), 
+                                          outmode))
 #endif
          ))
     {
index 65ee2749a3c244ca14ee7b76637db442f3753def..2704dadab4d92a5b4c10dd4ba290b982b1cc4210 100644 (file)
@@ -5490,16 +5490,15 @@ choose_reload_regs (chain)
                                                GET_MODE_CLASS (mode));
 
                  if (
-#ifdef CLASS_CANNOT_CHANGE_MODE
-                     (TEST_HARD_REG_BIT
-                      (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
-                      ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
-                                                      need_mode)
-                      : (GET_MODE_SIZE (GET_MODE (last_reg))
-                         >= GET_MODE_SIZE (need_mode)))
-#else
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                     (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
+                                                 need_mode)
+                      ||
+#endif
                      (GET_MODE_SIZE (GET_MODE (last_reg))
                       >= GET_MODE_SIZE (need_mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                     )
 #endif
                      && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
index 9aada8286e5bf6885c2224d81823f43f4696f9b9..1d71ec90ce41d1400fe893224656082e66e654a7 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2092,6 +2092,7 @@ extern int global_alloc                   PARAMS ((FILE *));
 extern void dump_global_regs           PARAMS ((FILE *));
 #endif
 #ifdef HARD_CONST
+/* Yes, this ifdef is silly, but HARD_REG_SET is not always defined.  */
 extern void retry_global_alloc         PARAMS ((int, HARD_REG_SET));
 #endif
 extern void build_insn_chain           PARAMS ((rtx));
@@ -2109,6 +2110,14 @@ 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));
+#ifdef HARD_CONST
+extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
+                                                enum machine_mode,
+                                                unsigned int));
+#endif
+extern bool invalid_mode_change_p      PARAMS ((unsigned int,
+                                                enum reg_class,
+                                                enum machine_mode));
 
 extern int delete_null_pointer_checks  PARAMS ((rtx));
 
@@ -2269,4 +2278,5 @@ extern void invert_br_probabilities       PARAMS ((rtx));
 extern bool expensive_function_p       PARAMS ((int));
 /* In tracer.c */
 extern void tracer                     PARAMS ((void));
+
 #endif /* ! GCC_RTL_H */
index 52a92504a001fe2d5be38d0fe7ba20ca2c3c9a56..212d3b9023609d93716787a3a9c84a4739421ca6 100644 (file)
@@ -2586,15 +2586,12 @@ simplify_subreg (outermode, op, innermode, byte)
   if (REG_P (op)
       && (! REG_FUNCTION_VALUE_P (op)
          || ! rtx_equal_function_value_matters)
-#ifdef CLASS_CANNOT_CHANGE_MODE
-      && ! (CLASS_CANNOT_CHANGE_MODE_P (outermode, innermode)
+      && REGNO (op) < FIRST_PSEUDO_REGISTER
+#ifdef CANNOT_CHANGE_MODE_CLASS
+      && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), outermode, innermode)
            && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
-           && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT
-           && (TEST_HARD_REG_BIT
-               (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                REGNO (op))))
+           && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
 #endif
-      && REGNO (op) < FIRST_PSEUDO_REGISTER
       && ((reload_completed && !frame_pointer_needed)
          || (REGNO (op) != FRAME_POINTER_REGNUM
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM