Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-12 14:29:25.265529315 +0100
+++ gcc/target.def	2017-09-12 19:42:13.226875090 +0100
@@ -5265,6 +5265,30 @@ forwarding logic, you can set @code{sri-
   secondary_reload_info *sri),
  default_secondary_reload)
 
+DEFHOOK
+(secondary_memory_needed_mode,
+ "If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory\n\
+when moving between two particular registers of mode @var{mode},\n\
+this hook specifies the mode that the memory should have.\n\
+\n\
+The default depends on @code{TARGET_LRA_P}.  Without LRA, the default\n\
+is to use a word-sized mode for integral modes that are smaller than a\n\
+a word.  This is right thing to do on most machines because it ensures\n\
+that all bits of the register are copied and prevents accesses to the\n\
+registers in a narrower mode, which some machines prohibit for\n\
+floating-point registers.\n\
+\n\
+However, this default behavior is not correct on some machines, such as\n\
+the DEC Alpha, that store short integers in floating-point registers\n\
+differently than in integer registers.  On those machines, the default\n\
+widening will not work correctly and you must define this hook to\n\
+suppress that widening in some cases.  See the file @file{alpha.c} for\n\
+details.\n\
+\n\
+With LRA, the default is to use @var{mode} unmodified.",
+ machine_mode, (machine_mode mode),
+ default_secondary_memory_needed_mode)
+
 /* Given an rtx X being reloaded into a reg required to be in class CLASS,
    return the class of reg to actually use.  */
 DEFHOOK
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-12 14:29:25.265529315 +0100
+++ gcc/targhooks.c	2017-09-12 19:42:13.226875090 +0100
@@ -1129,6 +1129,18 @@ default_secondary_reload (bool in_p ATTR
   return rclass;
 }
 
+/* The default implementation of TARGET_SECONDARY_MEMORY_NEEDED_MODE.  */
+
+machine_mode
+default_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (!targetm.lra_p ()
+      && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+      && INTEGRAL_MODE_P (mode))
+    return mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* By default, if flag_pic is true, then neither local nor global relocs
    should be placed in readonly memory.  */
 
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-09-12 14:29:25.265529315 +0100
+++ gcc/targhooks.h	2017-09-12 19:42:13.226875090 +0100
@@ -159,6 +159,7 @@ extern bool default_different_addr_displ
 extern reg_class_t default_secondary_reload (bool, rtx, reg_class_t,
 					     machine_mode,
 					     secondary_reload_info *);
+extern machine_mode default_secondary_memory_needed_mode (machine_mode);
 extern void default_target_option_override (void);
 extern void hook_void_bitmap (bitmap);
 extern int default_reloc_rw_mask (void);
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-09-12 14:29:25.263529402 +0100
+++ gcc/doc/tm.texi.in	2017-09-12 19:42:13.224976512 +0100
@@ -2324,29 +2324,7 @@ Do not define this macro if you do not d
 @code{SECONDARY_MEMORY_NEEDED}.
 @end defmac
 
-@defmac SECONDARY_MEMORY_NEEDED_MODE (@var{mode})
-When the compiler needs a secondary memory location to copy between two
-registers of mode @var{mode}, it normally allocates sufficient memory to
-hold a quantity of @code{BITS_PER_WORD} bits and performs the store and
-load operations in a mode that many bits wide and whose class is the
-same as that of @var{mode}.
-
-This is right thing to do on most machines because it ensures that all
-bits of the register are copied and prevents accesses to the registers
-in a narrower mode, which some machines prohibit for floating-point
-registers.
-
-However, this default behavior is not correct on some machines, such as
-the DEC Alpha, that store short integers in floating-point registers
-differently than in integer registers.  On those machines, the default
-widening will not work correctly and you must define this macro to
-suppress that widening in some cases.  See the file @file{alpha.h} for
-details.
-
-Do not define this macro if you do not define
-@code{SECONDARY_MEMORY_NEEDED} or if widening @var{mode} to a mode that
-is @code{BITS_PER_WORD} bits wide is correct for your machine.
-@end defmac
+@hook TARGET_SECONDARY_MEMORY_NEEDED_MODE
 
 @hook TARGET_CLASS_LIKELY_SPILLED_P
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-12 14:29:25.263529402 +0100
+++ gcc/doc/tm.texi	2017-09-12 19:42:13.224976512 +0100
@@ -2747,29 +2747,27 @@ Do not define this macro if you do not d
 @code{SECONDARY_MEMORY_NEEDED}.
 @end defmac
 
-@defmac SECONDARY_MEMORY_NEEDED_MODE (@var{mode})
-When the compiler needs a secondary memory location to copy between two
-registers of mode @var{mode}, it normally allocates sufficient memory to
-hold a quantity of @code{BITS_PER_WORD} bits and performs the store and
-load operations in a mode that many bits wide and whose class is the
-same as that of @var{mode}.
+@deftypefn {Target Hook} machine_mode TARGET_SECONDARY_MEMORY_NEEDED_MODE (machine_mode @var{mode})
+If @code{SECONDARY_MEMORY_NEEDED} tells the compiler to use memory
+when moving between two particular registers of mode @var{mode},
+this hook specifies the mode that the memory should have.
 
-This is right thing to do on most machines because it ensures that all
-bits of the register are copied and prevents accesses to the registers
-in a narrower mode, which some machines prohibit for floating-point
-registers.
+The default depends on @code{TARGET_LRA_P}.  Without LRA, the default
+is to use a word-sized mode for integral modes that are smaller than a
+a word.  This is right thing to do on most machines because it ensures
+that all bits of the register are copied and prevents accesses to the
+registers in a narrower mode, which some machines prohibit for
+floating-point registers.
 
 However, this default behavior is not correct on some machines, such as
 the DEC Alpha, that store short integers in floating-point registers
 differently than in integer registers.  On those machines, the default
-widening will not work correctly and you must define this macro to
-suppress that widening in some cases.  See the file @file{alpha.h} for
+widening will not work correctly and you must define this hook to
+suppress that widening in some cases.  See the file @file{alpha.c} for
 details.
 
-Do not define this macro if you do not define
-@code{SECONDARY_MEMORY_NEEDED} or if widening @var{mode} to a mode that
-is @code{BITS_PER_WORD} bits wide is correct for your machine.
-@end defmac
+With LRA, the default is to use @var{mode} unmodified.
+@end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_CLASS_LIKELY_SPILLED_P (reg_class_t @var{rclass})
 A target hook which returns @code{true} if pseudos that have been assigned
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	2017-09-12 14:28:56.396825056 +0100
+++ gcc/lra-constraints.c	2017-09-12 19:42:13.225925801 +0100
@@ -1203,11 +1203,9 @@ check_and_process_move (bool *change_p,
     return false;
 #ifdef SECONDARY_MEMORY_NEEDED
   if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
       && ((sclass != NO_REGS && dclass != NO_REGS)
-	  || GET_MODE (src) != SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (src)))
-#endif
-      )
+	  || (GET_MODE (src)
+	      != targetm.secondary_memory_needed_mode (GET_MODE (src)))))
     {
       *sec_mem_p = true;
       return false;
@@ -3940,11 +3938,7 @@ curr_insn_transform (bool check_only_p)
 		  && curr_static_id->operand[in].type == OP_IN);
       rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest;
       rld_mode = GET_MODE (rld);
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
-      sec_mode = SECONDARY_MEMORY_NEEDED_MODE (rld_mode);
-#else
-      sec_mode = rld_mode;
-#endif
+      sec_mode = targetm.secondary_memory_needed_mode (rld_mode);
       new_reg = lra_create_new_reg (sec_mode, NULL_RTX,
 				    NO_REGS, "secondary");
       /* If the mode is changed, it should be wider.  */
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2017-09-12 14:28:56.398824964 +0100
+++ gcc/reload.c	2017-09-12 19:42:13.225925801 +0100
@@ -574,13 +574,7 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSE
      locations do not support short load and stores from all registers
      (e.g., FP registers).  */
 
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
-  mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
-#else
-  if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
-    mode = mode_for_size (BITS_PER_WORD,
-			  GET_MODE_CLASS (mode), 0).require ();
-#endif
+  mode = targetm.secondary_memory_needed_mode (mode);
 
   /* If we already have made a MEM for this operand in MODE, return it.  */
   if (secondary_memlocs_elim[(int) mode][opnum] != 0)
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-09-12 14:29:25.224531114 +0100
+++ gcc/config/alpha/alpha.h	2017-09-12 19:42:13.211686464 +0100
@@ -486,16 +486,6 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,C
  (! TARGET_FIX && (((CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS) \
                    || ((CLASS2) == FLOAT_REGS && (CLASS1) != FLOAT_REGS)))
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  If MODE is floating-point, use it.  Otherwise,
-   widen to a word like the default.  This is needed because we always
-   store integers in FP registers in quadword format.  This whole
-   area is very tricky! */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE)		\
-   : GET_MODE_SIZE (MODE) >= 4 ? (MODE)			\
-   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require ())
-
 /* Return the class of registers that cannot change mode from FROM to TO.  */
 
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)		\
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2017-09-11 17:10:56.054131183 +0100
+++ gcc/config/alpha/alpha.c	2017-09-12 19:42:13.211686464 +0100
@@ -1688,6 +1688,21 @@ alpha_secondary_reload (bool in_p, rtx x
 
   return NO_REGS;
 }
+
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.  If MODE is
+   floating-point, use it.  Otherwise, widen to a word like the default.
+   This is needed because we always store integers in FP registers in
+   quadword format.  This whole area is very tricky!  */
+
+static machine_mode
+alpha_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return mode;
+  if (GET_MODE_SIZE (mode) >= 4)
+    return mode;
+  return mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0).require ();
+}
 
 /* Given SEQ, which is an INSN list, look for any MEMs in either
    a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and
@@ -10062,6 +10077,8 @@ #define TARGET_INSTANTIATE_DECLS alpha_i
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD alpha_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE alpha_secondary_memory_needed_mode
 
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-09-12 14:29:25.236530587 +0100
+++ gcc/config/i386/i386.h	2017-09-12 19:42:13.215483620 +0100
@@ -1524,14 +1524,6 @@ #define BASE_REG_CLASS GENERAL_REGS
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
   ix86_secondary_memory_needed ((CLASS1), (CLASS2), (MODE), 1)
 
-/* Get_secondary_mem widens integral modes to BITS_PER_WORD.
-   There is no need to emit full 64 bit move on 64 bit targets
-   for integral modes that can be moved using 32 bit move.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
-  (GET_MODE_BITSIZE (MODE) < 32 && INTEGRAL_MODE_P (MODE)	\
-   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
-   : MODE)
-
 /* Return a class of registers that cannot change FROM mode to TO mode.  */
 
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-12 14:29:25.236530587 +0100
+++ gcc/config/i386/i386.c	2017-09-12 19:42:13.215483620 +0100
@@ -41162,6 +41162,20 @@ ix86_secondary_memory_needed (enum reg_c
   return inline_secondary_memory_needed (class1, class2, mode, strict);
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens integral modes to BITS_PER_WORD.
+   There is no need to emit full 64 bit move on 64 bit targets
+   for integral modes that can be moved using 32 bit move.  */
+
+static machine_mode
+ix86_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_BITSIZE (mode) < 32 && INTEGRAL_MODE_P (mode))
+    return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* Implement the TARGET_CLASS_MAX_NREGS hook.
 
    On the 80386, this is the size of MODE in words,
@@ -53206,6 +53220,8 @@ #define TARGET_INSTANTIATE_DECLS ix86_in
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD ix86_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE ix86_secondary_memory_needed_mode
 
 #undef TARGET_CLASS_MAX_NREGS
 #define TARGET_CLASS_MAX_NREGS ix86_class_max_nregs
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-09-12 14:29:25.250529973 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-09-12 19:42:13.219280777 +0100
@@ -1611,13 +1611,6 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,C
 #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
   rs6000_secondary_memory_needed_rtx (MODE)
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  For cpus that cannot load/store SDmode values
-   from the 64-bit FP registers without using a full 64-bit
-   load/store, we need a wider mode.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  rs6000_secondary_memory_needed_mode (MODE)
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
Index: gcc/config/powerpcspe/powerpcspe-protos.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe-protos.h	2017-09-04 11:50:24.553468246 +0100
+++ gcc/config/powerpcspe/powerpcspe-protos.h	2017-09-12 19:42:13.216432909 +0100
@@ -154,7 +154,6 @@ extern void rs6000_emit_le_vsx_move (rtx
 extern bool valid_sf_si_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-12 14:29:25.250529973 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-12 19:42:13.218331488 +0100
@@ -1897,6 +1897,8 @@ #define TARGET_INSTANTIATE_DECLS rs6000_
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -21811,10 +21813,9 @@ rs6000_secondary_memory_needed_rtx (mach
   return ret;
 }
 
-/* Return the mode to be used for memory when a secondary memory
-   location is needed.  For SDmode values we need to use DDmode, in
-   all other cases we can use the same mode.  */
-machine_mode
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.  For SDmode values we
+   need to use DDmode, in all other cases we can use the same mode.  */
+static machine_mode
 rs6000_secondary_memory_needed_mode (machine_mode mode)
 {
   if (lra_in_progress && mode == SDmode)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-09-12 14:29:25.254529797 +0100
+++ gcc/config/rs6000/rs6000.h	2017-09-12 19:42:13.221179355 +0100
@@ -1514,13 +1514,6 @@ #define SECONDARY_RELOAD_CLASS(CLASS,MOD
 #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE)			\
   rs6000_secondary_memory_needed_ptr (CLASS1, CLASS2, MODE)
 
-/* Specify the mode to be used for memory when a secondary memory
-   location is needed.  For cpus that cannot load/store SDmode values
-   from the 64-bit FP registers without using a full 64-bit
-   load/store, we need a wider mode.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)		\
-  rs6000_secondary_memory_needed_mode (MODE)
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	2017-09-04 11:50:24.557970193 +0100
+++ gcc/config/rs6000/rs6000-protos.h	2017-09-12 19:42:13.219280777 +0100
@@ -155,7 +155,6 @@ extern void rs6000_emit_le_vsx_permute (
 extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
 extern bool valid_sf_si_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-12 14:29:25.254529797 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-12 19:42:13.221179355 +0100
@@ -1876,6 +1876,8 @@ #define TARGET_BUILTIN_RECIPROCAL rs6000
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE rs6000_secondary_memory_needed_mode
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -19238,10 +19240,9 @@ mems_ok_for_quad_peep (rtx mem1, rtx mem
   return 1;
 }
 
-/* Return the mode to be used for memory when a secondary memory
-   location is needed.  For SDmode values we need to use DDmode, in
-   all other cases we can use the same mode.  */
-machine_mode
+/* Implement TARGET_SECONDARY_RELOAD_NEEDED_MODE.  For SDmode values we
+   need to use DDmode, in all other cases we can use the same mode.  */
+static machine_mode
 rs6000_secondary_memory_needed_mode (machine_mode mode)
 {
   if (lra_in_progress && mode == SDmode)
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-09-12 14:29:25.256529710 +0100
+++ gcc/config/s390/s390.h	2017-09-12 19:42:13.223077933 +0100
@@ -599,13 +599,6 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
    && (!TARGET_VX || (SCALAR_FLOAT_MODE_P (MODE)			\
 			  && GET_MODE_SIZE (MODE) > 8)))
 
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
-   because the movsi and movsf patterns don't handle r/f moves.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)			\
- (GET_MODE_BITSIZE (MODE) < 32					\
-  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()	\
-  : (MODE))
-
 
 /* Stack layout and calling conventions.  */
 
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-09-12 14:29:25.256529710 +0100
+++ gcc/config/s390/s390.c	2017-09-12 19:42:13.223077933 +0100
@@ -4409,6 +4409,19 @@ #define __SECONDARY_RELOAD_CASE(M,m)
   return NO_REGS;
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
+   because the movsi and movsf patterns don't handle r/f moves.  */
+
+static machine_mode
+s390_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (GET_MODE_BITSIZE (mode) < 32)
+    return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+  return mode;
+}
+
 /* Generate code to load SRC, which is PLUS that is not a
    legitimate operand for the LA instruction, into TARGET.
    SCRATCH may be used as scratch register.  */
@@ -15959,6 +15972,8 @@ #define TARGET_PREFERRED_RELOAD_CLASS s3
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD s390_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE s390_secondary_memory_needed_mode
 
 #undef TARGET_LIBGCC_CMP_RETURN_MODE
 #define TARGET_LIBGCC_CMP_RETURN_MODE s390_libgcc_cmp_return_mode
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-09-12 14:29:25.259529578 +0100
+++ gcc/config/sparc/sparc.h	2017-09-12 19:42:13.224027222 +0100
@@ -1055,18 +1055,6 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
        || GET_MODE_SIZE (MODE) > 8 \
        || GET_MODE_SIZE (MODE) < 4))
 
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
-   because the movsi and movsf patterns don't handle r/f moves.
-   For v8 we copy the default definition.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)				   \
-  (TARGET_ARCH64							   \
-   ? (GET_MODE_BITSIZE (MODE) < 32					   \
-      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()		   \
-      : MODE)								   \
-   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD				   \
-      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require () \
-      : MODE))
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 /* On SPARC, this is the size of MODE in words.  */
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-09-12 14:29:25.258529622 +0100
+++ gcc/config/sparc/sparc.c	2017-09-12 19:42:13.224027222 +0100
@@ -672,6 +672,7 @@ static void sparc_print_operand_address
 static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
 					   machine_mode,
 					   secondary_reload_info *);
+static machine_mode sparc_secondary_memory_needed_mode (machine_mode);
 static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
 static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
@@ -859,6 +860,8 @@ #define TARGET_PREFERRED_RELOAD_CLASS sp
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD sparc_secondary_reload
+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE sparc_secondary_memory_needed_mode
 
 #undef TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
@@ -13032,6 +13035,30 @@ sparc_secondary_reload (bool in_p, rtx x
   return NO_REGS;
 }
 
+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
+
+   get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
+   because the movsi and movsf patterns don't handle r/f moves.
+   For v8 we copy the default definition.  */
+
+static machine_mode
+sparc_secondary_memory_needed_mode (machine_mode mode)
+{
+  if (TARGET_ARCH64)
+    {
+      if (GET_MODE_BITSIZE (mode) < 32)
+	return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
+      return mode;
+    }
+  else
+    {
+      if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+	return mode_for_size (BITS_PER_WORD,
+			      GET_MODE_CLASS (mode), 0).require ();
+      return mode;
+    }
+}
+
 /* Emit code to conditionally move either OPERANDS[2] or OPERANDS[3] into
    OPERANDS[0] in MODE.  OPERANDS[1] is the operator of the condition.  */
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-09-12 14:29:25.264529359 +0100
+++ gcc/system.h	2017-09-12 19:42:13.226875090 +0100
@@ -913,7 +913,7 @@ #define realloc xrealloc
 	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	\
-	HARD_REGNO_NREGS
+	HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
