diff mbox series

Turn FUNCTION_ARG_PADDING into a target hook

Message ID 8760d8t3bi.fsf@linaro.org
State New
Headers show
Series Turn FUNCTION_ARG_PADDING into a target hook | expand

Commit Message

Richard Sandiford Aug. 28, 2017, 10:05 a.m. UTC
This involved renaming the rather general-sounding "enum direction" to
"enum pad_direction" to avoid a conflict with the Fortran frontend.

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/
	* coretypes.h (pad_direction): New enum.
	* defaults.h (DEFAULT_FUNCTION_ARG_PADDING): Delete.
	(FUNCTION_ARG_PADDING): Likewise.
	* target.def (function_arg_padding): New hook.
	* targhooks.h (default_function_arg_padding): Declare.
	* targhooks.c (default_function_arg_padding): New function.
	* doc/tm.texi.in (FUNCTION_ARG_PADDING): Replace with...
	(TARGET_FUNCTION_ARG_PADDING): ...this.
	* doc/tm.texi: Regenerate.
	* calls.c (store_unaligned_arguments_into_pseudos): Use pad_direction
	instead of direction.
	(compute_argument_addresses): Likewise.
	(load_register_parameters): Likewise.
	(emit_library_call_value_1): Likewise.
	(store_one_arg): Use targetm.calls.function_arg_padding instead
	of FUNCTION_ARG_PADDING.
	(must_pass_in_stack_var_size_or_pad): Likewise.
	* expr.c (emit_group_load_1): Use pad_direction instead of direction.
	(emit_group_store): Likewise.
	(emit_single_push_insn_1): Use targetm.calls.function_arg_padding
	instead of FUNCTION_ARG_PADDING.
	(emit_push_insn): Likewise, and propagate enum change throughout
	function.
	* function.h (direction): Delete.
	(locate_and_pad_arg_data::where_pad): Use pad_direction instead
	of direction.
	* function.c (assign_parm_find_stack_rtl): Likewise.
	(assign_parm_setup_block_p): Likewise.
	(assign_parm_setup_block): Likewise.
	(gimplify_parameters): Likewise.
	(locate_and_pad_parm): Use targetm.calls.function_arg_padding
	instead of FUNCTION_ARG_PADDING, and propagate enum change throughout
	function.
	* config/aarch64/aarch64.h (FUNCTION_ARG_PADDING): Delete.
	(BLOCK_REG_PADDING): Use pad_direction instead of direction.
	* config/aarch64/aarch64-protos.h (aarch64_pad_arg_upward): Delete.
	* config/aarch64/aarch64.c (aarch64_pad_arg_upward): Replace with...
	(aarch64_function_arg_padding): ...this new function.
	(aarch64_gimplify_va_arg_expr): Use pad_direction instead of direction.
	(TARGET_FUNCTION_ARG_PADDING): Redefine.
	* config/arm/arm.h (FUNCTION_ARG_PADDING): Delete.
	(BLOCK_REG_PADDING): Use pad_direction instead of direction.
	* config/arm/arm-protos.h (arm_pad_arg_upward): Delete.
	* config/arm/arm.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(arm_pad_arg_upward): Replace with...
	(arm_function_arg_padding): ...this new function.
	* config/c6x/c6x.h (BLOCK_REG_PADDING): Use pad_direction instead
	of direction.
	* config/ia64/hpux.h (FUNCTION_ARG_PADDING): Delete.
	* config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): Delete.
	* config/ia64/ia64.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(ia64_hpux_function_arg_padding): Replace with...
	(ia64_function_arg_padding): ...this new function.  Use pad_direction
	instead of direction.  Check for TARGET_HPUX.
	* config/iq2000/iq2000.h (FUNCTION_ARG_PADDING): Delete.
	* config/iq2000/iq2000.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(iq2000_function_arg_padding): New function.
	* config/mips/mips-protos.h (mips_pad_arg_upward): Delete.
	* config/mips/mips.c (mips_pad_arg_upward): Replace with...
	(mips_function_arg_padding): ...this new function.
	(mips_pad_reg_upward): Update accordingly.
	(TARGET_FUNCTION_ARG_PADDING): Redefine.
	* config/mips/mips.h (PAD_VARARGS_DOWN): Use
	targetm.calls.function_arg_padding.
	(FUNCTION_ARG_PADDING): Delete.
	(BLOCK_REG_PADDING): Use pad_direction instead of direction.
	* config/nios2/nios2.h (FUNCTION_ARG_PADDING): Delete.
	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
	* config/nios2/nios2-protos.h (nios2_function_arg_padding): Delete.
	(nios2_block_reg_padding): Return pad_direction instead of direction.
	* config/nios2/nios2.c (nios2_block_reg_padding): Return pad_direction
	instead of direction.
	(nios2_function_arg_padding): Likewise.  Make static.
	(TARGET_FUNCTION_ARG_PADDING): Redefine.
	* config/pa/pa.h (FUNCTION_ARG_PADDING): Delete.
	(BLOCK_REG_PADDING): Use targetm.calls.function_arg_padding.
	* config/pa/pa-protos.h (pa_function_arg_padding): Delete.
	* config/pa/pa.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(pa_function_arg_padding): Make static.  Return pad_direction instead
	of direction.
	* config/powerpcspe/powerpcspe.h (FUNCTION_ARG_PADDING): Delete.
	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
	* config/powerpcspe/aix.h (BLOCK_REG_PADDING): Use pad_direction
	instead of direction.  Use targetm.calls.function_arg_padding.
	* config/powerpcspe/darwin.h (BLOCK_REG_PADDING): Likewise.
	* config/powerpcspe/freebsd64.h (BLOCK_REG_PADDING): Likewise.
	* config/powerpcspe/linux64.h (BLOCK_REG_PADDING): Likewise.
	* config/powerpcspe/powerpcspe-protos.h (function_arg_padding): Delete.
	* config/powerpcspe/powerpcspe.c (TARGET_FUNCTION_ARG_PADDING):
	Redefine.
	(function_arg_padding): Rename to...
	(rs6000_function_arg_padding): ...this.  Make static.  Return
	pad_direction instead of direction.
	(rs6000_return_in_msb): Use rs6000_function_arg_padding.
	* config/rs6000/rs6000.h (FUNCTION_ARG_PADDING): Delete.
	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.
	* config/rs6000/aix.h (BLOCK_REG_PADDING): Use pad_direction
	instead of direction.  Use targetm.calls.function_arg_padding.
	* config/rs6000/darwin.h (BLOCK_REG_PADDING): Likewise.
	* config/rs6000/freebsd64.h (BLOCK_REG_PADDING): Likewise.
	* config/rs6000/linux64.h (BLOCK_REG_PADDING): Likewise.
	* config/rs6000/rs6000-protos.h (function_arg_padding): Delete.
	* config/rs6000/rs6000.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(function_arg_padding): Rename to...
	(rs6000_function_arg_padding): ...this.  Make static.  Return
	pad_direction instead of direction.
	(rs6000_return_in_msb): Use rs6000_function_arg_padding.
	* config/s390/s390.h (FUNCTION_ARG_PADDING): Delete.
	* config/s390/s390.c (s390_function_arg_padding): New function.
	(TARGET_FUNCTION_ARG_PADDING): Redefine.
	* config/sparc/sparc.h (FUNCTION_ARG_PADDING): Delete.
	* config/sparc/sparc-protos.h (function_arg_padding): Delete.
	* config/sparc/sparc.c (TARGET_FUNCTION_ARG_PADDING): Redefine.
	(function_arg_padding): Rename to...
	(sparc_function_arg_padding): ...this.  Make static.  Return
	pad_direction instead of direction.
	* config/spu/spu.h (FUNCTION_ARG_PADDING): Delete.
	* config/spu/spu.c (spu_function_arg_padding): New function.
	(TARGET_FUNCTION_ARG_PADDING): Redefine.
	* system.h (FUNCTION_ARG_PADDING): Poison.

Comments

Jeff Law Aug. 29, 2017, 10:11 p.m. UTC | #1
On 08/28/2017 04:05 AM, Richard Sandiford wrote:
> This involved renaming the rather general-sounding "enum direction" to

> "enum pad_direction" to avoid a conflict with the Fortran frontend.

> 

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

> 	* coretypes.h (pad_direction): New enum.

> 	* defaults.h (DEFAULT_FUNCTION_ARG_PADDING): Delete.

> 	(FUNCTION_ARG_PADDING): Likewise.

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

> 	* targhooks.h (default_function_arg_padding): Declare.

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

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

> 	(TARGET_FUNCTION_ARG_PADDING): ...this.

> 	* doc/tm.texi: Regenerate.

> 	* calls.c (store_unaligned_arguments_into_pseudos): Use pad_direction

> 	instead of direction.

> 	(compute_argument_addresses): Likewise.

> 	(load_register_parameters): Likewise.

> 	(emit_library_call_value_1): Likewise.

> 	(store_one_arg): Use targetm.calls.function_arg_padding instead

> 	of FUNCTION_ARG_PADDING.

> 	(must_pass_in_stack_var_size_or_pad): Likewise.

> 	* expr.c (emit_group_load_1): Use pad_direction instead of direction.

> 	(emit_group_store): Likewise.

> 	(emit_single_push_insn_1): Use targetm.calls.function_arg_padding

> 	instead of FUNCTION_ARG_PADDING.

> 	(emit_push_insn): Likewise, and propagate enum change throughout

> 	function.

> 	* function.h (direction): Delete.

> 	(locate_and_pad_arg_data::where_pad): Use pad_direction instead

> 	of direction.

> 	* function.c (assign_parm_find_stack_rtl): Likewise.

> 	(assign_parm_setup_block_p): Likewise.

> 	(assign_parm_setup_block): Likewise.

> 	(gimplify_parameters): Likewise.

> 	(locate_and_pad_parm): Use targetm.calls.function_arg_padding

> 	instead of FUNCTION_ARG_PADDING, and propagate enum change throughout

> 	function.

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

> 	(BLOCK_REG_PADDING): Use pad_direction instead of direction.

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

> 	* config/aarch64/aarch64.c (aarch64_pad_arg_upward): Replace with...

> 	(aarch64_function_arg_padding): ...this new function.

> 	(aarch64_gimplify_va_arg_expr): Use pad_direction instead of direction.

> 	(TARGET_FUNCTION_ARG_PADDING): Redefine.

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

> 	(BLOCK_REG_PADDING): Use pad_direction instead of direction.

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

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

> 	(arm_pad_arg_upward): Replace with...

> 	(arm_function_arg_padding): ...this new function.

> 	* config/c6x/c6x.h (BLOCK_REG_PADDING): Use pad_direction instead

> 	of direction.

> 	* config/ia64/hpux.h (FUNCTION_ARG_PADDING): Delete.

> 	* config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): Delete.

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

> 	(ia64_hpux_function_arg_padding): Replace with...

> 	(ia64_function_arg_padding): ...this new function.  Use pad_direction

> 	instead of direction.  Check for TARGET_HPUX.

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

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

> 	(iq2000_function_arg_padding): New function.

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

> 	* config/mips/mips.c (mips_pad_arg_upward): Replace with...

> 	(mips_function_arg_padding): ...this new function.

> 	(mips_pad_reg_upward): Update accordingly.

> 	(TARGET_FUNCTION_ARG_PADDING): Redefine.

> 	* config/mips/mips.h (PAD_VARARGS_DOWN): Use

> 	targetm.calls.function_arg_padding.

> 	(FUNCTION_ARG_PADDING): Delete.

> 	(BLOCK_REG_PADDING): Use pad_direction instead of direction.

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

> 	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.

> 	* config/nios2/nios2-protos.h (nios2_function_arg_padding): Delete.

> 	(nios2_block_reg_padding): Return pad_direction instead of direction.

> 	* config/nios2/nios2.c (nios2_block_reg_padding): Return pad_direction

> 	instead of direction.

> 	(nios2_function_arg_padding): Likewise.  Make static.

> 	(TARGET_FUNCTION_ARG_PADDING): Redefine.

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

> 	(BLOCK_REG_PADDING): Use targetm.calls.function_arg_padding.

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

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

> 	(pa_function_arg_padding): Make static.  Return pad_direction instead

> 	of direction.

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

> 	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.

> 	* config/powerpcspe/aix.h (BLOCK_REG_PADDING): Use pad_direction

> 	instead of direction.  Use targetm.calls.function_arg_padding.

> 	* config/powerpcspe/darwin.h (BLOCK_REG_PADDING): Likewise.

> 	* config/powerpcspe/freebsd64.h (BLOCK_REG_PADDING): Likewise.

> 	* config/powerpcspe/linux64.h (BLOCK_REG_PADDING): Likewise.

> 	* config/powerpcspe/powerpcspe-protos.h (function_arg_padding): Delete.

> 	* config/powerpcspe/powerpcspe.c (TARGET_FUNCTION_ARG_PADDING):

> 	Redefine.

> 	(function_arg_padding): Rename to...

> 	(rs6000_function_arg_padding): ...this.  Make static.  Return

> 	pad_direction instead of direction.

> 	(rs6000_return_in_msb): Use rs6000_function_arg_padding.

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

> 	(PAD_VARARGS_DOWN): Use targetm.calls.function_arg_padding.

> 	* config/rs6000/aix.h (BLOCK_REG_PADDING): Use pad_direction

> 	instead of direction.  Use targetm.calls.function_arg_padding.

> 	* config/rs6000/darwin.h (BLOCK_REG_PADDING): Likewise.

> 	* config/rs6000/freebsd64.h (BLOCK_REG_PADDING): Likewise.

> 	* config/rs6000/linux64.h (BLOCK_REG_PADDING): Likewise.

> 	* config/rs6000/rs6000-protos.h (function_arg_padding): Delete.

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

> 	(function_arg_padding): Rename to...

> 	(rs6000_function_arg_padding): ...this.  Make static.  Return

> 	pad_direction instead of direction.

> 	(rs6000_return_in_msb): Use rs6000_function_arg_padding.

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

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

> 	(TARGET_FUNCTION_ARG_PADDING): Redefine.

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

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

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

> 	(function_arg_padding): Rename to...

> 	(sparc_function_arg_padding): ...this.  Make static.  Return

> 	pad_direction instead of direction.

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

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

> 	(TARGET_FUNCTION_ARG_PADDING): Redefine.

> 	* system.h (FUNCTION_ARG_PADDING): Poison.

> 


OK.

jeff
diff mbox series

Patch

Index: gcc/coretypes.h
===================================================================
--- gcc/coretypes.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/coretypes.h	2017-08-28 11:03:59.142665850 +0100
@@ -219,6 +219,22 @@  enum optimization_type {
   OPTIMIZE_FOR_SIZE
 };
 
+/* Enumerates a padding direction.  */
+enum pad_direction {
+  /* No padding is required.  */
+  PAD_NONE,
+
+  /* Insert padding above the data, i.e. at higher memeory addresses
+     when dealing with memory, and at the most significant end when
+     dealing with registers.  */
+  PAD_UPWARD,
+
+  /* Insert padding below the data, i.e. at lower memeory addresses
+     when dealing with memory, and at the least significant end when
+     dealing with registers.  */
+  PAD_DOWNWARD
+};
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/defaults.h	2017-08-28 11:03:59.142665850 +0100
@@ -1355,24 +1355,6 @@  #define CLEAR_RATIO(speed) ((speed) ? 15
 #define SET_RATIO(speed) MOVE_RATIO (speed)
 #endif
 
-/* Supply a default definition for FUNCTION_ARG_PADDING:
-   usually pad upward, but pad short args downward on
-   big-endian machines.  */
-
-#define DEFAULT_FUNCTION_ARG_PADDING(MODE, TYPE)			\
-  (! BYTES_BIG_ENDIAN							\
-   ? upward								\
-   : (((MODE) == BLKmode						\
-       ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST		\
-	  && int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT)) \
-       : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY)			\
-      ? downward : upward))
-
-#ifndef FUNCTION_ARG_PADDING
-#define FUNCTION_ARG_PADDING(MODE, TYPE)	\
-  DEFAULT_FUNCTION_ARG_PADDING ((MODE), (TYPE))
-#endif
-
 /* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save.
    Normally move_insn, so Pmode stack pointer.  */
 
Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-08-28 11:03:58.526233104 +0100
+++ gcc/target.def	2017-08-28 11:03:59.146688249 +0100
@@ -4533,6 +4533,24 @@  used for arguments without any special h
  (cumulative_args_t ca, machine_mode mode, const_tree type, bool named),
  default_function_arg_advance)
 
+DEFHOOK
+(function_arg_padding,
+ "This hook determines whether, and in which direction, to pad out\n\
+an argument of mode @var{mode} and type @var{type}.  It returns\n\
+@code{PAD_UPWARD} to insert padding above the argument, @code{PAD_DOWNWARD}\n\
+to insert padding below the argument, or @code{PAD_NONE} to inhibit padding.\n\
+\n\
+The @emph{amount} of padding is not controlled by this hook, but by\n\
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.  It is always just enough\n\
+to reach the next multiple of that boundary.\n\
+\n\
+This hook has a default definition that is right for most systems.\n\
+For little-endian machines, the default is to pad upward.  For\n\
+big-endian machines, the default is to pad downward for an argument of\n\
+constant size shorter than an @code{int}, and upward otherwise.",
+ pad_direction, (machine_mode mode, const_tree type),
+ default_function_arg_padding)
+
 /* Return zero if the argument described by the state of CA should
    be placed on a stack, or a hard register in which to store the
    argument.  The values MODE, TYPE, and NAMED describe that
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/targhooks.h	2017-08-28 11:03:59.146688249 +0100
@@ -132,6 +132,7 @@  extern bool hook_bool_CUMULATIVE_ARGS_tr
   (const_tree, const_tree, const_tree);
 extern void default_function_arg_advance
   (cumulative_args_t, machine_mode, const_tree, bool);
+extern pad_direction default_function_arg_padding (machine_mode, const_tree);
 extern rtx default_function_arg
   (cumulative_args_t, machine_mode, const_tree, bool);
 extern rtx default_function_incoming_arg
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/targhooks.c	2017-08-28 11:03:59.146688249 +0100
@@ -733,6 +733,31 @@  default_function_arg_advance (cumulative
   gcc_unreachable ();
 }
 
+/* Default implementation of TARGET_FUNCTION_ARG_PADDING: usually pad
+   upward, but pad short args downward on big-endian machines.  */
+
+pad_direction
+default_function_arg_padding (machine_mode mode, const_tree type)
+{
+  if (!BYTES_BIG_ENDIAN)
+    return PAD_UPWARD;
+
+  unsigned HOST_WIDE_INT size;
+  if (mode == BLKmode)
+    {
+      if (!type || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+	return PAD_UPWARD;
+      size = int_size_in_bytes (type);
+    }
+  else
+    size = GET_MODE_SIZE (mode);
+
+  if (size < (PARM_BOUNDARY / BITS_PER_UNIT))
+    return PAD_DOWNWARD;
+
+  return PAD_UPWARD;
+}
+
 rtx
 default_function_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
 		      machine_mode mode ATTRIBUTE_UNUSED,
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-08-28 11:03:58.526233104 +0100
+++ gcc/doc/tm.texi.in	2017-08-28 11:03:59.144677050 +0100
@@ -3363,21 +3363,7 @@  slot that is in the middle of the quad w
 top.
 @end defmac
 
-@defmac FUNCTION_ARG_PADDING (@var{mode}, @var{type})
-If defined, a C expression which determines whether, and in which direction,
-to pad out an argument with extra space.  The value should be of type
-@code{enum direction}: either @code{upward} to pad above the argument,
-@code{downward} to pad below, or @code{none} to inhibit padding.
-
-The @emph{amount} of padding is not controlled by this macro, but by the
-target hook @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.  It is
-always just enough to reach the next multiple of that boundary. 
-
-This macro has a default definition which is right for most systems.
-For little-endian machines, the default is to pad upward.  For
-big-endian machines, the default is to pad downward for an argument of
-constant size shorter than an @code{int}, and upward otherwise.
-@end defmac
+@hook TARGET_FUNCTION_ARG_PADDING
 
 @defmac PAD_VARARGS_DOWN
 If defined, a C expression which determines whether the default
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-08-28 11:03:58.526233104 +0100
+++ gcc/doc/tm.texi	2017-08-28 11:03:59.143671450 +0100
@@ -4096,21 +4096,21 @@  slot that is in the middle of the quad w
 top.
 @end defmac
 
-@defmac FUNCTION_ARG_PADDING (@var{mode}, @var{type})
-If defined, a C expression which determines whether, and in which direction,
-to pad out an argument with extra space.  The value should be of type
-@code{enum direction}: either @code{upward} to pad above the argument,
-@code{downward} to pad below, or @code{none} to inhibit padding.
+@deftypefn {Target Hook} pad_direction TARGET_FUNCTION_ARG_PADDING (machine_mode @var{mode}, const_tree @var{type})
+This hook determines whether, and in which direction, to pad out
+an argument of mode @var{mode} and type @var{type}.  It returns
+@code{PAD_UPWARD} to insert padding above the argument, @code{PAD_DOWNWARD}
+to insert padding below the argument, or @code{PAD_NONE} to inhibit padding.
 
-The @emph{amount} of padding is not controlled by this macro, but by the
-target hook @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.  It is
-always just enough to reach the next multiple of that boundary. 
+The @emph{amount} of padding is not controlled by this hook, but by
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.  It is always just enough
+to reach the next multiple of that boundary.
 
-This macro has a default definition which is right for most systems.
+This hook has a default definition that is right for most systems.
 For little-endian machines, the default is to pad upward.  For
 big-endian machines, the default is to pad downward for an argument of
 constant size shorter than an @code{int}, and upward otherwise.
-@end defmac
+@end deftypefn
 
 @defmac PAD_VARARGS_DOWN
 If defined, a C expression which determines whether the default
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/calls.c	2017-08-28 11:03:59.120542652 +0100
@@ -1153,7 +1153,7 @@  store_unaligned_arguments_into_pseudos (
 #ifdef BLOCK_REG_PADDING
 	    && (BLOCK_REG_PADDING (args[i].mode,
 				   TREE_TYPE (args[i].tree_value), 1)
-		== downward)
+		== PAD_DOWNWARD)
 #else
 	    && BYTES_BIG_ENDIAN
 #endif
@@ -2221,7 +2221,7 @@  compute_argument_addresses (struct arg_d
 	    }
 	  align = BITS_PER_UNIT;
 	  boundary = args[i].locate.boundary;
-	  if (args[i].locate.where_pad != downward)
+	  if (args[i].locate.where_pad != PAD_DOWNWARD)
 	    align = boundary;
 	  else if (CONST_INT_P (offset))
 	    {
@@ -2518,7 +2518,7 @@  load_register_parameters (struct arg_dat
 		 upward on a BYTES_BIG_ENDIAN machine.  */
 	      if (size < UNITS_PER_WORD
 		  && (args[i].locate.where_pad
-		      == (BYTES_BIG_ENDIAN ? upward : downward)))
+		      == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
 		{
 		  rtx x;
 		  int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
@@ -2579,7 +2579,7 @@  load_register_parameters (struct arg_dat
 	      /* Handle a BLKmode that needs shifting.  */
 	      if (nregs == 1 && size < UNITS_PER_WORD
 #ifdef BLOCK_REG_PADDING
-		  && args[i].locate.where_pad == downward
+		  && args[i].locate.where_pad == PAD_DOWNWARD
 #else
 		  && BYTES_BIG_ENDIAN
 #endif
@@ -4900,7 +4900,7 @@  emit_library_call_value_1 (int retval, r
 	     upward on a BYTES_BIG_ENDIAN machine.  */
 	  if (size < UNITS_PER_WORD
 	      && (argvec[argnum].locate.where_pad
-		  == (BYTES_BIG_ENDIAN ? upward : downward)))
+		  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
 	    {
 	      rtx x;
 	      int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
@@ -5423,14 +5423,16 @@  store_one_arg (struct arg_data *arg, rtx
 
       /* Compute how much space the argument should get:
 	 round up to a multiple of the alignment for arguments.  */
-      if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
+      if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+	  != PAD_NONE)
 	used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
 		 / (PARM_BOUNDARY / BITS_PER_UNIT))
 		* (PARM_BOUNDARY / BITS_PER_UNIT));
 
       /* Compute the alignment of the pushed argument.  */
       parm_align = arg->locate.boundary;
-      if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+      if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+	  == PAD_DOWNWARD)
 	{
 	  int pad = used - size;
 	  if (pad)
@@ -5489,7 +5491,8 @@  store_one_arg (struct arg_data *arg, rtx
 
       /* When an argument is padded down, the block is aligned to
 	 PARM_BOUNDARY, but the actual argument isn't.  */
-      if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+      if (targetm.calls.function_arg_padding (arg->mode, TREE_TYPE (pval))
+	  == PAD_DOWNWARD)
 	{
 	  if (arg->locate.size.var)
 	    parm_align = BITS_PER_UNIT;
@@ -5640,8 +5643,8 @@  must_pass_in_stack_var_size_or_pad (mach
      a register would put it into the wrong part of the register.  */
   if (mode == BLKmode
       && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
-      && (FUNCTION_ARG_PADDING (mode, type)
-	  == (BYTES_BIG_ENDIAN ? upward : downward)))
+      && (targetm.calls.function_arg_padding (mode, type)
+	  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
     return true;
 
   return false;
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/expr.c	2017-08-28 11:03:59.145682649 +0100
@@ -2134,7 +2134,7 @@  emit_group_load_1 (rtx *tmps, rtx dst, r
 	  if (
 #ifdef BLOCK_REG_PADDING
 	      BLOCK_REG_PADDING (GET_MODE (orig_src), type, i == start)
-	      == (BYTES_BIG_ENDIAN ? upward : downward)
+	      == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)
 #else
 	      BYTES_BIG_ENDIAN
 #endif
@@ -2544,7 +2544,7 @@  emit_group_store (rtx orig_dst, rtx src,
 	  if (
 #ifdef BLOCK_REG_PADDING
 	      BLOCK_REG_PADDING (GET_MODE (orig_dst), type, i == start)
-	      == (BYTES_BIG_ENDIAN ? upward : downward)
+	      == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)
 #else
 	      BYTES_BIG_ENDIAN
 #endif
@@ -4115,7 +4115,7 @@  emit_single_push_insn_1 (machine_mode mo
      then store X into the stack location using an offset.  This is
      because emit_move_insn does not know how to pad; it does not have
      access to type.  */
-  else if (FUNCTION_ARG_PADDING (mode, type) == downward)
+  else if (targetm.calls.function_arg_padding (mode, type) == PAD_DOWNWARD)
     {
       unsigned padding_size = rounded_size - GET_MODE_SIZE (mode);
       HOST_WIDE_INT offset;
@@ -4259,18 +4259,19 @@  emit_push_insn (rtx x, machine_mode mode
 		rtx alignment_pad, bool sibcall_p)
 {
   rtx xinner;
-  enum direction stack_direction = STACK_GROWS_DOWNWARD ? downward : upward;
+  pad_direction stack_direction
+    = STACK_GROWS_DOWNWARD ? PAD_DOWNWARD : PAD_UPWARD;
 
-  /* Decide where to pad the argument: `downward' for below,
-     `upward' for above, or `none' for don't pad it.
+  /* Decide where to pad the argument: PAD_DOWNWARD for below,
+     PAD_UPWARD for above, or PAD_NONE for don't pad it.
      Default is below for small data on big-endian machines; else above.  */
-  enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
+  pad_direction where_pad = targetm.calls.function_arg_padding (mode, type);
 
   /* Invert direction if stack is post-decrement.
      FIXME: why?  */
   if (STACK_PUSH_CODE == POST_DEC)
-    if (where_pad != none)
-      where_pad = (where_pad == downward ? upward : downward);
+    if (where_pad != PAD_NONE)
+      where_pad = (where_pad == PAD_DOWNWARD ? PAD_UPWARD : PAD_DOWNWARD);
 
   xinner = x;
 
@@ -4342,7 +4343,7 @@  emit_push_insn (rtx x, machine_mode mode
 	     or if padding below and stack grows up.
 	     But if space already allocated, this has already been done.  */
 	  if (extra && args_addr == 0
-	      && where_pad != none && where_pad != stack_direction)
+	      && where_pad != PAD_NONE && where_pad != stack_direction)
 	    anti_adjust_stack (GEN_INT (extra));
 
 	  move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0);
@@ -4371,7 +4372,7 @@  emit_push_insn (rtx x, machine_mode mode
 	     A single stack adjust will do.  */
 	  if (! args_addr)
 	    {
-	      temp = push_block (size, extra, where_pad == downward);
+	      temp = push_block (size, extra, where_pad == PAD_DOWNWARD);
 	      extra = 0;
 	    }
 	  else if (CONST_INT_P (args_so_far))
@@ -4465,7 +4466,7 @@  emit_push_insn (rtx x, machine_mode mode
 	 or if padding below and stack grows up.
 	 But if space already allocated, this has already been done.  */
       if (extra && args_addr == 0
-	  && where_pad != none && where_pad != stack_direction)
+	  && where_pad != PAD_NONE && where_pad != stack_direction)
 	anti_adjust_stack (GEN_INT (extra));
 
       /* If we make space by pushing it, we might as well push
@@ -4516,7 +4517,7 @@  emit_push_insn (rtx x, machine_mode mode
 	 or if padding below and stack grows up.
 	 But if space already allocated, this has already been done.  */
       if (extra && args_addr == 0
-	  && where_pad != none && where_pad != stack_direction)
+	  && where_pad != PAD_NONE && where_pad != stack_direction)
 	anti_adjust_stack (GEN_INT (extra));
 
 #ifdef PUSH_ROUNDING
Index: gcc/function.h
===================================================================
--- gcc/function.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/function.h	2017-08-28 11:03:59.145682649 +0100
@@ -469,8 +469,6 @@  #define VALUE_HISTOGRAMS(fun) (fun)->val
    data structures.  */
 extern struct machine_function * (*init_machine_status) (void);
 
-enum direction {none, upward, downward};
-
 /* Structure to record the size of a sequence of arguments
    as the sum of a tree-expression and a constant.  This structure is
    also used to store offsets from the stack, which might be negative,
@@ -499,7 +497,7 @@  struct locate_and_pad_arg_data
      force alignment for the next argument.  */
   struct args_size alignment_pad;
   /* Which way we should pad this arg.  */
-  enum direction where_pad;
+  pad_direction where_pad;
   /* slot_offset is at least this aligned.  */
   unsigned int boundary;
 };
Index: gcc/function.c
===================================================================
--- gcc/function.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/function.c	2017-08-28 11:03:59.145682649 +0100
@@ -2713,7 +2713,7 @@  assign_parm_find_stack_rtl (tree parm, s
      is TARGET_FUNCTION_ARG_BOUNDARY.  If we're using slot_offset, we're
      intentionally forcing upward padding.  Otherwise we have to come
      up with a guess at the alignment based on OFFSET_RTX.  */
-  if (data->locate.where_pad != downward || data->entry_parm)
+  if (data->locate.where_pad != PAD_DOWNWARD || data->entry_parm)
     align = boundary;
   else if (CONST_INT_P (offset_rtx))
     {
@@ -2867,7 +2867,7 @@  assign_parm_setup_block_p (struct assign
   if (REG_P (data->entry_parm)
       && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD
       && (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
-	  == (BYTES_BIG_ENDIAN ? upward : downward)))
+	  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
     return true;
 #endif
 
@@ -2985,7 +2985,7 @@  assign_parm_setup_block (struct assign_p
 #ifdef BLOCK_REG_PADDING
 	      && (size == UNITS_PER_WORD
 		  || (BLOCK_REG_PADDING (mode, data->passed_type, 1)
-		      != (BYTES_BIG_ENDIAN ? upward : downward)))
+		      != (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
 #endif
 	      )
 	    {
@@ -3025,7 +3025,7 @@  assign_parm_setup_block (struct assign_p
 	      gcc_checking_assert (BYTES_BIG_ENDIAN
 				   && (BLOCK_REG_PADDING (mode,
 							  data->passed_type, 1)
-				       == upward));
+				       == PAD_UPWARD));
 
 	      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
 
@@ -3046,7 +3046,7 @@  assign_parm_setup_block (struct assign_p
 	  else if (size != UNITS_PER_WORD
 #ifdef BLOCK_REG_PADDING
 		   && (BLOCK_REG_PADDING (mode, data->passed_type, 1)
-		       == downward)
+		       == PAD_DOWNWARD)
 #else
 		   && BYTES_BIG_ENDIAN
 #endif
@@ -3070,7 +3070,7 @@  assign_parm_setup_block (struct assign_p
 #ifdef BLOCK_REG_PADDING
 	  gcc_checking_assert (BLOCK_REG_PADDING (GET_MODE (mem),
 						  data->passed_type, 0)
-			       == upward);
+			       == PAD_UPWARD);
 #endif
 	  emit_move_insn (mem, entry_parm);
 	}
@@ -4099,7 +4099,7 @@  gimplify_parameters (void)
    rounding affects the initial and starting offsets, but not the argument
    size.
 
-   The second, controlled by FUNCTION_ARG_PADDING and PARM_BOUNDARY,
+   The second, controlled by TARGET_FUNCTION_ARG_PADDING and PARM_BOUNDARY,
    optionally rounds the size of the parm to PARM_BOUNDARY.  The
    initial offset is not affected by this rounding, while the size always
    is and the starting offset may be.  */
@@ -4117,7 +4117,7 @@  locate_and_pad_parm (machine_mode passed
 		     struct locate_and_pad_arg_data *locate)
 {
   tree sizetree;
-  enum direction where_pad;
+  pad_direction where_pad;
   unsigned int boundary, round_boundary;
   int part_size_in_regs;
 
@@ -4143,7 +4143,7 @@  locate_and_pad_parm (machine_mode passed
 
   sizetree
     = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
-  where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
+  where_pad = targetm.calls.function_arg_padding (passed_mode, type);
   boundary = targetm.calls.function_arg_boundary (passed_mode, type);
   round_boundary = targetm.calls.function_arg_round_boundary (passed_mode,
 							      type);
@@ -4192,7 +4192,7 @@  locate_and_pad_parm (machine_mode passed
 
       {
 	tree s2 = sizetree;
-	if (where_pad != none
+	if (where_pad != PAD_NONE
 	    && (!tree_fits_uhwi_p (sizetree)
 		|| (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
 	  s2 = round_up (s2, round_boundary / BITS_PER_UNIT);
@@ -4217,7 +4217,7 @@  locate_and_pad_parm (machine_mode passed
       /* Pad_below needs the pre-rounded size to know how much to pad
 	 below.  */
       locate->offset = locate->slot_offset;
-      if (where_pad == downward)
+      if (where_pad == PAD_DOWNWARD)
 	pad_below (&locate->offset, passed_mode, sizetree);
 
     }
@@ -4236,10 +4236,10 @@  locate_and_pad_parm (machine_mode passed
       /* Pad_below needs the pre-rounded size to know how much to pad below
 	 so this must be done before rounding up.  */
       locate->offset = locate->slot_offset;
-      if (where_pad == downward)
+      if (where_pad == PAD_DOWNWARD)
 	pad_below (&locate->offset, passed_mode, sizetree);
 
-      if (where_pad != none
+      if (where_pad != PAD_NONE
 	  && (!tree_fits_uhwi_p (sizetree)
 	      || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
 	sizetree = round_up (sizetree, round_boundary / BITS_PER_UNIT);
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/aarch64/aarch64.h	2017-08-28 11:03:59.122553852 +0100
@@ -668,11 +668,8 @@  typedef struct
 } CUMULATIVE_ARGS;
 #endif
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-  (aarch64_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (aarch64_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+  (aarch64_pad_reg_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
 
 #define PAD_VARARGS_DOWN	0
 
Index: gcc/config/aarch64/aarch64-protos.h
===================================================================
--- gcc/config/aarch64/aarch64-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/aarch64/aarch64-protos.h	2017-08-28 11:03:59.120542652 +0100
@@ -347,7 +347,6 @@  rtx aarch64_reverse_mask (machine_mode);
 bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
 char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
 char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
-bool aarch64_pad_arg_upward (machine_mode, const_tree);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
 bool aarch64_regno_ok_for_base_p (int, bool);
 bool aarch64_regno_ok_for_index_p (int, bool);
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/aarch64/aarch64.c	2017-08-28 11:03:59.121548252 +0100
@@ -2593,22 +2593,19 @@  aarch64_function_arg_boundary (machine_m
   return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
 }
 
-/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
-
-   Return true if an argument passed on the stack should be padded upwards,
-   i.e. if the least-significant byte of the stack slot has useful data.
+/* Implement TARGET_FUNCTION_ARG_PADDING.
 
    Small aggregate types are placed in the lowest memory address.
 
    The related parameter passing rules are B.4, C.3, C.5 and C.14.  */
 
-bool
-aarch64_pad_arg_upward (machine_mode mode, const_tree type)
+static pad_direction
+aarch64_function_arg_padding (machine_mode mode, const_tree type)
 {
   /* On little-endian targets, the least significant byte of every stack
      argument is passed at the lowest byte address of the stack slot.  */
   if (!BYTES_BIG_ENDIAN)
-    return true;
+    return PAD_UPWARD;
 
   /* Otherwise, integral, floating-point and pointer types are padded downward:
      the least significant byte of a stack argument is passed at the highest
@@ -2617,10 +2614,10 @@  aarch64_pad_arg_upward (machine_mode mod
       ? (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type)
 	 || POINTER_TYPE_P (type))
       : (SCALAR_INT_MODE_P (mode) || SCALAR_FLOAT_MODE_P (mode)))
-    return false;
+    return PAD_DOWNWARD;
 
   /* Everything else padded upward, i.e. data in first byte of stack slot.  */
-  return true;
+  return PAD_UPWARD;
 }
 
 /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
@@ -10622,7 +10619,7 @@  aarch64_gimplify_va_arg_expr (tree valis
 	  if (BYTES_BIG_ENDIAN && GET_MODE_SIZE (ag_mode) < UNITS_PER_VREG)
 	    adjust = UNITS_PER_VREG - GET_MODE_SIZE (ag_mode);
 	}
-      else if (BLOCK_REG_PADDING (mode, type, 1) == downward
+      else if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
 	       && size < UNITS_PER_VREG)
 	{
 	  adjust = UNITS_PER_VREG - size;
@@ -10641,7 +10638,7 @@  aarch64_gimplify_va_arg_expr (tree valis
       if (align > 8)
 	dw_align = true;
 
-      if (BLOCK_REG_PADDING (mode, type, 1) == downward
+      if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
 	  && size < UNITS_PER_WORD)
 	{
 	  adjust = UNITS_PER_WORD  - size;
@@ -10716,7 +10713,7 @@  aarch64_gimplify_va_arg_expr (tree valis
   /* String up with arg */
   on_stack = build2 (COMPOUND_EXPR, TREE_TYPE (arg), t, arg);
   /* Big-endianness related address adjustment.  */
-  if (BLOCK_REG_PADDING (mode, type, 1) == downward
+  if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD
       && size < UNITS_PER_WORD)
   {
     t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg), arg,
@@ -15370,6 +15367,9 @@  #define TARGET_FUNCTION_ARG_ADVANCE aarc
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary
 
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding
+
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL aarch64_function_ok_for_sibcall
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/arm/arm.h	2017-08-28 11:03:59.124565051 +0100
@@ -1480,11 +1480,8 @@  typedef struct
 } CUMULATIVE_ARGS;
 #endif
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-  (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+  (arm_pad_reg_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
 
 /* For AAPCS, padding should never be below the argument. For other ABIs,
  * mimic the default.  */
Index: gcc/config/arm/arm-protos.h
===================================================================
--- gcc/config/arm/arm-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/arm/arm-protos.h	2017-08-28 11:03:59.122553852 +0100
@@ -177,7 +177,6 @@  extern bool arm_coproc_ldc_stc_legitimat
 
 #if defined TREE_CODE
 extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
-extern bool arm_pad_arg_upward (machine_mode, const_tree);
 extern bool arm_pad_reg_upward (machine_mode, tree, int);
 #endif
 extern int arm_apply_result_size (void);
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/arm/arm.c	2017-08-28 11:03:59.124565051 +0100
@@ -186,6 +186,7 @@  static rtx arm_function_arg (cumulative_
 			     const_tree, bool);
 static void arm_function_arg_advance (cumulative_args_t, machine_mode,
 				      const_tree, bool);
+static pad_direction arm_function_arg_padding (machine_mode, const_tree);
 static unsigned int arm_function_arg_boundary (machine_mode, const_tree);
 static rtx aapcs_allocate_return_reg (machine_mode, const_tree,
 				      const_tree);
@@ -536,6 +537,8 @@  #define TARGET_ARG_PARTIAL_BYTES arm_arg
 #define TARGET_FUNCTION_ARG arm_function_arg
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE arm_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING arm_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY arm_function_arg_boundary
 
@@ -15155,22 +15158,21 @@  arm_must_pass_in_stack (machine_mode mod
 }
 
 
-/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
-   Return true if an argument passed on the stack should be padded upwards,
-   i.e. if the least-significant byte has useful data.
-   For legacy APCS ABIs we use the default.  For AAPCS based ABIs small
-   aggregate types are placed in the lowest memory address.  */
+/* Implement TARGET_FUNCTION_ARG_PADDING; return PAD_UPWARD if the lowest
+   byte of a stack argument has useful data.  For legacy APCS ABIs we use
+   the default.  For AAPCS based ABIs small aggregate types are placed
+   in the lowest memory address.  */
 
-bool
-arm_pad_arg_upward (machine_mode mode ATTRIBUTE_UNUSED, const_tree type)
+static pad_direction
+arm_function_arg_padding (machine_mode mode, const_tree type)
 {
   if (!TARGET_AAPCS_BASED)
-    return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward;
+    return default_function_arg_padding (mode, type);
 
   if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
-    return false;
+    return PAD_DOWNWARD;
 
-  return true;
+  return PAD_UPWARD;
 }
 
 
Index: gcc/config/c6x/c6x.h
===================================================================
--- gcc/config/c6x/c6x.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/c6x/c6x.h	2017-08-28 11:03:59.125570651 +0100
@@ -345,7 +345,7 @@  #define INIT_CUMULATIVE_ARGS(cum, fntype
   c6x_init_cumulative_args (&cum, fntype, libname, n_named_args)
 
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (c6x_block_reg_pad_upward (MODE, TYPE, FIRST) ? upward : downward)
+  (c6x_block_reg_pad_upward (MODE, TYPE, FIRST) ? PAD_UPWARD : PAD_DOWNWARD)
 
 #define FUNCTION_ARG_REGNO_P(r) \
     (((r) >= REG_A4 && (r) <= REG_A13) || ((r) >= REG_B4 && (r) <= REG_B13))
Index: gcc/config/ia64/hpux.h
===================================================================
--- gcc/config/ia64/hpux.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/ia64/hpux.h	2017-08-28 11:03:59.125570651 +0100
@@ -125,10 +125,6 @@  #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE
   ASM_OUTPUT_TYPE_DIRECTIVE (FILE, XSTR (FUN, 0), "function");	\
 } while (0)
 
-#undef FUNCTION_ARG_PADDING
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-	ia64_hpux_function_arg_padding ((MODE), (TYPE))
-
 #undef PAD_VARARGS_DOWN
 #define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
 
Index: gcc/config/ia64/ia64-protos.h
===================================================================
--- gcc/config/ia64/ia64-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/ia64/ia64-protos.h	2017-08-28 11:03:59.125570651 +0100
@@ -89,11 +89,6 @@  extern int ia64_dbx_register_number (int
 extern rtx ia64_return_addr_rtx (HOST_WIDE_INT, rtx);
 extern void ia64_split_return_addr_rtx (rtx);
 
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction'.  */
-extern enum direction ia64_hpux_function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
-
 extern void ia64_hpux_handle_builtin_pragma (struct cpp_reader *);
 extern void ia64_output_function_profiler (FILE *, int);
 extern void ia64_profile_hook (int);
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/ia64/ia64.c	2017-08-28 11:03:59.126576251 +0100
@@ -209,6 +209,7 @@  static rtx ia64_function_incoming_arg (c
 				       machine_mode, const_tree, bool);
 static void ia64_function_arg_advance (cumulative_args_t, machine_mode,
 				       const_tree, bool);
+static pad_direction ia64_function_arg_padding (machine_mode, const_tree);
 static unsigned int ia64_function_arg_boundary (machine_mode,
 						const_tree);
 static bool ia64_function_ok_for_sibcall (tree, tree);
@@ -509,6 +510,8 @@  #define TARGET_FUNCTION_ARG ia64_functio
 #define TARGET_FUNCTION_INCOMING_ARG ia64_function_incoming_arg
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE ia64_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING ia64_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY ia64_function_arg_boundary
 
@@ -10608,20 +10611,23 @@  ia64_builtin_decl (unsigned code, bool i
   return ia64_builtins[code];
 }
 
-/* For the HP-UX IA64 aggregate parameters are passed stored in the
+/* Implement TARGET_FUNCTION_ARG_PADDING.
+
+   For the HP-UX IA64 aggregate parameters are passed stored in the
    most significant bits of the stack slot.  */
 
-enum direction
-ia64_hpux_function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+ia64_function_arg_padding (machine_mode mode, const_tree type)
 {
-   /* Exception to normal case for structures/unions/etc.  */
-
-   if (type && AGGREGATE_TYPE_P (type)
-       && int_size_in_bytes (type) < UNITS_PER_WORD)
-     return upward;
+  /* Exception to normal case for structures/unions/etc.  */
+  if (TARGET_HPUX
+      && type
+      && AGGREGATE_TYPE_P (type)
+      && int_size_in_bytes (type) < UNITS_PER_WORD)
+    return PAD_UPWARD;
 
-   /* Fall back to the default.  */
-   return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+  /* Fall back to the default.  */
+  return default_function_arg_padding (mode, type);
 }
 
 /* Emit text to declare externally defined variables and functions, because
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/iq2000/iq2000.h	2017-08-28 11:03:59.126576251 +0100
@@ -308,16 +308,6 @@  typedef struct iq2000_args
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
   init_cumulative_args (& CUM, FNTYPE, LIBNAME)				\
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE)				\
-  (! BYTES_BIG_ENDIAN							\
-   ? upward								\
-   : (((MODE) == BLKmode						\
-       ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST		\
-	  && int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT))\
-       : (GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY			\
-	  && (GET_MODE_CLASS (MODE) == MODE_INT)))			\
-      ? downward : upward))
-
 #define FUNCTION_ARG_REGNO_P(N)						\
   (((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST))			
 
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/iq2000/iq2000.c	2017-08-28 11:03:59.126576251 +0100
@@ -165,6 +165,7 @@  static rtx iq2000_function_arg	      (cu
 				       machine_mode, const_tree, bool);
 static void iq2000_function_arg_advance (cumulative_args_t,
 					 machine_mode, const_tree, bool);
+static pad_direction iq2000_function_arg_padding (machine_mode, const_tree);
 static unsigned int iq2000_function_arg_boundary (machine_mode,
 						  const_tree);
 static void iq2000_va_start	      (tree, rtx);
@@ -231,6 +232,8 @@  #define TARGET_ARG_PARTIAL_BYTES	iq2000_
 #define TARGET_FUNCTION_ARG		iq2000_function_arg
 #undef  TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE	iq2000_function_arg_advance
+#undef  TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING	iq2000_function_arg_padding
 #undef  TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY	iq2000_function_arg_boundary
 
@@ -1376,6 +1379,22 @@  iq2000_function_arg (cumulative_args_t c
   return ret;
 }
 
+/* Implement TARGET_FUNCTION_ARG_PADDING.  */
+
+static pad_direction
+iq2000_function_arg_padding (machine_mode mode, const_tree type)
+{
+  return (! BYTES_BIG_ENDIAN
+	  ? PAD_UPWARD
+	  : ((mode == BLKmode
+	      ? (type
+		 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+		 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
+	      : (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY
+		 && GET_MODE_CLASS (mode) == MODE_INT))
+	     ? PAD_DOWNWARD : PAD_UPWARD));
+}
+
 static unsigned int
 iq2000_function_arg_boundary (machine_mode mode, const_tree type)
 {
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/mips/mips-protos.h	2017-08-28 11:03:59.126576251 +0100
@@ -246,7 +246,6 @@  extern bool mips_expand_block_move (rtx,
 extern void mips_expand_synci_loop (rtx, rtx);
 
 extern void mips_init_cumulative_args (CUMULATIVE_ARGS *, tree);
-extern bool mips_pad_arg_upward (machine_mode, const_tree);
 extern bool mips_pad_reg_upward (machine_mode, tree);
 
 extern bool mips_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/mips/mips.c	2017-08-28 11:03:59.128587451 +0100
@@ -6117,18 +6117,17 @@  mips_get_reg_raw_mode (int regno)
   return default_get_reg_raw_mode (regno);
 }
 
-/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
-   upward rather than downward.  In other words, return true if the
-   first byte of the stack slot has useful data, false if the last
-   byte does.  */
+/* Implement TARGET_FUNCTION_ARG_PADDING; return PAD_UPWARD if the first
+   byte of the stack slot has useful data, PAD_DOWNWARD if the last byte
+   does.  */
 
-bool
-mips_pad_arg_upward (machine_mode mode, const_tree type)
+static pad_direction
+mips_function_arg_padding (machine_mode mode, const_tree type)
 {
   /* On little-endian targets, the first byte of every stack argument
      is passed in the first byte of the stack slot.  */
   if (!BYTES_BIG_ENDIAN)
-    return true;
+    return PAD_UPWARD;
 
   /* Otherwise, integral types are padded downward: the last byte of a
      stack argument is passed in the last byte of the stack slot.  */
@@ -6138,22 +6137,24 @@  mips_pad_arg_upward (machine_mode mode,
 	 || FIXED_POINT_TYPE_P (type))
       : (SCALAR_INT_MODE_P (mode)
 	 || ALL_SCALAR_FIXED_POINT_MODE_P (mode)))
-    return false;
+    return PAD_DOWNWARD;
 
   /* Big-endian o64 pads floating-point arguments downward.  */
   if (mips_abi == ABI_O64)
     if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
-      return false;
+      return PAD_DOWNWARD;
 
   /* Other types are padded upward for o32, o64, n32 and n64.  */
   if (mips_abi != ABI_EABI)
-    return true;
+    return PAD_UPWARD;
 
   /* Arguments smaller than a stack slot are padded downward.  */
-  if (mode != BLKmode)
-    return GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY;
-  else
-    return int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT);
+  if (mode != BLKmode
+      ? GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY
+      : int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
+    return PAD_UPWARD;
+
+  return PAD_DOWNWARD;
 }
 
 /* Likewise BLOCK_REG_PADDING (MODE, TYPE, ...).  Return !BYTES_BIG_ENDIAN
@@ -6169,7 +6170,7 @@  mips_pad_reg_upward (machine_mode mode,
 
   /* Otherwise, apply the same padding to register arguments as we do
      to stack arguments.  */
-  return mips_pad_arg_upward (mode, type);
+  return mips_function_arg_padding (mode, type) == PAD_UPWARD;
 }
 
 /* Return nonzero when an argument must be passed by reference.  */
@@ -22458,6 +22459,8 @@  #define TARGET_ARG_PARTIAL_BYTES mips_ar
 #define TARGET_FUNCTION_ARG mips_function_arg
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE mips_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING mips_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY mips_function_arg_boundary
 #undef TARGET_GET_RAW_RESULT_MODE
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/mips/mips.h	2017-08-28 11:03:59.128587451 +0100
@@ -1679,7 +1679,7 @@  #define LOCAL_ALIGNMENT(TYPE, ALIGN) \
   DATA_ALIGNMENT (TYPE, ALIGN)
   
 #define PAD_VARARGS_DOWN \
-  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+  (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
 
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
@@ -2521,11 +2521,8 @@  typedef struct mips_args {
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
   mips_init_cumulative_args (&CUM, FNTYPE)
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-  (mips_pad_arg_upward (MODE, TYPE) ? upward : downward)
-
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (mips_pad_reg_upward (MODE, TYPE) ? upward : downward)
+  (mips_pad_reg_upward (MODE, TYPE) ? PAD_UPWARD : PAD_DOWNWARD)
 
 /* True if using EABI and varargs can be passed in floating-point
    registers.  Under these conditions, we need a more complex form
Index: gcc/config/nios2/nios2.h
===================================================================
--- gcc/config/nios2/nios2.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/nios2/nios2.h	2017-08-28 11:03:59.129593051 +0100
@@ -294,11 +294,8 @@  #define NUM_ARG_REGS (LAST_ARG_REGNO - F
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
   do { (CUM).regs_used = 0; } while (0)
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-  (nios2_function_arg_padding ((MODE), (TYPE)))
-
 #define PAD_VARARGS_DOWN \
-  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+  (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
 
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
   (nios2_block_reg_padding ((MODE), (TYPE), (FIRST)))
Index: gcc/config/nios2/nios2-protos.h
===================================================================
--- gcc/config/nios2/nios2-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/nios2/nios2-protos.h	2017-08-28 11:03:59.129593051 +0100
@@ -59,14 +59,8 @@  extern bool gen_ldstwm_peep (bool, int,
 
 extern void nios2_adjust_reg_alloc_order (void);
 
-#ifdef TREE_CODE
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines both ARGS_SIZE_RTX and `enum direction' */
-extern enum direction nios2_function_arg_padding (machine_mode, const_tree);
-extern enum direction nios2_block_reg_padding (machine_mode, tree, int);
-#endif /* ARGS_SIZE_RTX */
+extern pad_direction nios2_block_reg_padding (machine_mode, tree, int);
 
-#endif /* TREE_CODE */
 #endif /* RTX_CODE */
 
 #endif /* GCC_NIOS2_PROTOS_H */
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/nios2/nios2.c	2017-08-28 11:03:59.129593051 +0100
@@ -2983,30 +2983,31 @@  nios2_function_arg_advance (cumulative_a
     cum->regs_used += param_size;
 }
 
-enum direction
+static pad_direction
 nios2_function_arg_padding (machine_mode mode, const_tree type)
 {
   /* On little-endian targets, the first byte of every stack argument
      is passed in the first byte of the stack slot.  */
   if (!BYTES_BIG_ENDIAN)
-    return upward;
+    return PAD_UPWARD;
 
   /* Otherwise, integral types are padded downward: the last byte of a
      stack argument is passed in the last byte of the stack slot.  */
   if (type != 0
       ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
       : GET_MODE_CLASS (mode) == MODE_INT)
-    return downward;
+    return PAD_DOWNWARD;
 
   /* Arguments smaller than a stack slot are padded downward.  */
   if (mode != BLKmode)
-    return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
+    return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY
+	    ? PAD_UPWARD : PAD_DOWNWARD);
 
   return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
-	  ? upward : downward);
+	  ? PAD_UPWARD : PAD_DOWNWARD);
 }
 
-enum direction
+pad_direction
 nios2_block_reg_padding (machine_mode mode, tree type,
                          int first ATTRIBUTE_UNUSED)
 {
@@ -5009,6 +5010,9 @@  #define TARGET_FUNCTION_ARG nios2_functi
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
 
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING nios2_function_arg_padding
+
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
 
Index: gcc/config/pa/pa.h
===================================================================
--- gcc/config/pa/pa.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/pa/pa.h	2017-08-28 11:03:59.130598651 +0100
@@ -663,11 +663,6 @@  #define FUNCTION_ARG_SIZE(MODE, TYPE)	\
   the standard parameter passing conventions on the RS6000.  That's why
   you'll see lots of similar code in rs6000.h.  */
 
-/* If defined, a C expression which determines whether, and in which
-   direction, to pad out an argument with extra space.  */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-  pa_function_arg_padding ((MODE), (TYPE))
-
 /* Specify padding for the last element of a block move between registers
    and memory.
 
@@ -678,7 +673,7 @@  #define FUNCTION_ARG_PADDING(MODE, TYPE)
    so that there is only one element.  This allows the object to be
    correctly padded.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  pa_function_arg_padding ((MODE), (TYPE))
+  targetm.calls.function_arg_padding ((MODE), (TYPE))
 
 
 /* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
Index: gcc/config/pa/pa-protos.h
===================================================================
--- gcc/config/pa/pa-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/pa/pa-protos.h	2017-08-28 11:03:59.129593051 +0100
@@ -71,12 +71,6 @@  extern rtx pa_legitimize_reload_address
 
 extern rtx pa_return_addr_rtx (int, rtx);
 
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-#ifdef TREE_CODE
-extern enum direction pa_function_arg_padding (machine_mode, const_tree);
-#endif
-#endif /* ARGS_SIZE_RTX */
 extern int pa_insn_refs_are_delayed (rtx_insn *);
 extern rtx pa_get_deferred_plabel (rtx);
 extern rtx pa_maybe_emit_compare_and_swap_exchange_loop (rtx, rtx, rtx);
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/pa/pa.c	2017-08-28 11:03:59.130598651 +0100
@@ -172,6 +172,7 @@  static void pa_function_arg_advance (cum
 				     const_tree, bool);
 static rtx pa_function_arg (cumulative_args_t, machine_mode,
 			    const_tree, bool);
+static pad_direction pa_function_arg_padding (machine_mode, const_tree);
 static unsigned int pa_function_arg_boundary (machine_mode, const_tree);
 static struct machine_function * pa_init_machine_status (void);
 static reg_class_t pa_secondary_reload (bool, rtx, reg_class_t,
@@ -355,6 +356,8 @@  #define TARGET_ARG_PARTIAL_BYTES pa_arg_
 #define TARGET_FUNCTION_ARG pa_function_arg
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE pa_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING pa_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY pa_function_arg_boundary
 
@@ -6241,7 +6244,9 @@  pa_pass_by_reference (cumulative_args_t
     return size <= 0 || size > 8;
 }
 
-enum direction
+/* Implement TARGET_FUNCTION_ARG_PADDING.  */
+
+static pad_direction
 pa_function_arg_padding (machine_mode mode, const_tree type)
 {
   if (mode == BLKmode
@@ -6251,11 +6256,11 @@  pa_function_arg_padding (machine_mode mo
 	      || TREE_CODE (type) == COMPLEX_TYPE
 	      || TREE_CODE (type) == VECTOR_TYPE)))
     {
-      /* Return none if justification is not required.  */
+      /* Return PAD_NONE if justification is not required.  */
       if (type
 	  && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
 	  && (int_size_in_bytes (type) * BITS_PER_UNIT) % PARM_BOUNDARY == 0)
-	return none;
+	return PAD_NONE;
 
       /* The directions set here are ignored when a BLKmode argument larger
 	 than a word is placed in a register.  Different code is used for
@@ -6265,18 +6270,18 @@  pa_function_arg_padding (machine_mode mo
 	 the stack and in registers should be identical.  */
       if (TARGET_64BIT)
 	/* The 64-bit runtime specifies left justification for aggregates.  */
-        return upward;
+	return PAD_UPWARD;
       else
 	/* The 32-bit runtime architecture specifies right justification.
 	   When the argument is passed on the stack, the argument is padded
 	   with garbage on the left.  The HP compiler pads with zeros.  */
-	return downward;
+	return PAD_DOWNWARD;
     }
 
   if (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
-    return downward;
+    return PAD_DOWNWARD;
   else
-    return none;
+    return PAD_NONE;
 }
 
 
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-08-28 11:03:59.135626650 +0100
@@ -1901,16 +1901,8 @@  #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM
   init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \
 			0, NULL_TREE, MODE)
 
-/* If defined, a C expression which determines whether, and in which
-   direction, to pad out an argument with extra space.  The value
-   should be of type `enum direction': either `upward' to pad above
-   the argument, `downward' to pad below, or `none' to inhibit
-   padding.  */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding (MODE, TYPE)
-
 #define PAD_VARARGS_DOWN \
-   (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+  (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
 
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
Index: gcc/config/powerpcspe/aix.h
===================================================================
--- gcc/config/powerpcspe/aix.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/aix.h	2017-08-28 11:03:59.131604251 +0100
@@ -248,7 +248,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 1
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* Indicate that jump tables go in the text section.  */
 
Index: gcc/config/powerpcspe/darwin.h
===================================================================
--- gcc/config/powerpcspe/darwin.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/darwin.h	2017-08-28 11:03:59.131604251 +0100
@@ -344,7 +344,7 @@  #define ROUND_TYPE_ALIGN(STRUCT, COMPUTE
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 #define DOUBLE_INT_ASM_OP "\t.quad\t"
 
Index: gcc/config/powerpcspe/freebsd64.h
===================================================================
--- gcc/config/powerpcspe/freebsd64.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/freebsd64.h	2017-08-28 11:03:59.131604251 +0100
@@ -225,7 +225,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
    kernel. This is supported when running on a 64-bit kernel with
Index: gcc/config/powerpcspe/linux64.h
===================================================================
--- gcc/config/powerpcspe/linux64.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/linux64.h	2017-08-28 11:03:59.131604251 +0100
@@ -340,7 +340,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* Linux doesn't support saving and restoring 64-bit regs in a 32-bit
    process.  */
Index: gcc/config/powerpcspe/powerpcspe-protos.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/powerpcspe-protos.h	2017-08-28 11:03:59.131604251 +0100
@@ -196,10 +196,6 @@  extern void rs6000_xcoff_asm_output_alig
 							 unsigned HOST_WIDE_INT);
 extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
 extern bool rs6000_elf_in_small_data_p (const_tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
 
 #endif /* TREE_CODE */
 
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-08-28 11:03:59.134621050 +0100
@@ -88,6 +88,8 @@  #define TARGET_NO_PROTOTYPE 0
 #define min(A,B)	((A) < (B) ? (A) : (B))
 #define max(A,B)	((A) > (B) ? (A) : (B))
 
+static pad_direction rs6000_function_arg_padding (machine_mode, const_tree);
+
 /* Structure used to define the rs6000 stack */
 typedef struct rs6000_stack {
   int reload_completed;		/* stack info won't change from here on */
@@ -1810,6 +1812,8 @@  #define TARGET_ARG_PARTIAL_BYTES rs6000_
 #define TARGET_FUNCTION_ARG_ADVANCE rs6000_function_arg_advance
 #undef TARGET_FUNCTION_ARG
 #define TARGET_FUNCTION_ARG rs6000_function_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING rs6000_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY rs6000_function_arg_boundary
 
@@ -11814,7 +11818,8 @@  rs6000_return_in_msb (const_tree valtype
   return (DEFAULT_ABI == ABI_ELFv2
 	  && BYTES_BIG_ENDIAN
 	  && AGGREGATE_TYPE_P (valtype)
-	  && FUNCTION_ARG_PADDING (TYPE_MODE (valtype), valtype) == upward);
+	  && rs6000_function_arg_padding (TYPE_MODE (valtype),
+					  valtype) == PAD_UPWARD);
 }
 
 #ifdef HAVE_AS_GNU_ATTRIBUTE
@@ -12031,17 +12036,13 @@  abi_v4_pass_in_fpr (machine_mode mode)
   return false;
 }
 
-/* If defined, a C expression which determines whether, and in which
-   direction, to pad out an argument with extra space.  The value
-   should be of type `enum direction': either `upward' to pad above
-   the argument, `downward' to pad below, or `none' to inhibit
-   padding.
+/* Implement TARGET_FUNCTION_ARG_PADDING
 
    For the AIX ABI structs are always stored left shifted in their
    argument slot.  */
 
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+rs6000_function_arg_padding (machine_mode mode, const_tree type)
 {
 #ifndef AGGREGATE_PADDING_FIXED
 #define AGGREGATE_PADDING_FIXED 0
@@ -12053,7 +12054,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
   if (!AGGREGATE_PADDING_FIXED)
     {
       /* GCC used to pass structures of the same size as integer types as
-	 if they were in fact integers, ignoring FUNCTION_ARG_PADDING.
+	 if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING.
 	 i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
 	 passed padded downward, except that -mstrict-align further
 	 muddied the water in that multi-component structures of 2 and 4
@@ -12074,19 +12075,19 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
 	    size = GET_MODE_SIZE (mode);
 
 	  if (size == 1 || size == 2 || size == 4)
-	    return downward;
+	    return PAD_DOWNWARD;
 	}
-      return upward;
+      return PAD_UPWARD;
     }
 
   if (AGGREGATES_PAD_UPWARD_ALWAYS)
     {
       if (type != 0 && AGGREGATE_TYPE_P (type))
-	return upward;
+	return PAD_UPWARD;
     }
 
   /* Fall back to the default.  */
-  return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+  return default_function_arg_padding (mode, type);
 }
 
 /* If defined, a C expression that gives the alignment boundary, in bits,
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/rs6000.h	2017-08-28 11:03:59.138643450 +0100
@@ -1807,16 +1807,8 @@  #define INIT_CUMULATIVE_LIBCALL_ARGS(CUM
   init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE, \
 			0, NULL_TREE, MODE)
 
-/* If defined, a C expression which determines whether, and in which
-   direction, to pad out an argument with extra space.  The value
-   should be of type `enum direction': either `upward' to pad above
-   the argument, `downward' to pad below, or `none' to inhibit
-   padding.  */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding (MODE, TYPE)
-
 #define PAD_VARARGS_DOWN \
-   (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+  (targetm.calls.function_arg_padding (TYPE_MODE (type), type) == PAD_DOWNWARD)
 
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
Index: gcc/config/rs6000/aix.h
===================================================================
--- gcc/config/rs6000/aix.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/aix.h	2017-08-28 11:03:59.135626650 +0100
@@ -248,7 +248,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 1
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* Indicate that jump tables go in the text section.  */
 
Index: gcc/config/rs6000/darwin.h
===================================================================
--- gcc/config/rs6000/darwin.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/darwin.h	2017-08-28 11:03:59.135626650 +0100
@@ -339,7 +339,7 @@  #define ROUND_TYPE_ALIGN(STRUCT, COMPUTE
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 #define DOUBLE_INT_ASM_OP "\t.quad\t"
 
Index: gcc/config/rs6000/freebsd64.h
===================================================================
--- gcc/config/rs6000/freebsd64.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/freebsd64.h	2017-08-28 11:03:59.135626650 +0100
@@ -225,7 +225,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit
    kernel. This is supported when running on a 64-bit kernel with
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/linux64.h	2017-08-28 11:03:59.135626650 +0100
@@ -340,7 +340,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
    registers and memory.  FIRST is nonzero if this is the only
    element.  */
 #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
-  (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+  (!(FIRST) ? PAD_UPWARD : targetm.calls.function_arg_padding (MODE, TYPE))
 
 /* Linux doesn't support saving and restoring 64-bit regs in a 32-bit
    process.  */
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/rs6000-protos.h	2017-08-28 11:03:59.136632250 +0100
@@ -197,10 +197,6 @@  extern void rs6000_xcoff_asm_output_alig
 							 unsigned HOST_WIDE_INT);
 extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
 extern bool rs6000_elf_in_small_data_p (const_tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
 
 #endif /* TREE_CODE */
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/rs6000/rs6000.c	2017-08-28 11:03:59.138643450 +0100
@@ -89,6 +89,8 @@  #define TARGET_NO_PROTOTYPE 0
 #define min(A,B)	((A) < (B) ? (A) : (B))
 #define max(A,B)	((A) > (B) ? (A) : (B))
 
+static pad_direction rs6000_function_arg_padding (machine_mode, const_tree);
+
 /* Structure used to define the rs6000 stack */
 typedef struct rs6000_stack {
   int reload_completed;		/* stack info won't change from here on */
@@ -1795,6 +1797,8 @@  #define TARGET_ARG_PARTIAL_BYTES rs6000_
 #define TARGET_FUNCTION_ARG_ADVANCE rs6000_function_arg_advance
 #undef TARGET_FUNCTION_ARG
 #define TARGET_FUNCTION_ARG rs6000_function_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING rs6000_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY rs6000_function_arg_boundary
 
@@ -11324,7 +11328,8 @@  rs6000_return_in_msb (const_tree valtype
   return (DEFAULT_ABI == ABI_ELFv2
 	  && BYTES_BIG_ENDIAN
 	  && AGGREGATE_TYPE_P (valtype)
-	  && FUNCTION_ARG_PADDING (TYPE_MODE (valtype), valtype) == upward);
+	  && (rs6000_function_arg_padding (TYPE_MODE (valtype), valtype)
+	      == PAD_UPWARD));
 }
 
 #ifdef HAVE_AS_GNU_ATTRIBUTE
@@ -11541,17 +11546,13 @@  abi_v4_pass_in_fpr (machine_mode mode)
   return false;
 }
 
-/* If defined, a C expression which determines whether, and in which
-   direction, to pad out an argument with extra space.  The value
-   should be of type `enum direction': either `upward' to pad above
-   the argument, `downward' to pad below, or `none' to inhibit
-   padding.
+/* Implement TARGET_FUNCTION_ARG_PADDING.
 
    For the AIX ABI structs are always stored left shifted in their
    argument slot.  */
 
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+rs6000_function_arg_padding (machine_mode mode, const_tree type)
 {
 #ifndef AGGREGATE_PADDING_FIXED
 #define AGGREGATE_PADDING_FIXED 0
@@ -11563,7 +11564,7 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
   if (!AGGREGATE_PADDING_FIXED)
     {
       /* GCC used to pass structures of the same size as integer types as
-	 if they were in fact integers, ignoring FUNCTION_ARG_PADDING.
+	 if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING.
 	 i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
 	 passed padded downward, except that -mstrict-align further
 	 muddied the water in that multi-component structures of 2 and 4
@@ -11584,19 +11585,19 @@  #define AGGREGATES_PAD_UPWARD_ALWAYS 0
 	    size = GET_MODE_SIZE (mode);
 
 	  if (size == 1 || size == 2 || size == 4)
-	    return downward;
+	    return PAD_DOWNWARD;
 	}
-      return upward;
+      return PAD_UPWARD;
     }
 
   if (AGGREGATES_PAD_UPWARD_ALWAYS)
     {
       if (type != 0 && AGGREGATE_TYPE_P (type))
-	return upward;
+	return PAD_UPWARD;
     }
 
   /* Fall back to the default.  */
-  return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+  return default_function_arg_padding (mode, type);
 }
 
 /* If defined, a C expression that gives the alignment boundary, in bits,
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/s390/s390.h	2017-08-28 11:03:59.140654650 +0100
@@ -273,13 +273,6 @@  #define WORDS_BIG_ENDIAN 1
 
 #define STACK_SIZE_MODE (Pmode)
 
-/* Vector arguments are left-justified when placed on the stack during
-   parameter passing.  */
-#define FUNCTION_ARG_PADDING(MODE, TYPE)			\
-  (s390_function_arg_vector ((MODE), (TYPE))			\
-   ? upward							\
-   : DEFAULT_FUNCTION_ARG_PADDING ((MODE), (TYPE)))
-
 #ifndef IN_LIBGCC2
 
 /* Width of a word, in units (bytes).  */
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/s390/s390.c	2017-08-28 11:03:59.140654650 +0100
@@ -12109,6 +12109,18 @@  s390_function_arg (cumulative_args_t cum
   gcc_unreachable ();
 }
 
+/* Implement TARGET_FUNCTION_ARG_BOUNDARY.  Vector arguments are
+   left-justified when placed on the stack during parameter passing.  */
+
+static pad_direction
+s390_function_arg_padding (machine_mode mode, const_tree type)
+{
+  if (s390_function_arg_vector (mode, type))
+    return PAD_UPWARD;
+
+  return default_function_arg_padding (mode, type);
+}
+
 /* Return true if return values of type TYPE should be returned
    in a memory buffer whose address is passed by the caller as
    hidden first argument.  */
@@ -15825,6 +15837,8 @@  #define TARGET_FUNCTION_OK_FOR_SIBCALL s
 #define TARGET_FUNCTION_ARG s390_function_arg
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE s390_function_arg_advance
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING s390_function_arg_padding
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE s390_function_value
 #undef TARGET_LIBCALL_VALUE
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/sparc/sparc.h	2017-08-28 11:03:59.141660250 +0100
@@ -1215,14 +1215,6 @@  #define CUMULATIVE_ARGS struct sparc_arg
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
 init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL));
 
-/* If defined, a C expression which determines whether, and in which direction,
-   to pad out an argument with extra space.  The value should be of type
-   `enum direction': either `upward' to pad above the argument,
-   `downward' to pad below, or `none' to inhibit padding.  */
-
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
-function_arg_padding ((MODE), (TYPE))
-
 
 /* Generate the special assembly code needed to tell the assembler whatever
    it might need to know about the return value of a function.
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/sparc/sparc-protos.h	2017-08-28 11:03:59.140654650 +0100
@@ -28,10 +28,6 @@  #define __SPARC_PROTOS_H__
 extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
 #endif
 extern unsigned long sparc_type_code (tree);
-#ifdef ARGS_SIZE_RTX
-/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding (machine_mode, const_tree);
-#endif /* ARGS_SIZE_RTX */
 #endif /* TREE_CODE */
 
 extern void order_regs_for_local_alloc (void);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/sparc/sparc.c	2017-08-28 11:03:59.141660250 +0100
@@ -648,6 +648,7 @@  static rtx sparc_function_arg (cumulativ
 			       machine_mode, const_tree, bool);
 static rtx sparc_function_incoming_arg (cumulative_args_t,
 					machine_mode, const_tree, bool);
+static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
 static unsigned int sparc_function_arg_boundary (machine_mode,
 						 const_tree);
 static int sparc_arg_partial_bytes (cumulative_args_t,
@@ -796,6 +797,8 @@  #define TARGET_FUNCTION_ARG_ADVANCE spar
 #define TARGET_FUNCTION_ARG sparc_function_arg
 #undef TARGET_FUNCTION_INCOMING_ARG
 #define TARGET_FUNCTION_INCOMING_ARG sparc_function_incoming_arg
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING sparc_function_arg_padding
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY sparc_function_arg_boundary
 
@@ -7315,18 +7318,17 @@  sparc_function_arg_advance (cumulative_a
     }
 }
 
-/* Handle the FUNCTION_ARG_PADDING macro.
-   For the 64-bit ABI structs are always stored left shifted in their
-   argument slot.  */
+/* Implement TARGET_FUNCTION_ARG_PADDING.  For the 64-bit ABI structs
+   are always stored left shifted in their argument slot.  */
 
-enum direction
-function_arg_padding (machine_mode mode, const_tree type)
+static pad_direction
+sparc_function_arg_padding (machine_mode mode, const_tree type)
 {
   if (TARGET_ARCH64 && type && AGGREGATE_TYPE_P (type))
-    return upward;
+    return PAD_UPWARD;
 
   /* Fall back to the default.  */
-  return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
+  return default_function_arg_padding (mode, type);
 }
 
 /* Handle the TARGET_RETURN_IN_MEMORY target hook.
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/spu/spu.h	2017-08-28 11:03:59.142665850 +0100
@@ -329,8 +329,6 @@  #define FUNCTION_ARG_OFFSET(MODE, TYPE)
  ? (4 - GET_MODE_SIZE (MODE))						\
  : 0)
 
-#define FUNCTION_ARG_PADDING(MODE,TYPE) upward
-
 #define PAD_VARARGS_DOWN 0
 
 #define FUNCTION_ARG_REGNO_P(N) ((N) >= (FIRST_ARG_REGNUM) && (N) <= (LAST_ARG_REGNUM))
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-08-28 11:03:58.526233104 +0100
+++ gcc/config/spu/spu.c	2017-08-28 11:03:59.142665850 +0100
@@ -3876,6 +3876,14 @@  spu_function_arg_advance (cumulative_arg
 	   : HARD_REGNO_NREGS (cum, mode));
 }
 
+/* Implement TARGET_FUNCTION_ARG_PADDING.  */
+
+static pad_direction
+spu_function_arg_padding (machine_mode, const_tree)
+{
+  return PAD_UPWARD;
+}
+
 /* Variable sized types are passed by reference.  */
 static bool
 spu_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
@@ -7268,6 +7276,9 @@  #define TARGET_FUNCTION_ARG spu_function
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance
 
+#undef TARGET_FUNCTION_ARG_PADDING
+#define TARGET_FUNCTION_ARG_PADDING spu_function_arg_padding
+
 #undef TARGET_MUST_PASS_IN_STACK
 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-08-28 11:03:58.526233104 +0100
+++ gcc/system.h	2017-08-28 11:03:59.145682649 +0100
@@ -906,7 +906,7 @@  #define realloc xrealloc
 	CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P		\
 	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD			\
 	HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK		\
-	MODES_TIEABLE_P
+	MODES_TIEABLE_P FUNCTION_ARG_PADDING
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */