On Mon, Sep 21, 2026 at 1:39 PM Andrew Stubbs <[email protected]> wrote: > > 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 superceeds my previous patch for INSN_BASE_REG_CLASS.) > > 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).
LGTM, but - how did you test it? patchworks shows simplebootstrap passed on arm and aarch64. Thanks, Richard. > Assisted-by: Claude Sonnet 5 > > 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. > --- > 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 6a9ffcd7cb3..7ce34554ee7 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 281aa0bb009..5e1a38e47db 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 2687de646b0..4e56bf70c8d 100644 > --- a/gcc/config/i386/i386-protos.h > +++ b/gcc/config/i386/i386-protos.h > @@ -83,7 +83,6 @@ extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, > rtx, rtx, > extern bool ix86_expand_set_or_movmem (rtx[], bool, bool); > 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 3f00ddaa547..5e5e0bb033e 100644 > --- a/gcc/config/i386/i386.cc > +++ b/gcc/config/i386/i386.cc > @@ -12125,10 +12125,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)) > { > @@ -29079,6 +29085,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 fc961fb777c..47725c56090 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -1099,9 +1099,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 ca68bdc3e61..97afd017522 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -2550,6 +2550,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}) > @@ -2557,6 +2560,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}) > @@ -2564,6 +2570,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}) > @@ -2575,16 +2584,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 532e95ef216..2113b9c679a 100644 > --- a/gcc/doc/tm.texi.in > +++ b/gcc/doc/tm.texi.in > @@ -2135,6 +2135,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}) > @@ -2142,6 +2145,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}) > @@ -2149,6 +2155,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}) > @@ -2160,17 +2169,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 153624b8859..6ce257d2c49 100644 > --- a/gcc/lra-constraints.cc > +++ b/gcc/lra-constraints.cc > @@ -1763,7 +1763,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 > @@ -2945,7 +2946,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; > cl_dep_filter = nullptr; > badop = false; > @@ -3862,7 +3864,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, > @@ -3891,7 +3893,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); > @@ -4184,7 +4186,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) > @@ -4235,7 +4237,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"); > @@ -4299,7 +4301,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"); > @@ -4316,7 +4318,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]) > @@ -4414,7 +4416,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. */ > @@ -5186,7 +5189,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 2a9956353cc..9ef99d6838d 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 07c3659f8a8..bc02b28117f 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 > @@ -1452,7 +1453,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)); > } > @@ -1503,7 +1504,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 7917cc94a9d..453f1d6caa0 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 638aca6acee..3f338bde16a 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 77a71e5bbec..281d08952d0 100644 > --- a/gcc/rtl.h > +++ b/gcc/rtl.h > @@ -2231,6 +2231,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 d897dc400ea..df4a69d180a 100644 > --- a/gcc/rtlanal.cc > +++ b/gcc/rtlanal.cc > @@ -6886,6 +6886,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 66c20a9c9d2..11334f9d443 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -6177,6 +6177,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 388f696c8aa..7123827cfd7 100644 > --- a/gcc/targhooks.cc > +++ b/gcc/targhooks.cc > @@ -2322,6 +2322,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 86de6ef8a69..ffeaeb2a772 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); > -- > 2.54.0 >
