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
>

Reply via email to