[1/3] targhooks: Extend legitimate_address_p with code_helper [PR110248]

Message ID 7928a68a-cb83-3cd7-eacd-63e3f7c2445c@linux.ibm.com
State Unresolved
Headers
Series [1/3] targhooks: Extend legitimate_address_p with code_helper [PR110248] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Kewen.Lin June 30, 2023, 5:37 a.m. UTC
  Hi,

As PR110248 shows, some middle-end passes like IVOPTs can
query the target hook legitimate_address_p with some
artificially constructed rtx to determine whether some
addressing modes are supported by target for some gimple
statement.  But for now the existing legitimate_address_p
only checks the given mode, it's unable to distinguish
some special cases unfortunately, for example, for LEN_LOAD
ifn on Power port, we would expand it with lxvl hardware
insn, which only supports one register to hold the address
(the other register is holding the length), that is we
don't support base (reg) + index (reg) addressing mode for
sure.  But hook legitimate_address_p only considers the
given mode which would be some vector mode for LEN_LOAD
ifn, and we do support base + index addressing mode for
normal vector load and store insns, so the hook will return
true for the query unexpectedly.

This patch is to introduce one extra argument of type
code_helper for hook legitimate_address_p, it makes targets
able to handle some special case like what's described
above.  The subsequent patches will show how to leverage
the new code_helper argument.

I didn't separate those target specific adjustments to
their own patches, since those changes are no function
changes.  One typical change is to add one unnamed argument
with default ERROR_MARK, some ports need to include tree.h
in their {port}-protos.h since the hook is used in some
machine description files.  I've cross-built a corresponding
cc1 successfully for at least one triple of each affected
target so I believe they are safe.  But feel free to correct
me if separating is needed for the review of this patch.

Besides, it's bootstrapped and regtested on
x86_64-redhat-linux and powerpc64{,le}-linux-gnu.

Is it ok for trunk?

BR,
Kewen
------
	PR tree-optimization/110248

gcc/ChangeLog:

	* coretypes.h (class code_helper): Add forward declaration.
	* doc/tm.texi: Regenerate.
	* lra-constraints.cc (valid_address_p): Call target hook
	targetm.addr_space.legitimate_address_p with an extra parameter
	ERROR_MARK as its prototype changes.
	* recog.cc (memory_address_addr_space_p): Likewise.
	* reload.cc (strict_memory_address_addr_space_p): Likewise.
	* target.def (legitimate_address_p, addr_space.legitimate_address_p):
	Extend with one more argument of type code_helper, update the
	documentation accordingly.
	* targhooks.cc (default_legitimate_address_p): Adjust for the
	new code_helper argument.
	(default_addr_space_legitimate_address_p): Likewise.
	* targhooks.h (default_legitimate_address_p): Likewise.
	(default_addr_space_legitimate_address_p): Likewise.
	* config/aarch64/aarch64.cc (aarch64_legitimate_address_hook_p): Adjust
	with extra unnamed code_helper argument with default ERROR_MARK.
	* config/alpha/alpha.cc (alpha_legitimate_address_p): Likewise.
	* config/arc/arc.cc (arc_legitimate_address_p): Likewise.
	* config/arm/arm-protos.h (arm_legitimate_address_p): Likewise.
	(tree.h): New include for tree_code ERROR_MARK.
	* config/arm/arm.cc (arm_legitimate_address_p): Adjust with extra
	unnamed code_helper argument with default ERROR_MARK.
	* config/avr/avr.cc (avr_addr_space_legitimate_address_p): Likewise.
	* config/bfin/bfin.cc (bfin_legitimate_address_p): Likewise.
	* config/bpf/bpf.cc (bpf_legitimate_address_p): Likewise.
	* config/c6x/c6x.cc (c6x_legitimate_address_p): Likewise.
	* config/cris/cris-protos.h (cris_legitimate_address_p): Likewise.
	(tree.h): New include for tree_code ERROR_MARK.
	* config/cris/cris.cc (cris_legitimate_address_p): Adjust with extra
	unnamed code_helper argument with default ERROR_MARK.
	* config/csky/csky.cc (csky_legitimate_address_p): Likewise.
	* config/epiphany/epiphany.cc (epiphany_legitimate_address_p):
	Likewise.
	* config/frv/frv.cc (frv_legitimate_address_p): Likewise.
	* config/ft32/ft32.cc (ft32_addr_space_legitimate_address_p): Likewise.
	* config/gcn/gcn.cc (gcn_addr_space_legitimate_address_p): Likewise.
	* config/h8300/h8300.cc (h8300_legitimate_address_p): Likewise.
	* config/i386/i386.cc (ix86_legitimate_address_p): Likewise.
	* config/ia64/ia64.cc (ia64_legitimate_address_p): Likewise.
	* config/iq2000/iq2000.cc (iq2000_legitimate_address_p): Likewise.
	* config/lm32/lm32.cc (lm32_legitimate_address_p): Likewise.
	* config/loongarch/loongarch.cc (loongarch_legitimate_address_p):
	Likewise.
	* config/m32c/m32c.cc (m32c_legitimate_address_p): Likewise.
	(m32c_addr_space_legitimate_address_p): Likewise.
	* config/m32r/m32r.cc (m32r_legitimate_address_p): Likewise.
	* config/m68k/m68k.cc (m68k_legitimate_address_p): Likewise.
	* config/mcore/mcore.cc (mcore_legitimate_address_p): Likewise.
	* config/microblaze/microblaze-protos.h (tree.h): New include for
	tree_code ERROR_MARK.
	(microblaze_legitimate_address_p): Adjust with extra unnamed
	code_helper argument with default ERROR_MARK.
	* config/microblaze/microblaze.cc (microblaze_legitimate_address_p):
	Likewise.
	* config/mips/mips.cc (mips_legitimate_address_p): Likewise.
	* config/mmix/mmix.cc (mmix_legitimate_address_p): Likewise.
	* config/mn10300/mn10300.cc (mn10300_legitimate_address_p): Likewise.
	* config/moxie/moxie.cc (moxie_legitimate_address_p): Likewise.
	* config/msp430/msp430.cc (msp430_legitimate_address_p): Likewise.
	(msp430_addr_space_legitimate_address_p): Adjust with extra code_helper
	argument with default ERROR_MARK and adjust the call to function
	msp430_legitimate_address_p.
	* config/nds32/nds32.cc (nds32_legitimate_address_p): Adjust with extra
	unnamed code_helper argument with default ERROR_MARK.
	* config/nios2/nios2.cc (nios2_legitimate_address_p): Likewise.
	* config/nvptx/nvptx.cc (nvptx_legitimate_address_p): Likewise.
	* config/or1k/or1k.cc (or1k_legitimate_address_p): Likewise.
	* config/pa/pa.cc (pa_legitimate_address_p): Likewise.
	* config/pdp11/pdp11.cc (pdp11_legitimate_address_p): Likewise.
	* config/pru/pru.cc (pru_addr_space_legitimate_address_p): Likewise.
	* config/riscv/riscv.cc (riscv_legitimate_address_p): Likewise.
	* config/rl78/rl78-protos.h (rl78_as_legitimate_address): Likewise.
	(tree.h): New include for tree_code ERROR_MARK.
	* config/rl78/rl78.cc (rl78_as_legitimate_address): Adjust with
	extra unnamed code_helper argument with default ERROR_MARK.
	* config/rs6000/rs6000.cc (rs6000_legitimate_address_p): Likewise.
	(rs6000_debug_legitimate_address_p): Adjust with extra code_helper
	argument and adjust the call to function rs6000_legitimate_address_p.
	* config/rx/rx.cc (rx_is_legitimate_address): Adjust with extra
	unnamed code_helper argument with default ERROR_MARK.
	* config/s390/s390.cc (s390_legitimate_address_p): Likewise.
	* config/sh/sh.cc (sh_legitimate_address_p): Likewise.
	* config/sparc/sparc.cc (sparc_legitimate_address_p): Likewise.
	* config/v850/v850.cc (v850_legitimate_address_p): Likewise.
	* config/vax/vax.cc (vax_legitimate_address_p): Likewise.
	* config/visium/visium.cc (visium_legitimate_address_p): Likewise.
	* config/xtensa/xtensa.cc (xtensa_legitimate_address_p): Likewise.
	* config/stormy16/stormy16-protos.h (xstormy16_legitimate_address_p):
	Likewise.
	(tree.h): New include for tree_code ERROR_MARK.
	* config/stormy16/stormy16.cc (xstormy16_legitimate_address_p):
	Adjust with extra unnamed code_helper argument with default
	ERROR_MARK.
---
 gcc/config/aarch64/aarch64.cc             |  3 ++-
 gcc/config/alpha/alpha.cc                 |  3 ++-
 gcc/config/arc/arc.cc                     |  3 ++-
 gcc/config/arm/arm-protos.h               |  4 +++-
 gcc/config/arm/arm.cc                     |  2 +-
 gcc/config/avr/avr.cc                     |  4 ++--
 gcc/config/bfin/bfin.cc                   |  3 ++-
 gcc/config/bpf/bpf.cc                     |  3 ++-
 gcc/config/c6x/c6x.cc                     |  3 ++-
 gcc/config/cris/cris-protos.h             |  5 ++++-
 gcc/config/cris/cris.cc                   |  2 +-
 gcc/config/csky/csky.cc                   |  3 ++-
 gcc/config/epiphany/epiphany.cc           |  3 ++-
 gcc/config/frv/frv.cc                     |  5 +++--
 gcc/config/ft32/ft32.cc                   |  3 ++-
 gcc/config/gcn/gcn.cc                     |  2 +-
 gcc/config/h8300/h8300.cc                 |  3 ++-
 gcc/config/i386/i386.cc                   |  3 ++-
 gcc/config/ia64/ia64.cc                   |  7 ++++---
 gcc/config/iq2000/iq2000.cc               |  6 ++++--
 gcc/config/lm32/lm32.cc                   |  7 ++++---
 gcc/config/loongarch/loongarch.cc         |  3 ++-
 gcc/config/m32c/m32c.cc                   | 15 +++++++++------
 gcc/config/m32r/m32r.cc                   |  5 +++--
 gcc/config/m68k/m68k.cc                   |  5 +++--
 gcc/config/mcore/mcore.cc                 |  5 +++--
 gcc/config/microblaze/microblaze-protos.h |  5 ++++-
 gcc/config/microblaze/microblaze.cc       |  3 ++-
 gcc/config/mips/mips.cc                   |  3 ++-
 gcc/config/mmix/mmix.cc                   |  6 ++++--
 gcc/config/mn10300/mn10300.cc             |  3 ++-
 gcc/config/moxie/moxie.cc                 |  3 ++-
 gcc/config/msp430/msp430.cc               |  8 +++++---
 gcc/config/nds32/nds32.cc                 |  3 ++-
 gcc/config/nios2/nios2.cc                 |  5 +++--
 gcc/config/nvptx/nvptx.cc                 |  2 +-
 gcc/config/or1k/or1k.cc                   |  3 ++-
 gcc/config/pa/pa.cc                       |  5 +++--
 gcc/config/pdp11/pdp11.cc                 |  4 ++--
 gcc/config/pru/pru.cc                     |  3 ++-
 gcc/config/riscv/riscv.cc                 |  3 ++-
 gcc/config/rl78/rl78-protos.h             |  6 +++++-
 gcc/config/rl78/rl78.cc                   |  3 ++-
 gcc/config/rs6000/rs6000.cc               | 12 +++++++-----
 gcc/config/rx/rx.cc                       |  3 ++-
 gcc/config/s390/s390.cc                   |  3 ++-
 gcc/config/sh/sh.cc                       |  5 +++--
 gcc/config/sparc/sparc.cc                 |  6 ++++--
 gcc/config/stormy16/stormy16-protos.h     |  5 +++--
 gcc/config/stormy16/stormy16.cc           |  4 ++--
 gcc/config/v850/v850.cc                   |  3 ++-
 gcc/config/vax/vax.cc                     |  5 +++--
 gcc/config/visium/visium.cc               |  5 +++--
 gcc/config/xtensa/xtensa.cc               |  7 ++++---
 gcc/coretypes.h                           |  1 +
 gcc/doc/tm.texi                           | 18 +++++++++++++-----
 gcc/lra-constraints.cc                    |  3 ++-
 gcc/recog.cc                              |  3 ++-
 gcc/reload.cc                             |  3 ++-
 gcc/target.def                            | 18 +++++++++++++-----
 gcc/targhooks.cc                          |  8 +++++---
 gcc/targhooks.h                           |  6 +++---
 62 files changed, 190 insertions(+), 106 deletions(-)

--
2.39.3
  

Comments

Richard Biener June 30, 2023, 8:56 a.m. UTC | #1
On Fri, Jun 30, 2023 at 7:38 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
>
> Hi,
>
> As PR110248 shows, some middle-end passes like IVOPTs can
> query the target hook legitimate_address_p with some
> artificially constructed rtx to determine whether some
> addressing modes are supported by target for some gimple
> statement.  But for now the existing legitimate_address_p
> only checks the given mode, it's unable to distinguish
> some special cases unfortunately, for example, for LEN_LOAD
> ifn on Power port, we would expand it with lxvl hardware
> insn, which only supports one register to hold the address
> (the other register is holding the length), that is we
> don't support base (reg) + index (reg) addressing mode for
> sure.  But hook legitimate_address_p only considers the
> given mode which would be some vector mode for LEN_LOAD
> ifn, and we do support base + index addressing mode for
> normal vector load and store insns, so the hook will return
> true for the query unexpectedly.
>
> This patch is to introduce one extra argument of type
> code_helper for hook legitimate_address_p, it makes targets
> able to handle some special case like what's described
> above.  The subsequent patches will show how to leverage
> the new code_helper argument.
>
> I didn't separate those target specific adjustments to
> their own patches, since those changes are no function
> changes.  One typical change is to add one unnamed argument
> with default ERROR_MARK, some ports need to include tree.h
> in their {port}-protos.h since the hook is used in some
> machine description files.  I've cross-built a corresponding
> cc1 successfully for at least one triple of each affected
> target so I believe they are safe.  But feel free to correct
> me if separating is needed for the review of this patch.
>
> Besides, it's bootstrapped and regtested on
> x86_64-redhat-linux and powerpc64{,le}-linux-gnu.
>
> Is it ok for trunk?

Is defaulting the arguments in the targets necessary for
the middle-end or only for direct uses in the targets?

It looks OK in general but please give others some time to
comment.

Thanks,
Richard.

