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.  */
