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:
Richard Sandiford 2017-09-15 12:56:34 +00:00 committed by Richard Sandiford
parent fa0cdfb651
commit 0d80303065
64 changed files with 557 additions and 414 deletions

View file

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

View file

@ -6869,12 +6869,10 @@ simplify_set (rtx x)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
&& (WORD_REGISTER_OPERATIONS || !paradoxical_subreg_p (src))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
GET_MODE (SUBREG_REG (src)),
GET_MODE (src)))
#endif
&& !REG_CAN_CHANGE_MODE_P (REGNO (dest),
GET_MODE (SUBREG_REG (src)),
GET_MODE (src)))
&& (REG_P (dest)
|| (GET_CODE (dest) == SUBREG
&& REG_P (SUBREG_REG (dest)))))

View file

@ -9936,6 +9936,16 @@ alpha_modes_tieable_p (machine_mode mode1, machine_mode mode2)
? alpha_hard_regno_mode_ok (32, mode2)
: true);
}
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
static bool
alpha_can_change_mode_class (machine_mode from, machine_mode to,
reg_class_t rclass)
{
return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
|| !reg_classes_intersect_p (FLOAT_REGS, rclass));
}
/* 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;

View file

@ -479,12 +479,6 @@ enum reg_class {
#define PREFERRED_RELOAD_CLASS alpha_preferred_reload_class
/* Return the class of registers that cannot change mode from FROM to TO. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
? reg_classes_intersect_p (FLOAT_REGS, CLASS) : 0)
/* Provide the cost of a branch. Exact meaning under development. */
#define BRANCH_COST(speed_p, predictable_p) 5

View file

