https://gcc.gnu.org/g:b2d1e689f1123d7dd5c7ff744baf4aede475253b
commit b2d1e689f1123d7dd5c7ff744baf4aede475253b Author: Andrew Stubbs <[email protected]> Date: Wed Jul 1 11:58:25 2026 +0000 i386, rtl: Replace BASE_REG_CLASS macro family with a hook This patch replaces the separate macros BASE_REG_CLASS, MODE_BASE_REG_CLASS, MODE_BASE_REG_REG_CLASS, MODE_CODE_BASE_REG_CLASS, and INSN_BASE_REG_CLASS into a single hook: TARGET_BASE_REG_CLASS. It also adds a new parameter, MEM, that is intended to be used by AMD GCN soon. Adding this is the main motivation for changing the hook, but this patch should not change the behaviour of anything, yet. Rather than replace every definition of these macros in every backend, this keeps those as the default implementation of the hook. INSN_BASE_REG_CLASS had only one caller (i386), and was the one that I was interesting in extending, so it has been entirely deleted. This patch was largely generated using AI, but as the edits are mechanical changes with no real new content I do not believe them to be "legally significant" (a lot of lines are touched, but its the same thing repeated). Assisted-by: Claude Sonnet 5 Backport from mainline: gcc/ChangeLog: * target.def (base_reg_class): New target hook. * targhooks.h (default_base_reg_class): Declare. * targhooks.cc (default_base_reg_class): New function, implementing the previous BASE_REG_CLASS/MODE_BASE_REG_CLASS/ MODE_BASE_REG_REG_CLASS/MODE_CODE_BASE_REG_CLASS macro fallback chain as the hook's default. * addresses.h (base_reg_class): Rewrite to call the TARGET_BASE_REG_CLASS hook instead of dispatching through INSN_BASE_REG_CLASS and the other macros by hand; add a MEM parameter. * rtl.h (address_info): Add mem field. * rtlanal.cc (decompose_mem_address): Set it. * lra-constraints.cc (simplify_operand_subreg, process_alt_operands, base_to_reg, base_plus_disp_to_reg, process_address_1, curr_insn_transform): Pass the enclosing MEM, and INSN where previously omitted, to base_reg_class. * reload.cc (find_reloads, find_reloads_address, find_reloads_address_1, find_reloads_subreg_address): Likewise. * reload1.cc (maybe_fix_stack_asms): Likewise. * regcprop.cc: Include target.h. (replace_oldest_value_addr, replace_oldest_value_mem): Pass MEM to base_reg_class. * regrename.cc (base_reg_class_for_rename): Add a MEM parameter. (scan_rtx_address, scan_rtx): Pass it. * caller-save.cc: Include target.h. * config/i386/i386.h (INSN_BASE_REG_CLASS): Delete. * config/i386/i386-protos.h (ix86_insn_base_reg_class): Delete declaration. * config/i386/i386.cc (ix86_insn_base_reg_class): Rename to... (ix86_base_reg_class): ...this, adjust the signature, and implement TARGET_BASE_REG_CLASS instead of INSN_BASE_REG_CLASS. (TARGET_BASE_REG_CLASS): Define. * doc/tm.texi.in: Add TARGET_BASE_REG_CLASS. Mark BASE_REG_CLASS, MODE_BASE_REG_CLASS, MODE_BASE_REG_REG_CLASS and MODE_CODE_BASE_REG_CLASS as obsolete in favor of the new hook, and remove the now-unused INSN_BASE_REG_CLASS. * doc/tm.texi: Regenerate. (cherry picked from commit 4b78815305fa285ad223f08b52128afdae782a62) Diff: --- gcc/addresses.h | 34 +++++++----------------------- gcc/caller-save.cc | 1 + gcc/config/i386/i386-protos.h | 1 - gcc/config/i386/i386.cc | 15 ++++++++++--- gcc/config/i386/i386.h | 3 --- gcc/doc/tm.texi | 49 +++++++++++++++++++++++++++++++++++-------- gcc/doc/tm.texi.in | 21 ++++++++++++------- gcc/lra-constraints.cc | 23 +++++++++++--------- gcc/regcprop.cc | 9 +++++--- gcc/regrename.cc | 13 ++++++------ gcc/reload.cc | 44 ++++++++++++++++++++++---------------- gcc/reload1.cc | 3 ++- gcc/rtl.h | 4 ++++ gcc/rtlanal.cc | 1 + gcc/target.def | 32 ++++++++++++++++++++++++++++ gcc/targhooks.cc | 31 +++++++++++++++++++++++++++ gcc/targhooks.h | 3 +++ 17 files changed, 199 insertions(+), 88 deletions(-) diff --git a/gcc/addresses.h b/gcc/addresses.h index 6a9ffcd7cb3f..7ce34554ee7c 100644 --- a/gcc/addresses.h +++ b/gcc/addresses.h @@ -17,38 +17,20 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -/* Wrapper function to unify target macros MODE_CODE_BASE_REG_CLASS, - MODE_BASE_REG_REG_CLASS, MODE_BASE_REG_CLASS and BASE_REG_CLASS. - Arguments as for the MODE_CODE_BASE_REG_CLASS macro. */ +/* Wrapper function around the TARGET_BASE_REG_CLASS hook. MEM is the + MEM rtx being addressed, if known, and INSN is the instruction it + belongs to, if known; both may be null. */ #ifndef GCC_ADDRESSES_H #define GCC_ADDRESSES_H inline enum reg_class -base_reg_class (machine_mode mode ATTRIBUTE_UNUSED, - addr_space_t as ATTRIBUTE_UNUSED, - enum rtx_code outer_code ATTRIBUTE_UNUSED, - enum rtx_code index_code ATTRIBUTE_UNUSED, - rtx_insn *insn ATTRIBUTE_UNUSED = NULL) +base_reg_class (machine_mode mode, addr_space_t as, + enum rtx_code outer_code, enum rtx_code index_code, + rtx mem = NULL_RTX, rtx_insn *insn = NULL) { -#ifdef INSN_BASE_REG_CLASS - return INSN_BASE_REG_CLASS (insn); -#else -#ifdef MODE_CODE_BASE_REG_CLASS - return MODE_CODE_BASE_REG_CLASS (MACRO_MODE (mode), as, outer_code, - index_code); -#else -#ifdef MODE_BASE_REG_REG_CLASS - if (index_code == REG) - return MODE_BASE_REG_REG_CLASS (MACRO_MODE (mode)); -#endif -#ifdef MODE_BASE_REG_CLASS - return MODE_BASE_REG_CLASS (MACRO_MODE (mode)); -#else - return BASE_REG_CLASS; -#endif -#endif -#endif + return (enum reg_class) targetm.base_reg_class (mode, as, outer_code, + index_code, mem, insn); } inline enum reg_class diff --git a/gcc/caller-save.cc b/gcc/caller-save.cc index 281aa0bb0094..5e1a38e47dbc 100644 --- a/gcc/caller-save.cc +++ b/gcc/caller-save.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "backend.h" +#include "target.h" #include "rtl.h" #include "tree.h" #include "predict.h" diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 4ba4fb08556e..0cf05126f11a 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -81,7 +81,6 @@ extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx, extern bool ix86_expand_movmem (rtx[]); extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool); -extern enum reg_class ix86_insn_base_reg_class (rtx_insn *); extern bool ix86_regno_ok_for_insn_base_p (int, rtx_insn *); extern enum reg_class ix86_insn_index_reg_class (rtx_insn *); extern bool constant_address_p (rtx); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 392c50ff44c4..75d3c74c41fc 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -12111,10 +12111,16 @@ ix86_memory_address_reg_class (rtx_insn* insn) return addr_rclass; } -/* Return memory address register class insn can use. */ +/* Implement TARGET_BASE_REG_CLASS. -enum reg_class -ix86_insn_base_reg_class (rtx_insn* insn) + Return memory address register class INSN can use. MODE, AS, OUTER_CODE, + INDEX_CODE and MEM are unused: the EGPR-encoding restriction this + implements depends only on the instruction, not on the particular address + being formed. */ + +static reg_class_t +ix86_base_reg_class (machine_mode, addr_space_t, enum rtx_code, enum rtx_code, + rtx, rtx_insn *insn) { switch (ix86_memory_address_reg_class (insn)) { @@ -28559,6 +28565,9 @@ ix86_libgcc_floating_mode_supported_p #undef TARGET_CLASS_MAX_NREGS #define TARGET_CLASS_MAX_NREGS ix86_class_max_nregs +#undef TARGET_BASE_REG_CLASS +#define TARGET_BASE_REG_CLASS ix86_base_reg_class + #undef TARGET_PREFERRED_RELOAD_CLASS #define TARGET_PREFERRED_RELOAD_CLASS ix86_preferred_reload_class #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index fc3d8b3f4d45..59b72a2a1995 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1090,9 +1090,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define ADJUST_REG_ALLOC_ORDER x86_order_regs_for_local_alloc () -#define INSN_BASE_REG_CLASS(INSN) \ - ix86_insn_base_reg_class (INSN) - #define REGNO_OK_FOR_INSN_BASE_P(NUM, INSN) \ ix86_regno_ok_for_insn_base_p (NUM, INSN) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2832a447e3ee..5cbc8b2e596d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2563,6 +2563,9 @@ register. A macro whose definition is the name of the class to which a valid base register must belong. A base register is one used in an address which is the register value plus a displacement. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_BASE_REG_CLASS (@var{mode}) @@ -2570,6 +2573,9 @@ This is a variation of the @code{BASE_REG_CLASS} macro which allows the selection of a base register in a mode dependent manner. If @var{mode} is VOIDmode then it should return the same value as @code{BASE_REG_CLASS}. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_BASE_REG_REG_CLASS (@var{mode}) @@ -2577,6 +2583,9 @@ A C expression whose value is the register class to which a valid base register must belong in order to be used in a base plus index register address. You should define this macro if base plus index addresses have different requirements than other base register uses. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}) @@ -2588,16 +2597,38 @@ the code of the immediately enclosing expression (@code{MEM} for the top level of an address, @code{ADDRESS} for something that occurs in an @code{address_operand}). @var{index_code} is the code of the corresponding index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise. -@end defmac -@defmac INSN_BASE_REG_CLASS (@var{insn}) -A C expression whose value is the register class to which a valid -base register for a specified @var{insn} must belong. This macro is -used when some backend insns may have limited usage of base register -compared with other insns. If you define this macro, the compiler will -use it instead of all other defined macros that relate to -BASE_REG_CLASS. -@end defmac +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. +@end defmac + +@deftypefn {Target Hook} reg_class_t TARGET_BASE_REG_CLASS (machine_mode @var{mode}, addr_space_t @var{as}, enum rtx_code @var{outer_code}, enum rtx_code @var{index_code}, rtx @var{mem}, rtx_insn *@var{insn}) +A target hook that returns the register class to which a valid base +register for memory addressing must belong. @var{mode} and @var{as} are +the mode and address space of the value being addressed, @var{outer_code} +and @var{index_code} are the codes of the address expression and of the +index expression respectively (or @code{SCRATCH} where an index is not +applicable). + +If the address being asked about is the address of a particular +@code{MEM}, @var{mem} is that @code{MEM} rtx; otherwise it is null. When +non-null, targets should determine the required class by examining +@var{mem} directly (for example, to see whether the address side of the +@code{MEM} is itself held in a general or a vector register) rather than +by making assumptions from @var{mode} and @var{as} alone, since more than +one @code{MEM} of the same mode and address space can appear within a +single @var{insn} with different base-register requirements. + +If the specific instruction being processed is known, @var{insn} is that +instruction; otherwise it is null. This is provided for targets that +need context wider than a single @code{MEM}, such as avoiding particular +addressing-register encodings on specific instructions. + +The default implementation ignores @var{mem} and @var{insn} and calls the +legacy macros @code{BASE_REG_CLASS}, @code{MODE_BASE_REG_CLASS}, +@code{MODE_BASE_REG_REG_CLASS} and @code{MODE_CODE_BASE_REG_CLASS} instead, +based on @var{mode}, @var{as}, @var{outer_code} and @var{index_code} alone. +@end deftypefn @defmac INDEX_REG_CLASS A macro whose definition is the name of the class to which a valid diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 274bb899d0cb..cef9c6fa8eae 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -2139,6 +2139,9 @@ register. A macro whose definition is the name of the class to which a valid base register must belong. A base register is one used in an address which is the register value plus a displacement. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_BASE_REG_CLASS (@var{mode}) @@ -2146,6 +2149,9 @@ This is a variation of the @code{BASE_REG_CLASS} macro which allows the selection of a base register in a mode dependent manner. If @var{mode} is VOIDmode then it should return the same value as @code{BASE_REG_CLASS}. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_BASE_REG_REG_CLASS (@var{mode}) @@ -2153,6 +2159,9 @@ A C expression whose value is the register class to which a valid base register must belong in order to be used in a base plus index register address. You should define this macro if base plus index addresses have different requirements than other base register uses. + +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}) @@ -2164,17 +2173,13 @@ the code of the immediately enclosing expression (@code{MEM} for the top level of an address, @code{ADDRESS} for something that occurs in an @code{address_operand}). @var{index_code} is the code of the corresponding index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise. -@end defmac -@defmac INSN_BASE_REG_CLASS (@var{insn}) -A C expression whose value is the register class to which a valid -base register for a specified @var{insn} must belong. This macro is -used when some backend insns may have limited usage of base register -compared with other insns. If you define this macro, the compiler will -use it instead of all other defined macros that relate to -BASE_REG_CLASS. +This macro is obsolete, new ports should use the target hook +@code{TARGET_BASE_REG_CLASS} instead. @end defmac +@hook TARGET_BASE_REG_CLASS + @defmac INDEX_REG_CLASS A macro whose definition is the name of the class to which a valid index register must belong. An index register is one used in an diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index a567b19fc6c9..26eef2a3ef9d 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -1769,7 +1769,8 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) [ira_class_hard_regs [base_reg_class (GET_MODE (subst), MEM_ADDR_SPACE (subst), - ADDRESS, SCRATCH)][0]], + ADDRESS, SCRATCH, + subst, curr_insn)][0]], MEM_ADDR_SPACE (subst)))) { /* If we change the address for a paradoxical subreg of memory, the @@ -2726,7 +2727,8 @@ process_alt_operands (int only_alternative) if (satisfies_address_constraint_p (op, cn)) win = true; cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH); + ADDRESS, SCRATCH, NULL_RTX, + curr_insn); cl_filter = nullptr; badop = false; goto reg; @@ -3637,7 +3639,7 @@ base_to_reg (struct address_info *ad) lra_assert (ad->disp == ad->disp_term); cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, - get_index_code (ad)); + get_index_code (ad), ad->mem, curr_insn); new_reg = lra_create_new_reg (GET_MODE (*ad->base), NULL_RTX, cl, NULL, "base"); new_inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, @@ -3666,7 +3668,7 @@ base_plus_disp_to_reg (struct address_info *ad, rtx disp) lra_assert (ad->base == ad->base_term); cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, - get_index_code (ad)); + get_index_code (ad), ad->mem, curr_insn); new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, cl, NULL, "base + disp"); lra_emit_add (new_reg, *ad->base_term, disp); @@ -3959,7 +3961,7 @@ process_address_1 (int nop, bool check_only_p, REGNO (*ad.base_term)) != NULL_RTX) ? after : NULL), base_reg_class (ad.mode, ad.as, ad.base_outer_code, - get_index_code (&ad), curr_insn)))) + get_index_code (&ad), ad.mem, curr_insn)))) { change_p = true; if (ad.base_term2 != NULL) @@ -4010,7 +4012,7 @@ process_address_1 (int nop, bool check_only_p, int code = -1; enum reg_class cl = base_reg_class (ad.mode, ad.as, SCRATCH, SCRATCH, - curr_insn); + ad.mem, curr_insn); rtx addr = *ad.inner; new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr"); @@ -4074,7 +4076,7 @@ process_address_1 (int nop, bool check_only_p, case (1) above. */ enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS, GET_CODE (*ad.index), - curr_insn); + ad.mem, curr_insn); lra_assert (index_cl != NO_REGS); new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "disp"); @@ -4091,7 +4093,7 @@ process_address_1 (int nop, bool check_only_p, rtx_insn *insns, *last_insn; cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code, - get_index_code (&ad), curr_insn); + get_index_code (&ad), ad.mem, curr_insn); if (REG_P (*ad.base_term) && ira_class_subset_p[get_reg_class (REGNO (*ad.base_term))][cl]) @@ -4189,7 +4191,8 @@ process_address_1 (int nop, bool check_only_p, enum reg_class cl; rtx addr; reload_inner_addr: - cl = base_reg_class (ad.mode, ad.as, SCRATCH, SCRATCH, curr_insn); + cl = base_reg_class (ad.mode, ad.as, SCRATCH, SCRATCH, ad.mem, + curr_insn); addr = *ad.inner; new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr"); /* addr => new_base. */ @@ -4909,7 +4912,7 @@ curr_insn_transform (bool check_only_p) push_to_sequence (before); rclass = base_reg_class (GET_MODE (op), MEM_ADDR_SPACE (op), - MEM, SCRATCH, curr_insn); + MEM, SCRATCH, op, curr_insn); if (GET_RTX_CLASS (code) == RTX_AUTOINC) new_reg = emit_inc (rclass, *loc, /* This value does not matter for MODIFY. */ diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc index 2a9956353cc6..9ef99d6838d5 100644 --- a/gcc/regcprop.cc +++ b/gcc/regcprop.cc @@ -21,6 +21,7 @@ #include "system.h" #include "coretypes.h" #include "backend.h" +#include "target.h" #include "rtl.h" #include "df.h" #include "memmodel.h" @@ -34,7 +35,6 @@ #include "tree-pass.h" #include "rtl-iter.h" #include "cfgrtl.h" -#include "target.h" #include "function-abi.h" #include "cfgcleanup.h" @@ -696,7 +696,9 @@ replace_oldest_value_addr (rtx *loc, enum reg_class cl, if (locB) changed |= replace_oldest_value_addr (locB, base_reg_class (mode, as, PLUS, - index_code), + index_code, + NULL_RTX, + insn), mode, as, insn, vd); return changed; } @@ -744,7 +746,8 @@ replace_oldest_value_mem (rtx x, rtx_insn *insn, struct value_data *vd) if (DEBUG_INSN_P (insn)) cl = ALL_REGS; else - cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH); + cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH, + x, insn); return replace_oldest_value_addr (&XEXP (x, 0), cl, GET_MODE (x), MEM_ADDR_SPACE (x), diff --git a/gcc/regrename.cc b/gcc/regrename.cc index b0021019c698..3a7e36872681 100644 --- a/gcc/regrename.cc +++ b/gcc/regrename.cc @@ -1299,16 +1299,17 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act } /* A wrapper around base_reg_class which returns ALL_REGS if INSN is a - DEBUG_INSN. The arguments MODE, AS, CODE and INDEX_CODE are as for - base_reg_class. */ + DEBUG_INSN. The arguments MODE, AS, CODE, INDEX_CODE and MEM are as + for base_reg_class. */ static reg_class base_reg_class_for_rename (rtx_insn *insn, machine_mode mode, addr_space_t as, - rtx_code code, rtx_code index_code) + rtx_code code, rtx_code index_code, + rtx mem = NULL_RTX) { if (DEBUG_INSN_P (insn)) return ALL_REGS; - return base_reg_class (mode, as, code, index_code); + return base_reg_class (mode, as, code, index_code, mem, insn); } /* Adapted from find_reloads_address_1. CL is INDEX_REG_CLASS or @@ -1446,7 +1447,7 @@ scan_rtx_address (rtx_insn *insn, rtx *loc, enum reg_class cl, { reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x), MEM_ADDR_SPACE (x), - MEM, SCRATCH); + MEM, SCRATCH, x); scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x), MEM_ADDR_SPACE (x)); } @@ -1497,7 +1498,7 @@ scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action, { reg_class bclass = base_reg_class_for_rename (insn, GET_MODE (x), MEM_ADDR_SPACE (x), - MEM, SCRATCH); + MEM, SCRATCH, x); scan_rtx_address (insn, &XEXP (x, 0), bclass, action, GET_MODE (x), MEM_ADDR_SPACE (x)); diff --git a/gcc/reload.cc b/gcc/reload.cc index 7917cc94a9d0..453f1d6caa06 100644 --- a/gcc/reload.cc +++ b/gcc/reload.cc @@ -3328,7 +3328,7 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, were handled in find_reloads_address. */ this_alternative[i] = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH, insn); + ADDRESS, SCRATCH, NULL_RTX, insn); win = 1; badop = 0; break; @@ -3515,7 +3515,7 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, the address into a base register. */ this_alternative[i] = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH, insn); + ADDRESS, SCRATCH, NULL_RTX, insn); badop = 0; break; @@ -4025,7 +4025,8 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known, operand_reloadnum[i] = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX, &XEXP (recog_data.operand[i], 0), (rtx*) 0, - base_reg_class (VOIDmode, as, MEM, SCRATCH, insn), + base_reg_class (VOIDmode, as, MEM, SCRATCH, + recog_data.operand[i], insn), address_mode, VOIDmode, 0, 0, i, RELOAD_OTHER); rld[operand_reloadnum[i]].inc @@ -4904,8 +4905,10 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, if (reg_equiv_constant (regno) != 0) { find_reloads_address_part (reg_equiv_constant (regno), loc, - base_reg_class (mode, as, MEM, - SCRATCH, insn), + base_reg_class (mode, as, MEM, SCRATCH, + (memrefloc ? *memrefloc + : NULL_RTX), + insn), GET_MODE (ad), opnum, type, ind_levels); return 1; } @@ -4974,7 +4977,8 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, /* If we do not have one of the cases above, we must do the reload. */ push_reload (ad, NULL_RTX, loc, (rtx*) 0, - base_reg_class (mode, as, MEM, SCRATCH, insn), + base_reg_class (mode, as, MEM, SCRATCH, + memrefloc ? *memrefloc : NULL_RTX, insn), GET_MODE (ad), VOIDmode, 0, 0, opnum, type); return 1; } @@ -5075,9 +5079,8 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, /* Must use TEM here, not AD, since it is the one that will have any subexpressions reloaded, if needed. */ push_reload (tem, NULL_RTX, loc, (rtx*) 0, - base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem), - VOIDmode, 0, - 0, opnum, type); + base_reg_class (mode, as, MEM, SCRATCH, tem, insn), + GET_MODE (tem), VOIDmode, 0, 0, opnum, type); return ! removed_and; } else @@ -5131,8 +5134,10 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, reload the sum into a base reg. That will at least work. */ find_reloads_address_part (ad, loc, - base_reg_class (mode, as, MEM, - SCRATCH, insn), + base_reg_class (mode, as, MEM, SCRATCH, + (memrefloc ? *memrefloc + : NULL_RTX), + insn), GET_MODE (ad), opnum, type, ind_levels); } return ! removed_and; @@ -5212,7 +5217,8 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, op_index == 0 ? addend : offset_reg); *loc = ad; - cls = base_reg_class (mode, as, MEM, GET_CODE (addend), insn); + cls = base_reg_class (mode, as, MEM, GET_CODE (addend), + memrefloc ? *memrefloc : NULL_RTX, insn); find_reloads_address_part (XEXP (ad, op_index), &XEXP (ad, op_index), cls, GET_MODE (ad), opnum, type, ind_levels); @@ -5270,8 +5276,10 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, } find_reloads_address_part (ad, loc, - base_reg_class (mode, as, MEM, - SCRATCH, insn), + base_reg_class (mode, as, MEM, SCRATCH, + (memrefloc ? *memrefloc + : NULL_RTX), + insn), address_mode, opnum, type, ind_levels); return ! removed_and; } @@ -5524,7 +5532,7 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as, context_reg_class = index_reg_class (insn); else context_reg_class = base_reg_class (mode, as, outer_code, index_code, - insn); + NULL_RTX, insn); switch (code) { @@ -5750,7 +5758,7 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as, &XEXP (op1, 0), base_reg_class (mode, as, code, index_code, - insn), + tem, insn), GET_MODE (x), GET_MODE (x), 0, 0, opnum, RELOAD_OTHER); @@ -5769,7 +5777,7 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as, &XEXP (op1, 0), &XEXP (x, 0), base_reg_class (mode, as, code, index_code, - insn), + NULL_RTX, insn), GET_MODE (x), GET_MODE (x), 0, 0, opnum, RELOAD_OTHER); @@ -6229,7 +6237,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type, { push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0, base_reg_class (GET_MODE (tem), MEM_ADDR_SPACE (tem), - MEM, SCRATCH, insn), + MEM, SCRATCH, tem, insn), GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, opnum, type); reloaded = 1; } diff --git a/gcc/reload1.cc b/gcc/reload1.cc index 8cac4011c467..d9e9674d32b4 100644 --- a/gcc/reload1.cc +++ b/gcc/reload1.cc @@ -1390,7 +1390,8 @@ maybe_fix_stack_asms (void) if (insn_extra_address_constraint (cn)) cls = (int) reg_class_subunion[cls] [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH, chain->insn)]; + ADDRESS, SCRATCH, NULL_RTX, + chain->insn)]; else cls = (int) reg_class_subunion[cls] [reg_class_for_constraint (cn)]; diff --git a/gcc/rtl.h b/gcc/rtl.h index eebcc18a4f1a..93f46e5d5d34 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2220,6 +2220,10 @@ struct address_info { /* True if this is an RTX_AUTOINC address. */ bool autoinc_p; + /* The MEM whose address this is, or null if this describes an address + operand with no enclosing MEM (an ADDRESS rather than a MEM address). */ + rtx mem; + /* A pointer to the top-level address. */ rtx *outer; diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc index 88561a54e5a0..59b2c504c978 100644 --- a/gcc/rtlanal.cc +++ b/gcc/rtlanal.cc @@ -6879,6 +6879,7 @@ decompose_mem_address (struct address_info *info, rtx x) gcc_assert (MEM_P (x)); decompose_address (info, &XEXP (x, 0), GET_MODE (x), MEM_ADDR_SPACE (x), MEM); + info->mem = x; } /* Update INFO after a change to the address it describes. */ diff --git a/gcc/target.def b/gcc/target.def index 11b358f4160f..a37c3caec916 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -6166,6 +6166,38 @@ reload from using some alternatives, like @code{TARGET_PREFERRED_RELOAD_CLASS}." (rtx x, reg_class_t rclass), default_preferred_output_reload_class) +DEFHOOK +(base_reg_class, + "A target hook that returns the register class to which a valid base\n\ +register for memory addressing must belong. @var{mode} and @var{as} are\n\ +the mode and address space of the value being addressed, @var{outer_code}\n\ +and @var{index_code} are the codes of the address expression and of the\n\ +index expression respectively (or @code{SCRATCH} where an index is not\n\ +applicable).\n\ +\n\ +If the address being asked about is the address of a particular\n\ +@code{MEM}, @var{mem} is that @code{MEM} rtx; otherwise it is null. When\n\ +non-null, targets should determine the required class by examining\n\ +@var{mem} directly (for example, to see whether the address side of the\n\ +@code{MEM} is itself held in a general or a vector register) rather than\n\ +by making assumptions from @var{mode} and @var{as} alone, since more than\n\ +one @code{MEM} of the same mode and address space can appear within a\n\ +single @var{insn} with different base-register requirements.\n\ +\n\ +If the specific instruction being processed is known, @var{insn} is that\n\ +instruction; otherwise it is null. This is provided for targets that\n\ +need context wider than a single @code{MEM}, such as avoiding particular\n\ +addressing-register encodings on specific instructions.\n\ +\n\ +The default implementation ignores @var{mem} and @var{insn} and calls the\n\ +legacy macros @code{BASE_REG_CLASS}, @code{MODE_BASE_REG_CLASS},\n\ +@code{MODE_BASE_REG_REG_CLASS} and @code{MODE_CODE_BASE_REG_CLASS} instead,\n\ +based on @var{mode}, @var{as}, @var{outer_code} and @var{index_code} alone.", + reg_class_t, + (machine_mode mode, addr_space_t as, enum rtx_code outer_code, + enum rtx_code index_code, rtx mem, rtx_insn *insn), + default_base_reg_class) + DEFHOOK (select_early_remat_modes, "On some targets, certain modes cannot be held in registers around a\n\ diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 5f1eac75122c..d0d3665b652d 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -2311,6 +2311,37 @@ default_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED, return rclass; } +/* The default implementation of TARGET_BASE_REG_CLASS. */ + +reg_class_t +default_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED, + addr_space_t as ATTRIBUTE_UNUSED, + enum rtx_code outer_code ATTRIBUTE_UNUSED, + enum rtx_code index_code ATTRIBUTE_UNUSED, + rtx mem ATTRIBUTE_UNUSED, + rtx_insn *insn ATTRIBUTE_UNUSED) +{ +#ifdef MODE_CODE_BASE_REG_CLASS + return MODE_CODE_BASE_REG_CLASS (MACRO_MODE (mode), as, outer_code, + index_code); +#else +#ifdef MODE_BASE_REG_REG_CLASS + if (index_code == REG) + return MODE_BASE_REG_REG_CLASS (MACRO_MODE (mode)); +#endif +#ifdef MODE_BASE_REG_CLASS + return MODE_BASE_REG_CLASS (MACRO_MODE (mode)); +#elif defined (BASE_REG_CLASS) + return BASE_REG_CLASS; +#else + /* No target that leaves TARGET_BASE_REG_CLASS at its default also fails + to define BASE_REG_CLASS or one of the other macros above; a target + that defines none of them must override the hook directly instead. */ + gcc_unreachable (); +#endif +#endif +} + /* The default implementation of TARGET_PREFERRED_RENAME_CLASS. */ reg_class_t default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED) diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 9582233e69fe..0c9b8d227b81 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -259,6 +259,9 @@ extern void default_print_patchable_function_entry (FILE *, extern bool default_profile_before_prologue (void); extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t); +extern reg_class_t default_base_reg_class (machine_mode, addr_space_t, + enum rtx_code, enum rtx_code, + rtx, rtx_insn *); extern reg_class_t default_preferred_rename_class (reg_class_t rclass); extern bool default_class_likely_spilled_p (reg_class_t); extern unsigned char default_class_max_nregs (reg_class_t, machine_mode);
