Turn CANNOT_CHANGE_MODE_CLASS into a hook
authorRichard Sandiford <richard.sandiford@linaro.org>
Fri, 15 Sep 2017 12:56:34 +0000 (12:56 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 15 Sep 2017 12:56:34 +0000 (12:56 +0000)
This also seemed like a good opportunity to reverse the sense of the
hook to "can", to avoid the awkward double negative in !CANNOT.

2017-09-15  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayard  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* target.def (can_change_mode_class): New hook.
(mode_rep_extended): Refer to it instead of CANNOT_CHANGE_MODE_CLASS.
(hard_regno_nregs): Likewise.
* hooks.h (hook_bool_mode_mode_reg_class_t_true): Declare.
* hooks.c (hook_bool_mode_mode_reg_class_t_true): New function.
* doc/tm.texi.in (CANNOT_CHANGE_MODE_CLASS): Replace with...
(TARGET_CAN_CHANGE_MODE_CLASS): ...this.
(LOAD_EXTEND_OP): Update accordingly.
* doc/tm.texi: Regenerate.
* doc/rtl.texi: Refer to TARGET_CAN_CHANGE_MODE_CLASS instead of
CANNOT_CHANGE_MODE_CLASS.
* hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Replace with...
(REG_CAN_CHANGE_MODE_P): ...this new macro.
* combine.c (simplify_set): Update accordingly.
* emit-rtl.c (validate_subreg): Likewise.
* recog.c (general_operand): Likewise.
* regcprop.c (mode_change_ok): Likewise.
* reload1.c (choose_reload_regs): Likewise.
(inherit_piecemeal_p): Likewise.
* rtlanal.c (simplify_subreg_regno): Likewise.
* postreload.c (reload_cse_simplify_set): Use REG_CAN_CHANGE_MODE_P
instead of CANNOT_CHANGE_MODE_CLASS.
(reload_cse_simplify_operands): Likewise.
* reload.c (push_reload): Use targetm.can_change_mode_class
instead of CANNOT_CHANGE_MODE_CLASS.
(push_reload): Likewise.  Also use REG_CAN_CHANGE_MODE_P instead of
REG_CANNOT_CHANGE_MODE_P.
* config/alpha/alpha.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/alpha/alpha.c (alpha_can_change_mode_class): New function.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/arm/arm.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/arm/arm.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(arm_can_change_mode_class): New function.
* config/arm/neon.md: Refer to TARGET_CAN_CHANGE_MODE_CLASS rather
than CANNOT_CHANGE_MODE_CLASS in comments.
* config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/i386/i386-protos.h (ix86_cannot_change_mode_class): Delete.
* config/i386/i386.c (ix86_cannot_change_mode_class): Replace with...
(ix86_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/ia64/ia64.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/ia64/ia64.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(ia64_can_change_mode_class): New function.
* config/m32c/m32c.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/m32c/m32c-protos.h (m32c_cannot_change_mode_class): Delete.
* config/m32c/m32c.c (m32c_cannot_change_mode_class): Replace with...
(m32c_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/mips/mips.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/mips/mips-protos.h (mips_cannot_change_mode_class): Delete.
* config/mips/mips.c (mips_cannot_change_mode_class): Replace with...
(mips_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/msp430/msp430.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/msp430/msp430.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(msp430_can_change_mode_class): New function.
* config/nvptx/nvptx.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/nvptx/nvptx.c (nvptx_can_change_mode_class): New function.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/pa/pa32-regs.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/pa/pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/pa/pa-protos.h (pa_cannot_change_mode_class): Delete.
* config/pa/pa.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(pa_cannot_change_mode_class): Replace with...
(pa_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(pa_modes_tieable_p): Refer to TARGET_CAN_CHANGE_MODE_CLASS rather
than CANNOT_CHANGE_MODE_CLASS in comments.
* config/pdp11/pdp11.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class): Delete.
* config/pdp11/pdp11.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(pdp11_cannot_change_mode_class): Replace with...
(pdp11_can_change_mode_class): ...this new function, inverting the
sense of the return value.
* config/powerpcspe/powerpcspe.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/powerpcspe/powerpcspe-protos.h
(rs6000_cannot_change_mode_class_ptr): Delete.
* config/powerpcspe/powerpcspe.c
(rs6000_cannot_change_mode_class_ptr): Delete.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(rs6000_option_override_internal): Assign to
targetm.can_change_mode_class instead of
rs6000_cannot_change_mode_class_ptr.
(rs6000_cannot_change_mode_class): Replace with...
(rs6000_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(rs6000_debug_cannot_change_mode_class): Replace with...
(rs6000_debug_can_change_mode_class): ...this new function.
* config/riscv/riscv.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/riscv/riscv.c (riscv_can_change_mode_class): New function.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/rs6000/rs6000.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/rs6000/rs6000-protos.h (rs6000_cannot_change_mode_class_ptr):
Delete.
* config/rs6000/rs6000.c (rs6000_cannot_change_mode_class_ptr): Delete.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(rs6000_option_override_internal): Assign to
targetm.can_change_mode_class instead of
rs6000_cannot_change_mode_class_ptr.
(rs6000_cannot_change_mode_class): Replace with...
(rs6000_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(rs6000_debug_cannot_change_mode_class): Replace with...
(rs6000_debug_can_change_mode_class): ...this new function.
* config/s390/s390.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/s390/s390-protos.h (s390_cannot_change_mode_class): Delete.
* config/s390/s390.c (s390_cannot_change_mode_class): Replace with...
(s390_can_change_mode_class): ...this new function, inverting the
sense of the return value.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/sh/sh.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/sh/sh-protos.h (sh_cannot_change_mode_class): Delete.
* config/sh/sh.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(sh_cannot_change_mode_class): Replace with...
(sh_can_change_mode_class): ...this new function, inverting the
sense of the return value.
* config/sparc/sparc.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/sparc/sparc.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(sparc_can_change_mode_class): New function.
* config/spu/spu.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/spu/spu.c (spu_can_change_mode_class): New function.
(TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
* config/visium/visium.h (CANNOT_CHANGE_MODE_CLASS): Delete.
* config/visium/visium.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
(visium_can_change_mode_class): New function.
* system.h (CANNOT_CHANGE_MODE_CLASS): Poison.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r252816

64 files changed:
gcc/ChangeLog
gcc/combine.c
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/neon.md
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.h
gcc/config/m32c/m32c-protos.h
gcc/config/m32c/m32c.c
gcc/config/m32c/m32c.h
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/msp430/msp430.c
gcc/config/msp430/msp430.h
gcc/config/nvptx/nvptx.c
gcc/config/nvptx/nvptx.h
gcc/config/pa/pa-protos.h
gcc/config/pa/pa.c
gcc/config/pa/pa32-regs.h
gcc/config/pa/pa64-regs.h
gcc/config/pdp11/pdp11-protos.h
gcc/config/pdp11/pdp11.c
gcc/config/pdp11/pdp11.h
gcc/config/powerpcspe/powerpcspe-protos.h
gcc/config/powerpcspe/powerpcspe.c
gcc/config/powerpcspe/powerpcspe.h
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.h
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/spu/spu.c
gcc/config/spu/spu.h
gcc/config/visium/visium.c
gcc/config/visium/visium.h
gcc/doc/rtl.texi
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/emit-rtl.c
gcc/hard-reg-set.h
gcc/hooks.c
gcc/hooks.h
gcc/postreload.c
gcc/recog.c
gcc/regcprop.c
gcc/reload.c
gcc/reload1.c
gcc/rtlanal.c
gcc/system.h
gcc/target.def

index 65bfc163f5a5ce896315989e6561f72a0d3d68d3..fa5f73476243b122dc4ea450e20627fa874268e2 100644 (file)
@@ -1,3 +1,137 @@
+2017-09-15  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayard  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * target.def (can_change_mode_class): New hook.
+       (mode_rep_extended): Refer to it instead of CANNOT_CHANGE_MODE_CLASS.
+       (hard_regno_nregs): Likewise.
+       * hooks.h (hook_bool_mode_mode_reg_class_t_true): Declare.
+       * hooks.c (hook_bool_mode_mode_reg_class_t_true): New function.
+       * doc/tm.texi.in (CANNOT_CHANGE_MODE_CLASS): Replace with...
+       (TARGET_CAN_CHANGE_MODE_CLASS): ...this.
+       (LOAD_EXTEND_OP): Update accordingly.
+       * doc/tm.texi: Regenerate.
+       * doc/rtl.texi: Refer to TARGET_CAN_CHANGE_MODE_CLASS instead of
+       CANNOT_CHANGE_MODE_CLASS.
+       * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Replace with...
+       (REG_CAN_CHANGE_MODE_P): ...this new macro.
+       * combine.c (simplify_set): Update accordingly.
+       * emit-rtl.c (validate_subreg): Likewise.
+       * recog.c (general_operand): Likewise.
+       * regcprop.c (mode_change_ok): Likewise.
+       * reload1.c (choose_reload_regs): Likewise.
+       (inherit_piecemeal_p): Likewise.
+       * rtlanal.c (simplify_subreg_regno): Likewise.
+       * postreload.c (reload_cse_simplify_set): Use REG_CAN_CHANGE_MODE_P
+       instead of CANNOT_CHANGE_MODE_CLASS.
+       (reload_cse_simplify_operands): Likewise.
+       * reload.c (push_reload): Use targetm.can_change_mode_class
+       instead of CANNOT_CHANGE_MODE_CLASS.
+       (push_reload): Likewise.  Also use REG_CAN_CHANGE_MODE_P instead of
+       REG_CANNOT_CHANGE_MODE_P.
+       * config/alpha/alpha.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/alpha/alpha.c (alpha_can_change_mode_class): New function.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/arm/arm.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/arm/arm.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (arm_can_change_mode_class): New function.
+       * config/arm/neon.md: Refer to TARGET_CAN_CHANGE_MODE_CLASS rather
+       than CANNOT_CHANGE_MODE_CLASS in comments.
+       * config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/i386/i386-protos.h (ix86_cannot_change_mode_class): Delete.
+       * config/i386/i386.c (ix86_cannot_change_mode_class): Replace with...
+       (ix86_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/ia64/ia64.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/ia64/ia64.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (ia64_can_change_mode_class): New function.
+       * config/m32c/m32c.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/m32c/m32c-protos.h (m32c_cannot_change_mode_class): Delete.
+       * config/m32c/m32c.c (m32c_cannot_change_mode_class): Replace with...
+       (m32c_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/mips/mips.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/mips/mips-protos.h (mips_cannot_change_mode_class): Delete.
+       * config/mips/mips.c (mips_cannot_change_mode_class): Replace with...
+       (mips_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/msp430/msp430.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/msp430/msp430.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (msp430_can_change_mode_class): New function.
+       * config/nvptx/nvptx.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/nvptx/nvptx.c (nvptx_can_change_mode_class): New function.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/pa/pa32-regs.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/pa/pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/pa/pa-protos.h (pa_cannot_change_mode_class): Delete.
+       * config/pa/pa.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (pa_cannot_change_mode_class): Replace with...
+       (pa_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (pa_modes_tieable_p): Refer to TARGET_CAN_CHANGE_MODE_CLASS rather
+       than CANNOT_CHANGE_MODE_CLASS in comments.
+       * config/pdp11/pdp11.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class): Delete.
+       * config/pdp11/pdp11.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (pdp11_cannot_change_mode_class): Replace with...
+       (pdp11_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       * config/powerpcspe/powerpcspe.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/powerpcspe/powerpcspe-protos.h
+       (rs6000_cannot_change_mode_class_ptr): Delete.
+       * config/powerpcspe/powerpcspe.c
+       (rs6000_cannot_change_mode_class_ptr): Delete.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (rs6000_option_override_internal): Assign to
+       targetm.can_change_mode_class instead of
+       rs6000_cannot_change_mode_class_ptr.
+       (rs6000_cannot_change_mode_class): Replace with...
+       (rs6000_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (rs6000_debug_cannot_change_mode_class): Replace with...
+       (rs6000_debug_can_change_mode_class): ...this new function.
+       * config/riscv/riscv.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/riscv/riscv.c (riscv_can_change_mode_class): New function.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/rs6000/rs6000.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/rs6000/rs6000-protos.h (rs6000_cannot_change_mode_class_ptr):
+       Delete.
+       * config/rs6000/rs6000.c (rs6000_cannot_change_mode_class_ptr): Delete.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (rs6000_option_override_internal): Assign to
+       targetm.can_change_mode_class instead of
+       rs6000_cannot_change_mode_class_ptr.
+       (rs6000_cannot_change_mode_class): Replace with...
+       (rs6000_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (rs6000_debug_cannot_change_mode_class): Replace with...
+       (rs6000_debug_can_change_mode_class): ...this new function.
+       * config/s390/s390.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/s390/s390-protos.h (s390_cannot_change_mode_class): Delete.
+       * config/s390/s390.c (s390_cannot_change_mode_class): Replace with...
+       (s390_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/sh/sh.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/sh/sh-protos.h (sh_cannot_change_mode_class): Delete.
+       * config/sh/sh.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (sh_cannot_change_mode_class): Replace with...
+       (sh_can_change_mode_class): ...this new function, inverting the
+       sense of the return value.
+       * config/sparc/sparc.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/sparc/sparc.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (sparc_can_change_mode_class): New function.
+       * config/spu/spu.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/spu/spu.c (spu_can_change_mode_class): New function.
+       (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       * config/visium/visium.h (CANNOT_CHANGE_MODE_CLASS): Delete.
+       * config/visium/visium.c (TARGET_CAN_CHANGE_MODE_CLASS): Redefine.
+       (visium_can_change_mode_class): New function.
+       * system.h (CANNOT_CHANGE_MODE_CLASS): Poison.
+
 2017-09-15  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/82217
index 1832c3cb2bca0c1caa115a9761263090efccf538..affc1489ebec1d8b856aa32e7f479a2a0ba47b5d 100644 (file)
@@ -6869,12 +6869,10 @@ simplify_set (rtx x)
          == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
               + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
       && (WORD_REGISTER_OPERATIONS || !paradoxical_subreg_p (src))
-#ifdef CANNOT_CHANGE_MODE_CLASS
       && ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER
-           && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
-                                        GET_MODE (SUBREG_REG (src)),
-                                        GET_MODE (src)))
-#endif
+           && !REG_CAN_CHANGE_MODE_P (REGNO (dest),
+                                      GET_MODE (SUBREG_REG (src)),
+                                      GET_MODE (src)))
       && (REG_P (dest)
          || (GET_CODE (dest) == SUBREG
              && REG_P (SUBREG_REG (dest)))))
index bb81f8e5f61d18a4aa0cc1d2b6562215133a0fcb..e0f458c9109727d6541eae168ba2efe2bf3c3784 100644 (file)
@@ -9936,6 +9936,16 @@ alpha_modes_tieable_p (machine_mode mode1, machine_mode mode2)
          ? alpha_hard_regno_mode_ok (32, mode2)
          : true);
 }
+
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
+
+static bool
+alpha_can_change_mode_class (machine_mode from, machine_mode to,
+                            reg_class_t rclass)
+{
+  return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
+         || !reg_classes_intersect_p (FLOAT_REGS, rclass));
+}
 \f
 /* Initialize the GCC target structure.  */
 #if TARGET_ABI_OPEN_VMS
@@ -10140,6 +10150,9 @@ alpha_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P alpha_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS alpha_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 \f
index e42b64985e8692c93e3c205a55fafa20768f07af..6177020605aaffcb1b9a89e115eecc93411d833b 100644 (file)
@@ -479,12 +479,6 @@ enum reg_class {
 
 #define PREFERRED_RELOAD_CLASS  alpha_preferred_reload_class
 
-/* Return the class of registers that cannot change mode from FROM to TO.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)              \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)                  \
-   ? reg_classes_intersect_p (FLOAT_REGS, CLASS) : 0)
-
 /* Provide the cost of a branch.  Exact meaning under development.  */
 #define BRANCH_COST(speed_p, predictable_p) 5
 \f
index c8c43011206ba75433b7e3338ed07287b418c5c4..bc802adc3e33cff4a4ee6cf918d4ab396e16468a 100644 (file)
@@ -793,6 +793,9 @@ static const struct attribute_spec arm_attribute_table[] =
 
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P arm_modes_tieable_p
+
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS arm_can_change_mode_class
 \f
 /* Obstack for minipool constant handling.  */
 static struct obstack minipool_obstack;
@@ -31243,6 +31246,33 @@ arm_coproc_ldc_stc_legitimate_address (rtx op)
   return false;
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
+
+   In VFPv1, VFP registers could only be accessed in the mode they were
+   set, so subregs would be invalid there.  However, we don't support
+   VFPv1 at the moment, and the restriction was lifted in VFPv2.
+
+   In big-endian mode, modes greater than word size (i.e. DFmode) are stored in
+   VFP registers in little-endian order.  We can't describe that accurately to
+   GCC, so avoid taking subregs of such values.
+
+   The only exception is going from a 128-bit to a 64-bit type.  In that
+   case the data layout happens to be consistent for big-endian, so we
+   explicitly allow that case.  */
+
+static bool
+arm_can_change_mode_class (machine_mode from, machine_mode to,
+                          reg_class_t rclass)
+{
+  if (TARGET_BIG_END
+      && !(GET_MODE_SIZE (from) == 16 && GET_MODE_SIZE (to) == 8)
+      && (GET_MODE_SIZE (from) > UNITS_PER_WORD
+         || GET_MODE_SIZE (to) > UNITS_PER_WORD)
+      && reg_classes_intersect_p (VFP_REGS, rclass))
+    return false;
+  return true;
+}
+
 #if CHECKING_P
 namespace selftest {
 
index e8f32f19774564b12c5e307e235d2f56210591aa..1dc136110d53214fbdabf54eb5656aa9737f0cae 100644 (file)
@@ -1152,23 +1152,6 @@ enum reg_class
    or could index an array.  */
 #define REGNO_REG_CLASS(REGNO)  arm_regno_class (REGNO)
 
-/* In VFPv1, VFP registers could only be accessed in the mode they
-   were set, so subregs would be invalid there.  However, we don't
-   support VFPv1 at the moment, and the restriction was lifted in
-   VFPv2.
-   In big-endian mode, modes greater than word size (i.e. DFmode) are stored in
-   VFP registers in little-endian order.  We can't describe that accurately to
-   GCC, so avoid taking subregs of such values.
-   The only exception is going from a 128-bit to a 64-bit type.  In that case
-   the data layout happens to be consistent for big-endian, so we explicitly allow
-   that case.  */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)              \
-  (TARGET_BIG_END                                              \
-   && !(GET_MODE_SIZE (FROM) == 16 && GET_MODE_SIZE (TO) == 8) \
-   && (GET_MODE_SIZE (FROM) > UNITS_PER_WORD                   \
-       || GET_MODE_SIZE (TO) > UNITS_PER_WORD)                 \
-   && reg_classes_intersect_p (VFP_REGS, (CLASS)))
-
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS  (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS)
 #define BASE_REG_CLASS   (TARGET_THUMB1 ? LO_REGS : CORE_REGS)
index 9213c1ef788ffd8ff7d09238d5cee4ec36600c0f..12ba2d98a0ae0517465dd61cefe8e59011508a88 100644 (file)
        (match_operand:V4HF 1 "s_register_operand"))]
   "TARGET_NEON && TARGET_FP16"
 {
-  /* We need to use force_reg to avoid CANNOT_CHANGE_MODE_CLASS
+  /* We need to use force_reg to avoid TARGET_CAN_CHANGE_MODE_CLASS
      causing an ICE on big-endian because it cannot extract subregs in
      this case.  */
   if (can_create_pseudo_p ())
        (match_operand:V8HF 1 ""))]
   "TARGET_NEON && TARGET_FP16"
 { 
-  /* We need to use force_reg to avoid CANNOT_CHANGE_MODE_CLASS
+  /* We need to use force_reg to avoid TARGET_CAN_CHANGE_MODE_CLASS
      causing an ICE on big-endian because it cannot extract subregs in
      this case.  */
   if (can_create_pseudo_p ())
index ecb0a4c9682e7978df09baae169080b9eda8fc9e..4df6274add2e55fb6c5580f8dd4de4fa89caaef3 100644 (file)
@@ -167,8 +167,6 @@ extern int ix86_reg_parm_stack_space (const_tree);
 
 extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
                                  rtx, rtx, rtx);
-extern bool ix86_cannot_change_mode_class (machine_mode,
-                                          machine_mode, enum reg_class);
 
 extern bool ix86_libc_has_function (enum function_class fn_class);
 
index b2b02acc58ad1387f8d0128d3e2cc36136d7d656..fa79762a9229999d1b9b3dcc418cfa9923405ae2 100644 (file)
@@ -41204,20 +41204,19 @@ ix86_class_max_nregs (reg_class_t rclass, machine_mode mode)
     }
 }
 
-/* Return true if the registers in CLASS cannot represent the change from
-   modes FROM to TO.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
-bool
-ix86_cannot_change_mode_class (machine_mode from, machine_mode to,
-                              enum reg_class regclass)
+static bool
+ix86_can_change_mode_class (machine_mode from, machine_mode to,
+                           reg_class_t regclass)
 {
   if (from == to)
-    return false;
+    return true;
 
   /* x87 registers can't do subreg at all, as all values are reformatted
      to extended precision.  */
   if (MAYBE_FLOAT_CLASS_P (regclass))
-    return true;
+    return false;
 
   if (MAYBE_SSE_CLASS_P (regclass) || MAYBE_MMX_CLASS_P (regclass))
     {
@@ -41226,10 +41225,10 @@ ix86_cannot_change_mode_class (machine_mode from, machine_mode to,
         drop the subreg from (subreg:SI (reg:HI 100) 0).  This affects
         the vec_dupv4hi pattern.  */
       if (GET_MODE_SIZE (from) < 4)
-       return true;
+       return false;
     }
 
-  return false;
+  return true;
 }
 
 /* Return the cost of moving data of mode M between a
@@ -53434,6 +53433,9 @@ ix86_run_selftests (void)
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   ix86_hard_regno_call_part_clobbered
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS ix86_can_change_mode_class
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
index cbd6a111f57054b1ca3bcad7b06c411405de1306..2f5ed83c89e637c25559b3c6b39377c3b108f709 100644 (file)
@@ -1518,11 +1518,6 @@ enum reg_class
 
 #define INDEX_REG_CLASS INDEX_REGS
 #define BASE_REG_CLASS GENERAL_REGS
-
-/* Return a class of registers that cannot change FROM mode to TO mode.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  ix86_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index b9b85a019258cb6b86072cf27dab109026b7eb7a..b4d63592ea0e0f3738b92c74a8d56b5052d117ce 100644 (file)
@@ -339,6 +339,8 @@ static bool ia64_vectorize_vec_perm_const_ok (machine_mode vmode,
 static unsigned int ia64_hard_regno_nregs (unsigned int, machine_mode);
 static bool ia64_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool ia64_modes_tieable_p (machine_mode, machine_mode);
+static bool ia64_can_change_mode_class (machine_mode, machine_mode,
+                                       reg_class_t);
 
 #define MAX_VECT_LEN   8
 
@@ -668,6 +670,9 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P ia64_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS ia64_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain
@@ -11908,4 +11913,21 @@ ia64_expand_vec_perm_even_odd (rtx target, rtx op0, rtx op1, int odd)
   gcc_assert (ok);
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
+
+   In BR regs, we can't change the DImode at all.
+   In FP regs, we can't change FP values to integer values and vice versa,
+   but we can change e.g. DImode to SImode, and V2SFmode into DImode.  */
+
+static bool
+ia64_can_change_mode_class (machine_mode from, machine_mode to,
+                           reg_class_t rclass)
+{
+  if (reg_classes_intersect_p (rclass, BR_REGS))
+    return from == to;
+  if (SCALAR_FLOAT_MODE_P (from) != SCALAR_FLOAT_MODE_P (to))
+    return !reg_classes_intersect_p (rclass, FR_REGS);
+  return true;
+}
+
 #include "gt-ia64.h"
index 7eefa444a21a89e618b3d3100c3b8aa76557e68d..b08824f2ccd6fc7e2ca98ad102f5f900d834bcfb 100644 (file)
@@ -777,17 +777,6 @@ enum reg_class
    : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == RFmode) ? 1 \
    : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XCmode) ? 2 \
    : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* In BR regs, we can't change the DImode at all.
-   In FP regs, we can't change FP values to integer values and vice versa,
-   but we can change e.g. DImode to SImode, and V2SFmode into DImode.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)              \
-  (reg_classes_intersect_p (CLASS, BR_REGS)                    \
-   ? (FROM) != (TO)                                            \
-   : (SCALAR_FLOAT_MODE_P (FROM) != SCALAR_FLOAT_MODE_P (TO)   \
-      ? reg_classes_intersect_p (CLASS, FR_REGS)               \
-      : 0))
 \f
 /* Basic Stack Layout */
 
index 1c6465a91c47ec432844dff5131d7b48eab16096..8647a208420e48e8b816f22b5fc6fa50dbd7634b 100644 (file)
@@ -38,7 +38,6 @@ int  m32c_trampoline_size (void);
 
 #ifdef RTX_CODE
 
-int  m32c_cannot_change_mode_class (machine_mode, machine_mode, int);
 rtx  m32c_eh_return_stackadj_rtx (void);
 void m32c_emit_eh_epilogue (rtx);
 int  m32c_expand_cmpstr (rtx *);
index 168489ed4e79f03abb85f6b971b15e371b0ccda0..5987513e97d144d196acd114971ce02c52522e59 100644 (file)
@@ -799,17 +799,17 @@ m32c_class_max_nregs (reg_class_t regclass, machine_mode mode)
   return max;
 }
 
-/* Implements CANNOT_CHANGE_MODE_CLASS.  Only r0 and r1 can change to
+/* Implements TARGET_CAN_CHANGE_MODE_CLASS.  Only r0 and r1 can change to
    QI (r0l, r1l) because the chip doesn't support QI ops on other
    registers (well, it does on a0/a1 but if we let gcc do that, reload
    suffers).  Otherwise, we allow changes to larger modes.  */
-int
-m32c_cannot_change_mode_class (machine_mode from,
-                              machine_mode to, int rclass)
+static bool
+m32c_can_change_mode_class (machine_mode from,
+                           machine_mode to, reg_class_t rclass)
 {
   int rn;
 #if DEBUG0
-  fprintf (stderr, "cannot change from %s to %s in %s\n",
+  fprintf (stderr, "can change from %s to %s in %s\n",
           mode_name[from], mode_name[to], class_names[rclass]);
 #endif
 
@@ -818,18 +818,18 @@ m32c_cannot_change_mode_class (machine_mode from,
   for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
     if (class_contents[rclass][0] & (1 << rn))
       if (! m32c_hard_regno_mode_ok (rn, to))
-       return 1;
+       return false;
 
   if (to == QImode)
-    return (class_contents[rclass][0] & 0x1ffa);
+    return (class_contents[rclass][0] & 0x1ffa) == 0;
 
   if (class_contents[rclass][0] & 0x0005       /* r0, r1 */
       && GET_MODE_SIZE (from) > 1)
-    return 0;
+    return true;
   if (GET_MODE_SIZE (from) > 2)        /* all other regs */
-    return 0;
+    return true;
 
-  return 1;
+  return false;
 }
 
 /* Helpers for the rest of the file.  */
@@ -4496,6 +4496,9 @@ m32c_output_compare (rtx_insn *insn, rtx *operands)
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P m32c_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS m32c_can_change_mode_class
+
 /* The Global `targetm' Variable. */
 
 struct gcc_target targetm = TARGET_INITIALIZER;
index 231eff341140ee364cf5871035003851ae02ac1f..c4c0da088236ae554c64823a018c502d25cec7b7 100644 (file)
@@ -411,8 +411,6 @@ enum reg_class
 
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
-#define CANNOT_CHANGE_MODE_CLASS(F,T,C) m32c_cannot_change_mode_class(F,T,C)
-
 /* STACK AND CALLING */
 
 /* Frame Layout */
index d487f6f93ee41c6b149a4bfe615f2aa11422a979..1c4167a836a8886dd4f4538d3004747fd0c3150d 100644 (file)
@@ -294,8 +294,6 @@ extern bool mips_const_vector_bitimm_set_p (rtx, machine_mode);
 extern bool mips_const_vector_bitimm_clr_p (rtx, machine_mode);
 extern rtx mips_msa_vec_parallel_const_half (machine_mode, bool);
 extern rtx mips_gen_const_int_vector (machine_mode, HOST_WIDE_INT);
-extern bool mips_cannot_change_mode_class (machine_mode,
-                                          machine_mode, enum reg_class);
 extern bool mips_dangerous_for_la25_p (rtx);
 extern enum reg_class mips_secondary_reload_class (enum reg_class,
                                                   machine_mode,
index 20051a7e291b36a3b83e2e51d06237ea56713bc2..2af93d73142ad7dc43d4cfe2204c52e8ea8115e7 100644 (file)
@@ -12945,22 +12945,21 @@ mips_class_max_nregs (enum reg_class rclass, machine_mode mode)
   return (GET_MODE_SIZE (mode) + size - 1) / size;
 }
 
-/* Implement CANNOT_CHANGE_MODE_CLASS.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
-bool
-mips_cannot_change_mode_class (machine_mode from,
-                              machine_mode to,
-                              enum reg_class rclass)
+static bool
+mips_can_change_mode_class (machine_mode from,
+                           machine_mode to, reg_class_t rclass)
 {
   /* Allow conversions between different Loongson integer vectors,
      and between those vectors and DImode.  */
   if (GET_MODE_SIZE (from) == 8 && GET_MODE_SIZE (to) == 8
       && INTEGRAL_MODE_P (from) && INTEGRAL_MODE_P (to))
-    return false;
+    return true;
 
   /* Allow conversions between different MSA vector modes.  */
   if (MSA_SUPPORTED_MODE_P (from) && MSA_SUPPORTED_MODE_P (to))
-    return false;
+    return true;
 
   /* Otherwise, there are several problems with changing the modes of
      values in floating-point registers:
@@ -12985,7 +12984,7 @@ mips_cannot_change_mode_class (machine_mode from,
 
      We therefore disallow all mode changes involving FPRs.  */
 
-  return reg_classes_intersect_p (FP_REGS, rclass);
+  return !reg_classes_intersect_p (FP_REGS, rclass);
 }
 
 /* Implement target hook small_register_classes_for_mode_p.  */
@@ -22621,6 +22620,9 @@ mips_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
 #undef TARGET_SECONDARY_MEMORY_NEEDED
 #define TARGET_SECONDARY_MEMORY_NEEDED mips_secondary_memory_needed
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS mips_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 #include "gt-mips.h"
index 1a54dc624b16781e8acda5f7f510fe3c06426c08..991bd8d5049d005928265abe08d396b8778cbe03 100644 (file)
@@ -2302,9 +2302,6 @@ enum reg_class
    needed to represent mode MODE in a register of class CLASS.  */
 
 #define CLASS_MAX_NREGS(CLASS, MODE) mips_class_max_nregs (CLASS, MODE)
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  mips_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index 535d4baf6763d89d2c41156def438578c600d744..80ea1190fbaac9713e2f4deef9ccab21e43dbc8b 100644 (file)
@@ -3812,6 +3812,22 @@ msp430x_logical_shift_right (rtx amount)
      right shift instruction to perform the rest of the shift.  */
   return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes.  */
 }
+
+/* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)).  */
+
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
+
+static bool
+msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
+{
+  if ((to == PSImode && from == SImode)
+      || (to == SImode && from == PSImode)
+      || (to == DImode && from == PSImode)
+      || (to == PSImode && from == DImode))
+    return false;
+  return true;
+}
 \f
 struct gcc_target targetm = TARGET_INITIALIZER;
 
index edc416cc1d0a84168f52c90b23690870dd56c5a2..8494bf29acd5a9a16c8835cad38b806ed387e0f7 100644 (file)
@@ -407,14 +407,6 @@ typedef struct
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO,NREGS,MODE) \
   ((TARGET_LARGE && ((NREGS) <= 2)) ? PSImode : choose_hard_reg_mode ((REGNO), (NREGS), false))
 
-/* Also stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)).  */
-#define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
-  (   ((TO) == PSImode && (FROM) == SImode)    \
-   || ((TO) == SImode  && (FROM) == PSImode)    \
-   || ((TO) == DImode  && (FROM) == PSImode)    \
-   || ((TO) == PSImode && (FROM) == DImode)     \
-      )
-
 #define ACCUMULATE_OUTGOING_ARGS 1
 
 #undef  ASM_DECLARE_FUNCTION_NAME
index cc34271e52a39a58eac0324b89a979ef2e9c6f15..6cf9a6627631c1facc49fd785cb6e7de678e5d63 100644 (file)
@@ -5529,6 +5529,14 @@ nvptx_hard_regno_nregs (unsigned int, machine_mode)
   return 1;
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
+
+static bool
+nvptx_can_change_mode_class (machine_mode, machine_mode, reg_class_t)
+{
+  return false;
+}
+
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE nvptx_option_override
 
@@ -5659,6 +5667,9 @@ nvptx_hard_regno_nregs (unsigned int, machine_mode)
 #undef TARGET_HARD_REGNO_NREGS
 #define TARGET_HARD_REGNO_NREGS nvptx_hard_regno_nregs
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS nvptx_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-nvptx.h"
index 8fccbc72aaf11176248428f155c74936f0862532..ab00e472ceb29508d34f4a3aebedbe8b524e0795 100644 (file)
@@ -95,9 +95,6 @@
 #define FIXED_REGISTERS            { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 #define CALL_USED_REGISTERS { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
 
-#define CANNOT_CHANGE_MODE_CLASS(M1, M2, CLS)  \
-  ((void)(M1), (void)(M2), (void)(CLS), true)
-
 /* Register Classes.  */
 enum reg_class             {  NO_REGS,    ALL_REGS,    LIM_REG_CLASSES };
 #define REG_CLASS_NAMES    { "NO_REGS",  "ALL_REGS" }
index ba496f966d55f10c9e7eb1d132e76a137b006060..cbf25af19c89ec14cb99a8f8e8bfe46c2051ae5f 100644 (file)
@@ -106,8 +106,6 @@ extern void pa_asm_output_aligned_local (FILE *, const char *,
                                         unsigned HOST_WIDE_INT,
                                         unsigned int);
 extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
-extern bool pa_cannot_change_mode_class (machine_mode, machine_mode,
-                                        enum reg_class);
 extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
 
 extern const int pa_magic_milli[];
index f39b6721d2440c1e3e2c7476f1eec8d1be2f7eb9..651ae59378d4ed34255ab086d2f2a9addfc02b7d 100644 (file)
@@ -204,6 +204,7 @@ static bool pa_callee_copies (cumulative_args_t, machine_mode,
 static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
 static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool pa_modes_tieable_p (machine_mode, machine_mode);
+static bool pa_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -421,6 +422,9 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P pa_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS pa_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Parse the -mfixed-range= option string.  */
@@ -10001,27 +10005,26 @@ pa_hpux_file_end (void)
 }
 #endif
 
-/* Return true if a change from mode FROM to mode TO for a register
-   in register class RCLASS is invalid.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
-bool
-pa_cannot_change_mode_class (machine_mode from, machine_mode to,
-                            enum reg_class rclass)
+static bool
+pa_can_change_mode_class (machine_mode from, machine_mode to,
+                         reg_class_t rclass)
 {
   if (from == to)
-    return false;
+    return true;
 
   if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to))
-    return false;
+    return true;
 
   /* Reject changes to/from modes with zero size.  */
   if (!GET_MODE_SIZE (from) || !GET_MODE_SIZE (to))
-    return true;
+    return false;
 
   /* Reject changes to/from complex and vector modes.  */
   if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from)
       || COMPLEX_MODE_P (to) || VECTOR_MODE_P (to))
-    return true;
+    return false;
       
   /* There is no way to load QImode or HImode values directly from memory
      to a FP register.  SImode loads to the FP registers are not zero
@@ -10029,16 +10032,16 @@ pa_cannot_change_mode_class (machine_mode from, machine_mode to,
      of LOAD_EXTEND_OP.  Thus, we can't allow changing between modes with
      different sizes in the floating-point registers.  */
   if (MAYBE_FP_REG_CLASS_P (rclass))
-    return true;
+    return false;
 
   /* TARGET_HARD_REGNO_MODE_OK places modes with sizes larger than a word
      in specific sets of registers.  Thus, we cannot allow changing
      to a larger mode when it's larger than a word.  */
   if (GET_MODE_SIZE (to) > UNITS_PER_WORD
       && GET_MODE_SIZE (to) > GET_MODE_SIZE (from))
-    return true;
+    return false;
 
-  return false;
+  return true;
 }
 
 /* Implement TARGET_MODES_TIEABLE_P.
@@ -10047,7 +10050,7 @@ pa_cannot_change_mode_class (machine_mode from, machine_mode to,
    are not ok in the floating-point registers.  However, this prevents
    tieing these modes to SImode and DImode in the general registers.
    So, this isn't a good idea.  We rely on TARGET_HARD_REGNO_MODE_OK and
-   CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
+   TARGET_CAN_CHANGE_MODE_CLASS to prevent these modes from being used
    in the floating-point registers.  */
 
 static bool
index f168ecfeab3e80367db4968c9093d12eaf4580a8..d479b1aee7ebb3ca90d9d66e0608735c6e428415 100644 (file)
@@ -294,11 +294,6 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
   {0x00000000, 0x00000000, 0x01000000},        /* SHIFT_REGS */                \
   {0xfffffffe, 0xffffffff, 0x03ffffff}}        /* ALL_REGS */
 
-/* Defines invalid mode changes.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  pa_cannot_change_mode_class (FROM, TO, CLASS)
-
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
index 15b88089e9a1d9c3b61f34ed9f2249a4a5938f30..d9c8dd419e7cc7833f2f9af41229e3bf38712f5b 100644 (file)
@@ -230,11 +230,6 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
   {0x00000000, 0x10000000},    /* SHIFT_REGS */                \
   {0xfffffffe, 0x3fffffff}}    /* ALL_REGS */
 
-/* Defines invalid mode changes.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  pa_cannot_change_mode_class (FROM, TO, CLASS)
-
 /* Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
index 2fe138634e65b71c5888afe9beda2485cbc278c0..f6c7d1a7f1b651d864786a6b2d8f66093b3d4e47 100644 (file)
@@ -29,8 +29,6 @@ extern const char *output_move_multiple (rtx *);
 extern const char *output_block_move (rtx *);
 extern const char *output_jump (enum rtx_code, int, int);
 extern void print_operand_address (FILE *, rtx);
-extern bool pdp11_cannot_change_mode_class (machine_mode,
-                                            machine_mode, enum reg_class);
 typedef enum { no_action, dec_before, inc_after } pdp11_action;
 typedef enum { little, either, big } pdp11_partorder;
 extern bool pdp11_expand_operands (rtx *, rtx [][2], int, 
index 5364b47451cfb5da4c0b10310784a60ed4b87f66..4fdb077479d5cab55656c28c90c62c1b7d1167ae 100644 (file)
@@ -246,6 +246,9 @@ static bool pdp11_scalar_mode_supported_p (scalar_mode);
 
 #undef  TARGET_SECONDARY_MEMORY_NEEDED
 #define TARGET_SECONDARY_MEMORY_NEEDED pdp11_secondary_memory_needed
+
+#undef  TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS pdp11_can_change_mode_class
 \f
 /* A helper function to determine if REGNO should be saved in the
    current function's stack frame.  */
@@ -1372,20 +1375,20 @@ legitimate_const_double_p (rtx address)
   return 0;
 }
 
-/* Implement CANNOT_CHANGE_MODE_CLASS.  */
-bool
-pdp11_cannot_change_mode_class (machine_mode from,
-                               machine_mode to,
-                               enum reg_class rclass)
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
+static bool
+pdp11_can_change_mode_class (machine_mode from,
+                            machine_mode to,
+                            reg_class_t rclass)
 {
   /* Also, FPU registers contain a whole float value and the parts of
      it are not separately accessible.
 
      So we disallow all mode changes involving FPRs.  */
   if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
-    return true;
+    return false;
   
-  return reg_classes_intersect_p (FPU_REGS, rclass);
+  return !reg_classes_intersect_p (FPU_REGS, rclass);
 }
 
 /* TARGET_PREFERRED_RELOAD_CLASS
index d220697f30b5399ce2cb276190a71ae54c0ebda5..2a59f659156fe71f417326d810ad7c7bb8dfab97 100644 (file)
@@ -243,9 +243,6 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD):      \
   1                                                                    \
 )
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  pdp11_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index c87a6a08bd9c17805f80d8adbebe910e85e08228..78baeecad38f8c87e985f93bed70d11bc78c3111 100644 (file)
@@ -109,9 +109,6 @@ extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
 extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
                                                            machine_mode,
                                                            rtx);
-extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
-                                                   machine_mode,
-                                                   enum reg_class);
 extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
 extern void rs6000_secondary_reload_gpr (rtx, rtx, rtx, bool);
 extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
index 499dc1d694d4c134cf56f32a460d33341d6aa1cd..11664eed4e0e2b72cfb5b6ca7422a343d24ffbd6 100644 (file)
@@ -1387,12 +1387,9 @@ static enum reg_class rs6000_debug_preferred_reload_class (rtx,
 static bool rs6000_debug_secondary_memory_needed (machine_mode,
                                                  reg_class_t,
                                                  reg_class_t);
-static bool rs6000_cannot_change_mode_class (machine_mode,
-                                            machine_mode,
-                                            enum reg_class);
-static bool rs6000_debug_cannot_change_mode_class (machine_mode,
-                                                  machine_mode,
-                                                  enum reg_class);
+static bool rs6000_debug_can_change_mode_class (machine_mode,
+                                               machine_mode,
+                                               reg_class_t);
 static bool rs6000_save_toc_in_prologue_p (void);
 static rtx rs6000_internal_arg_pointer (void);
 
@@ -1410,11 +1407,6 @@ enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
 enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class)
   = rs6000_preferred_reload_class;
 
-bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
-                                            machine_mode,
-                                            enum reg_class)
-  = rs6000_cannot_change_mode_class;
-
 const int INSN_NOT_AVAILABLE = -1;
 
 static void rs6000_print_isa_options (FILE *, int, const char *,
@@ -1989,6 +1981,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 
 #undef TARGET_SLOW_UNALIGNED_ACCESS
 #define TARGET_SLOW_UNALIGNED_ACCESS rs6000_slow_unaligned_access
+
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS rs6000_can_change_mode_class
 \f
 
 /* Processor table.  */
@@ -5096,8 +5091,8 @@ rs6000_option_override_internal (bool global_init_p)
            = rs6000_debug_secondary_reload_class;
          targetm.secondary_memory_needed
            = rs6000_debug_secondary_memory_needed;
-         rs6000_cannot_change_mode_class_ptr
-           = rs6000_debug_cannot_change_mode_class;
+         targetm.can_change_mode_class
+           = rs6000_debug_can_change_mode_class;
          rs6000_preferred_reload_class_ptr
            = rs6000_debug_preferred_reload_class;
          rs6000_legitimize_reload_address_ptr
@@ -23297,12 +23292,12 @@ rs6000_debug_secondary_reload_class (enum reg_class rclass,
   return ret;
 }
 
-/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
 static bool
-rs6000_cannot_change_mode_class (machine_mode from,
-                                machine_mode to,
-                                enum reg_class rclass)
+rs6000_can_change_mode_class (machine_mode from,
+                             machine_mode to,
+                             reg_class_t rclass)
 {
   unsigned from_size = GET_MODE_SIZE (from);
   unsigned to_size = GET_MODE_SIZE (to);
@@ -23326,31 +23321,31 @@ rs6000_cannot_change_mode_class (machine_mode from,
             values.  */
 
          if (to_float128_vector_p && from_float128_vector_p)
-           return false;
+           return true;
 
          else if (to_float128_vector_p || from_float128_vector_p)
-           return true;
+           return false;
 
          /* TDmode in floating-mode registers must always go into a register
             pair with the most significant word in the even-numbered register
             to match ISA requirements.  In little-endian mode, this does not
             match subreg numbering, so we cannot allow subregs.  */
          if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
-           return true;
+           return false;
 
          if (from_size < 8 || to_size < 8)
-           return true;
+           return false;
 
          if (from_size == 8 && (8 * to_nregs) != to_size)
-           return true;
+           return false;
 
          if (to_size == 8 && (8 * from_nregs) != from_size)
-           return true;
+           return false;
 
-         return false;
+         return true;
        }
       else
-       return false;
+       return true;
     }
 
   if (TARGET_E500_DOUBLE
@@ -23361,7 +23356,7 @@ rs6000_cannot_change_mode_class (machine_mode from,
          || (((to) == DDmode) + ((from) == DDmode)) == 1
          || (((to) == TDmode) + ((from) == TDmode)) == 1
          || (((to) == DImode) + ((from) == DImode)) == 1))
