Turn HARD_REGNO_CALL_PART_CLOBBERED into a target hook

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

Commit Message

Richard Sandiford Aug. 28, 2017, 8:39 a.m.
The SVE patches change the size of a machine_mode from a compile-time
constant to a runtime invariant.  However, target-specific code can
continue to treat the modes as constant-sized if the target only has
constant-sized modes.

The main snag with this approach is that target-independent code still
uses macros from the target .h file.  This patch is one of several that
converts a target macro to a hook.

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

Richard


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

gcc/
	* target.def (hard_regno_call_part_clobbered): New hook.
	* doc/tm.texi.in (HARD_REGNO_CALL_PART_CLOBBERED): Replace with...
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): ...this hook.
	* doc/tm.texi: Regenerate.
	* hooks.h (hook_bool_uint_mode_false): Declare.
	* hooks.c (hook_bool_uint_mode_false): New function.
	* regs.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* cselib.c (cselib_process_insn): Use
	targetm.hard_regno_call_part_clobbered instead of
	HARD_REGNO_CALL_PART_CLOBBERED.
	* ira-conflicts.c (ira_build_conflicts): Likewise.
	* ira-costs.c (ira_tune_allocno_costs): Likewise.
	* lra-constraints.c (need_for_call_save_p): Likewise.
	* lra-lives.c: Include target.h.
	(check_pseudos_live_through_calls): Use
	targetm.hard_regno_call_part_clobbered instead of
	HARD_REGNO_CALL_PART_CLOBBERED.
	* regcprop.c: Include target.h.
	(copyprop_hardreg_forward_1): Use
	targetm.hard_regno_call_part_clobbered instead of
	HARD_REGNO_CALL_PART_CLOBBERED.
	* reginfo.c (choose_hard_reg_mode): Likewise.
	* regrename.c (check_new_reg_p): Likewise.
	* reload.c (find_equiv_reg): Likewise.
	* reload1.c (emit_reload_insns): Likewise.
	* sched-deps.c (deps_analyze_insn): Likewise.
	* sel-sched.c (init_regs_for_mode): Likewise.
	(mark_unavailable_hard_regs): Likewise.
	* targhooks.c (default_dwarf_frame_reg_mode): Likewise.
	* config/aarch64/aarch64.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered):
	New function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/avr/avr.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/avr/avr-protos.h (avr_hard_regno_call_part_clobbered):
	Delete.
	* config/avr/avr.c (avr_hard_regno_call_part_clobbered): Make static
	and return a bool.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/i386/i386.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/i386/i386.c (ix86_hard_regno_call_part_clobbered): New
	function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/mips/mips.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/mips/mips.c (mips_hard_regno_call_part_clobbered): New
	function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/powerpcspe/powerpcspe.h (HARD_REGNO_CALL_PART_CLOBBERED):
	Delete.
	* config/powerpcspe/powerpcspe.c
	(rs6000_hard_regno_call_part_clobbered): New function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/rs6000/rs6000.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/rs6000/rs6000.c (rs6000_hard_regno_call_part_clobbered):
	New function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/s390/s390.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* config/s390/s390.c (s390_hard_regno_call_part_clobbered): New
	function.
	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.
	* config/sh/sh.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.
	* system.h (HARD_REGNO_CALL_PART_CLOBBERED): Poison.

Comments

Jeff Law Sept. 4, 2017, 5:48 a.m. | #1
On 08/28/2017 02:39 AM, Richard Sandiford wrote:
> The SVE patches change the size of a machine_mode from a compile-time

> constant to a runtime invariant.  However, target-specific code can

> continue to treat the modes as constant-sized if the target only has

> constant-sized modes.

> 

> The main snag with this approach is that target-independent code still

> uses macros from the target .h file.  This patch is one of several that

> converts a target macro to a hook.

> 

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

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

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

> 

> Richard

> 

> 

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

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

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

> 

> gcc/

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

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

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): ...this hook.

> 	* doc/tm.texi: Regenerate.

> 	* hooks.h (hook_bool_uint_mode_false): Declare.

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

> 	* regs.h (HARD_REGNO_CALL_PART_CLOBBERED): Delete.

> 	* cselib.c (cselib_process_insn): Use

> 	targetm.hard_regno_call_part_clobbered instead of

> 	HARD_REGNO_CALL_PART_CLOBBERED.

> 	* ira-conflicts.c (ira_build_conflicts): Likewise.

> 	* ira-costs.c (ira_tune_allocno_costs): Likewise.