@ -793,6 +793,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P arm_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS arm_can_change_mode_class
/* 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 {

View file

@ -1152,23 +1152,6 @@ enum reg_class
or could index an array. */
#define REGNO_REG_CLASS(REGNO) arm_regno_class (REGNO)
/* In VFPv1, VFP registers could only be accessed in the mode they
were set, so subregs would be invalid there. However, we don't
support VFPv1 at the moment, and the restriction was lifted in
VFPv2.
In big-endian mode, modes greater than word size (i.e. DFmode) are stored in
VFP registers in little-endian order. We can't describe that accurately to
GCC, so avoid taking subregs of such values.
The only exception is going from a 128-bit to a 64-bit type. In that case
the data layout happens to be consistent for big-endian, so we explicitly allow
that case. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(TARGET_BIG_END \
&& !(GET_MODE_SIZE (FROM) == 16 && GET_MODE_SIZE (TO) == 8) \
&& (GET_MODE_SIZE (FROM) > UNITS_PER_WORD \
|| GET_MODE_SIZE (TO) > UNITS_PER_WORD) \
&& reg_classes_intersect_p (VFP_REGS, (CLASS)))
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS)
#define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : CORE_REGS)

View file

@ -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 ())

View file

@ -167,8 +167,6 @@ extern int ix86_reg_parm_stack_space (const_tree);
extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
rtx, rtx, rtx);
extern bool ix86_cannot_change_mode_class (machine_mode,
machine_mode, enum reg_class);
extern bool ix86_libc_has_function (enum function_class fn_class);

View file

@ -41204,20 +41204,19 @@ ix86_class_max_nregs (reg_class_t rclass, machine_mode mode)
}
}
/* Return true if the registers in CLASS cannot represent the change from
modes FROM to TO. */
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
bool
ix86_cannot_change_mode_class (machine_mode from, machine_mode to,
enum reg_class regclass)
static bool
ix86_can_change_mode_class (machine_mode from, machine_mode to,
reg_class_t regclass)
{
if (from == to)
return false;
return true;
/* x87 registers can't do subreg at all, as all values are reformatted
to extended precision. */
if (MAYBE_FLOAT_CLASS_P (regclass))
return true;
return false;
if (MAYBE_SSE_CLASS_P (regclass) || MAYBE_MMX_CLASS_P (regclass))
{
@ -41226,10 +41225,10 @@ ix86_cannot_change_mode_class (machine_mode from, machine_mode to,
drop the subreg from (subreg:SI (reg:HI 100) 0). This affects
the vec_dupv4hi pattern. */
if (GET_MODE_SIZE (from) < 4)
return true;
return false;
}
return false;
return true;
}
/* Return the cost of moving data of mode M between a
@ -53434,6 +53433,9 @@ ix86_run_selftests (void)
#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
ix86_hard_regno_call_part_clobbered
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS ix86_can_change_mode_class
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests

View file

@ -1518,11 +1518,6 @@ enum reg_class
#define INDEX_REG_CLASS INDEX_REGS
#define BASE_REG_CLASS GENERAL_REGS
/* Return a class of registers that cannot change FROM mode to TO mode. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
ix86_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */

View file

@ -339,6 +339,8 @@ static bool ia64_vectorize_vec_perm_const_ok (machine_mode vmode,
static unsigned int ia64_hard_regno_nregs (unsigned int, machine_mode);
static bool ia64_hard_regno_mode_ok (unsigned int, machine_mode);
static bool ia64_modes_tieable_p (machine_mode, machine_mode);
static bool ia64_can_change_mode_class (machine_mode, machine_mode,
reg_class_t);
#define MAX_VECT_LEN 8
@ -668,6 +670,9 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P ia64_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS ia64_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
/* 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"

View file

@ -777,17 +777,6 @@ enum reg_class
: (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == RFmode) ? 1 \
: (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XCmode) ? 2 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* In BR regs, we can't change the DImode at all.
In FP regs, we can't change FP values to integer values and vice versa,
but we can change e.g. DImode to SImode, and V2SFmode into DImode. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(reg_classes_intersect_p (CLASS, BR_REGS) \
? (FROM) != (TO) \
: (SCALAR_FLOAT_MODE_P (FROM) != SCALAR_FLOAT_MODE_P (TO) \
? reg_classes_intersect_p (CLASS, FR_REGS) \
: 0))
/* Basic Stack Layout */

View file

@ -38,7 +38,6 @@ int m32c_trampoline_size (void);
#ifdef RTX_CODE
int m32c_cannot_change_mode_class (machine_mode, machine_mode, int);
rtx m32c_eh_return_stackadj_rtx (void);
void m32c_emit_eh_epilogue (rtx);
int m32c_expand_cmpstr (rtx *);

View file

@ -799,17 +799,17 @@ m32c_class_max_nregs (reg_class_t regclass, machine_mode mode)
return max;
}
/* Implements CANNOT_CHANGE_MODE_CLASS. Only r0 and r1 can change to
/* Implements TARGET_CAN_CHANGE_MODE_CLASS. Only r0 and r1 can change to
QI (r0l, r1l) because the chip doesn't support QI ops on other
registers (well, it does on a0/a1 but if we let gcc do that, reload
suffers). Otherwise, we allow changes to larger modes. */
int
m32c_cannot_change_mode_class (machine_mode from,
machine_mode to, int rclass)
static bool
m32c_can_change_mode_class (machine_mode from,
machine_mode to, reg_class_t rclass)
{
int rn;
#if DEBUG0
fprintf (stderr, "cannot change from %s to %s in %s\n",
fprintf (stderr, "can change from %s to %s in %s\n",
mode_name[from], mode_name[to], class_names[rclass]);
#endif
@ -818,18 +818,18 @@ m32c_cannot_change_mode_class (machine_mode from,
for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
if (class_contents[rclass][0] & (1 << rn))
if (! m32c_hard_regno_mode_ok (rn, to))
return 1;
return false;
if (to == QImode)
return (class_contents[rclass][0] & 0x1ffa);
return (class_contents[rclass][0] & 0x1ffa) == 0;
if (class_contents[rclass][0] & 0x0005 /* r0, r1 */
&& GET_MODE_SIZE (from) > 1)
return 0;
return true;
if (GET_MODE_SIZE (from) > 2) /* all other regs */
return 0;
return true;
return 1;
return false;
}
/* Helpers for the rest of the file. */
@ -4496,6 +4496,9 @@ m32c_output_compare (rtx_insn *insn, rtx *operands)
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P m32c_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS m32c_can_change_mode_class
/* The Global `targetm' Variable. */
struct gcc_target targetm = TARGET_INITIALIZER;

View file

@ -411,8 +411,6 @@ enum reg_class
#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
#define CANNOT_CHANGE_MODE_CLASS(F,T,C) m32c_cannot_change_mode_class(F,T,C)
/* STACK AND CALLING */
/* Frame Layout */

View file

@ -294,8 +294,6 @@ extern bool mips_const_vector_bitimm_set_p (rtx, machine_mode);
extern bool mips_const_vector_bitimm_clr_p (rtx, machine_mode);
extern rtx mips_msa_vec_parallel_const_half (machine_mode, bool);
extern rtx mips_gen_const_int_vector (machine_mode, HOST_WIDE_INT);
extern bool mips_cannot_change_mode_class (machine_mode,
machine_mode, enum reg_class);
extern bool mips_dangerous_for_la25_p (rtx);
extern enum reg_class mips_secondary_reload_class (enum reg_class,
machine_mode,

View file

@ -12945,22 +12945,21 @@ mips_class_max_nregs (enum reg_class rclass, machine_mode mode)
return (GET_MODE_SIZE (mode) + size - 1) / size;
}
/* Implement CANNOT_CHANGE_MODE_CLASS. */
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
bool
mips_cannot_change_mode_class (machine_mode from,
machine_mode to,
enum reg_class rclass)
static bool
mips_can_change_mode_class (machine_mode from,
machine_mode to, reg_class_t rclass)
{
/* Allow conversions between different Loongson integer vectors,
and between those vectors and DImode. */
if (GET_MODE_SIZE (from) == 8 && GET_MODE_SIZE (to) == 8
&& INTEGRAL_MODE_P (from) && INTEGRAL_MODE_P (to))
return false;
return true;
/* Allow conversions between different MSA vector modes. */
if (MSA_SUPPORTED_MODE_P (from) && MSA_SUPPORTED_MODE_P (to))
return false;
return true;
/* Otherwise, there are several problems with changing the modes of
values in floating-point registers:
@ -12985,7 +12984,7 @@ mips_cannot_change_mode_class (machine_mode from,
We therefore disallow all mode changes involving FPRs. */
return reg_classes_intersect_p (FP_REGS, rclass);
return !reg_classes_intersect_p (FP_REGS, rclass);
}
/* Implement target hook small_register_classes_for_mode_p. */
@ -22621,6 +22620,9 @@ mips_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
#undef TARGET_SECONDARY_MEMORY_NEEDED
#define TARGET_SECONDARY_MEMORY_NEEDED mips_secondary_memory_needed
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS mips_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-mips.h"

View file

@ -2302,9 +2302,6 @@ enum reg_class
needed to represent mode MODE in a register of class CLASS. */
#define CLASS_MAX_NREGS(CLASS, MODE) mips_class_max_nregs (CLASS, MODE)
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
mips_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */

View file

@ -3812,6 +3812,22 @@ msp430x_logical_shift_right (rtx amount)
right shift instruction to perform the rest of the shift. */
return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
}
/* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
static bool
msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
{
if ((to == PSImode && from == SImode)
|| (to == SImode && from == PSImode)
|| (to == DImode && from == PSImode)
|| (to == PSImode && from == DImode))
return false;
return true;
}
struct gcc_target targetm = TARGET_INITIALIZER;

View file

@ -407,14 +407,6 @@ typedef struct
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO,NREGS,MODE) \
((TARGET_LARGE && ((NREGS) <= 2)) ? PSImode : choose_hard_reg_mode ((REGNO), (NREGS), false))
/* Also stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
#define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
( ((TO) == PSImode && (FROM) == SImode) \
|| ((TO) == SImode && (FROM) == PSImode) \
|| ((TO) == DImode && (FROM) == PSImode) \
|| ((TO) == PSImode && (FROM) == DImode) \
)
#define ACCUMULATE_OUTGOING_ARGS 1
#undef ASM_DECLARE_FUNCTION_NAME

View file

@ -5529,6 +5529,14 @@ nvptx_hard_regno_nregs (unsigned int, machine_mode)
return 1;
}
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
static bool
nvptx_can_change_mode_class (machine_mode, machine_mode, reg_class_t)
{
return false;
}
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE nvptx_option_override
@ -5659,6 +5667,9 @@ nvptx_hard_regno_nregs (unsigned int, machine_mode)
#undef TARGET_HARD_REGNO_NREGS
#define TARGET_HARD_REGNO_NREGS nvptx_hard_regno_nregs
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS nvptx_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-nvptx.h"

View file

@ -95,9 +95,6 @@
#define FIXED_REGISTERS { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
#define CALL_USED_REGISTERS { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
#define CANNOT_CHANGE_MODE_CLASS(M1, M2, CLS) \
((void)(M1), (void)(M2), (void)(CLS), true)
/* Register Classes. */
enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define REG_CLASS_NAMES { "NO_REGS", "ALL_REGS" }

View file

@ -106,8 +106,6 @@ extern void pa_asm_output_aligned_local (FILE *, const char *,
unsigned HOST_WIDE_INT,
unsigned int);
extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
extern bool pa_cannot_change_mode_class (machine_mode, machine_mode,
enum reg_class);
extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
extern const int pa_magic_milli[];

View file

@ -204,6 +204,7 @@ static bool pa_callee_copies (cumulative_args_t, machine_mode,
static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
static bool pa_modes_tieable_p (machine_mode, machine_mode);
static bool pa_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
/* The following extra sections are only used for SOM. */
static GTY(()) section *som_readonly_data_section;
@ -421,6 +422,9 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P pa_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS pa_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
/* 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

View file

@ -294,11 +294,6 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
{0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \
{0xfffffffe, 0xffffffff, 0x03ffffff}} /* ALL_REGS */
/* Defines invalid mode changes. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
pa_cannot_change_mode_class (FROM, TO, CLASS)
/* Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
or could index an array. */

View file

@ -230,11 +230,6 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
{0x00000000, 0x10000000}, /* SHIFT_REGS */ \
{0xfffffffe, 0x3fffffff}} /* ALL_REGS */
/* Defines invalid mode changes. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
pa_cannot_change_mode_class (FROM, TO, CLASS)
/* Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
or could index an array. */

View file

@ -29,8 +29,6 @@ extern const char *output_move_multiple (rtx *);
extern const char *output_block_move (rtx *);
extern const char *output_jump (enum rtx_code, int, int);
extern void print_operand_address (FILE *, rtx);
extern bool pdp11_cannot_change_mode_class (machine_mode,
machine_mode, enum reg_class);
typedef enum { no_action, dec_before, inc_after } pdp11_action;
typedef enum { little, either, big } pdp11_partorder;
extern bool pdp11_expand_operands (rtx *, rtx [][2], int,

View file

@ -246,6 +246,9 @@ static bool pdp11_scalar_mode_supported_p (scalar_mode);
#undef TARGET_SECONDARY_MEMORY_NEEDED
#define TARGET_SECONDARY_MEMORY_NEEDED pdp11_secondary_memory_needed
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS pdp11_can_change_mode_class
/* 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

View file

@ -243,9 +243,6 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD): \
1 \
)
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
pdp11_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */

View file

@ -109,9 +109,6 @@ extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
machine_mode,
rtx);
extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
machine_mode,
enum reg_class);
extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
extern void rs6000_secondary_reload_gpr (rtx, rtx, rtx, bool);
extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,

View file

@ -1387,12 +1387,9 @@ static enum reg_class rs6000_debug_preferred_reload_class (rtx,
static bool rs6000_debug_secondary_memory_needed (machine_mode,
reg_class_t,
reg_class_t);
static bool rs6000_cannot_change_mode_class (machine_mode,
machine_mode,
enum reg_class);
static bool rs6000_debug_cannot_change_mode_class (machine_mode,
machine_mode,
enum reg_class);
static bool rs6000_debug_can_change_mode_class (machine_mode,
machine_mode,
reg_class_t);
static bool rs6000_save_toc_in_prologue_p (void);
static rtx rs6000_internal_arg_pointer (void);
@ -1410,11 +1407,6 @@ enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class)
= rs6000_preferred_reload_class;
bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
machine_mode,
enum reg_class)
= rs6000_cannot_change_mode_class;
const int INSN_NOT_AVAILABLE = -1;
static void rs6000_print_isa_options (FILE *, int, const char *,
@ -1989,6 +1981,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_SLOW_UNALIGNED_ACCESS
#define TARGET_SLOW_UNALIGNED_ACCESS rs6000_slow_unaligned_access
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS rs6000_can_change_mode_class
/* 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),

View file

@ -1611,11 +1611,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
registers can hold 128 bits. */
#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
rs6000_cannot_change_mode_class_ptr (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */
/* Define this if pushing a word on the stack

View file

@ -3987,6 +3987,14 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
return riscv_slow_unaligned_access_p;
}
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
static bool
riscv_can_change_mode_class (machine_mode, machine_mode, reg_class_t rclass)
{
return !reg_classes_intersect_p (FP_REGS, rclass);
}
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@ -4131,6 +4139,9 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
#undef TARGET_SECONDARY_MEMORY_NEEDED
#define TARGET_SECONDARY_MEMORY_NEEDED riscv_secondary_memory_needed
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS riscv_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-riscv.h"

View file

@ -456,9 +456,6 @@ enum reg_class
(((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH) \
|| ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
reg_classes_intersect_p (FP_REGS, CLASS)
/* Stack layout; function entry, exit and calling. */
#define STACK_GROWS_DOWNWARD 1

View file

@ -110,9 +110,6 @@ extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
machine_mode,
rtx);
extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
machine_mode,
enum reg_class);
extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
extern void rs6000_secondary_reload_gpr (rtx, rtx, rtx, bool);
extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,