> BR,
> Kewen
> ------
>         PR tree-optimization/110248
>
> gcc/ChangeLog:
>
>         * coretypes.h (class code_helper): Add forward declaration.
>         * doc/tm.texi: Regenerate.
>         * lra-constraints.cc (valid_address_p): Call target hook
>         targetm.addr_space.legitimate_address_p with an extra parameter
>         ERROR_MARK as its prototype changes.
>         * recog.cc (memory_address_addr_space_p): Likewise.
>         * reload.cc (strict_memory_address_addr_space_p): Likewise.
>         * target.def (legitimate_address_p, addr_space.legitimate_address_p):
>         Extend with one more argument of type code_helper, update the
>         documentation accordingly.
>         * targhooks.cc (default_legitimate_address_p): Adjust for the
>         new code_helper argument.
>         (default_addr_space_legitimate_address_p): Likewise.
>         * targhooks.h (default_legitimate_address_p): Likewise.
>         (default_addr_space_legitimate_address_p): Likewise.
>         * config/aarch64/aarch64.cc (aarch64_legitimate_address_hook_p): Adjust
>         with extra unnamed code_helper argument with default ERROR_MARK.
>         * config/alpha/alpha.cc (alpha_legitimate_address_p): Likewise.
>         * config/arc/arc.cc (arc_legitimate_address_p): Likewise.
>         * config/arm/arm-protos.h (arm_legitimate_address_p): Likewise.
>         (tree.h): New include for tree_code ERROR_MARK.
>         * config/arm/arm.cc (arm_legitimate_address_p): Adjust with extra
>         unnamed code_helper argument with default ERROR_MARK.
>         * config/avr/avr.cc (avr_addr_space_legitimate_address_p): Likewise.
>         * config/bfin/bfin.cc (bfin_legitimate_address_p): Likewise.
>         * config/bpf/bpf.cc (bpf_legitimate_address_p): Likewise.
>         * config/c6x/c6x.cc (c6x_legitimate_address_p): Likewise.
>         * config/cris/cris-protos.h (cris_legitimate_address_p): Likewise.
>         (tree.h): New include for tree_code ERROR_MARK.
>         * config/cris/cris.cc (cris_legitimate_address_p): Adjust with extra
>         unnamed code_helper argument with default ERROR_MARK.
>         * config/csky/csky.cc (csky_legitimate_address_p): Likewise.
>         * config/epiphany/epiphany.cc (epiphany_legitimate_address_p):
>         Likewise.
>         * config/frv/frv.cc (frv_legitimate_address_p): Likewise.
>         * config/ft32/ft32.cc (ft32_addr_space_legitimate_address_p): Likewise.
>         * config/gcn/gcn.cc (gcn_addr_space_legitimate_address_p): Likewise.
>         * config/h8300/h8300.cc (h8300_legitimate_address_p): Likewise.
>         * config/i386/i386.cc (ix86_legitimate_address_p): Likewise.
>         * config/ia64/ia64.cc (ia64_legitimate_address_p): Likewise.
>         * config/iq2000/iq2000.cc (iq2000_legitimate_address_p): Likewise.
>         * config/lm32/lm32.cc (lm32_legitimate_address_p): Likewise.
>         * config/loongarch/loongarch.cc (loongarch_legitimate_address_p):
>         Likewise.
>         * config/m32c/m32c.cc (m32c_legitimate_address_p): Likewise.
>         (m32c_addr_space_legitimate_address_p): Likewise.
>         * config/m32r/m32r.cc (m32r_legitimate_address_p): Likewise.
>         * config/m68k/m68k.cc (m68k_legitimate_address_p): Likewise.
>         * config/mcore/mcore.cc (mcore_legitimate_address_p): Likewise.
>         * config/microblaze/microblaze-protos.h (tree.h): New include for
>         tree_code ERROR_MARK.
>         (microblaze_legitimate_address_p): Adjust with extra unnamed
>         code_helper argument with default ERROR_MARK.
>         * config/microblaze/microblaze.cc (microblaze_legitimate_address_p):
>         Likewise.
>         * config/mips/mips.cc (mips_legitimate_address_p): Likewise.
>         * config/mmix/mmix.cc (mmix_legitimate_address_p): Likewise.
>         * config/mn10300/mn10300.cc (mn10300_legitimate_address_p): Likewise.
>         * config/moxie/moxie.cc (moxie_legitimate_address_p): Likewise.
>         * config/msp430/msp430.cc (msp430_legitimate_address_p): Likewise.
>         (msp430_addr_space_legitimate_address_p): Adjust with extra code_helper
>         argument with default ERROR_MARK and adjust the call to function
>         msp430_legitimate_address_p.
>         * config/nds32/nds32.cc (nds32_legitimate_address_p): Adjust with extra
>         unnamed code_helper argument with default ERROR_MARK.
>         * config/nios2/nios2.cc (nios2_legitimate_address_p): Likewise.
>         * config/nvptx/nvptx.cc (nvptx_legitimate_address_p): Likewise.
>         * config/or1k/or1k.cc (or1k_legitimate_address_p): Likewise.
>         * config/pa/pa.cc (pa_legitimate_address_p): Likewise.
>         * config/pdp11/pdp11.cc (pdp11_legitimate_address_p): Likewise.
>         * config/pru/pru.cc (pru_addr_space_legitimate_address_p): Likewise.
>         * config/riscv/riscv.cc (riscv_legitimate_address_p): Likewise.
>         * config/rl78/rl78-protos.h (rl78_as_legitimate_address): Likewise.
>         (tree.h): New include for tree_code ERROR_MARK.
>         * config/rl78/rl78.cc (rl78_as_legitimate_address): Adjust with
>         extra unnamed code_helper argument with default ERROR_MARK.
>         * config/rs6000/rs6000.cc (rs6000_legitimate_address_p): Likewise.
>         (rs6000_debug_legitimate_address_p): Adjust with extra code_helper
>         argument and adjust the call to function rs6000_legitimate_address_p.
>         * config/rx/rx.cc (rx_is_legitimate_address): Adjust with extra
>         unnamed code_helper argument with default ERROR_MARK.
>         * config/s390/s390.cc (s390_legitimate_address_p): Likewise.
>         * config/sh/sh.cc (sh_legitimate_address_p): Likewise.
>         * config/sparc/sparc.cc (sparc_legitimate_address_p): Likewise.
>         * config/v850/v850.cc (v850_legitimate_address_p): Likewise.
>         * config/vax/vax.cc (vax_legitimate_address_p): Likewise.
>         * config/visium/visium.cc (visium_legitimate_address_p): Likewise.
>         * config/xtensa/xtensa.cc (xtensa_legitimate_address_p): Likewise.
>         * config/stormy16/stormy16-protos.h (xstormy16_legitimate_address_p):
>         Likewise.
>         (tree.h): New include for tree_code ERROR_MARK.
>         * config/stormy16/stormy16.cc (xstormy16_legitimate_address_p):
>         Adjust with extra unnamed code_helper argument with default
>         ERROR_MARK.
> ---
>  gcc/config/aarch64/aarch64.cc             |  3 ++-
>  gcc/config/alpha/alpha.cc                 |  3 ++-
>  gcc/config/arc/arc.cc                     |  3 ++-
>  gcc/config/arm/arm-protos.h               |  4 +++-
>  gcc/config/arm/arm.cc                     |  2 +-
>  gcc/config/avr/avr.cc                     |  4 ++--
>  gcc/config/bfin/bfin.cc                   |  3 ++-
>  gcc/config/bpf/bpf.cc                     |  3 ++-
>  gcc/config/c6x/c6x.cc                     |  3 ++-
>  gcc/config/cris/cris-protos.h             |  5 ++++-
>  gcc/config/cris/cris.cc                   |  2 +-
>  gcc/config/csky/csky.cc                   |  3 ++-
>  gcc/config/epiphany/epiphany.cc           |  3 ++-
>  gcc/config/frv/frv.cc                     |  5 +++--
>  gcc/config/ft32/ft32.cc                   |  3 ++-
>  gcc/config/gcn/gcn.cc                     |  2 +-
>  gcc/config/h8300/h8300.cc                 |  3 ++-
>  gcc/config/i386/i386.cc                   |  3 ++-
>  gcc/config/ia64/ia64.cc                   |  7 ++++---
>  gcc/config/iq2000/iq2000.cc               |  6 ++++--
>  gcc/config/lm32/lm32.cc                   |  7 ++++---
>  gcc/config/loongarch/loongarch.cc         |  3 ++-
>  gcc/config/m32c/m32c.cc                   | 15 +++++++++------
>  gcc/config/m32r/m32r.cc                   |  5 +++--
>  gcc/config/m68k/m68k.cc                   |  5 +++--
>  gcc/config/mcore/mcore.cc                 |  5 +++--
>  gcc/config/microblaze/microblaze-protos.h |  5 ++++-
>  gcc/config/microblaze/microblaze.cc       |  3 ++-
>  gcc/config/mips/mips.cc                   |  3 ++-
>  gcc/config/mmix/mmix.cc                   |  6 ++++--
>  gcc/config/mn10300/mn10300.cc             |  3 ++-
>  gcc/config/moxie/moxie.cc                 |  3 ++-
>  gcc/config/msp430/msp430.cc               |  8 +++++---
>  gcc/config/nds32/nds32.cc                 |  3 ++-
>  gcc/config/nios2/nios2.cc                 |  5 +++--
>  gcc/config/nvptx/nvptx.cc                 |  2 +-
>  gcc/config/or1k/or1k.cc                   |  3 ++-
>  gcc/config/pa/pa.cc                       |  5 +++--
>  gcc/config/pdp11/pdp11.cc                 |  4 ++--
>  gcc/config/pru/pru.cc                     |  3 ++-
>  gcc/config/riscv/riscv.cc                 |  3 ++-
>  gcc/config/rl78/rl78-protos.h             |  6 +++++-
>  gcc/config/rl78/rl78.cc                   |  3 ++-
>  gcc/config/rs6000/rs6000.cc               | 12 +++++++-----
>  gcc/config/rx/rx.cc                       |  3 ++-
>  gcc/config/s390/s390.cc                   |  3 ++-
>  gcc/config/sh/sh.cc                       |  5 +++--
>  gcc/config/sparc/sparc.cc                 |  6 ++++--
>  gcc/config/stormy16/stormy16-protos.h     |  5 +++--
>  gcc/config/stormy16/stormy16.cc           |  4 ++--
>  gcc/config/v850/v850.cc                   |  3 ++-
>  gcc/config/vax/vax.cc                     |  5 +++--
>  gcc/config/visium/visium.cc               |  5 +++--
>  gcc/config/xtensa/xtensa.cc               |  7 ++++---
>  gcc/coretypes.h                           |  1 +
>  gcc/doc/tm.texi                           | 18 +++++++++++++-----
>  gcc/lra-constraints.cc                    |  3 ++-
>  gcc/recog.cc                              |  3 ++-
>  gcc/reload.cc                             |  3 ++-
>  gcc/target.def                            | 18 +++++++++++++-----
>  gcc/targhooks.cc                          |  8 +++++---
>  gcc/targhooks.h                           |  6 +++---
>  62 files changed, 190 insertions(+), 106 deletions(-)
>
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 644ebdebc0e..2dfb811ec4f 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -11182,7 +11182,8 @@ aarch64_classify_symbolic_expression (rtx x)
>  /* Return TRUE if X is a legitimate address for accessing memory in
>     mode MODE.  */
>  static bool
> -aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p)
> +aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p,
> +                                  code_helper = ERROR_MARK)
>  {
>    struct aarch64_address_info addr;
>
> diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
> index 360b50e20d4..0367f117c21 100644
> --- a/gcc/config/alpha/alpha.cc
> +++ b/gcc/config/alpha/alpha.cc
> @@ -844,7 +844,8 @@ alpha_linkage_symbol_p (const char *symname)
>     low-order three bits; this is an "unaligned" access.  */
>
>  static bool
> -alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                           code_helper = ERROR_MARK)
>  {
>    /* If this is an ldq_u type address, discard the outer AND.  */
>    if (mode == DImode
> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
> index fef8a504f77..266ba8b00bb 100644
> --- a/gcc/config/arc/arc.cc
> +++ b/gcc/config/arc/arc.cc
> @@ -6715,7 +6715,8 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
>  }
>
>  static bool
> -arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +arc_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                         code_helper = ERROR_MARK)
>  {
>    if (RTX_OK_FOR_BASE_P (x, strict))
>       return true;
> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> index 7d73c66a15d..2257aa2c1c0 100644
> --- a/gcc/config/arm/arm-protos.h
> +++ b/gcc/config/arm/arm-protos.h
> @@ -23,6 +23,7 @@
>  #define GCC_ARM_PROTOS_H
>
>  #include "sbitmap.h"
> +#include "tree.h" /* For ERROR_MARK.  */
>
>  rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
>
> @@ -83,7 +84,8 @@ extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
>  extern int legitimate_pic_operand_p (rtx);
>  extern rtx legitimize_pic_address (rtx, machine_mode, rtx, rtx, bool);
>  extern rtx legitimize_tls_address (rtx, rtx);
> -extern bool arm_legitimate_address_p (machine_mode, rtx, bool);
> +extern bool arm_legitimate_address_p (machine_mode, rtx, bool,
> +                                     code_helper = ERROR_MARK);
>  extern int arm_legitimate_address_outer_p (machine_mode, rtx, RTX_CODE, int);
>  extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
>  extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> index 38f0839de1c..6e933c80183 100644
> --- a/gcc/config/arm/arm.cc
> +++ b/gcc/config/arm/arm.cc
> @@ -9171,7 +9171,7 @@ thumb_legitimate_offset_p (machine_mode mode, HOST_WIDE_INT val)
>  }
>
>  bool
> -arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>  {
>    if (TARGET_ARM)
>      return arm_legitimate_address_outer_p (mode, x, SET, strict_p);
> diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
> index 0447641a8e9..fa42602f877 100644
> --- a/gcc/config/avr/avr.cc
> +++ b/gcc/config/avr/avr.cc
> @@ -13431,8 +13431,8 @@ avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
>  /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
>
>  static bool
> -avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
> -                                     bool strict, addr_space_t as)
> +avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                                    addr_space_t as, code_helper = ERROR_MARK)
>  {
>    bool ok = false;
>
> diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
> index 4320ec26722..5718babb6b2 100644
> --- a/gcc/config/bfin/bfin.cc
> +++ b/gcc/config/bfin/bfin.cc
> @@ -2718,7 +2718,8 @@ bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
>  */
>
>  static bool
> -bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                          code_helper = ERROR_MARK)
>  {
>    switch (GET_CODE (x)) {
>    case REG:
> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
> index e0324e1e0e0..a16275c2810 100644
> --- a/gcc/config/bpf/bpf.cc
> +++ b/gcc/config/bpf/bpf.cc
> @@ -668,7 +668,8 @@ bpf_address_base_p (rtx x, bool strict)
>  static bool
>  bpf_legitimate_address_p (machine_mode mode,
>                           rtx x,
> -                         bool strict)
> +                         bool strict,
> +                         code_helper = ERROR_MARK)
>  {
>    switch (GET_CODE (x))
>      {
> diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc
> index 0c9cb821f28..72e8b4c5345 100644
> --- a/gcc/config/c6x/c6x.cc
> +++ b/gcc/config/c6x/c6x.cc
> @@ -2444,7 +2444,8 @@ c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
>  }
>
>  static bool
> -c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                         code_helper = ERROR_MARK)
>  {
>    return c6x_legitimate_address_p_1 (mode, x, strict, false);
>  }
> diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
> index 666e04f9eee..58555943986 100644
> --- a/gcc/config/cris/cris-protos.h
> +++ b/gcc/config/cris/cris-protos.h
> @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
>
>  /* Prototypes for the CRIS port.  */
>
> +#include "tree.h" /* For ERROR_MARK.  */
> +
>  extern bool cris_simple_epilogue (void);
>  #ifdef RTX_CODE
>  extern const char *cris_op_str (rtx);
> @@ -34,7 +36,8 @@ extern bool cris_base_or_autoincr_p (const_rtx, bool);
>  extern bool cris_bdap_index_p (const_rtx, bool);
>  extern void cris_reduce_compare (rtx *, rtx *, rtx *);
>  extern bool cris_biap_index_p (const_rtx, bool);
> -extern bool cris_legitimate_address_p (machine_mode, rtx, bool);
> +extern bool cris_legitimate_address_p (machine_mode, rtx, bool,
> +                                      code_helper = ERROR_MARK);
>  extern bool cris_store_multiple_op_p (rtx);
>  extern bool cris_movem_load_rest_p (rtx);
>  extern void cris_asm_output_symbol_ref (FILE *, rtx);
> diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
> index 7fca2af085a..edd2b898a6c 100644
> --- a/gcc/config/cris/cris.cc
> +++ b/gcc/config/cris/cris.cc
> @@ -1537,7 +1537,7 @@ cris_biap_index_p (const_rtx x, bool strict)
>  /* Worker function for TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  bool
> -cris_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +cris_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    const_rtx x1, x2;
>
> diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
> index b4ee3b273a4..731f47cb2c0 100644
> --- a/gcc/config/csky/csky.cc
> +++ b/gcc/config/csky/csky.cc
> @@ -3186,7 +3186,8 @@ csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
>     be recognized.  */
>
>  static bool
> -csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
> +csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p,
> +                          code_helper = ERROR_MARK)
>  {
>    enum rtx_code code = GET_CODE (addr);
>
> diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
> index 60a2845d6d1..a5460dbf97f 100644
> --- a/gcc/config/epiphany/epiphany.cc
> +++ b/gcc/config/epiphany/epiphany.cc
> @@ -2053,7 +2053,8 @@ epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
>       || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
>
>  static bool
> -epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                              code_helper = ERROR_MARK)
>  {
>  #define REG_OK_FOR_BASE_P(X) \
>    (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
> diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc
> index 2dbaa75f3dc..03976ba7b71 100644
> --- a/gcc/config/frv/frv.cc
> +++ b/gcc/config/frv/frv.cc
> @@ -261,7 +261,8 @@ static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
>  /* Forward references */
>
>  static void frv_option_override                        (void);
> -static bool frv_legitimate_address_p           (machine_mode, rtx, bool);
> +static bool frv_legitimate_address_p (machine_mode, rtx, bool,
> +                                     code_helper = ERROR_MARK);
>  static int frv_default_flags_for_cpu           (void);
>  static FRV_INLINE bool frv_small_data_reloc_p  (rtx, int);
>  static void frv_print_operand                  (FILE *, rtx, int);
> @@ -3396,7 +3397,7 @@ frv_legitimate_address_p_1 (machine_mode mode,
>  }
>
>  bool
> -frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>  {
>    return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
>  }
> diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc
> index 806ab769f79..059243d2a3d 100644
> --- a/gcc/config/ft32/ft32.cc
> +++ b/gcc/config/ft32/ft32.cc
> @@ -856,7 +856,8 @@ reg_ok_for_base_p (rtx r, bool strict)
>
>  static bool
>  ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> -                                      addr_space_t as ATTRIBUTE_UNUSED)
> +                                     addr_space_t as ATTRIBUTE_UNUSED,
> +                                     code_helper = ERROR_MARK)
>  {
>    int max_offset = TARGET_FT32B ? 16384 : 128;
>
> diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
> index 02f4dedec42..f6cff659703 100644
> --- a/gcc/config/gcn/gcn.cc
> +++ b/gcc/config/gcn/gcn.cc
> @@ -1654,7 +1654,7 @@ gcn_global_address_p (rtx addr)
>
>  static bool
>  gcn_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> -                                    addr_space_t as)
> +                                    addr_space_t as, code_helper = ERROR_MARK)
>  {
>    /* All vector instructions need to work on addresses in registers.  */
>    if (!TARGET_GCN5_PLUS && (vgpr_vector_mode_p (mode) && !REG_P (x)))
> diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
> index cdf74c1acbd..4bbb1b711e8 100644
> --- a/gcc/config/h8300/h8300.cc
> +++ b/gcc/config/h8300/h8300.cc
> @@ -5312,7 +5312,8 @@ h8300_rtx_ok_for_base_p (rtx x, int strict)
>     CONSTANT_ADDRESS.  */
>
>  static bool
> -h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                           code_helper = ERROR_MARK)
>  {
>    /* The register indirect addresses like @er0 is always valid.  */
>    if (h8300_rtx_ok_for_base_p (x, strict))
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index 0761965344b..7226b3e5fd3 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -11010,7 +11010,8 @@ ix86_validate_address_register (rtx op)
>     be recognized.  */
>
>  static bool
> -ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
> +ix86_legitimate_address_p (machine_mode, rtx addr, bool strict,
> +                          code_helper = ERROR_MARK)
>  {
>    struct ix86_address parts;
>    rtx base, index, disp;
> diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
> index 92f34dd1ee7..c241e1a50fc 100644
> --- a/gcc/config/ia64/ia64.cc
> +++ b/gcc/config/ia64/ia64.cc
> @@ -313,7 +313,8 @@ static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
>  static bool ia64_scalar_mode_supported_p (scalar_mode mode);
>  static bool ia64_vector_mode_supported_p (machine_mode mode);
>  static bool ia64_legitimate_constant_p (machine_mode, rtx);
> -static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
> +static bool ia64_legitimate_address_p (machine_mode, rtx, bool,
> +                                      code_helper = ERROR_MARK);
>  static bool ia64_cannot_force_const_mem (machine_mode, rtx);
>  static const char *ia64_mangle_type (const_tree);
>  static const char *ia64_invalid_conversion (const_tree, const_tree);
> @@ -1024,8 +1025,8 @@ ia64_legitimate_address_disp (const_rtx reg, const_rtx disp, bool strict)
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> -                          rtx x, bool strict)
> +ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> +                          bool strict, code_helper)
>  {
>    if (ia64_legitimate_address_reg (x, strict))
>      return true;
> diff --git a/gcc/config/iq2000/iq2000.cc b/gcc/config/iq2000/iq2000.cc
> index 733fecac2b7..54404e8d05a 100644
> --- a/gcc/config/iq2000/iq2000.cc
> +++ b/gcc/config/iq2000/iq2000.cc
> @@ -170,7 +170,8 @@ static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
>  static unsigned int iq2000_function_arg_boundary (machine_mode,
>                                                   const_tree);
>  static void iq2000_va_start          (tree, rtx);
> -static bool iq2000_legitimate_address_p (machine_mode, rtx, bool);
> +static bool iq2000_legitimate_address_p (machine_mode, rtx, bool,
> +                                        code_helper = ERROR_MARK);
>  static bool iq2000_can_eliminate      (const int, const int);
>  static void iq2000_asm_trampoline_template (FILE *);
>  static void iq2000_trampoline_init    (rtx, tree, rtx);
> @@ -304,7 +305,8 @@ iq2000_reg_mode_ok_for_base_p (rtx reg,
>     function is called during reload.  */
>
>  bool
> -iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict)
> +iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict,
> +                            code_helper)
>  {
>    if (TARGET_DEBUG_A_MODE)
>      {
> diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc
> index 6528358009d..9d65d66719c 100644
> --- a/gcc/config/lm32/lm32.cc
> +++ b/gcc/config/lm32/lm32.cc
> @@ -69,8 +69,8 @@ static void lm32_setup_incoming_varargs (cumulative_args_t cum,
>  static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
>                             int *total, bool speed);
>  static bool lm32_can_eliminate (const int, const int);
> -static bool
> -lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
> +static bool lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                                      code_helper = ERROR_MARK);
>  static HOST_WIDE_INT lm32_compute_frame_size (int size);
>  static void lm32_option_override (void);
>  static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
> @@ -1192,7 +1192,8 @@ lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
> +lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> +                          bool strict, code_helper)
>  {
>     /* (rM) */
>    if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index 5b8b93eb24b..86d58784113 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -2096,7 +2096,8 @@ loongarch_classify_address (struct loongarch_address_info *info, rtx x,
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> +                               code_helper = ERROR_MARK)
>  {
>    struct loongarch_address_info addr;
>
> diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
> index 65971d62990..e18efc3c7f2 100644
> --- a/gcc/config/m32c/m32c.cc
> +++ b/gcc/config/m32c/m32c.cc
> @@ -75,8 +75,11 @@ static int m32c_comp_type_attributes (const_tree, const_tree);
>  static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
>  static struct machine_function *m32c_init_machine_status (void);
>  static void m32c_insert_attributes (tree, tree *);
> -static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
> -static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
> +static bool m32c_legitimate_address_p (machine_mode, rtx, bool,
> +                                      code_helper = ERROR_MARK);
> +static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool,
> +                                                 addr_space_t,
> +                                                 code_helper = ERROR_MARK);
>  static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
>  static bool m32c_pass_by_reference (cumulative_args_t,
>                                     const function_arg_info &);
> @@ -1648,7 +1651,7 @@ m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
>  #undef TARGET_LEGITIMATE_ADDRESS_P
>  #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
>  bool
> -m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    int mode_adjust;
>    if (CONSTANT_P (x))
> @@ -1966,8 +1969,8 @@ m32c_addr_space_address_mode (addr_space_t addrspace)
>  #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
>    m32c_addr_space_legitimate_address_p
>  static bool
> -m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
> -                                     bool strict, addr_space_t as)
> +m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                                     addr_space_t as, code_helper ch)
>  {
>    if (as == ADDR_SPACE_FAR)
>      {
> @@ -2048,7 +2051,7 @@ m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>    else if (as != ADDR_SPACE_GENERIC)
>      gcc_unreachable ();
>
> -  return m32c_legitimate_address_p (mode, x, strict);
> +  return m32c_legitimate_address_p (mode, x, strict, ch);
>  }
>
>  /* Like m32c_legitimate_address, except with named address support.  */
> diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
> index 155a248459b..63a1798da3d 100644
> --- a/gcc/config/m32r/m32r.cc
> +++ b/gcc/config/m32r/m32r.cc
> @@ -66,7 +66,8 @@ static void  m32r_option_override (void);
>  static void  init_reg_tables (void);
>  static void  block_move_call (rtx, rtx, rtx);
>  static int   m32r_is_insn (rtx);
> -static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
> +static bool  m32r_legitimate_address_p (machine_mode, rtx, bool,
> +                                       code_helper = ERROR_MARK);
>  static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
>  static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
>  static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
> @@ -2913,7 +2914,7 @@ m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
>  /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    if (m32r_rtx_ok_for_base_p (x, strict)
>        || m32r_legitimate_offset_addres_p (mode, x, strict)
> diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
> index 03db2b6a936..145a92d8710 100644
> --- a/gcc/config/m68k/m68k.cc
> +++ b/gcc/config/m68k/m68k.cc
> @@ -158,7 +158,8 @@ static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);
>
>  static bool m68k_can_eliminate (const int, const int);
>  static void m68k_conditional_register_usage (void);
> -static bool m68k_legitimate_address_p (machine_mode, rtx, bool);
> +static bool m68k_legitimate_address_p (machine_mode, rtx, bool,
> +                                      code_helper = ERROR_MARK);
>  static void m68k_option_override (void);
>  static void m68k_override_options_after_change (void);
>  static rtx find_addr_reg (rtx);
> @@ -2311,7 +2312,7 @@ m68k_decompose_address (machine_mode mode, rtx x,
>     STRICT_P says whether strict checking is needed.  */
>
>  bool
> -m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>  {
>    struct m68k_address address;
>
> diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
> index e933b03cdff..6f1d7af7937 100644
> --- a/gcc/config/mcore/mcore.cc
> +++ b/gcc/config/mcore/mcore.cc
> @@ -144,7 +144,8 @@ static bool       mcore_warn_func_return        (tree);
>  static void       mcore_option_override                (void);
>  static bool       mcore_legitimate_constant_p   (machine_mode, rtx);
>  static bool      mcore_legitimate_address_p    (machine_mode, rtx, bool,
> -                                                addr_space_t);
> +                                                addr_space_t,
> +                                                code_helper = ERROR_MARK);
>  static bool      mcore_hard_regno_mode_ok      (unsigned int, machine_mode);
>  static bool      mcore_modes_tieable_p         (machine_mode, machine_mode);
>
>
> @@ -3249,7 +3250,7 @@ mcore_legitimate_index_p (machine_mode mode, const_rtx op)
>
>  static bool
>  mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> -                           addr_space_t as)
> +                           addr_space_t as, code_helper)
>  {
>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>
> diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
> index 31a6515176b..93fd8d17e3c 100644
> --- a/gcc/config/microblaze/microblaze-protos.h
> +++ b/gcc/config/microblaze/microblaze-protos.h
> @@ -22,6 +22,8 @@
>  #ifndef GCC_MICROBLAZE_PROTOS_H
>  #define GCC_MICROBLAZE_PROTOS_H
>
> +#include "tree.h"  /* For ERROR_MARK.  */
> +
>  #ifdef RTX_CODE
>  extern int pic_address_needs_scratch (rtx);
>  extern bool microblaze_constant_address_p (rtx x);
> @@ -40,7 +42,8 @@ extern int microblaze_can_use_return_insn (void);
>  extern void print_operand (FILE *, rtx, int);
>  extern void print_operand_address (FILE *, rtx);
>  extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
> -extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool);
> +extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool,
> +                                            code_helper = ERROR_MARK);
>  extern int microblaze_is_interrupt_variant (void);
>  extern int microblaze_is_break_handler (void);
>  extern int microblaze_break_function_p (tree func);
> diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
> index cbabf1af712..c9f6c4198cf 100644
> --- a/gcc/config/microblaze/microblaze.cc
> +++ b/gcc/config/microblaze/microblaze.cc
> @@ -919,7 +919,8 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
>     is called during reload.  */
>
>  bool
> -microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                                code_helper)
>  {
>    struct microblaze_address_info addr;
>
> diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
> index 999127a72e7..3497d42cdf3 100644
> --- a/gcc/config/mips/mips.cc
> +++ b/gcc/config/mips/mips.cc
> @@ -2691,7 +2691,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> +                          code_helper = ERROR_MARK)
>  {
>    struct mips_address_info addr;
>
> diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc
> index 1d36306fdb6..34743092749 100644
> --- a/gcc/config/mmix/mmix.cc
> +++ b/gcc/config/mmix/mmix.cc
> @@ -132,7 +132,8 @@ static void mmix_target_asm_function_end_prologue (FILE *);
>  static void mmix_target_asm_function_epilogue (FILE *);
>  static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
>  static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
> -static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
> +static bool mmix_legitimate_address_p (machine_mode, rtx, bool,
> +                                      code_helper = ERROR_MARK);
>  static bool mmix_legitimate_constant_p (machine_mode, rtx);
>  static void mmix_reorg (void);
>  static void mmix_asm_output_mi_thunk
> @@ -1109,7 +1110,8 @@ mmix_constant_address_p (rtx x)
>  bool
>  mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>                            rtx x,
> -                          bool strict_checking)
> +                          bool strict_checking,
> +                          code_helper)
>  {
>  #define MMIX_REG_OK(X)                                                 \
>    ((strict_checking                                                    \
> diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
> index a8b01a543cc..cd1de1b2d83 100644
> --- a/gcc/config/mn10300/mn10300.cc
> +++ b/gcc/config/mn10300/mn10300.cc
> @@ -1932,7 +1932,8 @@ mn10300_legitimate_pic_operand_p (rtx x)
>     function record_unscaled_index_insn_codes.  */
>
>  static bool
> -mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                             code_helper = ERROR_MARK)
>  {
>    rtx base, index;
>
> diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc
> index 2132b6e48a3..209d03077ea 100644
> --- a/gcc/config/moxie/moxie.cc
> +++ b/gcc/config/moxie/moxie.cc
> @@ -577,7 +577,8 @@ moxie_reg_ok_for_base_p (const_rtx reg, bool strict_p)
>  static bool
>  moxie_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>                             rtx x, bool strict_p,
> -                           addr_space_t as)
> +                           addr_space_t as,
> +                           code_helper = ERROR_MARK)
>  {
>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>
> diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
> index 6f9c56187ee..061a9c77961 100644
> --- a/gcc/config/msp430/msp430.cc
> +++ b/gcc/config/msp430/msp430.cc
> @@ -927,7 +927,8 @@ reg_ok_for_addr (rtx r, bool strict)
>  bool
>  msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>                              rtx x ATTRIBUTE_UNUSED,
> -                            bool strict ATTRIBUTE_UNUSED)
> +                            bool strict ATTRIBUTE_UNUSED,
> +                            code_helper = ERROR_MARK)
>  {
>    switch (GET_CODE (x))
>      {
> @@ -980,9 +981,10 @@ bool
>  msp430_addr_space_legitimate_address_p (machine_mode mode,
>                                         rtx x,
>                                         bool strict,
> -                                       addr_space_t as ATTRIBUTE_UNUSED)
> +                                       addr_space_t as ATTRIBUTE_UNUSED,
> +                                       code_helper ch = ERROR_MARK)
>  {
> -  return msp430_legitimate_address_p (mode, x, strict);
> +  return msp430_legitimate_address_p (mode, x, strict, ch);
>  }
>
>  #undef  TARGET_ASM_INTEGER
> diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
> index 91ed91d914f..1f8de2a514a 100644
> --- a/gcc/config/nds32/nds32.cc
> +++ b/gcc/config/nds32/nds32.cc
> @@ -2565,7 +2565,8 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
>  /* Addressing Modes.  */
>
>  static bool
> -nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> +                           code_helper = ERROR_MARK)
>  {
>    if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
>      {
> diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc
> index 936eb34ace4..b435d7475f9 100644
> --- a/gcc/config/nios2/nios2.cc
> +++ b/gcc/config/nios2/nios2.cc
> @@ -2141,8 +2141,9 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
>
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>  static bool
> -nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> -                           rtx operand, bool strict_p)
> +nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx operand,
> +                           bool strict_p,
> +                           code_helper = ERROR_MARK)
>  {
>    switch (GET_CODE (operand))
>      {
> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
> index e3b0304d537..49291d71a74 100644
> --- a/gcc/config/nvptx/nvptx.cc
> +++ b/gcc/config/nvptx/nvptx.cc
> @@ -2202,7 +2202,7 @@ nvptx_gen_shared_bcast (rtx reg, propagate_mask pm, unsigned rep,
>  /* Returns true if X is a valid address for use in a memory reference.  */
>
>  static bool
> -nvptx_legitimate_address_p (machine_mode, rtx x, bool)
> +nvptx_legitimate_address_p (machine_mode, rtx x, bool, code_helper)
>  {
>    enum rtx_code code = GET_CODE (x);
>
> diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc
> index ec30bc8156c..5eeed0e91be 100644
> --- a/gcc/config/or1k/or1k.cc
> +++ b/gcc/config/or1k/or1k.cc
> @@ -575,7 +575,8 @@ or1k_initial_elimination_offset (int from, int to)
>     Returns true if X is a legitimate address RTX on OpenRISC.  */
>
>  static bool
> -or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p)
> +or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p,
> +                          code_helper = ERROR_MARK)
>  {
>    rtx base, addend;
>
> diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
> index 0fa9e5fd632..2e906cff7ff 100644
> --- a/gcc/config/pa/pa.cc
> +++ b/gcc/config/pa/pa.cc
> @@ -196,7 +196,8 @@ static section *pa_function_section (tree, enum node_frequency, bool, bool);
>  static bool pa_cannot_force_const_mem (machine_mode, rtx);
>  static bool pa_legitimate_constant_p (machine_mode, rtx);
>  static unsigned int pa_section_type_flags (tree, const char *, int);
> -static bool pa_legitimate_address_p (machine_mode, rtx, bool);
> +static bool pa_legitimate_address_p (machine_mode, rtx, bool,
> +                                    code_helper = ERROR_MARK);
>  static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
>  static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
>  static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
> @@ -10787,7 +10788,7 @@ pa_section_type_flags (tree decl, const char *name, int reloc)
>     output as REG+SMALLINT.  */
>
>  static bool
> -pa_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    if ((REG_P (x)
>         && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
> diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
> index f6dd841f184..321837935c8 100644
> --- a/gcc/config/pdp11/pdp11.cc
> +++ b/gcc/config/pdp11/pdp11.cc
> @@ -1615,8 +1615,8 @@ pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
>  */
>
>  static bool
> -pdp11_legitimate_address_p (machine_mode mode,
> -                           rtx operand, bool strict)
> +pdp11_legitimate_address_p (machine_mode mode, rtx operand, bool strict,
> +                           code_helper = ERROR_MARK)
>  {
>      rtx xfoob;
>
> diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
> index e855bbb8195..6e8112be64a 100644
> --- a/gcc/config/pru/pru.cc
> +++ b/gcc/config/pru/pru.cc
> @@ -1466,7 +1466,8 @@ int pru_symref2ioregno (rtx op)
>  /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
>  static bool
>  pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
> -                                    bool strict_p, addr_space_t as)
> +                                    bool strict_p, addr_space_t as,
> +                                    code_helper = ERROR_MARK)
>  {
>    if (as == ADDR_SPACE_REGIO)
>      {
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 280aa0b33b9..31e2b9bccc2 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1163,7 +1163,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>
>  static bool
> -riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> +riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> +                           code_helper = ERROR_MARK)
>  {
>    struct riscv_address_info addr;
>
> diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
> index 7d474ffc130..813459ad8b6 100644
> --- a/gcc/config/rl78/rl78-protos.h
> +++ b/gcc/config/rl78/rl78-protos.h
> @@ -18,6 +18,9 @@
>     along with GCC; see the file COPYING3.  If not see
>     <http://www.gnu.org/licenses/>.  */
>
>
> +
> +#include "tree.h"  /* For ERROR_MARK.  */
> +
>  const char *    rl78_addsi3_internal (rtx *, unsigned int);
>  void           rl78_emit_eh_epilogue (rtx);
>  void           rl78_expand_compare (rtx *);
> @@ -33,7 +36,8 @@ int           rl78_far_p (rtx x);
>  bool           rl78_hl_b_c_addr_p (rtx);
>  int            rl78_initial_elimination_offset (int, int);
>  bool           rl78_as_legitimate_address (machine_mode, rtx,
> -                                           bool, addr_space_t);
> +                                           bool, addr_space_t,
> +                                           code_helper = ERROR_MARK);
>  int            rl78_legitimize_reload_address (rtx *, machine_mode, int,int, int);
>  enum reg_class rl78_mode_code_base_reg_class (machine_mode, addr_space_t, int, int);
>  bool           rl78_peep_movhi_p (rtx *);
> diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
> index 9083096c4ae..0cbd6bf780a 100644
> --- a/gcc/config/rl78/rl78.cc
> +++ b/gcc/config/rl78/rl78.cc
> @@ -1143,7 +1143,8 @@ rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE
>
>  bool
>  rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> -                           bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
> +                           bool strict ATTRIBUTE_UNUSED,
> +                           addr_space_t as ATTRIBUTE_UNUSED, code_helper)
>  {
>    rtx base, index, addend;
>    bool is_far_addr = false;
> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
> index 546c353029b..efc54528b23 100644
> --- a/gcc/config/rs6000/rs6000.cc
> +++ b/gcc/config/rs6000/rs6000.cc
> @@ -1109,7 +1109,8 @@ struct processor_costs ppca2_cost = {
>  static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);
>
>
>
> -static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
> +static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool,
> +                                              code_helper = ERROR_MARK);
>  static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
>  static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
>  static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
> @@ -9854,7 +9855,8 @@ use_toc_relative_ref (rtx sym, machine_mode mode)
>     because adjacent memory cells are accessed by adding word-sized offsets
>     during assembly output.  */
>  static bool
> -rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
> +rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
> +                            code_helper = ERROR_MARK)
>  {
>    bool reg_offset_p = reg_offset_addressing_ok_p (mode);
>    bool quad_offset_p = mode_supports_dq_form (mode);
> @@ -9957,10 +9959,10 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
>
>  /* Debug version of rs6000_legitimate_address_p.  */
>  static bool
> -rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
> -                                  bool reg_ok_strict)
> +rs6000_debug_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
> +                                  code_helper ch)
>  {
> -  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
> +  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict, ch);
>    fprintf (stderr,
>            "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
>            "strict = %d, reload = %s, code = %s\n",
> diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
> index 726b00a3193..245c6a4413d 100644
> --- a/gcc/config/rx/rx.cc
> +++ b/gcc/config/rx/rx.cc
> @@ -179,7 +179,8 @@ rx_small_data_operand (rtx op)
>
>  static bool
>  rx_is_legitimate_address (machine_mode mode, rtx x,
> -                         bool strict ATTRIBUTE_UNUSED)
> +                         bool strict ATTRIBUTE_UNUSED,
> +                         code_helper = ERROR_MARK)
>  {
>    if (RTX_OK_FOR_BASE (x, strict))
>      /* Register Indirect.  */
> diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
> index 9284477396d..5b8826162a9 100644
> --- a/gcc/config/s390/s390.cc
> +++ b/gcc/config/s390/s390.cc
> @@ -4914,7 +4914,8 @@ s390_expand_plus_operand (rtx target, rtx src,
>     STRICT specifies whether strict register checking applies.  */
>
>  static bool
> -s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> +s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> +                          code_helper = ERROR_MARK)
>  {
>    struct s390_address ad;
>
> diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
> index 938f7aa6281..294faf7c0c3 100644
> --- a/gcc/config/sh/sh.cc
> +++ b/gcc/config/sh/sh.cc
> @@ -266,7 +266,8 @@ static reg_class_t sh_preferred_reload_class (rtx, reg_class_t);
>  static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t,
>                                          machine_mode,
>                                          struct secondary_reload_info *);
> -static bool sh_legitimate_address_p (machine_mode, rtx, bool);
> +static bool sh_legitimate_address_p (machine_mode, rtx, bool,
> +                                    code_helper = ERROR_MARK);
>  static rtx sh_legitimize_address (rtx, rtx, machine_mode);
>  static rtx sh_delegitimize_address (rtx);
>  static bool sh_cannot_substitute_mem_equiv_p (rtx);
> @@ -9038,7 +9039,7 @@ sh_legitimate_index_p (machine_mode mode, rtx op, bool consider_sh2a,
>           GBR
>           GBR+disp  */
>  static bool
> -sh_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +sh_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    if (REG_P (x) && REGNO (x) == GBR_REG)
>      return true;
> diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
> index 0aade05faf5..82e57952414 100644
> --- a/gcc/config/sparc/sparc.cc
> +++ b/gcc/config/sparc/sparc.cc
> @@ -607,7 +607,8 @@ static void sparc_emit_set_const64 (rtx, rtx);
>  static void sparc_output_addr_vec (rtx);
>  static void sparc_output_addr_diff_vec (rtx);
>  static void sparc_output_deferred_case_vectors (void);
> -static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
> +static bool sparc_legitimate_address_p (machine_mode, rtx, bool,
> +                                       code_helper = ERROR_MARK);
>  static bool sparc_legitimate_constant_p (machine_mode, rtx);
>  static rtx sparc_builtin_saveregs (void);
>  static int epilogue_renumber (rtx *, int);
> @@ -4529,7 +4530,8 @@ sparc_pic_register_p (rtx x)
>     ordinarily.  This changes a bit when generating PIC.  */
>
>  static bool
> -sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> +sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> +                           code_helper)
>  {
>    rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
>
> diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
> index f90d88eba6f..27ae023bcb3 100644
> --- a/gcc/config/stormy16/stormy16-protos.h
> +++ b/gcc/config/stormy16/stormy16-protos.h
> @@ -18,7 +18,7 @@ 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/>.  */
>
> -
> +#include "tree.h"  /* For ERROR_MARK.  */
>
>  extern struct xstormy16_stack_layout xstormy16_compute_stack_layout (void);
>  extern void xstormy16_expand_prologue (void);
> @@ -65,6 +65,7 @@ extern const char * xstormy16_output_shift (machine_mode, enum rtx_code,
>                                             rtx, rtx, rtx);
>  extern bool  xstormy16_below100_symbol (rtx, machine_mode);
>  extern bool  xstormy16_splittable_below100_operand (rtx, machine_mode);
> -extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool);
> +extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool,
> +                                           code_helper = ERROR_MARK);
>  #endif
>
> diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
> index cd453c2a2f7..10887153906 100644
> --- a/gcc/config/stormy16/stormy16.cc
> +++ b/gcc/config/stormy16/stormy16.cc
> @@ -795,8 +795,8 @@ xstormy16_expand_andqi3 (rtx *operands)
>    && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))
>
>  bool
> -xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> -                               rtx x, bool strict)
> +xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> +                               bool strict, code_helper)
>  {
>    if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))
>      return true;
> diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
> index 0fb72716b17..416c2841a5c 100644
> --- a/gcc/config/v850/v850.cc
> +++ b/gcc/config/v850/v850.cc
> @@ -3030,7 +3030,8 @@ v850_rtx_ok_for_base_p (const_rtx x, bool strict_p)
>
>  static bool
>  v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> -                          addr_space_t as ATTRIBUTE_UNUSED)
> +                          addr_space_t as ATTRIBUTE_UNUSED,
> +                          code_helper = ERROR_MARK)
>  {
>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>
> diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
> index 82a176d3bfc..df9478d881a 100644
> --- a/gcc/config/vax/vax.cc
> +++ b/gcc/config/vax/vax.cc
> @@ -46,7 +46,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "target-def.h"
>
>  static void vax_option_override (void);
> -static bool vax_legitimate_address_p (machine_mode, rtx, bool);
> +static bool vax_legitimate_address_p (machine_mode, rtx, bool,
> +                                     code_helper = ERROR_MARK);
>  static void vax_file_start (void);
>  static void vax_init_libfuncs (void);
>  static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
> @@ -1902,7 +1903,7 @@ indexable_address_p (rtx xfoo0, rtx xfoo1, machine_mode mode, bool strict)
>     The MODE argument is the machine mode for the MEM expression
>     that wants to use this address.  */
>  bool
> -vax_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +vax_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    rtx xfoo0, xfoo1;
>
> diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
> index 48a61744db6..5fadbc80be0 100644
> --- a/gcc/config/visium/visium.cc
> +++ b/gcc/config/visium/visium.cc
> @@ -194,7 +194,8 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
>
>  static bool visium_legitimate_constant_p (machine_mode, rtx);
>
> -static bool visium_legitimate_address_p (machine_mode, rtx, bool);
> +static bool visium_legitimate_address_p (machine_mode, rtx, bool,
> +                                        code_helper = ERROR_MARK);
>
>  static bool visium_print_operand_punct_valid_p (unsigned char);
>  static void visium_print_operand (FILE *, rtx, int);
> @@ -1818,7 +1819,7 @@ rtx_ok_for_offset_p (machine_mode mode, rtx op)
>     kind of register is required.  */
>
>  static bool
> -visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> +visium_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>  {
>    rtx base;
>    unsigned int regno;
> diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
> index dd35e63c094..897cf7363f4 100644
> --- a/gcc/config/xtensa/xtensa.cc
> +++ b/gcc/config/xtensa/xtensa.cc
> @@ -123,7 +123,8 @@ static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
>  static bool xtensa_return_in_msb (const_tree);
>  static void printx (FILE *, signed int);
>  static rtx xtensa_builtin_saveregs (void);
> -static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
> +static bool xtensa_legitimate_address_p (machine_mode, rtx, bool,
> +                                        code_helper = ERROR_MARK);
>  static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
>                                                         int) ATTRIBUTE_UNUSED;
>  static section *xtensa_select_rtx_section (machine_mode, rtx,
> @@ -2296,9 +2297,9 @@ xtensa_emit_sibcall (int callop, rtx *operands)
>    return result;
>  }
>
> -
>  bool
> -xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> +xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> +                            code_helper)
>  {
>    /* Allow constant pool addresses.  */
>    if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> index ca8837cef67..3e9a2f19e27 100644
> --- a/gcc/coretypes.h
> +++ b/gcc/coretypes.h
> @@ -99,6 +99,7 @@ typedef const union tree_node *const_tree;
>  struct gimple;
>  typedef gimple *gimple_seq;
>  struct gimple_stmt_iterator;
> +class code_helper;
>
>  /* Forward decls for leaf gimple subclasses (for individual gimple codes).
>     Keep this in the same order as the corresponding codes in gimple.def.  */
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index 95ba56e05ae..e4d0cc43f41 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -5853,9 +5853,16 @@ the maximum number that @code{TARGET_LEGITIMATE_ADDRESS_P} would ever
>  accept.
>  @end defmac
>
> -@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict})
> +@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict}, code_helper @var{ch})
>  A function that returns whether @var{x} (an RTX) is a legitimate memory
>  address on the target machine for a memory operand of mode @var{mode}.
> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to
> +determine if it is valid to use @var{x} as a memory operand for RTX insn
> +which is generated for the given code_helper @var{ch}.  For example,
> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying
> +hardware instructions support fewer addressing modes than what are for the
> +normal vector load and store, then with this @var{ch} target can know the
> +actual use context and return more exact result.
>
>  Legitimate addresses are defined in two variants: a strict variant and a
>  non-strict one.  The @var{strict} parameter chooses which variant is
> @@ -10992,11 +10999,12 @@ version of this hook returns true for the modes returned by either the
>  target hooks for the given address space.
>  @end deftypefn
>
> -@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
> +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as}, code_helper @var{ch})
>  Define this to return true if @var{exp} is a valid address for mode
> -@var{mode} in the named address space @var{as}.  The @var{strict}
> -parameter says whether strict addressing is in effect after reload has
> -finished.  This target hook is the same as the
> +@var{mode} in the named address space @var{as} with the use context
> +@var{ch}.  The @var{strict} parameter says whether strict addressing
> +is in effect after reload has finished.  The @var{ch} indicates what
> +context @var{exp} will be used for.  This target hook is the same as the
>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes
>  explicit named address space support.
>  @end deftypefn
> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> index 4dc2d70c402..cb9cbac5bb3 100644
> --- a/gcc/lra-constraints.cc
> +++ b/gcc/lra-constraints.cc
> @@ -336,7 +336,8 @@ valid_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>   win:
>    return 1;
>  #else
> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
> +                                                 ERROR_MARK);
>  #endif
>  }
>
> diff --git a/gcc/recog.cc b/gcc/recog.cc
> index 37432087812..692c258def6 100644
> --- a/gcc/recog.cc
> +++ b/gcc/recog.cc
> @@ -1813,7 +1813,8 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>   win:
>    return true;
>  #else
> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
> +                                                 ERROR_MARK);
>  #endif
>  }
>
> diff --git a/gcc/reload.cc b/gcc/reload.cc
> index d079bc120d5..0be21f7b61e 100644
> --- a/gcc/reload.cc
> +++ b/gcc/reload.cc
> @@ -2172,7 +2172,8 @@ strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>   win:
>    return true;
>  #else
> -  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
> +  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as,
> +                                                 ERROR_MARK);
>  #endif
>  }
>
>
> diff --git a/gcc/target.def b/gcc/target.def
> index 7d684296c17..a500aeb6714 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -2897,6 +2897,13 @@ DEFHOOK
>  (legitimate_address_p,
>   "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
>  address on the target machine for a memory operand of mode @var{mode}.\n\
> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to\n\
> +determine if it is valid to use @var{x} as a memory operand for RTX insn\n\
> +which is generated for the given code_helper @var{ch}.  For example,\n\
> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying\n\
> +hardware instructions support fewer addressing modes than what are for the\n\
> +normal vector load and store, then with this @var{ch} target can know the\n\
> +actual use context and return more exact result.\n\
>  \n\
>  Legitimate addresses are defined in two variants: a strict variant and a\n\
>  non-strict one.  The @var{strict} parameter chooses which variant is\n\
> @@ -2957,7 +2964,7 @@ that case and the non-strict variant otherwise.\n\
>  \n\
>  Using the hook is usually simpler because it limits the number of\n\
>  files that are recompiled when changes are made.",
> - bool, (machine_mode mode, rtx x, bool strict),
> + bool, (machine_mode mode, rtx x, bool strict, code_helper ch),
>   default_legitimate_address_p)
>
>  /* True if the given constant can be put into an object_block.  */
> @@ -3348,12 +3355,13 @@ target hooks for the given address space.",
>  DEFHOOK
>  (legitimate_address_p,
>   "Define this to return true if @var{exp} is a valid address for mode\n\
> -@var{mode} in the named address space @var{as}.  The @var{strict}\n\
> -parameter says whether strict addressing is in effect after reload has\n\
> -finished.  This target hook is the same as the\n\
> +@var{mode} in the named address space @var{as} with the use context\n\
> +@var{ch}.  The @var{strict} parameter says whether strict addressing\n\
> +is in effect after reload has finished.  The @var{ch} indicates what\n\
> +context @var{exp} will be used for.  This target hook is the same as the\n\
>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
>  explicit named address space support.",
> - bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
> + bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as, code_helper ch),
>   default_addr_space_legitimate_address_p)
>
>  /* Return an updated address to convert an invalid pointer to a named
> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> index e190369f87a..4ef53267e50 100644
> --- a/gcc/targhooks.cc
> +++ b/gcc/targhooks.cc
> @@ -99,7 +99,8 @@ along with GCC; see the file COPYING3.  If not see
>  bool
>  default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>                               rtx addr ATTRIBUTE_UNUSED,
> -                             bool strict ATTRIBUTE_UNUSED)
> +                             bool strict ATTRIBUTE_UNUSED,
> +                             code_helper ATTRIBUTE_UNUSED)
>  {
>  #ifdef GO_IF_LEGITIMATE_ADDRESS
>    /* Defer to the old implementation using a goto.  */
> @@ -1680,9 +1681,10 @@ target_default_pointer_address_modes_p (void)
>  bool
>  default_addr_space_legitimate_address_p (machine_mode mode, rtx mem,
>                                          bool strict,
> -                                        addr_space_t as ATTRIBUTE_UNUSED)
> +                                        addr_space_t as ATTRIBUTE_UNUSED,
> +                                        code_helper code)
>  {
> -  return targetm.legitimate_address_p (mode, mem, strict);
> +  return targetm.legitimate_address_p (mode, mem, strict, code);
>  }
>
>  /* Named address space version of LEGITIMIZE_ADDRESS.
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index 1a0db8dddd5..761225512b7 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
>  #ifndef GCC_TARGHOOKS_H
>  #define GCC_TARGHOOKS_H
>
> -extern bool default_legitimate_address_p (machine_mode, rtx, bool);
> +extern bool default_legitimate_address_p (machine_mode, rtx, bool, code_helper);
>
>  extern void default_external_libcall (rtx);
>  extern rtx default_legitimize_address (rtx, rtx, machine_mode);
> @@ -202,8 +202,8 @@ extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
>  extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
>  extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
>                                                    addr_space_t);
> -extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
> -                                                    bool, addr_space_t);
> +extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
> +                                                    addr_space_t, code_helper);
>  extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
>                                                   addr_space_t);
>  extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
> --
> 2.39.3
  
Kewen.Lin June 30, 2023, 9:13 a.m. UTC | #2
Hi Richi,

Thanks for your review!

on 2023/6/30 16:56, Richard Biener wrote:
> On Fri, Jun 30, 2023 at 7:38 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
>>
>> Hi,
>>
>> As PR110248 shows, some middle-end passes like IVOPTs can
>> query the target hook legitimate_address_p with some
>> artificially constructed rtx to determine whether some
>> addressing modes are supported by target for some gimple
>> statement.  But for now the existing legitimate_address_p
>> only checks the given mode, it's unable to distinguish
>> some special cases unfortunately, for example, for LEN_LOAD
>> ifn on Power port, we would expand it with lxvl hardware
>> insn, which only supports one register to hold the address
>> (the other register is holding the length), that is we
>> don't support base (reg) + index (reg) addressing mode for
>> sure.  But hook legitimate_address_p only considers the
>> given mode which would be some vector mode for LEN_LOAD
>> ifn, and we do support base + index addressing mode for
>> normal vector load and store insns, so the hook will return
>> true for the query unexpectedly.
>>
>> This patch is to introduce one extra argument of type
>> code_helper for hook legitimate_address_p, it makes targets
>> able to handle some special case like what's described
>> above.  The subsequent patches will show how to leverage
>> the new code_helper argument.
>>
>> I didn't separate those target specific adjustments to
>> their own patches, since those changes are no function
>> changes.  One typical change is to add one unnamed argument
>> with default ERROR_MARK, some ports need to include tree.h
>> in their {port}-protos.h since the hook is used in some
>> machine description files.  I've cross-built a corresponding
>> cc1 successfully for at least one triple of each affected
>> target so I believe they are safe.  But feel free to correct
>> me if separating is needed for the review of this patch.
>>
>> Besides, it's bootstrapped and regtested on
>> x86_64-redhat-linux and powerpc64{,le}-linux-gnu.
>>
>> Is it ok for trunk?
> 
> Is defaulting the arguments in the targets necessary for
> the middle-end or only for direct uses in the targets?

It's only for the direct uses in target codes, the call
sites in generic code of these hooks would use the given
code_helper type variable or an explicit ERROR_MARK, they
don't require target codes to set that.

> 
> It looks OK in general but please give others some time to
> comment.

OK, thanks again!

BR,
Kewen

> 
> Thanks,
> Richard.
> 
>> BR,
>> Kewen
>> ------
>>         PR tree-optimization/110248
>>
>> gcc/ChangeLog:
>>
>>         * coretypes.h (class code_helper): Add forward declaration.
>>         * doc/tm.texi: Regenerate.
>>         * lra-constraints.cc (valid_address_p): Call target hook
>>         targetm.addr_space.legitimate_address_p with an extra parameter
>>         ERROR_MARK as its prototype changes.
>>         * recog.cc (memory_address_addr_space_p): Likewise.
>>         * reload.cc (strict_memory_address_addr_space_p): Likewise.
>>         * target.def (legitimate_address_p, addr_space.legitimate_address_p):
>>         Extend with one more argument of type code_helper, update the
>>         documentation accordingly.
>>         * targhooks.cc (default_legitimate_address_p): Adjust for the
>>         new code_helper argument.
>>         (default_addr_space_legitimate_address_p): Likewise.
>>         * targhooks.h (default_legitimate_address_p): Likewise.
>>         (default_addr_space_legitimate_address_p): Likewise.
>>         * config/aarch64/aarch64.cc (aarch64_legitimate_address_hook_p): Adjust
>>         with extra unnamed code_helper argument with default ERROR_MARK.
>>         * config/alpha/alpha.cc (alpha_legitimate_address_p): Likewise.
>>         * config/arc/arc.cc (arc_legitimate_address_p): Likewise.
>>         * config/arm/arm-protos.h (arm_legitimate_address_p): Likewise.
>>         (tree.h): New include for tree_code ERROR_MARK.
>>         * config/arm/arm.cc (arm_legitimate_address_p): Adjust with extra
>>         unnamed code_helper argument with default ERROR_MARK.
>>         * config/avr/avr.cc (avr_addr_space_legitimate_address_p): Likewise.
>>         * config/bfin/bfin.cc (bfin_legitimate_address_p): Likewise.
>>         * config/bpf/bpf.cc (bpf_legitimate_address_p): Likewise.
>>         * config/c6x/c6x.cc (c6x_legitimate_address_p): Likewise.
>>         * config/cris/cris-protos.h (cris_legitimate_address_p): Likewise.
>>         (tree.h): New include for tree_code ERROR_MARK.
>>         * config/cris/cris.cc (cris_legitimate_address_p): Adjust with extra
>>         unnamed code_helper argument with default ERROR_MARK.
>>         * config/csky/csky.cc (csky_legitimate_address_p): Likewise.
>>         * config/epiphany/epiphany.cc (epiphany_legitimate_address_p):
>>         Likewise.
>>         * config/frv/frv.cc (frv_legitimate_address_p): Likewise.
>>         * config/ft32/ft32.cc (ft32_addr_space_legitimate_address_p): Likewise.
>>         * config/gcn/gcn.cc (gcn_addr_space_legitimate_address_p): Likewise.
>>         * config/h8300/h8300.cc (h8300_legitimate_address_p): Likewise.
>>         * config/i386/i386.cc (ix86_legitimate_address_p): Likewise.
>>         * config/ia64/ia64.cc (ia64_legitimate_address_p): Likewise.
>>         * config/iq2000/iq2000.cc (iq2000_legitimate_address_p): Likewise.
>>         * config/lm32/lm32.cc (lm32_legitimate_address_p): Likewise.
>>         * config/loongarch/loongarch.cc (loongarch_legitimate_address_p):
>>         Likewise.
>>         * config/m32c/m32c.cc (m32c_legitimate_address_p): Likewise.
>>         (m32c_addr_space_legitimate_address_p): Likewise.
>>         * config/m32r/m32r.cc (m32r_legitimate_address_p): Likewise.
>>         * config/m68k/m68k.cc (m68k_legitimate_address_p): Likewise.
>>         * config/mcore/mcore.cc (mcore_legitimate_address_p): Likewise.
>>         * config/microblaze/microblaze-protos.h (tree.h): New include for
>>         tree_code ERROR_MARK.
>>         (microblaze_legitimate_address_p): Adjust with extra unnamed
>>         code_helper argument with default ERROR_MARK.
>>         * config/microblaze/microblaze.cc (microblaze_legitimate_address_p):
>>         Likewise.
>>         * config/mips/mips.cc (mips_legitimate_address_p): Likewise.
>>         * config/mmix/mmix.cc (mmix_legitimate_address_p): Likewise.
>>         * config/mn10300/mn10300.cc (mn10300_legitimate_address_p): Likewise.
>>         * config/moxie/moxie.cc (moxie_legitimate_address_p): Likewise.
>>         * config/msp430/msp430.cc (msp430_legitimate_address_p): Likewise.
>>         (msp430_addr_space_legitimate_address_p): Adjust with extra code_helper
>>         argument with default ERROR_MARK and adjust the call to function
>>         msp430_legitimate_address_p.
>>         * config/nds32/nds32.cc (nds32_legitimate_address_p): Adjust with extra
>>         unnamed code_helper argument with default ERROR_MARK.
>>         * config/nios2/nios2.cc (nios2_legitimate_address_p): Likewise.
>>         * config/nvptx/nvptx.cc (nvptx_legitimate_address_p): Likewise.
>>         * config/or1k/or1k.cc (or1k_legitimate_address_p): Likewise.
>>         * config/pa/pa.cc (pa_legitimate_address_p): Likewise.
>>         * config/pdp11/pdp11.cc (pdp11_legitimate_address_p): Likewise.
>>         * config/pru/pru.cc (pru_addr_space_legitimate_address_p): Likewise.
>>         * config/riscv/riscv.cc (riscv_legitimate_address_p): Likewise.
>>         * config/rl78/rl78-protos.h (rl78_as_legitimate_address): Likewise.
>>         (tree.h): New include for tree_code ERROR_MARK.
>>         * config/rl78/rl78.cc (rl78_as_legitimate_address): Adjust with
>>         extra unnamed code_helper argument with default ERROR_MARK.
>>         * config/rs6000/rs6000.cc (rs6000_legitimate_address_p): Likewise.
>>         (rs6000_debug_legitimate_address_p): Adjust with extra code_helper
>>         argument and adjust the call to function rs6000_legitimate_address_p.
>>         * config/rx/rx.cc (rx_is_legitimate_address): Adjust with extra
>>         unnamed code_helper argument with default ERROR_MARK.
>>         * config/s390/s390.cc (s390_legitimate_address_p): Likewise.
>>         * config/sh/sh.cc (sh_legitimate_address_p): Likewise.
>>         * config/sparc/sparc.cc (sparc_legitimate_address_p): Likewise.
>>         * config/v850/v850.cc (v850_legitimate_address_p): Likewise.
>>         * config/vax/vax.cc (vax_legitimate_address_p): Likewise.
>>         * config/visium/visium.cc (visium_legitimate_address_p): Likewise.
>>         * config/xtensa/xtensa.cc (xtensa_legitimate_address_p): Likewise.
>>         * config/stormy16/stormy16-protos.h (xstormy16_legitimate_address_p):
>>         Likewise.
>>         (tree.h): New include for tree_code ERROR_MARK.
>>         * config/stormy16/stormy16.cc (xstormy16_legitimate_address_p):
>>         Adjust with extra unnamed code_helper argument with default
>>         ERROR_MARK.
>> ---
>>  gcc/config/aarch64/aarch64.cc             |  3 ++-
>>  gcc/config/alpha/alpha.cc                 |  3 ++-
>>  gcc/config/arc/arc.cc                     |  3 ++-
>>  gcc/config/arm/arm-protos.h               |  4 +++-
>>  gcc/config/arm/arm.cc                     |  2 +-
>>  gcc/config/avr/avr.cc                     |  4 ++--
>>  gcc/config/bfin/bfin.cc                   |  3 ++-
>>  gcc/config/bpf/bpf.cc                     |  3 ++-
>>  gcc/config/c6x/c6x.cc                     |  3 ++-
>>  gcc/config/cris/cris-protos.h             |  5 ++++-
>>  gcc/config/cris/cris.cc                   |  2 +-
>>  gcc/config/csky/csky.cc                   |  3 ++-
>>  gcc/config/epiphany/epiphany.cc           |  3 ++-
>>  gcc/config/frv/frv.cc                     |  5 +++--
>>  gcc/config/ft32/ft32.cc                   |  3 ++-
>>  gcc/config/gcn/gcn.cc                     |  2 +-
>>  gcc/config/h8300/h8300.cc                 |  3 ++-
>>  gcc/config/i386/i386.cc                   |  3 ++-
>>  gcc/config/ia64/ia64.cc                   |  7 ++++---
>>  gcc/config/iq2000/iq2000.cc               |  6 ++++--
>>  gcc/config/lm32/lm32.cc                   |  7 ++++---
>>  gcc/config/loongarch/loongarch.cc         |  3 ++-
>>  gcc/config/m32c/m32c.cc                   | 15 +++++++++------
>>  gcc/config/m32r/m32r.cc                   |  5 +++--
>>  gcc/config/m68k/m68k.cc                   |  5 +++--
>>  gcc/config/mcore/mcore.cc                 |  5 +++--
>>  gcc/config/microblaze/microblaze-protos.h |  5 ++++-
>>  gcc/config/microblaze/microblaze.cc       |  3 ++-
>>  gcc/config/mips/mips.cc                   |  3 ++-
>>  gcc/config/mmix/mmix.cc                   |  6 ++++--
>>  gcc/config/mn10300/mn10300.cc             |  3 ++-
>>  gcc/config/moxie/moxie.cc                 |  3 ++-
>>  gcc/config/msp430/msp430.cc               |  8 +++++---
>>  gcc/config/nds32/nds32.cc                 |  3 ++-
>>  gcc/config/nios2/nios2.cc                 |  5 +++--
>>  gcc/config/nvptx/nvptx.cc                 |  2 +-
>>  gcc/config/or1k/or1k.cc                   |  3 ++-
>>  gcc/config/pa/pa.cc                       |  5 +++--
>>  gcc/config/pdp11/pdp11.cc                 |  4 ++--
>>  gcc/config/pru/pru.cc                     |  3 ++-
>>  gcc/config/riscv/riscv.cc                 |  3 ++-
>>  gcc/config/rl78/rl78-protos.h             |  6 +++++-
>>  gcc/config/rl78/rl78.cc                   |  3 ++-
>>  gcc/config/rs6000/rs6000.cc               | 12 +++++++-----
>>  gcc/config/rx/rx.cc                       |  3 ++-
>>  gcc/config/s390/s390.cc                   |  3 ++-
>>  gcc/config/sh/sh.cc                       |  5 +++--
>>  gcc/config/sparc/sparc.cc                 |  6 ++++--
>>  gcc/config/stormy16/stormy16-protos.h     |  5 +++--
>>  gcc/config/stormy16/stormy16.cc           |  4 ++--
>>  gcc/config/v850/v850.cc                   |  3 ++-
>>  gcc/config/vax/vax.cc                     |  5 +++--
>>  gcc/config/visium/visium.cc               |  5 +++--
>>  gcc/config/xtensa/xtensa.cc               |  7 ++++---
>>  gcc/coretypes.h                           |  1 +
>>  gcc/doc/tm.texi                           | 18 +++++++++++++-----
>>  gcc/lra-constraints.cc                    |  3 ++-
>>  gcc/recog.cc                              |  3 ++-
>>  gcc/reload.cc                             |  3 ++-
>>  gcc/target.def                            | 18 +++++++++++++-----
>>  gcc/targhooks.cc                          |  8 +++++---
>>  gcc/targhooks.h                           |  6 +++---
>>  62 files changed, 190 insertions(+), 106 deletions(-)
>>
>> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
>> index 644ebdebc0e..2dfb811ec4f 100644
>> --- a/gcc/config/aarch64/aarch64.cc
>> +++ b/gcc/config/aarch64/aarch64.cc
>> @@ -11182,7 +11182,8 @@ aarch64_classify_symbolic_expression (rtx x)
>>  /* Return TRUE if X is a legitimate address for accessing memory in
>>     mode MODE.  */
>>  static bool
>> -aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p)
>> +aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p,
>> +                                  code_helper = ERROR_MARK)
>>  {
>>    struct aarch64_address_info addr;
>>
>> diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
>> index 360b50e20d4..0367f117c21 100644
>> --- a/gcc/config/alpha/alpha.cc
>> +++ b/gcc/config/alpha/alpha.cc
>> @@ -844,7 +844,8 @@ alpha_linkage_symbol_p (const char *symname)
>>     low-order three bits; this is an "unaligned" access.  */
>>
>>  static bool
>> -alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    /* If this is an ldq_u type address, discard the outer AND.  */
>>    if (mode == DImode
>> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
>> index fef8a504f77..266ba8b00bb 100644
>> --- a/gcc/config/arc/arc.cc
>> +++ b/gcc/config/arc/arc.cc
>> @@ -6715,7 +6715,8 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
>>  }
>>
>>  static bool
>> -arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +arc_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                         code_helper = ERROR_MARK)
>>  {
>>    if (RTX_OK_FOR_BASE_P (x, strict))
>>       return true;
>> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
>> index 7d73c66a15d..2257aa2c1c0 100644
>> --- a/gcc/config/arm/arm-protos.h
>> +++ b/gcc/config/arm/arm-protos.h
>> @@ -23,6 +23,7 @@
>>  #define GCC_ARM_PROTOS_H
>>
>>  #include "sbitmap.h"
>> +#include "tree.h" /* For ERROR_MARK.  */
>>
>>  rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
>>
>> @@ -83,7 +84,8 @@ extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
>>  extern int legitimate_pic_operand_p (rtx);
>>  extern rtx legitimize_pic_address (rtx, machine_mode, rtx, rtx, bool);
>>  extern rtx legitimize_tls_address (rtx, rtx);
>> -extern bool arm_legitimate_address_p (machine_mode, rtx, bool);
>> +extern bool arm_legitimate_address_p (machine_mode, rtx, bool,
>> +                                     code_helper = ERROR_MARK);
>>  extern int arm_legitimate_address_outer_p (machine_mode, rtx, RTX_CODE, int);
>>  extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
>>  extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
>> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
>> index 38f0839de1c..6e933c80183 100644
>> --- a/gcc/config/arm/arm.cc
>> +++ b/gcc/config/arm/arm.cc
>> @@ -9171,7 +9171,7 @@ thumb_legitimate_offset_p (machine_mode mode, HOST_WIDE_INT val)
>>  }
>>
>>  bool
>> -arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>  {
>>    if (TARGET_ARM)
>>      return arm_legitimate_address_outer_p (mode, x, SET, strict_p);
>> diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
>> index 0447641a8e9..fa42602f877 100644
>> --- a/gcc/config/avr/avr.cc
>> +++ b/gcc/config/avr/avr.cc
>> @@ -13431,8 +13431,8 @@ avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
>>  /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
>>
>>  static bool
>> -avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>> -                                     bool strict, addr_space_t as)
>> +avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                                    addr_space_t as, code_helper = ERROR_MARK)
>>  {
>>    bool ok = false;
>>
>> diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
>> index 4320ec26722..5718babb6b2 100644
>> --- a/gcc/config/bfin/bfin.cc
>> +++ b/gcc/config/bfin/bfin.cc
>> @@ -2718,7 +2718,8 @@ bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
>>  */
>>
>>  static bool
>> -bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    switch (GET_CODE (x)) {
>>    case REG:
>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>> index e0324e1e0e0..a16275c2810 100644
>> --- a/gcc/config/bpf/bpf.cc
>> +++ b/gcc/config/bpf/bpf.cc
>> @@ -668,7 +668,8 @@ bpf_address_base_p (rtx x, bool strict)
>>  static bool
>>  bpf_legitimate_address_p (machine_mode mode,
>>                           rtx x,
>> -                         bool strict)
>> +                         bool strict,
>> +                         code_helper = ERROR_MARK)
>>  {
>>    switch (GET_CODE (x))
>>      {
>> diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc
>> index 0c9cb821f28..72e8b4c5345 100644
>> --- a/gcc/config/c6x/c6x.cc
>> +++ b/gcc/config/c6x/c6x.cc
>> @@ -2444,7 +2444,8 @@ c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
>>  }
>>
>>  static bool
>> -c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                         code_helper = ERROR_MARK)
>>  {
>>    return c6x_legitimate_address_p_1 (mode, x, strict, false);
>>  }
>> diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
>> index 666e04f9eee..58555943986 100644
>> --- a/gcc/config/cris/cris-protos.h
>> +++ b/gcc/config/cris/cris-protos.h
>> @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
>>
>>  /* Prototypes for the CRIS port.  */
>>
>> +#include "tree.h" /* For ERROR_MARK.  */
>> +
>>  extern bool cris_simple_epilogue (void);
>>  #ifdef RTX_CODE
>>  extern const char *cris_op_str (rtx);
>> @@ -34,7 +36,8 @@ extern bool cris_base_or_autoincr_p (const_rtx, bool);
>>  extern bool cris_bdap_index_p (const_rtx, bool);
>>  extern void cris_reduce_compare (rtx *, rtx *, rtx *);
>>  extern bool cris_biap_index_p (const_rtx, bool);
>> -extern bool cris_legitimate_address_p (machine_mode, rtx, bool);
>> +extern bool cris_legitimate_address_p (machine_mode, rtx, bool,
>> +                                      code_helper = ERROR_MARK);
>>  extern bool cris_store_multiple_op_p (rtx);
>>  extern bool cris_movem_load_rest_p (rtx);
>>  extern void cris_asm_output_symbol_ref (FILE *, rtx);
>> diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
>> index 7fca2af085a..edd2b898a6c 100644
>> --- a/gcc/config/cris/cris.cc
>> +++ b/gcc/config/cris/cris.cc
>> @@ -1537,7 +1537,7 @@ cris_biap_index_p (const_rtx x, bool strict)
>>  /* Worker function for TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  bool
>> -cris_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +cris_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    const_rtx x1, x2;
>>
>> diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
>> index b4ee3b273a4..731f47cb2c0 100644
>> --- a/gcc/config/csky/csky.cc
>> +++ b/gcc/config/csky/csky.cc
>> @@ -3186,7 +3186,8 @@ csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
>>     be recognized.  */
>>
>>  static bool
>> -csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
>> +csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    enum rtx_code code = GET_CODE (addr);
>>
>> diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
>> index 60a2845d6d1..a5460dbf97f 100644
>> --- a/gcc/config/epiphany/epiphany.cc
>> +++ b/gcc/config/epiphany/epiphany.cc
>> @@ -2053,7 +2053,8 @@ epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
>>       || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
>>
>>  static bool
>> -epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                              code_helper = ERROR_MARK)
>>  {
>>  #define REG_OK_FOR_BASE_P(X) \
>>    (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
>> diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc
>> index 2dbaa75f3dc..03976ba7b71 100644
>> --- a/gcc/config/frv/frv.cc
>> +++ b/gcc/config/frv/frv.cc
>> @@ -261,7 +261,8 @@ static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
>>  /* Forward references */
>>
>>  static void frv_option_override                        (void);
>> -static bool frv_legitimate_address_p           (machine_mode, rtx, bool);
>> +static bool frv_legitimate_address_p (machine_mode, rtx, bool,
>> +                                     code_helper = ERROR_MARK);
>>  static int frv_default_flags_for_cpu           (void);
>>  static FRV_INLINE bool frv_small_data_reloc_p  (rtx, int);
>>  static void frv_print_operand                  (FILE *, rtx, int);
>> @@ -3396,7 +3397,7 @@ frv_legitimate_address_p_1 (machine_mode mode,
>>  }
>>
>>  bool
>> -frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>  {
>>    return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
>>  }
>> diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc
>> index 806ab769f79..059243d2a3d 100644
>> --- a/gcc/config/ft32/ft32.cc
>> +++ b/gcc/config/ft32/ft32.cc
>> @@ -856,7 +856,8 @@ reg_ok_for_base_p (rtx r, bool strict)
>>
>>  static bool
>>  ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> -                                      addr_space_t as ATTRIBUTE_UNUSED)
>> +                                     addr_space_t as ATTRIBUTE_UNUSED,
>> +                                     code_helper = ERROR_MARK)
>>  {
>>    int max_offset = TARGET_FT32B ? 16384 : 128;
>>
>> diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
>> index 02f4dedec42..f6cff659703 100644
>> --- a/gcc/config/gcn/gcn.cc
>> +++ b/gcc/config/gcn/gcn.cc
>> @@ -1654,7 +1654,7 @@ gcn_global_address_p (rtx addr)
>>
>>  static bool
>>  gcn_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> -                                    addr_space_t as)
>> +                                    addr_space_t as, code_helper = ERROR_MARK)
>>  {
>>    /* All vector instructions need to work on addresses in registers.  */
>>    if (!TARGET_GCN5_PLUS && (vgpr_vector_mode_p (mode) && !REG_P (x)))
>> diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
>> index cdf74c1acbd..4bbb1b711e8 100644
>> --- a/gcc/config/h8300/h8300.cc
>> +++ b/gcc/config/h8300/h8300.cc
>> @@ -5312,7 +5312,8 @@ h8300_rtx_ok_for_base_p (rtx x, int strict)
>>     CONSTANT_ADDRESS.  */
>>
>>  static bool
>> -h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    /* The register indirect addresses like @er0 is always valid.  */
>>    if (h8300_rtx_ok_for_base_p (x, strict))
>> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
>> index 0761965344b..7226b3e5fd3 100644
>> --- a/gcc/config/i386/i386.cc
>> +++ b/gcc/config/i386/i386.cc
>> @@ -11010,7 +11010,8 @@ ix86_validate_address_register (rtx op)
>>     be recognized.  */
>>
>>  static bool
>> -ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
>> +ix86_legitimate_address_p (machine_mode, rtx addr, bool strict,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    struct ix86_address parts;
>>    rtx base, index, disp;
>> diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
>> index 92f34dd1ee7..c241e1a50fc 100644
>> --- a/gcc/config/ia64/ia64.cc
>> +++ b/gcc/config/ia64/ia64.cc
>> @@ -313,7 +313,8 @@ static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
>>  static bool ia64_scalar_mode_supported_p (scalar_mode mode);
>>  static bool ia64_vector_mode_supported_p (machine_mode mode);
>>  static bool ia64_legitimate_constant_p (machine_mode, rtx);
>> -static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool ia64_legitimate_address_p (machine_mode, rtx, bool,
>> +                                      code_helper = ERROR_MARK);
>>  static bool ia64_cannot_force_const_mem (machine_mode, rtx);
>>  static const char *ia64_mangle_type (const_tree);
>>  static const char *ia64_invalid_conversion (const_tree, const_tree);
>> @@ -1024,8 +1025,8 @@ ia64_legitimate_address_disp (const_rtx reg, const_rtx disp, bool strict)
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>> -                          rtx x, bool strict)
>> +ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>> +                          bool strict, code_helper)
>>  {
>>    if (ia64_legitimate_address_reg (x, strict))
>>      return true;
>> diff --git a/gcc/config/iq2000/iq2000.cc b/gcc/config/iq2000/iq2000.cc
>> index 733fecac2b7..54404e8d05a 100644
>> --- a/gcc/config/iq2000/iq2000.cc
>> +++ b/gcc/config/iq2000/iq2000.cc
>> @@ -170,7 +170,8 @@ static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
>>  static unsigned int iq2000_function_arg_boundary (machine_mode,
>>                                                   const_tree);
>>  static void iq2000_va_start          (tree, rtx);
>> -static bool iq2000_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool iq2000_legitimate_address_p (machine_mode, rtx, bool,
>> +                                        code_helper = ERROR_MARK);
>>  static bool iq2000_can_eliminate      (const int, const int);
>>  static void iq2000_asm_trampoline_template (FILE *);
>>  static void iq2000_trampoline_init    (rtx, tree, rtx);
>> @@ -304,7 +305,8 @@ iq2000_reg_mode_ok_for_base_p (rtx reg,
>>     function is called during reload.  */
>>
>>  bool
>> -iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict)
>> +iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict,
>> +                            code_helper)
>>  {
>>    if (TARGET_DEBUG_A_MODE)
>>      {
>> diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc
>> index 6528358009d..9d65d66719c 100644
>> --- a/gcc/config/lm32/lm32.cc
>> +++ b/gcc/config/lm32/lm32.cc
>> @@ -69,8 +69,8 @@ static void lm32_setup_incoming_varargs (cumulative_args_t cum,
>>  static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
>>                             int *total, bool speed);
>>  static bool lm32_can_eliminate (const int, const int);
>> -static bool
>> -lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
>> +static bool lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                                      code_helper = ERROR_MARK);
>>  static HOST_WIDE_INT lm32_compute_frame_size (int size);
>>  static void lm32_option_override (void);
>>  static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
>> @@ -1192,7 +1192,8 @@ lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
>> +lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>> +                          bool strict, code_helper)
>>  {
>>     /* (rM) */
>>    if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
>> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
>> index 5b8b93eb24b..86d58784113 100644
>> --- a/gcc/config/loongarch/loongarch.cc
>> +++ b/gcc/config/loongarch/loongarch.cc
>> @@ -2096,7 +2096,8 @@ loongarch_classify_address (struct loongarch_address_info *info, rtx x,
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>> +                               code_helper = ERROR_MARK)
>>  {
>>    struct loongarch_address_info addr;
>>
>> diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
>> index 65971d62990..e18efc3c7f2 100644
>> --- a/gcc/config/m32c/m32c.cc
>> +++ b/gcc/config/m32c/m32c.cc
>> @@ -75,8 +75,11 @@ static int m32c_comp_type_attributes (const_tree, const_tree);
>>  static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
>>  static struct machine_function *m32c_init_machine_status (void);
>>  static void m32c_insert_attributes (tree, tree *);
>> -static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
>> -static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
>> +static bool m32c_legitimate_address_p (machine_mode, rtx, bool,
>> +                                      code_helper = ERROR_MARK);
>> +static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool,
>> +                                                 addr_space_t,
>> +                                                 code_helper = ERROR_MARK);
>>  static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
>>  static bool m32c_pass_by_reference (cumulative_args_t,
>>                                     const function_arg_info &);
>> @@ -1648,7 +1651,7 @@ m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
>>  #undef TARGET_LEGITIMATE_ADDRESS_P
>>  #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
>>  bool
>> -m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    int mode_adjust;
>>    if (CONSTANT_P (x))
>> @@ -1966,8 +1969,8 @@ m32c_addr_space_address_mode (addr_space_t addrspace)
>>  #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
>>    m32c_addr_space_legitimate_address_p
>>  static bool
>> -m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>> -                                     bool strict, addr_space_t as)
>> +m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                                     addr_space_t as, code_helper ch)
>>  {
>>    if (as == ADDR_SPACE_FAR)
>>      {
>> @@ -2048,7 +2051,7 @@ m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>>    else if (as != ADDR_SPACE_GENERIC)
>>      gcc_unreachable ();
>>
>> -  return m32c_legitimate_address_p (mode, x, strict);
>> +  return m32c_legitimate_address_p (mode, x, strict, ch);
>>  }
>>
>>  /* Like m32c_legitimate_address, except with named address support.  */
>> diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
>> index 155a248459b..63a1798da3d 100644
>> --- a/gcc/config/m32r/m32r.cc
>> +++ b/gcc/config/m32r/m32r.cc
>> @@ -66,7 +66,8 @@ static void  m32r_option_override (void);
>>  static void  init_reg_tables (void);
>>  static void  block_move_call (rtx, rtx, rtx);
>>  static int   m32r_is_insn (rtx);
>> -static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool  m32r_legitimate_address_p (machine_mode, rtx, bool,
>> +                                       code_helper = ERROR_MARK);
>>  static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
>>  static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
>>  static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
>> @@ -2913,7 +2914,7 @@ m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
>>  /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    if (m32r_rtx_ok_for_base_p (x, strict)
>>        || m32r_legitimate_offset_addres_p (mode, x, strict)
>> diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
>> index 03db2b6a936..145a92d8710 100644
>> --- a/gcc/config/m68k/m68k.cc
>> +++ b/gcc/config/m68k/m68k.cc
>> @@ -158,7 +158,8 @@ static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);
>>
>>  static bool m68k_can_eliminate (const int, const int);
>>  static void m68k_conditional_register_usage (void);
>> -static bool m68k_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool m68k_legitimate_address_p (machine_mode, rtx, bool,
>> +                                      code_helper = ERROR_MARK);
>>  static void m68k_option_override (void);
>>  static void m68k_override_options_after_change (void);
>>  static rtx find_addr_reg (rtx);
>> @@ -2311,7 +2312,7 @@ m68k_decompose_address (machine_mode mode, rtx x,
>>     STRICT_P says whether strict checking is needed.  */
>>
>>  bool
>> -m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>  {
>>    struct m68k_address address;
>>
>> diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
>> index e933b03cdff..6f1d7af7937 100644
>> --- a/gcc/config/mcore/mcore.cc
>> +++ b/gcc/config/mcore/mcore.cc
>> @@ -144,7 +144,8 @@ static bool       mcore_warn_func_return        (tree);
>>  static void       mcore_option_override                (void);
>>  static bool       mcore_legitimate_constant_p   (machine_mode, rtx);
>>  static bool      mcore_legitimate_address_p    (machine_mode, rtx, bool,
>> -                                                addr_space_t);
>> +                                                addr_space_t,
>> +                                                code_helper = ERROR_MARK);
>>  static bool      mcore_hard_regno_mode_ok      (unsigned int, machine_mode);
>>  static bool      mcore_modes_tieable_p         (machine_mode, machine_mode);
>>
>>
>> @@ -3249,7 +3250,7 @@ mcore_legitimate_index_p (machine_mode mode, const_rtx op)
>>
>>  static bool
>>  mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>> -                           addr_space_t as)
>> +                           addr_space_t as, code_helper)
>>  {
>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>
>> diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
>> index 31a6515176b..93fd8d17e3c 100644
>> --- a/gcc/config/microblaze/microblaze-protos.h
>> +++ b/gcc/config/microblaze/microblaze-protos.h
>> @@ -22,6 +22,8 @@
>>  #ifndef GCC_MICROBLAZE_PROTOS_H
>>  #define GCC_MICROBLAZE_PROTOS_H
>>
>> +#include "tree.h"  /* For ERROR_MARK.  */
>> +
>>  #ifdef RTX_CODE
>>  extern int pic_address_needs_scratch (rtx);
>>  extern bool microblaze_constant_address_p (rtx x);
>> @@ -40,7 +42,8 @@ extern int microblaze_can_use_return_insn (void);
>>  extern void print_operand (FILE *, rtx, int);
>>  extern void print_operand_address (FILE *, rtx);
>>  extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
>> -extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool);
>> +extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool,
>> +                                            code_helper = ERROR_MARK);
>>  extern int microblaze_is_interrupt_variant (void);
>>  extern int microblaze_is_break_handler (void);
>>  extern int microblaze_break_function_p (tree func);
>> diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
>> index cbabf1af712..c9f6c4198cf 100644
>> --- a/gcc/config/microblaze/microblaze.cc
>> +++ b/gcc/config/microblaze/microblaze.cc
>> @@ -919,7 +919,8 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
>>     is called during reload.  */
>>
>>  bool
>> -microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                                code_helper)
>>  {
>>    struct microblaze_address_info addr;
>>
>> diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
>> index 999127a72e7..3497d42cdf3 100644
>> --- a/gcc/config/mips/mips.cc
>> +++ b/gcc/config/mips/mips.cc
>> @@ -2691,7 +2691,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    struct mips_address_info addr;
>>
>> diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc
>> index 1d36306fdb6..34743092749 100644
>> --- a/gcc/config/mmix/mmix.cc
>> +++ b/gcc/config/mmix/mmix.cc
>> @@ -132,7 +132,8 @@ static void mmix_target_asm_function_end_prologue (FILE *);
>>  static void mmix_target_asm_function_epilogue (FILE *);
>>  static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
>>  static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
>> -static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool mmix_legitimate_address_p (machine_mode, rtx, bool,
>> +                                      code_helper = ERROR_MARK);
>>  static bool mmix_legitimate_constant_p (machine_mode, rtx);
>>  static void mmix_reorg (void);
>>  static void mmix_asm_output_mi_thunk
>> @@ -1109,7 +1110,8 @@ mmix_constant_address_p (rtx x)
>>  bool
>>  mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>                            rtx x,
>> -                          bool strict_checking)
>> +                          bool strict_checking,
>> +                          code_helper)
>>  {
>>  #define MMIX_REG_OK(X)                                                 \
>>    ((strict_checking                                                    \
>> diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
>> index a8b01a543cc..cd1de1b2d83 100644
>> --- a/gcc/config/mn10300/mn10300.cc
>> +++ b/gcc/config/mn10300/mn10300.cc
>> @@ -1932,7 +1932,8 @@ mn10300_legitimate_pic_operand_p (rtx x)
>>     function record_unscaled_index_insn_codes.  */
>>
>>  static bool
>> -mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                             code_helper = ERROR_MARK)
>>  {
>>    rtx base, index;
>>
>> diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc
>> index 2132b6e48a3..209d03077ea 100644
>> --- a/gcc/config/moxie/moxie.cc
>> +++ b/gcc/config/moxie/moxie.cc
>> @@ -577,7 +577,8 @@ moxie_reg_ok_for_base_p (const_rtx reg, bool strict_p)
>>  static bool
>>  moxie_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>                             rtx x, bool strict_p,
>> -                           addr_space_t as)
>> +                           addr_space_t as,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>
>> diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
>> index 6f9c56187ee..061a9c77961 100644
>> --- a/gcc/config/msp430/msp430.cc
>> +++ b/gcc/config/msp430/msp430.cc
>> @@ -927,7 +927,8 @@ reg_ok_for_addr (rtx r, bool strict)
>>  bool
>>  msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>                              rtx x ATTRIBUTE_UNUSED,
>> -                            bool strict ATTRIBUTE_UNUSED)
>> +                            bool strict ATTRIBUTE_UNUSED,
>> +                            code_helper = ERROR_MARK)
>>  {
>>    switch (GET_CODE (x))
>>      {
>> @@ -980,9 +981,10 @@ bool
>>  msp430_addr_space_legitimate_address_p (machine_mode mode,
>>                                         rtx x,
>>                                         bool strict,
>> -                                       addr_space_t as ATTRIBUTE_UNUSED)
>> +                                       addr_space_t as ATTRIBUTE_UNUSED,
>> +                                       code_helper ch = ERROR_MARK)
>>  {
>> -  return msp430_legitimate_address_p (mode, x, strict);
>> +  return msp430_legitimate_address_p (mode, x, strict, ch);
>>  }
>>
>>  #undef  TARGET_ASM_INTEGER
>> diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
>> index 91ed91d914f..1f8de2a514a 100644
>> --- a/gcc/config/nds32/nds32.cc
>> +++ b/gcc/config/nds32/nds32.cc
>> @@ -2565,7 +2565,8 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
>>  /* Addressing Modes.  */
>>
>>  static bool
>> -nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
>>      {
>> diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc
>> index 936eb34ace4..b435d7475f9 100644
>> --- a/gcc/config/nios2/nios2.cc
>> +++ b/gcc/config/nios2/nios2.cc
>> @@ -2141,8 +2141,9 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
>>
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>  static bool
>> -nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>> -                           rtx operand, bool strict_p)
>> +nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx operand,
>> +                           bool strict_p,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    switch (GET_CODE (operand))
>>      {
>> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
>> index e3b0304d537..49291d71a74 100644
>> --- a/gcc/config/nvptx/nvptx.cc
>> +++ b/gcc/config/nvptx/nvptx.cc
>> @@ -2202,7 +2202,7 @@ nvptx_gen_shared_bcast (rtx reg, propagate_mask pm, unsigned rep,
>>  /* Returns true if X is a valid address for use in a memory reference.  */
>>
>>  static bool
>> -nvptx_legitimate_address_p (machine_mode, rtx x, bool)
>> +nvptx_legitimate_address_p (machine_mode, rtx x, bool, code_helper)
>>  {
>>    enum rtx_code code = GET_CODE (x);
>>
>> diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc
>> index ec30bc8156c..5eeed0e91be 100644
>> --- a/gcc/config/or1k/or1k.cc
>> +++ b/gcc/config/or1k/or1k.cc
>> @@ -575,7 +575,8 @@ or1k_initial_elimination_offset (int from, int to)
>>     Returns true if X is a legitimate address RTX on OpenRISC.  */
>>
>>  static bool
>> -or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p)
>> +or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    rtx base, addend;
>>
>> diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
>> index 0fa9e5fd632..2e906cff7ff 100644
>> --- a/gcc/config/pa/pa.cc
>> +++ b/gcc/config/pa/pa.cc
>> @@ -196,7 +196,8 @@ static section *pa_function_section (tree, enum node_frequency, bool, bool);
>>  static bool pa_cannot_force_const_mem (machine_mode, rtx);
>>  static bool pa_legitimate_constant_p (machine_mode, rtx);
>>  static unsigned int pa_section_type_flags (tree, const char *, int);
>> -static bool pa_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool pa_legitimate_address_p (machine_mode, rtx, bool,
>> +                                    code_helper = ERROR_MARK);
>>  static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
>>  static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
>>  static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
>> @@ -10787,7 +10788,7 @@ pa_section_type_flags (tree decl, const char *name, int reloc)
>>     output as REG+SMALLINT.  */
>>
>>  static bool
>> -pa_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    if ((REG_P (x)
>>         && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
>> diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
>> index f6dd841f184..321837935c8 100644
>> --- a/gcc/config/pdp11/pdp11.cc
>> +++ b/gcc/config/pdp11/pdp11.cc
>> @@ -1615,8 +1615,8 @@ pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
>>  */
>>
>>  static bool
>> -pdp11_legitimate_address_p (machine_mode mode,
>> -                           rtx operand, bool strict)
>> +pdp11_legitimate_address_p (machine_mode mode, rtx operand, bool strict,
>> +                           code_helper = ERROR_MARK)
>>  {
>>      rtx xfoob;
>>
>> diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
>> index e855bbb8195..6e8112be64a 100644
>> --- a/gcc/config/pru/pru.cc
>> +++ b/gcc/config/pru/pru.cc
>> @@ -1466,7 +1466,8 @@ int pru_symref2ioregno (rtx op)
>>  /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
>>  static bool
>>  pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
>> -                                    bool strict_p, addr_space_t as)
>> +                                    bool strict_p, addr_space_t as,
>> +                                    code_helper = ERROR_MARK)
>>  {
>>    if (as == ADDR_SPACE_REGIO)
>>      {
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 280aa0b33b9..31e2b9bccc2 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -1163,7 +1163,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>
>>  static bool
>> -riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>> +riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>> +                           code_helper = ERROR_MARK)
>>  {
>>    struct riscv_address_info addr;
>>
>> diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
>> index 7d474ffc130..813459ad8b6 100644
>> --- a/gcc/config/rl78/rl78-protos.h
>> +++ b/gcc/config/rl78/rl78-protos.h
>> @@ -18,6 +18,9 @@
>>     along with GCC; see the file COPYING3.  If not see
>>     <http://www.gnu.org/licenses/>.  */
>>
>>
>> +
>> +#include "tree.h"  /* For ERROR_MARK.  */
>> +
>>  const char *    rl78_addsi3_internal (rtx *, unsigned int);
>>  void           rl78_emit_eh_epilogue (rtx);
>>  void           rl78_expand_compare (rtx *);
>> @@ -33,7 +36,8 @@ int           rl78_far_p (rtx x);
>>  bool           rl78_hl_b_c_addr_p (rtx);
>>  int            rl78_initial_elimination_offset (int, int);
>>  bool           rl78_as_legitimate_address (machine_mode, rtx,
>> -                                           bool, addr_space_t);
>> +                                           bool, addr_space_t,
>> +                                           code_helper = ERROR_MARK);
>>  int            rl78_legitimize_reload_address (rtx *, machine_mode, int,int, int);
>>  enum reg_class rl78_mode_code_base_reg_class (machine_mode, addr_space_t, int, int);
>>  bool           rl78_peep_movhi_p (rtx *);
>> diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
>> index 9083096c4ae..0cbd6bf780a 100644
>> --- a/gcc/config/rl78/rl78.cc
>> +++ b/gcc/config/rl78/rl78.cc
>> @@ -1143,7 +1143,8 @@ rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE
>>
>>  bool
>>  rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>> -                           bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
>> +                           bool strict ATTRIBUTE_UNUSED,
>> +                           addr_space_t as ATTRIBUTE_UNUSED, code_helper)
>>  {
>>    rtx base, index, addend;
>>    bool is_far_addr = false;
>> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
>> index 546c353029b..efc54528b23 100644
>> --- a/gcc/config/rs6000/rs6000.cc
>> +++ b/gcc/config/rs6000/rs6000.cc
>> @@ -1109,7 +1109,8 @@ struct processor_costs ppca2_cost = {
>>  static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);
>>
>>
>>
>> -static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool,
>> +                                              code_helper = ERROR_MARK);
>>  static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
>>  static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
>>  static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
>> @@ -9854,7 +9855,8 @@ use_toc_relative_ref (rtx sym, machine_mode mode)
>>     because adjacent memory cells are accessed by adding word-sized offsets
>>     during assembly output.  */
>>  static bool
>> -rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
>> +rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
>> +                            code_helper = ERROR_MARK)
>>  {
>>    bool reg_offset_p = reg_offset_addressing_ok_p (mode);
>>    bool quad_offset_p = mode_supports_dq_form (mode);
>> @@ -9957,10 +9959,10 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
>>
>>  /* Debug version of rs6000_legitimate_address_p.  */
>>  static bool
>> -rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
>> -                                  bool reg_ok_strict)
>> +rs6000_debug_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
>> +                                  code_helper ch)
>>  {
>> -  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
>> +  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict, ch);
>>    fprintf (stderr,
>>            "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
>>            "strict = %d, reload = %s, code = %s\n",
>> diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
>> index 726b00a3193..245c6a4413d 100644
>> --- a/gcc/config/rx/rx.cc
>> +++ b/gcc/config/rx/rx.cc
>> @@ -179,7 +179,8 @@ rx_small_data_operand (rtx op)
>>
>>  static bool
>>  rx_is_legitimate_address (machine_mode mode, rtx x,
>> -                         bool strict ATTRIBUTE_UNUSED)
>> +                         bool strict ATTRIBUTE_UNUSED,
>> +                         code_helper = ERROR_MARK)
>>  {
>>    if (RTX_OK_FOR_BASE (x, strict))
>>      /* Register Indirect.  */
>> diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
>> index 9284477396d..5b8826162a9 100644
>> --- a/gcc/config/s390/s390.cc
>> +++ b/gcc/config/s390/s390.cc
>> @@ -4914,7 +4914,8 @@ s390_expand_plus_operand (rtx target, rtx src,
>>     STRICT specifies whether strict register checking applies.  */
>>
>>  static bool
>> -s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>> +s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    struct s390_address ad;
>>
>> diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
>> index 938f7aa6281..294faf7c0c3 100644
>> --- a/gcc/config/sh/sh.cc
>> +++ b/gcc/config/sh/sh.cc
>> @@ -266,7 +266,8 @@ static reg_class_t sh_preferred_reload_class (rtx, reg_class_t);
>>  static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t,
>>                                          machine_mode,
>>                                          struct secondary_reload_info *);
>> -static bool sh_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool sh_legitimate_address_p (machine_mode, rtx, bool,
>> +                                    code_helper = ERROR_MARK);
>>  static rtx sh_legitimize_address (rtx, rtx, machine_mode);
>>  static rtx sh_delegitimize_address (rtx);
>>  static bool sh_cannot_substitute_mem_equiv_p (rtx);
>> @@ -9038,7 +9039,7 @@ sh_legitimate_index_p (machine_mode mode, rtx op, bool consider_sh2a,
>>           GBR
>>           GBR+disp  */
>>  static bool
>> -sh_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +sh_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    if (REG_P (x) && REGNO (x) == GBR_REG)
>>      return true;
>> diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
>> index 0aade05faf5..82e57952414 100644
>> --- a/gcc/config/sparc/sparc.cc
>> +++ b/gcc/config/sparc/sparc.cc
>> @@ -607,7 +607,8 @@ static void sparc_emit_set_const64 (rtx, rtx);
>>  static void sparc_output_addr_vec (rtx);
>>  static void sparc_output_addr_diff_vec (rtx);
>>  static void sparc_output_deferred_case_vectors (void);
>> -static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool sparc_legitimate_address_p (machine_mode, rtx, bool,
>> +                                       code_helper = ERROR_MARK);
>>  static bool sparc_legitimate_constant_p (machine_mode, rtx);
>>  static rtx sparc_builtin_saveregs (void);
>>  static int epilogue_renumber (rtx *, int);
>> @@ -4529,7 +4530,8 @@ sparc_pic_register_p (rtx x)
>>     ordinarily.  This changes a bit when generating PIC.  */
>>
>>  static bool
>> -sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>> +sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>> +                           code_helper)
>>  {
>>    rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
>>
>> diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
>> index f90d88eba6f..27ae023bcb3 100644
>> --- a/gcc/config/stormy16/stormy16-protos.h
>> +++ b/gcc/config/stormy16/stormy16-protos.h
>> @@ -18,7 +18,7 @@ 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/>.  */
>>
>> -
>> +#include "tree.h"  /* For ERROR_MARK.  */
>>
>>  extern struct xstormy16_stack_layout xstormy16_compute_stack_layout (void);
>>  extern void xstormy16_expand_prologue (void);
>> @@ -65,6 +65,7 @@ extern const char * xstormy16_output_shift (machine_mode, enum rtx_code,
>>                                             rtx, rtx, rtx);
>>  extern bool  xstormy16_below100_symbol (rtx, machine_mode);
>>  extern bool  xstormy16_splittable_below100_operand (rtx, machine_mode);
>> -extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool);
>> +extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool,
>> +                                           code_helper = ERROR_MARK);
>>  #endif
>>
>> diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
>> index cd453c2a2f7..10887153906 100644
>> --- a/gcc/config/stormy16/stormy16.cc
>> +++ b/gcc/config/stormy16/stormy16.cc
>> @@ -795,8 +795,8 @@ xstormy16_expand_andqi3 (rtx *operands)
>>    && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))
>>
>>  bool
>> -xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>> -                               rtx x, bool strict)
>> +xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>> +                               bool strict, code_helper)
>>  {
>>    if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))
>>      return true;
>> diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
>> index 0fb72716b17..416c2841a5c 100644
>> --- a/gcc/config/v850/v850.cc
>> +++ b/gcc/config/v850/v850.cc
>> @@ -3030,7 +3030,8 @@ v850_rtx_ok_for_base_p (const_rtx x, bool strict_p)
>>
>>  static bool
>>  v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>> -                          addr_space_t as ATTRIBUTE_UNUSED)
>> +                          addr_space_t as ATTRIBUTE_UNUSED,
>> +                          code_helper = ERROR_MARK)
>>  {
>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>
>> diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
>> index 82a176d3bfc..df9478d881a 100644
>> --- a/gcc/config/vax/vax.cc
>> +++ b/gcc/config/vax/vax.cc
>> @@ -46,7 +46,8 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "target-def.h"
>>
>>  static void vax_option_override (void);
>> -static bool vax_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool vax_legitimate_address_p (machine_mode, rtx, bool,
>> +                                     code_helper = ERROR_MARK);
>>  static void vax_file_start (void);
>>  static void vax_init_libfuncs (void);
>>  static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
>> @@ -1902,7 +1903,7 @@ indexable_address_p (rtx xfoo0, rtx xfoo1, machine_mode mode, bool strict)
>>     The MODE argument is the machine mode for the MEM expression
>>     that wants to use this address.  */
>>  bool
>> -vax_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +vax_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    rtx xfoo0, xfoo1;
>>
>> diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
>> index 48a61744db6..5fadbc80be0 100644
>> --- a/gcc/config/visium/visium.cc
>> +++ b/gcc/config/visium/visium.cc
>> @@ -194,7 +194,8 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
>>
>>  static bool visium_legitimate_constant_p (machine_mode, rtx);
>>
>> -static bool visium_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool visium_legitimate_address_p (machine_mode, rtx, bool,
>> +                                        code_helper = ERROR_MARK);
>>
>>  static bool visium_print_operand_punct_valid_p (unsigned char);
>>  static void visium_print_operand (FILE *, rtx, int);
>> @@ -1818,7 +1819,7 @@ rtx_ok_for_offset_p (machine_mode mode, rtx op)
>>     kind of register is required.  */
>>
>>  static bool
>> -visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>> +visium_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>  {
>>    rtx base;
>>    unsigned int regno;
>> diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
>> index dd35e63c094..897cf7363f4 100644
>> --- a/gcc/config/xtensa/xtensa.cc
>> +++ b/gcc/config/xtensa/xtensa.cc
>> @@ -123,7 +123,8 @@ static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
>>  static bool xtensa_return_in_msb (const_tree);
>>  static void printx (FILE *, signed int);
>>  static rtx xtensa_builtin_saveregs (void);
>> -static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
>> +static bool xtensa_legitimate_address_p (machine_mode, rtx, bool,
>> +                                        code_helper = ERROR_MARK);
>>  static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
>>                                                         int) ATTRIBUTE_UNUSED;
>>  static section *xtensa_select_rtx_section (machine_mode, rtx,
>> @@ -2296,9 +2297,9 @@ xtensa_emit_sibcall (int callop, rtx *operands)
>>    return result;
>>  }
>>
>> -
>>  bool
>> -xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>> +xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>> +                            code_helper)
>>  {
>>    /* Allow constant pool addresses.  */
>>    if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
>> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
>> index ca8837cef67..3e9a2f19e27 100644
>> --- a/gcc/coretypes.h
>> +++ b/gcc/coretypes.h
>> @@ -99,6 +99,7 @@ typedef const union tree_node *const_tree;
>>  struct gimple;
>>  typedef gimple *gimple_seq;
>>  struct gimple_stmt_iterator;
>> +class code_helper;
>>
>>  /* Forward decls for leaf gimple subclasses (for individual gimple codes).
>>     Keep this in the same order as the corresponding codes in gimple.def.  */
>> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
>> index 95ba56e05ae..e4d0cc43f41 100644
>> --- a/gcc/doc/tm.texi
>> +++ b/gcc/doc/tm.texi
>> @@ -5853,9 +5853,16 @@ the maximum number that @code{TARGET_LEGITIMATE_ADDRESS_P} would ever
>>  accept.
>>  @end defmac
>>
>> -@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict})
>> +@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict}, code_helper @var{ch})
>>  A function that returns whether @var{x} (an RTX) is a legitimate memory
>>  address on the target machine for a memory operand of mode @var{mode}.
>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to
>> +determine if it is valid to use @var{x} as a memory operand for RTX insn
>> +which is generated for the given code_helper @var{ch}.  For example,
>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying
>> +hardware instructions support fewer addressing modes than what are for the
>> +normal vector load and store, then with this @var{ch} target can know the
>> +actual use context and return more exact result.
>>
>>  Legitimate addresses are defined in two variants: a strict variant and a
>>  non-strict one.  The @var{strict} parameter chooses which variant is
>> @@ -10992,11 +10999,12 @@ version of this hook returns true for the modes returned by either the
>>  target hooks for the given address space.
>>  @end deftypefn
>>
>> -@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
>> +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as}, code_helper @var{ch})
>>  Define this to return true if @var{exp} is a valid address for mode
>> -@var{mode} in the named address space @var{as}.  The @var{strict}
>> -parameter says whether strict addressing is in effect after reload has
>> -finished.  This target hook is the same as the
>> +@var{mode} in the named address space @var{as} with the use context
>> +@var{ch}.  The @var{strict} parameter says whether strict addressing
>> +is in effect after reload has finished.  The @var{ch} indicates what
>> +context @var{exp} will be used for.  This target hook is the same as the
>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes
>>  explicit named address space support.
>>  @end deftypefn
>> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
>> index 4dc2d70c402..cb9cbac5bb3 100644
>> --- a/gcc/lra-constraints.cc
>> +++ b/gcc/lra-constraints.cc
>> @@ -336,7 +336,8 @@ valid_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>   win:
>>    return 1;
>>  #else
>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
>> +                                                 ERROR_MARK);
>>  #endif
>>  }
>>
>> diff --git a/gcc/recog.cc b/gcc/recog.cc
>> index 37432087812..692c258def6 100644
>> --- a/gcc/recog.cc
>> +++ b/gcc/recog.cc
>> @@ -1813,7 +1813,8 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>>   win:
>>    return true;
>>  #else
>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
>> +                                                 ERROR_MARK);
>>  #endif
>>  }
>>
>> diff --git a/gcc/reload.cc b/gcc/reload.cc
>> index d079bc120d5..0be21f7b61e 100644
>> --- a/gcc/reload.cc
>> +++ b/gcc/reload.cc
>> @@ -2172,7 +2172,8 @@ strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>>   win:
>>    return true;
>>  #else
>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as,
>> +                                                 ERROR_MARK);
>>  #endif
>>  }
>>
>>
>> diff --git a/gcc/target.def b/gcc/target.def
>> index 7d684296c17..a500aeb6714 100644
>> --- a/gcc/target.def
>> +++ b/gcc/target.def
>> @@ -2897,6 +2897,13 @@ DEFHOOK
>>  (legitimate_address_p,
>>   "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
>>  address on the target machine for a memory operand of mode @var{mode}.\n\
>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to\n\
>> +determine if it is valid to use @var{x} as a memory operand for RTX insn\n\
>> +which is generated for the given code_helper @var{ch}.  For example,\n\
>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying\n\
>> +hardware instructions support fewer addressing modes than what are for the\n\
>> +normal vector load and store, then with this @var{ch} target can know the\n\
>> +actual use context and return more exact result.\n\
>>  \n\
>>  Legitimate addresses are defined in two variants: a strict variant and a\n\
>>  non-strict one.  The @var{strict} parameter chooses which variant is\n\
>> @@ -2957,7 +2964,7 @@ that case and the non-strict variant otherwise.\n\
>>  \n\
>>  Using the hook is usually simpler because it limits the number of\n\
>>  files that are recompiled when changes are made.",
>> - bool, (machine_mode mode, rtx x, bool strict),
>> + bool, (machine_mode mode, rtx x, bool strict, code_helper ch),
>>   default_legitimate_address_p)
>>
>>  /* True if the given constant can be put into an object_block.  */
>> @@ -3348,12 +3355,13 @@ target hooks for the given address space.",
>>  DEFHOOK
>>  (legitimate_address_p,
>>   "Define this to return true if @var{exp} is a valid address for mode\n\
>> -@var{mode} in the named address space @var{as}.  The @var{strict}\n\
>> -parameter says whether strict addressing is in effect after reload has\n\
>> -finished.  This target hook is the same as the\n\
>> +@var{mode} in the named address space @var{as} with the use context\n\
>> +@var{ch}.  The @var{strict} parameter says whether strict addressing\n\
>> +is in effect after reload has finished.  The @var{ch} indicates what\n\
>> +context @var{exp} will be used for.  This target hook is the same as the\n\
>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
>>  explicit named address space support.",
>> - bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
>> + bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as, code_helper ch),
>>   default_addr_space_legitimate_address_p)
>>
>>  /* Return an updated address to convert an invalid pointer to a named
>> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
>> index e190369f87a..4ef53267e50 100644
>> --- a/gcc/targhooks.cc
>> +++ b/gcc/targhooks.cc
>> @@ -99,7 +99,8 @@ along with GCC; see the file COPYING3.  If not see
>>  bool
>>  default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>                               rtx addr ATTRIBUTE_UNUSED,
>> -                             bool strict ATTRIBUTE_UNUSED)
>> +                             bool strict ATTRIBUTE_UNUSED,
>> +                             code_helper ATTRIBUTE_UNUSED)
>>  {
>>  #ifdef GO_IF_LEGITIMATE_ADDRESS
>>    /* Defer to the old implementation using a goto.  */
>> @@ -1680,9 +1681,10 @@ target_default_pointer_address_modes_p (void)
>>  bool
>>  default_addr_space_legitimate_address_p (machine_mode mode, rtx mem,
>>                                          bool strict,
>> -                                        addr_space_t as ATTRIBUTE_UNUSED)
>> +                                        addr_space_t as ATTRIBUTE_UNUSED,
>> +                                        code_helper code)
>>  {
>> -  return targetm.legitimate_address_p (mode, mem, strict);
>> +  return targetm.legitimate_address_p (mode, mem, strict, code);
>>  }
>>
>>  /* Named address space version of LEGITIMIZE_ADDRESS.
>> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
>> index 1a0db8dddd5..761225512b7 100644
>> --- a/gcc/targhooks.h
>> +++ b/gcc/targhooks.h
>> @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #ifndef GCC_TARGHOOKS_H
>>  #define GCC_TARGHOOKS_H
>>
>> -extern bool default_legitimate_address_p (machine_mode, rtx, bool);
>> +extern bool default_legitimate_address_p (machine_mode, rtx, bool, code_helper);
>>
>>  extern void default_external_libcall (rtx);
>>  extern rtx default_legitimize_address (rtx, rtx, machine_mode);
>> @@ -202,8 +202,8 @@ extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
>>  extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
>>  extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
>>                                                    addr_space_t);
>> -extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
>> -                                                    bool, addr_space_t);
>> +extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
>> +                                                    addr_space_t, code_helper);
>>  extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
>>                                                   addr_space_t);
>>  extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
>> --
>> 2.39.3
  
Kewen.Lin Aug. 7, 2023, 10:15 a.m. UTC | #3
Hi Richi,

on 2023/6/30 17:13, Kewen.Lin via Gcc-patches wrote:
> Hi Richi,
> 
> Thanks for your review!
> 
> on 2023/6/30 16:56, Richard Biener wrote:
>> On Fri, Jun 30, 2023 at 7:38 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
>>>
>>> Hi,
>>>
>>> As PR110248 shows, some middle-end passes like IVOPTs can
>>> query the target hook legitimate_address_p with some
>>> artificially constructed rtx to determine whether some
>>> addressing modes are supported by target for some gimple
>>> statement.  But for now the existing legitimate_address_p
>>> only checks the given mode, it's unable to distinguish
>>> some special cases unfortunately, for example, for LEN_LOAD
>>> ifn on Power port, we would expand it with lxvl hardware
>>> insn, which only supports one register to hold the address
>>> (the other register is holding the length), that is we
>>> don't support base (reg) + index (reg) addressing mode for
>>> sure.  But hook legitimate_address_p only considers the
>>> given mode which would be some vector mode for LEN_LOAD
>>> ifn, and we do support base + index addressing mode for
>>> normal vector load and store insns, so the hook will return
>>> true for the query unexpectedly.
>>>
>>> This patch is to introduce one extra argument of type
>>> code_helper for hook legitimate_address_p, it makes targets
>>> able to handle some special case like what's described
>>> above.  The subsequent patches will show how to leverage
>>> the new code_helper argument.
>>>
>>> I didn't separate those target specific adjustments to
>>> their own patches, since those changes are no function
>>> changes.  One typical change is to add one unnamed argument
>>> with default ERROR_MARK, some ports need to include tree.h
>>> in their {port}-protos.h since the hook is used in some
>>> machine description files.  I've cross-built a corresponding
>>> cc1 successfully for at least one triple of each affected
>>> target so I believe they are safe.  But feel free to correct
>>> me if separating is needed for the review of this patch.
>>>
>>> Besides, it's bootstrapped and regtested on
>>> x86_64-redhat-linux and powerpc64{,le}-linux-gnu.
>>>
>>> Is it ok for trunk?
>>
>> Is defaulting the arguments in the targets necessary for
>> the middle-end or only for direct uses in the targets?
> 
> It's only for the direct uses in target codes, the call
> sites in generic code of these hooks would use the given
> code_helper type variable or an explicit ERROR_MARK, they
> don't require target codes to set that.
> 
>>
>> It looks OK in general but please give others some time to
>> comment.

Some weeks passed and no further comments are received, I guess
this still looks good to you?

BR,
Kewen

> 
> OK, thanks again!
> 
> BR,
> Kewen
> 
>>
>> Thanks,
>> Richard.
>>
>>> BR,
>>> Kewen
>>> ------
>>>         PR tree-optimization/110248
>>>
>>> gcc/ChangeLog:
>>>
>>>         * coretypes.h (class code_helper): Add forward declaration.
>>>         * doc/tm.texi: Regenerate.
>>>         * lra-constraints.cc (valid_address_p): Call target hook
>>>         targetm.addr_space.legitimate_address_p with an extra parameter
>>>         ERROR_MARK as its prototype changes.
>>>         * recog.cc (memory_address_addr_space_p): Likewise.
>>>         * reload.cc (strict_memory_address_addr_space_p): Likewise.
>>>         * target.def (legitimate_address_p, addr_space.legitimate_address_p):
>>>         Extend with one more argument of type code_helper, update the
>>>         documentation accordingly.
>>>         * targhooks.cc (default_legitimate_address_p): Adjust for the
>>>         new code_helper argument.
>>>         (default_addr_space_legitimate_address_p): Likewise.
>>>         * targhooks.h (default_legitimate_address_p): Likewise.
>>>         (default_addr_space_legitimate_address_p): Likewise.
>>>         * config/aarch64/aarch64.cc (aarch64_legitimate_address_hook_p): Adjust
>>>         with extra unnamed code_helper argument with default ERROR_MARK.
>>>         * config/alpha/alpha.cc (alpha_legitimate_address_p): Likewise.
>>>         * config/arc/arc.cc (arc_legitimate_address_p): Likewise.
>>>         * config/arm/arm-protos.h (arm_legitimate_address_p): Likewise.
>>>         (tree.h): New include for tree_code ERROR_MARK.
>>>         * config/arm/arm.cc (arm_legitimate_address_p): Adjust with extra
>>>         unnamed code_helper argument with default ERROR_MARK.
>>>         * config/avr/avr.cc (avr_addr_space_legitimate_address_p): Likewise.
>>>         * config/bfin/bfin.cc (bfin_legitimate_address_p): Likewise.
>>>         * config/bpf/bpf.cc (bpf_legitimate_address_p): Likewise.
>>>         * config/c6x/c6x.cc (c6x_legitimate_address_p): Likewise.
>>>         * config/cris/cris-protos.h (cris_legitimate_address_p): Likewise.
>>>         (tree.h): New include for tree_code ERROR_MARK.
>>>         * config/cris/cris.cc (cris_legitimate_address_p): Adjust with extra
>>>         unnamed code_helper argument with default ERROR_MARK.
>>>         * config/csky/csky.cc (csky_legitimate_address_p): Likewise.
>>>         * config/epiphany/epiphany.cc (epiphany_legitimate_address_p):
>>>         Likewise.
>>>         * config/frv/frv.cc (frv_legitimate_address_p): Likewise.
>>>         * config/ft32/ft32.cc (ft32_addr_space_legitimate_address_p): Likewise.
>>>         * config/gcn/gcn.cc (gcn_addr_space_legitimate_address_p): Likewise.
>>>         * config/h8300/h8300.cc (h8300_legitimate_address_p): Likewise.
>>>         * config/i386/i386.cc (ix86_legitimate_address_p): Likewise.
>>>         * config/ia64/ia64.cc (ia64_legitimate_address_p): Likewise.
>>>         * config/iq2000/iq2000.cc (iq2000_legitimate_address_p): Likewise.
>>>         * config/lm32/lm32.cc (lm32_legitimate_address_p): Likewise.
>>>         * config/loongarch/loongarch.cc (loongarch_legitimate_address_p):
>>>         Likewise.
>>>         * config/m32c/m32c.cc (m32c_legitimate_address_p): Likewise.
>>>         (m32c_addr_space_legitimate_address_p): Likewise.
>>>         * config/m32r/m32r.cc (m32r_legitimate_address_p): Likewise.
>>>         * config/m68k/m68k.cc (m68k_legitimate_address_p): Likewise.
>>>         * config/mcore/mcore.cc (mcore_legitimate_address_p): Likewise.
>>>         * config/microblaze/microblaze-protos.h (tree.h): New include for
>>>         tree_code ERROR_MARK.
>>>         (microblaze_legitimate_address_p): Adjust with extra unnamed
>>>         code_helper argument with default ERROR_MARK.
>>>         * config/microblaze/microblaze.cc (microblaze_legitimate_address_p):
>>>         Likewise.
>>>         * config/mips/mips.cc (mips_legitimate_address_p): Likewise.
>>>         * config/mmix/mmix.cc (mmix_legitimate_address_p): Likewise.
>>>         * config/mn10300/mn10300.cc (mn10300_legitimate_address_p): Likewise.
>>>         * config/moxie/moxie.cc (moxie_legitimate_address_p): Likewise.
>>>         * config/msp430/msp430.cc (msp430_legitimate_address_p): Likewise.
>>>         (msp430_addr_space_legitimate_address_p): Adjust with extra code_helper
>>>         argument with default ERROR_MARK and adjust the call to function
>>>         msp430_legitimate_address_p.
>>>         * config/nds32/nds32.cc (nds32_legitimate_address_p): Adjust with extra
>>>         unnamed code_helper argument with default ERROR_MARK.
>>>         * config/nios2/nios2.cc (nios2_legitimate_address_p): Likewise.
>>>         * config/nvptx/nvptx.cc (nvptx_legitimate_address_p): Likewise.
>>>         * config/or1k/or1k.cc (or1k_legitimate_address_p): Likewise.
>>>         * config/pa/pa.cc (pa_legitimate_address_p): Likewise.
>>>         * config/pdp11/pdp11.cc (pdp11_legitimate_address_p): Likewise.
>>>         * config/pru/pru.cc (pru_addr_space_legitimate_address_p): Likewise.
>>>         * config/riscv/riscv.cc (riscv_legitimate_address_p): Likewise.
>>>         * config/rl78/rl78-protos.h (rl78_as_legitimate_address): Likewise.
>>>         (tree.h): New include for tree_code ERROR_MARK.
>>>         * config/rl78/rl78.cc (rl78_as_legitimate_address): Adjust with
>>>         extra unnamed code_helper argument with default ERROR_MARK.
>>>         * config/rs6000/rs6000.cc (rs6000_legitimate_address_p): Likewise.
>>>         (rs6000_debug_legitimate_address_p): Adjust with extra code_helper
>>>         argument and adjust the call to function rs6000_legitimate_address_p.
>>>         * config/rx/rx.cc (rx_is_legitimate_address): Adjust with extra
>>>         unnamed code_helper argument with default ERROR_MARK.
>>>         * config/s390/s390.cc (s390_legitimate_address_p): Likewise.
>>>         * config/sh/sh.cc (sh_legitimate_address_p): Likewise.
>>>         * config/sparc/sparc.cc (sparc_legitimate_address_p): Likewise.
>>>         * config/v850/v850.cc (v850_legitimate_address_p): Likewise.
>>>         * config/vax/vax.cc (vax_legitimate_address_p): Likewise.
>>>         * config/visium/visium.cc (visium_legitimate_address_p): Likewise.
>>>         * config/xtensa/xtensa.cc (xtensa_legitimate_address_p): Likewise.
>>>         * config/stormy16/stormy16-protos.h (xstormy16_legitimate_address_p):
>>>         Likewise.
>>>         (tree.h): New include for tree_code ERROR_MARK.
>>>         * config/stormy16/stormy16.cc (xstormy16_legitimate_address_p):
>>>         Adjust with extra unnamed code_helper argument with default
>>>         ERROR_MARK.
>>> ---
>>>  gcc/config/aarch64/aarch64.cc             |  3 ++-
>>>  gcc/config/alpha/alpha.cc                 |  3 ++-
>>>  gcc/config/arc/arc.cc                     |  3 ++-
>>>  gcc/config/arm/arm-protos.h               |  4 +++-
>>>  gcc/config/arm/arm.cc                     |  2 +-
>>>  gcc/config/avr/avr.cc                     |  4 ++--
>>>  gcc/config/bfin/bfin.cc                   |  3 ++-
>>>  gcc/config/bpf/bpf.cc                     |  3 ++-
>>>  gcc/config/c6x/c6x.cc                     |  3 ++-
>>>  gcc/config/cris/cris-protos.h             |  5 ++++-
>>>  gcc/config/cris/cris.cc                   |  2 +-
>>>  gcc/config/csky/csky.cc                   |  3 ++-
>>>  gcc/config/epiphany/epiphany.cc           |  3 ++-
>>>  gcc/config/frv/frv.cc                     |  5 +++--
>>>  gcc/config/ft32/ft32.cc                   |  3 ++-
>>>  gcc/config/gcn/gcn.cc                     |  2 +-
>>>  gcc/config/h8300/h8300.cc                 |  3 ++-
>>>  gcc/config/i386/i386.cc                   |  3 ++-
>>>  gcc/config/ia64/ia64.cc                   |  7 ++++---
>>>  gcc/config/iq2000/iq2000.cc               |  6 ++++--
>>>  gcc/config/lm32/lm32.cc                   |  7 ++++---
>>>  gcc/config/loongarch/loongarch.cc         |  3 ++-
>>>  gcc/config/m32c/m32c.cc                   | 15 +++++++++------
>>>  gcc/config/m32r/m32r.cc                   |  5 +++--
>>>  gcc/config/m68k/m68k.cc                   |  5 +++--
>>>  gcc/config/mcore/mcore.cc                 |  5 +++--
>>>  gcc/config/microblaze/microblaze-protos.h |  5 ++++-
>>>  gcc/config/microblaze/microblaze.cc       |  3 ++-
>>>  gcc/config/mips/mips.cc                   |  3 ++-
>>>  gcc/config/mmix/mmix.cc                   |  6 ++++--
>>>  gcc/config/mn10300/mn10300.cc             |  3 ++-
>>>  gcc/config/moxie/moxie.cc                 |  3 ++-
>>>  gcc/config/msp430/msp430.cc               |  8 +++++---
>>>  gcc/config/nds32/nds32.cc                 |  3 ++-
>>>  gcc/config/nios2/nios2.cc                 |  5 +++--
>>>  gcc/config/nvptx/nvptx.cc                 |  2 +-
>>>  gcc/config/or1k/or1k.cc                   |  3 ++-
>>>  gcc/config/pa/pa.cc                       |  5 +++--
>>>  gcc/config/pdp11/pdp11.cc                 |  4 ++--
>>>  gcc/config/pru/pru.cc                     |  3 ++-
>>>  gcc/config/riscv/riscv.cc                 |  3 ++-
>>>  gcc/config/rl78/rl78-protos.h             |  6 +++++-
>>>  gcc/config/rl78/rl78.cc                   |  3 ++-
>>>  gcc/config/rs6000/rs6000.cc               | 12 +++++++-----
>>>  gcc/config/rx/rx.cc                       |  3 ++-
>>>  gcc/config/s390/s390.cc                   |  3 ++-
>>>  gcc/config/sh/sh.cc                       |  5 +++--
>>>  gcc/config/sparc/sparc.cc                 |  6 ++++--
>>>  gcc/config/stormy16/stormy16-protos.h     |  5 +++--
>>>  gcc/config/stormy16/stormy16.cc           |  4 ++--
>>>  gcc/config/v850/v850.cc                   |  3 ++-
>>>  gcc/config/vax/vax.cc                     |  5 +++--
>>>  gcc/config/visium/visium.cc               |  5 +++--
>>>  gcc/config/xtensa/xtensa.cc               |  7 ++++---
>>>  gcc/coretypes.h                           |  1 +
>>>  gcc/doc/tm.texi                           | 18 +++++++++++++-----
>>>  gcc/lra-constraints.cc                    |  3 ++-
>>>  gcc/recog.cc                              |  3 ++-
>>>  gcc/reload.cc                             |  3 ++-
>>>  gcc/target.def                            | 18 +++++++++++++-----
>>>  gcc/targhooks.cc                          |  8 +++++---
>>>  gcc/targhooks.h                           |  6 +++---
>>>  62 files changed, 190 insertions(+), 106 deletions(-)
>>>
>>> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
>>> index 644ebdebc0e..2dfb811ec4f 100644
>>> --- a/gcc/config/aarch64/aarch64.cc
>>> +++ b/gcc/config/aarch64/aarch64.cc
>>> @@ -11182,7 +11182,8 @@ aarch64_classify_symbolic_expression (rtx x)
>>>  /* Return TRUE if X is a legitimate address for accessing memory in
>>>     mode MODE.  */
>>>  static bool
>>> -aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p)
>>> +aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p,
>>> +                                  code_helper = ERROR_MARK)
>>>  {
>>>    struct aarch64_address_info addr;
>>>
>>> diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
>>> index 360b50e20d4..0367f117c21 100644
>>> --- a/gcc/config/alpha/alpha.cc
>>> +++ b/gcc/config/alpha/alpha.cc
>>> @@ -844,7 +844,8 @@ alpha_linkage_symbol_p (const char *symname)
>>>     low-order three bits; this is an "unaligned" access.  */
>>>
>>>  static bool
>>> -alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    /* If this is an ldq_u type address, discard the outer AND.  */
>>>    if (mode == DImode
>>> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
>>> index fef8a504f77..266ba8b00bb 100644
>>> --- a/gcc/config/arc/arc.cc
>>> +++ b/gcc/config/arc/arc.cc
>>> @@ -6715,7 +6715,8 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
>>>  }
>>>
>>>  static bool
>>> -arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +arc_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                         code_helper = ERROR_MARK)
>>>  {
>>>    if (RTX_OK_FOR_BASE_P (x, strict))
>>>       return true;
>>> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
>>> index 7d73c66a15d..2257aa2c1c0 100644
>>> --- a/gcc/config/arm/arm-protos.h
>>> +++ b/gcc/config/arm/arm-protos.h
>>> @@ -23,6 +23,7 @@
>>>  #define GCC_ARM_PROTOS_H
>>>
>>>  #include "sbitmap.h"
>>> +#include "tree.h" /* For ERROR_MARK.  */
>>>
>>>  rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
>>>
>>> @@ -83,7 +84,8 @@ extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
>>>  extern int legitimate_pic_operand_p (rtx);
>>>  extern rtx legitimize_pic_address (rtx, machine_mode, rtx, rtx, bool);
>>>  extern rtx legitimize_tls_address (rtx, rtx);
>>> -extern bool arm_legitimate_address_p (machine_mode, rtx, bool);
>>> +extern bool arm_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                     code_helper = ERROR_MARK);
>>>  extern int arm_legitimate_address_outer_p (machine_mode, rtx, RTX_CODE, int);
>>>  extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
>>>  extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
>>> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
>>> index 38f0839de1c..6e933c80183 100644
>>> --- a/gcc/config/arm/arm.cc
>>> +++ b/gcc/config/arm/arm.cc
>>> @@ -9171,7 +9171,7 @@ thumb_legitimate_offset_p (machine_mode mode, HOST_WIDE_INT val)
>>>  }
>>>
>>>  bool
>>> -arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>>  {
>>>    if (TARGET_ARM)
>>>      return arm_legitimate_address_outer_p (mode, x, SET, strict_p);
>>> diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
>>> index 0447641a8e9..fa42602f877 100644
>>> --- a/gcc/config/avr/avr.cc
>>> +++ b/gcc/config/avr/avr.cc
>>> @@ -13431,8 +13431,8 @@ avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
>>>  /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
>>>
>>>  static bool
>>> -avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>>> -                                     bool strict, addr_space_t as)
>>> +avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                                    addr_space_t as, code_helper = ERROR_MARK)
>>>  {
>>>    bool ok = false;
>>>
>>> diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
>>> index 4320ec26722..5718babb6b2 100644
>>> --- a/gcc/config/bfin/bfin.cc
>>> +++ b/gcc/config/bfin/bfin.cc
>>> @@ -2718,7 +2718,8 @@ bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
>>>  */
>>>
>>>  static bool
>>> -bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    switch (GET_CODE (x)) {
>>>    case REG:
>>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>>> index e0324e1e0e0..a16275c2810 100644
>>> --- a/gcc/config/bpf/bpf.cc
>>> +++ b/gcc/config/bpf/bpf.cc
>>> @@ -668,7 +668,8 @@ bpf_address_base_p (rtx x, bool strict)
>>>  static bool
>>>  bpf_legitimate_address_p (machine_mode mode,
>>>                           rtx x,
>>> -                         bool strict)
>>> +                         bool strict,
>>> +                         code_helper = ERROR_MARK)
>>>  {
>>>    switch (GET_CODE (x))
>>>      {
>>> diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc
>>> index 0c9cb821f28..72e8b4c5345 100644
>>> --- a/gcc/config/c6x/c6x.cc
>>> +++ b/gcc/config/c6x/c6x.cc
>>> @@ -2444,7 +2444,8 @@ c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
>>>  }
>>>
>>>  static bool
>>> -c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                         code_helper = ERROR_MARK)
>>>  {
>>>    return c6x_legitimate_address_p_1 (mode, x, strict, false);
>>>  }
>>> diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
>>> index 666e04f9eee..58555943986 100644
>>> --- a/gcc/config/cris/cris-protos.h
>>> +++ b/gcc/config/cris/cris-protos.h
>>> @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
>>>
>>>  /* Prototypes for the CRIS port.  */
>>>
>>> +#include "tree.h" /* For ERROR_MARK.  */
>>> +
>>>  extern bool cris_simple_epilogue (void);
>>>  #ifdef RTX_CODE
>>>  extern const char *cris_op_str (rtx);
>>> @@ -34,7 +36,8 @@ extern bool cris_base_or_autoincr_p (const_rtx, bool);
>>>  extern bool cris_bdap_index_p (const_rtx, bool);
>>>  extern void cris_reduce_compare (rtx *, rtx *, rtx *);
>>>  extern bool cris_biap_index_p (const_rtx, bool);
>>> -extern bool cris_legitimate_address_p (machine_mode, rtx, bool);
>>> +extern bool cris_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                      code_helper = ERROR_MARK);
>>>  extern bool cris_store_multiple_op_p (rtx);
>>>  extern bool cris_movem_load_rest_p (rtx);
>>>  extern void cris_asm_output_symbol_ref (FILE *, rtx);
>>> diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
>>> index 7fca2af085a..edd2b898a6c 100644
>>> --- a/gcc/config/cris/cris.cc
>>> +++ b/gcc/config/cris/cris.cc
>>> @@ -1537,7 +1537,7 @@ cris_biap_index_p (const_rtx x, bool strict)
>>>  /* Worker function for TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  bool
>>> -cris_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +cris_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    const_rtx x1, x2;
>>>
>>> diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
>>> index b4ee3b273a4..731f47cb2c0 100644
>>> --- a/gcc/config/csky/csky.cc
>>> +++ b/gcc/config/csky/csky.cc
>>> @@ -3186,7 +3186,8 @@ csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
>>>     be recognized.  */
>>>
>>>  static bool
>>> -csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
>>> +csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    enum rtx_code code = GET_CODE (addr);
>>>
>>> diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
>>> index 60a2845d6d1..a5460dbf97f 100644
>>> --- a/gcc/config/epiphany/epiphany.cc
>>> +++ b/gcc/config/epiphany/epiphany.cc
>>> @@ -2053,7 +2053,8 @@ epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
>>>       || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
>>>
>>>  static bool
>>> -epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                              code_helper = ERROR_MARK)
>>>  {
>>>  #define REG_OK_FOR_BASE_P(X) \
>>>    (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
>>> diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc
>>> index 2dbaa75f3dc..03976ba7b71 100644
>>> --- a/gcc/config/frv/frv.cc
>>> +++ b/gcc/config/frv/frv.cc
>>> @@ -261,7 +261,8 @@ static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
>>>  /* Forward references */
>>>
>>>  static void frv_option_override                        (void);
>>> -static bool frv_legitimate_address_p           (machine_mode, rtx, bool);
>>> +static bool frv_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                     code_helper = ERROR_MARK);
>>>  static int frv_default_flags_for_cpu           (void);
>>>  static FRV_INLINE bool frv_small_data_reloc_p  (rtx, int);
>>>  static void frv_print_operand                  (FILE *, rtx, int);
>>> @@ -3396,7 +3397,7 @@ frv_legitimate_address_p_1 (machine_mode mode,
>>>  }
>>>
>>>  bool
>>> -frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>>  {
>>>    return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
>>>  }
>>> diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc
>>> index 806ab769f79..059243d2a3d 100644
>>> --- a/gcc/config/ft32/ft32.cc
>>> +++ b/gcc/config/ft32/ft32.cc
>>> @@ -856,7 +856,8 @@ reg_ok_for_base_p (rtx r, bool strict)
>>>
>>>  static bool
>>>  ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> -                                      addr_space_t as ATTRIBUTE_UNUSED)
>>> +                                     addr_space_t as ATTRIBUTE_UNUSED,
>>> +                                     code_helper = ERROR_MARK)
>>>  {
>>>    int max_offset = TARGET_FT32B ? 16384 : 128;
>>>
>>> diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
>>> index 02f4dedec42..f6cff659703 100644
>>> --- a/gcc/config/gcn/gcn.cc
>>> +++ b/gcc/config/gcn/gcn.cc
>>> @@ -1654,7 +1654,7 @@ gcn_global_address_p (rtx addr)
>>>
>>>  static bool
>>>  gcn_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> -                                    addr_space_t as)
>>> +                                    addr_space_t as, code_helper = ERROR_MARK)
>>>  {
>>>    /* All vector instructions need to work on addresses in registers.  */
>>>    if (!TARGET_GCN5_PLUS && (vgpr_vector_mode_p (mode) && !REG_P (x)))
>>> diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
>>> index cdf74c1acbd..4bbb1b711e8 100644
>>> --- a/gcc/config/h8300/h8300.cc
>>> +++ b/gcc/config/h8300/h8300.cc
>>> @@ -5312,7 +5312,8 @@ h8300_rtx_ok_for_base_p (rtx x, int strict)
>>>     CONSTANT_ADDRESS.  */
>>>
>>>  static bool
>>> -h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    /* The register indirect addresses like @er0 is always valid.  */
>>>    if (h8300_rtx_ok_for_base_p (x, strict))
>>> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
>>> index 0761965344b..7226b3e5fd3 100644
>>> --- a/gcc/config/i386/i386.cc
>>> +++ b/gcc/config/i386/i386.cc
>>> @@ -11010,7 +11010,8 @@ ix86_validate_address_register (rtx op)
>>>     be recognized.  */
>>>
>>>  static bool
>>> -ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
>>> +ix86_legitimate_address_p (machine_mode, rtx addr, bool strict,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    struct ix86_address parts;
>>>    rtx base, index, disp;
>>> diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
>>> index 92f34dd1ee7..c241e1a50fc 100644
>>> --- a/gcc/config/ia64/ia64.cc
>>> +++ b/gcc/config/ia64/ia64.cc
>>> @@ -313,7 +313,8 @@ static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
>>>  static bool ia64_scalar_mode_supported_p (scalar_mode mode);
>>>  static bool ia64_vector_mode_supported_p (machine_mode mode);
>>>  static bool ia64_legitimate_constant_p (machine_mode, rtx);
>>> -static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool ia64_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                      code_helper = ERROR_MARK);
>>>  static bool ia64_cannot_force_const_mem (machine_mode, rtx);
>>>  static const char *ia64_mangle_type (const_tree);
>>>  static const char *ia64_invalid_conversion (const_tree, const_tree);
>>> @@ -1024,8 +1025,8 @@ ia64_legitimate_address_disp (const_rtx reg, const_rtx disp, bool strict)
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>> -                          rtx x, bool strict)
>>> +ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>>> +                          bool strict, code_helper)
>>>  {
>>>    if (ia64_legitimate_address_reg (x, strict))
>>>      return true;
>>> diff --git a/gcc/config/iq2000/iq2000.cc b/gcc/config/iq2000/iq2000.cc
>>> index 733fecac2b7..54404e8d05a 100644
>>> --- a/gcc/config/iq2000/iq2000.cc
>>> +++ b/gcc/config/iq2000/iq2000.cc
>>> @@ -170,7 +170,8 @@ static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
>>>  static unsigned int iq2000_function_arg_boundary (machine_mode,
>>>                                                   const_tree);
>>>  static void iq2000_va_start          (tree, rtx);
>>> -static bool iq2000_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool iq2000_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                        code_helper = ERROR_MARK);
>>>  static bool iq2000_can_eliminate      (const int, const int);
>>>  static void iq2000_asm_trampoline_template (FILE *);
>>>  static void iq2000_trampoline_init    (rtx, tree, rtx);
>>> @@ -304,7 +305,8 @@ iq2000_reg_mode_ok_for_base_p (rtx reg,
>>>     function is called during reload.  */
>>>
>>>  bool
>>> -iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict)
>>> +iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict,
>>> +                            code_helper)
>>>  {
>>>    if (TARGET_DEBUG_A_MODE)
>>>      {
>>> diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc
>>> index 6528358009d..9d65d66719c 100644
>>> --- a/gcc/config/lm32/lm32.cc
>>> +++ b/gcc/config/lm32/lm32.cc
>>> @@ -69,8 +69,8 @@ static void lm32_setup_incoming_varargs (cumulative_args_t cum,
>>>  static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
>>>                             int *total, bool speed);
>>>  static bool lm32_can_eliminate (const int, const int);
>>> -static bool
>>> -lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
>>> +static bool lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                                      code_helper = ERROR_MARK);
>>>  static HOST_WIDE_INT lm32_compute_frame_size (int size);
>>>  static void lm32_option_override (void);
>>>  static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
>>> @@ -1192,7 +1192,8 @@ lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
>>> +lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>>> +                          bool strict, code_helper)
>>>  {
>>>     /* (rM) */
>>>    if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
>>> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
>>> index 5b8b93eb24b..86d58784113 100644
>>> --- a/gcc/config/loongarch/loongarch.cc
>>> +++ b/gcc/config/loongarch/loongarch.cc
>>> @@ -2096,7 +2096,8 @@ loongarch_classify_address (struct loongarch_address_info *info, rtx x,
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>>> +                               code_helper = ERROR_MARK)
>>>  {
>>>    struct loongarch_address_info addr;
>>>
>>> diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
>>> index 65971d62990..e18efc3c7f2 100644
>>> --- a/gcc/config/m32c/m32c.cc
>>> +++ b/gcc/config/m32c/m32c.cc
>>> @@ -75,8 +75,11 @@ static int m32c_comp_type_attributes (const_tree, const_tree);
>>>  static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
>>>  static struct machine_function *m32c_init_machine_status (void);
>>>  static void m32c_insert_attributes (tree, tree *);
>>> -static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
>>> -static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
>>> +static bool m32c_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                      code_helper = ERROR_MARK);
>>> +static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                                 addr_space_t,
>>> +                                                 code_helper = ERROR_MARK);
>>>  static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
>>>  static bool m32c_pass_by_reference (cumulative_args_t,
>>>                                     const function_arg_info &);
>>> @@ -1648,7 +1651,7 @@ m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
>>>  #undef TARGET_LEGITIMATE_ADDRESS_P
>>>  #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
>>>  bool
>>> -m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    int mode_adjust;
>>>    if (CONSTANT_P (x))
>>> @@ -1966,8 +1969,8 @@ m32c_addr_space_address_mode (addr_space_t addrspace)
>>>  #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
>>>    m32c_addr_space_legitimate_address_p
>>>  static bool
>>> -m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>>> -                                     bool strict, addr_space_t as)
>>> +m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                                     addr_space_t as, code_helper ch)
>>>  {
>>>    if (as == ADDR_SPACE_FAR)
>>>      {
>>> @@ -2048,7 +2051,7 @@ m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
>>>    else if (as != ADDR_SPACE_GENERIC)
>>>      gcc_unreachable ();
>>>
>>> -  return m32c_legitimate_address_p (mode, x, strict);
>>> +  return m32c_legitimate_address_p (mode, x, strict, ch);
>>>  }
>>>
>>>  /* Like m32c_legitimate_address, except with named address support.  */
>>> diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
>>> index 155a248459b..63a1798da3d 100644
>>> --- a/gcc/config/m32r/m32r.cc
>>> +++ b/gcc/config/m32r/m32r.cc
>>> @@ -66,7 +66,8 @@ static void  m32r_option_override (void);
>>>  static void  init_reg_tables (void);
>>>  static void  block_move_call (rtx, rtx, rtx);
>>>  static int   m32r_is_insn (rtx);
>>> -static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool  m32r_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                       code_helper = ERROR_MARK);
>>>  static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
>>>  static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
>>>  static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
>>> @@ -2913,7 +2914,7 @@ m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
>>>  /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    if (m32r_rtx_ok_for_base_p (x, strict)
>>>        || m32r_legitimate_offset_addres_p (mode, x, strict)
>>> diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
>>> index 03db2b6a936..145a92d8710 100644
>>> --- a/gcc/config/m68k/m68k.cc
>>> +++ b/gcc/config/m68k/m68k.cc
>>> @@ -158,7 +158,8 @@ static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);
>>>
>>>  static bool m68k_can_eliminate (const int, const int);
>>>  static void m68k_conditional_register_usage (void);
>>> -static bool m68k_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool m68k_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                      code_helper = ERROR_MARK);
>>>  static void m68k_option_override (void);
>>>  static void m68k_override_options_after_change (void);
>>>  static rtx find_addr_reg (rtx);
>>> @@ -2311,7 +2312,7 @@ m68k_decompose_address (machine_mode mode, rtx x,
>>>     STRICT_P says whether strict checking is needed.  */
>>>
>>>  bool
>>> -m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
>>>  {
>>>    struct m68k_address address;
>>>
>>> diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
>>> index e933b03cdff..6f1d7af7937 100644
>>> --- a/gcc/config/mcore/mcore.cc
>>> +++ b/gcc/config/mcore/mcore.cc
>>> @@ -144,7 +144,8 @@ static bool       mcore_warn_func_return        (tree);
>>>  static void       mcore_option_override                (void);
>>>  static bool       mcore_legitimate_constant_p   (machine_mode, rtx);
>>>  static bool      mcore_legitimate_address_p    (machine_mode, rtx, bool,
>>> -                                                addr_space_t);
>>> +                                                addr_space_t,
>>> +                                                code_helper = ERROR_MARK);
>>>  static bool      mcore_hard_regno_mode_ok      (unsigned int, machine_mode);
>>>  static bool      mcore_modes_tieable_p         (machine_mode, machine_mode);
>>>
>>>
>>> @@ -3249,7 +3250,7 @@ mcore_legitimate_index_p (machine_mode mode, const_rtx op)
>>>
>>>  static bool
>>>  mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>>> -                           addr_space_t as)
>>> +                           addr_space_t as, code_helper)
>>>  {
>>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>>
>>> diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
>>> index 31a6515176b..93fd8d17e3c 100644
>>> --- a/gcc/config/microblaze/microblaze-protos.h
>>> +++ b/gcc/config/microblaze/microblaze-protos.h
>>> @@ -22,6 +22,8 @@
>>>  #ifndef GCC_MICROBLAZE_PROTOS_H
>>>  #define GCC_MICROBLAZE_PROTOS_H
>>>
>>> +#include "tree.h"  /* For ERROR_MARK.  */
>>> +
>>>  #ifdef RTX_CODE
>>>  extern int pic_address_needs_scratch (rtx);
>>>  extern bool microblaze_constant_address_p (rtx x);
>>> @@ -40,7 +42,8 @@ extern int microblaze_can_use_return_insn (void);
>>>  extern void print_operand (FILE *, rtx, int);
>>>  extern void print_operand_address (FILE *, rtx);
>>>  extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
>>> -extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool);
>>> +extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                            code_helper = ERROR_MARK);
>>>  extern int microblaze_is_interrupt_variant (void);
>>>  extern int microblaze_is_break_handler (void);
>>>  extern int microblaze_break_function_p (tree func);
>>> diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
>>> index cbabf1af712..c9f6c4198cf 100644
>>> --- a/gcc/config/microblaze/microblaze.cc
>>> +++ b/gcc/config/microblaze/microblaze.cc
>>> @@ -919,7 +919,8 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
>>>     is called during reload.  */
>>>
>>>  bool
>>> -microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                                code_helper)
>>>  {
>>>    struct microblaze_address_info addr;
>>>
>>> diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
>>> index 999127a72e7..3497d42cdf3 100644
>>> --- a/gcc/config/mips/mips.cc
>>> +++ b/gcc/config/mips/mips.cc
>>> @@ -2691,7 +2691,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    struct mips_address_info addr;
>>>
>>> diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc
>>> index 1d36306fdb6..34743092749 100644
>>> --- a/gcc/config/mmix/mmix.cc
>>> +++ b/gcc/config/mmix/mmix.cc
>>> @@ -132,7 +132,8 @@ static void mmix_target_asm_function_end_prologue (FILE *);
>>>  static void mmix_target_asm_function_epilogue (FILE *);
>>>  static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
>>>  static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
>>> -static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool mmix_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                      code_helper = ERROR_MARK);
>>>  static bool mmix_legitimate_constant_p (machine_mode, rtx);
>>>  static void mmix_reorg (void);
>>>  static void mmix_asm_output_mi_thunk
>>> @@ -1109,7 +1110,8 @@ mmix_constant_address_p (rtx x)
>>>  bool
>>>  mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>                            rtx x,
>>> -                          bool strict_checking)
>>> +                          bool strict_checking,
>>> +                          code_helper)
>>>  {
>>>  #define MMIX_REG_OK(X)                                                 \
>>>    ((strict_checking                                                    \
>>> diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
>>> index a8b01a543cc..cd1de1b2d83 100644
>>> --- a/gcc/config/mn10300/mn10300.cc
>>> +++ b/gcc/config/mn10300/mn10300.cc
>>> @@ -1932,7 +1932,8 @@ mn10300_legitimate_pic_operand_p (rtx x)
>>>     function record_unscaled_index_insn_codes.  */
>>>
>>>  static bool
>>> -mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                             code_helper = ERROR_MARK)
>>>  {
>>>    rtx base, index;
>>>
>>> diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc
>>> index 2132b6e48a3..209d03077ea 100644
>>> --- a/gcc/config/moxie/moxie.cc
>>> +++ b/gcc/config/moxie/moxie.cc
>>> @@ -577,7 +577,8 @@ moxie_reg_ok_for_base_p (const_rtx reg, bool strict_p)
>>>  static bool
>>>  moxie_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>                             rtx x, bool strict_p,
>>> -                           addr_space_t as)
>>> +                           addr_space_t as,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>>
>>> diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
>>> index 6f9c56187ee..061a9c77961 100644
>>> --- a/gcc/config/msp430/msp430.cc
>>> +++ b/gcc/config/msp430/msp430.cc
>>> @@ -927,7 +927,8 @@ reg_ok_for_addr (rtx r, bool strict)
>>>  bool
>>>  msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>                              rtx x ATTRIBUTE_UNUSED,
>>> -                            bool strict ATTRIBUTE_UNUSED)
>>> +                            bool strict ATTRIBUTE_UNUSED,
>>> +                            code_helper = ERROR_MARK)
>>>  {
>>>    switch (GET_CODE (x))
>>>      {
>>> @@ -980,9 +981,10 @@ bool
>>>  msp430_addr_space_legitimate_address_p (machine_mode mode,
>>>                                         rtx x,
>>>                                         bool strict,
>>> -                                       addr_space_t as ATTRIBUTE_UNUSED)
>>> +                                       addr_space_t as ATTRIBUTE_UNUSED,
>>> +                                       code_helper ch = ERROR_MARK)
>>>  {
>>> -  return msp430_legitimate_address_p (mode, x, strict);
>>> +  return msp430_legitimate_address_p (mode, x, strict, ch);
>>>  }
>>>
>>>  #undef  TARGET_ASM_INTEGER
>>> diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
>>> index 91ed91d914f..1f8de2a514a 100644
>>> --- a/gcc/config/nds32/nds32.cc
>>> +++ b/gcc/config/nds32/nds32.cc
>>> @@ -2565,7 +2565,8 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
>>>  /* Addressing Modes.  */
>>>
>>>  static bool
>>> -nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
>>>      {
>>> diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc
>>> index 936eb34ace4..b435d7475f9 100644
>>> --- a/gcc/config/nios2/nios2.cc
>>> +++ b/gcc/config/nios2/nios2.cc
>>> @@ -2141,8 +2141,9 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
>>>
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>  static bool
>>> -nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>> -                           rtx operand, bool strict_p)
>>> +nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx operand,
>>> +                           bool strict_p,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    switch (GET_CODE (operand))
>>>      {
>>> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
>>> index e3b0304d537..49291d71a74 100644
>>> --- a/gcc/config/nvptx/nvptx.cc
>>> +++ b/gcc/config/nvptx/nvptx.cc
>>> @@ -2202,7 +2202,7 @@ nvptx_gen_shared_bcast (rtx reg, propagate_mask pm, unsigned rep,
>>>  /* Returns true if X is a valid address for use in a memory reference.  */
>>>
>>>  static bool
>>> -nvptx_legitimate_address_p (machine_mode, rtx x, bool)
>>> +nvptx_legitimate_address_p (machine_mode, rtx x, bool, code_helper)
>>>  {
>>>    enum rtx_code code = GET_CODE (x);
>>>
>>> diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc
>>> index ec30bc8156c..5eeed0e91be 100644
>>> --- a/gcc/config/or1k/or1k.cc
>>> +++ b/gcc/config/or1k/or1k.cc
>>> @@ -575,7 +575,8 @@ or1k_initial_elimination_offset (int from, int to)
>>>     Returns true if X is a legitimate address RTX on OpenRISC.  */
>>>
>>>  static bool
>>> -or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p)
>>> +or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    rtx base, addend;
>>>
>>> diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
>>> index 0fa9e5fd632..2e906cff7ff 100644
>>> --- a/gcc/config/pa/pa.cc
>>> +++ b/gcc/config/pa/pa.cc
>>> @@ -196,7 +196,8 @@ static section *pa_function_section (tree, enum node_frequency, bool, bool);
>>>  static bool pa_cannot_force_const_mem (machine_mode, rtx);
>>>  static bool pa_legitimate_constant_p (machine_mode, rtx);
>>>  static unsigned int pa_section_type_flags (tree, const char *, int);
>>> -static bool pa_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool pa_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                    code_helper = ERROR_MARK);
>>>  static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
>>>  static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
>>>  static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
>>> @@ -10787,7 +10788,7 @@ pa_section_type_flags (tree decl, const char *name, int reloc)
>>>     output as REG+SMALLINT.  */
>>>
>>>  static bool
>>> -pa_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    if ((REG_P (x)
>>>         && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
>>> diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
>>> index f6dd841f184..321837935c8 100644
>>> --- a/gcc/config/pdp11/pdp11.cc
>>> +++ b/gcc/config/pdp11/pdp11.cc
>>> @@ -1615,8 +1615,8 @@ pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
>>>  */
>>>
>>>  static bool
>>> -pdp11_legitimate_address_p (machine_mode mode,
>>> -                           rtx operand, bool strict)
>>> +pdp11_legitimate_address_p (machine_mode mode, rtx operand, bool strict,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>      rtx xfoob;
>>>
>>> diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
>>> index e855bbb8195..6e8112be64a 100644
>>> --- a/gcc/config/pru/pru.cc
>>> +++ b/gcc/config/pru/pru.cc
>>> @@ -1466,7 +1466,8 @@ int pru_symref2ioregno (rtx op)
>>>  /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
>>>  static bool
>>>  pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
>>> -                                    bool strict_p, addr_space_t as)
>>> +                                    bool strict_p, addr_space_t as,
>>> +                                    code_helper = ERROR_MARK)
>>>  {
>>>    if (as == ADDR_SPACE_REGIO)
>>>      {
>>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>>> index 280aa0b33b9..31e2b9bccc2 100644
>>> --- a/gcc/config/riscv/riscv.cc
>>> +++ b/gcc/config/riscv/riscv.cc
>>> @@ -1163,7 +1163,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
>>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
>>>
>>>  static bool
>>> -riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
>>> +riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>>> +                           code_helper = ERROR_MARK)
>>>  {
>>>    struct riscv_address_info addr;
>>>
>>> diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
>>> index 7d474ffc130..813459ad8b6 100644
>>> --- a/gcc/config/rl78/rl78-protos.h
>>> +++ b/gcc/config/rl78/rl78-protos.h
>>> @@ -18,6 +18,9 @@
>>>     along with GCC; see the file COPYING3.  If not see
>>>     <http://www.gnu.org/licenses/>.  */
>>>
>>>
>>> +
>>> +#include "tree.h"  /* For ERROR_MARK.  */
>>> +
>>>  const char *    rl78_addsi3_internal (rtx *, unsigned int);
>>>  void           rl78_emit_eh_epilogue (rtx);
>>>  void           rl78_expand_compare (rtx *);
>>> @@ -33,7 +36,8 @@ int           rl78_far_p (rtx x);
>>>  bool           rl78_hl_b_c_addr_p (rtx);
>>>  int            rl78_initial_elimination_offset (int, int);
>>>  bool           rl78_as_legitimate_address (machine_mode, rtx,
>>> -                                           bool, addr_space_t);
>>> +                                           bool, addr_space_t,
>>> +                                           code_helper = ERROR_MARK);
>>>  int            rl78_legitimize_reload_address (rtx *, machine_mode, int,int, int);
>>>  enum reg_class rl78_mode_code_base_reg_class (machine_mode, addr_space_t, int, int);
>>>  bool           rl78_peep_movhi_p (rtx *);
>>> diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
>>> index 9083096c4ae..0cbd6bf780a 100644
>>> --- a/gcc/config/rl78/rl78.cc
>>> +++ b/gcc/config/rl78/rl78.cc
>>> @@ -1143,7 +1143,8 @@ rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE
>>>
>>>  bool
>>>  rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>>> -                           bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
>>> +                           bool strict ATTRIBUTE_UNUSED,
>>> +                           addr_space_t as ATTRIBUTE_UNUSED, code_helper)
>>>  {
>>>    rtx base, index, addend;
>>>    bool is_far_addr = false;
>>> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
>>> index 546c353029b..efc54528b23 100644
>>> --- a/gcc/config/rs6000/rs6000.cc
>>> +++ b/gcc/config/rs6000/rs6000.cc
>>> @@ -1109,7 +1109,8 @@ struct processor_costs ppca2_cost = {
>>>  static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);
>>>
>>>
>>>
>>> -static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                              code_helper = ERROR_MARK);
>>>  static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
>>>  static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
>>>  static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
>>> @@ -9854,7 +9855,8 @@ use_toc_relative_ref (rtx sym, machine_mode mode)
>>>     because adjacent memory cells are accessed by adding word-sized offsets
>>>     during assembly output.  */
>>>  static bool
>>> -rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
>>> +rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
>>> +                            code_helper = ERROR_MARK)
>>>  {
>>>    bool reg_offset_p = reg_offset_addressing_ok_p (mode);
>>>    bool quad_offset_p = mode_supports_dq_form (mode);
>>> @@ -9957,10 +9959,10 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
>>>
>>>  /* Debug version of rs6000_legitimate_address_p.  */
>>>  static bool
>>> -rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
>>> -                                  bool reg_ok_strict)
>>> +rs6000_debug_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
>>> +                                  code_helper ch)
>>>  {
>>> -  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
>>> +  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict, ch);
>>>    fprintf (stderr,
>>>            "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
>>>            "strict = %d, reload = %s, code = %s\n",
>>> diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
>>> index 726b00a3193..245c6a4413d 100644
>>> --- a/gcc/config/rx/rx.cc
>>> +++ b/gcc/config/rx/rx.cc
>>> @@ -179,7 +179,8 @@ rx_small_data_operand (rtx op)
>>>
>>>  static bool
>>>  rx_is_legitimate_address (machine_mode mode, rtx x,
>>> -                         bool strict ATTRIBUTE_UNUSED)
>>> +                         bool strict ATTRIBUTE_UNUSED,
>>> +                         code_helper = ERROR_MARK)
>>>  {
>>>    if (RTX_OK_FOR_BASE (x, strict))
>>>      /* Register Indirect.  */
>>> diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
>>> index 9284477396d..5b8826162a9 100644
>>> --- a/gcc/config/s390/s390.cc
>>> +++ b/gcc/config/s390/s390.cc
>>> @@ -4914,7 +4914,8 @@ s390_expand_plus_operand (rtx target, rtx src,
>>>     STRICT specifies whether strict register checking applies.  */
>>>
>>>  static bool
>>> -s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>>> +s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    struct s390_address ad;
>>>
>>> diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
>>> index 938f7aa6281..294faf7c0c3 100644
>>> --- a/gcc/config/sh/sh.cc
>>> +++ b/gcc/config/sh/sh.cc
>>> @@ -266,7 +266,8 @@ static reg_class_t sh_preferred_reload_class (rtx, reg_class_t);
>>>  static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t,
>>>                                          machine_mode,
>>>                                          struct secondary_reload_info *);
>>> -static bool sh_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool sh_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                    code_helper = ERROR_MARK);
>>>  static rtx sh_legitimize_address (rtx, rtx, machine_mode);
>>>  static rtx sh_delegitimize_address (rtx);
>>>  static bool sh_cannot_substitute_mem_equiv_p (rtx);
>>> @@ -9038,7 +9039,7 @@ sh_legitimate_index_p (machine_mode mode, rtx op, bool consider_sh2a,
>>>           GBR
>>>           GBR+disp  */
>>>  static bool
>>> -sh_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +sh_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    if (REG_P (x) && REGNO (x) == GBR_REG)
>>>      return true;
>>> diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
>>> index 0aade05faf5..82e57952414 100644
>>> --- a/gcc/config/sparc/sparc.cc
>>> +++ b/gcc/config/sparc/sparc.cc
>>> @@ -607,7 +607,8 @@ static void sparc_emit_set_const64 (rtx, rtx);
>>>  static void sparc_output_addr_vec (rtx);
>>>  static void sparc_output_addr_diff_vec (rtx);
>>>  static void sparc_output_deferred_case_vectors (void);
>>> -static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool sparc_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                       code_helper = ERROR_MARK);
>>>  static bool sparc_legitimate_constant_p (machine_mode, rtx);
>>>  static rtx sparc_builtin_saveregs (void);
>>>  static int epilogue_renumber (rtx *, int);
>>> @@ -4529,7 +4530,8 @@ sparc_pic_register_p (rtx x)
>>>     ordinarily.  This changes a bit when generating PIC.  */
>>>
>>>  static bool
>>> -sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>>> +sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>>> +                           code_helper)
>>>  {
>>>    rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
>>>
>>> diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
>>> index f90d88eba6f..27ae023bcb3 100644
>>> --- a/gcc/config/stormy16/stormy16-protos.h
>>> +++ b/gcc/config/stormy16/stormy16-protos.h
>>> @@ -18,7 +18,7 @@ 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/>.  */
>>>
>>> -
>>> +#include "tree.h"  /* For ERROR_MARK.  */
>>>
>>>  extern struct xstormy16_stack_layout xstormy16_compute_stack_layout (void);
>>>  extern void xstormy16_expand_prologue (void);
>>> @@ -65,6 +65,7 @@ extern const char * xstormy16_output_shift (machine_mode, enum rtx_code,
>>>                                             rtx, rtx, rtx);
>>>  extern bool  xstormy16_below100_symbol (rtx, machine_mode);
>>>  extern bool  xstormy16_splittable_below100_operand (rtx, machine_mode);
>>> -extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool);
>>> +extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                           code_helper = ERROR_MARK);
>>>  #endif
>>>
>>> diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
>>> index cd453c2a2f7..10887153906 100644
>>> --- a/gcc/config/stormy16/stormy16.cc
>>> +++ b/gcc/config/stormy16/stormy16.cc
>>> @@ -795,8 +795,8 @@ xstormy16_expand_andqi3 (rtx *operands)
>>>    && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))
>>>
>>>  bool
>>> -xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>> -                               rtx x, bool strict)
>>> +xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
>>> +                               bool strict, code_helper)
>>>  {
>>>    if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))
>>>      return true;
>>> diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
>>> index 0fb72716b17..416c2841a5c 100644
>>> --- a/gcc/config/v850/v850.cc
>>> +++ b/gcc/config/v850/v850.cc
>>> @@ -3030,7 +3030,8 @@ v850_rtx_ok_for_base_p (const_rtx x, bool strict_p)
>>>
>>>  static bool
>>>  v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
>>> -                          addr_space_t as ATTRIBUTE_UNUSED)
>>> +                          addr_space_t as ATTRIBUTE_UNUSED,
>>> +                          code_helper = ERROR_MARK)
>>>  {
>>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
>>>
>>> diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
>>> index 82a176d3bfc..df9478d881a 100644
>>> --- a/gcc/config/vax/vax.cc
>>> +++ b/gcc/config/vax/vax.cc
>>> @@ -46,7 +46,8 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "target-def.h"
>>>
>>>  static void vax_option_override (void);
>>> -static bool vax_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool vax_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                     code_helper = ERROR_MARK);
>>>  static void vax_file_start (void);
>>>  static void vax_init_libfuncs (void);
>>>  static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
>>> @@ -1902,7 +1903,7 @@ indexable_address_p (rtx xfoo0, rtx xfoo1, machine_mode mode, bool strict)
>>>     The MODE argument is the machine mode for the MEM expression
>>>     that wants to use this address.  */
>>>  bool
>>> -vax_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +vax_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    rtx xfoo0, xfoo1;
>>>
>>> diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
>>> index 48a61744db6..5fadbc80be0 100644
>>> --- a/gcc/config/visium/visium.cc
>>> +++ b/gcc/config/visium/visium.cc
>>> @@ -194,7 +194,8 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
>>>
>>>  static bool visium_legitimate_constant_p (machine_mode, rtx);
>>>
>>> -static bool visium_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool visium_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                        code_helper = ERROR_MARK);
>>>
>>>  static bool visium_print_operand_punct_valid_p (unsigned char);
>>>  static void visium_print_operand (FILE *, rtx, int);
>>> @@ -1818,7 +1819,7 @@ rtx_ok_for_offset_p (machine_mode mode, rtx op)
>>>     kind of register is required.  */
>>>
>>>  static bool
>>> -visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
>>> +visium_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
>>>  {
>>>    rtx base;
>>>    unsigned int regno;
>>> diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
>>> index dd35e63c094..897cf7363f4 100644
>>> --- a/gcc/config/xtensa/xtensa.cc
>>> +++ b/gcc/config/xtensa/xtensa.cc
>>> @@ -123,7 +123,8 @@ static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
>>>  static bool xtensa_return_in_msb (const_tree);
>>>  static void printx (FILE *, signed int);
>>>  static rtx xtensa_builtin_saveregs (void);
>>> -static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
>>> +static bool xtensa_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                        code_helper = ERROR_MARK);
>>>  static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
>>>                                                         int) ATTRIBUTE_UNUSED;
>>>  static section *xtensa_select_rtx_section (machine_mode, rtx,
>>> @@ -2296,9 +2297,9 @@ xtensa_emit_sibcall (int callop, rtx *operands)
>>>    return result;
>>>  }
>>>
>>> -
>>>  bool
>>> -xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
>>> +xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
>>> +                            code_helper)
>>>  {
>>>    /* Allow constant pool addresses.  */
>>>    if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
>>> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
>>> index ca8837cef67..3e9a2f19e27 100644
>>> --- a/gcc/coretypes.h
>>> +++ b/gcc/coretypes.h
>>> @@ -99,6 +99,7 @@ typedef const union tree_node *const_tree;
>>>  struct gimple;
>>>  typedef gimple *gimple_seq;
>>>  struct gimple_stmt_iterator;
>>> +class code_helper;
>>>
>>>  /* Forward decls for leaf gimple subclasses (for individual gimple codes).
>>>     Keep this in the same order as the corresponding codes in gimple.def.  */
>>> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
>>> index 95ba56e05ae..e4d0cc43f41 100644
>>> --- a/gcc/doc/tm.texi
>>> +++ b/gcc/doc/tm.texi
>>> @@ -5853,9 +5853,16 @@ the maximum number that @code{TARGET_LEGITIMATE_ADDRESS_P} would ever
>>>  accept.
>>>  @end defmac
>>>
>>> -@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict})
>>> +@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict}, code_helper @var{ch})
>>>  A function that returns whether @var{x} (an RTX) is a legitimate memory
>>>  address on the target machine for a memory operand of mode @var{mode}.
>>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to
>>> +determine if it is valid to use @var{x} as a memory operand for RTX insn
>>> +which is generated for the given code_helper @var{ch}.  For example,
>>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying
>>> +hardware instructions support fewer addressing modes than what are for the
>>> +normal vector load and store, then with this @var{ch} target can know the
>>> +actual use context and return more exact result.
>>>
>>>  Legitimate addresses are defined in two variants: a strict variant and a
>>>  non-strict one.  The @var{strict} parameter chooses which variant is
>>> @@ -10992,11 +10999,12 @@ version of this hook returns true for the modes returned by either the
>>>  target hooks for the given address space.
>>>  @end deftypefn
>>>
>>> -@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
>>> +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as}, code_helper @var{ch})
>>>  Define this to return true if @var{exp} is a valid address for mode
>>> -@var{mode} in the named address space @var{as}.  The @var{strict}
>>> -parameter says whether strict addressing is in effect after reload has
>>> -finished.  This target hook is the same as the
>>> +@var{mode} in the named address space @var{as} with the use context
>>> +@var{ch}.  The @var{strict} parameter says whether strict addressing
>>> +is in effect after reload has finished.  The @var{ch} indicates what
>>> +context @var{exp} will be used for.  This target hook is the same as the
>>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes
>>>  explicit named address space support.
>>>  @end deftypefn
>>> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
>>> index 4dc2d70c402..cb9cbac5bb3 100644
>>> --- a/gcc/lra-constraints.cc
>>> +++ b/gcc/lra-constraints.cc
>>> @@ -336,7 +336,8 @@ valid_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>   win:
>>>    return 1;
>>>  #else
>>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
>>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
>>> +                                                 ERROR_MARK);
>>>  #endif
>>>  }
>>>
>>> diff --git a/gcc/recog.cc b/gcc/recog.cc
>>> index 37432087812..692c258def6 100644
>>> --- a/gcc/recog.cc
>>> +++ b/gcc/recog.cc
>>> @@ -1813,7 +1813,8 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>   win:
>>>    return true;
>>>  #else
>>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
>>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
>>> +                                                 ERROR_MARK);
>>>  #endif
>>>  }
>>>
>>> diff --git a/gcc/reload.cc b/gcc/reload.cc
>>> index d079bc120d5..0be21f7b61e 100644
>>> --- a/gcc/reload.cc
>>> +++ b/gcc/reload.cc
>>> @@ -2172,7 +2172,8 @@ strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>   win:
>>>    return true;
>>>  #else
>>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
>>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as,
>>> +                                                 ERROR_MARK);
>>>  #endif
>>>  }
>>>
>>>
>>> diff --git a/gcc/target.def b/gcc/target.def
>>> index 7d684296c17..a500aeb6714 100644
>>> --- a/gcc/target.def
>>> +++ b/gcc/target.def
>>> @@ -2897,6 +2897,13 @@ DEFHOOK
>>>  (legitimate_address_p,
>>>   "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
>>>  address on the target machine for a memory operand of mode @var{mode}.\n\
>>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to\n\
>>> +determine if it is valid to use @var{x} as a memory operand for RTX insn\n\
>>> +which is generated for the given code_helper @var{ch}.  For example,\n\
>>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying\n\
>>> +hardware instructions support fewer addressing modes than what are for the\n\
>>> +normal vector load and store, then with this @var{ch} target can know the\n\
>>> +actual use context and return more exact result.\n\
>>>  \n\
>>>  Legitimate addresses are defined in two variants: a strict variant and a\n\
>>>  non-strict one.  The @var{strict} parameter chooses which variant is\n\
>>> @@ -2957,7 +2964,7 @@ that case and the non-strict variant otherwise.\n\
>>>  \n\
>>>  Using the hook is usually simpler because it limits the number of\n\
>>>  files that are recompiled when changes are made.",
>>> - bool, (machine_mode mode, rtx x, bool strict),
>>> + bool, (machine_mode mode, rtx x, bool strict, code_helper ch),
>>>   default_legitimate_address_p)
>>>
>>>  /* True if the given constant can be put into an object_block.  */
>>> @@ -3348,12 +3355,13 @@ target hooks for the given address space.",
>>>  DEFHOOK
>>>  (legitimate_address_p,
>>>   "Define this to return true if @var{exp} is a valid address for mode\n\
>>> -@var{mode} in the named address space @var{as}.  The @var{strict}\n\
>>> -parameter says whether strict addressing is in effect after reload has\n\
>>> -finished.  This target hook is the same as the\n\
>>> +@var{mode} in the named address space @var{as} with the use context\n\
>>> +@var{ch}.  The @var{strict} parameter says whether strict addressing\n\
>>> +is in effect after reload has finished.  The @var{ch} indicates what\n\
>>> +context @var{exp} will be used for.  This target hook is the same as the\n\
>>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
>>>  explicit named address space support.",
>>> - bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
>>> + bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as, code_helper ch),
>>>   default_addr_space_legitimate_address_p)
>>>
>>>  /* Return an updated address to convert an invalid pointer to a named
>>> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
>>> index e190369f87a..4ef53267e50 100644
>>> --- a/gcc/targhooks.cc
>>> +++ b/gcc/targhooks.cc
>>> @@ -99,7 +99,8 @@ along with GCC; see the file COPYING3.  If not see
>>>  bool
>>>  default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
>>>                               rtx addr ATTRIBUTE_UNUSED,
>>> -                             bool strict ATTRIBUTE_UNUSED)
>>> +                             bool strict ATTRIBUTE_UNUSED,
>>> +                             code_helper ATTRIBUTE_UNUSED)
>>>  {
>>>  #ifdef GO_IF_LEGITIMATE_ADDRESS
>>>    /* Defer to the old implementation using a goto.  */
>>> @@ -1680,9 +1681,10 @@ target_default_pointer_address_modes_p (void)
>>>  bool
>>>  default_addr_space_legitimate_address_p (machine_mode mode, rtx mem,
>>>                                          bool strict,
>>> -                                        addr_space_t as ATTRIBUTE_UNUSED)
>>> +                                        addr_space_t as ATTRIBUTE_UNUSED,
>>> +                                        code_helper code)
>>>  {
>>> -  return targetm.legitimate_address_p (mode, mem, strict);
>>> +  return targetm.legitimate_address_p (mode, mem, strict, code);
>>>  }
>>>
>>>  /* Named address space version of LEGITIMIZE_ADDRESS.
>>> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
>>> index 1a0db8dddd5..761225512b7 100644
>>> --- a/gcc/targhooks.h
>>> +++ b/gcc/targhooks.h
>>> @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
>>>  #ifndef GCC_TARGHOOKS_H
>>>  #define GCC_TARGHOOKS_H
>>>
>>> -extern bool default_legitimate_address_p (machine_mode, rtx, bool);
>>> +extern bool default_legitimate_address_p (machine_mode, rtx, bool, code_helper);
>>>
>>>  extern void default_external_libcall (rtx);
>>>  extern rtx default_legitimize_address (rtx, rtx, machine_mode);
>>> @@ -202,8 +202,8 @@ extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
>>>  extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
>>>  extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
>>>                                                    addr_space_t);
>>> -extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
>>> -                                                    bool, addr_space_t);
>>> +extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
>>> +                                                    addr_space_t, code_helper);
>>>  extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
>>>                                                   addr_space_t);
>>>  extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
>>> --
>>> 2.39.3
  
Richard Biener Aug. 7, 2023, 11:58 a.m. UTC | #4
On Mon, Aug 7, 2023 at 12:15 PM Kewen.Lin <linkw@linux.ibm.com> wrote:
>
> Hi Richi,
>
> on 2023/6/30 17:13, Kewen.Lin via Gcc-patches wrote:
> > Hi Richi,
> >
> > Thanks for your review!
> >
> > on 2023/6/30 16:56, Richard Biener wrote:
> >> On Fri, Jun 30, 2023 at 7:38 AM Kewen.Lin <linkw@linux.ibm.com> wrote:
> >>>
> >>> Hi,
> >>>
> >>> As PR110248 shows, some middle-end passes like IVOPTs can
> >>> query the target hook legitimate_address_p with some
> >>> artificially constructed rtx to determine whether some
> >>> addressing modes are supported by target for some gimple
> >>> statement.  But for now the existing legitimate_address_p
> >>> only checks the given mode, it's unable to distinguish
> >>> some special cases unfortunately, for example, for LEN_LOAD
> >>> ifn on Power port, we would expand it with lxvl hardware
> >>> insn, which only supports one register to hold the address
> >>> (the other register is holding the length), that is we
> >>> don't support base (reg) + index (reg) addressing mode for
> >>> sure.  But hook legitimate_address_p only considers the
> >>> given mode which would be some vector mode for LEN_LOAD
> >>> ifn, and we do support base + index addressing mode for
> >>> normal vector load and store insns, so the hook will return
> >>> true for the query unexpectedly.
> >>>
> >>> This patch is to introduce one extra argument of type
> >>> code_helper for hook legitimate_address_p, it makes targets
> >>> able to handle some special case like what's described
> >>> above.  The subsequent patches will show how to leverage
> >>> the new code_helper argument.
> >>>
> >>> I didn't separate those target specific adjustments to
> >>> their own patches, since those changes are no function
> >>> changes.  One typical change is to add one unnamed argument
> >>> with default ERROR_MARK, some ports need to include tree.h
> >>> in their {port}-protos.h since the hook is used in some
> >>> machine description files.  I've cross-built a corresponding
> >>> cc1 successfully for at least one triple of each affected
> >>> target so I believe they are safe.  But feel free to correct
> >>> me if separating is needed for the review of this patch.
> >>>
> >>> Besides, it's bootstrapped and regtested on
> >>> x86_64-redhat-linux and powerpc64{,le}-linux-gnu.
> >>>
> >>> Is it ok for trunk?
> >>
> >> Is defaulting the arguments in the targets necessary for
> >> the middle-end or only for direct uses in the targets?
> >
> > It's only for the direct uses in target codes, the call
> > sites in generic code of these hooks would use the given
> > code_helper type variable or an explicit ERROR_MARK, they
> > don't require target codes to set that.
> >
> >>
> >> It looks OK in general but please give others some time to
> >> comment.
>
> Some weeks passed and no further comments are received, I guess
> this still looks good to you?

Yes.

> BR,
> Kewen
>
> >
> > OK, thanks again!
> >
> > BR,
> > Kewen
> >
> >>
> >> Thanks,
> >> Richard.
> >>
> >>> BR,
> >>> Kewen
> >>> ------
> >>>         PR tree-optimization/110248
> >>>
> >>> gcc/ChangeLog:
> >>>
> >>>         * coretypes.h (class code_helper): Add forward declaration.
> >>>         * doc/tm.texi: Regenerate.
> >>>         * lra-constraints.cc (valid_address_p): Call target hook
> >>>         targetm.addr_space.legitimate_address_p with an extra parameter
> >>>         ERROR_MARK as its prototype changes.
> >>>         * recog.cc (memory_address_addr_space_p): Likewise.
> >>>         * reload.cc (strict_memory_address_addr_space_p): Likewise.
> >>>         * target.def (legitimate_address_p, addr_space.legitimate_address_p):
> >>>         Extend with one more argument of type code_helper, update the
> >>>         documentation accordingly.
> >>>         * targhooks.cc (default_legitimate_address_p): Adjust for the
> >>>         new code_helper argument.
> >>>         (default_addr_space_legitimate_address_p): Likewise.
> >>>         * targhooks.h (default_legitimate_address_p): Likewise.
> >>>         (default_addr_space_legitimate_address_p): Likewise.
> >>>         * config/aarch64/aarch64.cc (aarch64_legitimate_address_hook_p): Adjust
> >>>         with extra unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/alpha/alpha.cc (alpha_legitimate_address_p): Likewise.
> >>>         * config/arc/arc.cc (arc_legitimate_address_p): Likewise.
> >>>         * config/arm/arm-protos.h (arm_legitimate_address_p): Likewise.
> >>>         (tree.h): New include for tree_code ERROR_MARK.
> >>>         * config/arm/arm.cc (arm_legitimate_address_p): Adjust with extra
> >>>         unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/avr/avr.cc (avr_addr_space_legitimate_address_p): Likewise.
> >>>         * config/bfin/bfin.cc (bfin_legitimate_address_p): Likewise.
> >>>         * config/bpf/bpf.cc (bpf_legitimate_address_p): Likewise.
> >>>         * config/c6x/c6x.cc (c6x_legitimate_address_p): Likewise.
> >>>         * config/cris/cris-protos.h (cris_legitimate_address_p): Likewise.
> >>>         (tree.h): New include for tree_code ERROR_MARK.
> >>>         * config/cris/cris.cc (cris_legitimate_address_p): Adjust with extra
> >>>         unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/csky/csky.cc (csky_legitimate_address_p): Likewise.
> >>>         * config/epiphany/epiphany.cc (epiphany_legitimate_address_p):
> >>>         Likewise.
> >>>         * config/frv/frv.cc (frv_legitimate_address_p): Likewise.
> >>>         * config/ft32/ft32.cc (ft32_addr_space_legitimate_address_p): Likewise.
> >>>         * config/gcn/gcn.cc (gcn_addr_space_legitimate_address_p): Likewise.
> >>>         * config/h8300/h8300.cc (h8300_legitimate_address_p): Likewise.
> >>>         * config/i386/i386.cc (ix86_legitimate_address_p): Likewise.
> >>>         * config/ia64/ia64.cc (ia64_legitimate_address_p): Likewise.
> >>>         * config/iq2000/iq2000.cc (iq2000_legitimate_address_p): Likewise.
> >>>         * config/lm32/lm32.cc (lm32_legitimate_address_p): Likewise.
> >>>         * config/loongarch/loongarch.cc (loongarch_legitimate_address_p):
> >>>         Likewise.
> >>>         * config/m32c/m32c.cc (m32c_legitimate_address_p): Likewise.
> >>>         (m32c_addr_space_legitimate_address_p): Likewise.
> >>>         * config/m32r/m32r.cc (m32r_legitimate_address_p): Likewise.
> >>>         * config/m68k/m68k.cc (m68k_legitimate_address_p): Likewise.
> >>>         * config/mcore/mcore.cc (mcore_legitimate_address_p): Likewise.
> >>>         * config/microblaze/microblaze-protos.h (tree.h): New include for
> >>>         tree_code ERROR_MARK.
> >>>         (microblaze_legitimate_address_p): Adjust with extra unnamed
> >>>         code_helper argument with default ERROR_MARK.
> >>>         * config/microblaze/microblaze.cc (microblaze_legitimate_address_p):
> >>>         Likewise.
> >>>         * config/mips/mips.cc (mips_legitimate_address_p): Likewise.
> >>>         * config/mmix/mmix.cc (mmix_legitimate_address_p): Likewise.
> >>>         * config/mn10300/mn10300.cc (mn10300_legitimate_address_p): Likewise.
> >>>         * config/moxie/moxie.cc (moxie_legitimate_address_p): Likewise.
> >>>         * config/msp430/msp430.cc (msp430_legitimate_address_p): Likewise.
> >>>         (msp430_addr_space_legitimate_address_p): Adjust with extra code_helper
> >>>         argument with default ERROR_MARK and adjust the call to function
> >>>         msp430_legitimate_address_p.
> >>>         * config/nds32/nds32.cc (nds32_legitimate_address_p): Adjust with extra
> >>>         unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/nios2/nios2.cc (nios2_legitimate_address_p): Likewise.
> >>>         * config/nvptx/nvptx.cc (nvptx_legitimate_address_p): Likewise.
> >>>         * config/or1k/or1k.cc (or1k_legitimate_address_p): Likewise.
> >>>         * config/pa/pa.cc (pa_legitimate_address_p): Likewise.
> >>>         * config/pdp11/pdp11.cc (pdp11_legitimate_address_p): Likewise.
> >>>         * config/pru/pru.cc (pru_addr_space_legitimate_address_p): Likewise.
> >>>         * config/riscv/riscv.cc (riscv_legitimate_address_p): Likewise.
> >>>         * config/rl78/rl78-protos.h (rl78_as_legitimate_address): Likewise.
> >>>         (tree.h): New include for tree_code ERROR_MARK.
> >>>         * config/rl78/rl78.cc (rl78_as_legitimate_address): Adjust with
> >>>         extra unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/rs6000/rs6000.cc (rs6000_legitimate_address_p): Likewise.
> >>>         (rs6000_debug_legitimate_address_p): Adjust with extra code_helper
> >>>         argument and adjust the call to function rs6000_legitimate_address_p.
> >>>         * config/rx/rx.cc (rx_is_legitimate_address): Adjust with extra
> >>>         unnamed code_helper argument with default ERROR_MARK.
> >>>         * config/s390/s390.cc (s390_legitimate_address_p): Likewise.
> >>>         * config/sh/sh.cc (sh_legitimate_address_p): Likewise.
> >>>         * config/sparc/sparc.cc (sparc_legitimate_address_p): Likewise.
> >>>         * config/v850/v850.cc (v850_legitimate_address_p): Likewise.
> >>>         * config/vax/vax.cc (vax_legitimate_address_p): Likewise.
> >>>         * config/visium/visium.cc (visium_legitimate_address_p): Likewise.
> >>>         * config/xtensa/xtensa.cc (xtensa_legitimate_address_p): Likewise.
> >>>         * config/stormy16/stormy16-protos.h (xstormy16_legitimate_address_p):
> >>>         Likewise.
> >>>         (tree.h): New include for tree_code ERROR_MARK.
> >>>         * config/stormy16/stormy16.cc (xstormy16_legitimate_address_p):
> >>>         Adjust with extra unnamed code_helper argument with default
> >>>         ERROR_MARK.
> >>> ---
> >>>  gcc/config/aarch64/aarch64.cc             |  3 ++-
> >>>  gcc/config/alpha/alpha.cc                 |  3 ++-
> >>>  gcc/config/arc/arc.cc                     |  3 ++-
> >>>  gcc/config/arm/arm-protos.h               |  4 +++-
> >>>  gcc/config/arm/arm.cc                     |  2 +-
> >>>  gcc/config/avr/avr.cc                     |  4 ++--
> >>>  gcc/config/bfin/bfin.cc                   |  3 ++-
> >>>  gcc/config/bpf/bpf.cc                     |  3 ++-
> >>>  gcc/config/c6x/c6x.cc                     |  3 ++-
> >>>  gcc/config/cris/cris-protos.h             |  5 ++++-
> >>>  gcc/config/cris/cris.cc                   |  2 +-
> >>>  gcc/config/csky/csky.cc                   |  3 ++-
> >>>  gcc/config/epiphany/epiphany.cc           |  3 ++-
> >>>  gcc/config/frv/frv.cc                     |  5 +++--
> >>>  gcc/config/ft32/ft32.cc                   |  3 ++-
> >>>  gcc/config/gcn/gcn.cc                     |  2 +-
> >>>  gcc/config/h8300/h8300.cc                 |  3 ++-
> >>>  gcc/config/i386/i386.cc                   |  3 ++-
> >>>  gcc/config/ia64/ia64.cc                   |  7 ++++---
> >>>  gcc/config/iq2000/iq2000.cc               |  6 ++++--
> >>>  gcc/config/lm32/lm32.cc                   |  7 ++++---
> >>>  gcc/config/loongarch/loongarch.cc         |  3 ++-
> >>>  gcc/config/m32c/m32c.cc                   | 15 +++++++++------
> >>>  gcc/config/m32r/m32r.cc                   |  5 +++--
> >>>  gcc/config/m68k/m68k.cc                   |  5 +++--
> >>>  gcc/config/mcore/mcore.cc                 |  5 +++--
> >>>  gcc/config/microblaze/microblaze-protos.h |  5 ++++-
> >>>  gcc/config/microblaze/microblaze.cc       |  3 ++-
> >>>  gcc/config/mips/mips.cc                   |  3 ++-
> >>>  gcc/config/mmix/mmix.cc                   |  6 ++++--
> >>>  gcc/config/mn10300/mn10300.cc             |  3 ++-
> >>>  gcc/config/moxie/moxie.cc                 |  3 ++-
> >>>  gcc/config/msp430/msp430.cc               |  8 +++++---
> >>>  gcc/config/nds32/nds32.cc                 |  3 ++-
> >>>  gcc/config/nios2/nios2.cc                 |  5 +++--
> >>>  gcc/config/nvptx/nvptx.cc                 |  2 +-
> >>>  gcc/config/or1k/or1k.cc                   |  3 ++-
> >>>  gcc/config/pa/pa.cc                       |  5 +++--
> >>>  gcc/config/pdp11/pdp11.cc                 |  4 ++--
> >>>  gcc/config/pru/pru.cc                     |  3 ++-
> >>>  gcc/config/riscv/riscv.cc                 |  3 ++-
> >>>  gcc/config/rl78/rl78-protos.h             |  6 +++++-
> >>>  gcc/config/rl78/rl78.cc                   |  3 ++-
> >>>  gcc/config/rs6000/rs6000.cc               | 12 +++++++-----
> >>>  gcc/config/rx/rx.cc                       |  3 ++-
> >>>  gcc/config/s390/s390.cc                   |  3 ++-
> >>>  gcc/config/sh/sh.cc                       |  5 +++--
> >>>  gcc/config/sparc/sparc.cc                 |  6 ++++--
> >>>  gcc/config/stormy16/stormy16-protos.h     |  5 +++--
> >>>  gcc/config/stormy16/stormy16.cc           |  4 ++--
> >>>  gcc/config/v850/v850.cc                   |  3 ++-
> >>>  gcc/config/vax/vax.cc                     |  5 +++--
> >>>  gcc/config/visium/visium.cc               |  5 +++--
> >>>  gcc/config/xtensa/xtensa.cc               |  7 ++++---
> >>>  gcc/coretypes.h                           |  1 +
> >>>  gcc/doc/tm.texi                           | 18 +++++++++++++-----
> >>>  gcc/lra-constraints.cc                    |  3 ++-
> >>>  gcc/recog.cc                              |  3 ++-
> >>>  gcc/reload.cc                             |  3 ++-
> >>>  gcc/target.def                            | 18 +++++++++++++-----
> >>>  gcc/targhooks.cc                          |  8 +++++---
> >>>  gcc/targhooks.h                           |  6 +++---
> >>>  62 files changed, 190 insertions(+), 106 deletions(-)
> >>>
> >>> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> >>> index 644ebdebc0e..2dfb811ec4f 100644
> >>> --- a/gcc/config/aarch64/aarch64.cc
> >>> +++ b/gcc/config/aarch64/aarch64.cc
> >>> @@ -11182,7 +11182,8 @@ aarch64_classify_symbolic_expression (rtx x)
> >>>  /* Return TRUE if X is a legitimate address for accessing memory in
> >>>     mode MODE.  */
> >>>  static bool
> >>> -aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p)
> >>> +aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p,
> >>> +                                  code_helper = ERROR_MARK)
> >>>  {
> >>>    struct aarch64_address_info addr;
> >>>
> >>> diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
> >>> index 360b50e20d4..0367f117c21 100644
> >>> --- a/gcc/config/alpha/alpha.cc
> >>> +++ b/gcc/config/alpha/alpha.cc
> >>> @@ -844,7 +844,8 @@ alpha_linkage_symbol_p (const char *symname)
> >>>     low-order three bits; this is an "unaligned" access.  */
> >>>
> >>>  static bool
> >>> -alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    /* If this is an ldq_u type address, discard the outer AND.  */
> >>>    if (mode == DImode
> >>> diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
> >>> index fef8a504f77..266ba8b00bb 100644
> >>> --- a/gcc/config/arc/arc.cc
> >>> +++ b/gcc/config/arc/arc.cc
> >>> @@ -6715,7 +6715,8 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
> >>>  }
> >>>
> >>>  static bool
> >>> -arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +arc_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                         code_helper = ERROR_MARK)
> >>>  {
> >>>    if (RTX_OK_FOR_BASE_P (x, strict))
> >>>       return true;
> >>> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> >>> index 7d73c66a15d..2257aa2c1c0 100644
> >>> --- a/gcc/config/arm/arm-protos.h
> >>> +++ b/gcc/config/arm/arm-protos.h
> >>> @@ -23,6 +23,7 @@
> >>>  #define GCC_ARM_PROTOS_H
> >>>
> >>>  #include "sbitmap.h"
> >>> +#include "tree.h" /* For ERROR_MARK.  */
> >>>
> >>>  rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
> >>>
> >>> @@ -83,7 +84,8 @@ extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
> >>>  extern int legitimate_pic_operand_p (rtx);
> >>>  extern rtx legitimize_pic_address (rtx, machine_mode, rtx, rtx, bool);
> >>>  extern rtx legitimize_tls_address (rtx, rtx);
> >>> -extern bool arm_legitimate_address_p (machine_mode, rtx, bool);
> >>> +extern bool arm_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                     code_helper = ERROR_MARK);
> >>>  extern int arm_legitimate_address_outer_p (machine_mode, rtx, RTX_CODE, int);
> >>>  extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
> >>>  extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
> >>> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> >>> index 38f0839de1c..6e933c80183 100644
> >>> --- a/gcc/config/arm/arm.cc
> >>> +++ b/gcc/config/arm/arm.cc
> >>> @@ -9171,7 +9171,7 @@ thumb_legitimate_offset_p (machine_mode mode, HOST_WIDE_INT val)
> >>>  }
> >>>
> >>>  bool
> >>> -arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
> >>>  {
> >>>    if (TARGET_ARM)
> >>>      return arm_legitimate_address_outer_p (mode, x, SET, strict_p);
> >>> diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
> >>> index 0447641a8e9..fa42602f877 100644
> >>> --- a/gcc/config/avr/avr.cc
> >>> +++ b/gcc/config/avr/avr.cc
> >>> @@ -13431,8 +13431,8 @@ avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
> >>>  /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
> >>>
> >>>  static bool
> >>> -avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
> >>> -                                     bool strict, addr_space_t as)
> >>> +avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                                    addr_space_t as, code_helper = ERROR_MARK)
> >>>  {
> >>>    bool ok = false;
> >>>
> >>> diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
> >>> index 4320ec26722..5718babb6b2 100644
> >>> --- a/gcc/config/bfin/bfin.cc
> >>> +++ b/gcc/config/bfin/bfin.cc
> >>> @@ -2718,7 +2718,8 @@ bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
> >>>  */
> >>>
> >>>  static bool
> >>> -bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    switch (GET_CODE (x)) {
> >>>    case REG:
> >>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
> >>> index e0324e1e0e0..a16275c2810 100644
> >>> --- a/gcc/config/bpf/bpf.cc
> >>> +++ b/gcc/config/bpf/bpf.cc
> >>> @@ -668,7 +668,8 @@ bpf_address_base_p (rtx x, bool strict)
> >>>  static bool
> >>>  bpf_legitimate_address_p (machine_mode mode,
> >>>                           rtx x,
> >>> -                         bool strict)
> >>> +                         bool strict,
> >>> +                         code_helper = ERROR_MARK)
> >>>  {
> >>>    switch (GET_CODE (x))
> >>>      {
> >>> diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc
> >>> index 0c9cb821f28..72e8b4c5345 100644
> >>> --- a/gcc/config/c6x/c6x.cc
> >>> +++ b/gcc/config/c6x/c6x.cc
> >>> @@ -2444,7 +2444,8 @@ c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
> >>>  }
> >>>
> >>>  static bool
> >>> -c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                         code_helper = ERROR_MARK)
> >>>  {
> >>>    return c6x_legitimate_address_p_1 (mode, x, strict, false);
> >>>  }
> >>> diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
> >>> index 666e04f9eee..58555943986 100644
> >>> --- a/gcc/config/cris/cris-protos.h
> >>> +++ b/gcc/config/cris/cris-protos.h
> >>> @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
> >>>
> >>>  /* Prototypes for the CRIS port.  */
> >>>
> >>> +#include "tree.h" /* For ERROR_MARK.  */
> >>> +
> >>>  extern bool cris_simple_epilogue (void);
> >>>  #ifdef RTX_CODE
> >>>  extern const char *cris_op_str (rtx);
> >>> @@ -34,7 +36,8 @@ extern bool cris_base_or_autoincr_p (const_rtx, bool);
> >>>  extern bool cris_bdap_index_p (const_rtx, bool);
> >>>  extern void cris_reduce_compare (rtx *, rtx *, rtx *);
> >>>  extern bool cris_biap_index_p (const_rtx, bool);
> >>> -extern bool cris_legitimate_address_p (machine_mode, rtx, bool);
> >>> +extern bool cris_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                      code_helper = ERROR_MARK);
> >>>  extern bool cris_store_multiple_op_p (rtx);
> >>>  extern bool cris_movem_load_rest_p (rtx);
> >>>  extern void cris_asm_output_symbol_ref (FILE *, rtx);
> >>> diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
> >>> index 7fca2af085a..edd2b898a6c 100644
> >>> --- a/gcc/config/cris/cris.cc
> >>> +++ b/gcc/config/cris/cris.cc
> >>> @@ -1537,7 +1537,7 @@ cris_biap_index_p (const_rtx x, bool strict)
> >>>  /* Worker function for TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  bool
> >>> -cris_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +cris_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    const_rtx x1, x2;
> >>>
> >>> diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
> >>> index b4ee3b273a4..731f47cb2c0 100644
> >>> --- a/gcc/config/csky/csky.cc
> >>> +++ b/gcc/config/csky/csky.cc
> >>> @@ -3186,7 +3186,8 @@ csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
> >>>     be recognized.  */
> >>>
> >>>  static bool
> >>> -csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
> >>> +csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    enum rtx_code code = GET_CODE (addr);
> >>>
> >>> diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
> >>> index 60a2845d6d1..a5460dbf97f 100644
> >>> --- a/gcc/config/epiphany/epiphany.cc
> >>> +++ b/gcc/config/epiphany/epiphany.cc
> >>> @@ -2053,7 +2053,8 @@ epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
> >>>       || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
> >>>
> >>>  static bool
> >>> -epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                              code_helper = ERROR_MARK)
> >>>  {
> >>>  #define REG_OK_FOR_BASE_P(X) \
> >>>    (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
> >>> diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc
> >>> index 2dbaa75f3dc..03976ba7b71 100644
> >>> --- a/gcc/config/frv/frv.cc
> >>> +++ b/gcc/config/frv/frv.cc
> >>> @@ -261,7 +261,8 @@ static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
> >>>  /* Forward references */
> >>>
> >>>  static void frv_option_override                        (void);
> >>> -static bool frv_legitimate_address_p           (machine_mode, rtx, bool);
> >>> +static bool frv_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                     code_helper = ERROR_MARK);
> >>>  static int frv_default_flags_for_cpu           (void);
> >>>  static FRV_INLINE bool frv_small_data_reloc_p  (rtx, int);
> >>>  static void frv_print_operand                  (FILE *, rtx, int);
> >>> @@ -3396,7 +3397,7 @@ frv_legitimate_address_p_1 (machine_mode mode,
> >>>  }
> >>>
> >>>  bool
> >>> -frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
> >>>  {
> >>>    return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
> >>>  }
> >>> diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc
> >>> index 806ab769f79..059243d2a3d 100644
> >>> --- a/gcc/config/ft32/ft32.cc
> >>> +++ b/gcc/config/ft32/ft32.cc
> >>> @@ -856,7 +856,8 @@ reg_ok_for_base_p (rtx r, bool strict)
> >>>
> >>>  static bool
> >>>  ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> -                                      addr_space_t as ATTRIBUTE_UNUSED)
> >>> +                                     addr_space_t as ATTRIBUTE_UNUSED,
> >>> +                                     code_helper = ERROR_MARK)
> >>>  {
> >>>    int max_offset = TARGET_FT32B ? 16384 : 128;
> >>>
> >>> diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
> >>> index 02f4dedec42..f6cff659703 100644
> >>> --- a/gcc/config/gcn/gcn.cc
> >>> +++ b/gcc/config/gcn/gcn.cc
> >>> @@ -1654,7 +1654,7 @@ gcn_global_address_p (rtx addr)
> >>>
> >>>  static bool
> >>>  gcn_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> -                                    addr_space_t as)
> >>> +                                    addr_space_t as, code_helper = ERROR_MARK)
> >>>  {
> >>>    /* All vector instructions need to work on addresses in registers.  */
> >>>    if (!TARGET_GCN5_PLUS && (vgpr_vector_mode_p (mode) && !REG_P (x)))
> >>> diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
> >>> index cdf74c1acbd..4bbb1b711e8 100644
> >>> --- a/gcc/config/h8300/h8300.cc
> >>> +++ b/gcc/config/h8300/h8300.cc
> >>> @@ -5312,7 +5312,8 @@ h8300_rtx_ok_for_base_p (rtx x, int strict)
> >>>     CONSTANT_ADDRESS.  */
> >>>
> >>>  static bool
> >>> -h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    /* The register indirect addresses like @er0 is always valid.  */
> >>>    if (h8300_rtx_ok_for_base_p (x, strict))
> >>> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> >>> index 0761965344b..7226b3e5fd3 100644
> >>> --- a/gcc/config/i386/i386.cc
> >>> +++ b/gcc/config/i386/i386.cc
> >>> @@ -11010,7 +11010,8 @@ ix86_validate_address_register (rtx op)
> >>>     be recognized.  */
> >>>
> >>>  static bool
> >>> -ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
> >>> +ix86_legitimate_address_p (machine_mode, rtx addr, bool strict,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    struct ix86_address parts;
> >>>    rtx base, index, disp;
> >>> diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
> >>> index 92f34dd1ee7..c241e1a50fc 100644
> >>> --- a/gcc/config/ia64/ia64.cc
> >>> +++ b/gcc/config/ia64/ia64.cc
> >>> @@ -313,7 +313,8 @@ static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
> >>>  static bool ia64_scalar_mode_supported_p (scalar_mode mode);
> >>>  static bool ia64_vector_mode_supported_p (machine_mode mode);
> >>>  static bool ia64_legitimate_constant_p (machine_mode, rtx);
> >>> -static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool ia64_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                      code_helper = ERROR_MARK);
> >>>  static bool ia64_cannot_force_const_mem (machine_mode, rtx);
> >>>  static const char *ia64_mangle_type (const_tree);
> >>>  static const char *ia64_invalid_conversion (const_tree, const_tree);
> >>> @@ -1024,8 +1025,8 @@ ia64_legitimate_address_disp (const_rtx reg, const_rtx disp, bool strict)
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>> -                          rtx x, bool strict)
> >>> +ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> >>> +                          bool strict, code_helper)
> >>>  {
> >>>    if (ia64_legitimate_address_reg (x, strict))
> >>>      return true;
> >>> diff --git a/gcc/config/iq2000/iq2000.cc b/gcc/config/iq2000/iq2000.cc
> >>> index 733fecac2b7..54404e8d05a 100644
> >>> --- a/gcc/config/iq2000/iq2000.cc
> >>> +++ b/gcc/config/iq2000/iq2000.cc
> >>> @@ -170,7 +170,8 @@ static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
> >>>  static unsigned int iq2000_function_arg_boundary (machine_mode,
> >>>                                                   const_tree);
> >>>  static void iq2000_va_start          (tree, rtx);
> >>> -static bool iq2000_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool iq2000_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                        code_helper = ERROR_MARK);
> >>>  static bool iq2000_can_eliminate      (const int, const int);
> >>>  static void iq2000_asm_trampoline_template (FILE *);
> >>>  static void iq2000_trampoline_init    (rtx, tree, rtx);
> >>> @@ -304,7 +305,8 @@ iq2000_reg_mode_ok_for_base_p (rtx reg,
> >>>     function is called during reload.  */
> >>>
> >>>  bool
> >>> -iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict)
> >>> +iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict,
> >>> +                            code_helper)
> >>>  {
> >>>    if (TARGET_DEBUG_A_MODE)
> >>>      {
> >>> diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc
> >>> index 6528358009d..9d65d66719c 100644
> >>> --- a/gcc/config/lm32/lm32.cc
> >>> +++ b/gcc/config/lm32/lm32.cc
> >>> @@ -69,8 +69,8 @@ static void lm32_setup_incoming_varargs (cumulative_args_t cum,
> >>>  static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
> >>>                             int *total, bool speed);
> >>>  static bool lm32_can_eliminate (const int, const int);
> >>> -static bool
> >>> -lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
> >>> +static bool lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                                      code_helper = ERROR_MARK);
> >>>  static HOST_WIDE_INT lm32_compute_frame_size (int size);
> >>>  static void lm32_option_override (void);
> >>>  static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
> >>> @@ -1192,7 +1192,8 @@ lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
> >>> +lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> >>> +                          bool strict, code_helper)
> >>>  {
> >>>     /* (rM) */
> >>>    if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
> >>> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> >>> index 5b8b93eb24b..86d58784113 100644
> >>> --- a/gcc/config/loongarch/loongarch.cc
> >>> +++ b/gcc/config/loongarch/loongarch.cc
> >>> @@ -2096,7 +2096,8 @@ loongarch_classify_address (struct loongarch_address_info *info, rtx x,
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> >>> +                               code_helper = ERROR_MARK)
> >>>  {
> >>>    struct loongarch_address_info addr;
> >>>
> >>> diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
> >>> index 65971d62990..e18efc3c7f2 100644
> >>> --- a/gcc/config/m32c/m32c.cc
> >>> +++ b/gcc/config/m32c/m32c.cc
> >>> @@ -75,8 +75,11 @@ static int m32c_comp_type_attributes (const_tree, const_tree);
> >>>  static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
> >>>  static struct machine_function *m32c_init_machine_status (void);
> >>>  static void m32c_insert_attributes (tree, tree *);
> >>> -static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
> >>> -static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
> >>> +static bool m32c_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                      code_helper = ERROR_MARK);
> >>> +static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                                 addr_space_t,
> >>> +                                                 code_helper = ERROR_MARK);
> >>>  static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
> >>>  static bool m32c_pass_by_reference (cumulative_args_t,
> >>>                                     const function_arg_info &);
> >>> @@ -1648,7 +1651,7 @@ m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
> >>>  #undef TARGET_LEGITIMATE_ADDRESS_P
> >>>  #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
> >>>  bool
> >>> -m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    int mode_adjust;
> >>>    if (CONSTANT_P (x))
> >>> @@ -1966,8 +1969,8 @@ m32c_addr_space_address_mode (addr_space_t addrspace)
> >>>  #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
> >>>    m32c_addr_space_legitimate_address_p
> >>>  static bool
> >>> -m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
> >>> -                                     bool strict, addr_space_t as)
> >>> +m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                                     addr_space_t as, code_helper ch)
> >>>  {
> >>>    if (as == ADDR_SPACE_FAR)
> >>>      {
> >>> @@ -2048,7 +2051,7 @@ m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
> >>>    else if (as != ADDR_SPACE_GENERIC)
> >>>      gcc_unreachable ();
> >>>
> >>> -  return m32c_legitimate_address_p (mode, x, strict);
> >>> +  return m32c_legitimate_address_p (mode, x, strict, ch);
> >>>  }
> >>>
> >>>  /* Like m32c_legitimate_address, except with named address support.  */
> >>> diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
> >>> index 155a248459b..63a1798da3d 100644
> >>> --- a/gcc/config/m32r/m32r.cc
> >>> +++ b/gcc/config/m32r/m32r.cc
> >>> @@ -66,7 +66,8 @@ static void  m32r_option_override (void);
> >>>  static void  init_reg_tables (void);
> >>>  static void  block_move_call (rtx, rtx, rtx);
> >>>  static int   m32r_is_insn (rtx);
> >>> -static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool  m32r_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                       code_helper = ERROR_MARK);
> >>>  static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
> >>>  static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
> >>>  static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
> >>> @@ -2913,7 +2914,7 @@ m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
> >>>  /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    if (m32r_rtx_ok_for_base_p (x, strict)
> >>>        || m32r_legitimate_offset_addres_p (mode, x, strict)
> >>> diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
> >>> index 03db2b6a936..145a92d8710 100644
> >>> --- a/gcc/config/m68k/m68k.cc
> >>> +++ b/gcc/config/m68k/m68k.cc
> >>> @@ -158,7 +158,8 @@ static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);
> >>>
> >>>  static bool m68k_can_eliminate (const int, const int);
> >>>  static void m68k_conditional_register_usage (void);
> >>> -static bool m68k_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool m68k_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                      code_helper = ERROR_MARK);
> >>>  static void m68k_option_override (void);
> >>>  static void m68k_override_options_after_change (void);
> >>>  static rtx find_addr_reg (rtx);
> >>> @@ -2311,7 +2312,7 @@ m68k_decompose_address (machine_mode mode, rtx x,
> >>>     STRICT_P says whether strict checking is needed.  */
> >>>
> >>>  bool
> >>> -m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
> >>>  {
> >>>    struct m68k_address address;
> >>>
> >>> diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
> >>> index e933b03cdff..6f1d7af7937 100644
> >>> --- a/gcc/config/mcore/mcore.cc
> >>> +++ b/gcc/config/mcore/mcore.cc
> >>> @@ -144,7 +144,8 @@ static bool       mcore_warn_func_return        (tree);
> >>>  static void       mcore_option_override                (void);
> >>>  static bool       mcore_legitimate_constant_p   (machine_mode, rtx);
> >>>  static bool      mcore_legitimate_address_p    (machine_mode, rtx, bool,
> >>> -                                                addr_space_t);
> >>> +                                                addr_space_t,
> >>> +                                                code_helper = ERROR_MARK);
> >>>  static bool      mcore_hard_regno_mode_ok      (unsigned int, machine_mode);
> >>>  static bool      mcore_modes_tieable_p         (machine_mode, machine_mode);
> >>>
> >>>
> >>> @@ -3249,7 +3250,7 @@ mcore_legitimate_index_p (machine_mode mode, const_rtx op)
> >>>
> >>>  static bool
> >>>  mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> >>> -                           addr_space_t as)
> >>> +                           addr_space_t as, code_helper)
> >>>  {
> >>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
> >>>
> >>> diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
> >>> index 31a6515176b..93fd8d17e3c 100644
> >>> --- a/gcc/config/microblaze/microblaze-protos.h
> >>> +++ b/gcc/config/microblaze/microblaze-protos.h
> >>> @@ -22,6 +22,8 @@
> >>>  #ifndef GCC_MICROBLAZE_PROTOS_H
> >>>  #define GCC_MICROBLAZE_PROTOS_H
> >>>
> >>> +#include "tree.h"  /* For ERROR_MARK.  */
> >>> +
> >>>  #ifdef RTX_CODE
> >>>  extern int pic_address_needs_scratch (rtx);
> >>>  extern bool microblaze_constant_address_p (rtx x);
> >>> @@ -40,7 +42,8 @@ extern int microblaze_can_use_return_insn (void);
> >>>  extern void print_operand (FILE *, rtx, int);
> >>>  extern void print_operand_address (FILE *, rtx);
> >>>  extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
> >>> -extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool);
> >>> +extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                            code_helper = ERROR_MARK);
> >>>  extern int microblaze_is_interrupt_variant (void);
> >>>  extern int microblaze_is_break_handler (void);
> >>>  extern int microblaze_break_function_p (tree func);
> >>> diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
> >>> index cbabf1af712..c9f6c4198cf 100644
> >>> --- a/gcc/config/microblaze/microblaze.cc
> >>> +++ b/gcc/config/microblaze/microblaze.cc
> >>> @@ -919,7 +919,8 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
> >>>     is called during reload.  */
> >>>
> >>>  bool
> >>> -microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                                code_helper)
> >>>  {
> >>>    struct microblaze_address_info addr;
> >>>
> >>> diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
> >>> index 999127a72e7..3497d42cdf3 100644
> >>> --- a/gcc/config/mips/mips.cc
> >>> +++ b/gcc/config/mips/mips.cc
> >>> @@ -2691,7 +2691,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    struct mips_address_info addr;
> >>>
> >>> diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc
> >>> index 1d36306fdb6..34743092749 100644
> >>> --- a/gcc/config/mmix/mmix.cc
> >>> +++ b/gcc/config/mmix/mmix.cc
> >>> @@ -132,7 +132,8 @@ static void mmix_target_asm_function_end_prologue (FILE *);
> >>>  static void mmix_target_asm_function_epilogue (FILE *);
> >>>  static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
> >>>  static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
> >>> -static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool mmix_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                      code_helper = ERROR_MARK);
> >>>  static bool mmix_legitimate_constant_p (machine_mode, rtx);
> >>>  static void mmix_reorg (void);
> >>>  static void mmix_asm_output_mi_thunk
> >>> @@ -1109,7 +1110,8 @@ mmix_constant_address_p (rtx x)
> >>>  bool
> >>>  mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>                            rtx x,
> >>> -                          bool strict_checking)
> >>> +                          bool strict_checking,
> >>> +                          code_helper)
> >>>  {
> >>>  #define MMIX_REG_OK(X)                                                 \
> >>>    ((strict_checking                                                    \
> >>> diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
> >>> index a8b01a543cc..cd1de1b2d83 100644
> >>> --- a/gcc/config/mn10300/mn10300.cc
> >>> +++ b/gcc/config/mn10300/mn10300.cc
> >>> @@ -1932,7 +1932,8 @@ mn10300_legitimate_pic_operand_p (rtx x)
> >>>     function record_unscaled_index_insn_codes.  */
> >>>
> >>>  static bool
> >>> -mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                             code_helper = ERROR_MARK)
> >>>  {
> >>>    rtx base, index;
> >>>
> >>> diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc
> >>> index 2132b6e48a3..209d03077ea 100644
> >>> --- a/gcc/config/moxie/moxie.cc
> >>> +++ b/gcc/config/moxie/moxie.cc
> >>> @@ -577,7 +577,8 @@ moxie_reg_ok_for_base_p (const_rtx reg, bool strict_p)
> >>>  static bool
> >>>  moxie_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>                             rtx x, bool strict_p,
> >>> -                           addr_space_t as)
> >>> +                           addr_space_t as,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
> >>>
> >>> diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
> >>> index 6f9c56187ee..061a9c77961 100644
> >>> --- a/gcc/config/msp430/msp430.cc
> >>> +++ b/gcc/config/msp430/msp430.cc
> >>> @@ -927,7 +927,8 @@ reg_ok_for_addr (rtx r, bool strict)
> >>>  bool
> >>>  msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>                              rtx x ATTRIBUTE_UNUSED,
> >>> -                            bool strict ATTRIBUTE_UNUSED)
> >>> +                            bool strict ATTRIBUTE_UNUSED,
> >>> +                            code_helper = ERROR_MARK)
> >>>  {
> >>>    switch (GET_CODE (x))
> >>>      {
> >>> @@ -980,9 +981,10 @@ bool
> >>>  msp430_addr_space_legitimate_address_p (machine_mode mode,
> >>>                                         rtx x,
> >>>                                         bool strict,
> >>> -                                       addr_space_t as ATTRIBUTE_UNUSED)
> >>> +                                       addr_space_t as ATTRIBUTE_UNUSED,
> >>> +                                       code_helper ch = ERROR_MARK)
> >>>  {
> >>> -  return msp430_legitimate_address_p (mode, x, strict);
> >>> +  return msp430_legitimate_address_p (mode, x, strict, ch);
> >>>  }
> >>>
> >>>  #undef  TARGET_ASM_INTEGER
> >>> diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
> >>> index 91ed91d914f..1f8de2a514a 100644
> >>> --- a/gcc/config/nds32/nds32.cc
> >>> +++ b/gcc/config/nds32/nds32.cc
> >>> @@ -2565,7 +2565,8 @@ nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
> >>>  /* Addressing Modes.  */
> >>>
> >>>  static bool
> >>> -nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
> >>>      {
> >>> diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc
> >>> index 936eb34ace4..b435d7475f9 100644
> >>> --- a/gcc/config/nios2/nios2.cc
> >>> +++ b/gcc/config/nios2/nios2.cc
> >>> @@ -2141,8 +2141,9 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
> >>>
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>  static bool
> >>> -nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>> -                           rtx operand, bool strict_p)
> >>> +nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx operand,
> >>> +                           bool strict_p,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    switch (GET_CODE (operand))
> >>>      {
> >>> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
> >>> index e3b0304d537..49291d71a74 100644
> >>> --- a/gcc/config/nvptx/nvptx.cc
> >>> +++ b/gcc/config/nvptx/nvptx.cc
> >>> @@ -2202,7 +2202,7 @@ nvptx_gen_shared_bcast (rtx reg, propagate_mask pm, unsigned rep,
> >>>  /* Returns true if X is a valid address for use in a memory reference.  */
> >>>
> >>>  static bool
> >>> -nvptx_legitimate_address_p (machine_mode, rtx x, bool)
> >>> +nvptx_legitimate_address_p (machine_mode, rtx x, bool, code_helper)
> >>>  {
> >>>    enum rtx_code code = GET_CODE (x);
> >>>
> >>> diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc
> >>> index ec30bc8156c..5eeed0e91be 100644
> >>> --- a/gcc/config/or1k/or1k.cc
> >>> +++ b/gcc/config/or1k/or1k.cc
> >>> @@ -575,7 +575,8 @@ or1k_initial_elimination_offset (int from, int to)
> >>>     Returns true if X is a legitimate address RTX on OpenRISC.  */
> >>>
> >>>  static bool
> >>> -or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p)
> >>> +or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    rtx base, addend;
> >>>
> >>> diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
> >>> index 0fa9e5fd632..2e906cff7ff 100644
> >>> --- a/gcc/config/pa/pa.cc
> >>> +++ b/gcc/config/pa/pa.cc
> >>> @@ -196,7 +196,8 @@ static section *pa_function_section (tree, enum node_frequency, bool, bool);
> >>>  static bool pa_cannot_force_const_mem (machine_mode, rtx);
> >>>  static bool pa_legitimate_constant_p (machine_mode, rtx);
> >>>  static unsigned int pa_section_type_flags (tree, const char *, int);
> >>> -static bool pa_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool pa_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                    code_helper = ERROR_MARK);
> >>>  static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
> >>>  static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
> >>>  static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
> >>> @@ -10787,7 +10788,7 @@ pa_section_type_flags (tree decl, const char *name, int reloc)
> >>>     output as REG+SMALLINT.  */
> >>>
> >>>  static bool
> >>> -pa_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    if ((REG_P (x)
> >>>         && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
> >>> diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
> >>> index f6dd841f184..321837935c8 100644
> >>> --- a/gcc/config/pdp11/pdp11.cc
> >>> +++ b/gcc/config/pdp11/pdp11.cc
> >>> @@ -1615,8 +1615,8 @@ pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
> >>>  */
> >>>
> >>>  static bool
> >>> -pdp11_legitimate_address_p (machine_mode mode,
> >>> -                           rtx operand, bool strict)
> >>> +pdp11_legitimate_address_p (machine_mode mode, rtx operand, bool strict,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>      rtx xfoob;
> >>>
> >>> diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
> >>> index e855bbb8195..6e8112be64a 100644
> >>> --- a/gcc/config/pru/pru.cc
> >>> +++ b/gcc/config/pru/pru.cc
> >>> @@ -1466,7 +1466,8 @@ int pru_symref2ioregno (rtx op)
> >>>  /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
> >>>  static bool
> >>>  pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
> >>> -                                    bool strict_p, addr_space_t as)
> >>> +                                    bool strict_p, addr_space_t as,
> >>> +                                    code_helper = ERROR_MARK)
> >>>  {
> >>>    if (as == ADDR_SPACE_REGIO)
> >>>      {
> >>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> >>> index 280aa0b33b9..31e2b9bccc2 100644
> >>> --- a/gcc/config/riscv/riscv.cc
> >>> +++ b/gcc/config/riscv/riscv.cc
> >>> @@ -1163,7 +1163,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
> >>>  /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
> >>>
> >>>  static bool
> >>> -riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
> >>> +riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> >>> +                           code_helper = ERROR_MARK)
> >>>  {
> >>>    struct riscv_address_info addr;
> >>>
> >>> diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
> >>> index 7d474ffc130..813459ad8b6 100644
> >>> --- a/gcc/config/rl78/rl78-protos.h
> >>> +++ b/gcc/config/rl78/rl78-protos.h
> >>> @@ -18,6 +18,9 @@
> >>>     along with GCC; see the file COPYING3.  If not see
> >>>     <http://www.gnu.org/licenses/>.  */
> >>>
> >>>
> >>> +
> >>> +#include "tree.h"  /* For ERROR_MARK.  */
> >>> +
> >>>  const char *    rl78_addsi3_internal (rtx *, unsigned int);
> >>>  void           rl78_emit_eh_epilogue (rtx);
> >>>  void           rl78_expand_compare (rtx *);
> >>> @@ -33,7 +36,8 @@ int           rl78_far_p (rtx x);
> >>>  bool           rl78_hl_b_c_addr_p (rtx);
> >>>  int            rl78_initial_elimination_offset (int, int);
> >>>  bool           rl78_as_legitimate_address (machine_mode, rtx,
> >>> -                                           bool, addr_space_t);
> >>> +                                           bool, addr_space_t,
> >>> +                                           code_helper = ERROR_MARK);
> >>>  int            rl78_legitimize_reload_address (rtx *, machine_mode, int,int, int);
> >>>  enum reg_class rl78_mode_code_base_reg_class (machine_mode, addr_space_t, int, int);
> >>>  bool           rl78_peep_movhi_p (rtx *);
> >>> diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
> >>> index 9083096c4ae..0cbd6bf780a 100644
> >>> --- a/gcc/config/rl78/rl78.cc
> >>> +++ b/gcc/config/rl78/rl78.cc
> >>> @@ -1143,7 +1143,8 @@ rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE
> >>>
> >>>  bool
> >>>  rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> >>> -                           bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
> >>> +                           bool strict ATTRIBUTE_UNUSED,
> >>> +                           addr_space_t as ATTRIBUTE_UNUSED, code_helper)
> >>>  {
> >>>    rtx base, index, addend;
> >>>    bool is_far_addr = false;
> >>> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
> >>> index 546c353029b..efc54528b23 100644
> >>> --- a/gcc/config/rs6000/rs6000.cc
> >>> +++ b/gcc/config/rs6000/rs6000.cc
> >>> @@ -1109,7 +1109,8 @@ struct processor_costs ppca2_cost = {
> >>>  static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);
> >>>
> >>>
> >>>
> >>> -static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                              code_helper = ERROR_MARK);
> >>>  static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
> >>>  static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
> >>>  static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
> >>> @@ -9854,7 +9855,8 @@ use_toc_relative_ref (rtx sym, machine_mode mode)
> >>>     because adjacent memory cells are accessed by adding word-sized offsets
> >>>     during assembly output.  */
> >>>  static bool
> >>> -rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
> >>> +rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
> >>> +                            code_helper = ERROR_MARK)
> >>>  {
> >>>    bool reg_offset_p = reg_offset_addressing_ok_p (mode);
> >>>    bool quad_offset_p = mode_supports_dq_form (mode);
> >>> @@ -9957,10 +9959,10 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
> >>>
> >>>  /* Debug version of rs6000_legitimate_address_p.  */
> >>>  static bool
> >>> -rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
> >>> -                                  bool reg_ok_strict)
> >>> +rs6000_debug_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
> >>> +                                  code_helper ch)
> >>>  {
> >>> -  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
> >>> +  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict, ch);
> >>>    fprintf (stderr,
> >>>            "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
> >>>            "strict = %d, reload = %s, code = %s\n",
> >>> diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
> >>> index 726b00a3193..245c6a4413d 100644
> >>> --- a/gcc/config/rx/rx.cc
> >>> +++ b/gcc/config/rx/rx.cc
> >>> @@ -179,7 +179,8 @@ rx_small_data_operand (rtx op)
> >>>
> >>>  static bool
> >>>  rx_is_legitimate_address (machine_mode mode, rtx x,
> >>> -                         bool strict ATTRIBUTE_UNUSED)
> >>> +                         bool strict ATTRIBUTE_UNUSED,
> >>> +                         code_helper = ERROR_MARK)
> >>>  {
> >>>    if (RTX_OK_FOR_BASE (x, strict))
> >>>      /* Register Indirect.  */
> >>> diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
> >>> index 9284477396d..5b8826162a9 100644
> >>> --- a/gcc/config/s390/s390.cc
> >>> +++ b/gcc/config/s390/s390.cc
> >>> @@ -4914,7 +4914,8 @@ s390_expand_plus_operand (rtx target, rtx src,
> >>>     STRICT specifies whether strict register checking applies.  */
> >>>
> >>>  static bool
> >>> -s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> >>> +s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    struct s390_address ad;
> >>>
> >>> diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
> >>> index 938f7aa6281..294faf7c0c3 100644
> >>> --- a/gcc/config/sh/sh.cc
> >>> +++ b/gcc/config/sh/sh.cc
> >>> @@ -266,7 +266,8 @@ static reg_class_t sh_preferred_reload_class (rtx, reg_class_t);
> >>>  static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t,
> >>>                                          machine_mode,
> >>>                                          struct secondary_reload_info *);
> >>> -static bool sh_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool sh_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                    code_helper = ERROR_MARK);
> >>>  static rtx sh_legitimize_address (rtx, rtx, machine_mode);
> >>>  static rtx sh_delegitimize_address (rtx);
> >>>  static bool sh_cannot_substitute_mem_equiv_p (rtx);
> >>> @@ -9038,7 +9039,7 @@ sh_legitimate_index_p (machine_mode mode, rtx op, bool consider_sh2a,
> >>>           GBR
> >>>           GBR+disp  */
> >>>  static bool
> >>> -sh_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +sh_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    if (REG_P (x) && REGNO (x) == GBR_REG)
> >>>      return true;
> >>> diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
> >>> index 0aade05faf5..82e57952414 100644
> >>> --- a/gcc/config/sparc/sparc.cc
> >>> +++ b/gcc/config/sparc/sparc.cc
> >>> @@ -607,7 +607,8 @@ static void sparc_emit_set_const64 (rtx, rtx);
> >>>  static void sparc_output_addr_vec (rtx);
> >>>  static void sparc_output_addr_diff_vec (rtx);
> >>>  static void sparc_output_deferred_case_vectors (void);
> >>> -static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool sparc_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                       code_helper = ERROR_MARK);
> >>>  static bool sparc_legitimate_constant_p (machine_mode, rtx);
> >>>  static rtx sparc_builtin_saveregs (void);
> >>>  static int epilogue_renumber (rtx *, int);
> >>> @@ -4529,7 +4530,8 @@ sparc_pic_register_p (rtx x)
> >>>     ordinarily.  This changes a bit when generating PIC.  */
> >>>
> >>>  static bool
> >>> -sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> >>> +sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> >>> +                           code_helper)
> >>>  {
> >>>    rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
> >>>
> >>> diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
> >>> index f90d88eba6f..27ae023bcb3 100644
> >>> --- a/gcc/config/stormy16/stormy16-protos.h
> >>> +++ b/gcc/config/stormy16/stormy16-protos.h
> >>> @@ -18,7 +18,7 @@ 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/>.  */
> >>>
> >>> -
> >>> +#include "tree.h"  /* For ERROR_MARK.  */
> >>>
> >>>  extern struct xstormy16_stack_layout xstormy16_compute_stack_layout (void);
> >>>  extern void xstormy16_expand_prologue (void);
> >>> @@ -65,6 +65,7 @@ extern const char * xstormy16_output_shift (machine_mode, enum rtx_code,
> >>>                                             rtx, rtx, rtx);
> >>>  extern bool  xstormy16_below100_symbol (rtx, machine_mode);
> >>>  extern bool  xstormy16_splittable_below100_operand (rtx, machine_mode);
> >>> -extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool);
> >>> +extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                           code_helper = ERROR_MARK);
> >>>  #endif
> >>>
> >>> diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
> >>> index cd453c2a2f7..10887153906 100644
> >>> --- a/gcc/config/stormy16/stormy16.cc
> >>> +++ b/gcc/config/stormy16/stormy16.cc
> >>> @@ -795,8 +795,8 @@ xstormy16_expand_andqi3 (rtx *operands)
> >>>    && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))
> >>>
> >>>  bool
> >>> -xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>> -                               rtx x, bool strict)
> >>> +xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
> >>> +                               bool strict, code_helper)
> >>>  {
> >>>    if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))
> >>>      return true;
> >>> diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
> >>> index 0fb72716b17..416c2841a5c 100644
> >>> --- a/gcc/config/v850/v850.cc
> >>> +++ b/gcc/config/v850/v850.cc
> >>> @@ -3030,7 +3030,8 @@ v850_rtx_ok_for_base_p (const_rtx x, bool strict_p)
> >>>
> >>>  static bool
> >>>  v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
> >>> -                          addr_space_t as ATTRIBUTE_UNUSED)
> >>> +                          addr_space_t as ATTRIBUTE_UNUSED,
> >>> +                          code_helper = ERROR_MARK)
> >>>  {
> >>>    gcc_assert (ADDR_SPACE_GENERIC_P (as));
> >>>
> >>> diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
> >>> index 82a176d3bfc..df9478d881a 100644
> >>> --- a/gcc/config/vax/vax.cc
> >>> +++ b/gcc/config/vax/vax.cc
> >>> @@ -46,7 +46,8 @@ along with GCC; see the file COPYING3.  If not see
> >>>  #include "target-def.h"
> >>>
> >>>  static void vax_option_override (void);
> >>> -static bool vax_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool vax_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                     code_helper = ERROR_MARK);
> >>>  static void vax_file_start (void);
> >>>  static void vax_init_libfuncs (void);
> >>>  static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
> >>> @@ -1902,7 +1903,7 @@ indexable_address_p (rtx xfoo0, rtx xfoo1, machine_mode mode, bool strict)
> >>>     The MODE argument is the machine mode for the MEM expression
> >>>     that wants to use this address.  */
> >>>  bool
> >>> -vax_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +vax_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    rtx xfoo0, xfoo1;
> >>>
> >>> diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
> >>> index 48a61744db6..5fadbc80be0 100644
> >>> --- a/gcc/config/visium/visium.cc
> >>> +++ b/gcc/config/visium/visium.cc
> >>> @@ -194,7 +194,8 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
> >>>
> >>>  static bool visium_legitimate_constant_p (machine_mode, rtx);
> >>>
> >>> -static bool visium_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool visium_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                        code_helper = ERROR_MARK);
> >>>
> >>>  static bool visium_print_operand_punct_valid_p (unsigned char);
> >>>  static void visium_print_operand (FILE *, rtx, int);
> >>> @@ -1818,7 +1819,7 @@ rtx_ok_for_offset_p (machine_mode mode, rtx op)
> >>>     kind of register is required.  */
> >>>
> >>>  static bool
> >>> -visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
> >>> +visium_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
> >>>  {
> >>>    rtx base;
> >>>    unsigned int regno;
> >>> diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
> >>> index dd35e63c094..897cf7363f4 100644
> >>> --- a/gcc/config/xtensa/xtensa.cc
> >>> +++ b/gcc/config/xtensa/xtensa.cc
> >>> @@ -123,7 +123,8 @@ static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
> >>>  static bool xtensa_return_in_msb (const_tree);
> >>>  static void printx (FILE *, signed int);
> >>>  static rtx xtensa_builtin_saveregs (void);
> >>> -static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
> >>> +static bool xtensa_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                        code_helper = ERROR_MARK);
> >>>  static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
> >>>                                                         int) ATTRIBUTE_UNUSED;
> >>>  static section *xtensa_select_rtx_section (machine_mode, rtx,
> >>> @@ -2296,9 +2297,9 @@ xtensa_emit_sibcall (int callop, rtx *operands)
> >>>    return result;
> >>>  }
> >>>
> >>> -
> >>>  bool
> >>> -xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
> >>> +xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
> >>> +                            code_helper)
> >>>  {
> >>>    /* Allow constant pool addresses.  */
> >>>    if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
> >>> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> >>> index ca8837cef67..3e9a2f19e27 100644
> >>> --- a/gcc/coretypes.h
> >>> +++ b/gcc/coretypes.h
> >>> @@ -99,6 +99,7 @@ typedef const union tree_node *const_tree;
> >>>  struct gimple;
> >>>  typedef gimple *gimple_seq;
> >>>  struct gimple_stmt_iterator;
> >>> +class code_helper;
> >>>
> >>>  /* Forward decls for leaf gimple subclasses (for individual gimple codes).
> >>>     Keep this in the same order as the corresponding codes in gimple.def.  */
> >>> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> >>> index 95ba56e05ae..e4d0cc43f41 100644
> >>> --- a/gcc/doc/tm.texi
> >>> +++ b/gcc/doc/tm.texi
> >>> @@ -5853,9 +5853,16 @@ the maximum number that @code{TARGET_LEGITIMATE_ADDRESS_P} would ever
> >>>  accept.
> >>>  @end defmac
> >>>
> >>> -@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict})
> >>> +@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict}, code_helper @var{ch})
> >>>  A function that returns whether @var{x} (an RTX) is a legitimate memory
> >>>  address on the target machine for a memory operand of mode @var{mode}.
> >>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to
> >>> +determine if it is valid to use @var{x} as a memory operand for RTX insn
> >>> +which is generated for the given code_helper @var{ch}.  For example,
> >>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying
> >>> +hardware instructions support fewer addressing modes than what are for the
> >>> +normal vector load and store, then with this @var{ch} target can know the
> >>> +actual use context and return more exact result.
> >>>
> >>>  Legitimate addresses are defined in two variants: a strict variant and a
> >>>  non-strict one.  The @var{strict} parameter chooses which variant is
> >>> @@ -10992,11 +10999,12 @@ version of this hook returns true for the modes returned by either the
> >>>  target hooks for the given address space.
> >>>  @end deftypefn
> >>>
> >>> -@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
> >>> +@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as}, code_helper @var{ch})
> >>>  Define this to return true if @var{exp} is a valid address for mode
> >>> -@var{mode} in the named address space @var{as}.  The @var{strict}
> >>> -parameter says whether strict addressing is in effect after reload has
> >>> -finished.  This target hook is the same as the
> >>> +@var{mode} in the named address space @var{as} with the use context
> >>> +@var{ch}.  The @var{strict} parameter says whether strict addressing
> >>> +is in effect after reload has finished.  The @var{ch} indicates what
> >>> +context @var{exp} will be used for.  This target hook is the same as the
> >>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes
> >>>  explicit named address space support.
> >>>  @end deftypefn
> >>> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> >>> index 4dc2d70c402..cb9cbac5bb3 100644
> >>> --- a/gcc/lra-constraints.cc
> >>> +++ b/gcc/lra-constraints.cc
> >>> @@ -336,7 +336,8 @@ valid_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>   win:
> >>>    return 1;
> >>>  #else
> >>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
> >>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
> >>> +                                                 ERROR_MARK);
> >>>  #endif
> >>>  }
> >>>
> >>> diff --git a/gcc/recog.cc b/gcc/recog.cc
> >>> index 37432087812..692c258def6 100644
> >>> --- a/gcc/recog.cc
> >>> +++ b/gcc/recog.cc
> >>> @@ -1813,7 +1813,8 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>   win:
> >>>    return true;
> >>>  #else
> >>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
> >>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
> >>> +                                                 ERROR_MARK);
> >>>  #endif
> >>>  }
> >>>
> >>> diff --git a/gcc/reload.cc b/gcc/reload.cc
> >>> index d079bc120d5..0be21f7b61e 100644
> >>> --- a/gcc/reload.cc
> >>> +++ b/gcc/reload.cc
> >>> @@ -2172,7 +2172,8 @@ strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>   win:
> >>>    return true;
> >>>  #else
> >>> -  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
> >>> +  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as,
> >>> +                                                 ERROR_MARK);
> >>>  #endif
> >>>  }
> >>>
> >>>
> >>> diff --git a/gcc/target.def b/gcc/target.def
> >>> index 7d684296c17..a500aeb6714 100644
> >>> --- a/gcc/target.def
> >>> +++ b/gcc/target.def
> >>> @@ -2897,6 +2897,13 @@ DEFHOOK
> >>>  (legitimate_address_p,
> >>>   "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
> >>>  address on the target machine for a memory operand of mode @var{mode}.\n\
> >>> +If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to\n\
> >>> +determine if it is valid to use @var{x} as a memory operand for RTX insn\n\
> >>> +which is generated for the given code_helper @var{ch}.  For example,\n\
> >>> +assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying\n\
> >>> +hardware instructions support fewer addressing modes than what are for the\n\
> >>> +normal vector load and store, then with this @var{ch} target can know the\n\
> >>> +actual use context and return more exact result.\n\
> >>>  \n\
> >>>  Legitimate addresses are defined in two variants: a strict variant and a\n\
> >>>  non-strict one.  The @var{strict} parameter chooses which variant is\n\
> >>> @@ -2957,7 +2964,7 @@ that case and the non-strict variant otherwise.\n\
> >>>  \n\
> >>>  Using the hook is usually simpler because it limits the number of\n\
> >>>  files that are recompiled when changes are made.",
> >>> - bool, (machine_mode mode, rtx x, bool strict),
> >>> + bool, (machine_mode mode, rtx x, bool strict, code_helper ch),
> >>>   default_legitimate_address_p)
> >>>
> >>>  /* True if the given constant can be put into an object_block.  */
> >>> @@ -3348,12 +3355,13 @@ target hooks for the given address space.",
> >>>  DEFHOOK
> >>>  (legitimate_address_p,
> >>>   "Define this to return true if @var{exp} is a valid address for mode\n\
> >>> -@var{mode} in the named address space @var{as}.  The @var{strict}\n\
> >>> -parameter says whether strict addressing is in effect after reload has\n\
> >>> -finished.  This target hook is the same as the\n\
> >>> +@var{mode} in the named address space @var{as} with the use context\n\
> >>> +@var{ch}.  The @var{strict} parameter says whether strict addressing\n\
> >>> +is in effect after reload has finished.  The @var{ch} indicates what\n\
> >>> +context @var{exp} will be used for.  This target hook is the same as the\n\
> >>>  @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
> >>>  explicit named address space support.",
> >>> - bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
> >>> + bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as, code_helper ch),
> >>>   default_addr_space_legitimate_address_p)
> >>>
> >>>  /* Return an updated address to convert an invalid pointer to a named
> >>> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> >>> index e190369f87a..4ef53267e50 100644
> >>> --- a/gcc/targhooks.cc
> >>> +++ b/gcc/targhooks.cc
> >>> @@ -99,7 +99,8 @@ along with GCC; see the file COPYING3.  If not see
> >>>  bool
> >>>  default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
> >>>                               rtx addr ATTRIBUTE_UNUSED,
> >>> -                             bool strict ATTRIBUTE_UNUSED)
> >>> +                             bool strict ATTRIBUTE_UNUSED,
> >>> +                             code_helper ATTRIBUTE_UNUSED)
> >>>  {
> >>>  #ifdef GO_IF_LEGITIMATE_ADDRESS
> >>>    /* Defer to the old implementation using a goto.  */
> >>> @@ -1680,9 +1681,10 @@ target_default_pointer_address_modes_p (void)
> >>>  bool
> >>>  default_addr_space_legitimate_address_p (machine_mode mode, rtx mem,
> >>>                                          bool strict,
> >>> -                                        addr_space_t as ATTRIBUTE_UNUSED)
> >>> +                                        addr_space_t as ATTRIBUTE_UNUSED,
> >>> +                                        code_helper code)
> >>>  {
> >>> -  return targetm.legitimate_address_p (mode, mem, strict);
> >>> +  return targetm.legitimate_address_p (mode, mem, strict, code);
> >>>  }
> >>>
> >>>  /* Named address space version of LEGITIMIZE_ADDRESS.
> >>> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> >>> index 1a0db8dddd5..761225512b7 100644
> >>> --- a/gcc/targhooks.h
> >>> +++ b/gcc/targhooks.h
> >>> @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3.  If not see
> >>>  #ifndef GCC_TARGHOOKS_H
> >>>  #define GCC_TARGHOOKS_H
> >>>
> >>> -extern bool default_legitimate_address_p (machine_mode, rtx, bool);
> >>> +extern bool default_legitimate_address_p (machine_mode, rtx, bool, code_helper);
> >>>
> >>>  extern void default_external_libcall (rtx);
> >>>  extern rtx default_legitimize_address (rtx, rtx, machine_mode);
> >>> @@ -202,8 +202,8 @@ extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
> >>>  extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
> >>>  extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
> >>>                                                    addr_space_t);
> >>> -extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
> >>> -                                                    bool, addr_space_t);
> >>> +extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
> >>> +                                                    addr_space_t, code_helper);
> >>>  extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
> >>>                                                   addr_space_t);
> >>>  extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
> >>> --
> >>> 2.39.3
>
>
  

Patch

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 644ebdebc0e..2dfb811ec4f 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -11182,7 +11182,8 @@  aarch64_classify_symbolic_expression (rtx x)
 /* Return TRUE if X is a legitimate address for accessing memory in
    mode MODE.  */
 static bool
-aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p)
+aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p,
+				   code_helper = ERROR_MARK)
 {
   struct aarch64_address_info addr;

diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
index 360b50e20d4..0367f117c21 100644
--- a/gcc/config/alpha/alpha.cc
+++ b/gcc/config/alpha/alpha.cc
@@ -844,7 +844,8 @@  alpha_linkage_symbol_p (const char *symname)
    low-order three bits; this is an "unaligned" access.  */

 static bool
-alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+alpha_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			    code_helper = ERROR_MARK)
 {
   /* If this is an ldq_u type address, discard the outer AND.  */
   if (mode == DImode
diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
index fef8a504f77..266ba8b00bb 100644
--- a/gcc/config/arc/arc.cc
+++ b/gcc/config/arc/arc.cc
@@ -6715,7 +6715,8 @@  arc_legitimate_constant_p (machine_mode mode, rtx x)
 }

 static bool
-arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+arc_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			  code_helper = ERROR_MARK)
 {
   if (RTX_OK_FOR_BASE_P (x, strict))
      return true;
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 7d73c66a15d..2257aa2c1c0 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -23,6 +23,7 @@ 
 #define GCC_ARM_PROTOS_H

 #include "sbitmap.h"
+#include "tree.h" /* For ERROR_MARK.  */

 rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);

@@ -83,7 +84,8 @@  extern int arm_split_constant (RTX_CODE, machine_mode, rtx,
 extern int legitimate_pic_operand_p (rtx);
 extern rtx legitimize_pic_address (rtx, machine_mode, rtx, rtx, bool);
 extern rtx legitimize_tls_address (rtx, rtx);
-extern bool arm_legitimate_address_p (machine_mode, rtx, bool);
+extern bool arm_legitimate_address_p (machine_mode, rtx, bool,
+				      code_helper = ERROR_MARK);
 extern int arm_legitimate_address_outer_p (machine_mode, rtx, RTX_CODE, int);
 extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
 extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 38f0839de1c..6e933c80183 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -9171,7 +9171,7 @@  thumb_legitimate_offset_p (machine_mode mode, HOST_WIDE_INT val)
 }

 bool
-arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+arm_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
 {
   if (TARGET_ARM)
     return arm_legitimate_address_outer_p (mode, x, SET, strict_p);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 0447641a8e9..fa42602f877 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -13431,8 +13431,8 @@  avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */

 static bool
-avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
-                                     bool strict, addr_space_t as)
+avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+				     addr_space_t as, code_helper = ERROR_MARK)
 {
   bool ok = false;

diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
index 4320ec26722..5718babb6b2 100644
--- a/gcc/config/bfin/bfin.cc
+++ b/gcc/config/bfin/bfin.cc
@@ -2718,7 +2718,8 @@  bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
 */

 static bool
-bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			   code_helper = ERROR_MARK)
 {
   switch (GET_CODE (x)) {
   case REG:
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index e0324e1e0e0..a16275c2810 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -668,7 +668,8 @@  bpf_address_base_p (rtx x, bool strict)
 static bool
 bpf_legitimate_address_p (machine_mode mode,
 			  rtx x,
-			  bool strict)
+			  bool strict,
+			  code_helper = ERROR_MARK)
 {
   switch (GET_CODE (x))
     {
diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc
index 0c9cb821f28..72e8b4c5345 100644
--- a/gcc/config/c6x/c6x.cc
+++ b/gcc/config/c6x/c6x.cc
@@ -2444,7 +2444,8 @@  c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
 }

 static bool
-c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			  code_helper = ERROR_MARK)
 {
   return c6x_legitimate_address_p_1 (mode, x, strict, false);
 }
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
index 666e04f9eee..58555943986 100644
--- a/gcc/config/cris/cris-protos.h
+++ b/gcc/config/cris/cris-protos.h
@@ -20,6 +20,8 @@  along with GCC; see the file COPYING3.  If not see

 /* Prototypes for the CRIS port.  */

+#include "tree.h" /* For ERROR_MARK.  */
+
 extern bool cris_simple_epilogue (void);
 #ifdef RTX_CODE
 extern const char *cris_op_str (rtx);
@@ -34,7 +36,8 @@  extern bool cris_base_or_autoincr_p (const_rtx, bool);
 extern bool cris_bdap_index_p (const_rtx, bool);
 extern void cris_reduce_compare (rtx *, rtx *, rtx *);
 extern bool cris_biap_index_p (const_rtx, bool);
-extern bool cris_legitimate_address_p (machine_mode, rtx, bool);
+extern bool cris_legitimate_address_p (machine_mode, rtx, bool,
+				       code_helper = ERROR_MARK);
 extern bool cris_store_multiple_op_p (rtx);
 extern bool cris_movem_load_rest_p (rtx);
 extern void cris_asm_output_symbol_ref (FILE *, rtx);
diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
index 7fca2af085a..edd2b898a6c 100644
--- a/gcc/config/cris/cris.cc
+++ b/gcc/config/cris/cris.cc
@@ -1537,7 +1537,7 @@  cris_biap_index_p (const_rtx x, bool strict)
 /* Worker function for TARGET_LEGITIMATE_ADDRESS_P.  */

 bool
-cris_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+cris_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   const_rtx x1, x2;

diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
index b4ee3b273a4..731f47cb2c0 100644
--- a/gcc/config/csky/csky.cc
+++ b/gcc/config/csky/csky.cc
@@ -3186,7 +3186,8 @@  csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p)
    be recognized.  */

 static bool
-csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p)
+csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p,
+			   code_helper = ERROR_MARK)
 {
   enum rtx_code code = GET_CODE (addr);

diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
index 60a2845d6d1..a5460dbf97f 100644
--- a/gcc/config/epiphany/epiphany.cc
+++ b/gcc/config/epiphany/epiphany.cc
@@ -2053,7 +2053,8 @@  epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
      || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))

 static bool
-epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			       code_helper = ERROR_MARK)
 {
 #define REG_OK_FOR_BASE_P(X) \
   (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
diff --git a/gcc/config/frv/frv.cc b/gcc/config/frv/frv.cc
index 2dbaa75f3dc..03976ba7b71 100644
--- a/gcc/config/frv/frv.cc
+++ b/gcc/config/frv/frv.cc
@@ -261,7 +261,8 @@  static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
 /* Forward references */

 static void frv_option_override			(void);
-static bool frv_legitimate_address_p		(machine_mode, rtx, bool);
+static bool frv_legitimate_address_p (machine_mode, rtx, bool,
+				      code_helper = ERROR_MARK);
 static int frv_default_flags_for_cpu		(void);
 static FRV_INLINE bool frv_small_data_reloc_p	(rtx, int);
 static void frv_print_operand			(FILE *, rtx, int);
@@ -3396,7 +3397,7 @@  frv_legitimate_address_p_1 (machine_mode mode,
 }

 bool
-frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+frv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
 {
   return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
 }
diff --git a/gcc/config/ft32/ft32.cc b/gcc/config/ft32/ft32.cc
index 806ab769f79..059243d2a3d 100644
--- a/gcc/config/ft32/ft32.cc
+++ b/gcc/config/ft32/ft32.cc
@@ -856,7 +856,8 @@  reg_ok_for_base_p (rtx r, bool strict)

 static bool
 ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
-                                      addr_space_t as ATTRIBUTE_UNUSED)
+				      addr_space_t as ATTRIBUTE_UNUSED,
+				      code_helper = ERROR_MARK)
 {
   int max_offset = TARGET_FT32B ? 16384 : 128;

diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index 02f4dedec42..f6cff659703 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -1654,7 +1654,7 @@  gcn_global_address_p (rtx addr)

 static bool
 gcn_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
-				     addr_space_t as)
+				     addr_space_t as, code_helper = ERROR_MARK)
 {
   /* All vector instructions need to work on addresses in registers.  */
   if (!TARGET_GCN5_PLUS && (vgpr_vector_mode_p (mode) && !REG_P (x)))
diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
index cdf74c1acbd..4bbb1b711e8 100644
--- a/gcc/config/h8300/h8300.cc
+++ b/gcc/config/h8300/h8300.cc
@@ -5312,7 +5312,8 @@  h8300_rtx_ok_for_base_p (rtx x, int strict)
    CONSTANT_ADDRESS.  */

 static bool
-h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+h8300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			    code_helper = ERROR_MARK)
 {
   /* The register indirect addresses like @er0 is always valid.  */
   if (h8300_rtx_ok_for_base_p (x, strict))
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 0761965344b..7226b3e5fd3 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -11010,7 +11010,8 @@  ix86_validate_address_register (rtx op)
    be recognized.  */

 static bool
-ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
+ix86_legitimate_address_p (machine_mode, rtx addr, bool strict,
+			   code_helper = ERROR_MARK)
 {
   struct ix86_address parts;
   rtx base, index, disp;
diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
index 92f34dd1ee7..c241e1a50fc 100644
--- a/gcc/config/ia64/ia64.cc
+++ b/gcc/config/ia64/ia64.cc
@@ -313,7 +313,8 @@  static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
 static bool ia64_scalar_mode_supported_p (scalar_mode mode);
 static bool ia64_vector_mode_supported_p (machine_mode mode);
 static bool ia64_legitimate_constant_p (machine_mode, rtx);
-static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
+static bool ia64_legitimate_address_p (machine_mode, rtx, bool,
+				       code_helper = ERROR_MARK);
 static bool ia64_cannot_force_const_mem (machine_mode, rtx);
 static const char *ia64_mangle_type (const_tree);
 static const char *ia64_invalid_conversion (const_tree, const_tree);
@@ -1024,8 +1025,8 @@  ia64_legitimate_address_disp (const_rtx reg, const_rtx disp, bool strict)
 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
-			   rtx x, bool strict)
+ia64_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
+			   bool strict, code_helper)
 {
   if (ia64_legitimate_address_reg (x, strict))
     return true;
diff --git a/gcc/config/iq2000/iq2000.cc b/gcc/config/iq2000/iq2000.cc
index 733fecac2b7..54404e8d05a 100644
--- a/gcc/config/iq2000/iq2000.cc
+++ b/gcc/config/iq2000/iq2000.cc
@@ -170,7 +170,8 @@  static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
 static unsigned int iq2000_function_arg_boundary (machine_mode,
 						  const_tree);
 static void iq2000_va_start	      (tree, rtx);
-static bool iq2000_legitimate_address_p (machine_mode, rtx, bool);
+static bool iq2000_legitimate_address_p (machine_mode, rtx, bool,
+					 code_helper = ERROR_MARK);
 static bool iq2000_can_eliminate      (const int, const int);
 static void iq2000_asm_trampoline_template (FILE *);
 static void iq2000_trampoline_init    (rtx, tree, rtx);
@@ -304,7 +305,8 @@  iq2000_reg_mode_ok_for_base_p (rtx reg,
    function is called during reload.  */

 bool
-iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict)
+iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict,
+			     code_helper)
 {
   if (TARGET_DEBUG_A_MODE)
     {
diff --git a/gcc/config/lm32/lm32.cc b/gcc/config/lm32/lm32.cc
index 6528358009d..9d65d66719c 100644
--- a/gcc/config/lm32/lm32.cc
+++ b/gcc/config/lm32/lm32.cc
@@ -69,8 +69,8 @@  static void lm32_setup_incoming_varargs (cumulative_args_t cum,
 static bool lm32_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
 			    int *total, bool speed);
 static bool lm32_can_eliminate (const int, const int);
-static bool
-lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict);
+static bool lm32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+				       code_helper = ERROR_MARK);
 static HOST_WIDE_INT lm32_compute_frame_size (int size);
 static void lm32_option_override (void);
 static rtx lm32_function_arg (cumulative_args_t, const function_arg_info &);
@@ -1192,7 +1192,8 @@  lm32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x, bool strict)
+lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
+			   bool strict, code_helper)
 {
    /* (rM) */
   if (strict && REG_P (x) && STRICT_REG_OK_FOR_BASE_P (x))
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 5b8b93eb24b..86d58784113 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2096,7 +2096,8 @@  loongarch_classify_address (struct loongarch_address_info *info, rtx x,
 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
+				code_helper = ERROR_MARK)
 {
   struct loongarch_address_info addr;

diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
index 65971d62990..e18efc3c7f2 100644
--- a/gcc/config/m32c/m32c.cc
+++ b/gcc/config/m32c/m32c.cc
@@ -75,8 +75,11 @@  static int m32c_comp_type_attributes (const_tree, const_tree);
 static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static struct machine_function *m32c_init_machine_status (void);
 static void m32c_insert_attributes (tree, tree *);
-static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
-static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
+static bool m32c_legitimate_address_p (machine_mode, rtx, bool,
+				       code_helper = ERROR_MARK);
+static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool,
+						  addr_space_t,
+						  code_helper = ERROR_MARK);
 static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
 static bool m32c_pass_by_reference (cumulative_args_t,
 				    const function_arg_info &);
@@ -1648,7 +1651,7 @@  m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
 bool
-m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   int mode_adjust;
   if (CONSTANT_P (x))
@@ -1966,8 +1969,8 @@  m32c_addr_space_address_mode (addr_space_t addrspace)
 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
   m32c_addr_space_legitimate_address_p
 static bool
-m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
-				      bool strict, addr_space_t as)
+m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+				      addr_space_t as, code_helper ch)
 {
   if (as == ADDR_SPACE_FAR)
     {
@@ -2048,7 +2051,7 @@  m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
   else if (as != ADDR_SPACE_GENERIC)
     gcc_unreachable ();

-  return m32c_legitimate_address_p (mode, x, strict);
+  return m32c_legitimate_address_p (mode, x, strict, ch);
 }

 /* Like m32c_legitimate_address, except with named address support.  */
diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
index 155a248459b..63a1798da3d 100644
--- a/gcc/config/m32r/m32r.cc
+++ b/gcc/config/m32r/m32r.cc
@@ -66,7 +66,8 @@  static void  m32r_option_override (void);
 static void  init_reg_tables (void);
 static void  block_move_call (rtx, rtx, rtx);
 static int   m32r_is_insn (rtx);
-static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
+static bool  m32r_legitimate_address_p (machine_mode, rtx, bool,
+					code_helper = ERROR_MARK);
 static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
 static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
 static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
@@ -2913,7 +2914,7 @@  m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
 /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   if (m32r_rtx_ok_for_base_p (x, strict)
       || m32r_legitimate_offset_addres_p (mode, x, strict)
diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
index 03db2b6a936..145a92d8710 100644
--- a/gcc/config/m68k/m68k.cc
+++ b/gcc/config/m68k/m68k.cc
@@ -158,7 +158,8 @@  static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);

 static bool m68k_can_eliminate (const int, const int);
 static void m68k_conditional_register_usage (void);
-static bool m68k_legitimate_address_p (machine_mode, rtx, bool);
+static bool m68k_legitimate_address_p (machine_mode, rtx, bool,
+				       code_helper = ERROR_MARK);
 static void m68k_option_override (void);
 static void m68k_override_options_after_change (void);
 static rtx find_addr_reg (rtx);
@@ -2311,7 +2312,7 @@  m68k_decompose_address (machine_mode mode, rtx x,
    STRICT_P says whether strict checking is needed.  */

 bool
-m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+m68k_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, code_helper)
 {
   struct m68k_address address;

diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
index e933b03cdff..6f1d7af7937 100644
--- a/gcc/config/mcore/mcore.cc
+++ b/gcc/config/mcore/mcore.cc
@@ -144,7 +144,8 @@  static bool       mcore_warn_func_return        (tree);
 static void       mcore_option_override		(void);
 static bool       mcore_legitimate_constant_p   (machine_mode, rtx);
 static bool	  mcore_legitimate_address_p	(machine_mode, rtx, bool,
-						 addr_space_t);
+						 addr_space_t,
+						 code_helper = ERROR_MARK);
 static bool	  mcore_hard_regno_mode_ok	(unsigned int, machine_mode);
 static bool	  mcore_modes_tieable_p		(machine_mode, machine_mode);


@@ -3249,7 +3250,7 @@  mcore_legitimate_index_p (machine_mode mode, const_rtx op)

 static bool
 mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
-			    addr_space_t as)
+			    addr_space_t as, code_helper)
 {
   gcc_assert (ADDR_SPACE_GENERIC_P (as));

diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index 31a6515176b..93fd8d17e3c 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -22,6 +22,8 @@ 
 #ifndef GCC_MICROBLAZE_PROTOS_H
 #define GCC_MICROBLAZE_PROTOS_H

+#include "tree.h"  /* For ERROR_MARK.  */
+
 #ifdef RTX_CODE
 extern int pic_address_needs_scratch (rtx);
 extern bool microblaze_constant_address_p (rtx x);
@@ -40,7 +42,8 @@  extern int microblaze_can_use_return_insn (void);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
 extern void init_cumulative_args (CUMULATIVE_ARGS *,tree, rtx);
-extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool);
+extern bool microblaze_legitimate_address_p (machine_mode, rtx, bool,
+					     code_helper = ERROR_MARK);
 extern int microblaze_is_interrupt_variant (void);
 extern int microblaze_is_break_handler (void);
 extern int microblaze_break_function_p (tree func);
diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
index cbabf1af712..c9f6c4198cf 100644
--- a/gcc/config/microblaze/microblaze.cc
+++ b/gcc/config/microblaze/microblaze.cc
@@ -919,7 +919,8 @@  microblaze_classify_address (struct microblaze_address_info *info, rtx x,
    is called during reload.  */

 bool
-microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+				 code_helper)
 {
   struct microblaze_address_info addr;

diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 999127a72e7..3497d42cdf3 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -2691,7 +2691,8 @@  mips_classify_address (struct mips_address_info *info, rtx x,
 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+mips_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
+			   code_helper = ERROR_MARK)
 {
   struct mips_address_info addr;

diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc
index 1d36306fdb6..34743092749 100644
--- a/gcc/config/mmix/mmix.cc
+++ b/gcc/config/mmix/mmix.cc
@@ -132,7 +132,8 @@  static void mmix_target_asm_function_end_prologue (FILE *);
 static void mmix_target_asm_function_epilogue (FILE *);
 static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t);
 static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t);
-static bool mmix_legitimate_address_p (machine_mode, rtx, bool);
+static bool mmix_legitimate_address_p (machine_mode, rtx, bool,
+				       code_helper = ERROR_MARK);
 static bool mmix_legitimate_constant_p (machine_mode, rtx);
 static void mmix_reorg (void);
 static void mmix_asm_output_mi_thunk