-    return true;
+    return false;
 
   /* Since the VSX register set includes traditional floating point registers
      and altivec registers, just check for the size being different instead of
@@ -23374,32 +23369,32 @@ rs6000_cannot_change_mode_class (machine_mode from,
       unsigned num_regs = (from_size + 15) / 16;
       if (hard_regno_nregs (FIRST_FPR_REGNO, to) > num_regs
          || hard_regno_nregs (FIRST_FPR_REGNO, from) > num_regs)
-       return true;
+       return false;
 
-      return (from_size != 8 && from_size != 16);
+      return (from_size == 8 || from_size == 16);
     }
 
   if (TARGET_ALTIVEC && rclass == ALTIVEC_REGS
       && (ALTIVEC_VECTOR_MODE (from) + ALTIVEC_VECTOR_MODE (to)) == 1)
-    return true;
+    return false;
 
   if (TARGET_SPE && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1
       && reg_classes_intersect_p (GENERAL_REGS, rclass))
-    return true;
+    return false;
 
-  return false;
+  return true;
 }
 
-/* Debug version of rs6000_cannot_change_mode_class.  */
+/* Debug version of rs6000_can_change_mode_class.  */
 static bool
-rs6000_debug_cannot_change_mode_class (machine_mode from,
-                                      machine_mode to,
-                                      enum reg_class rclass)
+rs6000_debug_can_change_mode_class (machine_mode from,
+                                   machine_mode to,
+                                   reg_class_t rclass)
 {
-  bool ret = rs6000_cannot_change_mode_class (from, to, rclass);
+  bool ret = rs6000_can_change_mode_class (from, to, rclass);
 
   fprintf (stderr,
-          "rs6000_cannot_change_mode_class, return %s, from = %s, "
+          "rs6000_can_change_mode_class, return %s, from = %s, "
           "to = %s, rclass = %s\n",
           ret ? "true" : "false",
           GET_MODE_NAME (from), GET_MODE_NAME (to),
index be3d0e887e8dc51790a8e05d5cd12c18953fd036..4a316615d838c12bf94cf89f9a36a94b1a9ad847 100644 (file)
@@ -1611,11 +1611,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
    registers can hold 128 bits.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
 
-/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                      \
-  rs6000_cannot_change_mode_class_ptr (FROM, TO, CLASS)
-
 /* Stack layout; function entry, exit and calling.  */
 
 /* Define this if pushing a word on the stack
index c6390aaec95f2e95b22724fe84abb3f1503aadbf..42ddac997a600cec9eca79cc18d89c48b4c958f8 100644 (file)
@@ -3987,6 +3987,14 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
   return riscv_slow_unaligned_access_p;
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
+
+static bool
+riscv_can_change_mode_class (machine_mode, machine_mode, reg_class_t rclass)
+{
+  return !reg_classes_intersect_p (FP_REGS, rclass);
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -4131,6 +4139,9 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
 #undef TARGET_SECONDARY_MEMORY_NEEDED
 #define TARGET_SECONDARY_MEMORY_NEEDED riscv_secondary_memory_needed
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS riscv_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
index 0a5ae406605319fbfe324b0d13f67c78d254cae9..53141bcfbe6d56dd8f46eda74c8efd366eeed278 100644 (file)
@@ -456,9 +456,6 @@ enum reg_class
   (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH)      \
    || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
 
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  reg_classes_intersect_p (FP_REGS, CLASS)
-
 /* Stack layout; function entry, exit and calling.  */
 
 #define STACK_GROWS_DOWNWARD 1
index 6e80396b80b9c6a64e15b341477697f738bdb50d..3f86aba947e7d34579b2bcc398fc61416141e142 100644 (file)
@@ -110,9 +110,6 @@ extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
 extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
                                                            machine_mode,
                                                            rtx);
-extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
-                                                   machine_mode,
-                                                   enum reg_class);
 extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
 extern void rs6000_secondary_reload_gpr (rtx, rtx, rtx, bool);
 extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
index 005366b33b841824f186bbdcb14dbb2f32db0335..9058f1fb47ab1fa873ee48f65fe3eeeff65edf6b 100644 (file)
@@ -1392,12 +1392,9 @@ static enum reg_class rs6000_debug_preferred_reload_class (rtx,
 static bool rs6000_debug_secondary_memory_needed (machine_mode,
                                                  reg_class_t,
                                                  reg_class_t);
-static bool rs6000_cannot_change_mode_class (machine_mode,
-                                            machine_mode,
-                                            enum reg_class);
-static bool rs6000_debug_cannot_change_mode_class (machine_mode,
-                                                  machine_mode,
-                                                  enum reg_class);
+static bool rs6000_debug_can_change_mode_class (machine_mode,
+                                               machine_mode,
+                                               reg_class_t);
 static bool rs6000_save_toc_in_prologue_p (void);
 static rtx rs6000_internal_arg_pointer (void);
 
@@ -1415,11 +1412,6 @@ enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
 enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class)
   = rs6000_preferred_reload_class;
 
-bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
-                                            machine_mode,
-                                            enum reg_class)
-  = rs6000_cannot_change_mode_class;
-
 const int INSN_NOT_AVAILABLE = -1;
 
 static void rs6000_print_isa_options (FILE *, int, const char *,
@@ -1979,6 +1971,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 
 #undef TARGET_SLOW_UNALIGNED_ACCESS
 #define TARGET_SLOW_UNALIGNED_ACCESS rs6000_slow_unaligned_access
+
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS rs6000_can_change_mode_class
 \f
 
 /* Processor table.  */
@@ -4715,8 +4710,8 @@ rs6000_option_override_internal (bool global_init_p)
            = rs6000_debug_secondary_reload_class;
          targetm.secondary_memory_needed
            = rs6000_debug_secondary_memory_needed;
-         rs6000_cannot_change_mode_class_ptr
-           = rs6000_debug_cannot_change_mode_class;
+         targetm.can_change_mode_class
+           = rs6000_debug_can_change_mode_class;
          rs6000_preferred_reload_class_ptr
            = rs6000_debug_preferred_reload_class;
          rs6000_legitimize_reload_address_ptr
@@ -20643,12 +20638,12 @@ rs6000_debug_secondary_reload_class (enum reg_class rclass,
   return ret;
 }
 
-/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
 static bool
-rs6000_cannot_change_mode_class (machine_mode from,
-                                machine_mode to,
-                                enum reg_class rclass)
+rs6000_can_change_mode_class (machine_mode from,
+                             machine_mode to,
+                             reg_class_t rclass)
 {
   unsigned from_size = GET_MODE_SIZE (from);
   unsigned to_size = GET_MODE_SIZE (to);
@@ -20672,31 +20667,31 @@ rs6000_cannot_change_mode_class (machine_mode from,
             values.  */
 
          if (to_float128_vector_p && from_float128_vector_p)
-           return false;
+           return true;
 
          else if (to_float128_vector_p || from_float128_vector_p)
-           return true;
+           return false;
 
          /* TDmode in floating-mode registers must always go into a register
             pair with the most significant word in the even-numbered register
             to match ISA requirements.  In little-endian mode, this does not
             match subreg numbering, so we cannot allow subregs.  */
          if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
-           return true;
+           return false;
 
          if (from_size < 8 || to_size < 8)
-           return true;
+           return false;
 
          if (from_size == 8 && (8 * to_nregs) != to_size)
-           return true;
+           return false;
 
          if (to_size == 8 && (8 * from_nregs) != from_size)
-           return true;
+           return false;
 
-         return false;
+         return true;
        }
       else
-       return false;
+       return true;
     }
 
   /* Since the VSX register set includes traditional floating point registers
@@ -20710,28 +20705,28 @@ rs6000_cannot_change_mode_class (machine_mode from,
       unsigned num_regs = (from_size + 15) / 16;
       if (hard_regno_nregs (FIRST_FPR_REGNO, to) > num_regs
          || hard_regno_nregs (FIRST_FPR_REGNO, from) > num_regs)
-       return true;
+       return false;
 
-      return (from_size != 8 && from_size != 16);
+      return (from_size == 8 || from_size == 16);
     }
 
   if (TARGET_ALTIVEC && rclass == ALTIVEC_REGS
       && (ALTIVEC_VECTOR_MODE (from) + ALTIVEC_VECTOR_MODE (to)) == 1)
-    return true;
+    return false;
 
-  return false;
+  return true;
 }
 
-/* Debug version of rs6000_cannot_change_mode_class.  */
+/* Debug version of rs6000_can_change_mode_class.  */
 static bool
-rs6000_debug_cannot_change_mode_class (machine_mode from,
-                                      machine_mode to,
-                                      enum reg_class rclass)
+rs6000_debug_can_change_mode_class (machine_mode from,
+                                   machine_mode to,
+                                   reg_class_t rclass)
 {
-  bool ret = rs6000_cannot_change_mode_class (from, to, rclass);
+  bool ret = rs6000_can_change_mode_class (from, to, rclass);
 
   fprintf (stderr,
-          "rs6000_cannot_change_mode_class, return %s, from = %s, "
+          "rs6000_can_change_mode_class, return %s, from = %s, "
           "to = %s, rclass = %s\n",
           ret ? "true" : "false",
           GET_MODE_NAME (from), GET_MODE_NAME (to),
index edd697154aa5dd159895ec7aaccee5e3d7c32754..3866cb39344f919044ebb4d1d8ea1ffe672ba0c2 100644 (file)
@@ -1515,11 +1515,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
    registers can hold 128 bits.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
 
-/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                      \
-  rs6000_cannot_change_mode_class_ptr (FROM, TO, CLASS)
-
 /* Stack layout; function entry, exit and calling.  */
 
 /* Define this if pushing a word on the stack
index dd6c0c1bf19b9940b6efc942c606c88de68ad0db..84b30704d9e56e8435d74a5ed0b81fbd8cdf269b 100644 (file)
@@ -49,8 +49,6 @@ extern void s390_function_profiler (FILE *, int);
 extern void s390_set_has_landing_pad_p (bool);
 extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
 extern int s390_class_max_nregs (enum reg_class, machine_mode);
-extern int s390_cannot_change_mode_class (machine_mode, machine_mode,
-                                         enum reg_class);
 extern bool s390_function_arg_vector (machine_mode, const_tree);
 #if S390_USE_TARGET_ATTRIBUTE
 extern tree s390_valid_target_attribute_tree (tree args,
index f62d740ec642686dba0c963f78f8800818d906ca..f8cf213901d5ddc0675635e56e1d06ebe4796c8d 100644 (file)
@@ -10630,13 +10630,12 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
   return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
 }
 
-/* Return TRUE if changing mode from FROM to TO should not be allowed
-   for register class CLASS.  */
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
-int
-s390_cannot_change_mode_class (machine_mode from_mode,
-                              machine_mode to_mode,
-                              enum reg_class rclass)
+static bool
+s390_can_change_mode_class (machine_mode from_mode,
+                           machine_mode to_mode,
+                           reg_class_t rclass)
 {
   machine_mode small_mode;
   machine_mode big_mode;
@@ -10646,10 +10645,10 @@ s390_cannot_change_mode_class (machine_mode from_mode,
   if (reg_classes_intersect_p (VEC_REGS, rclass)
       && ((from_mode == V1TFmode && to_mode == TFmode)
          || (from_mode == TFmode && to_mode == V1TFmode)))
-    return 1;
+    return false;
 
   if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode))
-    return 0;
+    return true;
 
   if (GET_MODE_SIZE (from_mode) < GET_MODE_SIZE (to_mode))
     {
@@ -10672,14 +10671,14 @@ s390_cannot_change_mode_class (machine_mode from_mode,
   if (reg_classes_intersect_p (VEC_REGS, rclass)
       && (GET_MODE_SIZE (small_mode) < 8
          || s390_class_max_nregs (VEC_REGS, big_mode) == 1))
-    return 1;
+    return false;
 
   /* Likewise for access registers, since they have only half the
      word size on 64-bit.  */
   if (reg_classes_intersect_p (ACCESS_REGS, rclass))
-    return 1;
+    return false;
 
-  return 0;
+  return true;
 }
 
 /* Return true if we use LRA instead of reload pass.  */
@@ -16115,6 +16114,9 @@ s390_asan_shadow_offset (void)
 #undef TARGET_OPTION_RESTORE
 #define TARGET_OPTION_RESTORE s390_function_specific_restore
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS s390_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-s390.h"
index 09325918da35477a09a70c8c97e51ff69bc87cfd..0f6ea874983e08935a23d0fe4846b282cf20e6f6 100644 (file)
@@ -477,9 +477,6 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
 #define CLASS_MAX_NREGS(CLASS, MODE)                                           \
   s390_class_max_nregs ((CLASS), (MODE))
 
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                      \
-  s390_cannot_change_mode_class ((FROM), (TO), (CLASS))
-
 /* We can reverse a CC mode safely if we know whether it comes from a
    floating point compare or not.  With the vector modes it is encoded
    as part of the mode.
index b52860d18bc1fc4b986b7cd97593867d8c654db4..e98030d31bd7d73fea07e7bfddd2c28e2806790f 100644 (file)
@@ -324,8 +324,6 @@ extern bool sh_cfun_interrupt_handler_p (void);
 extern bool sh_cfun_resbank_handler_p (void);
 extern bool sh_attr_renesas_p (const_tree);
 extern bool sh_cfun_attr_renesas_p (void);
-extern bool sh_cannot_change_mode_class
-             (machine_mode, machine_mode, enum reg_class);
 extern bool sh_small_register_classes_for_mode_p (machine_mode);
 extern void sh_mark_label (rtx, int);
 extern bool check_use_sfunc_addr (rtx_insn *, rtx);
index 22e3939c26e4ca808a5fa5abe99731f7fc3602b7..fa9f9ad17a6cdceaff3260d631d3a6ee21c4b27e 100644 (file)
@@ -325,6 +325,7 @@ static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 static unsigned int sh_hard_regno_nregs (unsigned int, machine_mode);
 static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool sh_modes_tieable_p (machine_mode, machine_mode);
+static bool sh_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
 \f
 static const struct attribute_spec sh_attribute_table[] =
 {
@@ -653,6 +654,9 @@ static const struct attribute_spec sh_attribute_table[] =
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P sh_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS sh_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 
@@ -10628,11 +10632,10 @@ sh_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
   return choose_hard_reg_mode (regno, nregs, false);
 }
 
-/* Return the class of registers for which a mode change from FROM to TO
-   is invalid.  */
-bool
-sh_cannot_change_mode_class (machine_mode from, machine_mode to,
-                            enum reg_class rclass)
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
+static bool
+sh_can_change_mode_class (machine_mode from, machine_mode to,
+                         reg_class_t rclass)
 {
   /* We want to enable the use of SUBREGs as a means to
      VEC_SELECT a single element of a vector.  */
@@ -10642,22 +10645,22 @@ sh_cannot_change_mode_class (machine_mode from, machine_mode to,
      on the stack with displacement addressing, as it happens with -O0.
      Thus we disallow the mode change for -O0.  */
   if (to == SFmode && VECTOR_MODE_P (from) && GET_MODE_INNER (from) == SFmode)
-    return optimize ? (reg_classes_intersect_p (GENERAL_REGS, rclass)) : false;
+    return optimize ? !reg_classes_intersect_p (GENERAL_REGS, rclass) : true;
 
   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 reg_classes_intersect_p (DF_REGS, rclass);
+           return !reg_classes_intersect_p (DF_REGS, rclass);
        }
       else
        {
          if (GET_MODE_SIZE (from) < 8)
-           return reg_classes_intersect_p (DF_REGS, rclass);
+           return !reg_classes_intersect_p (DF_REGS, rclass);
        }
     }
-  return false;
+  return true;
 }
 
 /* Return true if registers in machine mode MODE will likely be
index 56e5021f34e0eb1d68e44a970d887e131bb4595f..f020972931ad1a2849f09d1de2530666abb1470e 100644 (file)
@@ -1087,13 +1087,6 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
    Otherwise we will need at most one register per word.  */
 #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.
-   ??? We need to renumber the internal numbers for the frnn registers
-   when in little endian in order to allow mode size changes.  */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  sh_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index 53689a1ccfa27fb39d4d80997b3640b8c3cd0673..749a7f866cb5c077cc4a5709e2d9dca91cd95859 100644 (file)
@@ -682,7 +682,8 @@ static unsigned int sparc_min_arithmetic_precision (void);
 static unsigned int sparc_hard_regno_nregs (unsigned int, machine_mode);
 static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool sparc_modes_tieable_p (machine_mode, machine_mode);
-
+static bool sparc_can_change_mode_class (machine_mode, machine_mode,
+                                        reg_class_t);
 \f
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
@@ -921,6 +922,9 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P sparc_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS sparc_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return the memory reference contained in X if any, zero otherwise.  */
@@ -13401,4 +13405,26 @@ sparc_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
     = compound_expr (compound_expr (update_stfsr, update_ldfsr), update_call);
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  Borrowed from the PA port.
+
+   SImode loads to floating-point registers are not zero-extended.
+   The definition for LOAD_EXTEND_OP specifies that integer loads
+   narrower than BITS_PER_WORD will be zero-extended.  As a result,
+   we inhibit changes from SImode unless they are to a mode that is
+   identical in size.
+
+   Likewise for SFmode, since word-mode paradoxical subregs are
+   problematic on big-endian architectures.  */
+
+static bool
+sparc_can_change_mode_class (machine_mode from, machine_mode to,
+                            reg_class_t rclass)
+{
+  if (TARGET_ARCH64
+      && GET_MODE_SIZE (from) == 4
+      && GET_MODE_SIZE (to) != 4)
+    return !reg_classes_intersect_p (rclass, FP_REGS);
+  return true;
+}
+
 #include "gt-sparc.h"
index a9672e3bf1ce4c6e1ee03930fb565ae03d3ebd3f..af350d7a11acc051d39b2b9a272be7a62aa2ae10 100644 (file)
@@ -907,23 +907,6 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
 
 #define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
 
-/* Defines invalid mode changes.  Borrowed from the PA port.
-
-   SImode loads to floating-point registers are not zero-extended.
-   The definition for LOAD_EXTEND_OP specifies that integer loads
-   narrower than BITS_PER_WORD will be zero-extended.  As a result,
-   we inhibit changes from SImode unless they are to a mode that is
-   identical in size.
-
-   Likewise for SFmode, since word-mode paradoxical subregs are
-   problematic on big-endian architectures.  */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)              \
-  (TARGET_ARCH64                                               \
-   && GET_MODE_SIZE (FROM) == 4                                        \
-   && GET_MODE_SIZE (TO) != 4                                  \
-   ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
-
 /* This is the order in which to allocate registers normally.
 
    We put %f0-%f7 last among the float registers, so as to make it more
index 279adf30b72d97682e8a9fcc42b798b65418ef47..413567ba2bd9a4022d87eba3d7d49cca9c628564 100644 (file)
@@ -7162,6 +7162,17 @@ spu_modes_tieable_p (machine_mode mode1, machine_mode mode2)
   return (GET_MODE_BITSIZE (mode1) <= MAX_FIXED_MODE_SIZE
          && GET_MODE_BITSIZE (mode2) <= MAX_FIXED_MODE_SIZE);
 }
+
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.  GCC assumes that modes are
+   in the lowpart of a register, which is only true for SPU.  */
+
+static bool
+spu_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
+{
+  return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
+         || (GET_MODE_SIZE (from) <= 4 && GET_MODE_SIZE (to) <= 4)
+         || (GET_MODE_SIZE (from) >= 16 && GET_MODE_SIZE (to) >= 16));
+}
 \f
 /*  Table of machine attributes.  */
 static const struct attribute_spec spu_attribute_table[] =
@@ -7393,6 +7404,9 @@ static const struct attribute_spec spu_attribute_table[] =
 #undef TARGET_HARD_REGNO_NREGS
 #define TARGET_HARD_REGNO_NREGS spu_hard_regno_nregs
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS spu_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-spu.h"
index 1b01a74ab09e26ae9c11da4a633d9764448912ec..f41117e071dd0bfcf169eb45220997d0348a88a6 100644 (file)
@@ -211,13 +211,6 @@ enum reg_class {
 #define INT_REG_OK_FOR_BASE_P(X,STRICT) \
        ((!(STRICT) || REGNO_OK_FOR_BASE_P (REGNO (X))))
 
-/* GCC assumes that modes are in the lowpart of a register, which is
-   only true for SPU. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-        ((GET_MODE_SIZE (FROM) > 4 || GET_MODE_SIZE (TO) > 4) \
-        && (GET_MODE_SIZE (FROM) < 16 || GET_MODE_SIZE (TO) < 16) \
-        && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
-
 #define REGISTER_TARGET_PRAGMAS() do {                                 \
 c_register_addr_space ("__ea", ADDR_SPACE_EA);                         \
 targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin;   \
index 4a68f18835769791678785bda5f6f0a7771880c3..4dd66dcd40b3322c19977d98c3fb519f54471140 100644 (file)
@@ -234,6 +234,9 @@ static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
 
 static bool visium_modes_tieable_p (machine_mode, machine_mode);
 
+static bool visium_can_change_mode_class (machine_mode, machine_mode,
+                                         reg_class_t);
+
 /* Setup the global target hooks structure.  */
 
 #undef  TARGET_MAX_ANCHOR_OFFSET
@@ -354,6 +357,9 @@ static bool visium_modes_tieable_p (machine_mode, machine_mode);
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
 
+#undef TARGET_CAN_CHANGE_MODE_CLASS
+#define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 namespace {
@@ -4293,4 +4299,24 @@ reg_or_subreg_regno (rtx op)
   return regno;
 }
 
+/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
+
+   It's not obvious from the documentation of the hook that MDB cannot
+   change mode.  However difficulties arise from expressions of the form
+
+   (subreg:SI (reg:DI R_MDB) 0)
+
+   There is no way to convert that reference to a single machine
+   register and, without the following definition, reload will quietly
+   convert it to
+
+   (reg:SI R_MDB).  */
+
+static bool
+visium_can_change_mode_class (machine_mode from, machine_mode to,
+                             reg_class_t rclass)
+{
+  return (rclass != MDB || GET_MODE_SIZE (from) == GET_MODE_SIZE (to));
+}
+
 #include "gt-visium.h"
index 4e7485e3cd413aba324e5b0919d4f66e8fbd0225..b415e3c221d42dfab4c5557254b2243aa3c9543a 100644 (file)
@@ -723,24 +723,6 @@ enum reg_class
    registers. */
 #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
 
-/*  `CANNOT_CHANGE_MODE_CLASS (from, to, class)
-
-    If defined, a C expression that returns nonzero for a `class' for
-    which a change from mode `from' to mode `to' is invalid.
-
-    It's not obvious from the above that MDB cannot change mode. However
-    difficulties arise from expressions of the form
-
-    (subreg:SI (reg:DI R_MDB) 0)
-    There is no way to convert that reference to a single machine
-    register and, without the following definition, reload will quietly
-    convert it to
-     (reg:SI R_MDB)  */
-#define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
-  (CLASS == MDB ? (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) : 0)
-
 #define CLASS_MAX_NREGS(CLASS, MODE)    \
   ((CLASS) == MDB ?                     \
   ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \
index 12355c2fbad72c9b3820ad90449372638b618487..3b2b24748b885f36284db3217ef24d1de4b2dda2 100644 (file)
@@ -2024,17 +2024,17 @@ has an unknown number of undefined bits, so the assignment:
 does not guarantee that @samp{(subreg:HI (reg:PSI 0) 0)} has the
 value @samp{(reg:HI 4)}.
 
-@cindex @code{CANNOT_CHANGE_MODE_CLASS} and subreg semantics
+@cindex @code{TARGET_CAN_CHANGE_MODE_CLASS} and subreg semantics
 The rules above apply to both pseudo @var{reg}s and hard @var{reg}s.
 If the semantics are not correct for particular combinations of
 @var{m1}, @var{m2} and hard @var{reg}, the target-specific code
 must ensure that those combinations are never used.  For example:
 
 @smallexample
-CANNOT_CHANGE_MODE_CLASS (@var{m2}, @var{m1}, @var{class})
+TARGET_CAN_CHANGE_MODE_CLASS (@var{m2}, @var{m1}, @var{class})
 @end smallexample
 
-must be true for every class @var{class} that includes @var{reg}.
+must be false for every class @var{class} that includes @var{reg}.
 
 @findex SUBREG_REG
 @findex SUBREG_BYTE
index 04038015e8cccd51d8aa315b99a444d2831d1e52..5b9e2b34f54e64734378188f522ab8a0dec8e941 100644 (file)
@@ -2018,8 +2018,8 @@ This hook returns the number of consecutive hard registers, starting
 at register number @var{regno}, required to hold a value of mode
 @var{mode}.  This hook must never return zero, even if a register
 cannot hold the requested mode - indicate that with
-@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}
-instead.
+@code{TARGET_HARD_REGNO_MODE_OK} and/or
+@code{TARGET_CAN_CHANGE_MODE_CLASS} instead.
 
 The default definition returns the number of words in @var{mode}.
 @end deftypefn
@@ -2814,25 +2814,27 @@ This macro helps control the handling of multiple-word values
 in the reload pass.
 @end defmac
 
-@defmac CANNOT_CHANGE_MODE_CLASS (@var{from}, @var{to}, @var{class})
-If defined, a C expression that returns nonzero for a @var{class} for which
-a change from mode @var{from} to mode @var{to} is invalid.
+@deftypefn {Target Hook} bool TARGET_CAN_CHANGE_MODE_CLASS (machine_mode @var{from}, machine_mode @var{to}, reg_class_t @var{rclass})
+This hook returns true if it is possible to bitcast values held in
+registers of class @var{rclass} from mode @var{from} to mode @var{to}
+and if doing so preserves the low-order bits that are common to both modes.
+The result is only meaningful if @var{rclass} has registers that can hold
+both @code{from} and @code{to}.  The default implementation returns true.
 
-For example, loading 32-bit integer or floating-point objects into
-floating-point registers on 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{CANNOT_CHANGE_MODE_CLASS}
-as below:
+As an example of when such bitcasting is invalid, loading 32-bit integer or
+floating-point objects into floating-point registers on 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{TARGET_CAN_CHANGE_MODE_CLASS} to return:
 
 @smallexample
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
-   ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
+(GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
+ || !reg_classes_intersect_p (FLOAT_REGS, rclass))
 @end smallexample
 
 Even if storing from a register in mode @var{to} would be valid,
-if both @var{from} and @code{raw_reg_mode} for @var{class} are wider
+if both @var{from} and @code{raw_reg_mode} for @var{rclass} are wider
 than @code{word_mode}, then we must prevent @var{to} narrowing the
 mode.  This happens when the middle-end assumes that it can load
 or store pieces of an @var{N}-word pseudo, and that the pseudo will
@@ -2840,8 +2842,7 @@ eventually be allocated to @var{N} @code{word_mode} hard registers.
 Failure to prevent this kind of mode change will result in the
 entire @code{raw_reg_mode} being modified instead of the partial
 value that the middle-end intended.
-
-@end defmac
+@end deftypefn
 
 @deftypefn {Target Hook} reg_class_t TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS (int, @var{reg_class_t}, @var{reg_class_t})
 A target hook which can change allocno class for given pseudo from
@@ -10695,12 +10696,12 @@ define it as the constant @code{SIGN_EXTEND} or @code{ZERO_EXTEND}.
 
 You may return a non-@code{UNKNOWN} value even if for some hard registers
 the sign extension is not performed, if for the @code{REGNO_REG_CLASS}
-of these hard registers @code{CANNOT_CHANGE_MODE_CLASS} returns nonzero
+of these hard registers @code{TARGET_CAN_CHANGE_MODE_CLASS} returns false
 when the @var{from} mode is @var{mem_mode} and the @var{to} mode is any
 integral mode larger than this but not larger than @code{word_mode}.
 
 You must return @code{UNKNOWN} if for some hard registers that allow this
-mode, @code{CANNOT_CHANGE_MODE_CLASS} says that they cannot change to
+mode, @code{TARGET_CAN_CHANGE_MODE_CLASS} says that they cannot change to
 @code{word_mode}, but that they can change to another integral mode that
 is larger then @var{mem_mode} but still smaller than @code{word_mode}.
 @end defmac
@@ -10813,7 +10814,7 @@ widest integral mode and currently we take advantage of this fact.)
 Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}
 value even if the extension is not performed on certain hard registers
 as long as for the @code{REGNO_REG_CLASS} of these hard registers
-@code{CANNOT_CHANGE_MODE_CLASS} returns nonzero.
+@code{TARGET_CAN_CHANGE_MODE_CLASS} returns false.
 
 Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}
 describe two related properties.  If you define
index f6a0d09f1887f8377296de1c27d562b3e45b0413..57b017fb81dbfd2ac13d1db639474fd0b469ca00 100644 (file)
@@ -2334,34 +2334,7 @@ This macro helps control the handling of multiple-word values
 in the reload pass.
 @end defmac
 
-@defmac CANNOT_CHANGE_MODE_CLASS (@var{from}, @var{to}, @var{class})
-If defined, a C expression that returns nonzero for a @var{class} for which
-a change from mode @var{from} to mode @var{to} is invalid.
-
-For example, loading 32-bit integer or floating-point objects into
-floating-point registers on 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{CANNOT_CHANGE_MODE_CLASS}
-as below:
-
-@smallexample
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
-  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
-   ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
-@end smallexample
-
-Even if storing from a register in mode @var{to} would be valid,
-if both @var{from} and @code{raw_reg_mode} for @var{class} are wider
-than @code{word_mode}, then we must prevent @var{to} narrowing the
-mode.  This happens when the middle-end assumes that it can load
-or store pieces of an @var{N}-word pseudo, and that the pseudo will
-eventually be allocated to @var{N} @code{word_mode} hard registers.
-Failure to prevent this kind of mode change will result in the
-entire @code{raw_reg_mode} being modified instead of the partial
-value that the middle-end intended.
-
-@end defmac
+@hook TARGET_CAN_CHANGE_MODE_CLASS
 
 @hook TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS
 
@@ -7451,12 +7424,12 @@ define it as the constant @code{SIGN_EXTEND} or @code{ZERO_EXTEND}.
 
 You may return a non-@code{UNKNOWN} value even if for some hard registers
 the sign extension is not performed, if for the @code{REGNO_REG_CLASS}
-of these hard registers @code{CANNOT_CHANGE_MODE_CLASS} returns nonzero
+of these hard registers @code{TARGET_CAN_CHANGE_MODE_CLASS} returns false
 when the @var{from} mode is @var{mem_mode} and the @var{to} mode is any
 integral mode larger than this but not larger than @code{word_mode}.
 
 You must return @code{UNKNOWN} if for some hard registers that allow this
-mode, @code{CANNOT_CHANGE_MODE_CLASS} says that they cannot change to
+mode, @code{TARGET_CAN_CHANGE_MODE_CLASS} says that they cannot change to
 @code{word_mode}, but that they can change to another integral mode that
 is larger then @var{mem_mode} but still smaller than @code{word_mode}.
 @end defmac
index e36a7ddcec3ebe688bf63a0bf9b2c6f6bbf29f63..e790cbcb6ff0989453ed618563c3a12435fbf713 100644 (file)
@@ -866,13 +866,11 @@ validate_subreg (machine_mode omode, machine_mode imode,
     {
       unsigned int regno = REGNO (reg);
 
-#ifdef CANNOT_CHANGE_MODE_CLASS
       if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
          && GET_MODE_INNER (imode) == omode)
        ;
-      else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode))
+      else if (!REG_CAN_CHANGE_MODE_P (regno, imode, omode))
        return false;
-#endif
 
       return subreg_offset_representable_p (regno, imode, offset, omode);
     }
index d5fc417082fd000a976bcc2976c4c5f33d0f53d6..42a85a16a4ef90cb27e28984f130544908b8e96b 100644 (file)
@@ -765,9 +765,9 @@ extern struct target_hard_regs *this_target_hard_regs;
 
 extern const char * reg_class_names[];
 
-/* Given a hard REGN a FROM mode and a TO mode, return nonzero if
-   REGN cannot change modes between the specified modes.  */
-#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO)                          \
-         CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
+/* Given a hard REGN a FROM mode and a TO mode, return true if
+   REGN can change from mode FROM to mode TO.  */
+#define REG_CAN_CHANGE_MODE_P(REGN, FROM, TO)                          \
+  (targetm.can_change_mode_class (FROM, TO, REGNO_REG_CLASS (REGN)))
 
 #endif /* ! GCC_HARD_REG_SET_H */
index 44ebd6f5c857bcca75489d17f9c1829638250338..3af7795a7ef9a7caba5cd89ae1ccfac7c29d28ea 100644 (file)
@@ -495,6 +495,14 @@ hook_bool_reg_class_t_false (reg_class_t regclass ATTRIBUTE_UNUSED)
   return false;
 }
 
+/* Generic hook that takes 2 machine_modes and a register class and
+   returns true.  */
+bool
+hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode, reg_class_t)
+{
+  return true;
+}
+
 /* Generic hook that takes a machine_mode and 2 register classes
    and returns false.  */
 bool
index e5741df7f1cb862d92460355c61e7b6539108f4a..6838c23cf2c01fd30a698b6d5151777d47209c40 100644 (file)
@@ -59,6 +59,8 @@ extern bool hook_bool_rtx_false (rtx);
 extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int);
 extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
 extern bool hook_bool_reg_class_t_false (reg_class_t regclass);
+extern bool hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode,
+                                                 reg_class_t);
 extern bool hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode,
                                                          reg_class_t,
                                                          reg_class_t);
index 6026e21295aab140c176776252d33e5590a5c043..000ed341b0347c1358eff03616926fcfac72a142 100644 (file)
@@ -335,12 +335,8 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
              && !REG_P (SET_SRC (set))))
        {
          if (extend_op != UNKNOWN
-#ifdef CANNOT_CHANGE_MODE_CLASS
-             && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
-                                           word_mode,
-                                           REGNO_REG_CLASS (REGNO (SET_DEST (set))))
-#endif
-             )
+             && REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
+                                       GET_MODE (SET_DEST (set)), word_mode))
            {
              rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
              ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@@ -437,15 +433,13 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
                   || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
                   || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
            ; /* Continue ordinary processing.  */
-#ifdef CANNOT_CHANGE_MODE_CLASS
          /* If the register cannot change mode to word_mode, it follows that
             it cannot have been used in word_mode.  */
          else if (REG_P (SET_DEST (set))
-                  && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
-                                               word_mode,
-                                               REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
+                  && !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
+                                             GET_MODE (SET_DEST (set)),
+                                             word_mode))
            ; /* Continue ordinary processing.  */
-#endif
          /* If this is a straight load, make the extension explicit.  */
          else if (REG_P (SET_DEST (set))
                   && recog_data.n_operands == 2
index 78c26d617a960d6c6ebd79c8e0029c8c8b407414..cfce0291ba03732abe98c21cccec423db95fbe4c 100644 (file)
@@ -1009,10 +1009,9 @@ general_operand (rtx op, machine_mode mode)
          && MEM_P (sub))
        return 0;
 
-#ifdef CANNOT_CHANGE_MODE_CLASS
       if (REG_P (sub)
          && REGNO (sub) < FIRST_PSEUDO_REGISTER
-         && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
+         && !REG_CAN_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
          && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT
          /* LRA can generate some invalid SUBREGS just for matched
@@ -1020,7 +1019,6 @@ general_operand (rtx op, machine_mode mode)
             valid.  */
          && ! LRA_SUBREG_P (op))
        return 0;
-#endif
 
       /* FLOAT_MODE subregs can't be paradoxical.  Combine will occasionally
         create such rtl, and we must reject it.  */
index 6db7fdd72402074ce3be6bcb8d1fcb8507b406bd..73e945d45ae651b704f0dc072c3fd7211a6f0fe8 100644 (file)
@@ -376,11 +376,7 @@ mode_change_ok (machine_mode orig_mode, machine_mode new_mode,
   if (partial_subreg_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;
+  return REG_CAN_CHANGE_MODE_P (regno, orig_mode, new_mode);
 }
 
 /* Register REGNO was originally set in ORIG_MODE.  It - or a copy of it -
index c9b946134f3ef450697a56d4b1864240acef2ada..dae3b027bb387d52f5a84697308fecd993f3db6d 100644 (file)
@@ -1038,9 +1038,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
   scalar_int_mode inner_mode;
   if (in != 0 && GET_CODE (in) == SUBREG
       && (subreg_lowpart_p (in) || strict_low)
-#ifdef CANNOT_CHANGE_MODE_CLASS
-      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
-#endif
+      && targetm.can_change_mode_class (GET_MODE (SUBREG_REG (in)),
+                                       inmode, rclass)
       && contains_allocatable_reg_of_mode[rclass][GET_MODE (SUBREG_REG (in))]
       && (CONSTANT_P (SUBREG_REG (in))
          || GET_CODE (SUBREG_REG (in)) == PLUS
@@ -1076,13 +1075,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              && (secondary_reload_class (1, rclass, GET_MODE (SUBREG_REG (in)),
                                          SUBREG_REG (in))
                  == NO_REGS))
-#ifdef CANNOT_CHANGE_MODE_CLASS
          || (REG_P (SUBREG_REG (in))
              && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
-             && REG_CANNOT_CHANGE_MODE_P
-             (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
-#endif
-         ))
+             && !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (in)),
+                                        GET_MODE (SUBREG_REG (in)), inmode))))
     {
 #ifdef LIMIT_RELOAD_CLASS
       in_subreg_loc = inloc;
@@ -1143,9 +1139,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      label it input-output.)  */
   if (out != 0 && GET_CODE (out) == SUBREG
       && (subreg_lowpart_p (out) || strict_low)
-#ifdef CANNOT_CHANGE_MODE_CLASS
-      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
-#endif
+      && targetm.can_change_mode_class (GET_MODE (SUBREG_REG (out)),
+                                       outmode, rclass)
       && contains_allocatable_reg_of_mode[rclass][GET_MODE (SUBREG_REG (out))]
       && (CONSTANT_P (SUBREG_REG (out))
          || strict_low
@@ -1170,14 +1165,11 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
              && (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
                                          SUBREG_REG (out))
                  == NO_REGS))
-#ifdef CANNOT_CHANGE_MODE_CLASS
          || (REG_P (SUBREG_REG (out))
              && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
-             && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
-                                          GET_MODE (SUBREG_REG (out)),
-                                          outmode))
-#endif
-         ))
+             && !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
+                                        GET_MODE (SUBREG_REG (out)),
+                                        outmode))))
     {
 #ifdef LIMIT_RELOAD_CLASS
       out_subreg_loc = outloc;
index 1ad4b63e09e4922603acbf29506a8bccc845d93d..5e200b94ebb238abe0927533c5bbe59320f043d3 100644 (file)
@@ -6557,14 +6557,12 @@ choose_reload_regs (struct insn_chain *chain)
                  && reg_last_reload_reg[regno] != 0
                  && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
                      >= GET_MODE_SIZE (mode) + byte)
-#ifdef CANNOT_CHANGE_MODE_CLASS
                  /* Verify that the register it's in can be used in
                     mode MODE.  */
-                 && !REG_CANNOT_CHANGE_MODE_P (REGNO (reg_last_reload_reg[regno]),
-                                               GET_MODE (reg_last_reload_reg[regno]),
-                                               mode)
-#endif
-                 )
+                 && (REG_CAN_CHANGE_MODE_P
+                     (REGNO (reg_last_reload_reg[regno]),
+                      GET_MODE (reg_last_reload_reg[regno]),
+                      mode)))
                {
                  enum reg_class rclass = rld[r].rclass, last_class;
                  rtx last_reg = reg_last_reload_reg[regno];
@@ -8035,12 +8033,8 @@ inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
                     int src ATTRIBUTE_UNUSED,
                     machine_mode mode ATTRIBUTE_UNUSED)
 {
-#ifdef CANNOT_CHANGE_MODE_CLASS
-  return (!REG_CANNOT_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
-         && !REG_CANNOT_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
-#else
-  return true;
-#endif
+  return (REG_CAN_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
+         && REG_CAN_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
 }
 
 /* Output insns to reload values in and out of the chosen reload regs.  */
index af149bf8dcabee327dd986eadaef2e76bdc50840..b28325e644ba37c4817b62de52b6d74026a6b5a9 100644 (file)
@@ -3861,15 +3861,13 @@ simplify_subreg_regno (unsigned int xregno, machine_mode xmode,
   struct subreg_info info;
   unsigned int yregno;
 
-#ifdef CANNOT_CHANGE_MODE_CLASS
   /* Give the backend a chance to disallow the mode change.  */
   if (GET_MODE_CLASS (xmode) != MODE_COMPLEX_INT
       && GET_MODE_CLASS (xmode) != MODE_COMPLEX_FLOAT
-      && REG_CANNOT_CHANGE_MODE_P (xregno, xmode, ymode)
+      && !REG_CAN_CHANGE_MODE_P (xregno, xmode, ymode)
       /* We can use mode change in LRA for some transformations.  */
       && ! lra_in_progress)
     return -1;
-#endif
 
   /* We shouldn't simplify stack-related registers.  */
   if ((!reload_completed || frame_pointer_needed)
index 95a7195f5c83b6ebf50db7bcc1bf651b5664795c..1663a78891f3de58727d9319598d9ab404e758b5 100644 (file)
@@ -914,7 +914,7 @@ extern void fancy_abort (const char *, int, const char *)
        HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK               \
        MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS      \
        HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE                   \
-       SECONDARY_MEMORY_NEEDED
+       SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
index 350d98425d8ba3e320bbed021f4a857705675354..ed995494954baa798f05924b6dff6f7fa75dc0cd 100644 (file)
@@ -3151,7 +3151,7 @@ widest integral mode and currently we take advantage of this fact.)\n\
 Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}\n\
 value even if the extension is not performed on certain hard registers\n\
 as long as for the @code{REGNO_REG_CLASS} of these hard registers\n\
-@code{CANNOT_CHANGE_MODE_CLASS} returns nonzero.\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} returns false.\n\
 \n\
 Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}\n\
 describe two related properties.  If you define\n\
@@ -5043,6 +5043,38 @@ This is currently used only by the C and C++ front ends.",
  tree, (tree type, tree expr),
  hook_tree_tree_tree_null)
 
+DEFHOOK
+(can_change_mode_class,
+ "This hook returns true if it is possible to bitcast values held in\n\
+registers of class @var{rclass} from mode @var{from} to mode @var{to}\n\
+and if doing so preserves the low-order bits that are common to both modes.\n\
+The result is only meaningful if @var{rclass} has registers that can hold\n\
+both @code{from} and @code{to}.  The default implementation returns true.\n\
+\n\
+As an example of when such bitcasting is invalid, loading 32-bit integer or\n\
+floating-point objects into floating-point registers on Alpha extends them\n\
+to 64 bits.  Therefore loading a 64-bit object and then storing it as a\n\
+32-bit object does not store the low-order 32 bits, as would be the case\n\
+for a normal register.  Therefore, @file{alpha.h} defines\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} to return:\n\
+\n\
+@smallexample\n\
+(GET_MODE_SIZE (from) == GET_MODE_SIZE (to)\n\
+ || !reg_classes_intersect_p (FLOAT_REGS, rclass))\n\
+@end smallexample\n\
+\n\
+Even if storing from a register in mode @var{to} would be valid,\n\
+if both @var{from} and @code{raw_reg_mode} for @var{rclass} are wider\n\
+than @code{word_mode}, then we must prevent @var{to} narrowing the\n\
+mode.  This happens when the middle-end assumes that it can load\n\
+or store pieces of an @var{N}-word pseudo, and that the pseudo will\n\
+eventually be allocated to @var{N} @code{word_mode} hard registers.\n\
+Failure to prevent this kind of mode change will result in the\n\
+entire @code{raw_reg_mode} being modified instead of the partial\n\
+value that the middle-end intended.",
+ bool, (machine_mode from, machine_mode to, reg_class_t rclass),
+ hook_bool_mode_mode_reg_class_t_true)
+
 /* Change pseudo allocno class calculated by IRA.  */
 DEFHOOK
 (ira_change_pseudo_allocno_class,
@@ -5466,8 +5498,8 @@ DEFHOOK
 at register number @var{regno}, required to hold a value of mode\n\
 @var{mode}.  This hook must never return zero, even if a register\n\
 cannot hold the requested mode - indicate that with\n\
-@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}\n\
-instead.\n\
+@code{TARGET_HARD_REGNO_MODE_OK} and/or\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} instead.\n\
 \n\
 The default definition returns the number of words in @var{mode}.",
  unsigned int, (unsigned int regno, machine_mode mode),