View file

@ -1392,12 +1392,9 @@ static enum reg_class rs6000_debug_preferred_reload_class (rtx,
static bool rs6000_debug_secondary_memory_needed (machine_mode,
reg_class_t,
reg_class_t);
static bool rs6000_cannot_change_mode_class (machine_mode,
machine_mode,
enum reg_class);
static bool rs6000_debug_cannot_change_mode_class (machine_mode,
machine_mode,
enum reg_class);
static bool rs6000_debug_can_change_mode_class (machine_mode,
machine_mode,
reg_class_t);
static bool rs6000_save_toc_in_prologue_p (void);
static rtx rs6000_internal_arg_pointer (void);
@ -1415,11 +1412,6 @@ enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class)
= rs6000_preferred_reload_class;
bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
machine_mode,
enum reg_class)
= rs6000_cannot_change_mode_class;
const int INSN_NOT_AVAILABLE = -1;
static void rs6000_print_isa_options (FILE *, int, const char *,
@ -1979,6 +1971,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_SLOW_UNALIGNED_ACCESS
#define TARGET_SLOW_UNALIGNED_ACCESS rs6000_slow_unaligned_access
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS rs6000_can_change_mode_class
/* 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),

View file

@ -1515,11 +1515,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
registers can hold 128 bits. */
#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)]
/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
rs6000_cannot_change_mode_class_ptr (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */
/* Define this if pushing a word on the stack

View file

@ -49,8 +49,6 @@ extern void s390_function_profiler (FILE *, int);
extern void s390_set_has_landing_pad_p (bool);
extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
extern int s390_class_max_nregs (enum reg_class, machine_mode);
extern int s390_cannot_change_mode_class (machine_mode, machine_mode,
enum reg_class);
extern bool s390_function_arg_vector (machine_mode, const_tree);
#if S390_USE_TARGET_ATTRIBUTE
extern tree s390_valid_target_attribute_tree (tree args,

View file

@ -10630,13 +10630,12 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
}
/* Return TRUE if changing mode from FROM to TO should not be allowed
for register class CLASS. */
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */
int
s390_cannot_change_mode_class (machine_mode from_mode,
machine_mode to_mode,
enum reg_class rclass)
static bool
s390_can_change_mode_class (machine_mode from_mode,
machine_mode to_mode,
reg_class_t rclass)
{
machine_mode small_mode;
machine_mode big_mode;
@ -10646,10 +10645,10 @@ s390_cannot_change_mode_class (machine_mode from_mode,
if (reg_classes_intersect_p (VEC_REGS, rclass)
&& ((from_mode == V1TFmode && to_mode == TFmode)
|| (from_mode == TFmode && to_mode == V1TFmode)))
return 1;
return false;
if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode))
return 0;
return true;
if (GET_MODE_SIZE (from_mode) < GET_MODE_SIZE (to_mode))
{
@ -10672,14 +10671,14 @@ s390_cannot_change_mode_class (machine_mode from_mode,
if (reg_classes_intersect_p (VEC_REGS, rclass)
&& (GET_MODE_SIZE (small_mode) < 8
|| s390_class_max_nregs (VEC_REGS, big_mode) == 1))
return 1;
return false;
/* Likewise for access registers, since they have only half the
word size on 64-bit. */
if (reg_classes_intersect_p (ACCESS_REGS, rclass))
return 1;
return false;
return 0;
return true;
}
/* Return true if we use LRA instead of reload pass. */
@ -16115,6 +16114,9 @@ s390_asan_shadow_offset (void)
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE s390_function_specific_restore
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS s390_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"

View file

@ -477,9 +477,6 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
#define CLASS_MAX_NREGS(CLASS, MODE) \
s390_class_max_nregs ((CLASS), (MODE))
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
s390_cannot_change_mode_class ((FROM), (TO), (CLASS))
/* We can reverse a CC mode safely if we know whether it comes from a
floating point compare or not. With the vector modes it is encoded
as part of the mode.

View file

@ -324,8 +324,6 @@ extern bool sh_cfun_interrupt_handler_p (void);
extern bool sh_cfun_resbank_handler_p (void);
extern bool sh_attr_renesas_p (const_tree);
extern bool sh_cfun_attr_renesas_p (void);
extern bool sh_cannot_change_mode_class
(machine_mode, machine_mode, enum reg_class);
extern bool sh_small_register_classes_for_mode_p (machine_mode);
extern void sh_mark_label (rtx, int);
extern bool check_use_sfunc_addr (rtx_insn *, rtx);

View file

@ -325,6 +325,7 @@ static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static unsigned int sh_hard_regno_nregs (unsigned int, machine_mode);
static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
static bool sh_modes_tieable_p (machine_mode, machine_mode);
static bool sh_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
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

View file

@ -1087,13 +1087,6 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
Otherwise we will need at most one register per word. */
#define CLASS_MAX_NREGS(CLASS, MODE) \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* If defined, gives a class of registers that cannot be used as the
operand of a SUBREG that changes the mode of the object illegally.
??? We need to renumber the internal numbers for the frnn registers
when in little endian in order to allow mode size changes. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
sh_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */

View file

@ -682,7 +682,8 @@ static unsigned int sparc_min_arithmetic_precision (void);
static unsigned int sparc_hard_regno_nregs (unsigned int, machine_mode);
static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
static bool sparc_modes_tieable_p (machine_mode, machine_mode);
static bool sparc_can_change_mode_class (machine_mode, machine_mode,
reg_class_t);
#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"

View file

@ -907,23 +907,6 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
/* Defines invalid mode changes. Borrowed from the PA port.
SImode loads to floating-point registers are not zero-extended.
The definition for LOAD_EXTEND_OP specifies that integer loads
narrower than BITS_PER_WORD will be zero-extended. As a result,
we inhibit changes from SImode unless they are to a mode that is
identical in size.
Likewise for SFmode, since word-mode paradoxical subregs are
problematic on big-endian architectures. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(TARGET_ARCH64 \
&& GET_MODE_SIZE (FROM) == 4 \
&& GET_MODE_SIZE (TO) != 4 \
? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
/* This is the order in which to allocate registers normally.
We put %f0-%f7 last among the float registers, so as to make it more

View file

@ -7162,6 +7162,17 @@ spu_modes_tieable_p (machine_mode mode1, machine_mode mode2)
return (GET_MODE_BITSIZE (mode1) <= MAX_FIXED_MODE_SIZE
&& GET_MODE_BITSIZE (mode2) <= MAX_FIXED_MODE_SIZE);
}
/* Implement TARGET_CAN_CHANGE_MODE_CLASS. GCC assumes that modes are
in the lowpart of a register, which is only true for SPU. */
static bool
spu_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
{
return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
|| (GET_MODE_SIZE (from) <= 4 && GET_MODE_SIZE (to) <= 4)
|| (GET_MODE_SIZE (from) >= 16 && GET_MODE_SIZE (to) >= 16));
}
/* 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"

View file

@ -211,13 +211,6 @@ enum reg_class {
#define INT_REG_OK_FOR_BASE_P(X,STRICT) \
((!(STRICT) || REGNO_OK_FOR_BASE_P (REGNO (X))))
/* GCC assumes that modes are in the lowpart of a register, which is
only true for SPU. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
((GET_MODE_SIZE (FROM) > 4 || GET_MODE_SIZE (TO) > 4) \
&& (GET_MODE_SIZE (FROM) < 16 || GET_MODE_SIZE (TO) < 16) \
&& GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
#define REGISTER_TARGET_PRAGMAS() do { \
c_register_addr_space ("__ea", ADDR_SPACE_EA); \
targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin; \

View file

@ -234,6 +234,9 @@ static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
static bool visium_modes_tieable_p (machine_mode, machine_mode);
static bool visium_can_change_mode_class (machine_mode, machine_mode,
reg_class_t);
/* Setup the global target hooks structure. */
#undef TARGET_MAX_ANCHOR_OFFSET
@ -354,6 +357,9 @@ static bool visium_modes_tieable_p (machine_mode, machine_mode);
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS visium_can_change_mode_class
struct gcc_target targetm = TARGET_INITIALIZER;
namespace {
@ -4293,4 +4299,24 @@ reg_or_subreg_regno (rtx op)
return regno;
}
/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
It's not obvious from the documentation of the hook that MDB cannot
change mode. However difficulties arise from expressions of the form
(subreg:SI (reg:DI R_MDB) 0)
There is no way to convert that reference to a single machine
register and, without the following definition, reload will quietly
convert it to
(reg:SI R_MDB). */
static bool
visium_can_change_mode_class (machine_mode from, machine_mode to,
reg_class_t rclass)
{
return (rclass != MDB || GET_MODE_SIZE (from) == GET_MODE_SIZE (to));
}
#include "gt-visium.h"

View file

@ -723,24 +723,6 @@ enum reg_class
registers. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
/* `CANNOT_CHANGE_MODE_CLASS (from, to, class)
If defined, a C expression that returns nonzero for a `class' for
which a change from mode `from' to mode `to' is invalid.
It's not obvious from the above that MDB cannot change mode. However
difficulties arise from expressions of the form
(subreg:SI (reg:DI R_MDB) 0)
There is no way to convert that reference to a single machine
register and, without the following definition, reload will quietly
convert it to
(reg:SI R_MDB) */
#define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
(CLASS == MDB ? (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) : 0)
#define CLASS_MAX_NREGS(CLASS, MODE) \
((CLASS) == MDB ? \
((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \

View file

@ -2024,17 +2024,17 @@ has an unknown number of undefined bits, so the assignment:
does not guarantee that @samp{(subreg:HI (reg:PSI 0) 0)} has the
value @samp{(reg:HI 4)}.
@cindex @code{CANNOT_CHANGE_MODE_CLASS} and subreg semantics
@cindex @code{TARGET_CAN_CHANGE_MODE_CLASS} and subreg semantics
The rules above apply to both pseudo @var{reg}s and hard @var{reg}s.
If the semantics are not correct for particular combinations of
@var{m1}, @var{m2} and hard @var{reg}, the target-specific code
must ensure that those combinations are never used. For example:
@smallexample
CANNOT_CHANGE_MODE_CLASS (@var{m2}, @var{m1}, @var{class})
TARGET_CAN_CHANGE_MODE_CLASS (@var{m2}, @var{m1}, @var{class})
@end smallexample
must be true for every class @var{class} that includes @var{reg}.
must be false for every class @var{class} that includes @var{reg}.
@findex SUBREG_REG
@findex SUBREG_BYTE

View file

@ -2018,8 +2018,8 @@ This hook returns the number of consecutive hard registers, starting
at register number @var{regno}, required to hold a value of mode
@var{mode}. This hook must never return zero, even if a register
cannot hold the requested mode - indicate that with
@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}
instead.
@code{TARGET_HARD_REGNO_MODE_OK} and/or
@code{TARGET_CAN_CHANGE_MODE_CLASS} instead.
The default definition returns the number of words in @var{mode}.
@end deftypefn
@ -2814,25 +2814,27 @@ This macro helps control the handling of multiple-word values
in the reload pass.
@end defmac
@defmac CANNOT_CHANGE_MODE_CLASS (@var{from}, @var{to}, @var{class})
If defined, a C expression that returns nonzero for a @var{class} for which
a change from mode @var{from} to mode @var{to} is invalid.
@deftypefn {Target Hook} bool TARGET_CAN_CHANGE_MODE_CLASS (machine_mode @var{from}, machine_mode @var{to}, reg_class_t @var{rclass})
This hook returns true if it is possible to bitcast values held in
registers of class @var{rclass} from mode @var{from} to mode @var{to}
and if doing so preserves the low-order bits that are common to both modes.
The result is only meaningful if @var{rclass} has registers that can hold
both @code{from} and @code{to}. The default implementation returns true.
For example, loading 32-bit integer or floating-point objects into
floating-point registers on Alpha extends them to 64 bits.
Therefore loading a 64-bit object and then storing it as a 32-bit object
does not store the low-order 32 bits, as would be the case for a normal
register. Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS}
as below:
As an example of when such bitcasting is invalid, loading 32-bit integer or
floating-point objects into floating-point registers on Alpha extends them
to 64 bits. Therefore loading a 64-bit object and then storing it as a
32-bit object does not store the low-order 32 bits, as would be the case
for a normal register. Therefore, @file{alpha.h} defines
@code{TARGET_CAN_CHANGE_MODE_CLASS} to return:
@smallexample
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
(GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
|| !reg_classes_intersect_p (FLOAT_REGS, rclass))
@end smallexample
Even if storing from a register in mode @var{to} would be valid,
if both @var{from} and @code{raw_reg_mode} for @var{class} are wider
if both @var{from} and @code{raw_reg_mode} for @var{rclass} are wider
than @code{word_mode}, then we must prevent @var{to} narrowing the
mode. This happens when the middle-end assumes that it can load
or store pieces of an @var{N}-word pseudo, and that the pseudo will
@ -2840,8 +2842,7 @@ eventually be allocated to @var{N} @code{word_mode} hard registers.
Failure to prevent this kind of mode change will result in the
entire @code{raw_reg_mode} being modified instead of the partial
value that the middle-end intended.
@end defmac
@end deftypefn
@deftypefn {Target Hook} reg_class_t TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS (int, @var{reg_class_t}, @var{reg_class_t})
A target hook which can change allocno class for given pseudo from
@ -10695,12 +10696,12 @@ define it as the constant @code{SIGN_EXTEND} or @code{ZERO_EXTEND}.
You may return a non-@code{UNKNOWN} value even if for some hard registers
the sign extension is not performed, if for the @code{REGNO_REG_CLASS}
of these hard registers @code{CANNOT_CHANGE_MODE_CLASS} returns nonzero
of these hard registers @code{TARGET_CAN_CHANGE_MODE_CLASS} returns false
when the @var{from} mode is @var{mem_mode} and the @var{to} mode is any
integral mode larger than this but not larger than @code{word_mode}.
You must return @code{UNKNOWN} if for some hard registers that allow this
mode, @code{CANNOT_CHANGE_MODE_CLASS} says that they cannot change to
mode, @code{TARGET_CAN_CHANGE_MODE_CLASS} says that they cannot change to
@code{word_mode}, but that they can change to another integral mode that
is larger then @var{mem_mode} but still smaller than @code{word_mode}.
@end defmac
@ -10813,7 +10814,7 @@ widest integral mode and currently we take advantage of this fact.)
Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}
value even if the extension is not performed on certain hard registers
as long as for the @code{REGNO_REG_CLASS} of these hard registers
@code{CANNOT_CHANGE_MODE_CLASS} returns nonzero.
@code{TARGET_CAN_CHANGE_MODE_CLASS} returns false.
Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}
describe two related properties. If you define

View file

@ -2334,34 +2334,7 @@ This macro helps control the handling of multiple-word values
in the reload pass.
@end defmac
@defmac CANNOT_CHANGE_MODE_CLASS (@var{from}, @var{to}, @var{class})
If defined, a C expression that returns nonzero for a @var{class} for which
a change from mode @var{from} to mode @var{to} is invalid.
For example, loading 32-bit integer or floating-point objects into
floating-point registers on Alpha extends them to 64 bits.
Therefore loading a 64-bit object and then storing it as a 32-bit object
does not store the low-order 32 bits, as would be the case for a normal
register. Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS}
as below:
@smallexample
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
@end smallexample
Even if storing from a register in mode @var{to} would be valid,
if both @var{from} and @code{raw_reg_mode} for @var{class} are wider
than @code{word_mode}, then we must prevent @var{to} narrowing the
mode. This happens when the middle-end assumes that it can load
or store pieces of an @var{N}-word pseudo, and that the pseudo will
eventually be allocated to @var{N} @code{word_mode} hard registers.
Failure to prevent this kind of mode change will result in the
entire @code{raw_reg_mode} being modified instead of the partial
value that the middle-end intended.
@end defmac
@hook TARGET_CAN_CHANGE_MODE_CLASS
@hook TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS
@ -7451,12 +7424,12 @@ define it as the constant @code{SIGN_EXTEND} or @code{ZERO_EXTEND}.
You may return a non-@code{UNKNOWN} value even if for some hard registers
the sign extension is not performed, if for the @code{REGNO_REG_CLASS}
of these hard registers @code{CANNOT_CHANGE_MODE_CLASS} returns nonzero
of these hard registers @code{TARGET_CAN_CHANGE_MODE_CLASS} returns false
when the @var{from} mode is @var{mem_mode} and the @var{to} mode is any
integral mode larger than this but not larger than @code{word_mode}.
You must return @code{UNKNOWN} if for some hard registers that allow this
mode, @code{CANNOT_CHANGE_MODE_CLASS} says that they cannot change to
mode, @code{TARGET_CAN_CHANGE_MODE_CLASS} says that they cannot change to
@code{word_mode}, but that they can change to another integral mode that
is larger then @var{mem_mode} but still smaller than @code{word_mode}.
@end defmac

View file

@ -866,13 +866,11 @@ validate_subreg (machine_mode omode, machine_mode imode,
{
unsigned int regno = REGNO (reg);
#ifdef CANNOT_CHANGE_MODE_CLASS
if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode))
&& GET_MODE_INNER (imode) == omode)
;
else if (REG_CANNOT_CHANGE_MODE_P (regno, imode, omode))
else if (!REG_CAN_CHANGE_MODE_P (regno, imode, omode))
return false;
#endif
return subreg_offset_representable_p (regno, imode, offset, omode);
}

View file

@ -765,9 +765,9 @@ extern struct target_hard_regs *this_target_hard_regs;
extern const char * reg_class_names[];
/* Given a hard REGN a FROM mode and a TO mode, return nonzero if
REGN cannot change modes between the specified modes. */
#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \
CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
/* Given a hard REGN a FROM mode and a TO mode, return true if
REGN can change from mode FROM to mode TO. */
#define REG_CAN_CHANGE_MODE_P(REGN, FROM, TO) \
(targetm.can_change_mode_class (FROM, TO, REGNO_REG_CLASS (REGN)))
#endif /* ! GCC_HARD_REG_SET_H */

View file

@ -495,6 +495,14 @@ hook_bool_reg_class_t_false (reg_class_t regclass ATTRIBUTE_UNUSED)
return false;
}
/* Generic hook that takes 2 machine_modes and a register class and
returns true. */
bool
hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode, reg_class_t)
{
return true;
}
/* Generic hook that takes a machine_mode and 2 register classes
and returns false. */
bool