@@ -1109,7 +1110,8 @@  mmix_constant_address_p (rtx x)
 bool
 mmix_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
 			   rtx x,
-			   bool strict_checking)
+			   bool strict_checking,
+			   code_helper)
 {
 #define MMIX_REG_OK(X)							\
   ((strict_checking							\
diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
index a8b01a543cc..cd1de1b2d83 100644
--- a/gcc/config/mn10300/mn10300.cc
+++ b/gcc/config/mn10300/mn10300.cc
@@ -1932,7 +1932,8 @@  mn10300_legitimate_pic_operand_p (rtx x)
    function record_unscaled_index_insn_codes.  */

 static bool
-mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+mn10300_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			      code_helper = ERROR_MARK)
 {
   rtx base, index;

diff --git a/gcc/config/moxie/moxie.cc b/gcc/config/moxie/moxie.cc
index 2132b6e48a3..209d03077ea 100644
--- a/gcc/config/moxie/moxie.cc
+++ b/gcc/config/moxie/moxie.cc
@@ -577,7 +577,8 @@  moxie_reg_ok_for_base_p (const_rtx reg, bool strict_p)
 static bool
 moxie_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
 			    rtx x, bool strict_p,
-			    addr_space_t as)
+			    addr_space_t as,
+			    code_helper = ERROR_MARK)
 {
   gcc_assert (ADDR_SPACE_GENERIC_P (as));

diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
index 6f9c56187ee..061a9c77961 100644
--- a/gcc/config/msp430/msp430.cc
+++ b/gcc/config/msp430/msp430.cc
@@ -927,7 +927,8 @@  reg_ok_for_addr (rtx r, bool strict)
 bool
 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
 			     rtx x ATTRIBUTE_UNUSED,
-			     bool strict ATTRIBUTE_UNUSED)
+			     bool strict ATTRIBUTE_UNUSED,
+			     code_helper = ERROR_MARK)
 {
   switch (GET_CODE (x))
     {
@@ -980,9 +981,10 @@  bool
 msp430_addr_space_legitimate_address_p (machine_mode mode,
 					rtx x,
 					bool strict,
-					addr_space_t as ATTRIBUTE_UNUSED)
+					addr_space_t as ATTRIBUTE_UNUSED,
+					code_helper ch = ERROR_MARK)
 {
-  return msp430_legitimate_address_p (mode, x, strict);
+  return msp430_legitimate_address_p (mode, x, strict, ch);
 }

 #undef  TARGET_ASM_INTEGER
diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
index 91ed91d914f..1f8de2a514a 100644
--- a/gcc/config/nds32/nds32.cc
+++ b/gcc/config/nds32/nds32.cc
@@ -2565,7 +2565,8 @@  nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
 /* Addressing Modes.  */

 static bool
-nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict,
+			    code_helper = ERROR_MARK)
 {
   if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
     {
diff --git a/gcc/config/nios2/nios2.cc b/gcc/config/nios2/nios2.cc
index 936eb34ace4..b435d7475f9 100644
--- a/gcc/config/nios2/nios2.cc
+++ b/gcc/config/nios2/nios2.cc
@@ -2141,8 +2141,9 @@  nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)

 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */
 static bool
-nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
-			    rtx operand, bool strict_p)
+nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx operand,
+			    bool strict_p,
+			    code_helper = ERROR_MARK)
 {
   switch (GET_CODE (operand))
     {
diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
index e3b0304d537..49291d71a74 100644
--- a/gcc/config/nvptx/nvptx.cc
+++ b/gcc/config/nvptx/nvptx.cc
@@ -2202,7 +2202,7 @@  nvptx_gen_shared_bcast (rtx reg, propagate_mask pm, unsigned rep,
 /* Returns true if X is a valid address for use in a memory reference.  */

 static bool
-nvptx_legitimate_address_p (machine_mode, rtx x, bool)
+nvptx_legitimate_address_p (machine_mode, rtx x, bool, code_helper)
 {
   enum rtx_code code = GET_CODE (x);

diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc
index ec30bc8156c..5eeed0e91be 100644
--- a/gcc/config/or1k/or1k.cc
+++ b/gcc/config/or1k/or1k.cc
@@ -575,7 +575,8 @@  or1k_initial_elimination_offset (int from, int to)
    Returns true if X is a legitimate address RTX on OpenRISC.  */

 static bool
-or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p)
+or1k_legitimate_address_p (machine_mode, rtx x, bool strict_p,
+			   code_helper = ERROR_MARK)
 {
   rtx base, addend;

diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc
index 0fa9e5fd632..2e906cff7ff 100644
--- a/gcc/config/pa/pa.cc
+++ b/gcc/config/pa/pa.cc
@@ -196,7 +196,8 @@  static section *pa_function_section (tree, enum node_frequency, bool, bool);
 static bool pa_cannot_force_const_mem (machine_mode, rtx);
 static bool pa_legitimate_constant_p (machine_mode, rtx);
 static unsigned int pa_section_type_flags (tree, const char *, int);
-static bool pa_legitimate_address_p (machine_mode, rtx, bool);
+static bool pa_legitimate_address_p (machine_mode, rtx, bool,
+				     code_helper = ERROR_MARK);
 static bool pa_callee_copies (cumulative_args_t, const function_arg_info &);
 static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
 static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
@@ -10787,7 +10788,7 @@  pa_section_type_flags (tree decl, const char *name, int reloc)
    output as REG+SMALLINT.  */

 static bool
-pa_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   if ((REG_P (x)
        && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
index f6dd841f184..321837935c8 100644
--- a/gcc/config/pdp11/pdp11.cc
+++ b/gcc/config/pdp11/pdp11.cc
@@ -1615,8 +1615,8 @@  pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2)
 */

 static bool
-pdp11_legitimate_address_p (machine_mode mode,
-			    rtx operand, bool strict)
+pdp11_legitimate_address_p (machine_mode mode, rtx operand, bool strict,
+			    code_helper = ERROR_MARK)
 {
     rtx xfoob;

diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index e855bbb8195..6e8112be64a 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -1466,7 +1466,8 @@  int pru_symref2ioregno (rtx op)
 /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
 static bool
 pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
-				     bool strict_p, addr_space_t as)
+				     bool strict_p, addr_space_t as,
+				     code_helper = ERROR_MARK)
 {
   if (as == ADDR_SPACE_REGIO)
     {
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 280aa0b33b9..31e2b9bccc2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1163,7 +1163,8 @@  riscv_classify_address (struct riscv_address_info *info, rtx x,
 /* Implement TARGET_LEGITIMATE_ADDRESS_P.  */

 static bool
-riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p)
+riscv_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
+			    code_helper = ERROR_MARK)
 {
   struct riscv_address_info addr;

diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
index 7d474ffc130..813459ad8b6 100644
--- a/gcc/config/rl78/rl78-protos.h
+++ b/gcc/config/rl78/rl78-protos.h
@@ -18,6 +18,9 @@ 
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */


+
+#include "tree.h"  /* For ERROR_MARK.  */
+
 const char *    rl78_addsi3_internal (rtx *, unsigned int);
 void		rl78_emit_eh_epilogue (rtx);
 void		rl78_expand_compare (rtx *);
@@ -33,7 +36,8 @@  int		rl78_far_p (rtx x);
 bool		rl78_hl_b_c_addr_p (rtx);
 int		rl78_initial_elimination_offset (int, int);
 bool		rl78_as_legitimate_address (machine_mode, rtx,
-					    bool, addr_space_t);
+					    bool, addr_space_t,
+					    code_helper = ERROR_MARK);
 int		rl78_legitimize_reload_address (rtx *, machine_mode, int,int, int);
 enum reg_class	rl78_mode_code_base_reg_class (machine_mode, addr_space_t, int, int);
 bool		rl78_peep_movhi_p (rtx *);
diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
index 9083096c4ae..0cbd6bf780a 100644
--- a/gcc/config/rl78/rl78.cc
+++ b/gcc/config/rl78/rl78.cc
@@ -1143,7 +1143,8 @@  rl78_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE

 bool
 rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
-			    bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
+			    bool strict ATTRIBUTE_UNUSED,
+			    addr_space_t as ATTRIBUTE_UNUSED, code_helper)
 {
   rtx base, index, addend;
   bool is_far_addr = false;
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 546c353029b..efc54528b23 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -1109,7 +1109,8 @@  struct processor_costs ppca2_cost = {
 static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);



-static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
+static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool,
+					       code_helper = ERROR_MARK);
 static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
 static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
 static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
@@ -9854,7 +9855,8 @@  use_toc_relative_ref (rtx sym, machine_mode mode)
    because adjacent memory cells are accessed by adding word-sized offsets
    during assembly output.  */
 static bool
-rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)
+rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
+			     code_helper = ERROR_MARK)
 {
   bool reg_offset_p = reg_offset_addressing_ok_p (mode);
   bool quad_offset_p = mode_supports_dq_form (mode);
@@ -9957,10 +9959,10 @@  rs6000_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict)

 /* Debug version of rs6000_legitimate_address_p.  */
 static bool
-rs6000_debug_legitimate_address_p (machine_mode mode, rtx x,
-				   bool reg_ok_strict)
+rs6000_debug_legitimate_address_p (machine_mode mode, rtx x, bool reg_ok_strict,
+				   code_helper ch)
 {
-  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
+  bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict, ch);
   fprintf (stderr,
 	   "\nrs6000_legitimate_address_p: return = %s, mode = %s, "
 	   "strict = %d, reload = %s, code = %s\n",
diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
index 726b00a3193..245c6a4413d 100644
--- a/gcc/config/rx/rx.cc
+++ b/gcc/config/rx/rx.cc
@@ -179,7 +179,8 @@  rx_small_data_operand (rtx op)

 static bool
 rx_is_legitimate_address (machine_mode mode, rtx x,
-			  bool strict ATTRIBUTE_UNUSED)
+			  bool strict ATTRIBUTE_UNUSED,
+			  code_helper = ERROR_MARK)
 {
   if (RTX_OK_FOR_BASE (x, strict))
     /* Register Indirect.  */
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 9284477396d..5b8826162a9 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -4914,7 +4914,8 @@  s390_expand_plus_operand (rtx target, rtx src,
    STRICT specifies whether strict register checking applies.  */

 static bool
-s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
+s390_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
+			   code_helper = ERROR_MARK)
 {
   struct s390_address ad;

diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 938f7aa6281..294faf7c0c3 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -266,7 +266,8 @@  static reg_class_t sh_preferred_reload_class (rtx, reg_class_t);
 static reg_class_t sh_secondary_reload (bool, rtx, reg_class_t,
                                         machine_mode,
                                         struct secondary_reload_info *);
-static bool sh_legitimate_address_p (machine_mode, rtx, bool);
+static bool sh_legitimate_address_p (machine_mode, rtx, bool,
+				     code_helper = ERROR_MARK);
 static rtx sh_legitimize_address (rtx, rtx, machine_mode);
 static rtx sh_delegitimize_address (rtx);
 static bool sh_cannot_substitute_mem_equiv_p (rtx);
@@ -9038,7 +9039,7 @@  sh_legitimate_index_p (machine_mode mode, rtx op, bool consider_sh2a,
 	  GBR
 	  GBR+disp  */
 static bool
-sh_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+sh_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   if (REG_P (x) && REGNO (x) == GBR_REG)
     return true;
diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
index 0aade05faf5..82e57952414 100644
--- a/gcc/config/sparc/sparc.cc
+++ b/gcc/config/sparc/sparc.cc
@@ -607,7 +607,8 @@  static void sparc_emit_set_const64 (rtx, rtx);
 static void sparc_output_addr_vec (rtx);
 static void sparc_output_addr_diff_vec (rtx);
 static void sparc_output_deferred_case_vectors (void);
-static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
+static bool sparc_legitimate_address_p (machine_mode, rtx, bool,
+					code_helper = ERROR_MARK);
 static bool sparc_legitimate_constant_p (machine_mode, rtx);
 static rtx sparc_builtin_saveregs (void);
 static int epilogue_renumber (rtx *, int);
@@ -4529,7 +4530,8 @@  sparc_pic_register_p (rtx x)
    ordinarily.  This changes a bit when generating PIC.  */

 static bool
-sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
+sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
+			    code_helper)
 {
   rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;

diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h
index f90d88eba6f..27ae023bcb3 100644
--- a/gcc/config/stormy16/stormy16-protos.h
+++ b/gcc/config/stormy16/stormy16-protos.h
@@ -18,7 +18,7 @@  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/>.  */

-
+#include "tree.h"  /* For ERROR_MARK.  */

 extern struct xstormy16_stack_layout xstormy16_compute_stack_layout (void);
 extern void xstormy16_expand_prologue (void);
@@ -65,6 +65,7 @@  extern const char * xstormy16_output_shift (machine_mode, enum rtx_code,
 					    rtx, rtx, rtx);
 extern bool  xstormy16_below100_symbol (rtx, machine_mode);
 extern bool  xstormy16_splittable_below100_operand (rtx, machine_mode);
-extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool);
+extern bool xstormy16_legitimate_address_p (machine_mode, rtx, bool,
+					    code_helper = ERROR_MARK);
 #endif

diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
index cd453c2a2f7..10887153906 100644
--- a/gcc/config/stormy16/stormy16.cc
+++ b/gcc/config/stormy16/stormy16.cc
@@ -795,8 +795,8 @@  xstormy16_expand_andqi3 (rtx *operands)
   && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))

 bool
-xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
-				rtx x, bool strict)
+xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x,
+				bool strict, code_helper)
 {
   if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))
     return true;
diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
index 0fb72716b17..416c2841a5c 100644
--- a/gcc/config/v850/v850.cc
+++ b/gcc/config/v850/v850.cc
@@ -3030,7 +3030,8 @@  v850_rtx_ok_for_base_p (const_rtx x, bool strict_p)

 static bool
 v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p,
-			   addr_space_t as ATTRIBUTE_UNUSED)
+			   addr_space_t as ATTRIBUTE_UNUSED,
+			   code_helper = ERROR_MARK)
 {
   gcc_assert (ADDR_SPACE_GENERIC_P (as));

diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
index 82a176d3bfc..df9478d881a 100644
--- a/gcc/config/vax/vax.cc
+++ b/gcc/config/vax/vax.cc
@@ -46,7 +46,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "target-def.h"

 static void vax_option_override (void);
-static bool vax_legitimate_address_p (machine_mode, rtx, bool);
+static bool vax_legitimate_address_p (machine_mode, rtx, bool,
+				      code_helper = ERROR_MARK);
 static void vax_file_start (void);
 static void vax_init_libfuncs (void);
 static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
@@ -1902,7 +1903,7 @@  indexable_address_p (rtx xfoo0, rtx xfoo1, machine_mode mode, bool strict)
    The MODE argument is the machine mode for the MEM expression
    that wants to use this address.  */
 bool
-vax_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+vax_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   rtx xfoo0, xfoo1;

diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
index 48a61744db6..5fadbc80be0 100644
--- a/gcc/config/visium/visium.cc
+++ b/gcc/config/visium/visium.cc
@@ -194,7 +194,8 @@  static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,

 static bool visium_legitimate_constant_p (machine_mode, rtx);

-static bool visium_legitimate_address_p (machine_mode, rtx, bool);
+static bool visium_legitimate_address_p (machine_mode, rtx, bool,
+					 code_helper = ERROR_MARK);

 static bool visium_print_operand_punct_valid_p (unsigned char);
 static void visium_print_operand (FILE *, rtx, int);
@@ -1818,7 +1819,7 @@  rtx_ok_for_offset_p (machine_mode mode, rtx op)
    kind of register is required.  */

 static bool
-visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+visium_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 {
   rtx base;
   unsigned int regno;
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index dd35e63c094..897cf7363f4 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -123,7 +123,8 @@  static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
 static bool xtensa_return_in_msb (const_tree);
 static void printx (FILE *, signed int);
 static rtx xtensa_builtin_saveregs (void);
-static bool xtensa_legitimate_address_p (machine_mode, rtx, bool);
+static bool xtensa_legitimate_address_p (machine_mode, rtx, bool,
+					 code_helper = ERROR_MARK);
 static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
 							int) ATTRIBUTE_UNUSED;
 static section *xtensa_select_rtx_section (machine_mode, rtx,
@@ -2296,9 +2297,9 @@  xtensa_emit_sibcall (int callop, rtx *operands)
   return result;
 }

-
 bool
-xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
+xtensa_legitimate_address_p (machine_mode mode, rtx addr, bool strict,
+			     code_helper)
 {
   /* Allow constant pool addresses.  */
   if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index ca8837cef67..3e9a2f19e27 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -99,6 +99,7 @@  typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
+class code_helper;

 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 95ba56e05ae..e4d0cc43f41 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5853,9 +5853,16 @@  the maximum number that @code{TARGET_LEGITIMATE_ADDRESS_P} would ever
 accept.
 @end defmac

-@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict})
+@deftypefn {Target Hook} bool TARGET_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{x}, bool @var{strict}, code_helper @var{ch})
 A function that returns whether @var{x} (an RTX) is a legitimate memory
 address on the target machine for a memory operand of mode @var{mode}.
+If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to
+determine if it is valid to use @var{x} as a memory operand for RTX insn
+which is generated for the given code_helper @var{ch}.  For example,
+assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying
+hardware instructions support fewer addressing modes than what are for the
+normal vector load and store, then with this @var{ch} target can know the
+actual use context and return more exact result.

 Legitimate addresses are defined in two variants: a strict variant and a
 non-strict one.  The @var{strict} parameter chooses which variant is
@@ -10992,11 +10999,12 @@  version of this hook returns true for the modes returned by either the
 target hooks for the given address space.
 @end deftypefn

-@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
+@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as}, code_helper @var{ch})
 Define this to return true if @var{exp} is a valid address for mode
-@var{mode} in the named address space @var{as}.  The @var{strict}
-parameter says whether strict addressing is in effect after reload has
-finished.  This target hook is the same as the
+@var{mode} in the named address space @var{as} with the use context
+@var{ch}.  The @var{strict} parameter says whether strict addressing
+is in effect after reload has finished.  The @var{ch} indicates what
+context @var{exp} will be used for.  This target hook is the same as the
 @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes
 explicit named address space support.
 @end deftypefn
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 4dc2d70c402..cb9cbac5bb3 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -336,7 +336,8 @@  valid_address_p (machine_mode mode ATTRIBUTE_UNUSED,
  win:
   return 1;
 #else
-  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
+  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
+						  ERROR_MARK);
 #endif
 }

diff --git a/gcc/recog.cc b/gcc/recog.cc
index 37432087812..692c258def6 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -1813,7 +1813,8 @@  memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
  win:
   return true;
 #else
-  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
+  return targetm.addr_space.legitimate_address_p (mode, addr, 0, as,
+						  ERROR_MARK);
 #endif
 }

diff --git a/gcc/reload.cc b/gcc/reload.cc
index d079bc120d5..0be21f7b61e 100644
--- a/gcc/reload.cc
+++ b/gcc/reload.cc
@@ -2172,7 +2172,8 @@  strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
  win:
   return true;
 #else
-  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
+  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as,
+						  ERROR_MARK);
 #endif
 }


diff --git a/gcc/target.def b/gcc/target.def
index 7d684296c17..a500aeb6714 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2897,6 +2897,13 @@  DEFHOOK
 (legitimate_address_p,
  "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
 address on the target machine for a memory operand of mode @var{mode}.\n\
+If @var{ch} is not @code{ERROR_MARK}, it can be called from middle-end to\n\
+determine if it is valid to use @var{x} as a memory operand for RTX insn\n\
+which is generated for the given code_helper @var{ch}.  For example,\n\
+assuming the given @var{ch} is IFN_LEN_LOAD, on some target its underlying\n\
+hardware instructions support fewer addressing modes than what are for the\n\
+normal vector load and store, then with this @var{ch} target can know the\n\
+actual use context and return more exact result.\n\
 \n\
 Legitimate addresses are defined in two variants: a strict variant and a\n\
 non-strict one.  The @var{strict} parameter chooses which variant is\n\
@@ -2957,7 +2964,7 @@  that case and the non-strict variant otherwise.\n\
 \n\
 Using the hook is usually simpler because it limits the number of\n\
 files that are recompiled when changes are made.",
- bool, (machine_mode mode, rtx x, bool strict),
+ bool, (machine_mode mode, rtx x, bool strict, code_helper ch),
  default_legitimate_address_p)

 /* True if the given constant can be put into an object_block.  */
@@ -3348,12 +3355,13 @@  target hooks for the given address space.",
 DEFHOOK
 (legitimate_address_p,
  "Define this to return true if @var{exp} is a valid address for mode\n\
-@var{mode} in the named address space @var{as}.  The @var{strict}\n\
-parameter says whether strict addressing is in effect after reload has\n\
-finished.  This target hook is the same as the\n\
+@var{mode} in the named address space @var{as} with the use context\n\
+@var{ch}.  The @var{strict} parameter says whether strict addressing\n\
+is in effect after reload has finished.  The @var{ch} indicates what\n\
+context @var{exp} will be used for.  This target hook is the same as the\n\
 @code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
 explicit named address space support.",
- bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
+ bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as, code_helper ch),
  default_addr_space_legitimate_address_p)

 /* Return an updated address to convert an invalid pointer to a named
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index e190369f87a..4ef53267e50 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -99,7 +99,8 @@  along with GCC; see the file COPYING3.  If not see
 bool
 default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
 			      rtx addr ATTRIBUTE_UNUSED,
-			      bool strict ATTRIBUTE_UNUSED)
+			      bool strict ATTRIBUTE_UNUSED,
+			      code_helper ATTRIBUTE_UNUSED)
 {
 #ifdef GO_IF_LEGITIMATE_ADDRESS
   /* Defer to the old implementation using a goto.  */
@@ -1680,9 +1681,10 @@  target_default_pointer_address_modes_p (void)
 bool
 default_addr_space_legitimate_address_p (machine_mode mode, rtx mem,
 					 bool strict,
-					 addr_space_t as ATTRIBUTE_UNUSED)
+					 addr_space_t as ATTRIBUTE_UNUSED,
+					 code_helper code)
 {
-  return targetm.legitimate_address_p (mode, mem, strict);
+  return targetm.legitimate_address_p (mode, mem, strict, code);
 }

 /* Named address space version of LEGITIMIZE_ADDRESS.
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 1a0db8dddd5..761225512b7 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -20,7 +20,7 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_TARGHOOKS_H
 #define GCC_TARGHOOKS_H

-extern bool default_legitimate_address_p (machine_mode, rtx, bool);
+extern bool default_legitimate_address_p (machine_mode, rtx, bool, code_helper);

 extern void default_external_libcall (rtx);
 extern rtx default_legitimize_address (rtx, rtx, machine_mode);
@@ -202,8 +202,8 @@  extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
 extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
 extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
 						   addr_space_t);
-extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
-						     bool, addr_space_t);
+extern bool default_addr_space_legitimate_address_p (machine_mode, rtx, bool,
+						     addr_space_t, code_helper);
 extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
 						  addr_space_t);
 extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);