diff mbox series

[01/13,APX,EGPR] middle-end: Add insn argument to base_reg_class

Message ID 20230831082024.314097-2-hongyu.wang@intel.com
State New
Headers show
Series Support Intel APX EGPR | expand

Commit Message

Hongyu Wang Aug. 31, 2023, 8:20 a.m. UTC
From: Kong Lingling <lingling.kong@intel.com>

Current reload infrastructure does not support selective base_reg_class
for backend insn. Add insn argument to base_reg_class for
lra/reload usage.

gcc/ChangeLog:

	* addresses.h (base_reg_class):  Add insn argument.
	Pass to MODE_CODE_BASE_REG_CLASS.
	(regno_ok_for_base_p_1): Add insn argument.
	Pass to REGNO_MODE_CODE_OK_FOR_BASE_P.
	(regno_ok_for_base_p): Add insn argument and parse to ok_for_base_p_1.
	* config/avr/avr.h (MODE_CODE_BASE_REG_CLASS): Add insn argument.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
	* config/gcn/gcn.h (MODE_CODE_BASE_REG_CLASS): Ditto.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
	* config/rl78/rl78.h (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
	(MODE_CODE_BASE_REG_CLASS): Ditto.
	* doc/tm.texi: Add insn argument for MODE_CODE_BASE_REG_CLASS
	and REGNO_MODE_CODE_OK_FOR_BASE_P.
	* doc/tm.texi.in: Ditto.
	* lra-constraints.cc (process_address_1): Pass insn to
	base_reg_class.
	(curr_insn_transform): Ditto.
	* reload.cc (find_reloads): Ditto.
	(find_reloads_address): Ditto.
	(find_reloads_address_1): Ditto.
	(find_reloads_subreg_address): Ditto.
	* reload1.cc (maybe_fix_stack_asms): Ditto.
---
 gcc/addresses.h        | 15 +++++++++------
 gcc/config/avr/avr.h   |  5 +++--
 gcc/config/gcn/gcn.h   |  4 ++--
 gcc/config/rl78/rl78.h |  6 ++++--
 gcc/doc/tm.texi        |  8 ++++++--
 gcc/doc/tm.texi.in     |  8 ++++++--
 gcc/lra-constraints.cc | 15 +++++++++------
 gcc/reload.cc          | 30 ++++++++++++++++++------------
 gcc/reload1.cc         |  2 +-
 9 files changed, 58 insertions(+), 35 deletions(-)

Comments

Uros Bizjak Aug. 31, 2023, 10:15 a.m. UTC | #1
On Thu, Aug 31, 2023 at 10:20 AM Hongyu Wang <hongyu.wang@intel.com> wrote:
>
> From: Kong Lingling <lingling.kong@intel.com>
>
> Current reload infrastructure does not support selective base_reg_class
> for backend insn. Add insn argument to base_reg_class for
> lra/reload usage.

I don't think this is the correct approach. Ideally, a memory
constraint should somehow encode its BASE/INDEX register class.
Instead of passing "insn", simply a different constraint could be used
in the constraint string of the relevant insn.

Uros.
>
> gcc/ChangeLog:
>
>         * addresses.h (base_reg_class):  Add insn argument.
>         Pass to MODE_CODE_BASE_REG_CLASS.
>         (regno_ok_for_base_p_1): Add insn argument.
>         Pass to REGNO_MODE_CODE_OK_FOR_BASE_P.
>         (regno_ok_for_base_p): Add insn argument and parse to ok_for_base_p_1.
>         * config/avr/avr.h (MODE_CODE_BASE_REG_CLASS): Add insn argument.
>         (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
>         * config/gcn/gcn.h (MODE_CODE_BASE_REG_CLASS): Ditto.
>         (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
>         * config/rl78/rl78.h (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
>         (MODE_CODE_BASE_REG_CLASS): Ditto.
>         * doc/tm.texi: Add insn argument for MODE_CODE_BASE_REG_CLASS
>         and REGNO_MODE_CODE_OK_FOR_BASE_P.
>         * doc/tm.texi.in: Ditto.
>         * lra-constraints.cc (process_address_1): Pass insn to
>         base_reg_class.
>         (curr_insn_transform): Ditto.
>         * reload.cc (find_reloads): Ditto.
>         (find_reloads_address): Ditto.
>         (find_reloads_address_1): Ditto.
>         (find_reloads_subreg_address): Ditto.
>         * reload1.cc (maybe_fix_stack_asms): Ditto.
> ---
>  gcc/addresses.h        | 15 +++++++++------
>  gcc/config/avr/avr.h   |  5 +++--
>  gcc/config/gcn/gcn.h   |  4 ++--
>  gcc/config/rl78/rl78.h |  6 ++++--
>  gcc/doc/tm.texi        |  8 ++++++--
>  gcc/doc/tm.texi.in     |  8 ++++++--
>  gcc/lra-constraints.cc | 15 +++++++++------
>  gcc/reload.cc          | 30 ++++++++++++++++++------------
>  gcc/reload1.cc         |  2 +-
>  9 files changed, 58 insertions(+), 35 deletions(-)
>
> diff --git a/gcc/addresses.h b/gcc/addresses.h
> index 3519c241c6d..08b100cfe6d 100644
> --- a/gcc/addresses.h
> +++ b/gcc/addresses.h
> @@ -28,11 +28,12 @@ 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)
> +               enum rtx_code index_code ATTRIBUTE_UNUSED,
> +               rtx_insn *insn ATTRIBUTE_UNUSED = NULL)
>  {
>  #ifdef MODE_CODE_BASE_REG_CLASS
>    return MODE_CODE_BASE_REG_CLASS (MACRO_MODE (mode), as, outer_code,
> -                                  index_code);
> +                                  index_code, insn);
>  #else
>  #ifdef MODE_BASE_REG_REG_CLASS
>    if (index_code == REG)
> @@ -56,11 +57,12 @@ ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
>                  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)
> +                enum rtx_code index_code ATTRIBUTE_UNUSED,
> +                rtx_insn* insn ATTRIBUTE_UNUSED = NULL)
>  {
>  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
>    return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, MACRO_MODE (mode), as,
> -                                       outer_code, index_code);
> +                                       outer_code, index_code, insn);
>  #else
>  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
>    if (index_code == REG)
> @@ -79,12 +81,13 @@ ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
>
>  inline bool
>  regno_ok_for_base_p (unsigned regno, machine_mode mode, addr_space_t as,
> -                    enum rtx_code outer_code, enum rtx_code index_code)
> +                    enum rtx_code outer_code, enum rtx_code index_code,
> +                    rtx_insn* insn = NULL)
>  {
>    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
>      regno = reg_renumber[regno];
>
> -  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
> +  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code, insn);
>  }
>
>  #endif /* GCC_ADDRESSES_H */
> diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
> index 8e7e00db13b..1d090fe0838 100644
> --- a/gcc/config/avr/avr.h
> +++ b/gcc/config/avr/avr.h
> @@ -280,12 +280,13 @@ enum reg_class {
>
>  #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
>
> -#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code)   \
> +#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code, insn)   \
>    avr_mode_code_base_reg_class (mode, as, outer_code, index_code)
>
>  #define INDEX_REG_CLASS NO_REGS
>
> -#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code, index_code) \
> +#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code,         \
> +                                     index_code, insn)                   \
>    avr_regno_mode_code_ok_for_base_p (num, mode, as, outer_code, index_code)
>
>  #define REGNO_OK_FOR_INDEX_P(NUM) 0
> diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
> index 4ff9a5d4d12..b56702a77fd 100644
> --- a/gcc/config/gcn/gcn.h
> +++ b/gcc/config/gcn/gcn.h
> @@ -437,9 +437,9 @@ enum reg_class
>       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }}
>
>  #define REGNO_REG_CLASS(REGNO) gcn_regno_reg_class (REGNO)
> -#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX) \
> +#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX, INSN) \
>          gcn_mode_code_base_reg_class (MODE, AS, OUTER, INDEX)
> -#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX) \
> +#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX, INSN) \
>          gcn_regno_mode_code_ok_for_base_p (NUM, MODE, AS, OUTER, INDEX)
>  #define INDEX_REG_CLASS VGPR_REGS
>  #define REGNO_OK_FOR_INDEX_P(regno) regno_ok_for_index_p (regno)
> diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h
> index 7a7c6a44ba2..d0ed9162292 100644
> --- a/gcc/config/rl78/rl78.h
> +++ b/gcc/config/rl78/rl78.h
> @@ -375,10 +375,12 @@ enum reg_class
>
>  #define REGNO_OK_FOR_INDEX_P(regno)    REGNO_OK_FOR_BASE_P (regno)
>
> -#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, index_code) \
> +#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, \
> +                                     index_code, insn)                       \
>    rl78_regno_mode_code_ok_for_base_p (regno, mode, address_space, outer_code, index_code)
>
> -#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code) \
> +#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code, \
> +                                insn)                                        \
>    rl78_mode_code_base_reg_class (mode, address_space, outer_code, index_code)
>
>  #define RETURN_ADDR_RTX(COUNT, FRAMEADDR)                              \
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index d0d47b0d471..a4239e3de10 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -2533,7 +2533,7 @@ register address.  You should define this macro if base plus index
>  addresses have different requirements than other base register uses.
>  @end defmac
>
> -@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> +@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
>  A C expression whose value is the register class to which a valid
>  base register for a memory reference in mode @var{mode} to address
>  space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
> @@ -2542,6 +2542,8 @@ 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.
> +@code{insn} indicates insn specific base register class should be subset
> +of the original base register class.
>  @end defmac
>
>  @defmac INDEX_REG_CLASS
> @@ -2579,7 +2581,7 @@ Use of this macro is deprecated; please use the more general
>  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
>  @end defmac
>
> -@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> +@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
>  A C expression which is nonzero if register number @var{num} is
>  suitable for use as a base register in operand addresses, accessing
>  memory in mode @var{mode} in address space @var{address_space}.
> @@ -2592,6 +2594,8 @@ address, @code{ADDRESS} for something that occurs in an
>  corresponding index expression if @var{outer_code} is @code{PLUS};
>  @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
>  that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
> +@code{insn} indicates insn specific base register class should be subset
> +of the original base register class.
>  @end defmac
>
>  @defmac REGNO_OK_FOR_INDEX_P (@var{num})
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index 4ac96dc357d..72898f3adba 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -2128,7 +2128,7 @@ register address.  You should define this macro if base plus index
>  addresses have different requirements than other base register uses.
>  @end defmac
>
> -@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> +@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
>  A C expression whose value is the register class to which a valid
>  base register for a memory reference in mode @var{mode} to address
>  space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
> @@ -2137,6 +2137,8 @@ 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.
> +@code{insn} indicates insn specific base register class should be subset
> +of the original base register class.
>  @end defmac
>
>  @defmac INDEX_REG_CLASS
> @@ -2174,7 +2176,7 @@ Use of this macro is deprecated; please use the more general
>  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
>  @end defmac
>
> -@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> +@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
>  A C expression which is nonzero if register number @var{num} is
>  suitable for use as a base register in operand addresses, accessing
>  memory in mode @var{mode} in address space @var{address_space}.
> @@ -2187,6 +2189,8 @@ address, @code{ADDRESS} for something that occurs in an
>  corresponding index expression if @var{outer_code} is @code{PLUS};
>  @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
>  that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
> +@code{insn} indicates insn specific base register class should be subset
> +of the original base register class.
>  @end defmac
>
>  @defmac REGNO_OK_FOR_INDEX_P (@var{num})
> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> index c718bedff32..9e7915ce934 100644
> --- a/gcc/lra-constraints.cc
> +++ b/gcc/lra-constraints.cc
> @@ -3672,7 +3672,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)))))
> +                          get_index_code (&ad), curr_insn))))
>      {
>        change_p = true;
>        if (ad.base_term2 != NULL)
> @@ -3722,7 +3722,8 @@ process_address_1 (int nop, bool check_only_p,
>           rtx_insn *last = get_last_insn ();
>           int code = -1;
>           enum reg_class cl = base_reg_class (ad.mode, ad.as,
> -                                             SCRATCH, SCRATCH);
> +                                             SCRATCH, SCRATCH,
> +                                             curr_insn);
>           rtx addr = *ad.inner;
>
>           new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
> @@ -3785,7 +3786,8 @@ process_address_1 (int nop, bool check_only_p,
>           /* index * scale + disp => new base + index * scale,
>              case (1) above.  */
>           enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS,
> -                                             GET_CODE (*ad.index));
> +                                             GET_CODE (*ad.index),
> +                                             curr_insn);
>
>           lra_assert (INDEX_REG_CLASS != NO_REGS);
>           new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "disp");
> @@ -3846,7 +3848,7 @@ process_address_1 (int nop, bool check_only_p,
>               *ad.base_term = XEXP (SET_SRC (set), 0);
>               *ad.disp_term = XEXP (SET_SRC (set), 1);
>               cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
> -                                  get_index_code (&ad));
> +                                  get_index_code (&ad), curr_insn);
>               regno = REGNO (*ad.base_term);
>               if (regno >= FIRST_PSEUDO_REGISTER
>                   && cl != lra_get_allocno_class (regno))
> @@ -3890,7 +3892,8 @@ process_address_1 (int nop, bool check_only_p,
>    else
>      {
>        enum reg_class cl = base_reg_class (ad.mode, ad.as,
> -                                         SCRATCH, SCRATCH);
> +                                         SCRATCH, SCRATCH,
> +                                         curr_insn);
>        rtx addr = *ad.inner;
>
>        new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
> @@ -4639,7 +4642,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);
> +                                  MEM, SCRATCH, curr_insn);
>           if (GET_RTX_CLASS (code) == RTX_AUTOINC)
>             new_reg = emit_inc (rclass, *loc, *loc,
>                                 /* This value does not matter for MODIFY.  */
> diff --git a/gcc/reload.cc b/gcc/reload.cc
> index 2126bdd117c..72f7e27af15 100644
> --- a/gcc/reload.cc
> +++ b/gcc/reload.cc
> @@ -3321,7 +3321,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);
> +                                       ADDRESS, SCRATCH, insn);
>                     win = 1;
>                     badop = 0;
>                     break;
> @@ -3508,7 +3508,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);
> +                                           ADDRESS, SCRATCH, insn);
>                         badop = 0;
>                         break;
>
> @@ -4018,7 +4018,7 @@ 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),
> +                            base_reg_class (VOIDmode, as, MEM, SCRATCH, insn),
>                              address_mode,
>                              VOIDmode, 0, 0, i, RELOAD_OTHER);
>             rld[operand_reloadnum[i]].inc
> @@ -4897,7 +4897,8 @@ 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),
> +                                    base_reg_class (mode, as, MEM,
> +                                                    SCRATCH, insn),
>                                      GET_MODE (ad), opnum, type, ind_levels);
>           return 1;
>         }
> @@ -4966,7 +4967,7 @@ 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),
> +                  base_reg_class (mode, as, MEM, SCRATCH, insn),
>                    GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
>        return 1;
>      }
> @@ -5123,7 +5124,8 @@ 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),
> +                                    base_reg_class (mode, as, MEM,
> +                                                    SCRATCH, insn),
>                                      GET_MODE (ad), opnum, type, ind_levels);
>         }
>        return ! removed_and;
> @@ -5203,7 +5205,7 @@ 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));
> +         cls = base_reg_class (mode, as, MEM, GET_CODE (addend), insn);
>           find_reloads_address_part (XEXP (ad, op_index),
>                                      &XEXP (ad, op_index), cls,
>                                      GET_MODE (ad), opnum, type, ind_levels);
> @@ -5261,7 +5263,8 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
>         }
>
>        find_reloads_address_part (ad, loc,
> -                                base_reg_class (mode, as, MEM, SCRATCH),
> +                                base_reg_class (mode, as, MEM,
> +                                                SCRATCH, insn),
>                                  address_mode, opnum, type, ind_levels);
>        return ! removed_and;
>      }
> @@ -5513,7 +5516,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
>    if (context == 1)
>      context_reg_class = INDEX_REG_CLASS;
>    else
> -    context_reg_class = base_reg_class (mode, as, outer_code, index_code);
> +    context_reg_class = base_reg_class (mode, as, outer_code, index_code,
> +                                       insn);
>
>    switch (code)
>      {
> @@ -5738,7 +5742,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
>                 reloadnum = push_reload (tem, tem, &XEXP (x, 0),
>                                          &XEXP (op1, 0),
>                                          base_reg_class (mode, as,
> -                                                        code, index_code),
> +                                                        code, index_code,
> +                                                        insn),
>                                          GET_MODE (x), GET_MODE (x), 0,
>                                          0, opnum, RELOAD_OTHER);
>
> @@ -5756,7 +5761,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
>             reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
>                                      &XEXP (op1, 0), &XEXP (x, 0),
>                                      base_reg_class (mode, as,
> -                                                    code, index_code),
> +                                                    code, index_code,
> +                                                    insn),
>                                      GET_MODE (x), GET_MODE (x), 0, 0,
>                                      opnum, RELOAD_OTHER);
>
> @@ -6216,7 +6222,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),
> +                                  MEM, SCRATCH, insn),
>                    GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, opnum, type);
>        reloaded = 1;
>      }
> diff --git a/gcc/reload1.cc b/gcc/reload1.cc
> index 9ba822d1ff7..f41f4a4de22 100644
> --- a/gcc/reload1.cc
> +++ b/gcc/reload1.cc
> @@ -1382,7 +1382,7 @@ 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)];
> +                                            ADDRESS, SCRATCH, chain->insn)];
>                   else
>                     cls = (int) reg_class_subunion[cls]
>                       [reg_class_for_constraint (cn)];
> --
> 2.31.1
>
Hongyu Wang Sept. 1, 2023, 9:07 a.m. UTC | #2
Uros Bizjak via Gcc-patches <gcc-patches@gcc.gnu.org> 于2023年8月31日周四 18:16写道:
>
> On Thu, Aug 31, 2023 at 10:20 AM Hongyu Wang <hongyu.wang@intel.com> wrote:
> >
> > From: Kong Lingling <lingling.kong@intel.com>
> >
> > Current reload infrastructure does not support selective base_reg_class
> > for backend insn. Add insn argument to base_reg_class for
> > lra/reload usage.
>
> I don't think this is the correct approach. Ideally, a memory
> constraint should somehow encode its BASE/INDEX register class.
> Instead of passing "insn", simply a different constraint could be used
> in the constraint string of the relevant insn.

We tried constraint only at the beginning, but then we found the
reload infrastructure
does not work like that.

The BASE/INDEX reg classes are determined before choosing alternatives, in
process_address under curr_insn_transform. Process_address creates the mem
operand according to the BASE/INDEX reg class. Then, the memory operand
constraint check will evaluate the mem op with targetm.legitimate_address_p.

If we want to make use of EGPR in base/index we need to either extend BASE/INDEX
reg class in the backend, or, for specific insns, add a target hook to
tell reload
that the extended reg class with EGPR can be used to construct memory operand.

CC'd Vladimir as git send-mail failed to add recipient.

>
> Uros.
> >
> > gcc/ChangeLog:
> >
> >         * addresses.h (base_reg_class):  Add insn argument.
> >         Pass to MODE_CODE_BASE_REG_CLASS.
> >         (regno_ok_for_base_p_1): Add insn argument.
> >         Pass to REGNO_MODE_CODE_OK_FOR_BASE_P.
> >         (regno_ok_for_base_p): Add insn argument and parse to ok_for_base_p_1.
> >         * config/avr/avr.h (MODE_CODE_BASE_REG_CLASS): Add insn argument.
> >         (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
> >         * config/gcn/gcn.h (MODE_CODE_BASE_REG_CLASS): Ditto.
> >         (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
> >         * config/rl78/rl78.h (REGNO_MODE_CODE_OK_FOR_BASE_P): Ditto.
> >         (MODE_CODE_BASE_REG_CLASS): Ditto.
> >         * doc/tm.texi: Add insn argument for MODE_CODE_BASE_REG_CLASS
> >         and REGNO_MODE_CODE_OK_FOR_BASE_P.
> >         * doc/tm.texi.in: Ditto.
> >         * lra-constraints.cc (process_address_1): Pass insn to
> >         base_reg_class.
> >         (curr_insn_transform): Ditto.
> >         * reload.cc (find_reloads): Ditto.
> >         (find_reloads_address): Ditto.
> >         (find_reloads_address_1): Ditto.
> >         (find_reloads_subreg_address): Ditto.
> >         * reload1.cc (maybe_fix_stack_asms): Ditto.
> > ---
> >  gcc/addresses.h        | 15 +++++++++------
> >  gcc/config/avr/avr.h   |  5 +++--
> >  gcc/config/gcn/gcn.h   |  4 ++--
> >  gcc/config/rl78/rl78.h |  6 ++++--
> >  gcc/doc/tm.texi        |  8 ++++++--
> >  gcc/doc/tm.texi.in     |  8 ++++++--
> >  gcc/lra-constraints.cc | 15 +++++++++------
> >  gcc/reload.cc          | 30 ++++++++++++++++++------------
> >  gcc/reload1.cc         |  2 +-
> >  9 files changed, 58 insertions(+), 35 deletions(-)
> >
> > diff --git a/gcc/addresses.h b/gcc/addresses.h
> > index 3519c241c6d..08b100cfe6d 100644
> > --- a/gcc/addresses.h
> > +++ b/gcc/addresses.h
> > @@ -28,11 +28,12 @@ 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)
> > +               enum rtx_code index_code ATTRIBUTE_UNUSED,
> > +               rtx_insn *insn ATTRIBUTE_UNUSED = NULL)
> >  {
> >  #ifdef MODE_CODE_BASE_REG_CLASS
> >    return MODE_CODE_BASE_REG_CLASS (MACRO_MODE (mode), as, outer_code,
> > -                                  index_code);
> > +                                  index_code, insn);
> >  #else
> >  #ifdef MODE_BASE_REG_REG_CLASS
> >    if (index_code == REG)
> > @@ -56,11 +57,12 @@ ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
> >                  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)
> > +                enum rtx_code index_code ATTRIBUTE_UNUSED,
> > +                rtx_insn* insn ATTRIBUTE_UNUSED = NULL)
> >  {
> >  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
> >    return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, MACRO_MODE (mode), as,
> > -                                       outer_code, index_code);
> > +                                       outer_code, index_code, insn);
> >  #else
> >  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
> >    if (index_code == REG)
> > @@ -79,12 +81,13 @@ ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
> >
> >  inline bool
> >  regno_ok_for_base_p (unsigned regno, machine_mode mode, addr_space_t as,
> > -                    enum rtx_code outer_code, enum rtx_code index_code)
> > +                    enum rtx_code outer_code, enum rtx_code index_code,
> > +                    rtx_insn* insn = NULL)
> >  {
> >    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
> >      regno = reg_renumber[regno];
> >
> > -  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
> > +  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code, insn);
> >  }
> >
> >  #endif /* GCC_ADDRESSES_H */
> > diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
> > index 8e7e00db13b..1d090fe0838 100644
> > --- a/gcc/config/avr/avr.h
> > +++ b/gcc/config/avr/avr.h
> > @@ -280,12 +280,13 @@ enum reg_class {
> >
> >  #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
> >
> > -#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code)   \
> > +#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code, insn)   \
> >    avr_mode_code_base_reg_class (mode, as, outer_code, index_code)
> >
> >  #define INDEX_REG_CLASS NO_REGS
> >
> > -#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code, index_code) \
> > +#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code,         \
> > +                                     index_code, insn)                   \
> >    avr_regno_mode_code_ok_for_base_p (num, mode, as, outer_code, index_code)
> >
> >  #define REGNO_OK_FOR_INDEX_P(NUM) 0
> > diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
> > index 4ff9a5d4d12..b56702a77fd 100644
> > --- a/gcc/config/gcn/gcn.h
> > +++ b/gcc/config/gcn/gcn.h
> > @@ -437,9 +437,9 @@ enum reg_class
> >       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }}
> >
> >  #define REGNO_REG_CLASS(REGNO) gcn_regno_reg_class (REGNO)
> > -#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX) \
> > +#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX, INSN) \
> >          gcn_mode_code_base_reg_class (MODE, AS, OUTER, INDEX)
> > -#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX) \
> > +#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX, INSN) \
> >          gcn_regno_mode_code_ok_for_base_p (NUM, MODE, AS, OUTER, INDEX)
> >  #define INDEX_REG_CLASS VGPR_REGS
> >  #define REGNO_OK_FOR_INDEX_P(regno) regno_ok_for_index_p (regno)
> > diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h
> > index 7a7c6a44ba2..d0ed9162292 100644
> > --- a/gcc/config/rl78/rl78.h
> > +++ b/gcc/config/rl78/rl78.h
> > @@ -375,10 +375,12 @@ enum reg_class
> >
> >  #define REGNO_OK_FOR_INDEX_P(regno)    REGNO_OK_FOR_BASE_P (regno)
> >
> > -#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, index_code) \
> > +#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, \
> > +                                     index_code, insn)                       \
> >    rl78_regno_mode_code_ok_for_base_p (regno, mode, address_space, outer_code, index_code)
> >
> > -#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code) \
> > +#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code, \
> > +                                insn)                                        \
> >    rl78_mode_code_base_reg_class (mode, address_space, outer_code, index_code)
> >
> >  #define RETURN_ADDR_RTX(COUNT, FRAMEADDR)                              \
> > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> > index d0d47b0d471..a4239e3de10 100644
> > --- a/gcc/doc/tm.texi
> > +++ b/gcc/doc/tm.texi
> > @@ -2533,7 +2533,7 @@ register address.  You should define this macro if base plus index
> >  addresses have different requirements than other base register uses.
> >  @end defmac
> >
> > -@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> > +@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
> >  A C expression whose value is the register class to which a valid
> >  base register for a memory reference in mode @var{mode} to address
> >  space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
> > @@ -2542,6 +2542,8 @@ 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.
> > +@code{insn} indicates insn specific base register class should be subset
> > +of the original base register class.
> >  @end defmac
> >
> >  @defmac INDEX_REG_CLASS
> > @@ -2579,7 +2581,7 @@ Use of this macro is deprecated; please use the more general
> >  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
> >  @end defmac
> >
> > -@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> > +@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
> >  A C expression which is nonzero if register number @var{num} is
> >  suitable for use as a base register in operand addresses, accessing
> >  memory in mode @var{mode} in address space @var{address_space}.
> > @@ -2592,6 +2594,8 @@ address, @code{ADDRESS} for something that occurs in an
> >  corresponding index expression if @var{outer_code} is @code{PLUS};
> >  @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
> >  that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
> > +@code{insn} indicates insn specific base register class should be subset
> > +of the original base register class.
> >  @end defmac
> >
> >  @defmac REGNO_OK_FOR_INDEX_P (@var{num})
> > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> > index 4ac96dc357d..72898f3adba 100644
> > --- a/gcc/doc/tm.texi.in
> > +++ b/gcc/doc/tm.texi.in
> > @@ -2128,7 +2128,7 @@ register address.  You should define this macro if base plus index
> >  addresses have different requirements than other base register uses.
> >  @end defmac
> >
> > -@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> > +@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
> >  A C expression whose value is the register class to which a valid
> >  base register for a memory reference in mode @var{mode} to address
> >  space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
> > @@ -2137,6 +2137,8 @@ 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.
> > +@code{insn} indicates insn specific base register class should be subset
> > +of the original base register class.
> >  @end defmac
> >
> >  @defmac INDEX_REG_CLASS
> > @@ -2174,7 +2176,7 @@ Use of this macro is deprecated; please use the more general
> >  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
> >  @end defmac
> >
> > -@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
> > +@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
> >  A C expression which is nonzero if register number @var{num} is
> >  suitable for use as a base register in operand addresses, accessing
> >  memory in mode @var{mode} in address space @var{address_space}.
> > @@ -2187,6 +2189,8 @@ address, @code{ADDRESS} for something that occurs in an
> >  corresponding index expression if @var{outer_code} is @code{PLUS};
> >  @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
> >  that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
> > +@code{insn} indicates insn specific base register class should be subset
> > +of the original base register class.
> >  @end defmac
> >
> >  @defmac REGNO_OK_FOR_INDEX_P (@var{num})
> > diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> > index c718bedff32..9e7915ce934 100644
> > --- a/gcc/lra-constraints.cc
> > +++ b/gcc/lra-constraints.cc
> > @@ -3672,7 +3672,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)))))
> > +                          get_index_code (&ad), curr_insn))))
> >      {
> >        change_p = true;
> >        if (ad.base_term2 != NULL)
> > @@ -3722,7 +3722,8 @@ process_address_1 (int nop, bool check_only_p,
> >           rtx_insn *last = get_last_insn ();
> >           int code = -1;
> >           enum reg_class cl = base_reg_class (ad.mode, ad.as,
> > -                                             SCRATCH, SCRATCH);
> > +                                             SCRATCH, SCRATCH,
> > +                                             curr_insn);
> >           rtx addr = *ad.inner;
> >
> >           new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
> > @@ -3785,7 +3786,8 @@ process_address_1 (int nop, bool check_only_p,
> >           /* index * scale + disp => new base + index * scale,
> >              case (1) above.  */
> >           enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS,
> > -                                             GET_CODE (*ad.index));
> > +                                             GET_CODE (*ad.index),
> > +                                             curr_insn);
> >
> >           lra_assert (INDEX_REG_CLASS != NO_REGS);
> >           new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "disp");
> > @@ -3846,7 +3848,7 @@ process_address_1 (int nop, bool check_only_p,
> >               *ad.base_term = XEXP (SET_SRC (set), 0);
> >               *ad.disp_term = XEXP (SET_SRC (set), 1);
> >               cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
> > -                                  get_index_code (&ad));
> > +                                  get_index_code (&ad), curr_insn);
> >               regno = REGNO (*ad.base_term);
> >               if (regno >= FIRST_PSEUDO_REGISTER
> >                   && cl != lra_get_allocno_class (regno))
> > @@ -3890,7 +3892,8 @@ process_address_1 (int nop, bool check_only_p,
> >    else
> >      {
> >        enum reg_class cl = base_reg_class (ad.mode, ad.as,
> > -                                         SCRATCH, SCRATCH);
> > +                                         SCRATCH, SCRATCH,
> > +                                         curr_insn);
> >        rtx addr = *ad.inner;
> >
> >        new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
> > @@ -4639,7 +4642,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);
> > +                                  MEM, SCRATCH, curr_insn);
> >           if (GET_RTX_CLASS (code) == RTX_AUTOINC)
> >             new_reg = emit_inc (rclass, *loc, *loc,
> >                                 /* This value does not matter for MODIFY.  */
> > diff --git a/gcc/reload.cc b/gcc/reload.cc
> > index 2126bdd117c..72f7e27af15 100644
> > --- a/gcc/reload.cc
> > +++ b/gcc/reload.cc
> > @@ -3321,7 +3321,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);
> > +                                       ADDRESS, SCRATCH, insn);
> >                     win = 1;
> >                     badop = 0;
> >                     break;
> > @@ -3508,7 +3508,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);
> > +                                           ADDRESS, SCRATCH, insn);
> >                         badop = 0;
> >                         break;
> >
> > @@ -4018,7 +4018,7 @@ 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),
> > +                            base_reg_class (VOIDmode, as, MEM, SCRATCH, insn),
> >                              address_mode,
> >                              VOIDmode, 0, 0, i, RELOAD_OTHER);
> >             rld[operand_reloadnum[i]].inc
> > @@ -4897,7 +4897,8 @@ 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),
> > +                                    base_reg_class (mode, as, MEM,
> > +                                                    SCRATCH, insn),
> >                                      GET_MODE (ad), opnum, type, ind_levels);
> >           return 1;
> >         }
> > @@ -4966,7 +4967,7 @@ 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),
> > +                  base_reg_class (mode, as, MEM, SCRATCH, insn),
> >                    GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
> >        return 1;
> >      }
> > @@ -5123,7 +5124,8 @@ 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),
> > +                                    base_reg_class (mode, as, MEM,
> > +                                                    SCRATCH, insn),
> >                                      GET_MODE (ad), opnum, type, ind_levels);
> >         }
> >        return ! removed_and;
> > @@ -5203,7 +5205,7 @@ 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));
> > +         cls = base_reg_class (mode, as, MEM, GET_CODE (addend), insn);
> >           find_reloads_address_part (XEXP (ad, op_index),
> >                                      &XEXP (ad, op_index), cls,
> >                                      GET_MODE (ad), opnum, type, ind_levels);
> > @@ -5261,7 +5263,8 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
> >         }
> >
> >        find_reloads_address_part (ad, loc,
> > -                                base_reg_class (mode, as, MEM, SCRATCH),
> > +                                base_reg_class (mode, as, MEM,
> > +                                                SCRATCH, insn),
> >                                  address_mode, opnum, type, ind_levels);
> >        return ! removed_and;
> >      }
> > @@ -5513,7 +5516,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
> >    if (context == 1)
> >      context_reg_class = INDEX_REG_CLASS;
> >    else
> > -    context_reg_class = base_reg_class (mode, as, outer_code, index_code);
> > +    context_reg_class = base_reg_class (mode, as, outer_code, index_code,
> > +                                       insn);
> >
> >    switch (code)
> >      {
> > @@ -5738,7 +5742,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
> >                 reloadnum = push_reload (tem, tem, &XEXP (x, 0),
> >                                          &XEXP (op1, 0),
> >                                          base_reg_class (mode, as,
> > -                                                        code, index_code),
> > +                                                        code, index_code,
> > +                                                        insn),
> >                                          GET_MODE (x), GET_MODE (x), 0,
> >                                          0, opnum, RELOAD_OTHER);
> >
> > @@ -5756,7 +5761,8 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as,
> >             reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
> >                                      &XEXP (op1, 0), &XEXP (x, 0),
> >                                      base_reg_class (mode, as,
> > -                                                    code, index_code),
> > +                                                    code, index_code,
> > +                                                    insn),
> >                                      GET_MODE (x), GET_MODE (x), 0, 0,
> >                                      opnum, RELOAD_OTHER);
> >
> > @@ -6216,7 +6222,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),
> > +                                  MEM, SCRATCH, insn),
> >                    GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, opnum, type);
> >        reloaded = 1;
> >      }
> > diff --git a/gcc/reload1.cc b/gcc/reload1.cc
> > index 9ba822d1ff7..f41f4a4de22 100644
> > --- a/gcc/reload1.cc
> > +++ b/gcc/reload1.cc
> > @@ -1382,7 +1382,7 @@ 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)];
> > +                                            ADDRESS, SCRATCH, chain->insn)];
> >                   else
> >                     cls = (int) reg_class_subunion[cls]
> >                       [reg_class_for_constraint (cn)];
> > --
> > 2.31.1
> >
Vladimir Makarov Sept. 6, 2023, 7:43 p.m. UTC | #3
On 9/1/23 05:07, Hongyu Wang wrote:
> Uros Bizjak via Gcc-patches <gcc-patches@gcc.gnu.org> 于2023年8月31日周四 18:16写道:
>> On Thu, Aug 31, 2023 at 10:20 AM Hongyu Wang <hongyu.wang@intel.com> wrote:
>>> From: Kong Lingling <lingling.kong@intel.com>
>>>
>>> Current reload infrastructure does not support selective base_reg_class
>>> for backend insn. Add insn argument to base_reg_class for
>>> lra/reload usage.
>> I don't think this is the correct approach. Ideally, a memory
>> constraint should somehow encode its BASE/INDEX register class.
>> Instead of passing "insn", simply a different constraint could be used
>> in the constraint string of the relevant insn.
> We tried constraint only at the beginning, but then we found the
> reload infrastructure
> does not work like that.
>
> The BASE/INDEX reg classes are determined before choosing alternatives, in
> process_address under curr_insn_transform. Process_address creates the mem
> operand according to the BASE/INDEX reg class. Then, the memory operand
> constraint check will evaluate the mem op with targetm.legitimate_address_p.
>
> If we want to make use of EGPR in base/index we need to either extend BASE/INDEX
> reg class in the backend, or, for specific insns, add a target hook to
> tell reload
> that the extended reg class with EGPR can be used to construct memory operand.
>
> CC'd Vladimir as git send-mail failed to add recipient.
>
>
I think the approach proposed by Intel developers is better.  In some way
we already use such approach when we pass memory mode to get the base
reg class.  Although we could use different memory constraints for
different modes when the possible base reg differs for some memory
modes.

Using special memory constraints probably can be implemented too (I
understand attractiveness of such approach for readability of the
machine description).  But in my opinion it will require much bigger
work in IRA/LRA/reload.  It also significantly slow down RA as we need
to process insn constraints for processing each memory in many places
(e.g. for calculation of reg classes and costs in IRA).  Still I think
there will be a few cases for this approach resulting in a bigger
probability of assigning hard reg out of specific base reg class and
this will result in additional reloads.

So the approach proposed by Intel is ok for me.  Although if x86 maintainers
are strongly against this approach and the changes in x86 machine
dependent code and Intel developers implement Uros approach, I am
ready to review this.  But still I prefer the current Intel developers
approach for reasons I mentioned above.
Uros Bizjak Sept. 7, 2023, 6:23 a.m. UTC | #4
On Wed, Sep 6, 2023 at 9:43 PM Vladimir Makarov <vmakarov@redhat.com> wrote:
>
>
> On 9/1/23 05:07, Hongyu Wang wrote:
> > Uros Bizjak via Gcc-patches <gcc-patches@gcc.gnu.org> 于2023年8月31日周四 18:16写道:
> >> On Thu, Aug 31, 2023 at 10:20 AM Hongyu Wang <hongyu.wang@intel.com> wrote:
> >>> From: Kong Lingling <lingling.kong@intel.com>
> >>>
> >>> Current reload infrastructure does not support selective base_reg_class
> >>> for backend insn. Add insn argument to base_reg_class for
> >>> lra/reload usage.
> >> I don't think this is the correct approach. Ideally, a memory
> >> constraint should somehow encode its BASE/INDEX register class.
> >> Instead of passing "insn", simply a different constraint could be used
> >> in the constraint string of the relevant insn.
> > We tried constraint only at the beginning, but then we found the
> > reload infrastructure
> > does not work like that.
> >
> > The BASE/INDEX reg classes are determined before choosing alternatives, in
> > process_address under curr_insn_transform. Process_address creates the mem
> > operand according to the BASE/INDEX reg class. Then, the memory operand
> > constraint check will evaluate the mem op with targetm.legitimate_address_p.
> >
> > If we want to make use of EGPR in base/index we need to either extend BASE/INDEX
> > reg class in the backend, or, for specific insns, add a target hook to
> > tell reload
> > that the extended reg class with EGPR can be used to construct memory operand.
> >
> > CC'd Vladimir as git send-mail failed to add recipient.
> >
> >
> I think the approach proposed by Intel developers is better.  In some way
> we already use such approach when we pass memory mode to get the base
> reg class.  Although we could use different memory constraints for
> different modes when the possible base reg differs for some memory
> modes.
>
> Using special memory constraints probably can be implemented too (I
> understand attractiveness of such approach for readability of the
> machine description).  But in my opinion it will require much bigger
> work in IRA/LRA/reload.  It also significantly slow down RA as we need
> to process insn constraints for processing each memory in many places
> (e.g. for calculation of reg classes and costs in IRA).  Still I think
> there will be a few cases for this approach resulting in a bigger
> probability of assigning hard reg out of specific base reg class and
> this will result in additional reloads.
>
> So the approach proposed by Intel is ok for me.  Although if x86 maintainers
> are strongly against this approach and the changes in x86 machine
> dependent code and Intel developers implement Uros approach, I am
> ready to review this.  But still I prefer the current Intel developers
> approach for reasons I mentioned above.

My above proposal is more or less a wish from a target maintainer PoV.
Ideally, we would have a bunch of different memory constraints, and a
target hook that returns corresponding BASE/INDEX reg classes.
However, I have no idea about the complexity of the implementation in
the infrastructure part of the compiler.

Uros.
Vladimir Makarov Sept. 7, 2023, 12:13 p.m. UTC | #5
On 9/7/23 02:23, Uros Bizjak wrote:
> On Wed, Sep 6, 2023 at 9:43 PM Vladimir Makarov <vmakarov@redhat.com> wrote:
>>
>> On 9/1/23 05:07, Hongyu Wang wrote:
>>>
>> I think the approach proposed by Intel developers is better.  In some way
>> we already use such approach when we pass memory mode to get the base
>> reg class.  Although we could use different memory constraints for
>> different modes when the possible base reg differs for some memory
>> modes.
>>
>> Using special memory constraints probably can be implemented too (I
>> understand attractiveness of such approach for readability of the
>> machine description).  But in my opinion it will require much bigger
>> work in IRA/LRA/reload.  It also significantly slow down RA as we need
>> to process insn constraints for processing each memory in many places
>> (e.g. for calculation of reg classes and costs in IRA).  Still I think
>> there will be a few cases for this approach resulting in a bigger
>> probability of assigning hard reg out of specific base reg class and
>> this will result in additional reloads.
>>
>> So the approach proposed by Intel is ok for me.  Although if x86 maintainers
>> are strongly against this approach and the changes in x86 machine
>> dependent code and Intel developers implement Uros approach, I am
>> ready to review this.  But still I prefer the current Intel developers
>> approach for reasons I mentioned above.
> My above proposal is more or less a wish from a target maintainer PoV.
> Ideally, we would have a bunch of different memory constraints, and a
> target hook that returns corresponding BASE/INDEX reg classes.
> However, I have no idea about the complexity of the implementation in
> the infrastructure part of the compiler.
>
Basically, it needs introducing new hooks which return base and index 
classes from special memory constraints. When we process memory in an 
insn (a lot of places in IRA, LRA,reload) we should consider all 
possible memory insn constraints, take intersection of basic and index 
reg classes for the constraints and use them instead of the default base 
and reg classes.

The required functionality is absent in reload too.

I would say that it is a moderate size project (1-2 months for me).  It 
still requires to introduce new hooks and I guess there are few cases 
when we will still assign hard regs out of desirable base class for 
address pseudos and this will results in generation of additional reload 
insns.  It also means much more additional changes in RA source code and 
x86 machine dependent files.

Probably, with this approach there will be also edge cases when we need 
to solve new PRs because of LRA failures to generate the correct code 
but I believe they can be solved.

Therefore I lean toward the current Intel approach when to get base reg 
class we pass the insn as a parameter additionally to memory mode.
Vladimir Makarov Sept. 8, 2023, 5:03 p.m. UTC | #6
On 8/31/23 04:20, Hongyu Wang wrote:
> @@ -2542,6 +2542,8 @@ 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.
> +@code{insn} indicates insn specific base register class should be subset
> +of the original base register class.
>   @end defmac

I'd prefer more general description of 'insn' argument for the macros.  
Something like that:

@code{insn} can be used to define an insn-specific base register class.
Hongyu Wang Sept. 10, 2023, 4:49 a.m. UTC | #7
Vladimir Makarov via Gcc-patches <gcc-patches@gcc.gnu.org> 于2023年9月9日周六 01:04写道:
>
>
> On 8/31/23 04:20, Hongyu Wang wrote:
> > @@ -2542,6 +2542,8 @@ 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.
> > +@code{insn} indicates insn specific base register class should be subset
> > +of the original base register class.
> >   @end defmac
>
> I'd prefer more general description of 'insn' argument for the macros.
> Something like that:
>
> @code{insn} can be used to define an insn-specific base register class.
>

