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).
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