View file

@ -59,6 +59,8 @@ extern bool hook_bool_rtx_false (rtx);
extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int);
extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
extern bool hook_bool_reg_class_t_false (reg_class_t regclass);
extern bool hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode,
reg_class_t);
extern bool hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode,
reg_class_t,
reg_class_t);

View file

@ -335,12 +335,8 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
&& !REG_P (SET_SRC (set))))
{
if (extend_op != UNKNOWN
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
word_mode,
REGNO_REG_CLASS (REGNO (SET_DEST (set))))
#endif
)
&& REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
GET_MODE (SET_DEST (set)), word_mode))
{
rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@ -437,15 +433,13 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
|| GET_CODE (SET_SRC (set)) == ZERO_EXTEND
|| GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
; /* Continue ordinary processing. */
#ifdef CANNOT_CHANGE_MODE_CLASS
/* If the register cannot change mode to word_mode, it follows that
it cannot have been used in word_mode. */
else if (REG_P (SET_DEST (set))
&& CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
word_mode,
REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
&& !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
GET_MODE (SET_DEST (set)),
word_mode))
; /* Continue ordinary processing. */
#endif
/* If this is a straight load, make the extension explicit. */
else if (REG_P (SET_DEST (set))
&& recog_data.n_operands == 2

View file

@ -1009,10 +1009,9 @@ general_operand (rtx op, machine_mode mode)
&& MEM_P (sub))
return 0;
#ifdef CANNOT_CHANGE_MODE_CLASS
if (REG_P (sub)
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& !REG_CAN_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT
/* LRA can generate some invalid SUBREGS just for matched
@ -1020,7 +1019,6 @@ general_operand (rtx op, machine_mode mode)
valid. */
&& ! LRA_SUBREG_P (op))
return 0;
#endif
/* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
create such rtl, and we must reject it. */

View file

@ -376,11 +376,7 @@ mode_change_ok (machine_mode orig_mode, machine_mode new_mode,
if (partial_subreg_p (orig_mode, new_mode))
return false;
#ifdef CANNOT_CHANGE_MODE_CLASS
return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
#endif
return true;
return REG_CAN_CHANGE_MODE_P (regno, orig_mode, new_mode);
}
/* Register REGNO was originally set in ORIG_MODE. It - or a copy of it -

View file

@ -1038,9 +1038,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
scalar_int_mode inner_mode;
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
#endif
&& targetm.can_change_mode_class (GET_MODE (SUBREG_REG (in)),
inmode, rclass)
&& contains_allocatable_reg_of_mode[rclass][GET_MODE (SUBREG_REG (in))]
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
@ -1076,13 +1075,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& (secondary_reload_class (1, rclass, GET_MODE (SUBREG_REG (in)),
SUBREG_REG (in))
== NO_REGS))
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P
(REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
#endif
))
&& !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)), inmode))))
{
#ifdef LIMIT_RELOAD_CLASS
in_subreg_loc = inloc;
@ -1143,9 +1139,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
#endif
&& targetm.can_change_mode_class (GET_MODE (SUBREG_REG (out)),
outmode, rclass)
&& contains_allocatable_reg_of_mode[rclass][GET_MODE (SUBREG_REG (out))]
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
@ -1170,14 +1165,11 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
SUBREG_REG (out))
== NO_REGS))
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
outmode))
#endif
))
&& !REG_CAN_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
outmode))))
{
#ifdef LIMIT_RELOAD_CLASS
out_subreg_loc = outloc;

View file

@ -6557,14 +6557,12 @@ choose_reload_regs (struct insn_chain *chain)
&& reg_last_reload_reg[regno] != 0
&& (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
>= GET_MODE_SIZE (mode) + byte)
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Verify that the register it's in can be used in
mode MODE. */
&& !REG_CANNOT_CHANGE_MODE_P (REGNO (reg_last_reload_reg[regno]),
GET_MODE (reg_last_reload_reg[regno]),
mode)
#endif
)
&& (REG_CAN_CHANGE_MODE_P
(REGNO (reg_last_reload_reg[regno]),
GET_MODE (reg_last_reload_reg[regno]),
mode)))
{
enum reg_class rclass = rld[r].rclass, last_class;
rtx last_reg = reg_last_reload_reg[regno];
@ -8035,12 +8033,8 @@ inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
int src ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED)
{
#ifdef CANNOT_CHANGE_MODE_CLASS
return (!REG_CANNOT_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
&& !REG_CANNOT_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
#else
return true;
#endif
return (REG_CAN_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
&& REG_CAN_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
}
/* Output insns to reload values in and out of the chosen reload regs. */

View file

@ -3861,15 +3861,13 @@ simplify_subreg_regno (unsigned int xregno, machine_mode xmode,
struct subreg_info info;
unsigned int yregno;
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Give the backend a chance to disallow the mode change. */
if (GET_MODE_CLASS (xmode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (xmode) != MODE_COMPLEX_FLOAT
&& REG_CANNOT_CHANGE_MODE_P (xregno, xmode, ymode)
&& !REG_CAN_CHANGE_MODE_P (xregno, xmode, ymode)
/* We can use mode change in LRA for some transformations. */
&& ! lra_in_progress)
return -1;
#endif
/* We shouldn't simplify stack-related registers. */
if ((!reload_completed || frame_pointer_needed)

View file

@ -914,7 +914,7 @@ extern void fancy_abort (const char *, int, const char *)
HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK \
MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS \
HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE \
SECONDARY_MEMORY_NEEDED
SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS
/* Target macros only used for code built for the target, that have
moved to libgcc-tm.h or have never been present elsewhere. */

View file

@ -3151,7 +3151,7 @@ widest integral mode and currently we take advantage of this fact.)\n\
Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}\n\
value even if the extension is not performed on certain hard registers\n\
as long as for the @code{REGNO_REG_CLASS} of these hard registers\n\
@code{CANNOT_CHANGE_MODE_CLASS} returns nonzero.\n\
@code{TARGET_CAN_CHANGE_MODE_CLASS} returns false.\n\
\n\
Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}\n\
describe two related properties. If you define\n\
@ -5043,6 +5043,38 @@ This is currently used only by the C and C++ front ends.",
tree, (tree type, tree expr),
hook_tree_tree_tree_null)
DEFHOOK
(can_change_mode_class,
"This hook returns true if it is possible to bitcast values held in\n\
registers of class @var{rclass} from mode @var{from} to mode @var{to}\n\
and if doing so preserves the low-order bits that are common to both modes.\n\
The result is only meaningful if @var{rclass} has registers that can hold\n\
both @code{from} and @code{to}. The default implementation returns true.\n\
\n\
As an example of when such bitcasting is invalid, loading 32-bit integer or\n\
floating-point objects into floating-point registers on Alpha extends them\n\
to 64 bits. Therefore loading a 64-bit object and then storing it as a\n\
32-bit object does not store the low-order 32 bits, as would be the case\n\
for a normal register. Therefore, @file{alpha.h} defines\n\
@code{TARGET_CAN_CHANGE_MODE_CLASS} to return:\n\
\n\
@smallexample\n\
(GET_MODE_SIZE (from) == GET_MODE_SIZE (to)\n\
|| !reg_classes_intersect_p (FLOAT_REGS, rclass))\n\
@end smallexample\n\
\n\
Even if storing from a register in mode @var{to} would be valid,\n\
if both @var{from} and @code{raw_reg_mode} for @var{rclass} are wider\n\
than @code{word_mode}, then we must prevent @var{to} narrowing the\n\
mode. This happens when the middle-end assumes that it can load\n\
or store pieces of an @var{N}-word pseudo, and that the pseudo will\n\
eventually be allocated to @var{N} @code{word_mode} hard registers.\n\
Failure to prevent this kind of mode change will result in the\n\
entire @code{raw_reg_mode} being modified instead of the partial\n\
value that the middle-end intended.",
bool, (machine_mode from, machine_mode to, reg_class_t rclass),
hook_bool_mode_mode_reg_class_t_true)
/* Change pseudo allocno class calculated by IRA. */
DEFHOOK
(ira_change_pseudo_allocno_class,
@ -5466,8 +5498,8 @@ DEFHOOK
at register number @var{regno}, required to hold a value of mode\n\
@var{mode}. This hook must never return zero, even if a register\n\
cannot hold the requested mode - indicate that with\n\
@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}\n\
instead.\n\
@code{TARGET_HARD_REGNO_MODE_OK} and/or\n\
@code{TARGET_CAN_CHANGE_MODE_CLASS} instead.\n\
\n\
The default definition returns the number of words in @var{mode}.",
unsigned int, (unsigned int regno, machine_mode mode),