Sure, will adjust in the V2 patch.
Also, currently we reuse the old macro MODE_CODE_BASE_REG_CLASS, do
you think we need a new macro like INSN_BASE_REG_CLASS as other
parameters are actually unused? Then we don't need to change other
targets like avr/gcn.
Vladimir Makarov Sept. 14, 2023, 12:09 p.m. UTC | #8
On 9/10/23 00:49, Hongyu Wang wrote:
> Vladimir Makarov via Gcc-patches <gcc-patches@gcc.gnu.org> 于2023年9月9日周六 01:04写道:
>>
>> On 8/31/23 04:20, Hongyu Wang wrote:
>>> @@ -2542,6 +2542,8 @@ 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.
>>> +@code{insn} indicates insn specific base register class should be subset
>>> +of the original base register class.
>>>    @end defmac
>> I'd prefer more general description of 'insn' argument for the macros.
>> Something like that:
>>
>> @code{insn} can be used to define an insn-specific base register class.
>>
> Sure, will adjust in the V2 patch.
> Also, currently we reuse the old macro MODE_CODE_BASE_REG_CLASS, do
> you think we need a new macro like INSN_BASE_REG_CLASS as other
> parameters are actually unused? Then we don't need to change other
> targets like avr/gcn.
>
I thought about this too.  Using new macros would be definitely worth to 
add, especially when you are already adding INSN_INDEX_REG_CLASS.

The names INSN_BASE_REG_CLASS instead of MODE_CODE_BASE_REG_CLASS and 
REGNO_OK_FOR_INSN_BASE_P instead of REGNO_MODE_CODE_OK_FOR_BASE_P are ok 
for me too.

When you submit the v2 patch, I'll review the RA part as soon as 
possible (actually I already looked at this) and most probably give my 
approval for the RA part because I prefer you current approach for RA 
instead of introducing new memory constraints.
diff mbox series

Patch

diff --git a/gcc/addresses.h b/gcc/addresses.h
index 3519c241c6d..08b100cfe6d 100644
--- a/gcc/addresses.h
+++ b/gcc/addresses.h
@@ -28,11 +28,12 @@  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)
+		enum rtx_code index_code ATTRIBUTE_UNUSED,
+		rtx_insn *insn ATTRIBUTE_UNUSED = NULL)
 {
 #ifdef MODE_CODE_BASE_REG_CLASS
   return MODE_CODE_BASE_REG_CLASS (MACRO_MODE (mode), as, outer_code,
-				   index_code);
+				   index_code, insn);
 #else
 #ifdef MODE_BASE_REG_REG_CLASS
   if (index_code == REG)
@@ -56,11 +57,12 @@  ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
 		 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)
+		 enum rtx_code index_code ATTRIBUTE_UNUSED,
+		 rtx_insn* insn ATTRIBUTE_UNUSED = NULL)
 {
 #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
   return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, MACRO_MODE (mode), as,
-					outer_code, index_code);
+					outer_code, index_code, insn);
 #else
 #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
   if (index_code == REG)
@@ -79,12 +81,13 @@  ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
 
 inline bool
 regno_ok_for_base_p (unsigned regno, machine_mode mode, addr_space_t as,
-		     enum rtx_code outer_code, enum rtx_code index_code)
+		     enum rtx_code outer_code, enum rtx_code index_code,
+		     rtx_insn* insn = NULL)
 {
   if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
     regno = reg_renumber[regno];
 
-  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
+  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code, insn);
 }
 
 #endif /* GCC_ADDRESSES_H */
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 8e7e00db13b..1d090fe0838 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -280,12 +280,13 @@  enum reg_class {
 
 #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
 
-#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code)   \
+#define MODE_CODE_BASE_REG_CLASS(mode, as, outer_code, index_code, insn)   \
   avr_mode_code_base_reg_class (mode, as, outer_code, index_code)
 
 #define INDEX_REG_CLASS NO_REGS
 
-#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code, index_code) \
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, as, outer_code,	  \
+				      index_code, insn)			  \
   avr_regno_mode_code_ok_for_base_p (num, mode, as, outer_code, index_code)
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
diff --git a/gcc/config/gcn/gcn.h b/gcc/config/gcn/gcn.h
index 4ff9a5d4d12..b56702a77fd 100644
--- a/gcc/config/gcn/gcn.h
+++ b/gcc/config/gcn/gcn.h
@@ -437,9 +437,9 @@  enum reg_class
      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }}
 
 #define REGNO_REG_CLASS(REGNO) gcn_regno_reg_class (REGNO)
-#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX) \
+#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX, INSN) \
 	 gcn_mode_code_base_reg_class (MODE, AS, OUTER, INDEX)
-#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX) \
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX, INSN) \
 	 gcn_regno_mode_code_ok_for_base_p (NUM, MODE, AS, OUTER, INDEX)
 #define INDEX_REG_CLASS VGPR_REGS
 #define REGNO_OK_FOR_INDEX_P(regno) regno_ok_for_index_p (regno)
diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h
index 7a7c6a44ba2..d0ed9162292 100644
--- a/gcc/config/rl78/rl78.h
+++ b/gcc/config/rl78/rl78.h
@@ -375,10 +375,12 @@  enum reg_class
 
 #define REGNO_OK_FOR_INDEX_P(regno)	REGNO_OK_FOR_BASE_P (regno)
 
-#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, index_code) \
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(regno, mode, address_space, outer_code, \
+				      index_code, insn)			      \
   rl78_regno_mode_code_ok_for_base_p (regno, mode, address_space, outer_code, index_code)
 
-#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code) \
+#define MODE_CODE_BASE_REG_CLASS(mode, address_space, outer_code, index_code, \
+				 insn) 					      \
   rl78_mode_code_base_reg_class (mode, address_space, outer_code, index_code)
 
 #define RETURN_ADDR_RTX(COUNT, FRAMEADDR)				\
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index d0d47b0d471..a4239e3de10 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2533,7 +2533,7 @@  register address.  You should define this macro if base plus index
 addresses have different requirements than other base register uses.
 @end defmac
 
-@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
 A C expression whose value is the register class to which a valid
 base register for a memory reference in mode @var{mode} to address
 space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
@@ -2542,6 +2542,8 @@  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.
+@code{insn} indicates insn specific base register class should be subset
+of the original base register class.
 @end defmac
 
 @defmac INDEX_REG_CLASS
@@ -2579,7 +2581,7 @@  Use of this macro is deprecated; please use the more general
 @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
 @end defmac
 
-@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
 A C expression which is nonzero if register number @var{num} is
 suitable for use as a base register in operand addresses, accessing
 memory in mode @var{mode} in address space @var{address_space}.
@@ -2592,6 +2594,8 @@  address, @code{ADDRESS} for something that occurs in an
 corresponding index expression if @var{outer_code} is @code{PLUS};
 @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
 that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
+@code{insn} indicates insn specific base register class should be subset
+of the original base register class.
 @end defmac
 
 @defmac REGNO_OK_FOR_INDEX_P (@var{num})
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 4ac96dc357d..72898f3adba 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -2128,7 +2128,7 @@  register address.  You should define this macro if base plus index
 addresses have different requirements than other base register uses.
 @end defmac
 
-@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
 A C expression whose value is the register class to which a valid
 base register for a memory reference in mode @var{mode} to address
 space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
@@ -2137,6 +2137,8 @@  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.
+@code{insn} indicates insn specific base register class should be subset
+of the original base register class.
 @end defmac
 
 @defmac INDEX_REG_CLASS
@@ -2174,7 +2176,7 @@  Use of this macro is deprecated; please use the more general
 @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
 @end defmac
 
-@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code}, @var{insn})
 A C expression which is nonzero if register number @var{num} is
 suitable for use as a base register in operand addresses, accessing
 memory in mode @var{mode} in address space @var{address_space}.
@@ -2187,6 +2189,8 @@  address, @code{ADDRESS} for something that occurs in an
 corresponding index expression if @var{outer_code} is @code{PLUS};
 @code{SCRATCH} otherwise.  The mode may be @code{VOIDmode} for addresses
 that appear outside a @code{MEM}, i.e., as an @code{address_operand}.
+@code{insn} indicates insn specific base register class should be subset
+of the original base register class.
 @end defmac
 
 @defmac REGNO_OK_FOR_INDEX_P (@var{num})
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index c718bedff32..9e7915ce934 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -3672,7 +3672,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)))))
+			   get_index_code (&ad), curr_insn))))
     {
       change_p = true;
       if (ad.base_term2 != NULL)
@@ -3722,7 +3722,8 @@  process_address_1 (int nop, bool check_only_p,
 	  rtx_insn *last = get_last_insn ();
 	  int code = -1;
 	  enum reg_class cl = base_reg_class (ad.mode, ad.as,
-					      SCRATCH, SCRATCH);
+					      SCRATCH, SCRATCH,
+					      curr_insn);
 	  rtx addr = *ad.inner;
 
 	  new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
@@ -3785,7 +3786,8 @@  process_address_1 (int nop, bool check_only_p,
 	  /* index * scale + disp => new base + index * scale,
 	     case (1) above.  */
 	  enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS,
-					      GET_CODE (*ad.index));
+					      GET_CODE (*ad.index),
+					      curr_insn);
 
 	  lra_assert (INDEX_REG_CLASS != NO_REGS);
 	  new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "disp");
@@ -3846,7 +3848,7 @@  process_address_1 (int nop, bool check_only_p,
 	      *ad.base_term = XEXP (SET_SRC (set), 0);
 	      *ad.disp_term = XEXP (SET_SRC (set), 1);
 	      cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
-				   get_index_code (&ad));
+				   get_index_code (&ad), curr_insn);
 	      regno = REGNO (*ad.base_term);
 	      if (regno >= FIRST_PSEUDO_REGISTER
 		  && cl != lra_get_allocno_class (regno))
@@ -3890,7 +3892,8 @@  process_address_1 (int nop, bool check_only_p,
   else
     {
       enum reg_class cl = base_reg_class (ad.mode, ad.as,
-					  SCRATCH, SCRATCH);
+					  SCRATCH, SCRATCH,
+					  curr_insn);
       rtx addr = *ad.inner;
       
       new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr");
@@ -4639,7 +4642,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);
+				   MEM, SCRATCH, curr_insn);
 	  if (GET_RTX_CLASS (code) == RTX_AUTOINC)
 	    new_reg = emit_inc (rclass, *loc, *loc,
 				/* This value does not matter for MODIFY.  */
diff --git a/gcc/reload.cc b/gcc/reload.cc
index 2126bdd117c..72f7e27af15 100644
--- a/gcc/reload.cc
+++ b/gcc/reload.cc
@@ -3321,7 +3321,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);
+					ADDRESS, SCRATCH, insn);
 		    win = 1;
 		    badop = 0;
 		    break;
@@ -3508,7 +3508,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);
+					    ADDRESS, SCRATCH, insn);
 			badop = 0;
 			break;
 
@@ -4018,7 +4018,7 @@  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),
+			     base_reg_class (VOIDmode, as, MEM, SCRATCH, insn),
 			     address_mode,
 			     VOIDmode, 0, 0, i, RELOAD_OTHER);
 	    rld[operand_reloadnum[i]].inc
@@ -4897,7 +4897,8 @@  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),
+				     base_reg_class (mode, as, MEM,
+						     SCRATCH, insn),
 				     GET_MODE (ad), opnum, type, ind_levels);
 	  return 1;
 	}
@@ -4966,7 +4967,7 @@  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),
+		   base_reg_class (mode, as, MEM, SCRATCH, insn),
 		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
       return 1;
     }
@@ -5123,7 +5124,8 @@  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),
+				     base_reg_class (mode, as, MEM,
+						     SCRATCH, insn),
 				     GET_MODE (ad), opnum, type, ind_levels);
 	}
       return ! removed_and;
@@ -5203,7 +5205,7 @@  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));
+	  cls = base_reg_class (mode, as, MEM, GET_CODE (addend), insn);
 	  find_reloads_address_part (XEXP (ad, op_index),
 				     &XEXP (ad, op_index), cls,
 				     GET_MODE (ad), opnum, type, ind_levels);
@@ -5261,7 +5263,8 @@  find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
 	}
 
       find_reloads_address_part (ad, loc,
-				 base_reg_class (mode, as, MEM, SCRATCH),
+				 base_reg_class (mode, as, MEM,
+						 SCRATCH, insn),
 				 address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
@@ -5513,7 +5516,8 @@  find_reloads_address_1 (machine_mode mode, addr_space_t as,
   if (context == 1)
     context_reg_class = INDEX_REG_CLASS;
   else
-    context_reg_class = base_reg_class (mode, as, outer_code, index_code);
+    context_reg_class = base_reg_class (mode, as, outer_code, index_code,
+					insn);
 
   switch (code)
     {
@@ -5738,7 +5742,8 @@  find_reloads_address_1 (machine_mode mode, addr_space_t as,
 		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
 					 &XEXP (op1, 0),
 					 base_reg_class (mode, as,
-							 code, index_code),
+							 code, index_code,
+							 insn),
 					 GET_MODE (x), GET_MODE (x), 0,
 					 0, opnum, RELOAD_OTHER);
 
@@ -5756,7 +5761,8 @@  find_reloads_address_1 (machine_mode mode, addr_space_t as,
 	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
 				     &XEXP (op1, 0), &XEXP (x, 0),
 				     base_reg_class (mode, as,
-						     code, index_code),
+						     code, index_code,
+						     insn),
 				     GET_MODE (x), GET_MODE (x), 0, 0,
 				     opnum, RELOAD_OTHER);
 
@@ -6216,7 +6222,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),
+				   MEM, SCRATCH, insn),
 		   GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, opnum, type);
       reloaded = 1;
     }
diff --git a/gcc/reload1.cc b/gcc/reload1.cc
index 9ba822d1ff7..f41f4a4de22 100644
--- a/gcc/reload1.cc
+++ b/gcc/reload1.cc
@@ -1382,7 +1382,7 @@  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)];
+					     ADDRESS, SCRATCH, chain->insn)];
 		  else
 		    cls = (int) reg_class_subunion[cls]
 		      [reg_class_for_constraint (cn)];