> 	* lra-constraints.c (need_for_call_save_p): Likewise.

> 	* lra-lives.c: Include target.h.

> 	(check_pseudos_live_through_calls): Use

> 	targetm.hard_regno_call_part_clobbered instead of

> 	HARD_REGNO_CALL_PART_CLOBBERED.

> 	* regcprop.c: Include target.h.

> 	(copyprop_hardreg_forward_1): Use

> 	targetm.hard_regno_call_part_clobbered instead of

> 	HARD_REGNO_CALL_PART_CLOBBERED.

> 	* reginfo.c (choose_hard_reg_mode): Likewise.

> 	* regrename.c (check_new_reg_p): Likewise.

> 	* reload.c (find_equiv_reg): Likewise.

> 	* reload1.c (emit_reload_insns): Likewise.

> 	* sched-deps.c (deps_analyze_insn): Likewise.

> 	* sel-sched.c (init_regs_for_mode): Likewise.

> 	(mark_unavailable_hard_regs): Likewise.

> 	* targhooks.c (default_dwarf_frame_reg_mode): Likewise.

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

> 	* config/aarch64/aarch64.c (aarch64_hard_regno_call_part_clobbered):

> 	New function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* config/avr/avr-protos.h (avr_hard_regno_call_part_clobbered):

> 	Delete.

> 	* config/avr/avr.c (avr_hard_regno_call_part_clobbered): Make static

> 	and return a bool.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* config/i386/i386.c (ix86_hard_regno_call_part_clobbered): New

> 	function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* config/mips/mips.c (mips_hard_regno_call_part_clobbered): New

> 	function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

> 	* config/powerpcspe/powerpcspe.h (HARD_REGNO_CALL_PART_CLOBBERED):

> 	Delete.

> 	* config/powerpcspe/powerpcspe.c

> 	(rs6000_hard_regno_call_part_clobbered): New function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* config/rs6000/rs6000.c (rs6000_hard_regno_call_part_clobbered):

> 	New function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* config/s390/s390.c (s390_hard_regno_call_part_clobbered): New

> 	function.

> 	(TARGET_HARD_REGNO_CALL_PART_CLOBBERED): Redefine.

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

> 	* system.h (HARD_REGNO_CALL_PART_CLOBBERED): Poison.

OK.

jeff

Patch

Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-08-28 09:36:09.610827107 +0100
+++ gcc/target.def	2017-08-28 09:36:10.075827140 +0100
@@ -5395,6 +5395,19 @@  The default version of this hook always
  bool, (unsigned int regno),
  default_hard_regno_scratch_ok)
 
+DEFHOOK
+(hard_regno_call_part_clobbered,
+ "This hook should return true if @var{regno} is partly call-saved and\n\
+partly call-clobbered, and if a value of mode @var{mode} would be partly\n\
+clobbered by a call.  For example, if the low 32 bits of @var{regno} are\n\
+preserved across a call but higher bits are clobbered, this hook should\n\
+return true for a 64-bit mode but false for a 32-bit mode.\n\
+\n\
+The default implementation returns false, which is correct\n\
+for targets that don't have partly call-clobbered registers.",
+ bool, (unsigned int regno, machine_mode mode),
+ hook_bool_uint_mode_false)
+
 /* Return the smallest number of different values for which it is best to
    use a jump-table instead of a tree of conditional branches.  */
 DEFHOOK
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-08-28 09:36:09.610827107 +0100
+++ gcc/doc/tm.texi.in	2017-08-28 09:36:10.070827139 +0100
@@ -1698,16 +1698,10 @@  This macro is optional.  If not specifie
 of @code{CALL_USED_REGISTERS}.
 @end defmac
 
-@defmac HARD_REGNO_CALL_PART_CLOBBERED (@var{regno}, @var{mode})
 @cindex call-used register
 @cindex call-clobbered register
 @cindex call-saved register
-A C expression that is nonzero if it is not permissible to store a
-value of mode @var{mode} in hard register number @var{regno} across a
-call without some part of it being clobbered.  For most machines this
-macro need not be defined.  It is only required for machines that do not
-preserve the entire contents of a register across a call.
-@end defmac
+@hook TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 
 @findex fixed_regs
 @findex call_used_regs
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-08-28 09:36:09.610827107 +0100
+++ gcc/doc/tm.texi	2017-08-28 09:36:10.069827139 +0100
@@ -1869,16 +1869,19 @@  This macro is optional.  If not specifie
 of @code{CALL_USED_REGISTERS}.
 @end defmac
 
-@defmac HARD_REGNO_CALL_PART_CLOBBERED (@var{regno}, @var{mode})
 @cindex call-used register
 @cindex call-clobbered register
 @cindex call-saved register
-A C expression that is nonzero if it is not permissible to store a
-value of mode @var{mode} in hard register number @var{regno} across a
-call without some part of it being clobbered.  For most machines this
-macro need not be defined.  It is only required for machines that do not
-preserve the entire contents of a register across a call.
-@end defmac
+@deftypefn {Target Hook} bool TARGET_HARD_REGNO_CALL_PART_CLOBBERED (unsigned int @var{regno}, machine_mode @var{mode})
+This hook should return true if @var{regno} is partly call-saved and
+partly call-clobbered, and if a value of mode @var{mode} would be partly
+clobbered by a call.  For example, if the low 32 bits of @var{regno} are
+preserved across a call but higher bits are clobbered, this hook should
+return true for a 64-bit mode but false for a 32-bit mode.
+
+The default implementation returns false, which is correct
+for targets that don't have partly call-clobbered registers.
+@end deftypefn
 
 @findex fixed_regs
 @findex call_used_regs
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/hooks.h	2017-08-28 09:36:10.070827139 +0100
@@ -38,6 +38,7 @@  extern bool hook_bool_const_rtx_insn_con
 							  const rtx_insn *);
 extern bool hook_bool_mode_uhwi_false (machine_mode,
 				       unsigned HOST_WIDE_INT);
+extern bool hook_bool_uint_mode_false (unsigned int, machine_mode);
 extern bool hook_bool_tree_false (tree);
 extern bool hook_bool_const_tree_false (const_tree);
 extern bool hook_bool_tree_true (tree);
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/hooks.c	2017-08-28 09:36:10.070827139 +0100
@@ -126,6 +126,13 @@  hook_bool_mode_uhwi_false (machine_mode,
   return false;
 }
 
+/* Generic hook that takes (unsigned int, machine_mode) and returns false.  */
+bool
+hook_bool_uint_mode_false (unsigned int, machine_mode)
+{
+  return false;
+}
+
 /* Generic hook that takes (FILE *, const char *) and does nothing.  */
 void
 hook_void_FILEptr_constcharptr (FILE *, const char *)
Index: gcc/regs.h
===================================================================
--- gcc/regs.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/regs.h	2017-08-28 09:36:10.072827140 +0100
@@ -193,12 +193,6 @@  #define HARD_REGNO_CALLER_SAVE_MODE(REGN
   choose_hard_reg_mode (REGNO, NREGS, false)
 #endif
 
-/* Registers that get partially clobbered by a call in a given mode.
-   These must not be call used registers.  */
-#ifndef HARD_REGNO_CALL_PART_CLOBBERED
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
-#endif
-
 /* Target-dependent globals.  */
 struct target_regs {
   /* For each starting hard register, the number of consecutive hard
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/cselib.c	2017-08-28 09:36:10.068827139 +0100
@@ -2660,8 +2660,8 @@  cselib_process_insn (rtx_insn *insn)
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	if (call_used_regs[i]
 	    || (REG_VALUES (i) && REG_VALUES (i)->elt
-		&& HARD_REGNO_CALL_PART_CLOBBERED (i,
-		      GET_MODE (REG_VALUES (i)->elt->val_rtx))))
+		&& (targetm.hard_regno_call_part_clobbered
+		    (i, GET_MODE (REG_VALUES (i)->elt->val_rtx)))))
 	  cselib_invalidate_regno (i, reg_raw_mode[i]);
 
       /* Since it is not clear how cselib is going to be used, be
Index: gcc/ira-conflicts.c
===================================================================
--- gcc/ira-conflicts.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/ira-conflicts.c	2017-08-28 09:36:10.070827139 +0100
@@ -743,6 +743,7 @@  ira_build_conflicts (void)
       for (i = 0; i < n; i++)
 	{
 	  ira_object_t obj = ALLOCNO_OBJECT (a, i);
+	  machine_mode obj_mode = obj->allocno->mode;
 	  rtx allocno_reg = regno_reg_rtx [ALLOCNO_REGNO (a)];
 
 	  if ((! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
@@ -804,8 +805,8 @@  ira_build_conflicts (void)
 		 regs must conflict with them.  */
 	      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 		if (!TEST_HARD_REG_BIT (call_used_reg_set, regno)
-		    && HARD_REGNO_CALL_PART_CLOBBERED (regno,
-						       obj->allocno->mode))
+		    && targetm.hard_regno_call_part_clobbered (regno,
+							       obj_mode))
 		  {
 		    SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), regno);
 		    SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/ira-costs.c	2017-08-28 09:36:10.071827140 +0100
@@ -2341,7 +2341,8 @@  ira_tune_allocno_costs (void)
 						   *crossed_calls_clobber_regs)
 		  && (ira_hard_reg_set_intersection_p (regno, mode,
 						       call_used_reg_set)
-		      || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+		      || targetm.hard_regno_call_part_clobbered (regno,
+								 mode)))
 		cost += (ALLOCNO_CALL_FREQ (a)
 			 * (ira_memory_move_cost[mode][rclass][0]
 			    + ira_memory_move_cost[mode][rclass][1]));
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/lra-constraints.c	2017-08-28 09:36:10.071827140 +0100
@@ -5287,8 +5287,8 @@  need_for_call_save_p (int regno)
 	       ? lra_reg_info[regno].actual_call_used_reg_set
 	       : call_used_reg_set,
 	       PSEUDO_REGNO_MODE (regno), reg_renumber[regno])
-	      || HARD_REGNO_CALL_PART_CLOBBERED (reg_renumber[regno],
-						 PSEUDO_REGNO_MODE (regno))));
+	      || (targetm.hard_regno_call_part_clobbered
+		  (reg_renumber[regno], PSEUDO_REGNO_MODE (regno)))));
 }
 
 /* Global registers occurring in the current EBB.  */
Index: gcc/lra-lives.c
===================================================================
--- gcc/lra-lives.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/lra-lives.c	2017-08-28 09:36:10.072827140 +0100
@@ -42,6 +42,7 @@  Software Foundation; either version 3, o
 #include "cfganal.h"
 #include "sparseset.h"
 #include "lra-int.h"
+#include "target.h"
 
 /* Program points are enumerated by numbers from range
    0..LRA_LIVE_MAX_POINT-1.  There are approximately two times more
@@ -575,7 +576,8 @@  check_pseudos_live_through_calls (int re
 		    last_call_used_reg_set);
 
   for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++)
-    if (HARD_REGNO_CALL_PART_CLOBBERED (hr, PSEUDO_REGNO_MODE (regno)))
+    if (targetm.hard_regno_call_part_clobbered (hr,
+						PSEUDO_REGNO_MODE (regno)))
       SET_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, hr);
   lra_reg_info[regno].call_p = true;
   if (! sparseset_bit_p (pseudos_live_through_setjumps, regno))
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/regcprop.c	2017-08-28 09:36:10.072827140 +0100
@@ -34,6 +34,7 @@ 
 #include "tree-pass.h"
 #include "rtl-iter.h"
 #include "cfgrtl.h"
+#include "target.h"
 
 /* The following code does forward propagation of hard register copies.
    The object is to eliminate as many dependencies as possible, so that
@@ -1049,7 +1050,8 @@  copyprop_hardreg_forward_1 (basic_block
 				  regs_invalidated_by_call);
 	  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
 	    if ((TEST_HARD_REG_BIT (regs_invalidated_by_this_call, regno)
-		 || HARD_REGNO_CALL_PART_CLOBBERED (regno, vd->e[regno].mode))
+		 || (targetm.hard_regno_call_part_clobbered
+		     (regno, vd->e[regno].mode)))
 		&& (regno < set_regno || regno >= set_regno + set_nregs))
 	      kill_value_regno (regno, 1, vd);
 
Index: gcc/reginfo.c
===================================================================
--- gcc/reginfo.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/reginfo.c	2017-08-28 09:36:10.072827140 +0100
@@ -637,7 +637,8 @@  choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
-	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+	&& (!call_saved
+	    || !targetm.hard_regno_call_part_clobbered (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -646,7 +647,8 @@  choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
-	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+	&& (!call_saved
+	    || !targetm.hard_regno_call_part_clobbered (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -655,7 +657,8 @@  choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
-	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+	&& (!call_saved
+	    || !targetm.hard_regno_call_part_clobbered (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -664,7 +667,8 @@  choose_hard_reg_mode (unsigned int regno
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
-	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+	&& (!call_saved
+	    || !targetm.hard_regno_call_part_clobbered (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
@@ -677,7 +681,8 @@  choose_hard_reg_mode (unsigned int regno
       mode = (machine_mode) m;
       if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	  && HARD_REGNO_MODE_OK (regno, mode)
-	  && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+	  && (!call_saved
+	      || !targetm.hard_regno_call_part_clobbered (regno, mode)))
 	return mode;
     }
 
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/regrename.c	2017-08-28 09:36:10.072827140 +0100
@@ -338,9 +338,9 @@  check_new_reg_p (int reg ATTRIBUTE_UNUSE
     if ((! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
 	 && ! DEBUG_INSN_P (tmp->insn))
 	|| (this_head->need_caller_save_reg
-	    && ! (HARD_REGNO_CALL_PART_CLOBBERED
+	    && ! (targetm.hard_regno_call_part_clobbered
 		  (reg, GET_MODE (*tmp->loc)))
-	    && (HARD_REGNO_CALL_PART_CLOBBERED
+	    && (targetm.hard_regno_call_part_clobbered
 		(new_reg, GET_MODE (*tmp->loc)))))
       return false;
 
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/reload.c	2017-08-28 09:36:10.073827140 +0100
@@ -6922,13 +6922,14 @@  find_equiv_reg (rtx goal, rtx_insn *insn
 	  if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
 	    for (i = 0; i < nregs; ++i)
 	      if (call_used_regs[regno + i]
-		  || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
+		  || targetm.hard_regno_call_part_clobbered (regno + i, mode))
 		return 0;
 
 	  if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
 	    for (i = 0; i < valuenregs; ++i)
 	      if (call_used_regs[valueno + i]
-		  || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
+		  || targetm.hard_regno_call_part_clobbered (valueno + i,
+							     mode))
 		return 0;
 	}
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/reload1.c	2017-08-28 09:36:10.074827140 +0100
@@ -8276,7 +8276,8 @@  emit_reload_insns (struct insn_chain *ch
 			   : out_regno + k);
 		      reg_reloaded_insn[regno + k] = insn;
 		      SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
-		      if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+		      if (targetm.hard_regno_call_part_clobbered (regno + k,
+								  mode))
 			SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
 					  regno + k);
 		      else
@@ -8355,7 +8356,8 @@  emit_reload_insns (struct insn_chain *ch
 			   : in_regno + k);
 		      reg_reloaded_insn[regno + k] = insn;
 		      SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
-		      if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+		      if (targetm.hard_regno_call_part_clobbered (regno + k,
+								  mode))
 			SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
 					  regno + k);
 		      else
@@ -8469,8 +8471,8 @@  emit_reload_insns (struct insn_chain *ch
 		      reg_reloaded_insn[src_regno + k] = store_insn;
 		      CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + k);
 		      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + k);
-		      if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + k,
-							  mode))
+		      if (targetm.hard_regno_call_part_clobbered
+			  (src_regno + k, mode))
 			SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
 					  src_regno + k);
 		      else
Index: gcc/sched-deps.c
===================================================================
--- gcc/sched-deps.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/sched-deps.c	2017-08-28 09:36:10.074827140 +0100
@@ -3706,7 +3706,8 @@  deps_analyze_insn (struct deps_desc *dep
              Since we only have a choice between 'might be clobbered'
              and 'definitely not clobbered', we must include all
              partly call-clobbered registers here.  */
-            else if (HARD_REGNO_CALL_PART_CLOBBERED (i, reg_raw_mode[i])
+	    else if (targetm.hard_regno_call_part_clobbered (i,
+							     reg_raw_mode[i])
                      || TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
               SET_REGNO_REG_SET (reg_pending_clobbers, i);
           /* We don't know what set of fixed registers might be used
Index: gcc/sel-sched.c
===================================================================
--- gcc/sel-sched.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/sel-sched.c	2017-08-28 09:36:10.075827140 +0100
@@ -1102,7 +1102,7 @@  init_regs_for_mode (machine_mode mode)
       if (i >= 0)
         continue;
 
-      if (HARD_REGNO_CALL_PART_CLOBBERED (cur_reg, mode))
+      if (targetm.hard_regno_call_part_clobbered (cur_reg, mode))
         SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode],
                           cur_reg);
 
@@ -1251,7 +1251,7 @@  mark_unavailable_hard_regs (def_t def, s
 
   /* Exclude registers that are partially call clobbered.  */
   if (def->crosses_call
-      && ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+      && !targetm.hard_regno_call_part_clobbered (regno, mode))
     AND_COMPL_HARD_REG_SET (reg_rename_p->available_for_renaming,
                             sel_hrd.regs_for_call_clobbered[mode]);
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/targhooks.c	2017-08-28 09:36:10.076827140 +0100
@@ -1736,7 +1736,7 @@  default_dwarf_frame_reg_mode (int regno)
 {
   machine_mode save_mode = reg_raw_mode[regno];
 
-  if (HARD_REGNO_CALL_PART_CLOBBERED (regno, save_mode))
+  if (targetm.hard_regno_call_part_clobbered (regno, save_mode))
     save_mode = choose_hard_reg_mode (regno, 1, true);
   return save_mode;
 }
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/aarch64/aarch64.h	2017-08-28 09:36:10.053827138 +0100
@@ -888,12 +888,6 @@  #define SHIFT_COUNT_TRUNCATED (!TARGET_S
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
 
-/* Callee only saves lower 64-bits of a 128-bit register.  Tell the
-   compiler the callee clobbers the top 64-bits when restoring the
-   bottom 64-bits.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
-		(FP_REGNUM_P (REGNO) && GET_MODE_SIZE (MODE) > 8)
-
 #undef SWITCHABLE_TARGET
 #define SWITCHABLE_TARGET 1
 
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/aarch64/aarch64.c	2017-08-28 09:36:10.053827138 +0100
@@ -1115,6 +1115,16 @@  aarch64_hard_regno_mode_ok (unsigned reg
   return 0;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
+   the lower 64 bits of a 128-bit register.  Tell the compiler the callee
+   clobbers the top 64 bits when restoring the bottom 64 bits.  */
+
+static bool
+aarch64_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  return FP_REGNUM_P (regno) && GET_MODE_SIZE (mode) > 8;
+}
+
 /* Implement HARD_REGNO_CALLER_SAVE_MODE.  */
 machine_mode
 aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs,
@@ -15644,6 +15654,10 @@  #define TARGET_OMIT_STRUCT_RETURN_REG tr
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  aarch64_hard_regno_call_part_clobbered
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr.h	2017-08-28 09:36:10.054827138 +0100
@@ -285,9 +285,6 @@  #define REGNO_MODE_CODE_OK_FOR_BASE_P(nu
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)     \
-  avr_hard_regno_call_part_clobbered (REGNO, MODE)
-
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 #define STACK_PUSH_CODE POST_DEC
Index: gcc/config/avr/avr-protos.h
===================================================================
--- gcc/config/avr/avr-protos.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr-protos.h	2017-08-28 09:36:10.053827138 +0100
@@ -46,7 +46,6 @@  extern void avr_init_cumulative_args (CU
 #endif /* TREE_CODE */
 
 #ifdef RTX_CODE
-extern int avr_hard_regno_call_part_clobbered (unsigned, machine_mode);
 extern const char *output_movqi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movhi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movsisf (rtx_insn *insn, rtx operands[], int *l);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/avr/avr.c	2017-08-28 09:36:10.054827138 +0100
@@ -12186,9 +12186,9 @@  avr_hard_regno_mode_ok (int regno, machi
 }
 
 
-/* Implement `HARD_REGNO_CALL_PART_CLOBBERED'.  */
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
 
-int
+static bool
 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
 {
   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
@@ -14693,6 +14693,10 @@  #define TARGET_CONDITIONAL_REGISTER_USAG
 
 #undef  TARGET_HARD_REGNO_SCRATCH_OK
 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
+#undef  TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  avr_hard_regno_call_part_clobbered
+
 #undef  TARGET_CASE_VALUES_THRESHOLD
 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
 
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/i386/i386.h	2017-08-28 09:36:10.059827139 +0100
@@ -1214,12 +1214,6 @@  #define HARD_REGNO_CALLER_SAVE_MODE(REGN
 			   || MASK_REGNO_P (REGNO)) ? SImode		\
    : (MODE))
 
-/* The only ABI that saves SSE registers across calls is Win64 (thus no
-   need to check the current ABI here), and with AVX enabled Win64 only
-   guarantees that the low 16 bytes are saved.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)             \
-  (SSE_REGNO_P (REGNO) && GET_MODE_SIZE (MODE) > 16)
-
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/i386/i386.c	2017-08-28 09:36:10.058827139 +0100
@@ -41397,6 +41397,17 @@  ix86_hard_regno_mode_ok (int regno, mach
   return false;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The only ABI that
+   saves SSE registers across calls is Win64 (thus no need to check the
+   current ABI here), and with AVX enabled Win64 only guarantees that
+   the low 16 bytes are saved.  */
+
+static bool
+ix86_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16;
+}
+
 /* A subroutine of ix86_modes_tieable_p.  Return true if MODE is a
    tieable integer mode.  */
 
@@ -53239,6 +53250,10 @@  #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_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  ix86_hard_regno_call_part_clobbered
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/mips/mips.h	2017-08-28 09:36:10.060827139 +0100
@@ -1971,14 +1971,6 @@  #define HARD_REGNO_RENAME_OK(OLD_REG, NE
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   mips_hard_regno_caller_save_mode (REGNO, NREGS, MODE)
 
-/* Odd-numbered single-precision registers are not considered callee-saved
-   for o32 FPXX as they will be clobbered when run on an FR=1 FPU.
-   MSA vector registers with MODE > 64 bits are part clobbered too.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)			\
-  ((TARGET_FLOATXX && hard_regno_nregs[REGNO][MODE] == 1		\
-   && FP_REG_P (REGNO) && ((REGNO) & 1))				\
-   || (ISA_HAS_MSA && FP_REG_P (REGNO) && GET_MODE_SIZE (MODE) > 8))
-
 #define MODES_TIEABLE_P mips_modes_tieable_p
 
 /* Register to use for pushing function arguments.  */
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/mips/mips.c	2017-08-28 09:36:10.060827139 +0100
@@ -12857,6 +12857,26 @@  mips_hard_regno_scratch_ok (unsigned int
   return true;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  Odd-numbered
+   single-precision registers are not considered callee-saved for o32
+   FPXX as they will be clobbered when run on an FR=1 FPU.  MSA vector
+   registers with MODE > 64 bits are part clobbered too.  */
+
+static bool
+mips_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_FLOATXX
+      && hard_regno_nregs[regno][mode] == 1
+      && FP_REG_P (regno)
+      && (regno & 1) != 0)
+    return true;
+
+  if (ISA_HAS_MSA && FP_REG_P (regno) && GET_MODE_SIZE (mode) > 8)
+    return true;
+
+  return false;
+}
+
 /* Implement HARD_REGNO_NREGS.  */
 
 unsigned int
@@ -22557,6 +22577,10 @@  #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_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  mips_hard_regno_call_part_clobbered
+
 /* The architecture reserves bit 0 for MIPS16 so use bit 1 for descriptors.  */
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-08-28 09:36:10.064827139 +0100
@@ -1302,13 +1302,6 @@  #define HARD_REGNO_CALLER_SAVE_MODE(REGN
    ? DImode								\
    : choose_hard_reg_mode ((REGNO), (NREGS), false))
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)			\
-  (((TARGET_32BIT && TARGET_POWERPC64					\
-     && (GET_MODE_SIZE (MODE) > 4)					\
-     && INT_REGNO_P (REGNO)) ? 1 : 0)					\
-   || (TARGET_VSX && FP_REGNO_P (REGNO)					\
-       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
-
 #define VSX_VECTOR_MODE(MODE)		\
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-08-28 09:36:10.063827139 +0100
@@ -1972,6 +1972,10 @@  #define TARGET_OPTAB_SUPPORTED_P rs6000_
 
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
+
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  rs6000_hard_regno_call_part_clobbered
 
 
 /* Processor table.  */
@@ -2157,6 +2161,26 @@  rs6000_hard_regno_mode_ok (int regno, ma
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
+
+static bool
+rs6000_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_32BIT
+      && TARGET_POWERPC64
+      && GET_MODE_SIZE (mode) > 4
+      && INT_REGNO_P (regno))
+    return true;
+
+  if (TARGET_VSX
+      && FP_REGNO_P (regno)
+      && GET_MODE_SIZE (mode) > 8
+      && !FLOAT128_2REG_P (mode))
+    return true;
+
+  return false;
+}
+
 /* Print interesting facts about registers.  */
 static void
 rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/rs6000/rs6000.h	2017-08-28 09:36:10.067827139 +0100
@@ -1240,13 +1240,6 @@  #define HARD_REGNO_CALLER_SAVE_MODE(REGN
    ? DImode								\
    : choose_hard_reg_mode ((REGNO), (NREGS), false))
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)			\
-  (((TARGET_32BIT && TARGET_POWERPC64					\
-     && (GET_MODE_SIZE (MODE) > 4)					\
-     && INT_REGNO_P (REGNO)) ? 1 : 0)					\
-   || (TARGET_VSX && FP_REGNO_P (REGNO)					\
-       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
-
 #define VSX_VECTOR_MODE(MODE)		\
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/rs6000/rs6000.c	2017-08-28 09:36:10.066827139 +0100
@@ -1963,6 +1963,9 @@  #define TARGET_GET_FUNCTION_VERSIONS_DIS
 #undef TARGET_OPTION_FUNCTION_VERSIONS
 #define TARGET_OPTION_FUNCTION_VERSIONS common_function_versions
 
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  rs6000_hard_regno_call_part_clobbered
 
 
 /* Processor table.  */
@@ -2125,6 +2128,26 @@  rs6000_hard_regno_mode_ok (int regno, ma
   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
+
+static bool
+rs6000_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (TARGET_32BIT
+      && TARGET_POWERPC64
+      && GET_MODE_SIZE (mode) > 4
+      && INT_REGNO_P (regno))
+    return true;
+
+  if (TARGET_VSX
+      && FP_REGNO_P (regno)
+      && GET_MODE_SIZE (mode) > 8
+      && !FLOAT128_2REG_P (mode))
+    return true;
+
+  return false;
+}
+
 /* Print interesting facts about registers.  */
 static void
 rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/s390/s390.h	2017-08-28 09:36:10.068827139 +0100
@@ -509,19 +509,6 @@  #define MODES_TIEABLE_P(MODE1, MODE2)		\
    (((MODE1) == SFmode || (MODE1) == DFmode)	\
    == ((MODE2) == SFmode || (MODE2) == DFmode))
 
-/* When generating code that runs in z/Architecture mode,
-   but conforms to the 31-bit ABI, GPRs can hold 8 bytes;
-   the ABI guarantees only that the lower 4 bytes are
-   saved across calls, however.  */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)			\
-  ((!TARGET_64BIT && TARGET_ZARCH					\
-    && GET_MODE_SIZE (MODE) > 4						\
-    && (((REGNO) >= 6 && (REGNO) <= 15) || (REGNO) == 32))		\
-   || (TARGET_VX							\
-       && GET_MODE_SIZE (MODE) > 8					\
-       && (((TARGET_64BIT && (REGNO) >= 24 && (REGNO) <= 31))		\
-	   || (!TARGET_64BIT && ((REGNO) == 18 || (REGNO) == 19)))))
-
 /* Maximum number of registers to represent a value of mode MODE
    in a register of class CLASS.  */
 #define CLASS_MAX_NREGS(CLASS, MODE)   					\
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/s390/s390.c	2017-08-28 09:36:10.068827139 +0100
@@ -10476,6 +10476,29 @@  s390_hard_regno_scratch_ok (unsigned int
   return true;
 }
 
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  When generating
+   code that runs in z/Architecture mode, but conforms to the 31-bit
+   ABI, GPRs can hold 8 bytes; the ABI guarantees only that the lower 4
+   bytes are saved across calls, however.  */
+
+static bool
+s390_hard_regno_call_part_clobbered (unsigned int regno, machine_mode mode)
+{
+  if (!TARGET_64BIT
+      && TARGET_ZARCH
+      && GET_MODE_SIZE (mode) > 4
+      && ((regno >= 6 && regno <= 15) || regno == 32))
+    return true;
+
+  if (TARGET_VX
+      && GET_MODE_SIZE (mode) > 8
+      && (((TARGET_64BIT && regno >= 24 && regno <= 31))
+	  || (!TARGET_64BIT && (regno == 18 || regno == 19))))
+    return true;
+
+  return false;
+}
+
 /* Maximum number of registers to represent a value of mode MODE
    in a register of class RCLASS.  */
 
@@ -15877,6 +15900,10 @@  #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_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+  s390_hard_regno_call_part_clobbered
+
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE s390_attribute_table
 
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/config/sh/sh.h	2017-08-28 09:36:10.068827139 +0100
@@ -811,8 +811,6 @@  #define CALL_REALLY_USED_REGISTERS
   1,      1,      0,      0,						\
 }
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO,MODE) (false)
-
 /* 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
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-08-28 09:36:09.610827107 +0100
+++ gcc/system.h	2017-08-28 09:36:10.075827140 +0100
@@ -904,7 +904,8 @@  #define realloc xrealloc
 	ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE		\
 	LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE	\
 	CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P		\
-	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD
+	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD			\
+	HARD_REGNO_CALL_PART_CLOBBERED
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */