mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 21:01:27 +08:00
Turn SECONDARY_MEMORY_NEEDED into a hook
Since the patch is going through all the definitions anyway, it seemed like a good opportunity to put the mode argument first, to match the order for register_move_cost. 2017-09-13 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * target.def (secondary_memory_needed): New hook. (secondary_reload): Refer to TARGET_SECONDARY_MEMORY_NEEDED instead of SECONDARY_MEMORY_NEEDED. (secondary_memory_needed_mode): Likewise. * hooks.h (hook_bool_mode_reg_class_t_reg_class_t_false): Declare. * hooks.c (hook_bool_mode_reg_class_t_reg_class_t_false): New function. * doc/tm.texi.in (SECONDARY_MEMORY_NEEDED): Replace with... (TARGET_SECONDARY_MEMORY_NEEDED): ...this. (SECONDARY_MEMORY_NEEDED_RTX): Update reference accordingly. * doc/tm.texi: Regenerate. * config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED): Delete. * config/alpha/alpha.c (alpha_secondary_memory_needed): New function. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. * config/i386/i386.h (SECONDARY_MEMORY_NEEDED): Delete. * config/i386/i386-protos.h (ix86_secondary_memory_needed): Delete. * config/i386/i386.c (inline_secondary_memory_needed): Put the mode argument first and change the reg_class arguments to reg_class_t. (ix86_secondary_memory_needed): Likewise. Remove the strict parameter. Make static. Update the call to inline_secondary_memory_needed. (ix86_register_move_cost): Update the call to inline_secondary_memory_needed. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. * config/ia64/ia64.h (SECONDARY_MEMORY_NEEDED): Delete commented-out definition. * config/ia64/ia64.c (spill_xfmode_rfmode_operand): Refer to TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED in comment. * config/mips/mips.h (SECONDARY_MEMORY_NEEDED): Delete. * config/mips/mips-protos.h (mips_secondary_memory_needed): Delete. * config/mips/mips.c (mips_secondary_memory_needed): Make static and match hook interface. Add comment from mips.h. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. * config/mmix/mmix.md (truncdfsf2): Refer to TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED in comment. * config/pa/pa-64.h (SECONDARY_MEMORY_NEEDED): Rename to... (PA_SECONDARY_MEMORY_NEEDED): ...this, and put the mode argument first. * config/pa/pa.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. (pa_secondary_memory_needed): New function. * config/pdp11/pdp11.h (SECONDARY_MEMORY_NEEDED): Delete. * config/pdp11/pdp11-protos.h (pdp11_secondary_memory_needed): Delete. * config/pdp11/pdp11.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. (pdp11_secondary_memory_needed): Make static and match hook interface. * config/powerpcspe/powerpcspe.h (SECONDARY_MEMORY_NEEDED): Delete. * config/powerpcspe/powerpcspe-protos.h (rs6000_secondary_memory_needed_ptr): Delete. * config/powerpcspe/powerpcspe.c (rs6000_secondary_memory_needed_ptr): Delete. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. (rs6000_option_override_internal): Assign to targetm.secondary_memory_needed rather than rs6000_secondary_memory_needed_ptr. (rs6000_secondary_memory_needed): Match hook interface. (rs6000_debug_secondary_memory_needed): Likewise. * config/riscv/riscv.h (SECONDARY_MEMORY_NEEDED): Delete. * config/riscv/riscv.c (riscv_secondary_memory_needed): New function. (riscv_register_move_cost): Use it instead of SECONDARY_MEMORY_NEEDED. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. * config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED): Delete. * config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_ptr): Delete. * config/rs6000/rs6000.c (rs6000_secondary_memory_needed_ptr): Delete. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. (rs6000_option_override_internal): Assign to targetm.secondary_memory_needed rather than rs6000_secondary_memory_needed_ptr. (rs6000_secondary_memory_needed): Match hook interface. (rs6000_debug_secondary_memory_needed): Likewise. * config/s390/s390.h (SECONDARY_MEMORY_NEEDED): Delete. * config/s390/s390.c (s390_secondary_memory_needed): New function. (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. * config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED): Delete. * config/sparc/sparc.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine. (sparc_secondary_memory_needed): New function. * lra-constraints.c (check_and_process_move): Refer to TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED in comment. (curr_insn_transform): Likewise. (process_alt_operands): Use targetm.secondary_memory_needed instead of TARGET_SECONDARY_MEMORY_NEEDED. (check_secondary_memory_needed_p): Likewise. (choose_split_class): Likewise. * reload.c: Unconditionally include code that was previously conditional on SECONDARY_MEMORY_NEEDED. (push_secondary_reload): Use targetm.secondary_memory_needed instead of TARGET_SECONDARY_MEMORY_NEEDED. (push_reload): Likewise. * reload1.c: Unconditionally include code that was previously conditional on SECONDARY_MEMORY_NEEDED. (choose_reload_regs): Use targetm.secondary_memory_needed instead of TARGET_SECONDARY_MEMORY_NEEDED. (gen_reload): Likewise. * system.h (SECONDARY_MEMORY_NEEDED): Poison. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r252461
This commit is contained in:
parent
94e23f53d7
commit
f15643d4ea
@ -1,3 +1,101 @@
|
||||
2017-09-13 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
||||
* target.def (secondary_memory_needed): New hook.
|
||||
(secondary_reload): Refer to TARGET_SECONDARY_MEMORY_NEEDED
|
||||
instead of SECONDARY_MEMORY_NEEDED.
|
||||
(secondary_memory_needed_mode): Likewise.
|
||||
* hooks.h (hook_bool_mode_reg_class_t_reg_class_t_false): Declare.
|
||||
* hooks.c (hook_bool_mode_reg_class_t_reg_class_t_false): New function.
|
||||
* doc/tm.texi.in (SECONDARY_MEMORY_NEEDED): Replace with...
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): ...this.
|
||||
(SECONDARY_MEMORY_NEEDED_RTX): Update reference accordingly.
|
||||
* doc/tm.texi: Regenerate.
|
||||
* config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/alpha/alpha.c (alpha_secondary_memory_needed): New function.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
* config/i386/i386.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/i386/i386-protos.h (ix86_secondary_memory_needed): Delete.
|
||||
* config/i386/i386.c (inline_secondary_memory_needed): Put the
|
||||
mode argument first and change the reg_class arguments to reg_class_t.
|
||||
(ix86_secondary_memory_needed): Likewise. Remove the strict parameter.
|
||||
Make static. Update the call to inline_secondary_memory_needed.
|
||||
(ix86_register_move_cost): Update the call to
|
||||
inline_secondary_memory_needed.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
* config/ia64/ia64.h (SECONDARY_MEMORY_NEEDED): Delete commented-out
|
||||
definition.
|
||||
* config/ia64/ia64.c (spill_xfmode_rfmode_operand): Refer to
|
||||
TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED
|
||||
in comment.
|
||||
* config/mips/mips.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/mips/mips-protos.h (mips_secondary_memory_needed): Delete.
|
||||
* config/mips/mips.c (mips_secondary_memory_needed): Make static
|
||||
and match hook interface. Add comment from mips.h.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
* config/mmix/mmix.md (truncdfsf2): Refer to
|
||||
TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED
|
||||
in comment.
|
||||
* config/pa/pa-64.h (SECONDARY_MEMORY_NEEDED): Rename to...
|
||||
(PA_SECONDARY_MEMORY_NEEDED): ...this, and put the mode argument first.
|
||||
* config/pa/pa.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
(pa_secondary_memory_needed): New function.
|
||||
* config/pdp11/pdp11.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/pdp11/pdp11-protos.h (pdp11_secondary_memory_needed): Delete.
|
||||
* config/pdp11/pdp11.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
(pdp11_secondary_memory_needed): Make static and match hook interface.
|
||||
* config/powerpcspe/powerpcspe.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/powerpcspe/powerpcspe-protos.h
|
||||
(rs6000_secondary_memory_needed_ptr): Delete.
|
||||
* config/powerpcspe/powerpcspe.c (rs6000_secondary_memory_needed_ptr):
|
||||
Delete.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
(rs6000_option_override_internal): Assign to
|
||||
targetm.secondary_memory_needed rather than
|
||||
rs6000_secondary_memory_needed_ptr.
|
||||
(rs6000_secondary_memory_needed): Match hook interface.
|
||||
(rs6000_debug_secondary_memory_needed): Likewise.
|
||||
* config/riscv/riscv.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/riscv/riscv.c (riscv_secondary_memory_needed): New function.
|
||||
(riscv_register_move_cost): Use it instead of SECONDARY_MEMORY_NEEDED.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
* config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/rs6000/rs6000-protos.h (rs6000_secondary_memory_needed_ptr):
|
||||
Delete.
|
||||
* config/rs6000/rs6000.c (rs6000_secondary_memory_needed_ptr): Delete.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
(rs6000_option_override_internal): Assign to
|
||||
targetm.secondary_memory_needed rather than
|
||||
rs6000_secondary_memory_needed_ptr.
|
||||
(rs6000_secondary_memory_needed): Match hook interface.
|
||||
(rs6000_debug_secondary_memory_needed): Likewise.
|
||||
* config/s390/s390.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/s390/s390.c (s390_secondary_memory_needed): New function.
|
||||
(TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED): Delete.
|
||||
* config/sparc/sparc.c (TARGET_SECONDARY_MEMORY_NEEDED): Redefine.
|
||||
(sparc_secondary_memory_needed): New function.
|
||||
* lra-constraints.c (check_and_process_move): Refer to
|
||||
TARGET_SECONDARY_MEMORY_NEEDED rather than SECONDARY_MEMORY_NEEDED
|
||||
in comment.
|
||||
(curr_insn_transform): Likewise.
|
||||
(process_alt_operands): Use targetm.secondary_memory_needed
|
||||
instead of TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
(check_secondary_memory_needed_p): Likewise.
|
||||
(choose_split_class): Likewise.
|
||||
* reload.c: Unconditionally include code that was previously
|
||||
conditional on SECONDARY_MEMORY_NEEDED.
|
||||
(push_secondary_reload): Use targetm.secondary_memory_needed
|
||||
instead of TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
(push_reload): Likewise.
|
||||
* reload1.c: Unconditionally include code that was previously
|
||||
conditional on SECONDARY_MEMORY_NEEDED.
|
||||
(choose_reload_regs): Use targetm.secondary_memory_needed
|
||||
instead of TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
(gen_reload): Likewise.
|
||||
* system.h (SECONDARY_MEMORY_NEEDED): Poison.
|
||||
|
||||
2017-09-13 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
@ -1689,6 +1689,20 @@ alpha_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
If we are copying between general and FP registers, we need a memory
|
||||
location unless the FIX extension is available. */
|
||||
|
||||
static bool
|
||||
alpha_secondary_memory_needed (machine_mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
return (!TARGET_FIX
|
||||
&& ((class1 == FLOAT_REGS && class2 != FLOAT_REGS)
|
||||
|| (class2 == FLOAT_REGS && class1 != FLOAT_REGS)));
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE. If MODE is
|
||||
floating-point, use it. Otherwise, widen to a word like the default.
|
||||
This is needed because we always store integers in FP registers in
|
||||
@ -10077,6 +10091,8 @@ alpha_modes_tieable_p (machine_mode mode1, machine_mode mode2)
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD alpha_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED alpha_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE alpha_secondary_memory_needed_mode
|
||||
|
||||
|
@ -479,13 +479,6 @@ enum reg_class {
|
||||
|
||||
#define PREFERRED_RELOAD_CLASS alpha_preferred_reload_class
|
||||
|
||||
/* If we are copying between general and FP registers, we need a memory
|
||||
location unless the FIX extension is available. */
|
||||
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
(! TARGET_FIX && (((CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS) \
|
||||
|| ((CLASS2) == FLOAT_REGS && (CLASS1) != FLOAT_REGS)))
|
||||
|
||||
/* Return the class of registers that cannot change mode from FROM to TO. */
|
||||
|
||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||
|
@ -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_secondary_memory_needed (enum reg_class, enum reg_class,
|
||||
machine_mode, int);
|
||||
extern bool ix86_cannot_change_mode_class (machine_mode,
|
||||
machine_mode, enum reg_class);
|
||||
|
||||
|
@ -41102,8 +41102,8 @@ ix86_class_likely_spilled_p (reg_class_t rclass)
|
||||
To optimize register_move_cost performance, define inline variant. */
|
||||
|
||||
static inline bool
|
||||
inline_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
|
||||
machine_mode mode, int strict)
|
||||
inline_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2, int strict)
|
||||
{
|
||||
if (lra_in_progress && (class1 == NO_REGS || class2 == NO_REGS))
|
||||
return false;
|
||||
@ -41155,11 +41155,13 @@ inline_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
|
||||
machine_mode mode, int strict)
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED. */
|
||||
|
||||
static bool
|
||||
ix86_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
return inline_secondary_memory_needed (class1, class2, mode, strict);
|
||||
return inline_secondary_memory_needed (mode, class1, class2, true);
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
|
||||
@ -41380,7 +41382,7 @@ ix86_register_move_cost (machine_mode mode, reg_class_t class1_i,
|
||||
by load. In order to avoid bad register allocation choices, we need
|
||||
for this to be *at least* as high as the symmetric MEMORY_MOVE_COST. */
|
||||
|
||||
if (inline_secondary_memory_needed (class1, class2, mode, 0))
|
||||
if (inline_secondary_memory_needed (mode, class1, class2, false))
|
||||
{
|
||||
int cost = 1;
|
||||
|
||||
@ -53220,6 +53222,8 @@ ix86_run_selftests (void)
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD ix86_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED ix86_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE ix86_secondary_memory_needed_mode
|
||||
|
||||
|
@ -1519,11 +1519,6 @@ enum reg_class
|
||||
#define INDEX_REG_CLASS INDEX_REGS
|
||||
#define BASE_REG_CLASS GENERAL_REGS
|
||||
|
||||
/* If we are copying between general and FP registers, we need a memory
|
||||
location. The same is true for SSE and MMX registers. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
ix86_secondary_memory_needed ((CLASS1), (CLASS2), (MODE), 1)
|
||||
|
||||
/* Return a class of registers that cannot change FROM mode to TO mode. */
|
||||
|
||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||
|
@ -1626,8 +1626,8 @@ ia64_split_tmode_move (rtx operands[])
|
||||
|
||||
/* ??? Fixing GR->FR XFmode moves during reload is hard. You need to go
|
||||
through memory plus an extra GR scratch register. Except that you can
|
||||
either get the first from SECONDARY_MEMORY_NEEDED or the second from
|
||||
SECONDARY_RELOAD_CLASS, but not both.
|
||||
either get the first from TARGET_SECONDARY_MEMORY_NEEDED or the second
|
||||
from SECONDARY_RELOAD_CLASS, but not both.
|
||||
|
||||
We got into problems in the first place by allowing a construct like
|
||||
(subreg:XF (reg:TI)), which we got from a union containing a long double.
|
||||
|
@ -767,24 +767,6 @@ enum reg_class
|
||||
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
|
||||
ia64_secondary_reload_class (CLASS, MODE, X)
|
||||
|
||||
/* Certain machines have the property that some registers cannot be copied to
|
||||
some other registers without using memory. Define this macro on those
|
||||
machines to be a C expression that is nonzero if objects of mode M in
|
||||
registers of CLASS1 can only be copied to registers of class CLASS2 by
|
||||
storing a register of CLASS1 into memory and loading that memory location
|
||||
into a register of CLASS2. */
|
||||
|
||||
#if 0
|
||||
/* ??? May need this, but since we've disallowed XFmode in GR_REGS,
|
||||
I'm not quite sure how it could be invoked. The normal problems
|
||||
with unions should be solved with the addressof fiddling done by
|
||||
movxf and friends. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
(((MODE) == XFmode || (MODE) == XCmode) \
|
||||
&& (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
|
||||
|| ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
|
||||
#endif
|
||||
|
||||
/* A C expression for the maximum number of consecutive registers of
|
||||
class CLASS needed to hold a value of mode MODE.
|
||||
This is closely related to TARGET_HARD_REGNO_NREGS. */
|
||||
|
@ -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_secondary_memory_needed (enum reg_class, enum reg_class,
|
||||
machine_mode);
|
||||
extern bool mips_cannot_change_mode_class (machine_mode,
|
||||
machine_mode, enum reg_class);
|
||||
extern bool mips_dangerous_for_la25_p (rtx);
|
||||
|
@ -13201,11 +13201,22 @@ mips_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in)
|
||||
+ memory_move_secondary_cost (mode, rclass, in));
|
||||
}
|
||||
|
||||
/* Implement SECONDARY_MEMORY_NEEDED. */
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
bool
|
||||
mips_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
|
||||
machine_mode mode)
|
||||
When targeting the o32 FPXX ABI, all moves with a length of doubleword
|
||||
or greater must be performed by FR-mode-aware instructions.
|
||||
This can be achieved using MFHC1/MTHC1 when these instructions are
|
||||
available but otherwise moves must go via memory.
|
||||
For the o32 FP64A ABI, all odd-numbered moves with a length of
|
||||
doubleword or greater are required to use memory. Using MTC1/MFC1
|
||||
to access the lower-half of these registers would require a forbidden
|
||||
single-precision access. We require all double-word moves to use
|
||||
memory because adding even and odd floating-point registers classes
|
||||
would have a significant impact on the backend. */
|
||||
|
||||
static bool
|
||||
mips_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
/* Ignore spilled pseudos. */
|
||||
if (lra_in_progress && (class1 == NO_REGS || class2 == NO_REGS))
|
||||
@ -22607,6 +22618,9 @@ mips_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
|
||||
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
|
||||
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
|
||||
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED mips_secondary_memory_needed
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
#include "gt-mips.h"
|
||||
|
@ -2298,19 +2298,6 @@ enum reg_class
|
||||
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
|
||||
mips_secondary_reload_class (CLASS, MODE, X, false)
|
||||
|
||||
/* When targeting the o32 FPXX ABI, all moves with a length of doubleword
|
||||
or greater must be performed by FR-mode-aware instructions.
|
||||
This can be achieved using MFHC1/MTHC1 when these instructions are
|
||||
available but otherwise moves must go via memory.
|
||||
For the o32 FP64A ABI, all odd-numbered moves with a length of
|
||||
doubleword or greater are required to use memory. Using MTC1/MFC1
|
||||
to access the lower-half of these registers would require a forbidden
|
||||
single-precision access. We require all double-word moves to use
|
||||
memory because adding even and odd floating-point registers classes
|
||||
would have a significant impact on the backend. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
mips_secondary_memory_needed ((CLASS1), (CLASS2), (MODE))
|
||||
|
||||
/* Return the maximum number of consecutive registers
|
||||
needed to represent mode MODE in a register of class CLASS. */
|
||||
|
||||
|
@ -623,7 +623,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
|
||||
;; possible to do that? Bug in GCC? Anyway, this used to be a simple
|
||||
;; pattern with a memory_operand predicate, but was split up with a
|
||||
;; define_expand with the old pattern as "anonymous".
|
||||
;; FIXME: Perhaps with SECONDARY_MEMORY_NEEDED?
|
||||
;; FIXME: Perhaps with TARGET_SECONDARY_MEMORY_NEEDED?
|
||||
(define_expand "truncdfsf2"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand")
|
||||
(float_truncate:SF (match_operand:DF 1 "register_operand")))]
|
||||
|
@ -97,7 +97,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
function which has no frame and this function might also use SP-16.
|
||||
We have 14-bit immediates on the 64-bit port, so we use secondary
|
||||
memory for the copies. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
#define PA_SECONDARY_MEMORY_NEEDED(MODE, CLASS1, CLASS2) \
|
||||
(MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \
|
||||
|| MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))
|
||||
|
||||
|
@ -178,6 +178,8 @@ static struct machine_function * pa_init_machine_status (void);
|
||||
static reg_class_t pa_secondary_reload (bool, rtx, reg_class_t,
|
||||
machine_mode,
|
||||
secondary_reload_info *);
|
||||
static bool pa_secondary_memory_needed (machine_mode,
|
||||
reg_class_t, reg_class_t);
|
||||
static void pa_extra_live_on_entry (bitmap);
|
||||
static machine_mode pa_promote_function_mode (const_tree,
|
||||
machine_mode, int *,
|
||||
@ -377,6 +379,8 @@ static size_t n_deferred_plabels = 0;
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD pa_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED pa_secondary_memory_needed
|
||||
|
||||
#undef TARGET_EXTRA_LIVE_ON_ENTRY
|
||||
#define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry
|
||||
@ -6189,6 +6193,20 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED. */
|
||||
|
||||
static bool
|
||||
pa_secondary_memory_needed (machine_mode mode ATTRIBUTE_UNUSED,
|
||||
reg_class_t class1 ATTRIBUTE_UNUSED,
|
||||
reg_class_t class2 ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef PA_SECONDARY_MEMORY_NEEDED
|
||||
return PA_SECONDARY_MEMORY_NEEDED (mode, class1, class2);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. The argument pointer
|
||||
is only marked as live on entry by df-scan when it is a fixed
|
||||
register. It isn't a fixed register in the 64-bit runtime,
|
||||
|
@ -31,8 +31,6 @@ 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);
|
||||
extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
|
||||
machine_mode);
|
||||
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,
|
||||
|
@ -243,6 +243,9 @@ static bool pdp11_scalar_mode_supported_p (scalar_mode);
|
||||
|
||||
#undef TARGET_MODES_TIEABLE_P
|
||||
#define TARGET_MODES_TIEABLE_P pdp11_modes_tieable_p
|
||||
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED pdp11_secondary_memory_needed
|
||||
|
||||
/* A helper function to determine if REGNO should be saved in the
|
||||
current function's stack frame. */
|
||||
@ -1453,14 +1456,13 @@ pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
|
||||
return LOAD_FPU_REGS;
|
||||
}
|
||||
|
||||
/* Target routine to check if register to register move requires memory.
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
The answer is yes if we're going between general register and FPU
|
||||
registers. The mode doesn't matter in making this check.
|
||||
*/
|
||||
bool
|
||||
pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
|
||||
machine_mode mode ATTRIBUTE_UNUSED)
|
||||
static bool
|
||||
pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
|
||||
{
|
||||
int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS ||
|
||||
c1 == FPU_REGS);
|
||||
|
@ -236,10 +236,6 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
|
||||
#define INDEX_REG_CLASS GENERAL_REGS
|
||||
#define BASE_REG_CLASS GENERAL_REGS
|
||||
|
||||
/* Hook for testing if memory is needed for moving between registers. */
|
||||
#define SECONDARY_MEMORY_NEEDED(class1, class2, m) \
|
||||
pdp11_secondary_memory_needed (class1, class2, m)
|
||||
|
||||
/* Return the maximum number of consecutive registers
|
||||
needed to represent mode MODE in a register of class CLASS. */
|
||||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
|
@ -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_secondary_memory_needed_ptr) (enum reg_class,
|
||||
enum reg_class,
|
||||
machine_mode);
|
||||
extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
|
||||
machine_mode,
|
||||
enum reg_class);
|
||||
|
@ -1384,11 +1384,9 @@ static enum reg_class rs6000_debug_secondary_reload_class (enum reg_class,
|
||||
static enum reg_class rs6000_preferred_reload_class (rtx, enum reg_class);
|
||||
static enum reg_class rs6000_debug_preferred_reload_class (rtx,
|
||||
enum reg_class);
|
||||
static bool rs6000_secondary_memory_needed (enum reg_class, enum reg_class,
|
||||
machine_mode);
|
||||
static bool rs6000_debug_secondary_memory_needed (enum reg_class,
|
||||
enum reg_class,
|
||||
machine_mode);
|
||||
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);
|
||||
@ -1412,10 +1410,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_secondary_memory_needed_ptr) (enum reg_class, enum reg_class,
|
||||
machine_mode)
|
||||
= rs6000_secondary_memory_needed;
|
||||
|
||||
bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
|
||||
machine_mode,
|
||||
enum reg_class)
|
||||
@ -1897,6 +1891,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED rs6000_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
|
||||
|
||||
@ -5098,7 +5094,7 @@ rs6000_option_override_internal (bool global_init_p)
|
||||
targetm.legitimize_address = rs6000_debug_legitimize_address;
|
||||
rs6000_secondary_reload_class_ptr
|
||||
= rs6000_debug_secondary_reload_class;
|
||||
rs6000_secondary_memory_needed_ptr
|
||||
targetm.secondary_memory_needed
|
||||
= rs6000_debug_secondary_memory_needed;
|
||||
rs6000_cannot_change_mode_class_ptr
|
||||
= rs6000_debug_cannot_change_mode_class;
|
||||
@ -23149,9 +23145,9 @@ rs6000_debug_preferred_reload_class (rtx x, enum reg_class rclass)
|
||||
set and vice versa. */
|
||||
|
||||
static bool
|
||||
rs6000_secondary_memory_needed (enum reg_class from_class,
|
||||
enum reg_class to_class,
|
||||
machine_mode mode)
|
||||
rs6000_secondary_memory_needed (machine_mode mode,
|
||||
reg_class_t from_class,
|
||||
reg_class_t to_class)
|
||||
{
|
||||
enum rs6000_reg_type from_type, to_type;
|
||||
bool altivec_p = ((from_class == ALTIVEC_REGS)
|
||||
@ -23175,11 +23171,11 @@ rs6000_secondary_memory_needed (enum reg_class from_class,
|
||||
|
||||
/* Debug version of rs6000_secondary_memory_needed. */
|
||||
static bool
|
||||
rs6000_debug_secondary_memory_needed (enum reg_class from_class,
|
||||
enum reg_class to_class,
|
||||
machine_mode mode)
|
||||
rs6000_debug_secondary_memory_needed (machine_mode mode,
|
||||
reg_class_t from_class,
|
||||
reg_class_t to_class)
|
||||
{
|
||||
bool ret = rs6000_secondary_memory_needed (from_class, to_class, mode);
|
||||
bool ret = rs6000_secondary_memory_needed (mode, from_class, to_class);
|
||||
|
||||
fprintf (stderr,
|
||||
"rs6000_secondary_memory_needed, return: %s, from_class = %s, "
|
||||
|
@ -1596,14 +1596,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
|
||||
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
|
||||
rs6000_secondary_reload_class_ptr (CLASS, MODE, IN)
|
||||
|
||||
/* If we are copying between FP or AltiVec registers and anything
|
||||
else, we need a memory location. The exception is when we are
|
||||
targeting ppc64 and the move to/from fpr to gpr instructions
|
||||
are available.*/
|
||||
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
rs6000_secondary_memory_needed_ptr (CLASS1, CLASS2, MODE)
|
||||
|
||||
/* For cpus that cannot load/store SDmode values from the 64-bit
|
||||
FP registers without using a full 64-bit load/store, we need
|
||||
to allocate a full 64-bit stack slot for them. */
|
||||
|
@ -3510,13 +3510,26 @@ riscv_can_use_return_insn (void)
|
||||
return reload_completed && cfun->machine->frame.total_size == 0;
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
When floating-point registers are wider than integer ones, moves between
|
||||
them must go through memory. */
|
||||
|
||||
static bool
|
||||
riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
return (GET_MODE_SIZE (mode) > UNITS_PER_WORD
|
||||
&& (class1 == FP_REGS) != (class2 == FP_REGS));
|
||||
}
|
||||
|
||||
/* Implement TARGET_REGISTER_MOVE_COST. */
|
||||
|
||||
static int
|
||||
riscv_register_move_cost (machine_mode mode,
|
||||
reg_class_t from, reg_class_t to)
|
||||
{
|
||||
return SECONDARY_MEMORY_NEEDED (from, to, mode) ? 8 : 2;
|
||||
return riscv_secondary_memory_needed (mode, from, to) ? 8 : 2;
|
||||
}
|
||||
|
||||
/* Implement TARGET_HARD_REGNO_NREGS. */
|
||||
@ -4115,6 +4128,9 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
|
||||
#undef TARGET_SLOW_UNALIGNED_ACCESS
|
||||
#define TARGET_SLOW_UNALIGNED_ACCESS riscv_slow_unaligned_access
|
||||
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED riscv_secondary_memory_needed
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
#include "gt-riscv.h"
|
||||
|
@ -221,12 +221,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
Extensions of pointers to word_mode must be signed. */
|
||||
#define POINTERS_EXTEND_UNSIGNED false
|
||||
|
||||
/* When floating-point registers are wider than integer ones, moves between
|
||||
them must go through memory. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
(GET_MODE_SIZE (MODE) > UNITS_PER_WORD \
|
||||
&& ((CLASS1) == FP_REGS) != ((CLASS2) == FP_REGS))
|
||||
|
||||
/* Define if loading short immediate values into registers sign extends. */
|
||||
#define SHORT_IMMEDIATES_SIGN_EXTEND 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_secondary_memory_needed_ptr) (enum reg_class,
|
||||
enum reg_class,
|
||||
machine_mode);
|
||||
extern bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
|
||||
machine_mode,
|
||||
enum reg_class);
|
||||
|
@ -1389,11 +1389,9 @@ static enum reg_class rs6000_debug_secondary_reload_class (enum reg_class,
|
||||
static enum reg_class rs6000_preferred_reload_class (rtx, enum reg_class);
|
||||
static enum reg_class rs6000_debug_preferred_reload_class (rtx,
|
||||
enum reg_class);
|
||||
static bool rs6000_secondary_memory_needed (enum reg_class, enum reg_class,
|
||||
machine_mode);
|
||||
static bool rs6000_debug_secondary_memory_needed (enum reg_class,
|
||||
enum reg_class,
|
||||
machine_mode);
|
||||
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);
|
||||
@ -1417,10 +1415,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_secondary_memory_needed_ptr) (enum reg_class, enum reg_class,
|
||||
machine_mode)
|
||||
= rs6000_secondary_memory_needed;
|
||||
|
||||
bool (*rs6000_cannot_change_mode_class_ptr) (machine_mode,
|
||||
machine_mode,
|
||||
enum reg_class)
|
||||
@ -1876,6 +1870,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED rs6000_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
|
||||
|
||||
@ -4716,7 +4712,7 @@ rs6000_option_override_internal (bool global_init_p)
|
||||
targetm.legitimize_address = rs6000_debug_legitimize_address;
|
||||
rs6000_secondary_reload_class_ptr
|
||||
= rs6000_debug_secondary_reload_class;
|
||||
rs6000_secondary_memory_needed_ptr
|
||||
targetm.secondary_memory_needed
|
||||
= rs6000_debug_secondary_memory_needed;
|
||||
rs6000_cannot_change_mode_class_ptr
|
||||
= rs6000_debug_cannot_change_mode_class;
|
||||
@ -20491,9 +20487,9 @@ rs6000_debug_preferred_reload_class (rtx x, enum reg_class rclass)
|
||||
set and vice versa. */
|
||||
|
||||
static bool
|
||||
rs6000_secondary_memory_needed (enum reg_class from_class,
|
||||
enum reg_class to_class,
|
||||
machine_mode mode)
|
||||
rs6000_secondary_memory_needed (machine_mode mode,
|
||||
reg_class_t from_class,
|
||||
reg_class_t to_class)
|
||||
{
|
||||
enum rs6000_reg_type from_type, to_type;
|
||||
bool altivec_p = ((from_class == ALTIVEC_REGS)
|
||||
@ -20517,11 +20513,11 @@ rs6000_secondary_memory_needed (enum reg_class from_class,
|
||||
|
||||
/* Debug version of rs6000_secondary_memory_needed. */
|
||||
static bool
|
||||
rs6000_debug_secondary_memory_needed (enum reg_class from_class,
|
||||
enum reg_class to_class,
|
||||
machine_mode mode)
|
||||
rs6000_debug_secondary_memory_needed (machine_mode mode,
|
||||
reg_class_t from_class,
|
||||
reg_class_t to_class)
|
||||
{
|
||||
bool ret = rs6000_secondary_memory_needed (from_class, to_class, mode);
|
||||
bool ret = rs6000_secondary_memory_needed (mode, from_class, to_class);
|
||||
|
||||
fprintf (stderr,
|
||||
"rs6000_secondary_memory_needed, return: %s, from_class = %s, "
|
||||
|
@ -1506,14 +1506,6 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
|
||||
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
|
||||
rs6000_secondary_reload_class_ptr (CLASS, MODE, IN)
|
||||
|
||||
/* If we are copying between FP or AltiVec registers and anything
|
||||
else, we need a memory location. The exception is when we are
|
||||
targeting ppc64 and the move to/from fpr to gpr instructions
|
||||
are available.*/
|
||||
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
rs6000_secondary_memory_needed_ptr (CLASS1, CLASS2, MODE)
|
||||
|
||||
/* Return the maximum number of consecutive registers
|
||||
needed to represent mode MODE in a register of class CLASS.
|
||||
|
||||
|
@ -4409,6 +4409,35 @@ s390_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
We need secondary memory to move data between GPRs and FPRs.
|
||||
|
||||
- With DFP the ldgr lgdr instructions are available. Due to the
|
||||
different alignment we cannot use them for SFmode. For 31 bit a
|
||||
64 bit value in GPR would be a register pair so here we still
|
||||
need to go via memory.
|
||||
|
||||
- With z13 we can do the SF/SImode moves with vlgvf. Due to the
|
||||
overlapping of FPRs and VRs we still disallow TF/TD modes to be
|
||||
in full VRs so as before also on z13 we do these moves via
|
||||
memory.
|
||||
|
||||
FIXME: Should we try splitting it into two vlgvg's/vlvg's instead? */
|
||||
|
||||
static bool
|
||||
s390_secondary_memory_needed (machine_mode mode,
|
||||
reg_class_t class1, reg_class_t class2)
|
||||
{
|
||||
return (((reg_classes_intersect_p (class1, VEC_REGS)
|
||||
&& reg_classes_intersect_p (class2, GENERAL_REGS))
|
||||
|| (reg_classes_intersect_p (class1, GENERAL_REGS)
|
||||
&& reg_classes_intersect_p (class2, VEC_REGS)))
|
||||
&& (!TARGET_DFP || !TARGET_64BIT || GET_MODE_SIZE (mode) != 8)
|
||||
&& (!TARGET_VX || (SCALAR_FLOAT_MODE_P (mode)
|
||||
&& GET_MODE_SIZE (mode) > 8)));
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
|
||||
|
||||
get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
|
||||
@ -15972,6 +16001,8 @@ s390_asan_shadow_offset (void)
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD s390_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED s390_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE s390_secondary_memory_needed_mode
|
||||
|
||||
|
@ -577,29 +577,6 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
|
||||
#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
|
||||
|
||||
|
||||
/* We need secondary memory to move data between GPRs and FPRs.
|
||||
|
||||
- With DFP the ldgr lgdr instructions are available. Due to the
|
||||
different alignment we cannot use them for SFmode. For 31 bit a
|
||||
64 bit value in GPR would be a register pair so here we still
|
||||
need to go via memory.
|
||||
|
||||
- With z13 we can do the SF/SImode moves with vlgvf. Due to the
|
||||
overlapping of FPRs and VRs we still disallow TF/TD modes to be
|
||||
in full VRs so as before also on z13 we do these moves via
|
||||
memory.
|
||||
|
||||
FIXME: Should we try splitting it into two vlgvg's/vlvg's instead? */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
(((reg_classes_intersect_p ((CLASS1), VEC_REGS) \
|
||||
&& reg_classes_intersect_p ((CLASS2), GENERAL_REGS)) \
|
||||
|| (reg_classes_intersect_p ((CLASS1), GENERAL_REGS) \
|
||||
&& reg_classes_intersect_p ((CLASS2), VEC_REGS))) \
|
||||
&& (!TARGET_DFP || !TARGET_64BIT || GET_MODE_SIZE (MODE) != 8) \
|
||||
&& (!TARGET_VX || (SCALAR_FLOAT_MODE_P (MODE) \
|
||||
&& GET_MODE_SIZE (MODE) > 8)))
|
||||
|
||||
|
||||
/* Stack layout and calling conventions. */
|
||||
|
||||
/* Our stack grows from higher to lower addresses. However, local variables
|
||||
|
@ -672,6 +672,8 @@ static void sparc_print_operand_address (FILE *, machine_mode, rtx);
|
||||
static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
|
||||
machine_mode,
|
||||
secondary_reload_info *);
|
||||
static bool sparc_secondary_memory_needed (machine_mode, reg_class_t,
|
||||
reg_class_t);
|
||||
static machine_mode sparc_secondary_memory_needed_mode (machine_mode);
|
||||
static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
|
||||
static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
|
||||
@ -860,6 +862,8 @@ char sparc_hard_reg_printed[8];
|
||||
|
||||
#undef TARGET_SECONDARY_RELOAD
|
||||
#define TARGET_SECONDARY_RELOAD sparc_secondary_reload
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED sparc_secondary_memory_needed
|
||||
#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
#define TARGET_SECONDARY_MEMORY_NEEDED_MODE sparc_secondary_memory_needed_mode
|
||||
|
||||
@ -13053,6 +13057,21 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
|
||||
|
||||
On SPARC when not VIS3 it is not possible to directly move data
|
||||
between GENERAL_REGS and FP_REGS. */
|
||||
|
||||
static bool
|
||||
sparc_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
return ((FP_REG_CLASS_P (class1) != FP_REG_CLASS_P (class2))
|
||||
&& (! TARGET_VIS3
|
||||
|| GET_MODE_SIZE (mode) > 8
|
||||
|| GET_MODE_SIZE (mode) < 4));
|
||||
}
|
||||
|
||||
/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
|
||||
|
||||
get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
|
||||
|
@ -1047,14 +1047,6 @@ extern char leaf_reg_remap[];
|
||||
#define SPARC_SETHI32_P(X) \
|
||||
(SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
|
||||
|
||||
/* On SPARC when not VIS3 it is not possible to directly move data
|
||||
between GENERAL_REGS and FP_REGS. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
((FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) \
|
||||
&& (! TARGET_VIS3 \
|
||||
|| GET_MODE_SIZE (MODE) > 8 \
|
||||
|| GET_MODE_SIZE (MODE) < 4))
|
||||
|
||||
/* Return the maximum number of consecutive registers
|
||||
needed to represent mode MODE in a register of class CLASS. */
|
||||
/* On SPARC, this is the size of MODE in words. */
|
||||
|
@ -2656,7 +2656,7 @@ in memory and the hard register number if it is in a register.
|
||||
|
||||
Scratch operands in memory (constraint @code{"=m"} / @code{"=&m"}) are
|
||||
currently not supported. For the time being, you will have to continue
|
||||
to use @code{SECONDARY_MEMORY_NEEDED} for that purpose.
|
||||
to use @code{TARGET_SECONDARY_MEMORY_NEEDED} for that purpose.
|
||||
|
||||
@code{copy_cost} also uses this target hook to find out how values are
|
||||
copied. If you want it to include some extra cost for the need to allocate
|
||||
@ -2726,29 +2726,28 @@ intermediate storage. This case often occurs between floating-point and
|
||||
general registers.
|
||||
@end defmac
|
||||
|
||||
@defmac SECONDARY_MEMORY_NEEDED (@var{class1}, @var{class2}, @var{m})
|
||||
@deftypefn {Target Hook} bool TARGET_SECONDARY_MEMORY_NEEDED (machine_mode @var{mode}, reg_class_t @var{class1}, reg_class_t @var{class2})
|
||||
Certain machines have the property that some registers cannot be copied
|
||||
to some other registers without using memory. Define this macro on
|
||||
those machines to be a C expression that is nonzero if objects of mode
|
||||
@var{m} in registers of @var{class1} can only be copied to registers of
|
||||
class @var{class2} by storing a register of @var{class1} into memory
|
||||
and loading that memory location into a register of @var{class2}.
|
||||
|
||||
Do not define this macro if its value would always be zero.
|
||||
@end defmac
|
||||
to some other registers without using memory. Define this hook on
|
||||
those machines to return true if objects of mode @var{m} in registers
|
||||
of @var{class1} can only be copied to registers of class @var{class2} by
|
||||
storing a register of @var{class1} into memory and loading that memory
|
||||
location into a register of @var{class2}. The default definition returns
|
||||
false for all inputs.
|
||||
@end deftypefn
|
||||
|
||||
@defmac SECONDARY_MEMORY_NEEDED_RTX (@var{mode})
|
||||
Normally when @code{SECONDARY_MEMORY_NEEDED} is defined, the compiler
|
||||
Normally when @code{TARGET_SECONDARY_MEMORY_NEEDED} is defined, the compiler
|
||||
allocates a stack slot for a memory location needed for register copies.
|
||||
If this macro is defined, the compiler instead uses the memory location
|
||||
defined by this macro.
|
||||
|
||||
Do not define this macro if you do not define
|
||||
@code{SECONDARY_MEMORY_NEEDED}.
|
||||
@code{TARGET_SECONDARY_MEMORY_NEEDED}.
|
||||
@end defmac
|
||||
|
||||
@deftypefn {Target Hook} machine_mode TARGET_SECONDARY_MEMORY_NEEDED_MODE (machine_mode @var{mode})
|
||||
If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory
|
||||
If @code{TARGET_SECONDARY_MEMORY_NEEDED} tells the compiler to use memory
|
||||
when moving between two particular registers of mode @var{mode},
|
||||
this hook specifies the mode that the memory should have.
|
||||
|
||||
|
@ -2303,25 +2303,16 @@ intermediate storage. This case often occurs between floating-point and
|
||||
general registers.
|
||||
@end defmac
|
||||
|
||||
@defmac SECONDARY_MEMORY_NEEDED (@var{class1}, @var{class2}, @var{m})
|
||||
Certain machines have the property that some registers cannot be copied
|
||||
to some other registers without using memory. Define this macro on
|
||||
those machines to be a C expression that is nonzero if objects of mode
|
||||
@var{m} in registers of @var{class1} can only be copied to registers of
|
||||
class @var{class2} by storing a register of @var{class1} into memory
|
||||
and loading that memory location into a register of @var{class2}.
|
||||
|
||||
Do not define this macro if its value would always be zero.
|
||||
@end defmac
|
||||
@hook TARGET_SECONDARY_MEMORY_NEEDED
|
||||
|
||||
@defmac SECONDARY_MEMORY_NEEDED_RTX (@var{mode})
|
||||
Normally when @code{SECONDARY_MEMORY_NEEDED} is defined, the compiler
|
||||
Normally when @code{TARGET_SECONDARY_MEMORY_NEEDED} is defined, the compiler
|
||||
allocates a stack slot for a memory location needed for register copies.
|
||||
If this macro is defined, the compiler instead uses the memory location
|
||||
defined by this macro.
|
||||
|
||||
Do not define this macro if you do not define
|
||||
@code{SECONDARY_MEMORY_NEEDED}.
|
||||
@code{TARGET_SECONDARY_MEMORY_NEEDED}.
|
||||
@end defmac
|
||||
|
||||
@hook TARGET_SECONDARY_MEMORY_NEEDED_MODE
|
||||
|
@ -495,3 +495,12 @@ hook_bool_reg_class_t_false (reg_class_t regclass ATTRIBUTE_UNUSED)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generic hook that takes a machine_mode and 2 register classes
|
||||
and returns false. */
|
||||
bool
|
||||
hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode, reg_class_t,
|
||||
reg_class_t)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,9 @@ 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_reg_class_t_reg_class_t_false (machine_mode,
|
||||
reg_class_t,
|
||||
reg_class_t);
|
||||
extern bool hook_bool_rtx_mode_int_int_intp_bool_false (rtx, machine_mode,
|
||||
int, int, int *, bool);
|
||||
extern bool hook_bool_tree_tree_false (tree, tree);
|
||||
|
@ -1159,8 +1159,8 @@ emit_spill_move (bool to_p, rtx mem_pseudo, rtx val)
|
||||
|
||||
/* Process a special case insn (register move), return true if we
|
||||
don't need to process it anymore. INSN should be a single set
|
||||
insn. Set up that RTL was changed through CHANGE_P and macro
|
||||
SECONDARY_MEMORY_NEEDED says to use secondary memory through
|
||||
insn. Set up that RTL was changed through CHANGE_P and that hook
|
||||
TARGET_SECONDARY_MEMORY_NEEDED says to use secondary memory through
|
||||
SEC_MEM_P. */
|
||||
static bool
|
||||
check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
|
||||
@ -1201,8 +1201,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
|
||||
return false;
|
||||
if (sclass == NO_REGS && dclass == NO_REGS)
|
||||
return false;
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
|
||||
if (targetm.secondary_memory_needed (GET_MODE (src), sclass, dclass)
|
||||
&& ((sclass != NO_REGS && dclass != NO_REGS)
|
||||
|| (GET_MODE (src)
|
||||
!= targetm.secondary_memory_needed_mode (GET_MODE (src)))))
|
||||
@ -1210,7 +1209,6 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
|
||||
*sec_mem_p = true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (! REG_P (dreg) || ! REG_P (sreg))
|
||||
return false;
|
||||
sri.prev_sri = NULL;
|
||||
@ -2739,19 +2737,18 @@ process_alt_operands (int only_alternative)
|
||||
reject += 3;
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If reload requires moving value through secondary
|
||||
memory, it will need one more insn at least. */
|
||||
if (this_alternative != NO_REGS
|
||||
&& REG_P (op) && (cl = get_reg_class (REGNO (op))) != NO_REGS
|
||||
&& ((curr_static_id->operand[nop].type != OP_OUT
|
||||
&& SECONDARY_MEMORY_NEEDED (cl, this_alternative,
|
||||
GET_MODE (op)))
|
||||
&& targetm.secondary_memory_needed (GET_MODE (op), cl,
|
||||
this_alternative))
|
||||
|| (curr_static_id->operand[nop].type != OP_IN
|
||||
&& SECONDARY_MEMORY_NEEDED (this_alternative, cl,
|
||||
GET_MODE (op)))))
|
||||
&& (targetm.secondary_memory_needed
|
||||
(GET_MODE (op), this_alternative, cl)))))
|
||||
losers++;
|
||||
#endif
|
||||
|
||||
/* Input reloads can be inherited more often than output
|
||||
reloads can be removed, so penalize output
|
||||
reloads. */
|
||||
@ -3716,9 +3713,7 @@ curr_insn_transform (bool check_only_p)
|
||||
/* Flag that the insn has been changed through a transformation. */
|
||||
bool change_p;
|
||||
bool sec_mem_p;
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
bool use_sec_mem_p;
|
||||
#endif
|
||||
int max_regno_before;
|
||||
int reused_alternative_num;
|
||||
|
||||
@ -3899,8 +3894,7 @@ curr_insn_transform (bool check_only_p)
|
||||
change_p = true;
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* Some target macros SECONDARY_MEMORY_NEEDED (e.g. x86) are defined
|
||||
/* Some targets' TARGET_SECONDARY_MEMORY_NEEDED (e.g. x86) are defined
|
||||
too conservatively. So we use the secondary memory only if there
|
||||
is no any alternative without reloads. */
|
||||
use_sec_mem_p = false;
|
||||
@ -3985,7 +3979,6 @@ curr_insn_transform (bool check_only_p)
|
||||
lra_update_insn_regno_info (curr_insn);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
lra_assert (goal_alt_number >= 0);
|
||||
lra_set_used_insn_alternative (curr_insn, goal_alt_number);
|
||||
@ -5084,9 +5077,6 @@ static bool
|
||||
check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED,
|
||||
rtx usage_insns ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifndef SECONDARY_MEMORY_NEEDED
|
||||
return false;
|
||||
#else
|
||||
rtx_insn *insn;
|
||||
rtx set, dest;
|
||||
enum reg_class cl;
|
||||
@ -5103,8 +5093,7 @@ check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED,
|
||||
lra_assert (inher_cl != NO_REGS);
|
||||
cl = get_reg_class (REGNO (dest));
|
||||
return (cl != NO_REGS && cl != ALL_REGS
|
||||
&& SECONDARY_MEMORY_NEEDED (inher_cl, cl, GET_MODE (dest)));
|
||||
#endif
|
||||
&& targetm.secondary_memory_needed (GET_MODE (dest), inher_cl, cl));
|
||||
}
|
||||
|
||||
/* Registers involved in inheritance/split in the current EBB
|
||||
@ -5364,28 +5353,24 @@ choose_split_class (enum reg_class allocno_class,
|
||||
int hard_regno ATTRIBUTE_UNUSED,
|
||||
machine_mode mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifndef SECONDARY_MEMORY_NEEDED
|
||||
return allocno_class;
|
||||
#else
|
||||
int i;
|
||||
enum reg_class cl, best_cl = NO_REGS;
|
||||
enum reg_class hard_reg_class ATTRIBUTE_UNUSED
|
||||
= REGNO_REG_CLASS (hard_regno);
|
||||
|
||||
if (! SECONDARY_MEMORY_NEEDED (allocno_class, allocno_class, mode)
|
||||
if (! targetm.secondary_memory_needed (mode, allocno_class, allocno_class)
|
||||
&& TEST_HARD_REG_BIT (reg_class_contents[allocno_class], hard_regno))
|
||||
return allocno_class;
|
||||
for (i = 0;
|
||||
(cl = reg_class_subclasses[allocno_class][i]) != LIM_REG_CLASSES;
|
||||
i++)
|
||||
if (! SECONDARY_MEMORY_NEEDED (cl, hard_reg_class, mode)
|
||||
&& ! SECONDARY_MEMORY_NEEDED (hard_reg_class, cl, mode)
|
||||
if (! targetm.secondary_memory_needed (mode, cl, hard_reg_class)
|
||||
&& ! targetm.secondary_memory_needed (mode, hard_reg_class, cl)
|
||||
&& TEST_HARD_REG_BIT (reg_class_contents[cl], hard_regno)
|
||||
&& (best_cl == NO_REGS
|
||||
|| ira_class_hard_regs_num[best_cl] < ira_class_hard_regs_num[cl]))
|
||||
best_cl = cl;
|
||||
return best_cl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Copy any equivalence information from ORIGINAL_REGNO to NEW_REGNO.
|
||||
|
31
gcc/reload.c
31
gcc/reload.c
@ -172,8 +172,6 @@ struct decomposition
|
||||
HOST_WIDE_INT end; /* Ending offset or register number. */
|
||||
};
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
|
||||
/* Save MEMs needed to copy from one class of registers to another. One MEM
|
||||
is used per mode, but normally only one or two modes are ever used.
|
||||
|
||||
@ -185,7 +183,6 @@ struct decomposition
|
||||
static rtx secondary_memlocs[NUM_MACHINE_MODES];
|
||||
static rtx secondary_memlocs_elim[NUM_MACHINE_MODES][MAX_RECOG_OPERANDS];
|
||||
static int secondary_memlocs_elim_used = 0;
|
||||
#endif
|
||||
|
||||
/* The instruction we are doing reloads for;
|
||||
so we can test whether a register dies in it. */
|
||||
@ -456,14 +453,13 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
|
||||
|
||||
if (s_reload == n_reloads)
|
||||
{
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to copy between the two reload regs,
|
||||
set it up now. Note that we do the input case before making
|
||||
the reload and the output case after. This is due to the
|
||||
way reloads are output. */
|
||||
|
||||
if (in_p && icode == CODE_FOR_nothing
|
||||
&& SECONDARY_MEMORY_NEEDED (rclass, reload_class, mode))
|
||||
&& targetm.secondary_memory_needed (mode, rclass, reload_class))
|
||||
{
|
||||
get_secondary_mem (x, reload_mode, opnum, type);
|
||||
|
||||
@ -471,7 +467,6 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
|
||||
the new reload at the end. */
|
||||
s_reload = n_reloads;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We need to make a new secondary reload for this register class. */
|
||||
rld[s_reload].in = rld[s_reload].out = 0;
|
||||
@ -497,11 +492,9 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
|
||||
|
||||
n_reloads++;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
if (! in_p && icode == CODE_FOR_nothing
|
||||
&& SECONDARY_MEMORY_NEEDED (reload_class, rclass, mode))
|
||||
&& targetm.secondary_memory_needed (mode, reload_class, rclass))
|
||||
get_secondary_mem (x, mode, opnum, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
*picode = icode;
|
||||
@ -556,8 +549,6 @@ scratch_reload_class (enum insn_code icode)
|
||||
return rclass;
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
|
||||
/* Return a memory location that will be used to copy X in mode MODE.
|
||||
If we haven't already made a location for this mode in this insn,
|
||||
call find_reloads_address on the location being returned. */
|
||||
@ -634,7 +625,6 @@ clear_secondary_mem (void)
|
||||
{
|
||||
memset (secondary_memlocs, 0, sizeof secondary_memlocs);
|
||||
}
|
||||
#endif /* SECONDARY_MEMORY_NEEDED */
|
||||
|
||||
|
||||
/* Find the largest class which has at least one register valid in
|
||||
@ -1353,7 +1343,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||
/* We found no existing reload suitable for re-use.
|
||||
So add an additional reload. */
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
if (subreg_in_class == NO_REGS
|
||||
&& in != 0
|
||||
&& (REG_P (in)
|
||||
@ -1362,9 +1351,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||
subreg_in_class = REGNO_REG_CLASS (reg_or_subregno (in));
|
||||
/* If a memory location is needed for the copy, make one. */
|
||||
if (subreg_in_class != NO_REGS
|
||||
&& SECONDARY_MEMORY_NEEDED (subreg_in_class, rclass, inmode))
|
||||
&& targetm.secondary_memory_needed (inmode, subreg_in_class, rclass))
|
||||
get_secondary_mem (in, inmode, opnum, type);
|
||||
#endif
|
||||
|
||||
i = n_reloads;
|
||||
rld[i].in = in;
|
||||
@ -1388,16 +1376,13 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||
|
||||
n_reloads++;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
if (out != 0
|
||||
&& (REG_P (out)
|
||||
|| (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
|
||||
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (rclass,
|
||||
REGNO_REG_CLASS (reg_or_subregno (out)),
|
||||
outmode))
|
||||
&& (targetm.secondary_memory_needed
|
||||
(outmode, rclass, REGNO_REG_CLASS (reg_or_subregno (out)))))
|
||||
get_secondary_mem (out, outmode, opnum, type);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1797,14 +1782,12 @@ combine_reloads (void)
|
||||
[(int) rld[output_reload].outmode])
|
||||
&& rld[i].inc == 0
|
||||
&& rld[i].reg_rtx == 0
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* Don't combine two reloads with different secondary
|
||||
memory locations. */
|
||||
&& (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum] == 0
|
||||
|| secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] == 0
|
||||
|| rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
|
||||
secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
|
||||
#endif
|
||||
&& (targetm.small_register_classes_for_mode_p (VOIDmode)
|
||||
? (rld[i].rclass == rld[output_reload].rclass)
|
||||
: (reg_class_subset_p (rld[i].rclass,
|
||||
@ -1854,12 +1837,10 @@ combine_reloads (void)
|
||||
= rld[output_reload].secondary_out_icode;
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* Copy any secondary MEM. */
|
||||
if (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum] != 0)
|
||||
secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum]
|
||||
= secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum];
|
||||
#endif
|
||||
/* If required, minimize the register class. */
|
||||
if (reg_class_subset_p (rld[output_reload].rclass,
|
||||
rld[i].rclass))
|
||||
@ -2668,7 +2649,6 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
|
||||
if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (insn)))
|
||||
no_output_reloads = 1;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* The eliminated forms of any secondary memory locations are per-insn, so
|
||||
clear them out here. */
|
||||
|
||||
@ -2678,7 +2658,6 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
|
||||
sizeof (secondary_memlocs_elim[0]) * secondary_memlocs_elim_used);
|
||||
secondary_memlocs_elim_used = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
|
||||
is cheap to move between them. If it is not, there may not be an insn
|
||||
|
@ -768,10 +768,8 @@ reload (rtx_insn *first, int global)
|
||||
/* Enable find_equiv_reg to distinguish insns made by reload. */
|
||||
reload_first_uid = get_max_uid ();
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* Initialize the secondary memory table. */
|
||||
clear_secondary_mem ();
|
||||
#endif
|
||||
|
||||
/* We don't have a stack slot for any spill reg yet. */
|
||||
memset (spill_stack_slot, 0, sizeof spill_stack_slot);
|
||||
@ -6331,7 +6329,6 @@ choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx)
|
||||
rld[i].when_needed, rld[i].mode);
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If X is not a subreg, return it unmodified. If it is a subreg,
|
||||
look up whether we made a replacement for the SUBREG_REG. Return
|
||||
either the replacement or the SUBREG_REG. */
|
||||
@ -6343,7 +6340,6 @@ replaced_subreg (rtx x)
|
||||
return find_replacement (&SUBREG_REG (x));
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute the offset to pass to subreg_regno_offset, for a pseudo of
|
||||
mode OUTERMODE that is available in a hard reg of mode INNERMODE.
|
||||
@ -6593,12 +6589,8 @@ choose_reload_regs (struct insn_chain *chain)
|
||||
&& (secondary_reload_class (1, rclass, mode,
|
||||
last_reg)
|
||||
== NO_REGS)
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
&& ! SECONDARY_MEMORY_NEEDED (last_class, rclass,
|
||||
mode)
|
||||
#endif
|
||||
))
|
||||
|
||||
&& !(targetm.secondary_memory_needed
|
||||
(mode, last_class, rclass))))
|
||||
&& (rld[r].nregs == max_group_size
|
||||
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
|
||||
i))
|
||||
@ -6973,9 +6965,7 @@ choose_reload_regs (struct insn_chain *chain)
|
||||
{
|
||||
int r = reload_order[j];
|
||||
rtx check_reg;
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
rtx tem;
|
||||
#endif
|
||||
if (reload_inherited[r] && rld[r].reg_rtx)
|
||||
check_reg = rld[r].reg_rtx;
|
||||
else if (reload_override_in[r]
|
||||
@ -7014,15 +7004,15 @@ choose_reload_regs (struct insn_chain *chain)
|
||||
if (pass)
|
||||
pass = 2;
|
||||
}
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we needed a memory location for the reload, we also have to
|
||||
remove its related reloads. */
|
||||
else if (rld[r].in
|
||||
&& rld[r].out != rld[r].in
|
||||
&& (tem = replaced_subreg (rld[r].in), REG_P (tem))
|
||||
&& REGNO (tem) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem)),
|
||||
rld[r].rclass, rld[r].inmode)
|
||||
&& (targetm.secondary_memory_needed
|
||||
(rld[r].inmode, REGNO_REG_CLASS (REGNO (tem)),
|
||||
rld[r].rclass))
|
||||
&& remove_address_replacements
|
||||
(get_secondary_mem (tem, rld[r].inmode, rld[r].opnum,
|
||||
rld[r].when_needed)))
|
||||
@ -7030,7 +7020,6 @@ choose_reload_regs (struct insn_chain *chain)
|
||||
if (pass)
|
||||
pass = 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -8535,9 +8524,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
||||
{
|
||||
rtx_insn *last = get_last_insn ();
|
||||
rtx_insn *tem;
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
rtx tem1, tem2;
|
||||
#endif
|
||||
|
||||
/* If IN is a paradoxical SUBREG, remove it and try to put the
|
||||
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
|
||||
@ -8673,15 +8660,14 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
||||
set_dst_reg_note (insn, REG_EQUIV, in, out);
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to do the move, do it that way. */
|
||||
else if ((tem1 = replaced_subreg (in), tem2 = replaced_subreg (out),
|
||||
(REG_P (tem1) && REG_P (tem2)))
|
||||
&& REGNO (tem1) < FIRST_PSEUDO_REGISTER
|
||||
&& REGNO (tem2) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem1)),
|
||||
REGNO_REG_CLASS (REGNO (tem2)),
|
||||
GET_MODE (out)))
|
||||
&& targetm.secondary_memory_needed (GET_MODE (out),
|
||||
REGNO_REG_CLASS (REGNO (tem1)),
|
||||
REGNO_REG_CLASS (REGNO (tem2))))
|
||||
{
|
||||
/* Get the memory to use and rewrite both registers to its mode. */
|
||||
rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
|
||||
@ -8695,7 +8681,6 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
||||
gen_reload (loc, in, opnum, type);
|
||||
gen_reload (out, loc, opnum, type);
|
||||
}
|
||||
#endif
|
||||
else if (REG_P (out) && UNARY_P (in))
|
||||
{
|
||||
rtx op1;
|
||||
|
@ -913,7 +913,8 @@ extern void fancy_abort (const char *, int, const char *)
|
||||
STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD \
|
||||
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
|
||||
HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE \
|
||||
SECONDARY_MEMORY_NEEDED
|
||||
|
||||
/* Target macros only used for code built for the target, that have
|
||||
moved to libgcc-tm.h or have never been present elsewhere. */
|
||||
|
@ -5252,7 +5252,7 @@ in memory and the hard register number if it is in a register.\n\
|
||||
\n\
|
||||
Scratch operands in memory (constraint @code{\"=m\"} / @code{\"=&m\"}) are\n\
|
||||
currently not supported. For the time being, you will have to continue\n\
|
||||
to use @code{SECONDARY_MEMORY_NEEDED} for that purpose.\n\
|
||||
to use @code{TARGET_SECONDARY_MEMORY_NEEDED} for that purpose.\n\
|
||||
\n\
|
||||
@code{copy_cost} also uses this target hook to find out how values are\n\
|
||||
copied. If you want it to include some extra cost for the need to allocate\n\
|
||||
@ -5265,9 +5265,21 @@ forwarding logic, you can set @code{sri->extra_cost} to a negative amount.",
|
||||
secondary_reload_info *sri),
|
||||
default_secondary_reload)
|
||||
|
||||
DEFHOOK
|
||||
(secondary_memory_needed,
|
||||
"Certain machines have the property that some registers cannot be copied\n\
|
||||
to some other registers without using memory. Define this hook on\n\
|
||||
those machines to return true if objects of mode @var{m} in registers\n\
|
||||
of @var{class1} can only be copied to registers of class @var{class2} by\n\
|
||||
storing a register of @var{class1} into memory and loading that memory\n\
|
||||
location into a register of @var{class2}. The default definition returns\n\
|
||||
false for all inputs.",
|
||||
bool, (machine_mode mode, reg_class_t class1, reg_class_t class2),
|
||||
hook_bool_mode_reg_class_t_reg_class_t_false)
|
||||
|
||||
DEFHOOK
|
||||
(secondary_memory_needed_mode,
|
||||
"If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory\n\
|
||||
"If @code{TARGET_SECONDARY_MEMORY_NEEDED} tells the compiler to use memory\n\
|
||||
when moving between two particular registers of mode @var{mode},\n\
|
||||
this hook specifies the mode that the memory should have.\n\
|
||||
\n\
|
||||
|
Loading…
x
Reference in New Issue
Block a user