Turn MODES_TIEABLE_P into a target hook

Message ID 87a82kt4nl.fsf@linaro.org
State New
Headers show
Series
  • Turn MODES_TIEABLE_P into a target hook
Related show

Commit Message

Richard Sandiford Aug. 28, 2017, 9:36 a.m.
The lack of function comments in msp430.c and rl78.c is deliberate;
the local style there is to define the hook macro immediately before
the function as a form of documentation.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by checking that there were no extra warnings or changes in
testsuite assembly output for at least one target per CPU.  OK to install?

Richard


2017-08-27  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* target.def (modes_tieable_p): New hook.
	* doc/tm.texi (MODES_TIEABLE_P): Replace with...
	(TARGET_MODES_TIEABLE_P): ...this.
	* doc/tm.texi.in: Regenerate.
	* hooks.h (hook_bool_mode_mode_true): Declare.
	* hooks.c (hook_bool_mode_mode_true): New function.
	* combine.c (subst): Use targetm.modes_tieable_p instead of
	MODES_TIEABLE_P.
	* dse.c (find_shift_sequence): Likewise.
	* expmed.c (extract_low_bits): Likewise.
	* lower-subreg.c: Include target.h.
	(find_decomposable_subregs): Use targetm.modes_tieable_p instead of
	MODES_TIEABLE_P.
	* rtlanal.c (rtx_cost): Likewise.
	* config/aarch64/aarch64.h (MODES_TIEABLE_P): Delete.
	* config/aarch64/aarch64-protos.h (aarch64_modes_tieable_p): Delete.
	* config/aarch64/aarch64.c (aarch64_modes_tieable_p): Make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/alpha/alpha.h (MODES_TIEABLE_P): Delete.
	* config/alpha/alpha.c (alpha_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/arc/arc.h (MODES_TIEABLE_P): Delete.
	* config/arc/arc.c (TARGET_MODES_TIEABLE_P): Redefine.
	(arc_modes_tieable_p): New function.
	* config/arm/arm.h (MODES_TIEABLE_P): Delete.
	* config/arm/arm-protos.h (arm_modes_tieable_p): Delete.
	* config/arm/arm.c (TARGET_MODES_TIEABLE_P): Redefine.
	(arm_modes_tieable_p): Make static.
	* config/avr/avr.h (MODES_TIEABLE_P): Delete.
	* config/bfin/bfin.h (MODES_TIEABLE_P): Delete.
	* config/bfin/bfin.c (bfin_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/c6x/c6x.h (MODES_TIEABLE_P): Delete.
	* config/c6x/c6x.c (c6x_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/cr16/cr16.h (MODES_TIEABLE_P): Delete.
	* config/cr16/cr16.c (TARGET_MODES_TIEABLE_P): Redefine.
	(cr16_modes_tieable_p): New function.
	* config/cris/cris.h (MODES_TIEABLE_P): Delete.
	* config/epiphany/epiphany.h (MODES_TIEABLE_P): Delete.
	* config/fr30/fr30.h (MODES_TIEABLE_P): Delete.
	(TRULY_NOOP_TRUNCATION): Update comment.
	* config/frv/frv.h (MODES_TIEABLE_P): Delete.
	(TRULY_NOOP_TRUNCATION): Update comment.
	* config/frv/frv.c (TARGET_MODES_TIEABLE_P): Redefine.
	(frv_modes_tieable_p): New function.
	* config/ft32/ft32.h (MODES_TIEABLE_P): Delete.
	* config/h8300/h8300.h (MODES_TIEABLE_P): Delete.
	* config/h8300/h8300.c (h8300_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/i386/i386.h (MODES_TIEABLE_P): Delete.
	* config/i386/i386-protos.h (ix86_modes_tieable_p): Delete.
	* config/i386/i386.c (ix86_modes_tieable_p): Make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/ia64/ia64.h (MODES_TIEABLE_P): Delete.
	* config/ia64/ia64.c (TARGET_MODES_TIEABLE_P): Redefine.
	(ia64_modes_tieable_p): New function.
	* config/iq2000/iq2000.h (MODES_TIEABLE_P): Delete.
	* config/iq2000/iq2000.c (TARGET_MODES_TIEABLE_P): Redefine.
	(iq2000_modes_tieable_p): New function.
	* config/lm32/lm32.h (MODES_TIEABLE_P): Delete.
	* config/lm32/lm32.c (TARGET_MODES_TIEABLE_P): Redefine.
	(lm32_modes_tieable_p): New function.
	* config/m32c/m32c.h (MODES_TIEABLE_P): Delete.
	* config/m32c/m32c-protos.h (m32c_modes_tieable_p): Delete.
	* config/m32c/m32c.c (m32c_modes_tieable_p): Make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/m32r/m32r.h (MODES_TIEABLE_P): Delete.
	* config/m32r/m32r.c (TARGET_MODES_TIEABLE_P): Redefine.
	(m32r_modes_tieable_p): New function.
	* config/m68k/m68k.h (MODES_TIEABLE_P): Delete.
	* config/m68k/m68k.c (TARGET_MODES_TIEABLE_P): Redefine.
	(m68k_modes_tieable_p): New function.
	* config/mcore/mcore.h (MODES_TIEABLE_P): Delete.
	* config/mcore/mcore.c (TARGET_MODES_TIEABLE_P): Redefine.
	(mcore_modes_tieable_p): New function.
	* config/microblaze/microblaze.h (MODES_TIEABLE_P): Delete.
	* config/microblaze/microblaze.c (microblaze_modes_tieable_p): New
	function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/mips/mips.h (MODES_TIEABLE_P): Delete.
	* config/mips/mips-protos.h (mips_modes_tieable_p): Delete.
	* config/mips/mips.c (mips_modes_tieable_p): Make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/mmix/mmix.h (MODES_TIEABLE_P): Delete.
	* config/mn10300/mn10300.h (MODES_TIEABLE_P): Delete.
	* config/mn10300/mn10300-protos.h (mn10300_modes_tieable): Delete.
	* config/mn10300/mn10300.c (mn10300_modes_tieable): Rename to...
	(mn10300_modes_tieable_p): ...this and make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/moxie/moxie.h (MODES_TIEABLE_P): Delete.
	* config/msp430/msp430.h (MODES_TIEABLE_P): Delete.
	* config/msp430/msp430-protos.h (msp430_modes_tieable_p): Delete.
	* config/msp430/msp430.c (TARGET_MODES_TIEABLE_P): Redefine.
	(msp430_modes_tieable_p): Make static.
	* config/nds32/nds32.h (MODES_TIEABLE_P): Delete.
	* config/nds32/nds32.c (nds32_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/nios2/nios2.h (MODES_TIEABLE_P): Delete.
	* config/nvptx/nvptx.h (MODES_TIEABLE_P): Delete.
	* config/nvptx/nvptx.c (nvptx_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/pa/pa.h (MODES_TIEABLE_P): Delete.
	* config/pa/pa-protos.h (pa_modes_tieable_p): Delete.
	* config/pa/pa.c (pa_modes_tieable_p): Make static.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/pdp11/pdp11.h (MODES_TIEABLE_P): Delete.
	* config/pdp11/pdp11.c (TARGET_MODES_TIEABLE_P): Redefine.
	(pdp11_modes_tieable_p): New function.
	* config/powerpcspe/powerpcspe.h (MODES_TIEABLE_P): Delete.
	* config/powerpcspe/powerpcspe.c (TARGET_MODES_TIEABLE_P): Redefine.
	(rs6000_modes_tieable_p): New function.
	(rs6000_debug_reg_global): Use it instead of MODES_TIEABLE_P.
	* config/powerpcspe/powerpcspe.md: Update comment.
	* config/riscv/riscv.h (MODES_TIEABLE_P): Delete.
	* config/riscv/riscv.c (riscv_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/rl78/rl78.h (MODES_TIEABLE_P): Delete.
	* config/rl78/rl78.c (TARGET_MODES_TIEABLE_P): Redefine.
	(rl78_modes_tieable_p): New function.
	* config/rs6000/rs6000.h (MODES_TIEABLE_P): Delete.
	* config/rs6000/rs6000.c (TARGET_MODES_TIEABLE_P): Redefine.
	(rs6000_modes_tieable_p): New function.
	(rs6000_debug_reg_global): Use it instead of MODES_TIEABLE_P.
	* config/rs6000/rs6000.md: Update comment.
	* config/rx/rx.h (MODES_TIEABLE_P): Delete.
	* config/rx/rx.c (rx_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/s390/s390.h (MODES_TIEABLE_P): Delete.
	* config/s390/s390.c (s390_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/sh/sh.h (MODES_TIEABLE_P): Delete.
	* config/sh/sh.c (TARGET_MODES_TIEABLE_P): Redefine.
	(sh_modes_tieable_p): New function.
	* config/sparc/sparc.h (MODES_TIEABLE_P): Delete.
	* config/sparc/sparc-protos.h (sparc_modes_tieable_p): Delete.
	* config/sparc/sparc.c (TARGET_MODES_TIEABLE_P): Redefine.
	(sparc_modes_tieable_p): Make static.
	* config/spu/spu.h (MODES_TIEABLE_P): Delete.
	* config/spu/spu.c (spu_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/stormy16/stormy16.h (MODES_TIEABLE_P): Delete.
	* config/stormy16/stormy16.c (xstormy16_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/tilegx/tilegx.h (MODES_TIEABLE_P): Delete.
	* config/tilepro/tilepro.h (MODES_TIEABLE_P): Delete.
	* config/v850/v850.h (MODES_TIEABLE_P): Delete.
	* config/v850/v850.c (v850_modes_tieable_p): New function.
	(TARGET_MODES_TIEABLE_P): Redefine.
	* config/vax/vax.h (MODES_TIEABLE_P): Delete.
	* config/visium/visium.h (MODES_TIEABLE_P): Delete.
	* config/visium/visium.c (TARGET_MODES_TIEABLE_P): Redefine.
	(visium_modes_tieable_p): New function.
	* config/xtensa/xtensa.h (MODES_TIEABLE_P): Delete.
	* config/xtensa/xtensa.c (TARGET_MODES_TIEABLE_P): Redefine.
	(xtensa_modes_tieable_p): New function.
	* system.h (MODES_TIEABLE_P): Poison.

Comments

Jeff Law Sept. 4, 2017, 5:27 a.m. | #1
On 08/28/2017 03:36 AM, Richard Sandiford wrote:
> The lack of function comments in msp430.c and rl78.c is deliberate;

> the local style there is to define the hook macro immediately before

> the function as a form of documentation.

> 

> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.

> Also tested by checking that there were no extra warnings or changes in

> testsuite assembly output for at least one target per CPU.  OK to install?

> 

> Richard

> 

> 

> 2017-08-27  Richard Sandiford  <richard.sandiford@linaro.org>

> 	    Alan Hayward  <alan.hayward@arm.com>

> 	    David Sherwood  <david.sherwood@arm.com>

> 

> gcc/

> 	* target.def (modes_tieable_p): New hook.

> 	* doc/tm.texi (MODES_TIEABLE_P): Replace with...

> 	(TARGET_MODES_TIEABLE_P): ...this.

> 	* doc/tm.texi.in: Regenerate.

> 	* hooks.h (hook_bool_mode_mode_true): Declare.

> 	* hooks.c (hook_bool_mode_mode_true): New function.

> 	* combine.c (subst): Use targetm.modes_tieable_p instead of

> 	MODES_TIEABLE_P.

> 	* dse.c (find_shift_sequence): Likewise.

> 	* expmed.c (extract_low_bits): Likewise.

> 	* lower-subreg.c: Include target.h.

> 	(find_decomposable_subregs): Use targetm.modes_tieable_p instead of

> 	MODES_TIEABLE_P.

> 	* rtlanal.c (rtx_cost): Likewise.

> 	* config/aarch64/aarch64.h (MODES_TIEABLE_P): Delete.

> 	* config/aarch64/aarch64-protos.h (aarch64_modes_tieable_p): Delete.

> 	* config/aarch64/aarch64.c (aarch64_modes_tieable_p): Make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/alpha/alpha.h (MODES_TIEABLE_P): Delete.

> 	* config/alpha/alpha.c (alpha_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/arc/arc.h (MODES_TIEABLE_P): Delete.

> 	* config/arc/arc.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(arc_modes_tieable_p): New function.

> 	* config/arm/arm.h (MODES_TIEABLE_P): Delete.

> 	* config/arm/arm-protos.h (arm_modes_tieable_p): Delete.

> 	* config/arm/arm.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(arm_modes_tieable_p): Make static.

> 	* config/avr/avr.h (MODES_TIEABLE_P): Delete.

> 	* config/bfin/bfin.h (MODES_TIEABLE_P): Delete.

> 	* config/bfin/bfin.c (bfin_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/c6x/c6x.h (MODES_TIEABLE_P): Delete.

> 	* config/c6x/c6x.c (c6x_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/cr16/cr16.h (MODES_TIEABLE_P): Delete.

> 	* config/cr16/cr16.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(cr16_modes_tieable_p): New function.

> 	* config/cris/cris.h (MODES_TIEABLE_P): Delete.

> 	* config/epiphany/epiphany.h (MODES_TIEABLE_P): Delete.

> 	* config/fr30/fr30.h (MODES_TIEABLE_P): Delete.

> 	(TRULY_NOOP_TRUNCATION): Update comment.

> 	* config/frv/frv.h (MODES_TIEABLE_P): Delete.

> 	(TRULY_NOOP_TRUNCATION): Update comment.

> 	* config/frv/frv.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(frv_modes_tieable_p): New function.

> 	* config/ft32/ft32.h (MODES_TIEABLE_P): Delete.

> 	* config/h8300/h8300.h (MODES_TIEABLE_P): Delete.

> 	* config/h8300/h8300.c (h8300_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/i386/i386.h (MODES_TIEABLE_P): Delete.

> 	* config/i386/i386-protos.h (ix86_modes_tieable_p): Delete.

> 	* config/i386/i386.c (ix86_modes_tieable_p): Make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/ia64/ia64.h (MODES_TIEABLE_P): Delete.

> 	* config/ia64/ia64.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(ia64_modes_tieable_p): New function.

> 	* config/iq2000/iq2000.h (MODES_TIEABLE_P): Delete.

> 	* config/iq2000/iq2000.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(iq2000_modes_tieable_p): New function.

> 	* config/lm32/lm32.h (MODES_TIEABLE_P): Delete.

> 	* config/lm32/lm32.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(lm32_modes_tieable_p): New function.

> 	* config/m32c/m32c.h (MODES_TIEABLE_P): Delete.

> 	* config/m32c/m32c-protos.h (m32c_modes_tieable_p): Delete.

> 	* config/m32c/m32c.c (m32c_modes_tieable_p): Make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/m32r/m32r.h (MODES_TIEABLE_P): Delete.

> 	* config/m32r/m32r.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(m32r_modes_tieable_p): New function.

> 	* config/m68k/m68k.h (MODES_TIEABLE_P): Delete.

> 	* config/m68k/m68k.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(m68k_modes_tieable_p): New function.

> 	* config/mcore/mcore.h (MODES_TIEABLE_P): Delete.

> 	* config/mcore/mcore.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(mcore_modes_tieable_p): New function.

> 	* config/microblaze/microblaze.h (MODES_TIEABLE_P): Delete.

> 	* config/microblaze/microblaze.c (microblaze_modes_tieable_p): New

> 	function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/mips/mips.h (MODES_TIEABLE_P): Delete.

> 	* config/mips/mips-protos.h (mips_modes_tieable_p): Delete.

> 	* config/mips/mips.c (mips_modes_tieable_p): Make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/mmix/mmix.h (MODES_TIEABLE_P): Delete.

> 	* config/mn10300/mn10300.h (MODES_TIEABLE_P): Delete.

> 	* config/mn10300/mn10300-protos.h (mn10300_modes_tieable): Delete.

> 	* config/mn10300/mn10300.c (mn10300_modes_tieable): Rename to...

> 	(mn10300_modes_tieable_p): ...this and make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/moxie/moxie.h (MODES_TIEABLE_P): Delete.

> 	* config/msp430/msp430.h (MODES_TIEABLE_P): Delete.

> 	* config/msp430/msp430-protos.h (msp430_modes_tieable_p): Delete.

> 	* config/msp430/msp430.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(msp430_modes_tieable_p): Make static.

> 	* config/nds32/nds32.h (MODES_TIEABLE_P): Delete.

> 	* config/nds32/nds32.c (nds32_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/nios2/nios2.h (MODES_TIEABLE_P): Delete.

> 	* config/nvptx/nvptx.h (MODES_TIEABLE_P): Delete.

> 	* config/nvptx/nvptx.c (nvptx_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/pa/pa.h (MODES_TIEABLE_P): Delete.

> 	* config/pa/pa-protos.h (pa_modes_tieable_p): Delete.

> 	* config/pa/pa.c (pa_modes_tieable_p): Make static.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/pdp11/pdp11.h (MODES_TIEABLE_P): Delete.

> 	* config/pdp11/pdp11.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(pdp11_modes_tieable_p): New function.

> 	* config/powerpcspe/powerpcspe.h (MODES_TIEABLE_P): Delete.

> 	* config/powerpcspe/powerpcspe.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(rs6000_modes_tieable_p): New function.

> 	(rs6000_debug_reg_global): Use it instead of MODES_TIEABLE_P.

> 	* config/powerpcspe/powerpcspe.md: Update comment.

> 	* config/riscv/riscv.h (MODES_TIEABLE_P): Delete.

> 	* config/riscv/riscv.c (riscv_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/rl78/rl78.h (MODES_TIEABLE_P): Delete.

> 	* config/rl78/rl78.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(rl78_modes_tieable_p): New function.

> 	* config/rs6000/rs6000.h (MODES_TIEABLE_P): Delete.

> 	* config/rs6000/rs6000.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(rs6000_modes_tieable_p): New function.

> 	(rs6000_debug_reg_global): Use it instead of MODES_TIEABLE_P.

> 	* config/rs6000/rs6000.md: Update comment.

> 	* config/rx/rx.h (MODES_TIEABLE_P): Delete.

> 	* config/rx/rx.c (rx_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/s390/s390.h (MODES_TIEABLE_P): Delete.

> 	* config/s390/s390.c (s390_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/sh/sh.h (MODES_TIEABLE_P): Delete.

> 	* config/sh/sh.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(sh_modes_tieable_p): New function.

> 	* config/sparc/sparc.h (MODES_TIEABLE_P): Delete.

> 	* config/sparc/sparc-protos.h (sparc_modes_tieable_p): Delete.

> 	* config/sparc/sparc.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(sparc_modes_tieable_p): Make static.

> 	* config/spu/spu.h (MODES_TIEABLE_P): Delete.

> 	* config/spu/spu.c (spu_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/stormy16/stormy16.h (MODES_TIEABLE_P): Delete.

> 	* config/stormy16/stormy16.c (xstormy16_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/tilegx/tilegx.h (MODES_TIEABLE_P): Delete.

> 	* config/tilepro/tilepro.h (MODES_TIEABLE_P): Delete.

> 	* config/v850/v850.h (MODES_TIEABLE_P): Delete.

> 	* config/v850/v850.c (v850_modes_tieable_p): New function.

> 	(TARGET_MODES_TIEABLE_P): Redefine.

> 	* config/vax/vax.h (MODES_TIEABLE_P): Delete.

> 	* config/visium/visium.h (MODES_TIEABLE_P): Delete.

> 	* config/visium/visium.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(visium_modes_tieable_p): New function.

> 	* config/xtensa/xtensa.h (MODES_TIEABLE_P): Delete.

> 	* config/xtensa/xtensa.c (TARGET_MODES_TIEABLE_P): Redefine.

> 	(xtensa_modes_tieable_p): New function.

> 	* system.h (MODES_TIEABLE_P): Poison.

OK.
jeff

Patch

Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-08-28 10:35:26.214037420 +0100
+++ gcc/target.def	2017-08-28 10:35:27.226537417 +0100
@@ -5406,8 +5406,8 @@  all narrower integer modes, it is not ne
 this hook to distinguish between these modes, provided you define\n\
 patterns @samp{movhi}, etc., to take advantage of this.  This is\n\
 useful because of the interaction between @code{TARGET_HARD_REGNO_MODE_OK}\n\
-and @code{MODES_TIEABLE_P}; it is very desirable for all integer modes\n\
-to be tieable.\n\
+and @code{TARGET_MODES_TIEABLE_P}; it is very desirable for all integer\n\
+modes to be tieable.\n\
 \n\
 Many machines have special registers for floating point arithmetic.\n\
 Often people assume that floating point machine modes are allowed only\n\
@@ -5440,6 +5440,25 @@  be used unless some pattern's constraint
  bool, (unsigned int regno, machine_mode mode),
  hook_bool_uint_mode_true)
 
+DEFHOOK
+(modes_tieable_p,
+ "This hook returns true if a value of mode @var{mode1} is accessible\n\
+in mode @var{mode2} without copying.\n\
+\n\
+If @code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode1})} and\n\
+@code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always\n\
+the same for any @var{r}, then\n\
+@code{TARGET_MODES_TIEABLE_P (@var{mode1}, @var{mode2})}\n\
+should be true.  If they differ for any @var{r}, you should define\n\
+this hook to return false unless some other mechanism ensures the\n\
+accessibility of the value in a narrower mode.\n\
+\n\
+You should define this hook to return true in as many cases as\n\
+possible since doing so will allow GCC to perform better register\n\
+allocation.  The default definition returns true unconditionally.",
+ bool, (machine_mode mode1, machine_mode mode2),
+ hook_bool_mode_mode_true)
+
 /* Return true if is OK to use a hard register REGNO as scratch register
    in peephole2.  */
 DEFHOOK
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-08-28 10:35:26.214037420 +0100
+++ gcc/doc/tm.texi	2017-08-28 10:35:27.223837417 +0100
@@ -2091,8 +2091,8 @@  all narrower integer modes, it is not ne
 this hook to distinguish between these modes, provided you define
 patterns @samp{movhi}, etc., to take advantage of this.  This is
 useful because of the interaction between @code{TARGET_HARD_REGNO_MODE_OK}
-and @code{MODES_TIEABLE_P}; it is very desirable for all integer modes
-to be tieable.
+and @code{TARGET_MODES_TIEABLE_P}; it is very desirable for all integer
+modes to be tieable.
 
 Many machines have special registers for floating point arithmetic.
 Often people assume that floating point machine modes are allowed only
@@ -2135,21 +2135,22 @@  handler.
 The default is always nonzero.
 @end defmac
 
-@defmac MODES_TIEABLE_P (@var{mode1}, @var{mode2})
-A C expression that is nonzero if a value of mode
-@var{mode1} is accessible in mode @var{mode2} without copying.
+@deftypefn {Target Hook} bool TARGET_MODES_TIEABLE_P (machine_mode @var{mode1}, machine_mode @var{mode2})
+This hook returns true if a value of mode @var{mode1} is accessible
+in mode @var{mode2} without copying.
 
 If @code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode1})} and
-@code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always the same
-for any @var{r}, then @code{MODES_TIEABLE_P (@var{mode1}, @var{mode2})}
-should be nonzero.  If they differ for any @var{r}, you should define
-this macro to return zero unless some other mechanism ensures the
+@code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always
+the same for any @var{r}, then
+@code{TARGET_MODES_TIEABLE_P (@var{mode1}, @var{mode2})}
+should be true.  If they differ for any @var{r}, you should define
+this hook to return false unless some other mechanism ensures the
 accessibility of the value in a narrower mode.
 
-You should define this macro to return nonzero in as many cases as
+You should define this hook to return true in as many cases as
 possible since doing so will allow GCC to perform better register
-allocation.
-@end defmac
+allocation.  The default definition returns true unconditionally.
+@end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_HARD_REGNO_SCRATCH_OK (unsigned int @var{regno})
 This target hook should return @code{true} if it is OK to use a hard register
@@ -10796,8 +10797,8 @@  On many machines, this expression can be
 
 @c rearranged this, removed the phrase "it is reported that".  this was
 @c to fix an overfull hbox.  --mew 10feb93
-When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for
-modes for which @code{MODES_TIEABLE_P} is 0, suboptimal code can result.
+When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for modes
+for which @code{TARGET_MODES_TIEABLE_P} is false, suboptimal code can result.
 If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
 such cases may improve things.
 @end defmac
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-08-28 10:35:26.214037420 +0100
+++ gcc/doc/tm.texi.in	2017-08-28 10:35:27.224737417 +0100
@@ -1871,21 +1871,7 @@  handler.
 The default is always nonzero.
 @end defmac
 
-@defmac MODES_TIEABLE_P (@var{mode1}, @var{mode2})
-A C expression that is nonzero if a value of mode
-@var{mode1} is accessible in mode @var{mode2} without copying.
-
-If @code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode1})} and
-@code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always the same
-for any @var{r}, then @code{MODES_TIEABLE_P (@var{mode1}, @var{mode2})}
-should be nonzero.  If they differ for any @var{r}, you should define
-this macro to return zero unless some other mechanism ensures the
-accessibility of the value in a narrower mode.
-
-You should define this macro to return nonzero in as many cases as
-possible since doing so will allow GCC to perform better register
-allocation.
-@end defmac
+@hook TARGET_MODES_TIEABLE_P
 
 @hook TARGET_HARD_REGNO_SCRATCH_OK
 
@@ -7610,8 +7596,8 @@  On many machines, this expression can be
 
 @c rearranged this, removed the phrase "it is reported that".  this was
 @c to fix an overfull hbox.  --mew 10feb93
-When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for
-modes for which @code{MODES_TIEABLE_P} is 0, suboptimal code can result.
+When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for modes
+for which @code{TARGET_MODES_TIEABLE_P} is false, suboptimal code can result.
 If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
 such cases may improve things.
 @end defmac
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/hooks.h	2017-08-28 10:35:27.225637417 +0100
@@ -30,6 +30,7 @@  extern bool hook_bool_bool_gcc_optionsp_
 extern bool hook_bool_const_int_const_int_true (const int, const int);
 extern bool hook_bool_mode_false (machine_mode);
 extern bool hook_bool_mode_true (machine_mode);
+extern bool hook_bool_mode_mode_true (machine_mode, machine_mode);
 extern bool hook_bool_mode_const_rtx_false (machine_mode, const_rtx);
 extern bool hook_bool_mode_const_rtx_true (machine_mode, const_rtx);
 extern bool hook_bool_mode_rtx_false (machine_mode, rtx);
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/hooks.c	2017-08-28 10:35:27.225637417 +0100
@@ -82,6 +82,13 @@  hook_bool_mode_true (machine_mode)
   return true;
 }
 
+/* Generic hook that takes (machine_mode, machine_mode) and returns true.  */
+bool
+hook_bool_mode_mode_true (machine_mode, machine_mode)
+{
+  return true;
+}
+
 /* Generic hook that takes (machine_mode, const_rtx) and returns false.  */
 bool
 hook_bool_mode_const_rtx_false (machine_mode, const_rtx)
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/combine.c	2017-08-28 10:35:27.186037417 +0100
@@ -5419,11 +5419,11 @@  #define COMBINE_RTX_EQUAL_P(X,Y)			\
 		     FROM to CC0.  */
 
 		  if (GET_CODE (to) == SUBREG
-		      && ! MODES_TIEABLE_P (GET_MODE (to),
-					    GET_MODE (SUBREG_REG (to)))
+		      && !targetm.modes_tieable_p (GET_MODE (to),
+						   GET_MODE (SUBREG_REG (to)))
 		      && ! (code == SUBREG
-			    && MODES_TIEABLE_P (GET_MODE (x),
-						GET_MODE (SUBREG_REG (to))))
+			    && (targetm.modes_tieable_p
+				(GET_MODE (x), GET_MODE (SUBREG_REG (to)))))
 		      && (!HAVE_cc0
 			  || (! (code == SET
 				 && i == 1
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/dse.c	2017-08-28 10:35:27.224737417 +0100
@@ -1628,7 +1628,7 @@  find_shift_sequence (int access_size,
       /* Also try a wider mode if the necessary punning is either not
 	 desirable or not possible.  */
       if (!CONSTANT_P (store_info->rhs)
-	  && !MODES_TIEABLE_P (new_mode, store_mode))
+	  && !targetm.modes_tieable_p (new_mode, store_mode))
 	continue;
 
       new_reg = gen_reg_rtx (new_mode);
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/expmed.c	2017-08-28 10:35:27.225637417 +0100
@@ -2235,7 +2235,7 @@  extract_low_bits (machine_mode mode, mac
     return NULL_RTX;
 
   if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (src_mode)
-      && MODES_TIEABLE_P (mode, src_mode))
+      && targetm.modes_tieable_p (mode, src_mode))
     {
       rtx x = gen_lowpart_common (mode, src);
       if (x)
@@ -2247,9 +2247,9 @@  extract_low_bits (machine_mode mode, mac
   if (src_int_mode == BLKmode || int_mode == BLKmode)
     return NULL_RTX;
 
-  if (!MODES_TIEABLE_P (src_int_mode, src_mode))
+  if (!targetm.modes_tieable_p (src_int_mode, src_mode))
     return NULL_RTX;
-  if (!MODES_TIEABLE_P (int_mode, mode))
+  if (!targetm.modes_tieable_p (int_mode, mode))
     return NULL_RTX;
 
   src = gen_lowpart (src_int_mode, src);
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/lower-subreg.c	2017-08-28 10:35:27.225637417 +0100
@@ -40,6 +40,7 @@  Software Foundation; either version 3, o
 #include "tree-pass.h"
 #include "lower-subreg.h"
 #include "rtl-iter.h"
+#include "target.h"
 
 
 /* Decompose multi-word pseudo-registers into individual
@@ -497,7 +498,7 @@  find_decomposable_subregs (rtx *loc, enu
 	     likely to mess up whatever the backend is trying to do.  */
 	  if (outer_words > 1
 	      && outer_size == inner_size
-	      && !MODES_TIEABLE_P (GET_MODE (x), GET_MODE (inner)))
+	      && !targetm.modes_tieable_p (GET_MODE (x), GET_MODE (inner)))
 	    {
 	      bitmap_set_bit (non_decomposable_context, regno);
 	      bitmap_set_bit (subreg_context, regno);
@@ -535,7 +536,7 @@  find_decomposable_subregs (rtx *loc, enu
 		  bitmap_set_bit (non_decomposable_context, regno);
 		  break;
 		case DECOMPOSABLE_SIMPLE_MOVE:
-		  if (MODES_TIEABLE_P (GET_MODE (x), word_mode))
+		  if (targetm.modes_tieable_p (GET_MODE (x), word_mode))
 		    bitmap_set_bit (decomposable_context, regno);
 		  break;
 		case SIMPLE_MOVE:
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/rtlanal.c	2017-08-28 10:35:27.226537417 +0100
@@ -4172,12 +4172,12 @@  rtx_cost (rtx x, machine_mode mode, enum
       total = 0;
       /* If we can't tie these modes, make this expensive.  The larger
 	 the mode, the more expensive it is.  */
-      if (! MODES_TIEABLE_P (mode, GET_MODE (SUBREG_REG (x))))
+      if (!targetm.modes_tieable_p (mode, GET_MODE (SUBREG_REG (x))))
 	return COSTS_N_INSNS (2 + factor);
       break;
 
     case TRUNCATE:
-      if (MODES_TIEABLE_P (mode, GET_MODE (XEXP (x, 0))))
+      if (targetm.modes_tieable_p (mode, GET_MODE (XEXP (x, 0))))
 	{
 	  total = 0;
 	  break;
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/aarch64/aarch64.h	2017-08-28 10:35:27.186937417 +0100
@@ -403,8 +403,6 @@  #define DWARF_FRAME_RETURN_COLUMN	DWARF_
 
 #define HARD_REGNO_NREGS(REGNO, MODE)	aarch64_hard_regno_nregs (REGNO, MODE)
 
-#define MODES_TIEABLE_P(MODE1, MODE2) aarch64_modes_tieable_p (MODE1, MODE2)
-
 #define DWARF2_UNWIND_INFO 1
 
 /* Use R0 through R3 to pass exception handling information.  */
Index: gcc/config/aarch64/aarch64-protos.h
===================================================================
--- gcc/config/aarch64/aarch64-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/aarch64/aarch64-protos.h	2017-08-28 10:35:27.186037417 +0100
@@ -339,8 +339,6 @@  bool aarch64_label_mentioned_p (rtx);
 void aarch64_declare_function_name (FILE *, const char*, tree);
 bool aarch64_legitimate_pic_operand_p (rtx);
 bool aarch64_mask_and_shift_for_ubfiz_p (machine_mode, rtx, rtx);
-bool aarch64_modes_tieable_p (machine_mode mode1,
-			      machine_mode mode2);
 bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
 bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
 bool aarch64_mov_operand_p (rtx, machine_mode);
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/aarch64/aarch64.c	2017-08-28 10:35:27.186937417 +0100
@@ -13848,16 +13848,15 @@  aarch64_reverse_mask (machine_mode mode)
   return force_reg (V16QImode, mask);
 }
 
-/* Implement MODES_TIEABLE_P.  In principle we should always return true.
-   However due to issues with register allocation it is preferable to avoid
-   tieing integer scalar and FP scalar modes.  Executing integer operations
-   in general registers is better than treating them as scalar vector
-   operations.  This reduces latency and avoids redundant int<->FP moves.
-   So tie modes if they are either the same class, or vector modes with
-   other vector modes, vector structs or any scalar mode.
-*/
+/* Implement TARGET_MODES_TIEABLE_P.  In principle we should always return
+   true.  However due to issues with register allocation it is preferable
+   to avoid tieing integer scalar and FP scalar modes.  Executing integer
+   operations in general registers is better than treating them as scalar
+   vector operations.  This reduces latency and avoids redundant int<->FP
+   moves.  So tie modes if they are either the same class, or vector modes
+   with other vector modes, vector structs or any scalar mode.  */
 
-bool
+static bool
 aarch64_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2))
@@ -15657,6 +15656,9 @@  #define TARGET_CUSTOM_FUNCTION_DESCRIPTO
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK aarch64_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P aarch64_modes_tieable_p
+
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   aarch64_hard_regno_call_part_clobbered
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/alpha/alpha.h	2017-08-28 10:35:27.187837417 +0100
@@ -385,17 +385,6 @@  #define REG_ALLOC_ORDER { \
 #define HARD_REGNO_NREGS(REGNO, MODE)   \
   CEIL (GET_MODE_SIZE (MODE), UNITS_PER_WORD)
 
-/* A C expression that is nonzero if a value of mode
-   MODE1 is accessible in mode MODE2 without copying.
-
-   This asymmetric test is true when MODE1 could be put
-   in an FP register but MODE2 could not.  */
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 				\
-  (targetm.hard_regno_mode_ok (32, (MODE1))			\
-   ? targetm.hard_regno_mode_ok (32, (MODE2))			\
-   : 1)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/alpha/alpha.c	2017-08-28 10:35:27.187837417 +0100
@@ -9907,6 +9907,17 @@  alpha_hard_regno_mode_ok (unsigned int r
 	    || mode == DCmode);
   return true;
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  This asymmetric test is true when
+   MODE1 could be put in an FP register but MODE2 could not.  */
+
+static bool
+alpha_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (alpha_hard_regno_mode_ok (32, mode1)
+	  ? alpha_hard_regno_mode_ok (32, mode2)
+	  : true);
+}
 
 /* Initialize the GCC target structure.  */
 #if TARGET_ABI_OPEN_VMS
@@ -10104,6 +10115,9 @@  #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK alpha_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P alpha_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
Index: gcc/config/arc/arc.h
===================================================================
--- gcc/config/arc/arc.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/arc/arc.h	2017-08-28 10:35:27.188737417 +0100
@@ -450,21 +450,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE) \
   && REGNO >= ARC_FIRST_SIMD_VR_REG && REGNO <= ARC_LAST_SIMD_VR_REG) ? 1 \
  : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose
-   register allocation so as to avoid move instructions between a
-   value of mode MODE1 and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `TARGET_MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-
-/* Tie QI/HI/SI modes together.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-(GET_MODE_CLASS (MODE1) == MODE_INT		\
- && GET_MODE_CLASS (MODE2) == MODE_INT		\
- && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD	\
- && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
-
 /* Internal macros to classify a register number as to whether it's a
    general purpose register for compact insns (r0-r3,r12-r15), or
    stack pointer (r28).  */
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/arc/arc.c	2017-08-28 10:35:27.188737417 +0100
@@ -540,6 +540,9 @@  #define TARGET_DWARF_REGISTER_SPAN arc_d
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK arc_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P arc_modes_tieable_p
+
 /* Try to keep the (mov:DF _, reg) as early as possible so
    that the d<add/sub/mul>h-lr insns appear together and can
    use the peephole2 pattern.  */
@@ -1836,6 +1839,17 @@  arc_hard_regno_mode_ok (unsigned int reg
   return (arc_hard_regno_modes[regno] & arc_mode_class[mode]) != 0;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  Tie QI/HI/SI modes together.  */
+
+static bool
+arc_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == MODE_INT
+	  && GET_MODE_CLASS (mode2) == MODE_INT
+	  && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	  && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
+}
+
 /* Handle an "interrupt" attribute; arguments as in
    struct attribute_spec.handler.  */
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/arm/arm.h	2017-08-28 10:35:27.190537417 +0100
@@ -990,8 +990,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
     && !IS_VFP_REGNUM (REGNO)		\
    ? 1 : ARM_NUM_REGS (MODE))
 
-#define MODES_TIEABLE_P(MODE1, MODE2) arm_modes_tieable_p (MODE1, MODE2)
-
 #define VALID_IWMMXT_REG_MODE(MODE) \
  (arm_vector_mode_supported_p (MODE) || (MODE) == DImode)
 
Index: gcc/config/arm/arm-protos.h
===================================================================
--- gcc/config/arm/arm-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/arm/arm-protos.h	2017-08-28 10:35:27.188737417 +0100
@@ -61,7 +61,6 @@  extern void arm_gen_unlikely_cbranch (en
 				      rtx label_ref);
 extern bool arm_vector_mode_supported_p (machine_mode);
 extern bool arm_small_register_classes_for_mode_p (machine_mode);
-extern bool arm_modes_tieable_p (machine_mode, machine_mode);
 extern int const_ok_for_arm (HOST_WIDE_INT);
 extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
 extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/arm/arm.c	2017-08-28 10:35:27.190537417 +0100
@@ -314,6 +314,7 @@  static unsigned int arm_elf_section_type
 static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
 static machine_mode arm_floatn_mode (int, bool);
 static bool arm_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool arm_modes_tieable_p (machine_mode, machine_mode);
 
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -783,6 +784,9 @@  #define TARGET_FIXED_CONDITION_CODE_REGS
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK arm_hard_regno_mode_ok
+
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P arm_modes_tieable_p
 
 /* Obstack for minipool constant handling.  */
 static struct obstack minipool_obstack;
@@ -23426,9 +23430,9 @@  arm_hard_regno_mode_ok (unsigned int reg
   return false;
 }
 
-/* Implement MODES_TIEABLE_P.  */
+/* Implement TARGET_MODES_TIEABLE_P.  */
 
-bool
+static bool
 arm_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2))
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/avr/avr.h	2017-08-28 10:35:27.191437417 +0100
@@ -212,8 +212,6 @@  #define ADJUST_REG_ALLOC_ORDER avr_adjus
 #define HARD_REGNO_NREGS(REGNO, MODE)                                   \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
 enum reg_class {
   NO_REGS,
   R0_REG,			/* r0 */
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/bfin/bfin.h	2017-08-28 10:35:27.191437417 +0100
@@ -692,23 +692,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE) \
    considered for use as a rename register for FROM register */
 #define HARD_REGNO_RENAME_OK(FROM, TO) bfin_hard_regno_rename_ok (FROM, TO)
 
-/* A C expression that is nonzero if it is desirable to choose
-   register allocation so as to avoid move instructions between a
-   value of mode MODE1 and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero. */
-#define MODES_TIEABLE_P(MODE1, MODE2)			\
- ((MODE1) == (MODE2)					\
-  || ((GET_MODE_CLASS (MODE1) == MODE_INT		\
-       || GET_MODE_CLASS (MODE1) == MODE_FLOAT)		\
-      && (GET_MODE_CLASS (MODE2) == MODE_INT		\
-	  || GET_MODE_CLASS (MODE2) == MODE_FLOAT)	\
-      && (MODE1) != BImode && (MODE2) != BImode		\
-      && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD	\
-      && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD))
-
 /* `PREFERRED_RELOAD_CLASS (X, CLASS)'
    A C expression that places additional restrictions on the register
    class to use when it is necessary to copy value X into a register
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/bfin/bfin.c	2017-08-28 10:35:27.191437417 +0100
@@ -2146,6 +2146,21 @@  bfin_hard_regno_mode_ok (unsigned int re
   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+bfin_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || ((GET_MODE_CLASS (mode1) == MODE_INT
+	       || GET_MODE_CLASS (mode1) == MODE_FLOAT)
+	      && (GET_MODE_CLASS (mode2) == MODE_INT
+		  || GET_MODE_CLASS (mode2) == MODE_FLOAT)
+	      && mode1 != BImode && mode2 != BImode
+	      && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	      && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
+}
+
 /* Implements target hook vector_mode_supported_p.  */
 
 static bool
@@ -5850,4 +5865,7 @@  #define TARGET_CAN_USE_DOLOOP_P bfin_can
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P bfin_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/c6x/c6x.h
===================================================================
--- gcc/config/c6x/c6x.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/c6x/c6x.h	2017-08-28 10:35:27.193237417 +0100
@@ -185,11 +185,6 @@  #define HARD_REGNO_NREGS(regno, mode)		\
   ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)  \
    / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(mode1, mode2)	       \
-  ((mode1) == (mode2) ||		       \
-   (GET_MODE_SIZE (mode1) <= UNITS_PER_WORD && \
-    GET_MODE_SIZE (mode2) <= UNITS_PER_WORD))
-
 
 /* Register Classes.  */
 
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/c6x/c6x.c	2017-08-28 10:35:27.193237417 +0100
@@ -6705,6 +6705,17 @@  c6x_hard_regno_mode_ok (unsigned int reg
 {
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD || (regno & 1) == 0;
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+c6x_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || (GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	      && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
+}
+
 
 /* Target Structure.  */
 
@@ -6873,6 +6884,8 @@  #define TARGET_BUILTIN_DECL c6x_builtin_
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK c6x_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P c6x_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
Index: gcc/config/cr16/cr16.h
===================================================================
--- gcc/config/cr16/cr16.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/cr16/cr16.h	2017-08-28 10:35:27.193237417 +0100
@@ -247,9 +247,6 @@  #define RETURN_ADDR_RTX(COUNT, FRAME)
   (0 == COUNT)	?  gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA)		\
 		:  const0_rtx
 
-#define MODES_TIEABLE_P(MODE1, MODE2)  \
-  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
-
 enum reg_class
 {
   NO_REGS,
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/cr16/cr16.c	2017-08-28 10:35:27.193237417 +0100
@@ -222,6 +222,8 @@  #define TARGET_ASM_UNALIGNED_DI_OP 	TARG
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK	cr16_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P		cr16_modes_tieable_p
 
 /* Target hook implementations.  */
 
@@ -493,6 +495,13 @@  cr16_hard_regno_mode_ok (unsigned int re
   return true;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+static bool
+cr16_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2);
+}
+
 /* Returns register number for function return value.*/
 static inline unsigned int
 cr16_ret_register (void)
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/cris/cris.h	2017-08-28 10:35:27.193237417 +0100
@@ -477,12 +477,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)	\
  (MODE == VOIDmode \
   ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Because CCmode isn't covered by the "narrower mode" statement in
-   tm.texi, we can still say all modes are tieable despite not having an
-   always 1 TARGET_HARD_REGNO_MODE_OK.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
-
 /* Node: Leaf Functions */
 /* (no definitions) */
 
Index: gcc/config/epiphany/epiphany.h
===================================================================
--- gcc/config/epiphany/epiphany.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/epiphany/epiphany.h	2017-08-28 10:35:27.194137417 +0100
@@ -309,16 +309,6 @@  #define HARD_REGNO_RENAME_OK(SRC, DST) e
 #define HARD_REGNO_NREGS(REGNO, MODE) \
 ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose
-   register allocation so as to avoid move instructions between a
-   value of mode MODE1 and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
 /* Register classes and constants.  */
 
 /* Define the classes of registers for register constraints in the
Index: gcc/config/fr30/fr30.h
===================================================================
--- gcc/config/fr30/fr30.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/fr30/fr30.h	2017-08-28 10:35:27.194137417 +0100
@@ -246,15 +246,6 @@  #define ADDITIONAL_REGISTER_NAMES 				\
 #define HARD_REGNO_NREGS(REGNO, MODE) 			\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose register
-   allocation so as to avoid move instructions between a value of mode MODE1
-   and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
 /*}}}*/ 
 /*{{{  Register Classes.  */ 
 
@@ -810,9 +801,9 @@  #define MOVE_MAX 8
    On many machines, this expression can be 1.
 
    When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
-   which `MODES_TIEABLE_P' is 0, suboptimal code can result.  If this is the
-   case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
-   things.  */
+   which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
+   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in such
+   cases may improve things.  */
 #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
 
 /* An alias for the machine mode for pointers.  On most machines, define this
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/frv/frv.h	2017-08-28 10:35:27.195037417 +0100
@@ -763,15 +763,6 @@  #define REG_ALLOC_ORDER							\
    we can build the appropriate instructions to properly reload the values.  */
 #define HARD_REGNO_NREGS(REGNO, MODE) frv_hard_regno_nregs (REGNO, MODE)
 
-/* A C expression that is nonzero if it is desirable to choose register
-   allocation so as to avoid move instructions between a value of mode MODE1
-   and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) (MODE1 == MODE2)
-
 /* Define this macro if the compiler should avoid copies to/from CCmode
    registers.  You should only define this macro if support fo copying to/from
    CCmode is incomplete.  */
@@ -1855,10 +1846,10 @@  #define MOVE_MAX 8
 
    On many machines, this expression can be 1.
 
-   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
-   which `MODES_TIEABLE_P' is 0, suboptimal code can result.  If this is the
-   case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
-   things.  */
+   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes
+   for which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
+   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in such
+   cases may improve things.  */
 #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
 
 /* An alias for the machine mode for pointers.  On most machines, define this
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/frv/frv.c	2017-08-28 10:35:27.194137417 +0100
@@ -400,6 +400,7 @@  static void frv_conditional_register_usa
 static void frv_trampoline_init			(rtx, tree, rtx);
 static bool frv_class_likely_spilled_p 		(reg_class_t);
 static bool frv_hard_regno_mode_ok		(unsigned int, machine_mode);
+static bool frv_modes_tieable_p			(machine_mode, machine_mode);
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_PRINT_OPERAND
@@ -519,6 +520,8 @@  #define TARGET_LIBCALL_VALUE frv_libcall
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK frv_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P frv_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -6590,6 +6593,14 @@  frv_hard_regno_mode_ok (unsigned int reg
   return false;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+frv_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return mode1 == mode2;
+}
+
 
 /* A C expression for the number of consecutive hard registers, starting at
    register number REGNO, required to hold a value of mode MODE.
Index: gcc/config/ft32/ft32.h
===================================================================
--- gcc/config/ft32/ft32.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/ft32/ft32.h	2017-08-28 10:35:27.195037417 +0100
@@ -178,10 +178,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)             \
    / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if a value of mode MODE1 is
-   accessible in mode MODE2 without copying.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
 /* The Overall Framework of an Assembler File */
 
 #undef  ASM_SPEC
Index: gcc/config/h8300/h8300.h
===================================================================
--- gcc/config/h8300/h8300.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/h8300/h8300.h	2017-08-28 10:35:27.195037417 +0100
@@ -239,17 +239,6 @@  #define REG_ALLOC_ORDER				\
 #define HARD_REGNO_NREGS(REGNO, MODE)		\
   h8300_hard_regno_nregs ((REGNO), (MODE))
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)					  \
-  ((MODE1) == (MODE2)							  \
-   || (((MODE1) == QImode || (MODE1) == HImode				  \
-	|| ((TARGET_H8300H || TARGET_H8300S) && (MODE1) == SImode))	  \
-       &&  ((MODE2) == QImode || (MODE2) == HImode			  \
-	    || ((TARGET_H8300H || TARGET_H8300S) && (MODE2) == SImode))))
-
 /* A C expression that is nonzero if hard register NEW_REG can be
    considered for use as a rename register for OLD_REG register */
 
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/h8300/h8300.c	2017-08-28 10:35:27.195037417 +0100
@@ -5904,6 +5904,20 @@  h8300_hard_regno_mode_ok (unsigned int r
     return regno == MAC_REG ? mode == SImode : 1;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+h8300_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || ((mode1 == QImode
+	       || mode1 == HImode
+	       || ((TARGET_H8300H || TARGET_H8300S) && mode1 == SImode))
+	      && (mode2 == QImode
+		  || mode2 == HImode
+		  || ((TARGET_H8300H || TARGET_H8300S) && mode2 == SImode))));
+}
+
 /* Helper function for the move patterns.  Make sure a move is legitimate.  */
 
 bool
@@ -6104,6 +6118,9 @@  #define TARGET_HARD_REGNO_SCRATCH_OK h83
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK h8300_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P h8300_modes_tieable_p
+
 #undef TARGET_LRA_P
 #define TARGET_LRA_P hook_bool_void_false
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/i386/i386.h	2017-08-28 10:35:27.198637417 +0100
@@ -1181,14 +1181,6 @@  #define FMA4_VEC_FLOAT_MODE_P(MODE) \
   (TARGET_FMA4 && ((MODE) == V4SFmode || (MODE) == V2DFmode \
 		  || (MODE) == V8SFmode || (MODE) == V4DFmode))
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  ix86_modes_tieable_p ((MODE1), (MODE2))
-
 /* It is possible to write patterns to move flags; but until someone
    does it,  */
 #define AVOID_CCMODE_COPIES
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/i386/i386-protos.h	2017-08-28 10:35:27.195037417 +0100
@@ -167,7 +167,6 @@  extern int ix86_reg_parm_stack_space (co
 
 extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
 				  rtx, rtx, rtx);
-extern bool ix86_modes_tieable_p (machine_mode, machine_mode);
 extern bool ix86_secondary_memory_needed (enum reg_class, enum reg_class,
 					  machine_mode, int);
 extern bool ix86_cannot_change_mode_class (machine_mode,
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/i386/i386.c	2017-08-28 10:35:27.198637417 +0100
@@ -41430,11 +41430,13 @@  ix86_tieable_integer_mode_p (machine_mod
     }
 }
 
-/* Return true if MODE1 is accessible in a register that can hold MODE2
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   Return true if MODE1 is accessible in a register that can hold MODE2
    without copying.  That is, all register classes that can hold MODE2
    can also hold MODE1.  */
 
-bool
+static bool
 ix86_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (mode1 == mode2)
@@ -53252,6 +53254,9 @@  #define TARGET_NOCE_CONVERSION_PROFITABL
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK ix86_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P ix86_modes_tieable_p
+
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   ix86_hard_regno_call_part_clobbered
Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/ia64/ia64.h	2017-08-28 10:35:27.199537417 +0100
@@ -614,22 +614,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
    : FR_REGNO_P (REGNO) && (MODE) == XCmode ? 2				\
    : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose register
-   allocation so as to avoid move instructions between a value of mode MODE1
-   and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-/* Don't tie integer and FP modes, as that causes us to get integer registers
-   allocated for FP instructions.  XFmode only supported in FP registers so
-   we can't tie it with any other modes.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)			\
-  (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)	\
-   && ((((MODE1) == XFmode) || ((MODE1) == XCmode) || ((MODE1) == RFmode))	\
-       == (((MODE2) == XFmode) || ((MODE2) == XCmode) || ((MODE2) == RFmode)))	\
-   && (((MODE1) == BImode) == ((MODE2) == BImode)))
-
 /* Specify the modes required to caller save a given hard regno.
    We need to ensure floating pt regs are not saved as DImode.  */
 
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/ia64/ia64.c	2017-08-28 10:35:27.199537417 +0100
@@ -336,6 +336,7 @@  static bool ia64_vectorize_vec_perm_cons
 					      const unsigned char *sel);
 
 static bool ia64_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool ia64_modes_tieable_p (machine_mode, machine_mode);
 
 #define MAX_VECT_LEN	8
 
@@ -658,6 +659,9 @@  #define TARGET_CUSTOM_FUNCTION_DESCRIPTO
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK ia64_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P ia64_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain
@@ -4281,6 +4285,21 @@  ia64_hard_regno_mode_ok (unsigned int re
   return false;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   Don't tie integer and FP modes, as that causes us to get integer registers
+   allocated for FP instructions.  XFmode only supported in FP registers so
+   we can't tie it with any other modes.  */
+
+static bool
+ia64_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2)
+	  && ((mode1 == XFmode || mode1 == XCmode || mode1 == RFmode)
+	      == (mode2 == XFmode || mode2 == XCmode || mode2 == RFmode))
+	  && (mode1 == BImode) == (mode2 == BImode));
+}
+
 /* Target hook for assembling integer objects.  Handle word-sized
    aligned objects and detect the cases when @fptr is needed.  */
 
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/iq2000/iq2000.h	2017-08-28 10:35:27.200437417 +0100
@@ -165,12 +165,6 @@  #define REG_ALLOC_ORDER							\
 #define HARD_REGNO_NREGS(REGNO, MODE)   \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)				\
-  ((GET_MODE_CLASS (MODE1) == MODE_FLOAT ||			\
-    GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)		\
-   == (GET_MODE_CLASS (MODE2) == MODE_FLOAT ||			\
-       GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
-
 #define AVOID_CCMODE_COPIES
 
 
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/iq2000/iq2000.c	2017-08-28 10:35:27.199537417 +0100
@@ -178,6 +178,7 @@  static void iq2000_print_operand      (F
 static void iq2000_print_operand_address (FILE *, machine_mode, rtx);
 static bool iq2000_print_operand_punct_valid_p (unsigned char code);
 static bool iq2000_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool iq2000_modes_tieable_p (machine_mode, machine_mode);
 
 #undef  TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS 		iq2000_init_builtins
@@ -257,6 +258,8 @@  #define TARGET_TRAMPOLINE_INIT		iq2000_t
 
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK	iq2000_hard_regno_mode_ok
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P		iq2000_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -3499,4 +3502,15 @@  iq2000_hard_regno_mode_ok (unsigned int
 	  : (regno & 1) == 0 || GET_MODE_SIZE (mode) == 4);
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+iq2000_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
+
 #include "gt-iq2000.h"
Index: gcc/config/lm32/lm32.h
===================================================================
--- gcc/config/lm32/lm32.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/lm32/lm32.h	2017-08-28 10:35:27.200437417 +0100
@@ -166,12 +166,6 @@  #define CALL_USED_REGISTERS \
 #define HARD_REGNO_NREGS(REGNO, MODE)                                   \
     ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)           \
-(      GET_MODE_CLASS (MODE1) == MODE_INT		\
-    && GET_MODE_CLASS (MODE2) == MODE_INT		\
-    && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD	\
-    && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
-
 #define AVOID_CCMODE_COPIES
 
 /*----------------------------------*/
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/lm32/lm32.c	2017-08-28 10:35:27.200437417 +0100
@@ -78,6 +78,7 @@  static void lm32_function_arg_advance (c
 				       machine_mode mode,
 				       const_tree type, bool named);
 static bool lm32_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool lm32_modes_tieable_p (machine_mode, machine_mode);
 
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE lm32_option_override
@@ -109,6 +110,8 @@  #define TARGET_LRA_P hook_bool_void_fals
 #define TARGET_LEGITIMATE_ADDRESS_P lm32_legitimate_address_p
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK lm32_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P lm32_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -1232,3 +1235,14 @@  lm32_hard_regno_mode_ok (unsigned int re
 {
   return G_REG_P (regno);
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+lm32_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == MODE_INT
+	  && GET_MODE_CLASS (mode2) == MODE_INT
+	  && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	  && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
+}
Index: gcc/config/m32c/m32c.h
===================================================================
--- gcc/config/m32c/m32c.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m32c/m32c.h	2017-08-28 10:35:27.200437417 +0100
@@ -256,7 +256,6 @@  #define REG_ALLOC_ORDER { \
 /* How Values Fit in Registers */
 
 #define HARD_REGNO_NREGS(R,M) m32c_hard_regno_nregs (R, M)
-#define MODES_TIEABLE_P(M1,M2) m32c_modes_tieable_p (M1, M2)
 #define AVOID_CCMODE_COPIES
 
 /* Register Classes */
Index: gcc/config/m32c/m32c-protos.h
===================================================================
--- gcc/config/m32c/m32c-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m32c/m32c-protos.h	2017-08-28 10:35:27.200437417 +0100
@@ -55,7 +55,6 @@  bool m32c_immd_dbl_mov (rtx *, machine_m
 rtx  m32c_incoming_return_addr_rtx (void);
 int  m32c_legitimize_reload_address (rtx *, machine_mode, int, int, int);
 int  m32c_limit_reload_class (machine_mode, int);
-int  m32c_modes_tieable_p (machine_mode, machine_mode);
 bool m32c_mov_ok (rtx *, machine_mode);
 char * m32c_output_compare (rtx_insn *, rtx *);
 int  m32c_prepare_move (rtx *, machine_mode);
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m32c/m32c.c	2017-08-28 10:35:27.200437417 +0100
@@ -583,11 +583,11 @@  m32c_hard_regno_mode_ok (unsigned int re
   return m32c_hard_regno_nregs_1 (regno, mode) != 0;
 }
 
-/* Implements MODES_TIEABLE_P.  In general, modes aren't tieable since
+/* Implement TARGET_MODES_TIEABLE_P.  In general, modes aren't tieable since
    registers are all different sizes.  However, since most modes are
    bigger than our registers anyway, it's easier to implement this
    function that way, leaving QImode as the only unique case.  */
-int
+static bool
 m32c_modes_tieable_p (machine_mode m1, machine_mode m2)
 {
   if (GET_MODE_SIZE (m1) == GET_MODE_SIZE (m2))
@@ -4491,6 +4491,8 @@  #define TARGET_FRAME_POINTER_REQUIRED ho
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK m32c_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P m32c_modes_tieable_p
 
 /* The Global `targetm' Variable. */
 
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m32r/m32r.h	2017-08-28 10:35:27.202237417 +0100
@@ -396,21 +396,6 @@  #define REG_ALLOC_ORDER				\
 #define HARD_REGNO_NREGS(REGNO, MODE) \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose
-   register allocation so as to avoid move instructions between a
-   value of mode MODE1 and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-
-/* Tie QI/HI/SI modes together.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 		\
-  (   GET_MODE_CLASS (MODE1) == MODE_INT	\
-   && GET_MODE_CLASS (MODE2) == MODE_INT	\
-   && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD	\
-   && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
-
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
   m32r_hard_regno_rename_ok (OLD_REG, NEW_REG)
 
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m32r/m32r.c	2017-08-28 10:35:27.202237417 +0100
@@ -103,6 +103,7 @@  static void m32r_trampoline_init (rtx, t
 static bool m32r_legitimate_constant_p (machine_mode, rtx);
 static bool m32r_attribute_identifier (const_tree);
 static bool m32r_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool m32r_modes_tieable_p (machine_mode, machine_mode);
 
 /* M32R specific attributes.  */
 
@@ -213,6 +214,9 @@  #define TARGET_LEGITIMATE_CONSTANT_P m32
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK m32r_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P m32r_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Called by m32r_option_override to initialize various things.  */
@@ -2759,6 +2763,17 @@  m32r_hard_regno_mode_ok (unsigned int re
   return (m32r_hard_regno_modes[regno] & m32r_mode_class[mode]) != 0;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  Tie QI/HI/SI modes together.  */
+
+static bool
+m32r_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == MODE_INT
+	  && GET_MODE_CLASS (mode2) == MODE_INT
+	  && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	  && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
+}
+
 /* Return true if using NEW_REG in place of OLD_REG is ok.  */
 
 int
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m68k/m68k.h	2017-08-28 10:35:27.202237417 +0100
@@ -397,13 +397,6 @@  #define HARD_REGNO_RENAME_OK(OLD_REG, NE
 #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
   m68k_secondary_reload_class (CLASS, MODE, X)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)			\
-  (! TARGET_HARD_FLOAT					\
-   || ((GET_MODE_CLASS (MODE1) == MODE_FLOAT		\
-	|| GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)	\
-       == (GET_MODE_CLASS (MODE2) == MODE_FLOAT		\
-	   || GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT)))
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/m68k/m68k.c	2017-08-28 10:35:27.202237417 +0100
@@ -188,6 +188,7 @@  static void m68k_init_sync_libfuncs (voi
 static enum flt_eval_method
 m68k_excess_precision (enum excess_precision_type);
 static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool m68k_modes_tieable_p (machine_mode, machine_mode);
 
 /* Initialize the GCC target structure.  */
 
@@ -338,6 +339,9 @@  #define TARGET_ATOMIC_TEST_AND_SET_TRUEV
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK m68k_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P m68k_modes_tieable_p
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
@@ -5204,6 +5208,18 @@  m68k_hard_regno_mode_ok (unsigned int re
   return false;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+m68k_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (!TARGET_HARD_FLOAT
+	  || ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	       || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	      == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+		  || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT)));
+}
+
 /* Implement SECONDARY_RELOAD_CLASS.  */
 
 enum reg_class
Index: gcc/config/mcore/mcore.h
===================================================================
--- gcc/config/mcore/mcore.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mcore/mcore.h	2017-08-28 10:35:27.203137417 +0100
@@ -248,13 +248,6 @@  #define REG_ALLOC_ORDER  \
 #define HARD_REGNO_NREGS(REGNO, MODE)  \
    (((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  ((MODE1) == (MODE2) || GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
-
 /* Definitions for register eliminations.
 
    We have two registers that can be eliminated on the MCore.  First, the
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mcore/mcore.c	2017-08-28 10:35:27.203137417 +0100
@@ -145,6 +145,7 @@  static bool       mcore_legitimate_const
 static bool	  mcore_legitimate_address_p	(machine_mode, rtx, bool,
 						 addr_space_t);
 static bool	  mcore_hard_regno_mode_ok	(unsigned int, machine_mode);
+static bool	  mcore_modes_tieable_p		(machine_mode, machine_mode);
 
 /* MCore specific attributes.  */
 
@@ -244,6 +245,9 @@  #define TARGET_WARN_FUNC_RETURN mcore_wa
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK mcore_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P mcore_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Adjust the stack and return the number of bytes taken to do it.  */
@@ -3275,3 +3279,11 @@  mcore_hard_regno_mode_ok (unsigned int r
 
   return regno < 18;
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+mcore_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return mode1 == mode2 || GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2);
+}
Index: gcc/config/microblaze/microblaze.h
===================================================================
--- gcc/config/microblaze/microblaze.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/microblaze/microblaze.h	2017-08-28 10:35:27.203137417 +0100
@@ -295,12 +295,6 @@  #define ST_REG_P(REGNO) ((REGNO) == ST_R
 #define HARD_REGNO_NREGS(REGNO, MODE)					\
 	((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)					\
-  ((GET_MODE_CLASS (MODE1) == MODE_FLOAT ||				\
-    GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)			\
-   == (GET_MODE_CLASS (MODE2) == MODE_FLOAT ||				\
-       GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
-
 #define STACK_POINTER_REGNUM   (GP_REG_FIRST + MB_ABI_STACK_POINTER_REGNUM)
 
 #define STACK_POINTER_OFFSET   FIRST_PARM_OFFSET(FNDECL)
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/microblaze/microblaze.c	2017-08-28 10:35:27.203137417 +0100
@@ -1860,6 +1860,17 @@  microblaze_hard_regno_mode_ok (unsigned
   return microblaze_hard_regno_mode_ok_p[mode][regno];
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+microblaze_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
+
 /* Return true if FUNC is an interrupt function as specified
    by the "interrupt_handler" attribute.  */
 
@@ -3890,6 +3901,9 @@  #define TARGET_MACHINE_DEPENDENT_REORG m
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK microblaze_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P microblaze_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-microblaze.h"
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mips/mips.h	2017-08-28 10:35:27.204937417 +0100
@@ -1968,8 +1968,6 @@  #define HARD_REGNO_RENAME_OK(OLD_REG, NE
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   mips_hard_regno_caller_save_mode (REGNO, NREGS, MODE)
 
-#define MODES_TIEABLE_P mips_modes_tieable_p
-
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM (GP_REG_FIRST + 29)
 
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mips/mips-protos.h	2017-08-28 10:35:27.203137417 +0100
@@ -300,7 +300,6 @@  extern bool mips_secondary_memory_needed
 extern bool mips_cannot_change_mode_class (machine_mode,
 					   machine_mode, enum reg_class);
 extern bool mips_dangerous_for_la25_p (rtx);
-extern bool mips_modes_tieable_p (machine_mode, machine_mode);
 extern enum reg_class mips_secondary_reload_class (enum reg_class,
 						   machine_mode,
 						   rtx, bool);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mips/mips.c	2017-08-28 10:35:27.204937417 +0100
@@ -13017,9 +13017,9 @@  mips_mode_ok_for_mov_fmt_p (machine_mode
     }
 }
 
-/* Implement MODES_TIEABLE_P.  */
+/* Implement TARGET_MODES_TIEABLE_P.  */
 
-bool
+static bool
 mips_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   /* FPRs allow no mode punning, so it's not worth tying modes if we'd
@@ -22588,6 +22588,9 @@  #define TARGET_HARD_REGNO_SCRATCH_OK mip
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK mips_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P mips_modes_tieable_p
+
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   mips_hard_regno_call_part_clobbered
Index: gcc/config/mmix/mmix.h
===================================================================
--- gcc/config/mmix/mmix.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mmix/mmix.h	2017-08-28 10:35:27.204937417 +0100
@@ -386,12 +386,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  	\
     / UNITS_PER_WORD)
 
-/* Note that no register can really be accessed in single-float mode, so
-   we *can* say 1 here.  FIXME:  Will TRT happen for single-float, or do
-   we have to punt to libgcc1.asm?  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
-
 /* Node: Leaf Functions */
 /* (empty) */
 
Index: gcc/config/mn10300/mn10300.h
===================================================================
--- gcc/config/mn10300/mn10300.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mn10300/mn10300.h	2017-08-28 10:35:27.205837417 +0100
@@ -233,13 +233,6 @@  #define REG_ALLOC_ORDER \
 #define HARD_REGNO_NREGS(REGNO, MODE)   \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  mn10300_modes_tieable ((MODE1), (MODE2))
-
 /* 4 data, and effectively 3 address registers is small as far as I'm
    concerned.  */
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
Index: gcc/config/mn10300/mn10300-protos.h
===================================================================
--- gcc/config/mn10300/mn10300-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mn10300/mn10300-protos.h	2017-08-28 10:35:27.204937417 +0100
@@ -25,7 +25,6 @@  extern rtx   mn10300_legitimize_reload_a
 						int, int, int);
 extern bool  mn10300_function_value_regno_p (const unsigned int);
 extern unsigned int   mn10300_get_live_callee_saved_regs (unsigned int *);
-extern bool  mn10300_modes_tieable (machine_mode, machine_mode);
 extern const char *mn10300_output_add (rtx[3], bool);
 extern void  mn10300_print_operand (FILE *, rtx, int);
 extern void  mn10300_print_operand_address (FILE *, rtx);
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/mn10300/mn10300.c	2017-08-28 10:35:27.205837417 +0100
@@ -2650,8 +2650,10 @@  mn10300_hard_regno_mode_ok (unsigned int
   return false;
 }
 
-bool
-mn10300_modes_tieable (machine_mode mode1, machine_mode mode2)
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+mn10300_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if (GET_MODE_CLASS (mode1) == MODE_FLOAT
       && GET_MODE_CLASS (mode2) != MODE_FLOAT)
@@ -3430,4 +3432,7 @@  #define TARGET_FLAGS_REGNUM  CC_REG
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK mn10300_hard_regno_mode_ok
 
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P mn10300_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/moxie/moxie.h
===================================================================
--- gcc/config/moxie/moxie.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/moxie/moxie.h	2017-08-28 10:35:27.205837417 +0100
@@ -183,10 +183,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)		   \
    / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if a value of mode MODE1 is
-   accessible in mode MODE2 without copying.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
 /* The Overall Framework of an Assembler File */
 
 #undef  ASM_SPEC
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/msp430/msp430.h	2017-08-28 10:35:27.205837417 +0100
@@ -332,9 +332,6 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
 
 #define HARD_REGNO_NREGS(REGNO, MODE)            \
   msp430_hard_regno_nregs (REGNO, MODE)
-
-#define MODES_TIEABLE_P(MODE1, MODE2)				\
-  msp430_modes_tieable_p (MODE1, MODE2)
 
 /* Exception Handling */
 
Index: gcc/config/msp430/msp430-protos.h
===================================================================
--- gcc/config/msp430/msp430-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/msp430/msp430-protos.h	2017-08-28 10:35:27.205837417 +0100
@@ -39,7 +39,6 @@  int	msp430_initial_elimination_offset (i
 bool    msp430_is_interrupt_func (void);
 const char * msp430x_logical_shift_right (rtx);
 const char * msp430_mcu_name (void);
-bool	msp430_modes_tieable_p (machine_mode, machine_mode);
 void    msp430_output_aligned_decl_common (FILE *, const tree, const char *, unsigned HOST_WIDE_INT, unsigned);
 void	msp430_output_labelref (FILE *, const char *);
 void	msp430_register_pragmas (void);
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/msp430/msp430.c	2017-08-28 10:35:27.205837417 +0100
@@ -943,8 +943,10 @@  msp430_hard_regno_mode_ok (unsigned int
 		   - (unsigned int) msp430_hard_regno_nregs (regno, mode));
 }
 
-/* Implements MODES_TIEABLE_P.  */
-bool
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
+
+static bool
 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   if ((mode1 == PSImode || mode2 == SImode)
Index: gcc/config/nds32/nds32.h
===================================================================
--- gcc/config/nds32/nds32.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/nds32/nds32.h	2017-08-28 10:35:27.206737417 +0100
@@ -600,17 +600,6 @@  #define HONOR_REG_ALLOC_ORDER optimize_s
    reg "regno" for holding a value of mode "mode".  */
 #define HARD_REGNO_NREGS(regno, mode) nds32_hard_regno_nregs (regno, mode)
 
-/* A C expression that is nonzero if a value of mode1
-   is accessible in mode2 without copying.
-   Define this macro to return nonzero in as many cases as possible
-   since doing so will allow GCC to perform better register allocation.
-   We can use general registers to tie QI/HI/SI modes together.  */
-#define MODES_TIEABLE_P(mode1, mode2)          \
-  (GET_MODE_CLASS (mode1) == MODE_INT          \
-   && GET_MODE_CLASS (mode2) == MODE_INT       \
-   && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD  \
-   && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD)
-
 
 /* Register Classes.  */
 
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/nds32/nds32.c	2017-08-28 10:35:27.206737417 +0100
@@ -2768,6 +2768,21 @@  nds32_hard_regno_mode_ok (unsigned int r
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK nds32_hard_regno_mode_ok
+
+/* Implement TARGET_MODES_TIEABLE_P.  We can use general registers to
+   tie QI/HI/SI modes together.  */
+
+static bool
+nds32_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == MODE_INT
+	  && GET_MODE_CLASS (mode2) == MODE_INT
+	  && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
+	  && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
+}
+
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P nds32_modes_tieable_p
 
 /* Register Classes.  */
 
Index: gcc/config/nios2/nios2.h
===================================================================
--- gcc/config/nios2/nios2.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/nios2/nios2.h	2017-08-28 10:35:27.206737417 +0100
@@ -172,7 +172,6 @@  #define CALL_USED_REGISTERS
 /*  30 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     \
   }
 
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
 #define HARD_REGNO_NREGS(REGNO, MODE)            \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
Index: gcc/config/nvptx/nvptx.h
===================================================================
--- gcc/config/nvptx/nvptx.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/nvptx/nvptx.h	2017-08-28 10:35:27.206737417 +0100
@@ -117,8 +117,6 @@  #define REGNO_OK_FOR_INDEX_P(X) false
 #define CLASS_MAX_NREGS(class, mode) \
   ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(M1, M2) false
-
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)		\
   if ((MODE) == QImode || (MODE) == HImode)		\
     {							\
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/nvptx/nvptx.c	2017-08-28 10:35:27.206737417 +0100
@@ -5513,6 +5513,14 @@  nvptx_data_alignment (const_tree type, u
   return basic_align;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+nvptx_modes_tieable_p (machine_mode, machine_mode)
+{
+  return false;
+}
+
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE nvptx_option_override
 
@@ -5637,6 +5645,9 @@  #define TARGET_VECTOR_MODE_SUPPORTED_P n
 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE \
     nvptx_preferred_simd_mode
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P nvptx_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-nvptx.h"
Index: gcc/config/pa/pa.h
===================================================================
--- gcc/config/pa/pa.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/pa/pa.h	2017-08-28 10:35:27.207637417 +0100
@@ -324,13 +324,6 @@  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
    when given unaligned data.  */
 #define STRICT_ALIGNMENT 1
 
-/* Value is 1 if it is a good idea to tie two pseudo registers when one
-   has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  pa_modes_tieable_p (MODE1, MODE2)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/pa/pa-protos.h
===================================================================
--- gcc/config/pa/pa-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/pa/pa-protos.h	2017-08-28 10:35:27.207637417 +0100
@@ -114,7 +114,6 @@  extern void pa_asm_output_aligned_local
 extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
 extern bool pa_cannot_change_mode_class (machine_mode, machine_mode,
 					 enum reg_class);
-extern bool pa_modes_tieable_p (machine_mode, machine_mode);
 extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
 
 extern const int pa_magic_milli[];
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/pa/pa.c	2017-08-28 10:35:27.207637417 +0100
@@ -199,6 +199,7 @@  static bool pa_legitimate_address_p (mac
 static bool pa_callee_copies (cumulative_args_t, machine_mode,
 			      const_tree, bool);
 static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool pa_modes_tieable_p (machine_mode, machine_mode);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -407,6 +408,8 @@  #define TARGET_LRA_P hook_bool_void_fals
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK pa_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P pa_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -10012,10 +10015,7 @@  pa_cannot_change_mode_class (machine_mod
   return false;
 }
 
-/* Returns TRUE if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be FALSE for correct output.
+/* Implement TARGET_MODES_TIEABLE_P.
    
    We should return FALSE for QImode and HImode because these modes
    are not ok in the floating-point registers.  However, this prevents
@@ -10024,7 +10024,7 @@  pa_cannot_change_mode_class (machine_mod
    CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
    in the floating-point registers.  */
 
-bool
+static bool
 pa_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   /* Don't tie modes in different classes.  */
Index: gcc/config/pdp11/pdp11.h
===================================================================
--- gcc/config/pdp11/pdp11.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/pdp11/pdp11.h	2017-08-28 10:35:27.208537417 +0100
@@ -176,12 +176,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
     :1)
     
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) 0
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/pdp11/pdp11.c	2017-08-28 10:35:27.208537417 +0100
@@ -238,6 +238,9 @@  #define TARGET_SCALAR_MODE_SUPPORTED_P p
 
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK pdp11_hard_regno_mode_ok
+
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P pdp11_modes_tieable_p
 
 /* A helper function to determine if REGNO should be saved in the
    current function's stack frame.  */
@@ -1947,4 +1950,12 @@  pdp11_hard_regno_mode_ok (unsigned int r
   return FLOAT_MODE_P (mode);
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+pdp11_modes_tieable_p (machine_mode, machine_mode)
+{
+  return false;
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-08-28 10:35:27.212137417 +0100
@@ -1330,40 +1330,6 @@  #define SPE_VECTOR_MODE(MODE)		\
 #define PAIRED_VECTOR_MODE(MODE)        \
          ((MODE) == V2SFmode)            
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.
-
-   PTImode cannot tie with other modes because PTImode is restricted to even
-   GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).
-
-   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
-   128-bit floating point on VSX systems ties with other vectors.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)		\
-  ((MODE1) == PTImode				\
-   ? (MODE2) == PTImode				\
-   : (MODE2) == PTImode				\
-   ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
-   : SCALAR_FLOAT_MODE_P (MODE1)		\
-   ? SCALAR_FLOAT_MODE_P (MODE2)		\
-   : SCALAR_FLOAT_MODE_P (MODE2)		\
-   ? 0						\
-   : GET_MODE_CLASS (MODE1) == MODE_CC		\
-   ? GET_MODE_CLASS (MODE2) == MODE_CC		\
-   : GET_MODE_CLASS (MODE2) == MODE_CC		\
-   ? 0						\
-   : SPE_VECTOR_MODE (MODE1)			\
-   ? SPE_VECTOR_MODE (MODE2)			\
-   : SPE_VECTOR_MODE (MODE2)			\
-   ? 0						\
-   : 1)
-
 /* Post-reload, we can't use any new AltiVec registers, as we already
    emitted the vrsave mask.  */
 
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-08-28 10:35:27.212137417 +0100
@@ -1977,6 +1977,9 @@  #define TARGET_CUSTOM_FUNCTION_DESCRIPTO
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK rs6000_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P rs6000_modes_tieable_p
+
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   rs6000_hard_regno_call_part_clobbered
@@ -2173,6 +2176,46 @@  rs6000_hard_regno_mode_ok (unsigned int
   return rs6000_hard_regno_mode_ok_p[mode][regno];
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   PTImode cannot tie with other modes because PTImode is restricted to even
+   GPR registers, and TImode can go in any GPR as well as VSX registers (PR
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
+
+static bool
+rs6000_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  if (mode1 == PTImode)
+    return mode2 == PTImode;
+  if (mode2 == PTImode)
+    return false;
+
+  if (ALTIVEC_OR_VSX_VECTOR_MODE (mode1))
+    return ALTIVEC_OR_VSX_VECTOR_MODE (mode2);
+  if (ALTIVEC_OR_VSX_VECTOR_MODE (mode2))
+    return false;
+
+  if (SCALAR_FLOAT_MODE_P (mode1))
+    return SCALAR_FLOAT_MODE_P (mode2);
+  if (SCALAR_FLOAT_MODE_P (mode2))
+    return false;
+
+  if (GET_MODE_CLASS (mode1) == MODE_CC)
+    return GET_MODE_CLASS (mode2) == MODE_CC;
+  if (GET_MODE_CLASS (mode2) == MODE_CC)
+    return false;
+
+  if (SPE_VECTOR_MODE (mode1))
+    return SPE_VECTOR_MODE (mode2);
+  if (SPE_VECTOR_MODE (mode2))
+    return false;
+
+  return true;
+}
+
 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
 
 static bool
@@ -2649,7 +2692,7 @@  rs6000_debug_reg_global (void)
       for (m2 = 0; m2 < ARRAY_SIZE (print_tieable_modes); m2++)
 	{
 	  machine_mode mode2 = print_tieable_modes[m2];
-	  if (mode1 != mode2 && MODES_TIEABLE_P (mode1, mode2))
+	  if (mode1 != mode2 && rs6000_modes_tieable_p (mode1, mode2))
 	    {
 	      if (first_time)
 		{
Index: gcc/config/powerpcspe/powerpcspe.md
===================================================================
--- gcc/config/powerpcspe/powerpcspe.md	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/powerpcspe/powerpcspe.md	2017-08-28 10:35:27.213037417 +0100
@@ -4834,9 +4834,9 @@  (define_insn_and_split "*signbit<mode>2_
  [(set_attr "length" "8,8,4")
   (set_attr "type" "mftgpr,load,integer")])
 
-;; MODES_TIEABLE_P doesn't allow DImode to be tied with the various floating
-;; point types, which makes normal SUBREG's problematical. Instead use a
-;; special pattern to avoid using a normal movdi.
+;; TARGET_MODES_TIEABLE_P doesn't allow DImode to be tied with the various
+;; floating point types, which makes normal SUBREG's problematical.  Instead
+;; use a special pattern to avoid using a normal movdi.
 (define_insn "signbit<mode>2_dm2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
 	(unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa")
Index: gcc/config/riscv/riscv.h
===================================================================
--- gcc/config/riscv/riscv.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/riscv/riscv.h	2017-08-28 10:35:27.213037417 +0100
@@ -296,13 +296,6 @@  #define FP_REG_RTX_P(X) (REG_P (X) && FP
 
 #define HARD_REGNO_NREGS(REGNO, MODE) riscv_hard_regno_nregs (REGNO, MODE)
 
-/* Don't allow floating-point modes to be tied, since type punning of
-   single-precision and double-precision is implementation defined.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)			\
-  ((MODE1) == (MODE2)					\
-   || !(GET_MODE_CLASS (MODE1) == MODE_FLOAT		\
-	&& GET_MODE_CLASS (MODE2) == MODE_FLOAT))
-
 /* Use s0 as the frame pointer if it is so requested.  */
 #define HARD_FRAME_POINTER_REGNUM 8
 #define STACK_POINTER_REGNUM 2
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/riscv/riscv.c	2017-08-28 10:35:27.213037417 +0100
@@ -3558,6 +3558,19 @@  riscv_hard_regno_mode_ok (unsigned int r
   return true;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   Don't allow floating-point modes to be tied, since type punning of
+   single-precision and double-precision is implementation defined.  */
+
+static bool
+riscv_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || !(GET_MODE_CLASS (mode1) == MODE_FLOAT
+	       && GET_MODE_CLASS (mode2) == MODE_FLOAT));
+}
+
 /* Implement HARD_REGNO_NREGS.  */
 
 unsigned int
@@ -4086,6 +4099,9 @@  #define TARGET_EXPAND_BUILTIN riscv_expa
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK riscv_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P riscv_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
Index: gcc/config/rl78/rl78.h
===================================================================
--- gcc/config/rl78/rl78.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rl78/rl78.h	2017-08-28 10:35:27.213937417 +0100
@@ -409,12 +409,6 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
 
 #define HARD_REGNO_NREGS(REGNO, MODE)            \
   rl78_hard_regno_nregs (REGNO, MODE)
-
-#define MODES_TIEABLE_P(MODE1, MODE2)				\
-  (   (   GET_MODE_CLASS (MODE1) == MODE_FLOAT			\
-       || GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)		\
-   == (   GET_MODE_CLASS (MODE2) == MODE_FLOAT			\
-       || GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
 
 
 #define TEXT_SECTION_ASM_OP ".text"
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rl78/rl78.c	2017-08-28 10:35:27.213937417 +0100
@@ -491,6 +491,18 @@  rl78_hard_regno_mode_ok (unsigned int re
   return false;
 }
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P rl78_modes_tieable_p
+
+static bool
+rl78_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
+
 /* Simplify_gen_subreg() doesn't handle memory references the way we
    need it to below, so we use this function for when we must get a
    valid subreg in a "natural" state.  */
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rs6000/rs6000.h	2017-08-28 10:35:27.215737417 +0100
@@ -1262,40 +1262,6 @@  #define ALTIVEC_OR_VSX_VECTOR_MODE(MODE)
 #define PAIRED_VECTOR_MODE(MODE)        \
          ((MODE) == V2SFmode)            
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.
-
-   PTImode cannot tie with other modes because PTImode is restricted to even
-   GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).
-
-   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
-   128-bit floating point on VSX systems ties with other vectors.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)		\
-  ((MODE1) == PTImode				\
-   ? (MODE2) == PTImode				\
-   : (MODE2) == PTImode				\
-   ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
-   : SCALAR_FLOAT_MODE_P (MODE1)		\
-   ? SCALAR_FLOAT_MODE_P (MODE2)		\
-   : SCALAR_FLOAT_MODE_P (MODE2)		\
-   ? 0						\
-   : GET_MODE_CLASS (MODE1) == MODE_CC		\
-   ? GET_MODE_CLASS (MODE2) == MODE_CC		\
-   : GET_MODE_CLASS (MODE2) == MODE_CC		\
-   ? 0						\
-   : PAIRED_VECTOR_MODE (MODE1)			\
-   ? PAIRED_VECTOR_MODE (MODE2)			\
-   : PAIRED_VECTOR_MODE (MODE2)			\
-   ? 0						\
-   : 1)
-
 /* Post-reload, we can't use any new AltiVec registers, as we already
    emitted the vrsave mask.  */
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rs6000/rs6000.c	2017-08-28 10:35:27.215737417 +0100
@@ -1967,6 +1967,9 @@  #define TARGET_OPTION_FUNCTION_VERSIONS
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK rs6000_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P rs6000_modes_tieable_p
+
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   rs6000_hard_regno_call_part_clobbered
@@ -2140,6 +2143,46 @@  rs6000_hard_regno_mode_ok (unsigned int
   return rs6000_hard_regno_mode_ok_p[mode][regno];
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   PTImode cannot tie with other modes because PTImode is restricted to even
+   GPR registers, and TImode can go in any GPR as well as VSX registers (PR
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
+
+static bool
+rs6000_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  if (mode1 == PTImode)
+    return mode2 == PTImode;
+  if (mode2 == PTImode)
+    return false;
+
+  if (ALTIVEC_OR_VSX_VECTOR_MODE (mode1))
+    return ALTIVEC_OR_VSX_VECTOR_MODE (mode2);
+  if (ALTIVEC_OR_VSX_VECTOR_MODE (mode2))
+    return false;
+
+  if (SCALAR_FLOAT_MODE_P (mode1))
+    return SCALAR_FLOAT_MODE_P (mode2);
+  if (SCALAR_FLOAT_MODE_P (mode2))
+    return false;
+
+  if (GET_MODE_CLASS (mode1) == MODE_CC)
+    return GET_MODE_CLASS (mode2) == MODE_CC;
+  if (GET_MODE_CLASS (mode2) == MODE_CC)
+    return false;
+
+  if (PAIRED_VECTOR_MODE (mode1))
+    return PAIRED_VECTOR_MODE (mode2);
+  if (PAIRED_VECTOR_MODE (mode2))
+    return false;
+
+  return true;
+}
+
 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
 
 static bool
@@ -2611,7 +2654,7 @@  rs6000_debug_reg_global (void)
       for (m2 = 0; m2 < ARRAY_SIZE (print_tieable_modes); m2++)
 	{
 	  machine_mode mode2 = print_tieable_modes[m2];
-	  if (mode1 != mode2 && MODES_TIEABLE_P (mode1, mode2))
+	  if (mode1 != mode2 && rs6000_modes_tieable_p (mode1, mode2))
 	    {
 	      if (first_time)
 		{
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rs6000/rs6000.md	2017-08-28 10:35:27.216637417 +0100
@@ -4806,9 +4806,9 @@  (define_insn_and_split "*signbit<mode>2_
  [(set_attr "length" "8,8,4")
   (set_attr "type" "mftgpr,load,integer")])
 
-;; MODES_TIEABLE_P doesn't allow DImode to be tied with the various floating
-;; point types, which makes normal SUBREG's problematical. Instead use a
-;; special pattern to avoid using a normal movdi.
+;; TARGET_MODES_TIEABLE_P doesn't allow DImode to be tied with the various
+;; floating point types, which makes normal SUBREG's problematical.  Instead
+;; use a special pattern to avoid using a normal movdi.
 (define_insn "signbit<mode>2_dm2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
 	(unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa")
Index: gcc/config/rx/rx.h
===================================================================
--- gcc/config/rx/rx.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rx/rx.h	2017-08-28 10:35:27.216637417 +0100
@@ -333,11 +333,6 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
 
 #define HARD_REGNO_NREGS(REGNO, MODE)   CLASS_MAX_NREGS (0, MODE)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)				\
-  (   (   GET_MODE_CLASS (MODE1) == MODE_FLOAT			\
-       || GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)		\
-   == (   GET_MODE_CLASS (MODE2) == MODE_FLOAT			\
-       || GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
 
 
 #define REGISTER_NAMES						\
Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/rx/rx.c	2017-08-28 10:35:27.216637417 +0100
@@ -3441,6 +3441,17 @@  rx_hard_regno_mode_ok (unsigned int regn
 {
   return REGNO_REG_CLASS (regno) == GR_REGS;
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+rx_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
 
 #undef  TARGET_NARROW_VOLATILE_BITFIELD
 #define TARGET_NARROW_VOLATILE_BITFIELD		rx_narrow_volatile_bitfield
@@ -3598,6 +3609,9 @@  #define TARGET_LRA_P 				rx_enable_lra
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK		rx_hard_regno_mode_ok
 
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P			rx_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rx.h"
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/s390/s390.h	2017-08-28 10:35:27.218437417 +0100
@@ -502,10 +502,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
 #define HARD_REGNO_RENAME_OK(FROM, TO)          \
   s390_hard_regno_rename_ok ((FROM), (TO))
 
-#define MODES_TIEABLE_P(MODE1, MODE2)		\
-   (((MODE1) == SFmode || (MODE1) == DFmode)	\
-   == ((MODE2) == SFmode || (MODE2) == DFmode))
-
 /* Maximum number of registers to represent a value of mode MODE
    in a register of class CLASS.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)   					\
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/s390/s390.c	2017-08-28 10:35:27.217537417 +0100
@@ -10438,6 +10438,15 @@  s390_hard_regno_mode_ok (unsigned int re
   return false;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+s390_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((mode1 == SFmode || mode1 == DFmode)
+	  == (mode2 == SFmode || mode2 == DFmode));
+}
+
 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
 
 bool
@@ -15904,6 +15913,8 @@  #define TARGET_HARD_REGNO_SCRATCH_OK s39
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK s390_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P s390_modes_tieable_p
 
 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/sh/sh.h	2017-08-28 10:35:27.220237417 +0100
@@ -822,18 +822,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE) \
     ? ((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD - 1)) / (2*UNITS_PER_WORD)) \
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.
-   That's the case for xd registers: we don't hold SFmode values in
-   them, so we can't tie an SFmode pseudos with one in another
-   floating-point mode.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  ((MODE1) == (MODE2) \
-   || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
-       && (((MODE1) != SFmode && (MODE2) != SFmode))))
-
 /* Specify the modes required to caller save a given hard regno.  */
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)	\
   sh_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/sh/sh.c	2017-08-28 10:35:27.218437417 +0100
@@ -322,6 +322,7 @@  static bool sh_fixed_condition_code_regs
 
 static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool sh_modes_tieable_p (machine_mode, machine_mode);
 
 static const struct attribute_spec sh_attribute_table[] =
 {
@@ -645,6 +646,9 @@  #define TARGET_CANNOT_FORCE_CONST_MEM sh
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK sh_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P sh_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -10573,6 +10577,22 @@  sh_hard_regno_mode_ok (unsigned int regn
   return true;
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.
+
+   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
+   and MODE2, for any hard reg, then this must be false for correct output.
+   That's the case for xd registers: we don't hold SFmode values in
+   them, so we can't tie an SFmode pseudos with one in another
+   floating-point mode.  */
+
+static bool
+sh_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2)
+	      && (mode1 != SFmode && mode2 != SFmode)));
+}
+
 /* Specify the modes required to caller save a given hard regno.
    choose_hard_reg_mode chooses mode based on TARGET_HARD_REGNO_MODE_OK
    and returns ?Imode for float regs when sh_hard_regno_mode_ok
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/sparc/sparc.h	2017-08-28 10:35:27.221137417 +0100
@@ -773,8 +773,6 @@  #define REGMODE_NATURAL_SIZE(MODE) sparc
    register window instruction in the prologue.  */
 #define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
 
-#define MODES_TIEABLE_P(MODE1, MODE2) sparc_modes_tieable_p (MODE1, MODE2)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/sparc/sparc-protos.h	2017-08-28 10:35:27.220237417 +0100
@@ -111,7 +111,6 @@  extern void sparc_expand_vec_perm_bmask(
 extern bool sparc_expand_conditional_move (machine_mode, rtx *);
 extern void sparc_expand_vcond (machine_mode, rtx *, int, int);
 unsigned int sparc_regmode_natural_size (machine_mode);
-bool sparc_modes_tieable_p (machine_mode, machine_mode);
 #endif /* RTX_CODE */
 
 extern rtl_opt_pass *make_pass_work_around_errata (gcc::context *);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/sparc/sparc.c	2017-08-28 10:35:27.221137417 +0100
@@ -676,6 +676,7 @@  static void sparc_atomic_assign_expand_f
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static unsigned int sparc_min_arithmetic_precision (void);
 static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool sparc_modes_tieable_p (machine_mode, machine_mode);
 
 
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
@@ -904,6 +905,9 @@  #define TARGET_CUSTOM_FUNCTION_DESCRIPTO
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK sparc_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P sparc_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return the memory reference contained in X if any, zero otherwise.  */
@@ -13139,15 +13143,12 @@  sparc_hard_regno_mode_ok (unsigned int r
   return (hard_regno_mode_classes[regno] & sparc_mode_class[mode]) != 0;
 }
 
-/* Return TRUE if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be FALSE for correct output.
+/* Implement TARGET_MODES_TIEABLE_P.
 
    For V9 we have to deal with the fact that only the lower 32 floating
    point registers are 32-bit addressable.  */
 
-bool
+static bool
 sparc_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 {
   enum mode_class mclass1, mclass2;
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/spu/spu.h	2017-08-28 10:35:27.221137417 +0100
@@ -176,10 +176,6 @@  #define CALL_USED_REGISTERS {			    \
 #define HARD_REGNO_NREGS(REGNO, MODE)   \
     ((GET_MODE_BITSIZE(MODE)+MAX_FIXED_MODE_SIZE-1)/MAX_FIXED_MODE_SIZE)
 
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  (GET_MODE_BITSIZE (MODE1) <= MAX_FIXED_MODE_SIZE \
-   && GET_MODE_BITSIZE (MODE2) <= MAX_FIXED_MODE_SIZE)
-
 
 /* Register Classes */
 
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/spu/spu.c	2017-08-28 10:35:27.221137417 +0100
@@ -7141,6 +7141,14 @@  spu_expand_atomic_op (enum rtx_code code
     emit_move_insn (orig_after, after);
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+spu_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_BITSIZE (mode1) <= MAX_FIXED_MODE_SIZE
+	  && GET_MODE_BITSIZE (mode2) <= MAX_FIXED_MODE_SIZE);
+}
 
 /*  Table of machine attributes.  */
 static const struct attribute_spec spu_attribute_table[] =
@@ -7363,6 +7371,9 @@  #define TARGET_CANONICALIZE_COMPARISON s
 #undef TARGET_CAN_USE_DOLOOP_P
 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P spu_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-spu.h"
Index: gcc/config/stormy16/stormy16.h
===================================================================
--- gcc/config/stormy16/stormy16.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/stormy16/stormy16.h	2017-08-28 10:35:27.222037417 +0100
@@ -145,15 +145,6 @@  #define REG_ALLOC_ORDER { 7, 6, 5, 4, 3,
 #define HARD_REGNO_NREGS(REGNO, MODE) 				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* A C expression that is nonzero if it is desirable to choose register
-   allocation so as to avoid move instructions between a value of mode MODE1
-   and a value of mode MODE2.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are ever different for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' must be zero.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) != BImode && (MODE2) != BImode)
-
 
 /* Register Classes.  */
 
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/stormy16/stormy16.c	2017-08-28 10:35:27.222037417 +0100
@@ -2625,6 +2625,14 @@  xstormy16_hard_regno_mode_ok (unsigned i
 {
   return regno != 16 || mode == BImode;
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+xstormy16_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return mode1 != BImode && mode2 != BImode;
+}
 
 #undef  TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
@@ -2704,6 +2712,8 @@  #define TARGET_TRAMPOLINE_INIT xstormy16
 
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK xstormy16_hard_regno_mode_ok
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P xstormy16_modes_tieable_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
Index: gcc/config/tilegx/tilegx.h
===================================================================
--- gcc/config/tilegx/tilegx.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/tilegx/tilegx.h	2017-08-28 10:35:27.222037417 +0100
@@ -162,8 +162,6 @@  #define REG_ALLOC_ORDER {				\
 #define HARD_REGNO_NREGS(REGNO, MODE)	\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)  1
-
 /* Register that holds an address into the text segment that can be
    used by pic code.  */
 #define TILEGX_PIC_TEXT_LABEL_REGNUM (flag_pic ? 50 : INVALID_REGNUM)
Index: gcc/config/tilepro/tilepro.h
===================================================================
--- gcc/config/tilepro/tilepro.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/tilepro/tilepro.h	2017-08-28 10:35:27.222037417 +0100
@@ -127,8 +127,6 @@  #define REG_ALLOC_ORDER {				\
 #define HARD_REGNO_NREGS(REGNO, MODE)	\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-#define MODES_TIEABLE_P(MODE1, MODE2)  1
-
 /* Register that holds an address into the text segment that can be
    used by pic code.  */
 #define TILEPRO_PIC_TEXT_LABEL_REGNUM (flag_pic ? 50 : INVALID_REGNUM)
Index: gcc/config/v850/v850.h
===================================================================
--- gcc/config/v850/v850.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/v850/v850.h	2017-08-28 10:35:27.222037417 +0100
@@ -300,13 +300,6 @@  #define REG_ALLOC_ORDER							\
 #define HARD_REGNO_NREGS(REGNO, MODE)   \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  (MODE1 == MODE2 || (GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4))
-
 
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/v850/v850.c	2017-08-28 10:35:27.222037417 +0100
@@ -3255,6 +3255,15 @@  v850_hard_regno_mode_ok (unsigned int re
 {
   return GET_MODE_SIZE (mode) <= 4 || ((regno & 1) == 0 && regno != 0);
 }
+
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+v850_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (mode1 == mode2
+	  || (GET_MODE_SIZE (mode1) <= 4 && GET_MODE_SIZE (mode2) <= 4));
+}
 
 /* Initialize the GCC target structure.  */
 
@@ -3363,6 +3372,9 @@  #define TARGET_CAN_USE_DOLOOP_P can_use_
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK v850_hard_regno_mode_ok
 
+#undef  TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P v850_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-v850.h"
Index: gcc/config/vax/vax.h
===================================================================
--- gcc/config/vax/vax.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/vax/vax.h	2017-08-28 10:35:27.222937417 +0100
@@ -143,12 +143,6 @@  #define CALL_USED_REGISTERS {1, 1, 1, 1,
 #define HARD_REGNO_NREGS(REGNO, MODE)	\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)  1
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/visium/visium.h
===================================================================
--- gcc/config/visium/visium.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/visium/visium.h	2017-08-28 10:35:27.222937417 +0100
@@ -573,25 +573,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE) \
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
   visium_hard_regno_rename_ok (OLD_REG, NEW_REG)
 
-/* `MODES_TIEABLE_P (MODE1, MODE2)'
-
-   A C expression that is nonzero if a value of mode MODE1 is
-   accessible in mode MODE2 without copying.
-
-   If `TARGET_HARD_REGNO_MODE_OK (R, MODE1)' and
-   `TARGET_HARD_REGNO_MODE_OK (R, MODE2)' are always the same for any R,
-   then `MODES_TIEABLE_P (MODE1, MODE2)' should be nonzero.  If they
-   differ for any R, you should define this macro to return zero unless
-   some other mechanism ensures the accessibility of the value in a
-   narrower mode.
-
-   You should define this macro to return nonzero in as many cases as
-   possible since doing so will allow GNU CC to perform better
-   register allocation. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-  ((GET_MODE_CLASS (MODE1) == MODE_INT) \
-  && (GET_MODE_CLASS (MODE2) == MODE_INT))
-
 /* Register Classes
 
    On many machines, the numbered registers are not all equivalent.
@@ -1271,7 +1252,7 @@  #define SHIFT_COUNT_TRUNCATED 0
    On many machines, this expression can be 1.
 
    When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for
-   modes for which `MODES_TIEABLE_P' is 0, suboptimal code can result.
+   modes for which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
    If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in
    such cases may improve things. */
 #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/visium/visium.c	2017-08-28 10:35:27.222937417 +0100
@@ -230,6 +230,8 @@  static unsigned int visium_reorg (void);
 
 static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
 
+static bool visium_modes_tieable_p (machine_mode, machine_mode);
+
 /* Setup the global target hooks structure.  */
 
 #undef  TARGET_MAX_ANCHOR_OFFSET
@@ -344,6 +346,9 @@  #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P visium_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 namespace {
@@ -861,6 +866,15 @@  visium_hard_regno_mode_ok (unsigned int
 	  && HARD_REGNO_NREGS (regno, mode) == 1);
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+visium_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return (GET_MODE_CLASS (mode1) == MODE_INT
+	  && GET_MODE_CLASS (mode2) == MODE_INT);
+}
+
 /* Return true if it is ok to do sibling call optimization for the specified
    call expression EXP.  DECL will be the called function, or NULL if this
    is an indirect call.  */
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/xtensa/xtensa.h	2017-08-28 10:35:27.223837417 +0100
@@ -328,16 +328,6 @@  #define HARD_REGNO_NREGS(REGNO, MODE)
 	((GET_MODE_SIZE (MODE) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG) : \
 	((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If TARGET_HARD_REGNO_MODE_OK could produce different values for MODE1
-   and MODE2, for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)					\
-  ((GET_MODE_CLASS (MODE1) == MODE_FLOAT ||				\
-    GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)			\
-   == (GET_MODE_CLASS (MODE2) == MODE_FLOAT ||				\
-       GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
-
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM (GP_REG_FIRST + 1)
 
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2017-08-28 10:35:26.214037420 +0100
+++ gcc/config/xtensa/xtensa.c	2017-08-28 10:35:27.222937417 +0100
@@ -179,6 +179,7 @@  static bool xtensa_member_type_forces_bl
 
 static void xtensa_conditional_register_usage (void);
 static bool xtensa_hard_regno_mode_ok (unsigned int, machine_mode);
+static bool xtensa_modes_tieable_p (machine_mode, machine_mode);
 
 
 
@@ -310,6 +311,9 @@  #define TARGET_CONDITIONAL_REGISTER_USAG
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK xtensa_hard_regno_mode_ok
 
+#undef TARGET_MODES_TIEABLE_P
+#define TARGET_MODES_TIEABLE_P xtensa_modes_tieable_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -2265,6 +2269,17 @@  xtensa_hard_regno_mode_ok (unsigned int
   return xtensa_hard_regno_mode_ok_p[mode][regno];
 }
 
+/* Implement TARGET_MODES_TIEABLE_P.  */
+
+static bool
+xtensa_modes_tieable_p (machine_mode mode1, machine_mode mode2)
+{
+  return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
+	  == (GET_MODE_CLASS (mode2) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
+}
+
 /* A C compound statement to output to stdio stream STREAM the
    assembler syntax for an instruction operand X.  X is an RTL
    expression.
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-08-28 10:35:26.214037420 +0100
+++ gcc/system.h	2017-08-28 10:35:27.226537417 +0100
@@ -905,7 +905,8 @@  #define realloc xrealloc
 	LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE	\
 	CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P		\
 	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD			\
-	HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK
+	HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK		\
+	MODES_TIEABLE_P
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */