Turn HARD_REGNO_NREGS into a target hook

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

Commit Message

Richard Sandiford Sept. 11, 2017, 5:18 p.m.
Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by comparing the testsuite assembly output on at least one
target per CPU directory.  OK to install?

Richard


gcc/
	* target.def (hard_regno_nregs): New hook.
	(class_max_nregs): Refer to it instead of HARD_REGNO_NREGS.
	* targhooks.h (default_hard_regno_nregs): Declare.
	* targhooks.c (default_hard_regno_nregs): New function.
	* doc/tm.texi.in (HARD_REGNO_NREGS): Replace with...
	(TARGET_HARD_REGNO_NREGS): ...this hook.
	(HARD_REGNO_NREGS_HAS_PADDING): Update accordingly.
	(CLASS_MAX_NREGS): Likewise.
	* doc/tm.texi: Regenerate.
	* reginfo.c (init_reg_modes_target): Use targetm.hard_regno_nregs
	instead of HARD_REGNO_NREGS.
	* rtl.h (REG_NREGS): Refer to TARGET_HARD_REGNO_NREGS rather than
	HARD_REGNO_NREGS in the comment.
	* config/aarch64/aarch64.h (HARD_REGNO_NREGS): Delete.
	* config/aarch64/aarch64-protos.h (aarch64_hard_regno_nregs): Delete.
	* config/aarch64/aarch64.c (aarch64_hard_regno_nregs): Make static.
	Return an unsigned int.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/alpha/alpha.h (HARD_REGNO_NREGS): Delete.
	* config/arc/arc.h (HARD_REGNO_NREGS): Delete.
	* config/arc/arc.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(arc_hard_regno_nregs): New function.
	* config/arm/arm.h (HARD_REGNO_NREGS): Delete.
	* config/arm/arm.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(arm_hard_regno_nregs): New function.
	* config/avr/avr.h (HARD_REGNO_NREGS): Delete.
	* config/bfin/bfin.h (HARD_REGNO_NREGS): Delete.
	* config/bfin/bfin.c (bfin_hard_regno_nregs): New function.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/c6x/c6x.h (HARD_REGNO_NREGS): Delete.
	* config/cr16/cr16.h (LONG_REG_P): Use targetm.hard_regno_nregs.
	(HARD_REGNO_NREGS): Delete.
	* config/cr16/cr16.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(cr16_hard_regno_nregs): New function.
	(cr16_memory_move_cost): Use it instead of HARD_REGNO_NREGS.
	* config/cris/cris.h (HARD_REGNO_NREGS): Delete.
	* config/cris/cris.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(cris_hard_regno_nregs): New function.
	* config/epiphany/epiphany.h (HARD_REGNO_NREGS): Delete.
	* config/fr30/fr30.h (HARD_REGNO_NREGS): Delete.
	(CLASS_MAX_NREGS): Use targetm.hard_regno_nregs.
	* config/frv/frv.h (HARD_REGNO_NREGS): Delete.
	(CLASS_MAX_NREGS): Remove outdated copy of documentation.
	* config/frv/frv-protos.h (frv_hard_regno_nregs): Delete.
	* config/frv/frv.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(frv_hard_regno_nregs): Make static.  Take and return an
	unsigned int.
	(frv_class_max_nregs): Remove outdated copy of documentation.
	* config/ft32/ft32.h (HARD_REGNO_NREGS): Delete.
	* config/h8300/h8300.h (HARD_REGNO_NREGS): Delete.
	* config/h8300/h8300-protos.h (h8300_hard_regno_nregs): Delete.
	* config/h8300/h8300.c (h8300_hard_regno_nregs): Delete.
	* config/i386/i386.h (HARD_REGNO_NREGS): Delete.
	* config/i386/i386.c (ix86_hard_regno_nregs): New function.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/ia64/ia64.h (HARD_REGNO_NREGS): Delete.
	(CLASS_MAX_NREGS): Update comment.
	* config/ia64/ia64.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(ia64_hard_regno_nregs): New function.
	* config/iq2000/iq2000.h (HARD_REGNO_NREGS): Delete.
	* config/lm32/lm32.h (HARD_REGNO_NREGS): Delete.
	* config/m32c/m32c.h (HARD_REGNO_NREGS): Delete.
	* config/m32c/m32c-protos.h (m32c_hard_regno_nregs): Delete.
	* config/m32c/m32c.c (m32c_hard_regno_nregs_1): Take and return
	an unsigned int.
	(m32c_hard_regno_nregs): Likewise.  Make static.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/m32r/m32r.h (HARD_REGNO_NREGS): Delete.
	* config/m68k/m68k.h (HARD_REGNO_NREGS): Delete.
	* config/m68k/m68k.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(m68k_hard_regno_nregs): New function.
	* config/mcore/mcore.h (HARD_REGNO_NREGS): Delete.
	* config/microblaze/microblaze.h (HARD_REGNO_NREGS): Delete.
	* config/mips/mips.h (HARD_REGNO_NREGS): Delete.
	* config/mips/mips-protos.h (mips_hard_regno_nregs): Delete.
	* config/mips/mips.c (mips_hard_regno_nregs): Make static.
	Take and return an unsigned int.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/mmix/mmix.h (HARD_REGNO_NREGS): Delete.
	(CLASS_MAX_NREGS): Use targetm.hard_regno_nregs.
	* config/mn10300/mn10300.h (HARD_REGNO_NREGS): Delete.
	* config/moxie/moxie.h (HARD_REGNO_NREGS): Delete.
	* config/msp430/msp430.h (HARD_REGNO_NREGS): Delete.
	* config/msp430/msp430-protos.h (msp430_hard_regno_nregs): Delete.
	* config/msp430/msp430.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(msp430_hard_regno_nregs): Make static.  Take and return an
	unsigned int.
	* config/nds32/nds32.h (HARD_REGNO_NREGS): Delete.
	* config/nds32/nds32-protos.h (nds32_hard_regno_nregs): Delete.
	* config/nds32/nds32.c (nds32_hard_regno_nregs): Delete.
	(nds32_hard_regno_mode_ok): Use targetm.hard_regno_nregs.
	* config/nios2/nios2.h (HARD_REGNO_NREGS): Delete.
	* config/nvptx/nvptx.h (HARD_REGNO_NREGS): Delete.
	* config/nvptx/nvptx.c (nvptx_hard_regno_nregs): New function.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/pa/pa32-regs.h (HARD_REGNO_NREGS): Rename to...
	(PA_HARD_REGNO_NREGS): ...this.
	* config/pa/pa64-regs.h (HARD_REGNO_NREGS): Rename to...
	(PA_HARD_REGNO_NREGS): ...this.
	* config/pa/pa.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(pa_hard_regno_nregs): New function.
	* config/pdp11/pdp11.h (HARD_REGNO_NREGS): Delete.
	* config/pdp11/pdp11.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(pdp11_hard_regno_nregs): New function.
	* config/powerpcspe/powerpcspe.h (HARD_REGNO_NREGS): Delete.
	* config/powerpcspe/powerpcspe.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(rs6000_hard_regno_nregs_hook): New function.
	* config/riscv/riscv.h (HARD_REGNO_NREGS): Delete.
	* config/riscv/riscv-protos.h (riscv_hard_regno_nregs): Delete.
	* config/riscv/riscv.c (riscv_hard_regno_nregs): Make static.
	Take and return an unsigned int.  Move earlier in file.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/rl78/rl78.h (HARD_REGNO_NREGS): Delete.
	* config/rl78/rl78-protos.h (rl78_hard_regno_nregs): Delete.
	* config/rl78/rl78.c (TARGET_HARD_REGNO_NREGS): Reefine.
	(rl78_hard_regno_nregs): Make static.  Take and return an
	unsigned int.
	* config/rs6000/rs6000.h (HARD_REGNO_NREGS): Delete.
	* config/rs6000/rs6000.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(rs6000_hard_regno_nregs_hook): New function.
	* config/rx/rx.h (HARD_REGNO_NREGS): Delete.
	* config/rx/rx.c (rx_hard_regno_nregs): New function.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/s390/s390.h (HARD_REGNO_NREGS): Delete.
	* config/s390/s390.c (REGNO_PAIR_OK): Use s390_hard_regno_nregs
	instead of HARD_REGNO_NREGS.
	(s390_hard_regno_nregs): New function.
	(s390_hard_regno_mode_ok): Add comment from s390.h.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/sh/sh.h (HARD_REGNO_NREGS): Delete.
	* config/sh/sh.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(sh_hard_regno_nregs): New function.
	(sh_pass_in_reg_p): Use it.
	* config/sparc/sparc.h (HARD_REGNO_NREGS): Delete.
	* config/sparc/sparc.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(sparc_hard_regno_nregs): New function.
	* config/spu/spu.h (HARD_REGNO_NREGS): Delete.
	* config/spu/spu.c (spu_hard_regno_nregs): New function.
	(spu_function_arg_advance): Use it, supplying a valid register number.
	(TARGET_HARD_REGNO_NREGS): Redefine.
	* config/stormy16/stormy16.h (HARD_REGNO_NREGS): Delete.
	* config/tilegx/tilegx.h (HARD_REGNO_NREGS): Delete.
	* config/tilepro/tilepro.h (HARD_REGNO_NREGS): Delete.
	* config/v850/v850.h (HARD_REGNO_NREGS): Delete.
	* config/vax/vax.h (HARD_REGNO_NREGS): Delete.
	* config/visium/visium.h (HARD_REGNO_NREGS): Delete.
	(CLASS_MAX_NREGS): Remove copy of old documentation.
	* config/visium/visium.c (TARGET_HARD_REGNO_NREGS): Redefine.
	(visium_hard_regno_nregs): New function.
	(visium_hard_regno_mode_ok): Use it instead of HARD_REGNO_NREGS.
	* config/xtensa/xtensa.h (HARD_REGNO_NREGS): Delete.
	* config/xtensa/xtensa.c (TARGET_HARD_REGNO_NREGS): Redefine.
	xtensa_hard_regno_nregs): New function.
	* system.h (HARD_REGNO_NREGS): Poison.

Comments

Jeff Law Sept. 11, 2017, 10:33 p.m. | #1
On 09/11/2017 11:18 AM, Richard Sandiford wrote:
> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.

> Also tested by comparing the testsuite assembly output on at least one

> target per CPU directory.  OK to install?

> 

> Richard

> 

> 

> gcc/

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

> 	(class_max_nregs): Refer to it instead of HARD_REGNO_NREGS.

> 	* targhooks.h (default_hard_regno_nregs): Declare.

> 	* targhooks.c (default_hard_regno_nregs): New function.

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

> 	(TARGET_HARD_REGNO_NREGS): ...this hook.

> 	(HARD_REGNO_NREGS_HAS_PADDING): Update accordingly.

> 	(CLASS_MAX_NREGS): Likewise.

> 	* doc/tm.texi: Regenerate.

> 	* reginfo.c (init_reg_modes_target): Use targetm.hard_regno_nregs

> 	instead of HARD_REGNO_NREGS.

> 	* rtl.h (REG_NREGS): Refer to TARGET_HARD_REGNO_NREGS rather than

> 	HARD_REGNO_NREGS in the comment.

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

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

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

> 	Return an unsigned int.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

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

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

> 	(arc_hard_regno_nregs): New function.

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

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

> 	(arm_hard_regno_nregs): New function.

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

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

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

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

> 	* config/cr16/cr16.h (LONG_REG_P): Use targetm.hard_regno_nregs.

> 	(HARD_REGNO_NREGS): Delete.

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

> 	(cr16_hard_regno_nregs): New function.

> 	(cr16_memory_move_cost): Use it instead of HARD_REGNO_NREGS.

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

> 	* config/cris/cris.c (TARGET_HARD_REGNO_NREGS): Redefine.

> 	(cris_hard_regno_nregs): New function.

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

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

> 	(CLASS_MAX_NREGS): Use targetm.hard_regno_nregs.

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

> 	(CLASS_MAX_NREGS): Remove outdated copy of documentation.

> 	* config/frv/frv-protos.h (frv_hard_regno_nregs): Delete.

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

> 	(frv_hard_regno_nregs): Make static.  Take and return an

> 	unsigned int.

> 	(frv_class_max_nregs): Remove outdated copy of documentation.

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

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

> 	* config/h8300/h8300-protos.h (h8300_hard_regno_nregs): Delete.

> 	* config/h8300/h8300.c (h8300_hard_regno_nregs): Delete.

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

> 	* config/i386/i386.c (ix86_hard_regno_nregs): New function.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

> 	(CLASS_MAX_NREGS): Update comment.

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

> 	(ia64_hard_regno_nregs): New function.

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

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

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

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

> 	* config/m32c/m32c.c (m32c_hard_regno_nregs_1): Take and return

> 	an unsigned int.

> 	(m32c_hard_regno_nregs): Likewise.  Make static.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

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

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

> 	(m68k_hard_regno_nregs): New function.

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

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

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

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

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

> 	Take and return an unsigned int.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

> 	(CLASS_MAX_NREGS): Use targetm.hard_regno_nregs.

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

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

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

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

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

> 	(msp430_hard_regno_nregs): Make static.  Take and return an

> 	unsigned int.

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

> 	* config/nds32/nds32-protos.h (nds32_hard_regno_nregs): Delete.

> 	* config/nds32/nds32.c (nds32_hard_regno_nregs): Delete.

> 	(nds32_hard_regno_mode_ok): Use targetm.hard_regno_nregs.

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

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

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

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

> 	* config/pa/pa32-regs.h (HARD_REGNO_NREGS): Rename to...

> 	(PA_HARD_REGNO_NREGS): ...this.

> 	* config/pa/pa64-regs.h (HARD_REGNO_NREGS): Rename to...

> 	(PA_HARD_REGNO_NREGS): ...this.

> 	* config/pa/pa.c (TARGET_HARD_REGNO_NREGS): Redefine.

> 	(pa_hard_regno_nregs): New function.

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

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

> 	(pdp11_hard_regno_nregs): New function.

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

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

> 	(rs6000_hard_regno_nregs_hook): New function.

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

> 	* config/riscv/riscv-protos.h (riscv_hard_regno_nregs): Delete.

> 	* config/riscv/riscv.c (riscv_hard_regno_nregs): Make static.

> 	Take and return an unsigned int.  Move earlier in file.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

> 	* config/rl78/rl78-protos.h (rl78_hard_regno_nregs): Delete.

> 	* config/rl78/rl78.c (TARGET_HARD_REGNO_NREGS): Reefine.

> 	(rl78_hard_regno_nregs): Make static.  Take and return an

> 	unsigned int.

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

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

> 	(rs6000_hard_regno_nregs_hook): New function.

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

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

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

> 	* config/s390/s390.c (REGNO_PAIR_OK): Use s390_hard_regno_nregs

> 	instead of HARD_REGNO_NREGS.

> 	(s390_hard_regno_nregs): New function.

> 	(s390_hard_regno_mode_ok): Add comment from s390.h.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

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

> 	(sh_hard_regno_nregs): New function.

> 	(sh_pass_in_reg_p): Use it.

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

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

> 	(sparc_hard_regno_nregs): New function.

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

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

> 	(spu_function_arg_advance): Use it, supplying a valid register number.

> 	(TARGET_HARD_REGNO_NREGS): Redefine.

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

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

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

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

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

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

> 	(CLASS_MAX_NREGS): Remove copy of old documentation.

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

> 	(visium_hard_regno_nregs): New function.

> 	(visium_hard_regno_mode_ok): Use it instead of HARD_REGNO_NREGS.

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

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

> 	xtensa_hard_regno_nregs): New function.

> 	* system.h (HARD_REGNO_NREGS): Poison.

OK.
jeff

Patch

Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-11 17:55:38.950289484 +0100
+++ gcc/target.def	2017-09-11 17:55:40.037247666 +0100
@@ -5345,10 +5345,10 @@  DEFHOOK
  "A target hook returns the maximum number of consecutive registers\n\
 of class @var{rclass} needed to hold a value of mode @var{mode}.\n\
 \n\
-This is closely related to the macro @code{HARD_REGNO_NREGS}.  In fact,\n\
-the value returned by @code{TARGET_CLASS_MAX_NREGS (@var{rclass},\n\
+This is closely related to the macro @code{TARGET_HARD_REGNO_NREGS}.\n\
+In fact, the value returned by @code{TARGET_CLASS_MAX_NREGS (@var{rclass},\n\
 @var{mode})} target hook should be the maximum value of\n\
-@code{HARD_REGNO_NREGS (@var{regno}, @var{mode})} for all @var{regno}\n\
+@code{TARGET_HARD_REGNO_NREGS (@var{regno}, @var{mode})} for all @var{regno}\n\
 values in the class @var{rclass}.\n\
 \n\
 This target hook helps control the handling of multiple-word values\n\
@@ -5425,6 +5425,19 @@  that are not actually in any insns yet,
  hook_void_void)
 
 DEFHOOK
+(hard_regno_nregs,
+ "This hook returns the number of consecutive hard registers, starting\n\
+at register number @var{regno}, required to hold a value of mode\n\
+@var{mode}.  This hook must never return zero, even if a register\n\
+cannot hold the requested mode - indicate that with\n\
+@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}\n\
+instead.\n\
+\n\
+The default definition returns the number of words in @var{mode}.",
+ unsigned int, (unsigned int regno, machine_mode mode),
+ default_hard_regno_nregs)
+
+DEFHOOK
 (hard_regno_mode_ok,
  "This hook returns true if it is permissible to store a value\n\
 of mode @var{mode} in hard register number @var{regno} (or in several\n\
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/targhooks.h	2017-09-11 17:55:40.038247628 +0100
@@ -165,6 +165,7 @@  extern int default_reloc_rw_mask (void);
 extern tree default_mangle_decl_assembler_name (tree, tree);
 extern tree default_emutls_var_fields (tree, tree *);
 extern tree default_emutls_var_init (tree, tree, tree);
+extern unsigned int default_hard_regno_nregs (unsigned int, machine_mode);
 extern bool default_hard_regno_scratch_ok (unsigned int);
 extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/targhooks.c	2017-09-11 17:55:40.037247666 +0100
@@ -1424,6 +1424,14 @@  default_addr_space_convert (rtx op ATTRI
   gcc_unreachable ();
 }
 
+/* The defualt implementation of TARGET_HARD_REGNO_NREGS.  */
+
+unsigned int
+default_hard_regno_nregs (unsigned int, machine_mode mode)
+{
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 bool
 default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
 {
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-09-11 17:55:38.950289484 +0100
+++ gcc/doc/tm.texi.in	2017-09-11 17:55:40.032247858 +0100
@@ -1804,23 +1804,7 @@  This section discusses the macros that d
 (specifically, which machine modes) each register can hold, and how many
 consecutive registers are needed for a given mode.
 
-@defmac HARD_REGNO_NREGS (@var{regno}, @var{mode})
-A C expression for the number of consecutive hard registers, starting
-at register number @var{regno}, required to hold a value of mode
-@var{mode}.  This macro must never return zero, even if a register
-cannot hold the requested mode - indicate that with
-@code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}
-instead.
-
-On a machine where all registers are exactly one word, a suitable
-definition of this macro is
-
-@smallexample
-#define HARD_REGNO_NREGS(REGNO, MODE)            \
-   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
-    / UNITS_PER_WORD)
-@end smallexample
-@end defmac
+@hook TARGET_HARD_REGNO_NREGS
 
 @defmac HARD_REGNO_NREGS_HAS_PADDING (@var{regno}, @var{mode})
 A C expression that is nonzero if a value of mode @var{mode}, stored
@@ -1828,7 +1812,7 @@  in memory, ends with padding that causes
 in registers starting at register number @var{regno} (as determined by
 multiplying GCC's notion of the size of the register when containing
 this mode by the number of registers returned by
-@code{HARD_REGNO_NREGS}).  By default this is zero.
+@code{TARGET_HARD_REGNO_NREGS}).  By default this is zero.
 
 For example, if a floating-point value is stored in three 32-bit
 registers but takes up 128 bits in memory, then this would be
@@ -2372,9 +2356,9 @@  is @code{BITS_PER_WORD} bits wide is cor
 A C expression for the maximum number of consecutive registers
 of class @var{class} needed to hold a value of mode @var{mode}.
 
-This is closely related to the macro @code{HARD_REGNO_NREGS}.  In fact,
+This is closely related to the macro @code{TARGET_HARD_REGNO_NREGS}.  In fact,
 the value of the macro @code{CLASS_MAX_NREGS (@var{class}, @var{mode})}
-should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno},
+should be the maximum value of @code{TARGET_HARD_REGNO_NREGS (@var{regno},
 @var{mode})} for all @var{regno} values in the class @var{class}.
 
 This macro helps control the handling of multiple-word values
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-11 17:55:38.950289484 +0100
+++ gcc/doc/tm.texi	2017-09-11 17:55:40.030247935 +0100
@@ -2013,23 +2013,16 @@  This section discusses the macros that d
 (specifically, which machine modes) each register can hold, and how many
 consecutive registers are needed for a given mode.
 
-@defmac HARD_REGNO_NREGS (@var{regno}, @var{mode})
-A C expression for the number of consecutive hard registers, starting
+@deftypefn {Target Hook} {unsigned int} TARGET_HARD_REGNO_NREGS (unsigned int @var{regno}, machine_mode @var{mode})
+This hook returns the number of consecutive hard registers, starting
 at register number @var{regno}, required to hold a value of mode
-@var{mode}.  This macro must never return zero, even if a register
+@var{mode}.  This hook must never return zero, even if a register
 cannot hold the requested mode - indicate that with
 @code{TARGET_HARD_REGNO_MODE_OK} and/or @code{CANNOT_CHANGE_MODE_CLASS}
 instead.
 
-On a machine where all registers are exactly one word, a suitable
-definition of this macro is
-
-@smallexample
-#define HARD_REGNO_NREGS(REGNO, MODE)            \
-   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
-    / UNITS_PER_WORD)
-@end smallexample
-@end defmac
+The default definition returns the number of words in @var{mode}.
+@end deftypefn
 
 @defmac HARD_REGNO_NREGS_HAS_PADDING (@var{regno}, @var{mode})
 A C expression that is nonzero if a value of mode @var{mode}, stored
@@ -2037,7 +2030,7 @@  in memory, ends with padding that causes
 in registers starting at register number @var{regno} (as determined by
 multiplying GCC's notion of the size of the register when containing
 this mode by the number of registers returned by
-@code{HARD_REGNO_NREGS}).  By default this is zero.
+@code{TARGET_HARD_REGNO_NREGS}).  By default this is zero.
 
 For example, if a floating-point value is stored in three 32-bit
 registers but takes up 128 bits in memory, then this would be
@@ -2798,10 +2791,10 @@  pressure.
 A target hook returns the maximum number of consecutive registers
 of class @var{rclass} needed to hold a value of mode @var{mode}.
 
-This is closely related to the macro @code{HARD_REGNO_NREGS}.  In fact,
-the value returned by @code{TARGET_CLASS_MAX_NREGS (@var{rclass},
+This is closely related to the macro @code{TARGET_HARD_REGNO_NREGS}.
+In fact, the value returned by @code{TARGET_CLASS_MAX_NREGS (@var{rclass},
 @var{mode})} target hook should be the maximum value of
-@code{HARD_REGNO_NREGS (@var{regno}, @var{mode})} for all @var{regno}
+@code{TARGET_HARD_REGNO_NREGS (@var{regno}, @var{mode})} for all @var{regno}
 values in the class @var{rclass}.
 
 This target hook helps control the handling of multiple-word values
@@ -2815,9 +2808,9 @@  in words.
 A C expression for the maximum number of consecutive registers
 of class @var{class} needed to hold a value of mode @var{mode}.
 
-This is closely related to the macro @code{HARD_REGNO_NREGS}.  In fact,
+This is closely related to the macro @code{TARGET_HARD_REGNO_NREGS}.  In fact,
 the value of the macro @code{CLASS_MAX_NREGS (@var{class}, @var{mode})}
-should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno},
+should be the maximum value of @code{TARGET_HARD_REGNO_NREGS (@var{regno},
 @var{mode})} for all @var{regno} values in the class @var{class}.
 
 This macro helps control the handling of multiple-word values
Index: gcc/reginfo.c
===================================================================
--- gcc/reginfo.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/reginfo.c	2017-09-11 17:55:40.033247820 +0100
@@ -509,7 +509,7 @@  init_reg_modes_target (void)
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     for (j = 0; j < MAX_MACHINE_MODE; j++)
       this_target_regs->x_hard_regno_nregs[i][j]
-	= HARD_REGNO_NREGS (i, (machine_mode)j);
+	= targetm.hard_regno_nregs (i, (machine_mode) j);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/rtl.h	2017-09-11 17:55:40.034247781 +0100
@@ -1802,7 +1802,7 @@  #define REGNO(RTX) (rhs_regno(RTX))
 #define SET_REGNO(RTX, N) (df_ref_change_reg_with_loc (RTX, N))
 
 /* Return the number of consecutive registers in a REG.  This is always
-   1 for pseudo registers and is determined by HARD_REGNO_NREGS for
+   1 for pseudo registers and is determined by TARGET_HARD_REGNO_NREGS for
    hard registers.  */
 #define REG_NREGS(RTX) (REG_CHECK (RTX)->nregs)
 
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/aarch64/aarch64.h	2017-09-11 17:55:39.950251013 +0100
@@ -401,8 +401,6 @@  #define DWARF_FRAME_REGNUM(REGNO)	DBX_RE
 
 #define DWARF_FRAME_RETURN_COLUMN	DWARF_FRAME_REGNUM (LR_REGNUM)
 
-#define HARD_REGNO_NREGS(REGNO, MODE)	aarch64_hard_regno_nregs (REGNO, MODE)
-
 #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-09-11 17:55:38.950289484 +0100
+++ gcc/config/aarch64/aarch64-protos.h	2017-09-11 17:55:39.949251051 +0100
@@ -384,7 +384,6 @@  int aarch64_asm_preferred_eh_data_format
 int aarch64_fpconst_pow_of_2 (rtx);
 machine_mode aarch64_hard_regno_caller_save_mode (unsigned, unsigned,
 						       machine_mode);
-int aarch64_hard_regno_nregs (unsigned, machine_mode);
 int aarch64_uxt_size (int, HOST_WIDE_INT);
 int aarch64_vec_fpconst_pow_of_2 (rtx);
 rtx aarch64_eh_return_handler_rtx (void);
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/aarch64/aarch64.c	2017-09-11 17:55:39.950251013 +0100
@@ -1067,9 +1067,9 @@  aarch64_array_mode_supported_p (machine_
   return false;
 }
 
-/* Implement HARD_REGNO_NREGS.  */
+/* Implement TARGET_HARD_REGNO_NREGS.  */
 
-int
+static unsigned int
 aarch64_hard_regno_nregs (unsigned regno, machine_mode mode)
 {
   switch (aarch64_regno_regclass (regno))
@@ -15685,6 +15685,8 @@  #define TARGET_OMIT_STRUCT_RETURN_REG tr
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS aarch64_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK aarch64_hard_regno_mode_ok
 
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/alpha/alpha.h	2017-09-11 17:55:39.950251013 +0100
@@ -371,14 +371,6 @@  #define REG_ALLOC_ORDER { \
    29, 30, 31, 63		/* gp, sp, ap, sfp */			\
 }
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-  CEIL (GET_MODE_SIZE (MODE), UNITS_PER_WORD)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/arc/arc.h
===================================================================
--- gcc/config/arc/arc.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/arc/arc.h	2017-09-11 17:55:39.952250936 +0100
@@ -441,15 +441,6 @@  #define REG_ALLOC_ORDER \
   48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,		\
   27, 28, 29, 30, 31, 63}
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((GET_MODE_SIZE (MODE) == 16 \
-  && REGNO >= ARC_FIRST_SIMD_VR_REG && REGNO <= ARC_LAST_SIMD_VR_REG) ? 1 \
- : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/arc/arc.c	2017-09-11 17:55:39.951250975 +0100
@@ -590,6 +590,8 @@  #define TARGET_HAVE_TLS HAVE_AS_TLS
 #undef TARGET_DWARF_REGISTER_SPAN
 #define TARGET_DWARF_REGISTER_SPAN arc_dwarf_register_span
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS arc_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK arc_hard_regno_mode_ok
 
@@ -1877,6 +1879,19 @@  arc_conditional_register_usage (void)
   }
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+arc_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (GET_MODE_SIZE (mode) == 16
+      && regno >= ARC_FIRST_SIMD_VR_REG
+      && regno <= ARC_LAST_SIMD_VR_REG)
+    return 1;
+
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/arm/arm.h	2017-09-11 17:55:39.956250782 +0100
@@ -976,20 +976,6 @@  #define DBX_REGISTER_NUMBER(REGNO) arm_d
 #define SUBTARGET_FRAME_POINTER_REQUIRED 0
 #endif
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-
-   On the ARM core regs are UNITS_PER_WORD bits wide.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)  	\
-  ((TARGET_32BIT			\
-    && REGNO > PC_REGNUM		\
-    && REGNO != FRAME_POINTER_REGNUM	\
-    && REGNO != ARG_POINTER_REGNUM)	\
-    && !IS_VFP_REGNUM (REGNO)		\
-   ? 1 : ARM_NUM_REGS (MODE))
-
 #define VALID_IWMMXT_REG_MODE(MODE) \
  (arm_vector_mode_supported_p (MODE) || (MODE) == DImode)
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/arm/arm.c	2017-09-11 17:55:39.956250782 +0100
@@ -314,6 +314,7 @@  static unsigned int arm_elf_section_type
 						int reloc);
 static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
 static opt_scalar_float_mode arm_floatn_mode (int, bool);
+static unsigned int arm_hard_regno_nregs (unsigned int, machine_mode);
 static bool arm_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool arm_modes_tieable_p (machine_mode, machine_mode);
 
@@ -785,6 +786,8 @@  #define TARGET_CUSTOM_FUNCTION_DESCRIPTO
 #undef TARGET_FIXED_CONDITION_CODE_REGS
 #define TARGET_FIXED_CONDITION_CODE_REGS arm_fixed_condition_code_regs
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS arm_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK arm_hard_regno_mode_ok
 
@@ -23348,6 +23351,21 @@  thumb2_asm_output_opcode (FILE * stream)
     }
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  On the ARM core regs are
+   UNITS_PER_WORD bytes wide.  */
+static unsigned int
+arm_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_32BIT
+      && regno > PC_REGNUM
+      && regno != FRAME_POINTER_REGNUM
+      && regno != ARG_POINTER_REGNUM
+      && !IS_VFP_REGNUM (regno))
+    return 1;
+
+  return ARM_NUM_REGS (mode);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 static bool
 arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/avr/avr.h	2017-09-11 17:55:39.957250744 +0100
@@ -209,9 +209,6 @@  #define REG_ALLOC_ORDER {			\
 #define ADJUST_REG_ALLOC_ORDER avr_adjust_reg_alloc_order()
 
 
-#define HARD_REGNO_NREGS(REGNO, MODE)                                   \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 enum reg_class {
   NO_REGS,
   R0_REG,			/* r0 */
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/bfin/bfin.h	2017-09-11 17:55:39.957250744 +0100
@@ -683,11 +683,6 @@  #define CLASS_MAX_NREGS(CLASS, MODE)
   ((MODE) == V2PDImode && (CLASS) == AREGS ? 2				\
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-  ((MODE) == PDImode && ((REGNO) == REG_A0 || (REGNO) == REG_A1) ? 1	\
-   : (MODE) == V2PDImode && ((REGNO) == REG_A0 || (REGNO) == REG_A1) ? 2 \
-   : CLASS_MAX_NREGS (GENERAL_REGS, MODE))
-
 /* A C expression that is nonzero if hard register TO can be
    considered for use as a rename register for FROM register */
 #define HARD_REGNO_RENAME_OK(FROM, TO) bfin_hard_regno_rename_ok (FROM, TO)
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/bfin/bfin.c	2017-09-11 17:55:39.957250744 +0100
@@ -2114,6 +2114,18 @@  bfin_expand_call (rtx retval, rtx fnaddr
     CALL_INSN_FUNCTION_USAGE (call) = use;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+bfin_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (mode == PDImode && (regno == REG_A0 || regno == REG_A1))
+    return 1;
+  if (mode == V2PDImode && (regno == REG_A0 || regno == REG_A1))
+    return 2;
+  return CLASS_MAX_NREGS (GENERAL_REGS, mode);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.
 
    Do not allow to store a value in REG_CC for any mode.
@@ -5862,6 +5874,8 @@  #define TARGET_DELAY_VARTRACK true
 #undef TARGET_CAN_USE_DOLOOP_P
 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS bfin_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
 
Index: gcc/config/c6x/c6x.h
===================================================================
--- gcc/config/c6x/c6x.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/c6x/c6x.h	2017-09-11 17:55:39.957250744 +0100
@@ -181,11 +181,6 @@  #define REG_ALLOC_ORDER							\
     REG_A1, REG_A2, REG_B0, REG_B1, REG_B2, REG_ILC			\
   }
 
-#define HARD_REGNO_NREGS(regno, mode)		\
-  ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)  \
-   / UNITS_PER_WORD)
-
-
 /* Register Classes.  */
 
 enum reg_class
Index: gcc/config/cr16/cr16.h
===================================================================
--- gcc/config/cr16/cr16.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/cr16/cr16.h	2017-09-11 17:55:39.958250705 +0100
@@ -197,12 +197,8 @@  #define CALL_USED_REGISTERS
 
 /* Returns 1 if the register is longer than word size, 0 otherwise.  */
 #define LONG_REG_P(REGNO)                                                    \
-  (HARD_REGNO_NREGS (REGNO, GET_MODE_WIDER_MODE (word_mode).require ()) == 1)
-
-#define HARD_REGNO_NREGS(REGNO, MODE)                                         \
- ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                        \
-  ? ((GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD)\
-  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD       - 1) / UNITS_PER_WORD))
+  (targetm.hard_regno_nregs (REGNO,                                          \
+			     GET_MODE_WIDER_MODE (word_mode).require ()) == 1)
 
 #define NOTICE_UPDATE_CC(EXP, INSN) \
    notice_update_cc ((EXP))
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/cr16/cr16.c	2017-09-11 17:55:39.958250705 +0100
@@ -220,6 +220,8 @@  #define TARGET_ASM_UNALIGNED_SI_OP 	TARG
 #undef TARGET_ASM_UNALIGNED_DI_OP
 #define TARGET_ASM_UNALIGNED_DI_OP 	TARGET_ASM_ALIGNED_DI_OP
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS		cr16_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK	cr16_hard_regno_mode_ok
 #undef TARGET_MODES_TIEABLE_P
@@ -468,6 +470,16 @@  cr16_regno_reg_class (int regno)
   return NO_REGS;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+cr16_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno >= CR16_FIRST_DWORD_REGISTER)
+    return CEIL (GET_MODE_SIZE (mode), CR16_UNITS_PER_DWORD);
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the CR16 architecture, all
    registers can hold all modes, except that double precision floats
    (and double ints) must fall on even-register boundaries.  */
@@ -1371,7 +1383,7 @@  cr16_memory_move_cost (machine_mode mode
 {
   /* One LD or ST takes twice the time of a simple reg-reg move.  */
   if (reg_classes_intersect_p (rclass, GENERAL_REGS))
-    return (4 * HARD_REGNO_NREGS (0, mode));
+    return (4 * cr16_hard_regno_nregs (0, mode));
   else
     return (100);
 }
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/cris/cris.h	2017-09-11 17:55:39.958250705 +0100
@@ -469,14 +469,6 @@  #define REG_ALLOC_ORDER_V32 \
  {15, 9, 13, 12, 11, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 16, 14, 18, 19}
 
 
-/* Node: Values in Registers */
-
-/* The VOIDmode test is so we can omit mode on anonymous insns.  FIXME:
-   Still needed in 2.9x, at least for Axis-20000319.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)	\
- (MODE == VOIDmode \
-  ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* Node: Leaf Functions */
 /* (no definitions) */
 
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/cris/cris.c	2017-09-11 17:55:39.958250705 +0100
@@ -163,6 +163,7 @@  static rtx cris_function_value(const_tre
 static rtx cris_libcall_value (machine_mode, const_rtx);
 static bool cris_function_value_regno_p (const unsigned int);
 static void cris_file_end (void);
+static unsigned int cris_hard_regno_nregs (unsigned int, machine_mode);
 static bool cris_hard_regno_mode_ok (unsigned int, machine_mode);
 
 /* This is the parsed result of the "-max-stack-stackframe=" option.  If
@@ -281,6 +282,8 @@  #define TARGET_LIBCALL_VALUE cris_libcal
 #undef TARGET_FUNCTION_VALUE_REGNO_P
 #define TARGET_FUNCTION_VALUE_REGNO_P cris_function_value_regno_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS cris_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK cris_hard_regno_mode_ok
 
@@ -4296,6 +4299,19 @@  cris_trampoline_init (rtx m_tramp, tree
      sake of a trampoline.  */
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.
+
+   The VOIDmode test is so we can omit mode on anonymous insns.  FIXME:
+   Still needed in 2.9x, at least for Axis-20000319.  */
+
+static unsigned int
+cris_hard_regno_nregs (unsigned int, machine_mode mode)
+{
+  if (mode == VOIDmode)
+    return 1;
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.
 
    CRIS permits all registers to hold all modes.  Well, except for the
Index: gcc/config/epiphany/epiphany.h
===================================================================
--- gcc/config/epiphany/epiphany.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/epiphany/epiphany.h	2017-09-11 17:55:39.959250667 +0100
@@ -302,13 +302,6 @@  #define REG_ALLOC_ORDER \
 
 #define HARD_REGNO_RENAME_OK(SRC, DST) epiphany_regno_rename_ok (SRC, DST)
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/fr30/fr30.h	2017-09-11 17:55:39.959250667 +0100
@@ -238,15 +238,6 @@  #define ADDITIONAL_REGISTER_NAMES 				\
 }
 
 /*}}}*/ 
-/*{{{  How Values Fit in Registers.  */ 
-
-/* A C expression for the number of consecutive hard registers, starting at
-   register number REGNO, required to hold a value of mode MODE.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) 			\
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/*}}}*/ 
 /*{{{  Register Classes.  */ 
 
 /* An enumeral type that must be defined with all the register class names as
@@ -345,16 +336,7 @@  #define REGNO_OK_FOR_BASE_P(NUM) 1
    will reload one or both registers only if neither labeling works.  */
 #define REGNO_OK_FOR_INDEX_P(NUM) 1
 
-/* A C expression for the maximum number of consecutive registers of
-   class CLASS needed to hold a value of mode MODE.
-
-   This is closely related to the macro `HARD_REGNO_NREGS'.  In fact, the value
-   of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of
-   `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS.
-
-   This macro helps control the handling of multiple-word values in
-   the reload pass.  */
-#define CLASS_MAX_NREGS(CLASS, MODE) HARD_REGNO_NREGS (0, MODE)
+#define CLASS_MAX_NREGS(CLASS, MODE) targetm.hard_regno_nregs (0, MODE)
 
 /*}}}*/ 
 /*{{{  Basic Stack Layout.  */ 
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/frv/frv.h	2017-09-11 17:55:39.961250590 +0100
@@ -747,22 +747,6 @@  #define REG_ALLOC_ORDER							\
 }
 
 
-/* How Values Fit in Registers.  */
-
-/* A C expression for the number of consecutive hard registers, starting at
-   register number REGNO, required to hold a value of mode MODE.
-
-   On a machine where all registers are exactly one word, a suitable definition
-   of this macro is
-
-        #define HARD_REGNO_NREGS(REGNO, MODE)            \
-           ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
-            / UNITS_PER_WORD))  */
-
-/* On the FRV, make the CC modes take 3 words in the integer registers, so that
-   we can build the appropriate instructions to properly reload the values.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) frv_hard_regno_nregs (REGNO, MODE)
-
 /* 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.  */
@@ -930,17 +914,6 @@  #define SECONDARY_INPUT_RELOAD_CLASS(CLA
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
   frv_secondary_reload_class (CLASS, MODE, X)
 
-/* A C expression for the maximum number of consecutive registers of
-   class CLASS needed to hold a value of mode MODE.
-
-   This is closely related to the macro `HARD_REGNO_NREGS'.  In fact, the value
-   of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of
-   `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS.
-
-   This macro helps control the handling of multiple-word values in
-   the reload pass.
-
-   This declaration is required.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) frv_class_max_nregs (CLASS, MODE)
 
 #define ZERO_P(x) (x == CONST0_RTX (GET_MODE (x)))
Index: gcc/config/frv/frv-protos.h
===================================================================
--- gcc/config/frv/frv-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/frv/frv-protos.h	2017-09-11 17:55:39.959250667 +0100
@@ -74,7 +74,6 @@  extern void frv_ifcvt_modify_cancel	(str
 extern enum reg_class frv_secondary_reload_class
 					(enum reg_class,
 					 machine_mode, rtx);
-extern int frv_hard_regno_nregs		(int, machine_mode);
 extern int frv_class_max_nregs		(enum reg_class rclass,
 					 machine_mode mode);
 extern machine_mode frv_select_cc_mode (enum rtx_code, rtx, rtx);
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/frv/frv.c	2017-09-11 17:55:39.960250628 +0100
@@ -397,6 +397,7 @@  static bool frv_can_eliminate			(const i
 static void frv_conditional_register_usage	(void);
 static void frv_trampoline_init			(rtx, tree, rtx);
 static bool frv_class_likely_spilled_p 		(reg_class_t);
+static unsigned int frv_hard_regno_nregs	(unsigned int, machine_mode);
 static bool frv_hard_regno_mode_ok		(unsigned int, machine_mode);
 static bool frv_modes_tieable_p			(machine_mode, machine_mode);
 
@@ -516,6 +517,8 @@  #define TARGET_FUNCTION_VALUE frv_functi
 #undef TARGET_LIBCALL_VALUE
 #define TARGET_LIBCALL_VALUE frv_libcall_value
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS frv_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK frv_hard_regno_mode_ok
 #undef TARGET_MODES_TIEABLE_P
@@ -6600,23 +6603,15 @@  frv_modes_tieable_p (machine_mode mode1,
 }
 
 
-/* A C expression for the number of consecutive hard registers, starting at
-   register number REGNO, required to hold a value of mode MODE.
+/* Implement TARGET_HARD_REGNO_NREGS.
 
-   On a machine where all registers are exactly one word, a suitable definition
-   of this macro is
-
-        #define HARD_REGNO_NREGS(REGNO, MODE)            \
-           ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
-            / UNITS_PER_WORD))  */
-
-/* On the FRV, make the CC_FP mode take 3 words in the integer registers, so
+   On the FRV, make the CC_FP mode take 3 words in the integer registers, so
    that we can build the appropriate instructions to properly reload the
    values.  Also, make the byte-sized accumulator guards use one guard
    for each byte.  */
 
-int
-frv_hard_regno_nregs (int regno, machine_mode mode)
+static unsigned int
+frv_hard_regno_nregs (unsigned int regno, machine_mode mode)
 {
   if (ACCG_P (regno))
     return GET_MODE_SIZE (mode);
@@ -6625,17 +6620,7 @@  frv_hard_regno_nregs (int regno, machine
 }
 
 
-/* A C expression for the maximum number of consecutive registers of
-   class RCLASS needed to hold a value of mode MODE.
-
-   This is closely related to the macro `HARD_REGNO_NREGS'.  In fact, the value
-   of the macro `CLASS_MAX_NREGS (RCLASS, MODE)' should be the maximum value of
-   `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class RCLASS.
-
-   This macro helps control the handling of multiple-word values in
-   the reload pass.
-
-   This declaration is required.  */
+/* Implement CLASS_MAX_NREGS.  */
 
 int
 frv_class_max_nregs (enum reg_class rclass, machine_mode mode)
Index: gcc/config/ft32/ft32.h
===================================================================
--- gcc/config/ft32/ft32.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/ft32/ft32.h	2017-09-11 17:55:39.961250590 +0100
@@ -171,13 +171,6 @@  #define AVOID_CCMODE_COPIES 1
 #define REGNO_REG_CLASS(R) ((R < FT32_PC) ? GENERAL_REGS :                \
                             (R == FT32_CC ? CC_REGS : SPECIAL_REGS))
 
-/* A C expression for the number of consecutive hard registers,
-   starting at register number REGNO, required to hold a value of mode
-   MODE.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)                      \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)             \
-   / UNITS_PER_WORD)
-
 /* The Overall Framework of an Assembler File */
 
 #undef  ASM_SPEC
Index: gcc/config/h8300/h8300.h
===================================================================
--- gcc/config/h8300/h8300.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/h8300/h8300.h	2017-09-11 17:55:39.963250513 +0100
@@ -236,9 +236,6 @@  #define REG_ALLOC_ORDER				\
 /* r0 r1 r2 r3 r4 r5 r6 r7 mac ap rap  fp */	\
   { 2, 3, 0, 1, 4, 5, 6, 8,  7, 9, 10, 11 }
 
-#define HARD_REGNO_NREGS(REGNO, MODE)		\
-  h8300_hard_regno_nregs ((REGNO), (MODE))
-
 /* 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-protos.h
===================================================================
--- gcc/config/h8300/h8300-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/h8300/h8300-protos.h	2017-09-11 17:55:39.961250590 +0100
@@ -99,7 +99,6 @@  extern int h8300_current_function_monito
 extern int h8300_initial_elimination_offset (int, int);
 extern int h8300_regs_ok_for_stm (int, rtx[]);
 extern int h8300_hard_regno_rename_ok (unsigned int, unsigned int);
-extern int h8300_hard_regno_nregs (int, machine_mode);
 extern bool h8300_move_ok (rtx, rtx);
 
 struct cpp_reader;
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/h8300/h8300.c	2017-09-11 17:55:39.963250513 +0100
@@ -5878,17 +5878,6 @@  h8300_legitimate_address_p (machine_mode
   return 0;
 }
 
-/* Worker function for HARD_REGNO_NREGS.
-
-   We pretend the MAC register is 32bits -- we don't have any data
-   types on the H8 series to handle more than 32bits.  */
-
-int
-h8300_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, machine_mode mode)
-{
-  return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/i386/i386.h	2017-09-11 17:55:39.969250282 +0100
@@ -1073,25 +1073,6 @@  #define ADJUST_REG_ALLOC_ORDER x86_order
 
 #define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL)
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-
-   Actually there are no two word move instructions for consecutive
-   registers.  And only registers 0-3 may have mov byte instructions
-   applied to them.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
-  (GENERAL_REGNO_P (REGNO)						\
-   ? ((MODE) == XFmode							\
-      ? (TARGET_64BIT ? 2 : 3)						\
-      : ((MODE) == XCmode						\
-	 ? (TARGET_64BIT ? 4 : 6)					\
-	 : CEIL (GET_MODE_SIZE (MODE), UNITS_PER_WORD)))		\
-   : (COMPLEX_MODE_P (MODE) ? 2 :					\
-      (((MODE == V64SFmode) || (MODE == V64SImode)) ? 4 : 1)))
-
 #define HARD_REGNO_NREGS_HAS_PADDING(REGNO, MODE)			\
   (TARGET_128BIT_LONG_DOUBLE && !TARGET_64BIT				\
    && GENERAL_REGNO_P (REGNO)						\
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/i386/i386.c	2017-09-11 17:55:39.968250321 +0100
@@ -41410,6 +41410,32 @@  ix86_register_move_cost (machine_mode mo
   return 2;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  This is ordinarily the length in
+   words of a value of mode MODE but can be less for certain modes in
+   special long registers.
+
+   Actually there are no two word move instructions for consecutive
+   registers.  And only registers 0-3 may have mov byte instructions
+   applied to them.  */
+
+static unsigned int
+ix86_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (GENERAL_REGNO_P (regno))
+    {
+      if (mode == XFmode)
+	return TARGET_64BIT ? 2 : 3;
+      if (mode == XCmode)
+	return TARGET_64BIT ? 4 : 6;
+      return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+    }
+  if (COMPLEX_MODE_P (mode))
+    return 2;
+  if (mode == V64SFmode || mode == V64SImode)
+    return 4;
+  return 1;
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
@@ -53376,6 +53402,8 @@  #define TARGET_MAX_NOCE_IFCVT_SEQ_COST i
 #undef TARGET_NOCE_CONVERSION_PROFITABLE_P
 #define TARGET_NOCE_CONVERSION_PROFITABLE_P ix86_noce_conversion_profitable_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS ix86_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK ix86_hard_regno_mode_ok
 
Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/ia64/ia64.h	2017-09-11 17:55:39.970250244 +0100
@@ -598,22 +598,6 @@  #define REG_ALLOC_ORDER							   \
 
 /* How Values Fit in Registers */
 
-/* A C expression for the number of consecutive hard registers, starting at
-   register number REGNO, required to hold a value of mode MODE.  */
-
-/* ??? We say that BImode PR values require two registers.  This allows us to
-   easily store the normal and inverted values.  We use CCImode to indicate
-   a single predicate register.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
-  ((REGNO) == PR_REG (0) && (MODE) == DImode ? 64			\
-   : PR_REGNO_P (REGNO) && (MODE) == BImode ? 2				\
-   : (PR_REGNO_P (REGNO) || GR_REGNO_P (REGNO)) && (MODE) == CCImode ? 1\
-   : FR_REGNO_P (REGNO) && (MODE) == XFmode ? 1				\
-   : FR_REGNO_P (REGNO) && (MODE) == RFmode ? 1				\
-   : FR_REGNO_P (REGNO) && (MODE) == XCmode ? 2				\
-   : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* Specify the modes required to caller save a given hard regno.
    We need to ensure floating pt regs are not saved as DImode.  */
 
@@ -803,7 +787,7 @@  #define SECONDARY_MEMORY_NEEDED(CLASS1,
 
 /* A C expression for the maximum number of consecutive registers of
    class CLASS needed to hold a value of mode MODE.
-   This is closely related to the macro `HARD_REGNO_NREGS'.  */
+   This is closely related to TARGET_HARD_REGNO_NREGS.  */
 
 #define CLASS_MAX_NREGS(CLASS, MODE) \
   ((MODE) == BImode && (CLASS) == PR_REGS ? 2			\
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/ia64/ia64.c	2017-09-11 17:55:39.969250282 +0100
@@ -336,6 +336,7 @@  static section * ia64_hpux_function_sect
 static bool ia64_vectorize_vec_perm_const_ok (machine_mode vmode,
 					      const unsigned char *sel);
 
+static unsigned int ia64_hard_regno_nregs (unsigned int, machine_mode);
 static bool ia64_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool ia64_modes_tieable_p (machine_mode, machine_mode);
 
@@ -659,6 +660,8 @@  #define TARGET_ATTRIBUTE_TAKES_IDENTIFIE
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 0
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS ia64_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK ia64_hard_regno_mode_ok
 
@@ -4263,6 +4266,30 @@  ia64_hard_regno_rename_ok (int from, int
   return 1;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.
+
+   ??? We say that BImode PR values require two registers.  This allows us to
+   easily store the normal and inverted values.  We use CCImode to indicate
+   a single predicate register.  */
+
+static unsigned int
+ia64_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno == PR_REG (0) && mode == DImode)
+    return 64;
+  if (PR_REGNO_P (regno) && (mode) == BImode)
+    return 2;
+  if ((PR_REGNO_P (regno) || GR_REGNO_P (regno)) && mode == CCImode)
+    return 1;
+  if (FR_REGNO_P (regno) && mode == XFmode)
+    return 1;
+  if (FR_REGNO_P (regno) && mode == RFmode)
+    return 1;
+  if (FR_REGNO_P (regno) && mode == XCmode)
+    return 2;
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/iq2000/iq2000.h	2017-09-11 17:55:39.970250244 +0100
@@ -160,10 +160,6 @@  #define REG_ALLOC_ORDER							\
 }
 
 
-/* How Values Fit in Registers.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 #define AVOID_CCMODE_COPIES
 
Index: gcc/config/lm32/lm32.h
===================================================================
--- gcc/config/lm32/lm32.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/lm32/lm32.h	2017-09-11 17:55:39.970250244 +0100
@@ -163,9 +163,6 @@  #define CALL_USED_REGISTERS \
   0, 0, 0, 0, 0, 0, 0, 0,   \
   0, 0, 1, 0, 1, 0, 1, 1}
 
-#define HARD_REGNO_NREGS(REGNO, MODE)                                   \
-    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 #define AVOID_CCMODE_COPIES
 
 /*----------------------------------*/
Index: gcc/config/m32c/m32c.h
===================================================================
--- gcc/config/m32c/m32c.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m32c/m32c.h	2017-09-11 17:55:39.971250205 +0100
@@ -255,7 +255,6 @@  #define REG_ALLOC_ORDER { \
 
 /* How Values Fit in Registers */
 
-#define HARD_REGNO_NREGS(R,M) m32c_hard_regno_nregs (R, M)
 #define AVOID_CCMODE_COPIES
 
 /* Register Classes */
Index: gcc/config/m32c/m32c-protos.h
===================================================================
--- gcc/config/m32c/m32c-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m32c/m32c-protos.h	2017-09-11 17:55:39.970250244 +0100
@@ -49,7 +49,6 @@  int  m32c_expand_movstr (rtx *);
 void m32c_expand_neg_mulpsi3 (rtx *);
 int  m32c_expand_setmemhi (rtx *);
 bool m32c_matches_constraint_p (rtx, int);
-int  m32c_hard_regno_nregs (int, machine_mode);
 bool m32c_illegal_subreg_p (rtx);
 bool m32c_immd_dbl_mov (rtx *, machine_mode);
 rtx  m32c_incoming_return_addr_rtx (void);
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m32c/m32c.c	2017-09-11 17:55:39.971250205 +0100
@@ -539,11 +539,11 @@  m32c_conditional_register_usage (void)
 
 /* How Values Fit in Registers */
 
-/* Implements HARD_REGNO_NREGS.  This is complicated by the fact that
+/* Implements TARGET_HARD_REGNO_NREGS.  This is complicated by the fact that
    different registers are different sizes from each other, *and* may
    be different sizes in different chip families.  */
-static int
-m32c_hard_regno_nregs_1 (int regno, machine_mode mode)
+static unsigned int
+m32c_hard_regno_nregs_1 (unsigned int regno, machine_mode mode)
 {
   if (regno == FLG_REGNO && mode == CCmode)
     return 1;
@@ -568,10 +568,10 @@  m32c_hard_regno_nregs_1 (int regno, mach
   return 0;
 }
 
-int
-m32c_hard_regno_nregs (int regno, machine_mode mode)
+static unsigned int
+m32c_hard_regno_nregs (unsigned int regno, machine_mode mode)
 {
-  int rv = m32c_hard_regno_nregs_1 (regno, mode);
+  unsigned int rv = m32c_hard_regno_nregs_1 (regno, mode);
   return rv ? rv : 1;
 }
 
@@ -4489,6 +4489,8 @@  #define TARGET_ENCODE_SECTION_INFO m32c_
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS m32c_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK m32c_hard_regno_mode_ok
 #undef TARGET_MODES_TIEABLE_P
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m32r/m32r.h	2017-09-11 17:55:39.971250205 +0100
@@ -389,13 +389,6 @@  #define REG_ALLOC_ORDER				\
 }
 #endif
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
   m32r_hard_regno_rename_ok (OLD_REG, NEW_REG)
 
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m68k/m68k.h	2017-09-11 17:55:39.972250167 +0100
@@ -381,13 +381,6 @@  #define REG_ALLOC_ORDER		\
 }
 
 
-/* On the m68k, ordinary registers hold 32 bits worth;
-   for the 68881 registers, a single register is always enough for
-   anything that can be stored in them at all.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-  ((REGNO) >= 16 ? GET_MODE_NUNITS (MODE)	\
-   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* 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/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/m68k/m68k.c	2017-09-11 17:55:39.971250205 +0100
@@ -187,6 +187,7 @@  static bool m68k_output_addr_const_extra
 static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 static enum flt_eval_method
 m68k_excess_precision (enum excess_precision_type);
+static unsigned int m68k_hard_regno_nregs (unsigned int, machine_mode);
 static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool m68k_modes_tieable_p (machine_mode, machine_mode);
 
@@ -336,6 +337,8 @@  #define TARGET_C_EXCESS_PRECISION m68k_e
 #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS m68k_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK m68k_hard_regno_mode_ok
 
@@ -5178,6 +5181,20 @@  m68k_hard_regno_rename_ok (unsigned int
   return 1;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.
+
+   On the m68k, ordinary registers hold 32 bits worth;
+   for the 68881 registers, a single register is always enough for
+   anything that can be stored in them at all.  */
+
+static unsigned int
+m68k_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno >= 16)
+    return GET_MODE_NUNITS (mode);
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the 68000, we let the cpu
    registers can hold any mode, but restrict the 68881 registers to
    floating-point modes.  */
Index: gcc/config/mcore/mcore.h
===================================================================
--- gcc/config/mcore/mcore.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mcore/mcore.h	2017-09-11 17:55:39.972250167 +0100
@@ -239,15 +239,6 @@  #define REG_ALLOC_ORDER  \
  /* r7  r6  r5  r4  r3  r2  r15 r14 r13 r12 r11 r10  r9  r8  r1  r0  ap  c   fp x19*/ \
   {  7,  6,  5,  4,  3,  2,  15, 14, 13, 12, 11, 10,  9,  8,  1,  0, 16, 17, 18, 19}
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-
-   On the MCore regs are UNITS_PER_WORD bits wide; */
-#define HARD_REGNO_NREGS(REGNO, MODE)  \
-   (((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* Definitions for register eliminations.
 
    We have two registers that can be eliminated on the MCore.  First, the
Index: gcc/config/microblaze/microblaze.h
===================================================================
--- gcc/config/microblaze/microblaze.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/microblaze/microblaze.h	2017-09-11 17:55:39.972250167 +0100
@@ -292,9 +292,6 @@  #define FRP_REG_NUM     35
 #define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
 #define ST_REG_P(REGNO) ((REGNO) == ST_REG)
 
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
-	((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 #define STACK_POINTER_REGNUM   (GP_REG_FIRST + MB_ABI_STACK_POINTER_REGNUM)
 
 #define STACK_POINTER_OFFSET   FIRST_PARM_OFFSET(FNDECL)
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mips/mips.h	2017-09-11 17:55:39.974250090 +0100
@@ -1959,8 +1959,6 @@  #define COPNUM_AS_CHAR_FROM_REGNUM(REGNO
    : COP3_REG_P (REGNO) ? '3' : '?')
 
 
-#define HARD_REGNO_NREGS(REGNO, MODE) mips_hard_regno_nregs (REGNO, MODE)
-
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG)				\
   mips_hard_regno_rename_ok (OLD_REG, NEW_REG)
 
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mips/mips-protos.h	2017-09-11 17:55:39.972250167 +0100
@@ -323,7 +323,6 @@  extern const char *mips_output_division
 extern const char *mips_msa_output_division (const char *, rtx *);
 extern const char *mips_output_probe_stack_range (rtx, rtx);
 extern bool mips_hard_regno_rename_ok (unsigned int, unsigned int);
-extern unsigned int mips_hard_regno_nregs (int, machine_mode);
 extern bool mips_linked_madd_p (rtx_insn *, rtx_insn *);
 extern bool mips_store_data_bypass_p (rtx_insn *, rtx_insn *);
 extern int mips_dspalu_bypass_p (rtx, rtx);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mips/mips.c	2017-09-11 17:55:39.974250090 +0100
@@ -12886,10 +12886,10 @@  mips_hard_regno_call_part_clobbered (uns
   return false;
 }
 
-/* Implement HARD_REGNO_NREGS.  */
+/* Implement TARGET_HARD_REGNO_NREGS.  */
 
-unsigned int
-mips_hard_regno_nregs (int regno, machine_mode mode)
+static unsigned int
+mips_hard_regno_nregs (unsigned int regno, machine_mode mode)
 {
   if (ST_REG_P (regno))
     /* The size of FP status registers is always 4, because they only hold
@@ -22589,6 +22589,8 @@  #define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK mips_hard_regno_scratch_ok
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS mips_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK mips_hard_regno_mode_ok
 
Index: gcc/config/mmix/mmix.h
===================================================================
--- gcc/config/mmix/mmix.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mmix/mmix.h	2017-09-11 17:55:39.974250090 +0100
@@ -380,12 +380,6 @@  #define MMIX_GNU_ABI_REG_ALLOC_ORDER		\
 /* The default one.  */
 #define REG_ALLOC_ORDER MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER
 
-/* Node: Values in Registers */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)            	\
-   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  	\
-    / UNITS_PER_WORD)
-
 /* Node: Leaf Functions */
 /* (empty) */
 
@@ -438,7 +432,7 @@  #define SECONDARY_INPUT_RELOAD_CLASS(CLA
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
  mmix_secondary_reload_class (CLASS, MODE, X, 0)
 
-#define CLASS_MAX_NREGS(CLASS, MODE) HARD_REGNO_NREGS (CLASS, MODE)
+#define CLASS_MAX_NREGS(CLASS, MODE) targetm.hard_regno_nregs (CLASS, MODE)
 
 
 /* Node: Frame Layout */
Index: gcc/config/mn10300/mn10300.h
===================================================================
--- gcc/config/mn10300/mn10300.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/mn10300/mn10300.h	2017-09-11 17:55:39.975250051 +0100
@@ -224,15 +224,6 @@  #define REG_ALLOC_ORDER \
   , 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 50, 51 \
   }
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* 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/moxie/moxie.h
===================================================================
--- gcc/config/moxie/moxie.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/moxie/moxie.h	2017-09-11 17:55:39.975250051 +0100
@@ -176,13 +176,6 @@  #define AVOID_CCMODE_COPIES 1
 #define REGNO_REG_CLASS(R) ((R < MOXIE_PC) ? GENERAL_REGS :		\
                             (R == MOXIE_CC ? CC_REGS : SPECIAL_REGS))
 
-/* A C expression for the number of consecutive hard registers,
-   starting at register number REGNO, required to hold a value of mode
-   MODE.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)			   \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)		   \
-   / UNITS_PER_WORD)
-
 /* The Overall Framework of an Assembler File */
 
 #undef  ASM_SPEC
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/msp430/msp430.h	2017-09-11 17:55:39.975250051 +0100
@@ -332,9 +332,6 @@  #define PROFILE_BEFORE_PROLOGUE 1
 #define FUNCTION_PROFILER(FILE, LABELNO)	\
     fprintf (FILE, "\tcall\t__mcount\n");
 
-#define HARD_REGNO_NREGS(REGNO, MODE)            \
-  msp430_hard_regno_nregs (REGNO, MODE)
-
 /* Exception Handling */
 
 /* R12,R13,R14 - EH data
Index: gcc/config/msp430/msp430-protos.h
===================================================================
--- gcc/config/msp430/msp430-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/msp430/msp430-protos.h	2017-09-11 17:55:39.975250051 +0100
@@ -29,7 +29,6 @@  void	msp430_expand_helper (rtx *operands
 void	msp430_expand_prologue (void);
 const char * msp430x_extendhisi (rtx *);
 void	msp430_fixup_compare_operands (machine_mode, rtx *);
-int	msp430_hard_regno_nregs (int, machine_mode);
 int	msp430_hard_regno_nregs_has_padding (int, machine_mode);
 int	msp430_hard_regno_nregs_with_padding (int, machine_mode);
 bool    msp430_hwmult_enabled (void);
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/msp430/msp430.c	2017-09-11 17:55:39.975250051 +0100
@@ -900,11 +900,11 @@  msp430_ms_bitfield_layout_p (const_tree
 
 /* Register Usage */
 
-/* Implements HARD_REGNO_NREGS.  MSP430X registers can hold a single
-   PSImode value, but not an SImode value.  */
-int
-msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
-			 machine_mode mode)
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
+
+static unsigned int
+msp430_hard_regno_nregs (unsigned int, machine_mode mode)
 {
   if (mode == PSImode && msp430x)
     return 1;
Index: gcc/config/nds32/nds32.h
===================================================================
--- gcc/config/nds32/nds32.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nds32/nds32.h	2017-09-11 17:55:39.976250013 +0100
@@ -596,10 +596,6 @@  #define REG_ALLOC_ORDER           \
    own cost calculations.  */
 #define HONOR_REG_ALLOC_ORDER optimize_size
 
-/* The number of consecutive hard regs needed starting at
-   reg "regno" for holding a value of mode "mode".  */
-#define HARD_REGNO_NREGS(regno, mode) nds32_hard_regno_nregs (regno, mode)
-
 
 /* Register Classes.  */
 
Index: gcc/config/nds32/nds32-protos.h
===================================================================
--- gcc/config/nds32/nds32-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nds32/nds32-protos.h	2017-09-11 17:55:39.975250051 +0100
@@ -26,13 +26,6 @@ 
 extern void nds32_init_expanders (void);
 
 
-/* Register Usage.  */
-
-/* -- How Values Fit in Registers.  */
-
-extern int nds32_hard_regno_nregs (int, machine_mode);
-
-
 /* Register Classes.  */
 
 extern enum reg_class nds32_regno_reg_class (int);
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nds32/nds32.c	2017-09-11 17:55:39.976250013 +0100
@@ -2746,20 +2746,13 @@  nds32_init_expanders (void)
 
 /* -- How Values Fit in Registers.  */
 
-int
-nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
-			machine_mode mode)
-{
-  return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
-}
-
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
 nds32_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
 {
   /* Restrict double-word quantities to even register pairs.  */
-  if (HARD_REGNO_NREGS (regno, mode) == 1
+  if (targetm.hard_regno_nregs (regno, mode) == 1
       || !((regno) & 1))
     return true;
 
Index: gcc/config/nios2/nios2.h
===================================================================
--- gcc/config/nios2/nios2.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nios2/nios2.h	2017-09-11 17:55:39.976250013 +0100
@@ -172,9 +172,6 @@  #define CALL_USED_REGISTERS
 /*  30 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     \
   }
 
-#define HARD_REGNO_NREGS(REGNO, MODE)            \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* Order in which to allocate registers.  Each register must be
    listed once.  This is the default ordering for R1 and non-CDX R2
    code.  For CDX, we overwrite this in ADJUST_REG_ALLOC_ORDER.  */
Index: gcc/config/nvptx/nvptx.h
===================================================================
--- gcc/config/nvptx/nvptx.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nvptx/nvptx.h	2017-09-11 17:55:39.977249974 +0100
@@ -95,8 +95,6 @@  #define FIRST_PSEUDO_REGISTER 16
 #define FIXED_REGISTERS	    { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 #define CALL_USED_REGISTERS { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
 
-#define HARD_REGNO_NREGS(REG, MODE)		\
-  ((void)(REG), (void)(MODE), 1)
 #define CANNOT_CHANGE_MODE_CLASS(M1, M2, CLS)	\
   ((void)(M1), (void)(M2), (void)(CLS), true)
 
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/nvptx/nvptx.c	2017-09-11 17:55:39.977249974 +0100
@@ -5521,6 +5521,14 @@  nvptx_modes_tieable_p (machine_mode, mac
   return false;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+nvptx_hard_regno_nregs (unsigned int, machine_mode)
+{
+  return 1;
+}
+
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE nvptx_option_override
 
@@ -5648,6 +5656,9 @@  #define TARGET_VECTORIZE_PREFERRED_SIMD_
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P nvptx_modes_tieable_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS nvptx_hard_regno_nregs
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-nvptx.h"
Index: gcc/config/pa/pa32-regs.h
===================================================================
--- gcc/config/pa/pa32-regs.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/pa/pa32-regs.h	2017-09-11 17:55:39.978249936 +0100
@@ -166,7 +166,7 @@  #define REG_ALLOC_ORDER \
    point registers are 64 bits wide.  Snake fp regs are treated as
    32 bits wide since the left and right parts are independently
    accessible.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
+#define PA_HARD_REGNO_NREGS(REGNO, MODE)				\
   (FP_REGNO_P (REGNO)							\
    ? (!TARGET_PA_11							\
       ? COMPLEX_MODE_P (MODE) ? 2 : 1					\
Index: gcc/config/pa/pa64-regs.h
===================================================================
--- gcc/config/pa/pa64-regs.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/pa/pa64-regs.h	2017-09-11 17:55:39.978249936 +0100
@@ -137,7 +137,7 @@  #define REG_ALLOC_ORDER \
    WORD_SIZE bits.  Note that SCmode values are placed in a single FPR.
    Thus, any patterns defined to operate on these values would have to
    use the 32-bit addressability of the FPR registers.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
+#define PA_HARD_REGNO_NREGS(REGNO, MODE)				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 /* These are the valid FP modes.  */
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/pa/pa.c	2017-09-11 17:55:39.978249936 +0100
@@ -199,6 +199,7 @@  static unsigned int pa_section_type_flag
 static bool pa_legitimate_address_p (machine_mode, rtx, bool);
 static bool pa_callee_copies (cumulative_args_t, machine_mode,
 			      const_tree, bool);
+static unsigned int pa_hard_regno_nregs (unsigned int, machine_mode);
 static bool pa_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool pa_modes_tieable_p (machine_mode, machine_mode);
 
@@ -409,6 +410,8 @@  #define TARGET_LEGITIMATE_ADDRESS_P pa_l
 #undef TARGET_LRA_P
 #define TARGET_LRA_P hook_bool_void_false
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS pa_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK pa_hard_regno_mode_ok
 #undef TARGET_MODES_TIEABLE_P
@@ -10765,6 +10768,14 @@  pa_callee_copies (cumulative_args_t cum
   return !TARGET_CALLER_COPIES;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+pa_hard_regno_nregs (unsigned int regno ATTRIBUTE_UNUSED, machine_mode mode)
+{
+  return PA_HARD_REGNO_NREGS (regno, mode);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/pdp11/pdp11.h
===================================================================
--- gcc/config/pdp11/pdp11.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/pdp11/pdp11.h	2017-09-11 17:55:39.978249936 +0100
@@ -164,18 +164,6 @@  #define CALL_USED_REGISTERS  \
  0, 0, 0, 0, 0, 0, 1, 1 }
 
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-*/
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-((REGNO <= PC_REGNUM)?							\
-    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)	\
-    :1)
-    
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/pdp11/pdp11.c	2017-09-11 17:55:39.978249936 +0100
@@ -236,6 +236,8 @@  #define TARGET_LEGITIMATE_CONSTANT_P pdp
 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P pdp11_scalar_mode_supported_p
 
+#undef  TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS pdp11_hard_regno_nregs
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK pdp11_hard_regno_mode_ok
 
@@ -1931,6 +1933,16 @@  pdp11_branch_cost ()
   return (TARGET_BRANCH_CHEAP ? 0 : 1);
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+pdp11_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno <= PC_REGNUM)
+    return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+  return 1;
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the pdp, the cpu registers
    can hold any mode other than float (because otherwise we may end up
    being asked to move from CPU to FPU register, which isn't a valid
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-09-11 17:55:39.992249397 +0100
@@ -1263,11 +1263,6 @@  #define VLOGICAL_REGNO_P(N)						\
   (INT_REGNO_P (N) || ALTIVEC_REGNO_P (N)				\
    || (TARGET_VSX && FP_REGNO_P (N)))					\
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
-
 /* When setting up caller-save slots (MODE == VOIDmode) ensure we allocate
    enough space to account for vectors in FP regs.  However, TFmode/TDmode
    should not use VSX instructions to do a caller save. */
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-11 17:55:39.991249436 +0100
@@ -1977,6 +1977,8 @@  #define TARGET_OPTAB_SUPPORTED_P rs6000_
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS rs6000_hard_regno_nregs_hook
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK rs6000_hard_regno_mode_ok
 
@@ -2174,6 +2176,14 @@  rs6000_hard_regno_mode_ok_uncached (int
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+rs6000_hard_regno_nregs_hook (unsigned int regno, machine_mode mode)
+{
+  return rs6000_hard_regno_nregs[mode][regno];
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/riscv/riscv.h
===================================================================
--- gcc/config/riscv/riscv.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/riscv/riscv.h	2017-09-11 17:55:39.994249320 +0100
@@ -292,8 +292,6 @@  #define FP_REG_P(REGNO)  \
 
 #define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
 
-#define HARD_REGNO_NREGS(REGNO, MODE) riscv_hard_regno_nregs (REGNO, MODE)
-
 /* 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-protos.h
===================================================================
--- gcc/config/riscv/riscv-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/riscv/riscv-protos.h	2017-09-11 17:55:39.992249397 +0100
@@ -68,7 +68,6 @@  extern void riscv_expand_prologue (void)
 extern void riscv_expand_epilogue (bool);
 extern bool riscv_can_use_return_insn (void);
 extern rtx riscv_function_value (const_tree, const_tree, machine_mode);
-extern unsigned int riscv_hard_regno_nregs (int, machine_mode);
 
 /* Routines implemented in riscv-c.c.  */
 void riscv_cpu_cpp_builtins (cpp_reader *);
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/riscv/riscv.c	2017-09-11 17:55:39.993249359 +0100
@@ -3519,6 +3519,18 @@  riscv_register_move_cost (machine_mode m
   return SECONDARY_MEMORY_NEEDED (from, to, mode) ? 8 : 2;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+riscv_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (FP_REG_P (regno))
+    return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
+
+  /* All other registers are word-sized.  */
+  return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
@@ -3571,18 +3583,6 @@  riscv_modes_tieable_p (machine_mode mode
 	       && GET_MODE_CLASS (mode2) == MODE_FLOAT));
 }
 
-/* Implement HARD_REGNO_NREGS.  */
-
-unsigned int
-riscv_hard_regno_nregs (int regno, machine_mode mode)
-{
-  if (FP_REG_P (regno))
-    return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
-
-  /* All other registers are word-sized.  */
-  return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
 /* Implement CLASS_MAX_NREGS.  */
 
 static unsigned char
@@ -4104,6 +4104,8 @@  #define TARGET_BUILTIN_DECL riscv_builti
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN riscv_expand_builtin
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS riscv_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK riscv_hard_regno_mode_ok
 
Index: gcc/config/rl78/rl78.h
===================================================================
--- gcc/config/rl78/rl78.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rl78/rl78.h	2017-09-11 17:55:39.996249243 +0100
@@ -407,10 +407,6 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
     fprintf (FILE, "\tbsr\t__mcount\n");
 
 
-#define HARD_REGNO_NREGS(REGNO, MODE)            \
-  rl78_hard_regno_nregs (REGNO, MODE)
-
-
 #define TEXT_SECTION_ASM_OP ".text"
 #define DATA_SECTION_ASM_OP ".data"
 #define BSS_SECTION_ASM_OP ".bss"
Index: gcc/config/rl78/rl78-protos.h
===================================================================
--- gcc/config/rl78/rl78-protos.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rl78/rl78-protos.h	2017-09-11 17:55:39.994249320 +0100
@@ -29,7 +29,6 @@  void		rl78_expand_eh_epilogue (rtx);
 void		rl78_expand_epilogue (void);
 void		rl78_expand_prologue (void);
 int		rl78_far_p (rtx x);
-int		rl78_hard_regno_nregs (int, machine_mode);
 bool		rl78_hl_b_c_addr_p (rtx);
 int		rl78_initial_elimination_offset (int, int);
 bool		rl78_as_legitimate_address (machine_mode, rtx,
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rl78/rl78.c	2017-09-11 17:55:39.995249282 +0100
@@ -449,9 +449,11 @@  rl78_real_insns_ok (void)
   return false;
 }
 
-/* Implements HARD_REGNO_NREGS.  */
-int
-rl78_hard_regno_nregs (int regno, machine_mode mode)
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS rl78_hard_regno_nregs
+
+static unsigned int
+rl78_hard_regno_nregs (unsigned int regno, machine_mode mode)
 {
   int rs = register_sizes[regno];
   if (rs < 1)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rs6000/rs6000.h	2017-09-11 17:55:40.006248859 +0100
@@ -1202,11 +1202,6 @@  #define VLOGICAL_REGNO_P(N)						\
   (INT_REGNO_P (N) || ALTIVEC_REGNO_P (N)				\
    || (TARGET_VSX && FP_REGNO_P (N)))					\
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
-
 /* When setting up caller-save slots (MODE == VOIDmode) ensure we allocate
    enough space to account for vectors in FP regs.  However, TFmode/TDmode
    should not use VSX instructions to do a caller save. */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-11 17:55:40.005248897 +0100
@@ -1967,6 +1967,8 @@  #define TARGET_GET_FUNCTION_VERSIONS_DIS
 #undef TARGET_OPTION_FUNCTION_VERSIONS
 #define TARGET_OPTION_FUNCTION_VERSIONS common_function_versions
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS rs6000_hard_regno_nregs_hook
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK rs6000_hard_regno_mode_ok
 
@@ -2141,6 +2143,14 @@  rs6000_hard_regno_mode_ok_uncached (int
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+rs6000_hard_regno_nregs_hook (unsigned int regno, machine_mode mode)
+{
+  return rs6000_hard_regno_nregs[mode][regno];
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/config/rx/rx.h
===================================================================
--- gcc/config/rx/rx.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rx/rx.h	2017-09-11 17:55:40.007248820 +0100
@@ -331,10 +331,6 @@  #define FUNCTION_PROFILER(FILE, LABELNO)
     fprintf (FILE, "\tbsr\t__mcount\n");
 
 
-#define HARD_REGNO_NREGS(REGNO, MODE)   CLASS_MAX_NREGS (0, MODE)
-
-
-
 #define REGISTER_NAMES						\
   {								\
     "r0",  "r1",  "r2",   "r3",   "r4",   "r5",   "r6",   "r7",	\
Index: gcc/config/rx/rx.c
===================================================================
--- gcc/config/rx/rx.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/rx/rx.c	2017-09-11 17:55:40.007248820 +0100
@@ -3434,6 +3434,14 @@  rx_atomic_sequence::~rx_atomic_sequence
     emit_insn (gen_mvtc (GEN_INT (CTRLREG_PSW), m_prev_psw_reg));
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+rx_hard_regno_nregs (unsigned int, machine_mode mode)
+{
+  return CLASS_MAX_NREGS (0, mode);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
@@ -3606,6 +3614,8 @@  #define TARGET_WARN_FUNC_RETURN 		rx_war
 #undef  TARGET_LRA_P
 #define TARGET_LRA_P 				rx_enable_lra
 
+#undef  TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS			rx_hard_regno_nregs
 #undef  TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK		rx_hard_regno_mode_ok
 
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/s390/s390.h	2017-09-11 17:55:40.011248666 +0100
@@ -469,29 +469,6 @@  #define REG_ALLOC_ORDER							\
      15, 32, 33, 34, 35, 36, 37 }
 
 
-/* Fitting values into registers.  */
-
-/* Integer modes <= word size fit into any GPR.
-   Integer modes > word size fit into successive GPRs, starting with
-   an even-numbered register.
-   SImode and DImode fit into FPRs as well.
-
-   Floating point modes <= word size fit into any FPR or GPR.
-   Floating point modes > word size (i.e. DFmode on 32-bit) fit
-   into any FPR, or an even-odd GPR pair.
-   TFmode fits only into an even-odd FPR pair.
-
-   Complex floating point modes fit either into two FPRs, or into
-   successive GPRs (again starting with an even number).
-   TCmode fits only into two successive even-odd FPR pairs.
-
-   Condition code modes fit only into the CC register.  */
-
-/* Because all registers in a class have the same size HARD_REGNO_NREGS
-   is equivalent to CLASS_MAX_NREGS.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)                           \
-  s390_class_max_nregs (REGNO_REG_CLASS (REGNO), (MODE))
-
 #define HARD_REGNO_RENAME_OK(FROM, TO)          \
   s390_hard_regno_rename_ok ((FROM), (TO))
 
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/s390/s390.c	2017-09-11 17:55:40.011248666 +0100
@@ -496,7 +496,7 @@  #define CONST_OK_FOR_On(x) \
         CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
 
 #define REGNO_PAIR_OK(REGNO, MODE)                               \
-  (HARD_REGNO_NREGS ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
+  (s390_hard_regno_nregs ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
 
 /* That's the read ahead of the dynamic branch prediction unit in
    bytes on a z10 (or higher) CPU.  */
@@ -10383,7 +10383,32 @@  s390_optimize_nonescaping_tx (void)
   return;
 }
 
-/* Implement TARGET_HARD_REGNO_MODE_OK.  */
+/* Implement TARGET_HARD_REGNO_NREGS.  Because all registers in a class
+   have the same size, this is equivalent to CLASS_MAX_NREGS.  */
+
+static unsigned int
+s390_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  return s390_class_max_nregs (REGNO_REG_CLASS (regno), mode);
+}
+
+/* Implement TARGET_HARD_REGNO_MODE_OK.
+
+   Integer modes <= word size fit into any GPR.
+   Integer modes > word size fit into successive GPRs, starting with
+   an even-numbered register.
+   SImode and DImode fit into FPRs as well.
+
+   Floating point modes <= word size fit into any FPR or GPR.
+   Floating point modes > word size (i.e. DFmode on 32-bit) fit
+   into any FPR, or an even-odd GPR pair.
+   TFmode fits only into an even-odd FPR pair.
+
+   Complex floating point modes fit either into two FPRs, or into
+   successive GPRs (again starting with an even number).
+   TCmode fits only into two successive even-odd FPR pairs.
+
+   Condition code modes fit only into the CC register.  */
 
 static bool
 s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
@@ -15977,6 +16002,8 @@  #define TARGET_CANONICALIZE_COMPARISON s
 #undef TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK s390_hard_regno_scratch_ok
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS s390_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK s390_hard_regno_mode_ok
 #undef TARGET_MODES_TIEABLE_P
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/sh/sh.h	2017-09-11 17:55:40.015248512 +0100
@@ -812,17 +812,6 @@  #define CALL_REALLY_USED_REGISTERS
   1,      1,      0,      0,						\
 }
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-
-   On the SH all but the XD regs are UNITS_PER_WORD bits wide.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-   (XD_REGISTER_P (REGNO) \
-    ? ((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD - 1)) / (2*UNITS_PER_WORD)) \
-    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/sh/sh.c	2017-09-11 17:55:40.014248551 +0100
@@ -322,6 +322,7 @@  static bool sh_legitimate_combined_insn
 static bool sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2);
 
 static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+static unsigned int sh_hard_regno_nregs (unsigned int, machine_mode);
 static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool sh_modes_tieable_p (machine_mode, machine_mode);
 
@@ -644,6 +645,8 @@  #define TARGET_ATOMIC_TEST_AND_SET_TRUEV
 #undef TARGET_CANNOT_FORCE_CONST_MEM
 #define TARGET_CANNOT_FORCE_CONST_MEM sh_cannot_force_const_mem_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS sh_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK sh_hard_regno_mode_ok
 
@@ -7954,7 +7957,7 @@  sh_pass_in_reg_p (const CUMULATIVE_ARGS&
 	      + int_size_in_bytes (type))
 	     <= NPARM_REGS (SImode) * UNITS_PER_WORD)
 	  : ((sh_round_reg (cum, mode)
-	      + HARD_REGNO_NREGS (BASE_ARG_REG (mode), mode))
+	      + sh_hard_regno_nregs (BASE_ARG_REG (mode), mode))
 	     <= NPARM_REGS (mode)))
        : sh_round_reg (cum, mode) < NPARM_REGS (mode)));
 }
@@ -10503,6 +10506,17 @@  sh_expand_builtin (tree exp, rtx target,
   return target;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  On the SH all but the XD regs are
+   UNITS_PER_WORD bits wide.  */
+
+static unsigned int
+sh_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (XD_REGISTER_P (regno))
+    return CEIL (GET_MODE_SIZE (mode), 2 * UNITS_PER_WORD);
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.
 
    We can allow any mode in any general register.  The special registers
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/sparc/sparc.h	2017-09-11 17:55:40.019248359 +0100
@@ -745,25 +745,6 @@  #define CALL_REALLY_USED_REGISTERS  \
 				\
   1, 1, 1, 1, 1, 1, 1}
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-
-   On SPARC, ordinary registers hold 32 bits worth;
-   this means both integer and floating point registers.
-   On v9, integer regs hold 64 bits worth; floating point regs hold
-   32 bits worth (this includes the new fp regs as even the odd ones are
-   included in the hard register count).  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-  ((REGNO) == SPARC_GSR_REG ? 1 :					\
-   (TARGET_ARCH64							\
-    ? (SPARC_INT_REG_P (REGNO) || (REGNO) == FRAME_POINTER_REGNUM			\
-       ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD	\
-       : (GET_MODE_SIZE (MODE) + 3) / 4)				\
-    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
-
 /* Due to the ARCH64 discrepancy above we must override this next
    macro too.  */
 #define REGMODE_NATURAL_SIZE(MODE) sparc_regmode_natural_size (MODE)
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/sparc/sparc.c	2017-09-11 17:55:40.018248397 +0100
@@ -676,6 +676,7 @@  static scalar_int_mode sparc_cstore_mode
 static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static unsigned int sparc_min_arithmetic_precision (void);
+static unsigned int sparc_hard_regno_nregs (unsigned int, machine_mode);
 static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool sparc_modes_tieable_p (machine_mode, machine_mode);
 
@@ -905,6 +906,8 @@  #define TARGET_MIN_ARITHMETIC_PRECISION
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS sparc_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK sparc_hard_regno_mode_ok
 
@@ -13149,6 +13152,28 @@  sparc_regmode_natural_size (machine_mode
   return size;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.
+
+   On SPARC, ordinary registers hold 32 bits worth; this means both
+   integer and floating point registers.  On v9, integer regs hold 64
+   bits worth; floating point regs hold 32 bits worth (this includes the
+   new fp regs as even the odd ones are included in the hard register
+   count).  */
+
+static unsigned int
+sparc_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno == SPARC_GSR_REG)
+    return 1;
+  if (TARGET_ARCH64)
+    {
+      if (SPARC_INT_REG_P (regno) || regno == FRAME_POINTER_REGNUM)
+	return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+      return CEIL (GET_MODE_SIZE (mode), 4);
+    }
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.
 
    ??? Because of the funny way we pass parameters we should allow certain
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/spu/spu.h	2017-09-11 17:55:40.021248282 +0100
@@ -171,12 +171,6 @@  #define CALL_USED_REGISTERS {			    \
 }
 
 
-/* Values in Registers */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-    ((GET_MODE_BITSIZE(MODE)+MAX_FIXED_MODE_SIZE-1)/MAX_FIXED_MODE_SIZE)
-
-
 /* Register Classes */
 
 enum reg_class { 
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/spu/spu.c	2017-09-11 17:55:40.020248320 +0100
@@ -281,6 +281,14 @@  spu_option_override (void)
   REAL_MODE_FORMAT (SFmode) = &spu_single_format;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+spu_hard_regno_nregs (unsigned int, machine_mode mode)
+{
+  return CEIL (GET_MODE_BITSIZE (mode), MAX_FIXED_MODE_SIZE);
+}
+
 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
    struct attribute_spec.handler.  */
 
@@ -3870,7 +3878,7 @@  spu_function_arg_advance (cumulative_arg
 	   ? ((int_size_in_bytes (type) + 15) / 16)
 	   : mode == VOIDmode
 	   ? 1
-	   : HARD_REGNO_NREGS (cum, mode));
+	   : spu_hard_regno_nregs (FIRST_ARG_REGNUM, mode));
 }
 
 /* Implement TARGET_FUNCTION_ARG_PADDING.  */
@@ -7382,6 +7390,9 @@  #define TARGET_CAN_USE_DOLOOP_P can_use_
 #undef TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P spu_modes_tieable_p
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS spu_hard_regno_nregs
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-spu.h"
Index: gcc/config/stormy16/stormy16.h
===================================================================
--- gcc/config/stormy16/stormy16.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/stormy16/stormy16.h	2017-09-11 17:55:40.021248282 +0100
@@ -140,12 +140,6 @@  #define CALL_USED_REGISTERS \
 #define REG_ALLOC_ORDER { 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 10, 11, 12, 13, 14, 15, 16 }
 
 
-/* How Values Fit in Registers.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) 				\
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-
 /* Register Classes.  */
 
 enum reg_class
Index: gcc/config/tilegx/tilegx.h
===================================================================
--- gcc/config/tilegx/tilegx.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/tilegx/tilegx.h	2017-09-11 17:55:40.021248282 +0100
@@ -156,9 +156,6 @@  #define REG_ALLOC_ORDER {				\
       66, 67						\
 }
 
-#define HARD_REGNO_NREGS(REGNO, MODE)	\
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/tilepro/tilepro.h	2017-09-11 17:55:40.021248282 +0100
@@ -121,9 +121,6 @@  #define REG_ALLOC_ORDER {				\
       66						\
 }
 
-#define HARD_REGNO_NREGS(REGNO, MODE)	\
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/v850/v850.h	2017-09-11 17:55:40.022248243 +0100
@@ -291,15 +291,6 @@  #define REG_ALLOC_ORDER							\
   34, 35								\
 }
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-
-#define HARD_REGNO_NREGS(REGNO, MODE)   \
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
Index: gcc/config/vax/vax.h
===================================================================
--- gcc/config/vax/vax.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/vax/vax.h	2017-09-11 17:55:40.022248243 +0100
@@ -135,14 +135,6 @@  #define FIXED_REGISTERS {0, 0, 0, 0, 0,
    Aside from that, you can include as many other registers as you like.  */
 #define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.
-   On the VAX, all registers are one word long.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)	\
-  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/visium/visium.h	2017-09-11 17:55:40.024248166 +0100
@@ -556,16 +556,6 @@  #define REG_ALLOC_ORDER \
    50, 51, 52,                             /* flags, arg, frame */ \
    0, 34 }                                 /* r0, f0 */
 
-/* `HARD_REGNO_NREGS (REGNO, MODE)'
-
-   A C expression for the number of consecutive hard registers,
-   starting at register number REGNO, required to hold a value of mode
-   MODE.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-  ((REGNO) == MDB_REGNUM ?                    \
-  ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \
-  : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* `HARD_REGNO_RENAME_OK (OLD_REG, NEW_REG)'
 
    A C expression which is nonzero if hard register NEW_REG can be
@@ -751,18 +741,6 @@  #define PREFERRED_RELOAD_CLASS(X,CLASS)
 #define CANNOT_CHANGE_MODE_CLASS(FROM,TO,CLASS) \
   (CLASS == MDB ? (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) : 0)
 
-/* `CLASS_MAX_NREGS (CLASS, MODE)'
-
-   A C expression for the maximum number of consecutive registers of
-   class CLASS needed to hold a value of mode MODE.
-
-   This is closely related to the macro `HARD_REGNO_NREGS'.  In fact,
-   the value of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be
-   the maximum value of `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO
-   values in the class CLASS.
-
-   This macro helps control the handling of multiple-word values in
-   the reload pass.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)    \
   ((CLASS) == MDB ?                     \
   ((GET_MODE_SIZE (MODE) + 2 * UNITS_PER_WORD - 1) / (2 * UNITS_PER_WORD)) \
Index: gcc/config/visium/visium.c
===================================================================
--- gcc/config/visium/visium.c	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/visium/visium.c	2017-09-11 17:55:40.023248205 +0100
@@ -228,6 +228,8 @@  static void visium_init_libfuncs (void);
 
 static unsigned int visium_reorg (void);
 
+static unsigned int visium_hard_regno_nregs (unsigned int, machine_mode);
+
 static bool visium_hard_regno_mode_ok (unsigned int, machine_mode);
 
 static bool visium_modes_tieable_p (machine_mode, machine_mode);
@@ -343,6 +345,9 @@  #define TARGET_MD_ASM_ADJUST visium_md_a
 #undef TARGET_FLAGS_REGNUM
 #define TARGET_FLAGS_REGNUM FLAGS_REGNUM
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS visium_hard_regno_nregs
+
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK visium_hard_regno_mode_ok
 
@@ -846,6 +851,16 @@  visium_hard_regno_rename_ok (unsigned in
   return 1;
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+visium_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (regno == MDB_REGNUM)
+    return CEIL (GET_MODE_SIZE (mode), 2 * UNITS_PER_WORD);
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.
 
    Modes with sizes which cross from the one register class to the
@@ -863,7 +878,7 @@  visium_hard_regno_mode_ok (unsigned int
     return mode == SFmode || (mode == SImode && TARGET_FPU_IEEE);
 
   return (GET_MODE_CLASS (mode) == MODE_INT
-	  && HARD_REGNO_NREGS (regno, mode) == 1);
+	  && visium_hard_regno_nregs (regno, mode) == 1);
 }
 
 /* Implement TARGET_MODES_TIEABLE_P.  */
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/config/xtensa/xtensa.h	2017-09-11 17:55:40.025248128 +0100
@@ -321,13 +321,6 @@  #define BR_REG_P(REGNO) ((unsigned) ((RE
 #define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
 #define ACC_REG_P(REGNO) ((unsigned) ((REGNO) - ACC_REG_FIRST) < ACC_REG_NUM)
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)					\
-  (FP_REG_P (REGNO) ?							\
-	((GET_MODE_SIZE (MODE) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG) : \
-	((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
 /* 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-09-11 17:55:38.950289484 +0100
+++ gcc/config/xtensa/xtensa.c	2017-09-11 17:55:40.025248128 +0100
@@ -178,6 +178,7 @@  static bool xtensa_member_type_forces_bl
 					   machine_mode mode);
 
 static void xtensa_conditional_register_usage (void);
+static unsigned int xtensa_hard_regno_nregs (unsigned int, machine_mode);
 static bool xtensa_hard_regno_mode_ok (unsigned int, machine_mode);
 static bool xtensa_modes_tieable_p (machine_mode, machine_mode);
 
@@ -308,6 +309,8 @@  #define TARGET_INVALID_WITHIN_DOLOOP xte
 #undef TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE xtensa_conditional_register_usage
 
+#undef TARGET_HARD_REGNO_NREGS
+#define TARGET_HARD_REGNO_NREGS xtensa_hard_regno_nregs
 #undef TARGET_HARD_REGNO_MODE_OK
 #define TARGET_HARD_REGNO_MODE_OK xtensa_hard_regno_mode_ok
 
@@ -2261,6 +2264,16 @@  xtensa_option_override (void)
     }
 }
 
+/* Implement TARGET_HARD_REGNO_NREGS.  */
+
+static unsigned int
+xtensa_hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+  if (FP_REG_P (regno))
+    return CEIL (GET_MODE_SIZE (mode), UNITS_PER_FPREG);
+  return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
+}
+
 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
 
 static bool
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-09-11 17:55:38.950289484 +0100
+++ gcc/system.h	2017-09-11 17:55:40.034247781 +0100
@@ -912,7 +912,8 @@  #define realloc xrealloc
 	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		\
-	MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS
+	MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS	\
+	HARD_REGNO_NREGS
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */