Turn CANNOT_CHANGE_MODE_CLASS into a hook
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
This commit is contained in:
parent
fa0cdfb651
commit
0d80303065
64 changed files with 557 additions and 414 deletions
134
gcc/ChangeLog
134
gcc/ChangeLog
|
@ -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
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/* 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 {
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
(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 ())
|
||||
|
@ -157,7 +157,7 @@
|
|||
(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 ())
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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"
|
||||
|
|
|
@ -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))
|
||||
|
||||
/* Basic Stack Layout */
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
#include "gt-mips.h"
|
||||
|
|
|
@ -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)
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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)
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
/* 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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
/* 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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
#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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/* 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"
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 -
|
||||
|
|
26
gcc/reload.c
26
gcc/reload.c
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Reference in a new issue