Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-15 15:26:09.232205170 +0100
+++ gcc/target.def	2019-08-19 15:58:21.746125942 +0100
@@ -4677,8 +4677,8 @@ compiler when this occurs, and how many
 @code{TARGET_FUNCTION_ARG} for these arguments should return the first\n\
 register to be used by the caller for this argument; likewise\n\
 @code{TARGET_FUNCTION_INCOMING_ARG}, for the called function.",
- int, (cumulative_args_t cum, machine_mode mode, tree type, bool named),
- hook_int_CUMULATIVE_ARGS_mode_tree_bool_0)
+ int, (cumulative_args_t cum, const function_arg_info &arg),
+ hook_int_CUMULATIVE_ARGS_arg_info_0)
 
 /* Update the state in CA to advance past an argument in the
    argument list.  The values MODE, TYPE, and NAMED describe that
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-15 15:26:09.228205200 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:58:21.746125942 +0100
@@ -4057,7 +4057,7 @@ Perform a target dependent initializatio
 This hook is called at the start of register allocation.
 @end deftypefn
 
-@deftypefn {Target Hook} int TARGET_ARG_PARTIAL_BYTES (cumulative_args_t @var{cum}, machine_mode @var{mode}, tree @var{type}, bool @var{named})
+@deftypefn {Target Hook} int TARGET_ARG_PARTIAL_BYTES (cumulative_args_t @var{cum}, const function_arg_info @var{&arg})
 This target hook returns the number of bytes at the beginning of an
 argument that must be put in registers.  The value must be zero for
 arguments that are passed entirely in registers or that are entirely
Index: gcc/target.h
===================================================================
--- gcc/target.h	2019-07-10 19:41:21.619936277 +0100
+++ gcc/target.h	2019-08-19 15:58:21.746125942 +0100
@@ -149,6 +149,9 @@ struct noce_if_info;
 /* This is defined in tree-vectorizer.h.  */
 class _stmt_vec_info;
 
+/* This is defined in calls.h.  */
+class function_arg_info;
+
 /* These are defined in tree-vect-stmts.c.  */
 extern tree stmt_vectype (class _stmt_vec_info *);
 extern bool stmt_in_inner_loop_p (class _stmt_vec_info *);
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:16.094166837 +0100
+++ gcc/calls.h	2019-08-19 15:58:21.714126173 +0100
@@ -20,6 +20,77 @@ Software Foundation; either version 3, o
 #ifndef GCC_CALLS_H
 #define GCC_CALLS_H
 
+/* Describes a function argument.
+
+   Each argument conceptually has a gimple-level type.  Usually this type
+   is available directly as a tree via the TYPE field, but when calling
+   libgcc support functions it might instead be inferred from a mode,
+   in which case the type isn't available directly.
+
+   This gimple-level type might go through promotion before being passed to
+   the target function.  Depending on the context, the MODE field is either
+   the mode of the gimple-level type (whether explicitly given or not)
+   or the mode after promotion has been performed.  */
+class function_arg_info
+{
+public:
+  function_arg_info () : type (NULL_TREE), mode (VOIDmode), named (false) {}
+
+  /* Initialize an argument of mode MODE, either before or after promotion.  */
+  function_arg_info (machine_mode mode, bool named)
+    : type (NULL_TREE), mode (mode), named (named)
+  {}
+
+  /* Initialize an unpromoted argument of type TYPE.  */
+  function_arg_info (tree type, bool named)
+    : type (type), mode (TYPE_MODE (type)), named (named)
+  {}
+
+  /* Initialize an argument with explicit properties.  */
+  function_arg_info (tree type, machine_mode mode, bool named)
+    : type (type), mode (mode), named (named)
+  {}
+
+  /* Return true if the gimple-level type is an aggregate.  */
+  bool aggregate_type_p () const { return type && AGGREGATE_TYPE_P (type); }
+
+  /* Return the size of the gimple-level type, or -1 if the size is
+     variable or otherwise not representable as a poly_int64.
+
+     Use this function when MODE is the mode of the type before promotion,
+     or in any context if the target never promotes function arguments.  */
+  poly_int64 type_size_in_bytes () const
+  {
+    if (type)
+      return int_size_in_bytes (type);
+    return GET_MODE_SIZE (mode);
+  }
+
+  /* Return the size of the argument after promotion, or -1 if the size
+     is variable or otherwise not representable as a poly_int64.
+
+     Use this function when MODE is the mode of the type after promotion.  */
+  poly_int64 promoted_size_in_bytes () const
+  {
+    if (mode == BLKmode)
+      return int_size_in_bytes (type);
+    return GET_MODE_SIZE (mode);
+  }
+
+  /* The type of the argument, or null if not known (which is true for
+     libgcc support functions).  */
+  tree type;
+
+  /* The mode of the argument.  Depending on context, this might be
+     the mode of the argument type or the mode after promotion.  */
+  machine_mode mode;
+
+  /* True if the argument is treated as a named argument, false if it is
+     treated as an unnamed variadic argument (i.e. one passed through
+     "...").  See also TARGET_STRICT_ARGUMENT_NAMING.  */
+  unsigned int named : 1;
+};
+
 extern int flags_from_decl_or_type (const_tree);
 extern int call_expr_flags (const_tree);
 extern int setjmp_call_p (const_tree);
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	2019-08-15 15:26:09.232205170 +0100
+++ gcc/targhooks.h	2019-08-19 15:58:21.746125942 +0100
@@ -137,8 +137,8 @@ extern bool hook_bool_CUMULATIVE_ARGS_tr
   (cumulative_args_t, machine_mode, const_tree, bool);
 extern bool hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
   (cumulative_args_t, machine_mode, const_tree, bool);
-extern int hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
-  (cumulative_args_t, machine_mode, tree, bool);
+extern int hook_int_CUMULATIVE_ARGS_arg_info_0
+  (cumulative_args_t, const function_arg_info &);
 extern void hook_void_CUMULATIVE_ARGS_tree
   (cumulative_args_t, tree);
 extern const char *hook_invalid_arg_for_unprototyped_fn
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/targhooks.c	2019-08-19 15:58:21.746125942 +0100
@@ -768,10 +768,8 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool
 }
 
 int
-hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
-	cumulative_args_t ca ATTRIBUTE_UNUSED,
-	machine_mode mode ATTRIBUTE_UNUSED,
-	tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
+				     const function_arg_info &)
 {
   return 0;
 }
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:16.094166837 +0100
+++ gcc/calls.c	2019-08-19 15:58:21.714126173 +0100
@@ -2142,10 +2142,9 @@ initialize_argument_information (int num
       else
 	args[i].tail_call_reg = args[i].reg;
 
+      function_arg_info arg (type, mode, argpos < n_named_args);
       if (args[i].reg)
-	args[i].partial
-	  = targetm.calls.arg_partial_bytes (args_so_far, mode, type,
-					     argpos < n_named_args);
+	args[i].partial = targetm.calls.arg_partial_bytes (args_so_far, arg);
 
       args[i].pass_on_stack = targetm.calls.must_pass_in_stack (mode, type);
 
@@ -4871,10 +4870,10 @@ emit_library_call_value_1 (int retval, r
       argvec[count].mode = Pmode;
       argvec[count].partial = 0;
 
+      function_arg_info ptr_arg (Pmode, /*named=*/true);
       argvec[count].reg = targetm.calls.function_arg (args_so_far,
 						      Pmode, NULL_TREE, true);
-      gcc_assert (targetm.calls.arg_partial_bytes (args_so_far, Pmode,
-						   NULL_TREE, 1) == 0);
+      gcc_assert (targetm.calls.arg_partial_bytes (args_so_far, ptr_arg) == 0);
 
       locate_and_pad_parm (Pmode, NULL_TREE,
 #ifdef STACK_PARMS_IN_REG_PARM_AREA
@@ -4952,13 +4951,14 @@ emit_library_call_value_1 (int retval, r
 	}
 
       mode = promote_function_mode (NULL_TREE, mode, &unsigned_p, NULL_TREE, 0);
+      function_arg_info arg (mode, /*named=*/true);
       argvec[count].mode = mode;
       argvec[count].value = convert_modes (mode, GET_MODE (val), val, unsigned_p);
       argvec[count].reg = targetm.calls.function_arg (args_so_far, mode,
 						      NULL_TREE, true);
 
       argvec[count].partial
-	= targetm.calls.arg_partial_bytes (args_so_far, mode, NULL_TREE, 1);
+	= targetm.calls.arg_partial_bytes (args_so_far, arg);
 
       if (argvec[count].reg == 0
 	  || argvec[count].partial != 0
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2019-07-16 09:11:06.105419196 +0100
+++ gcc/expr.c	2019-08-19 15:58:21.746125942 +0100
@@ -1709,11 +1709,12 @@ block_move_libcall_safe_for_call_parm (v
     for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
       {
 	machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
+	function_arg_info arg_info (mode, /*named=*/true);
 	rtx tmp = targetm.calls.function_arg (args_so_far, mode,
 					      NULL_TREE, true);
 	if (!tmp || !REG_P (tmp))
 	  return false;
-	if (targetm.calls.arg_partial_bytes (args_so_far, mode, NULL, 1))
+	if (targetm.calls.arg_partial_bytes (args_so_far, arg_info))
 	  return false;
 	targetm.calls.function_arg_advance (args_so_far, mode,
 					    NULL_TREE, true);
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-15 15:26:04.772237567 +0100
+++ gcc/function.c	2019-08-19 15:58:21.746125942 +0100
@@ -2559,10 +2559,9 @@ assign_parm_find_entry_rtl (struct assig
     {
       int partial;
 
-      partial = targetm.calls.arg_partial_bytes (all->args_so_far,
-						 data->promoted_mode,
-						 data->passed_type,
-						 data->named_arg);
+      function_arg_info arg (data->passed_type, data->promoted_mode,
+			     data->named_arg);
+      partial = targetm.calls.arg_partial_bytes (all->args_so_far, arg);
       data->partial = partial;
 
       /* The caller might already have allocated stack space for the
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:16.094166837 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:58:21.718126146 +0100
@@ -5635,20 +5635,17 @@ alpha_function_arg_advance (cumulative_a
 }
 
 static int
-alpha_arg_partial_bytes (cumulative_args_t cum_v,
-			 machine_mode mode ATTRIBUTE_UNUSED,
-			 tree type ATTRIBUTE_UNUSED,
-			 bool named ATTRIBUTE_UNUSED)
+alpha_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   int words = 0;
   CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED = get_cumulative_args (cum_v);
 
 #if TARGET_ABI_OPEN_VMS
   if (cum->num_args < 6
-      && 6 < cum->num_args + ALPHA_ARG_SIZE (mode, type))
+      && 6 < cum->num_args + ALPHA_ARG_SIZE (arg.mode, arg.type))
     words = 6 - cum->num_args;
 #elif TARGET_ABI_OSF
-  if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (mode, type))
+  if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (arg.mode, arg.type))
     words = 6 - *cum;
 #else
 #error Unhandled ABI
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c	2019-08-13 22:35:11.721252311 +0100
+++ gcc/config/arc/arc.c	2019-08-19 15:58:21.718126146 +0100
@@ -6432,17 +6432,15 @@ #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO
 /* Implement TARGET_ARG_PARTIAL_BYTES.  */
 
 static int
-arc_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-		       tree type, bool named ATTRIBUTE_UNUSED)
+arc_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  int bytes = (mode == BLKmode
-	       ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
+  int bytes = arg.promoted_size_in_bytes ();
   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   int arg_num = *cum;
   int ret;
 
-  arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
+  arg_num = ROUND_ADVANCE_CUM (arg_num, arg.mode, arg.type);
   ret = GPR_REST_ARG_REGS (arg_num);
 
   /* ICEd at function.c:2361, and ret is copied to data->partial */
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-07-10 19:41:36.755815057 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:58:21.726126086 +0100
@@ -187,8 +187,8 @@ static int arm_memory_move_cost (machine
 static void emit_constant_insn (rtx cond, rtx pattern);
 static rtx_insn *emit_set_insn (rtx, rtx);
 static rtx emit_multi_reg_push (unsigned long, unsigned long);
-static int arm_arg_partial_bytes (cumulative_args_t, machine_mode,
-				  tree, bool);
+static int arm_arg_partial_bytes (cumulative_args_t,
+				  const function_arg_info &);
 static rtx arm_function_arg (cumulative_args_t, machine_mode,
 			     const_tree, bool);
 static void arm_function_arg_advance (cumulative_args_t, machine_mode,
@@ -6754,23 +6754,22 @@ arm_function_arg_boundary (machine_mode
 }
 
 static int
-arm_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode,
-		       tree type, bool named)
+arm_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
   int nregs = pcum->nregs;
 
   if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
     {
-      aapcs_layout_arg (pcum, mode, type, named);
+      aapcs_layout_arg (pcum, arg.mode, arg.type, arg.named);
       return pcum->aapcs_partial;
     }
 
-  if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode))
+  if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (arg.mode))
     return 0;
 
   if (NUM_ARG_REGS > nregs
-      && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type))
+      && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (arg.mode, arg.type))
       && pcum->can_split)
     return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
 
@@ -6999,11 +6998,11 @@ cmse_func_args_or_return_in_stack (tree
       if (VOID_TYPE_P (arg_type))
 	continue;
 
+      function_arg_info arg (arg_type, /*named=*/true);
       if (!first_param)
 	arm_function_arg_advance (args_so_far, arg_mode, arg_type, true);
       arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true);
-      if (!arg_rtx
-	  || arm_arg_partial_bytes (args_so_far, arg_mode, arg_type, true))
+      if (!arg_rtx || arm_arg_partial_bytes (args_so_far, arg))
 	{
 	  error ("%qE attribute not available to functions with arguments "
 		 "passed on the stack", name);
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	2019-08-13 22:35:11.729252254 +0100
+++ gcc/config/bfin/bfin.c	2019-08-19 15:58:21.726126086 +0100
@@ -1723,12 +1723,9 @@ bfin_function_arg (cumulative_args_t cum
    stack.   */
 
 static int
-bfin_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
-			tree type ATTRIBUTE_UNUSED,
-			bool named ATTRIBUTE_UNUSED)
+bfin_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
 {
-  int bytes
-    = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+  int bytes = arg.promoted_size_in_bytes ();
   int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
   
   if (bytes == -1)
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-05-29 10:49:36.676710232 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:58:21.726126086 +0100
@@ -141,8 +141,8 @@ static bool cris_rtx_costs (rtx, machine
 static int cris_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool cris_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
-static int cris_arg_partial_bytes (cumulative_args_t, machine_mode,
-				   tree, bool);
+static int cris_arg_partial_bytes (cumulative_args_t,
+				   const function_arg_info &);
 static rtx cris_function_arg (cumulative_args_t, machine_mode,
 			      const_tree, bool);
 static rtx cris_function_incoming_arg (cumulative_args_t,
@@ -4111,13 +4111,12 @@ cris_function_value_regno_p (const unsig
 }
 
 static int
-cris_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
-			tree type, bool named ATTRIBUTE_UNUSED)
+cris_arg_partial_bytes (cumulative_args_t ca, const function_arg_info &arg)
 {
   if (get_cumulative_args (ca)->regs == CRIS_MAX_ARGS_IN_REGS - 1
-      && !targetm.calls.must_pass_in_stack (mode, type)
-      && CRIS_FUNCTION_ARG_SIZE (mode, type) > 4
-      && CRIS_FUNCTION_ARG_SIZE (mode, type) <= 8)
+      && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+      && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 4
+      && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) <= 8)
     return UNITS_PER_WORD;
   else
     return 0;
Index: gcc/config/csky/csky.c
===================================================================
--- gcc/config/csky/csky.c	2019-05-29 10:49:36.968709386 +0100
+++ gcc/config/csky/csky.c	2019-08-19 15:58:21.726126086 +0100
@@ -1917,11 +1917,10 @@ csky_return_addr (int count, rtx frame A
    that are passed entirely in registers or
    that are entirely pushed on the stack.  */
 static int
-csky_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode,
-			tree type, bool named ATTRIBUTE_UNUSED)
+csky_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
-  int param_size = csky_num_arg_regs (mode, type);
+  int param_size = csky_num_arg_regs (arg.mode, arg.type);
 
   if (*pcum < CSKY_NPARM_REGS
       && *pcum + param_size > CSKY_NPARM_REGS)
Index: gcc/config/epiphany/epiphany.c
===================================================================
--- gcc/config/epiphany/epiphany.c	2019-05-29 10:49:36.648710313 +0100
+++ gcc/config/epiphany/epiphany.c	2019-08-19 15:58:21.730126059 +0100
@@ -744,18 +744,20 @@ epiphany_setup_incoming_varargs (cumulat
 }
 
 static int
-epiphany_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
-			    tree type, bool named ATTRIBUTE_UNUSED)
+epiphany_arg_partial_bytes (cumulative_args_t cum,
+			    const function_arg_info &arg)
 {
   int words = 0, rounded_cum;
 
-  gcc_assert (!epiphany_pass_by_reference (cum, mode, type, /* named */ true));
+  gcc_assert (!epiphany_pass_by_reference (cum, arg.mode, arg.type,
+					   arg.named));
 
-  rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum), mode, type);
+  rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum),
+				   arg.mode, arg.type);
   if (rounded_cum < MAX_EPIPHANY_PARM_REGS)
     {
       words = MAX_EPIPHANY_PARM_REGS - rounded_cum;
-      if (words >= ROUND_ADVANCE_ARG (mode, type))
+      if (words >= ROUND_ADVANCE_ARG (arg.mode, arg.type))
 	words = 0;
     }
   return words * UNITS_PER_WORD;
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-03-08 18:15:37.772736275 +0000
+++ gcc/config/fr30/fr30.c	2019-08-19 15:58:21.730126059 +0100
@@ -39,6 +39,7 @@ #define IN_TARGET_CODE 1
 #include "output.h"
 #include "expr.h"
 #include "builtins.h"
+#include "calls.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -115,8 +116,8 @@ struct fr30_frame_info
 static void fr30_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					 tree, int *, int);
 static bool fr30_must_pass_in_stack (machine_mode, const_tree);
-static int fr30_arg_partial_bytes (cumulative_args_t, machine_mode,
-				   tree, bool);
+static int fr30_arg_partial_bytes (cumulative_args_t,
+				   const function_arg_info &);
 static rtx fr30_function_arg (cumulative_args_t, machine_mode,
 			      const_tree, bool);
 static void fr30_function_arg_advance (cumulative_args_t, machine_mode,
@@ -770,23 +771,20 @@ fr30_num_arg_regs (machine_mode mode, co
   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 }
 
-/* Returns the number of bytes in which *part* of a parameter of machine
-   mode MODE and tree type TYPE (which may be NULL if the type is not known).
-   If the argument fits entirely in the argument registers, or entirely on
-   the stack, then 0 is returned.
-   CUM is the number of argument registers already used by earlier
-   parameters to the function.  */
+/* Returns the number of bytes of argument registers required to hold *part*
+   of argument ARG.  If the argument fits entirely in the argument registers,
+   or entirely on the stack, then 0 is returned.  CUM is the number of
+   argument registers already used by earlier parameters to the function.  */
 
 static int
-fr30_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			tree type, bool named)
+fr30_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   /* Unnamed arguments, i.e. those that are prototyped as ...
      are always passed on the stack.
      Also check here to see if all the argument registers are full.  */
-  if (named == 0 || *cum >= FR30_NUM_ARG_REGS)
+  if (!arg.named || *cum >= FR30_NUM_ARG_REGS)
     return 0;
 
   /* Work out how many argument registers would be needed if this
@@ -795,7 +793,7 @@ fr30_arg_partial_bytes (cumulative_args_
      are needed because the parameter must be passed on the stack)
      then return zero, as this parameter does not require partial
      register, partial stack stack space.  */
-  if (*cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS)
+  if (*cum + fr30_num_arg_regs (arg.mode, arg.type) <= FR30_NUM_ARG_REGS)
     return 0;
   
   return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-13 22:35:11.729252254 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:58:21.730126059 +0100
@@ -49,6 +49,7 @@ #define IN_TARGET_CODE 1
 #include "builtins.h"
 #include "ifcvt.h"
 #include "rtl-iter.h"
+#include "calls.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -379,8 +380,8 @@ static void frv_output_const_unspec		(FI
 static bool frv_function_ok_for_sibcall		(tree, tree);
 static rtx frv_struct_value_rtx			(tree, int);
 static bool frv_must_pass_in_stack (machine_mode mode, const_tree type);
-static int frv_arg_partial_bytes (cumulative_args_t, machine_mode,
-				  tree, bool);
+static int frv_arg_partial_bytes (cumulative_args_t,
+				  const function_arg_info &);
 static rtx frv_function_arg (cumulative_args_t, machine_mode,
 			     const_tree, bool);
 static rtx frv_function_incoming_arg (cumulative_args_t, machine_mode,
@@ -3183,28 +3184,12 @@ frv_function_arg_advance (cumulative_arg
 }
 
 
-/* A C expression for the number of words, at the beginning of an argument,
-   must be put in registers.  The value must be zero for arguments that are
-   passed entirely in registers or that are entirely pushed on the stack.
-
-   On some machines, certain arguments must be passed partially in registers
-   and partially in memory.  On these machines, typically the first N words of
-   arguments are passed in registers, and the rest on the stack.  If a
-   multi-word argument (a `double' or a structure) crosses that boundary, its
-   first few words must be passed in registers and the rest must be pushed.
-   This macro tells the compiler when this occurs, and how many of the words
-   should go in registers.
-
-   `FUNCTION_ARG' for these arguments should return the first register to be
-   used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
-   the called function.  */
+/* Implement TARGET_ARG_PARTIAL_BYTES.  */
 
 static int
-frv_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
-		       tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+frv_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
 {
-
-  machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+  machine_mode xmode = (arg.mode == BLKmode) ? SImode : arg.mode;
   int bytes = GET_MODE_SIZE (xmode);
   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   int arg_num = *get_cumulative_args (cum);
Index: gcc/config/ft32/ft32.c
===================================================================
--- gcc/config/ft32/ft32.c	2019-04-08 21:55:28.370369171 +0100
+++ gcc/config/ft32/ft32.c	2019-08-19 15:58:21.730126059 +0100
@@ -711,8 +711,7 @@ ft32_pass_by_reference (cumulative_args_
    that fit in argument passing registers.  */
 
 static int
-ft32_arg_partial_bytes (cumulative_args_t cum_v,
-                        machine_mode mode, tree type, bool named)
+ft32_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int bytes_left, size;
@@ -720,16 +719,16 @@ ft32_arg_partial_bytes (cumulative_args_
   if (*cum >= 8)
     return 0;
 
-  if (ft32_pass_by_reference (cum_v, mode, type, named))
+  if (ft32_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
     size = 4;
-  else if (type)
+  else if (arg.type)
     {
-      if (AGGREGATE_TYPE_P (type))
+      if (AGGREGATE_TYPE_P (arg.type))
         return 0;
-      size = int_size_in_bytes (type);
+      size = int_size_in_bytes (arg.type);
     }
   else
-    size = GET_MODE_SIZE (mode);
+    size = GET_MODE_SIZE (arg.mode);
 
   bytes_left = (4 * 6) - ((*cum - 2) * 4);
 
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:10.750205506 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:58:21.730126059 +0100
@@ -2349,22 +2349,21 @@ gcn_function_arg_advance (cumulative_arg
    in registers or that are entirely pushed on the stack.  */
 
 static int
-gcn_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, tree type,
-		       bool named)
+gcn_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (!named)
+  if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return 0;
 
   if (cum->num >= NUM_PARM_REGS)
     return 0;
 
   /* If the argument fits entirely in registers, return 0.  */
-  if (cum->num + num_arg_regs (mode, type) <= NUM_PARM_REGS)
+  if (cum->num + num_arg_regs (arg.mode, arg.type) <= NUM_PARM_REGS)
     return 0;
 
   return (NUM_PARM_REGS - cum->num) * UNITS_PER_WORD;
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	2019-08-19 15:58:10.754205475 +0100
+++ gcc/config/ia64/ia64.c	2019-08-19 15:58:21.734126028 +0100
@@ -201,8 +201,8 @@ static bool ia64_can_eliminate (const in
 static machine_mode hfa_element_mode (const_tree, bool);
 static void ia64_setup_incoming_varargs (cumulative_args_t, machine_mode,
 					 tree, int *, int);
-static int ia64_arg_partial_bytes (cumulative_args_t, machine_mode,
-				   tree, bool);
+static int ia64_arg_partial_bytes (cumulative_args_t,
+				   const function_arg_info &);
 static rtx ia64_function_arg_1 (cumulative_args_t, machine_mode,
 				const_tree, bool, bool);
 static rtx ia64_function_arg (cumulative_args_t, machine_mode,
@@ -4961,13 +4961,12 @@ ia64_function_incoming_arg (cumulative_a
    in memory.  */
 
 static int
-ia64_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			tree type, bool named ATTRIBUTE_UNUSED)
+ia64_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  int words = ia64_function_arg_words (type, mode);
-  int offset = ia64_function_arg_offset (cum, type, words);
+  int words = ia64_function_arg_words (arg.type, arg.mode);
+  int offset = ia64_function_arg_offset (cum, arg.type, words);
 
   /* If all argument slots are used, then it must go on the stack.  */
   if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-13 22:35:11.741252166 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:58:21.734126028 +0100
@@ -161,8 +161,8 @@ static section *iq2000_select_section (t
 static rtx  iq2000_legitimize_address (rtx, rtx, machine_mode);
 static bool iq2000_pass_by_reference  (cumulative_args_t, machine_mode,
 				       const_tree, bool);
-static int  iq2000_arg_partial_bytes  (cumulative_args_t, machine_mode,
-				       tree, bool);
+static int  iq2000_arg_partial_bytes  (cumulative_args_t,
+				       const function_arg_info &arg);
 static rtx iq2000_function_arg	      (cumulative_args_t,
 				       machine_mode, const_tree, bool);
 static void iq2000_function_arg_advance (cumulative_args_t,
@@ -1421,13 +1421,12 @@ iq2000_function_arg_boundary (machine_mo
 }
 
 static int
-iq2000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			  tree type ATTRIBUTE_UNUSED,
-			  bool named ATTRIBUTE_UNUSED)
+iq2000_arg_partial_bytes (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
+  if (arg.mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
     {
       if (TARGET_DEBUG_D_MODE)
 	fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	2019-07-01 09:37:06.080534032 +0100
+++ gcc/config/m32r/m32r.c	2019-08-19 15:58:21.734126028 +0100
@@ -93,8 +93,8 @@ static bool m32r_rtx_costs (rtx, machine
 static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
 static bool m32r_pass_by_reference (cumulative_args_t, machine_mode,
 				    const_tree, bool);
-static int m32r_arg_partial_bytes (cumulative_args_t, machine_mode,
-				   tree, bool);
+static int m32r_arg_partial_bytes (cumulative_args_t,
+				   const function_arg_info &);
 static rtx m32r_function_arg (cumulative_args_t, machine_mode,
 			      const_tree, bool);
 static void m32r_function_arg_advance (cumulative_args_t, machine_mode,
@@ -1164,17 +1164,13 @@ gen_split_move_double (rtx operands[])
 
 
 static int
-m32r_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			tree type, bool named ATTRIBUTE_UNUSED)
+m32r_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   int words;
   unsigned int size =
-    (((mode == BLKmode && type)
-      ? (unsigned int) int_size_in_bytes (type)
-      : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
-    / UNITS_PER_WORD;
+    (arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
   if (*cum >= M32R_MAX_PARM_REGS)
     words = 0;
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-03-08 18:15:38.512733464 +0000
+++ gcc/config/mcore/mcore.c	2019-08-19 15:58:21.734126028 +0100
@@ -129,8 +129,7 @@ static bool       mcore_rtx_costs		(rtx,
 static void       mcore_external_libcall	(rtx);
 static bool       mcore_return_in_memory	(const_tree, const_tree);
 static int        mcore_arg_partial_bytes       (cumulative_args_t,
-						 machine_mode,
-						 tree, bool);
+						 const function_arg_info &);
 static rtx        mcore_function_arg            (cumulative_args_t,
 						 machine_mode,
 						 const_tree, bool);
@@ -2841,22 +2840,19 @@ mcore_function_arg_boundary (machine_mod
 }
 
 /* Returns the number of bytes of argument registers required to hold *part*
-   of a parameter of machine mode MODE and type TYPE (which may be NULL if
-   the type is not known).  If the argument fits entirely in the argument
-   registers, or entirely on the stack, then 0 is returned.  CUM is the
-   number of argument registers already used by earlier parameters to
-   the function.  */
+   of argument ARG.  If the argument fits entirely in the argument registers,
+   or entirely on the stack, then 0 is returned.  CUM is the number of
+   argument registers already used by earlier parameters to the function.  */
 
 static int
-mcore_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
-			 tree type, bool named)
+mcore_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
 {
-  int reg = ROUND_REG (*get_cumulative_args (cum), mode);
+  int reg = ROUND_REG (*get_cumulative_args (cum), arg.mode);
 
-  if (named == 0)
+  if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
     return 0;
       
   /* REG is not the *hardware* register number of the register that holds
@@ -2871,7 +2867,7 @@ mcore_arg_partial_bytes (cumulative_args
     return 0;
 
   /* If the argument fits entirely in registers, return 0.  */
-  if (reg + mcore_num_arg_regs (mode, type) <= NPARM_REGS)
+  if (reg + mcore_num_arg_regs (arg.mode, arg.type) <= NPARM_REGS)
     return 0;
 
   /* The argument overflows the number of available argument registers.
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2019-07-01 09:37:06.516530382 +0100
+++ gcc/config/microblaze/microblaze.c	2019-08-19 15:58:21.734126028 +0100
@@ -1653,30 +1653,25 @@ microblaze_function_arg (cumulative_args
 
 /* Return number of bytes of argument to put in registers. */
 static int
-function_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,	
-			    tree type, bool named ATTRIBUTE_UNUSED)	
+function_arg_partial_bytes (cumulative_args_t cum_v,
+			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if ((mode == BLKmode
-       || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
-       || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
+  if ((arg.mode == BLKmode
+       || GET_MODE_CLASS (arg.mode) != MODE_COMPLEX_INT
+       || GET_MODE_CLASS (arg.mode) != MODE_COMPLEX_FLOAT)
       && cum->arg_words < MAX_ARGS_IN_REGISTERS)
     {
-      int words;
-      if (mode == BLKmode)
-	words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
-		 / UNITS_PER_WORD);
-      else
-	words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-
+      int words = ((arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1)
+		   / UNITS_PER_WORD);
       if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
 	return 0;		/* structure fits in registers */
 
       return (MAX_ARGS_IN_REGISTERS - cum->arg_words) * UNITS_PER_WORD;
     }
 
-  else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
+  else if (arg.mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
     return UNITS_PER_WORD;
 
   return 0;
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:10.758205447 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:58:21.738126000 +0100
@@ -6140,12 +6140,12 @@ mips_function_arg_advance (cumulative_ar
 /* Implement TARGET_ARG_PARTIAL_BYTES.  */
 
 static int
-mips_arg_partial_bytes (cumulative_args_t cum,
-			machine_mode mode, tree type, bool named)
+mips_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
 {
   struct mips_arg_info info;
 
-  mips_get_arg_info (&info, get_cumulative_args (cum), mode, type, named);
+  mips_get_arg_info (&info, get_cumulative_args (cum),
+		     arg.mode, arg.type, arg.named);
   return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
 }
 
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	2019-05-29 10:49:36.680710222 +0100
+++ gcc/config/mn10300/mn10300.c	2019-08-19 15:58:21.738126000 +0100
@@ -1607,8 +1607,8 @@ mn10300_function_arg_advance (cumulative
    partially in registers and partially in memory.  */
 
 static int
-mn10300_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			   tree type, bool named ATTRIBUTE_UNUSED)
+mn10300_arg_partial_bytes (cumulative_args_t cum_v,
+			   const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int size;
@@ -1617,11 +1617,7 @@ mn10300_arg_partial_bytes (cumulative_ar
   int nregs = 2;
 
   /* Figure out the size of the object to be passed.  */
-  if (mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  size = arg.promoted_size_in_bytes ();
   cum->nbytes = (cum->nbytes + 3) & ~3;
 
   /* Don't pass this arg via a register if all the argument registers
@@ -1634,7 +1630,7 @@ mn10300_arg_partial_bytes (cumulative_ar
 
   /* Don't pass this arg via a register if it would be split between
      registers and memory.  */
-  if (type == NULL_TREE
+  if (arg.type == NULL_TREE
       && cum->nbytes + size > nregs * UNITS_PER_WORD)
     return 0;
 
Index: gcc/config/moxie/moxie.c
===================================================================
--- gcc/config/moxie/moxie.c	2019-03-08 18:15:37.800736169 +0000
+++ gcc/config/moxie/moxie.c	2019-08-19 15:58:21.738126000 +0100
@@ -478,9 +478,7 @@ moxie_pass_by_reference (cumulative_args
    that fit in argument passing registers.  */
 
 static int
-moxie_arg_partial_bytes (cumulative_args_t cum_v,
-			 machine_mode mode,
-			 tree type, bool named)
+moxie_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int bytes_left, size;
@@ -488,16 +486,16 @@ moxie_arg_partial_bytes (cumulative_args
   if (*cum >= 8)
     return 0;
 
-  if (moxie_pass_by_reference (cum_v, mode, type, named))
+  if (moxie_pass_by_reference (cum_v, arg.mode, arg.type, arg.named))
     size = 4;
-  else if (type)
+  else if (arg.type)
     {
-      if (AGGREGATE_TYPE_P (type))
+      if (AGGREGATE_TYPE_P (arg.type))
 	return 0;
-      size = int_size_in_bytes (type);
+      size = int_size_in_bytes (arg.type);
     }
   else
-    size = GET_MODE_SIZE (mode);
+    size = GET_MODE_SIZE (arg.mode);
 
   bytes_left = (4 * 6) - ((*cum - 2) * 4);
 
Index: gcc/config/msp430/msp430.c
===================================================================
--- gcc/config/msp430/msp430.c	2019-08-19 15:58:10.758205447 +0100
+++ gcc/config/msp430/msp430.c	2019-08-19 15:58:21.738126000 +0100
@@ -728,14 +728,11 @@ msp430_function_arg (cumulative_args_t c
 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
 
 int
-msp430_arg_partial_bytes (cumulative_args_t cap,
-			  machine_mode mode,
-			  tree type,
-			  bool named)
+msp430_arg_partial_bytes (cumulative_args_t cap, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
 
-  msp430_evaluate_arg (cap, mode, type, named);
+  msp430_evaluate_arg (cap, arg.mode, arg.type, arg.named);
 
   if (ca->reg_count && ca->mem_count)
     return ca->reg_count * UNITS_PER_WORD;
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-05-29 10:49:36.604710441 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:58:21.738126000 +0100
@@ -1963,8 +1963,7 @@ nds32_must_pass_in_stack (machine_mode m
 }
 
 static int
-nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
-			 tree type, bool named ATTRIBUTE_UNUSED)
+nds32_arg_partial_bytes (cumulative_args_t ca, const function_arg_info &arg)
 {
   /* Returns the number of bytes at the beginning of an argument that
      must be put in registers.  The value must be zero for arguments that are
@@ -1985,18 +1984,19 @@ nds32_arg_partial_bytes (cumulative_args
 
   /* If we have already runned out of argument registers, return zero
      so that the argument will be entirely pushed on the stack.  */
-  if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
+  if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, arg.mode, arg.type)
       >= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS)
     return 0;
 
   /* Calculate how many registers do we need for this argument.  */
-  needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (mode, type);
+  needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (arg.mode, arg.type);
 
   /* Calculate how many argument registers have left for passing argument.
      Note that we should count it from next available register number.  */
   remaining_reg_count
     = NDS32_MAX_GPR_REGS_FOR_ARGS
-      - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
+      - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset,
+					     arg.mode, arg.type)
 	 - NDS32_GPR_ARG_FIRST_REGNUM);
 
   /* Note that we have to return the nubmer of bytes, not registers count.  */
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/nios2/nios2.c	2019-08-19 15:58:21.738126000 +0100
@@ -3390,20 +3390,11 @@ nios2_function_arg (cumulative_args_t cu
    in memory.  */
 
 static int
-nios2_arg_partial_bytes (cumulative_args_t cum_v,
-                         machine_mode mode, tree type ATTRIBUTE_UNUSED,
-                         bool named ATTRIBUTE_UNUSED)
+nios2_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 
-  HOST_WIDE_INT param_size;
-
-  if (mode == BLKmode)
-    {
-      param_size = int_size_in_bytes (type);
-      gcc_assert (param_size >= 0);
-    }
-  else
-    param_size = GET_MODE_SIZE (mode);
+  HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
+  gcc_assert (param_size >= 0);
 
   /* Convert to words (round up).  */
   param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	2019-08-19 15:58:10.762205420 +0100
+++ gcc/config/pa/pa.c	2019-08-19 15:58:21.738126000 +0100
@@ -166,8 +166,7 @@ static void pa_init_libfuncs (void);
 static rtx pa_struct_value_rtx (tree, int);
 static bool pa_pass_by_reference (cumulative_args_t, machine_mode,
 				  const_tree, bool);
-static int pa_arg_partial_bytes (cumulative_args_t, machine_mode,
-				 tree, bool);
+static int pa_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
 static void pa_function_arg_advance (cumulative_args_t, machine_mode,
 				     const_tree, bool);
 static rtx pa_function_arg (cumulative_args_t, machine_mode,
@@ -9685,8 +9684,7 @@ pa_function_arg_boundary (machine_mode m
    then this routine should return zero.  */
 
 static int
-pa_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-		      tree type, bool named ATTRIBUTE_UNUSED)
+pa_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   unsigned int max_arg_words = 8;
@@ -9695,10 +9693,11 @@ pa_arg_partial_bytes (cumulative_args_t
   if (!TARGET_64BIT)
     return 0;
 
-  if (pa_function_arg_size (mode, type) > 1 && (cum->words & 1))
+  if (pa_function_arg_size (arg.mode, arg.type) > 1 && (cum->words & 1))
     offset = 1;
 
-  if (cum->words + offset + pa_function_arg_size (mode, type) <= max_arg_words)
+  if (cum->words + offset + pa_function_arg_size (arg.mode, arg.type)
+      <= max_arg_words)
     /* Arg fits fully into registers.  */
     return 0;
   else if (cum->words + offset >= max_arg_words)
Index: gcc/config/pru/pru.c
===================================================================
--- gcc/config/pru/pru.c	2019-08-13 22:35:11.749252108 +0100
+++ gcc/config/pru/pru.c	2019-08-19 15:58:21.738126000 +0100
@@ -2179,10 +2179,7 @@ pru_function_arg (cumulative_args_t cum_
    between registers and memory, so we can return 0.  */
 
 static int
-pru_arg_partial_bytes (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
-		       machine_mode mode ATTRIBUTE_UNUSED,
-		       tree type ATTRIBUTE_UNUSED,
-		       bool named ATTRIBUTE_UNUSED)
+pru_arg_partial_bytes (cumulative_args_t, const function_arg_info &)
 {
   return 0;
 }
Index: gcc/config/riscv/riscv.c
===================================================================
--- gcc/config/riscv/riscv.c	2019-08-09 09:31:25.661331004 +0100
+++ gcc/config/riscv/riscv.c	2019-08-19 15:58:21.738126000 +0100
@@ -2778,11 +2778,12 @@ riscv_function_arg_advance (cumulative_a
 
 static int
 riscv_arg_partial_bytes (cumulative_args_t cum,
-			 machine_mode mode, tree type, bool named)
+			 const function_arg_info &generic_arg)
 {
   struct riscv_arg_info arg;
 
-  riscv_get_arg_info (&arg, get_cumulative_args (cum), mode, type, named, false);
+  riscv_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode,
+		      generic_arg.type, generic_arg.named, false);
   return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0;
 }
 
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-07-29 09:39:47.206185758 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:21.742125973 +0100
@@ -159,9 +159,8 @@ extern void setup_incoming_varargs (cumu
 extern unsigned int rs6000_function_arg_boundary (machine_mode mode,
 						  const_tree type);
 extern bool rs6000_must_pass_in_stack (machine_mode mode, const_tree type);
-extern int rs6000_arg_partial_bytes (cumulative_args_t cum_v,
-				     machine_mode mode, tree type,
-				     bool named);
+extern int rs6000_arg_partial_bytes (cumulative_args_t,
+				     const function_arg_info &);
 extern void rs6000_function_arg_advance (cumulative_args_t cum,
 					 machine_mode mode,
 					 const_tree type, bool named);
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:10.762205420 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:21.742125973 +0100
@@ -2007,8 +2007,8 @@ rs6000_function_arg (cumulative_args_t c
    returns the number of bytes used by the first element of the PARALLEL.  */
 
 int
-rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-			  tree type, bool named)
+rs6000_arg_partial_bytes (cumulative_args_t cum_v,
+			  const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   bool passed_in_gprs = true;
@@ -2017,12 +2017,13 @@ rs6000_arg_partial_bytes (cumulative_arg
   machine_mode elt_mode;
   int n_elts;
 
-  rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts);
+  rs6000_discover_homogeneous_aggregate (arg.mode, arg.type,
+					 &elt_mode, &n_elts);
 
   if (DEFAULT_ABI == ABI_V4)
     return 0;
 
-  if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
+  if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, arg.named))
     {
       /* If we are passing this arg in the fixed parameter save area (gprs or
          memory) as well as VRs, we do not use the partial bytes mechanism;
@@ -2041,14 +2042,13 @@ rs6000_arg_partial_bytes (cumulative_arg
     }
 
   /* In this complicated case we just disable the partial_nregs code.  */
-  if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type))
+  if (TARGET_MACHO && rs6000_darwin64_struct_check_p (arg.mode, arg.type))
     return 0;
 
-  align_words = rs6000_parm_start (mode, type, cum->words);
+  align_words = rs6000_parm_start (arg.mode, arg.type, cum->words);
 
   if (USE_FP_FOR_ARG_P (cum, elt_mode)
-      && !(TARGET_AIX && !TARGET_ELF
-	   && type != NULL && AGGREGATE_TYPE_P (type)))
+      && !(TARGET_AIX && !TARGET_ELF && arg.aggregate_type_p ()))
     {
       unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3;
 
@@ -2056,7 +2056,7 @@ rs6000_arg_partial_bytes (cumulative_arg
          (gprs or memory) as well as FPRs, we do not use the partial
 	 bytes mechanism; instead, rs6000_function_arg will return a
 	 PARALLEL including a memory element as necessary.  */
-      if (type
+      if (arg.type
 	  && (cum->nargs_prototype <= 0
 	      || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
 		  && TARGET_XL_COMPAT
@@ -2087,7 +2087,7 @@ rs6000_arg_partial_bytes (cumulative_arg
 
   if (passed_in_gprs
       && align_words < GP_ARG_NUM_REG
-      && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
+      && GP_ARG_NUM_REG < align_words + rs6000_arg_size (arg.mode, arg.type))
     ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8);
 
   if (ret != 0 && TARGET_DEBUG_ARG)
@@ -2222,7 +2222,8 @@ rs6000_parm_needs_stack (cumulative_args
     return true;
 
   /* Also true if we're partially in registers and partially not.  */
-  if (rs6000_arg_partial_bytes (args_so_far, mode, type, true) != 0)
+  function_arg_info arg (type, mode, /*named=*/true);
+  if (rs6000_arg_partial_bytes (args_so_far, arg) != 0)
     return true;
 
   /* Update info on where next arg arrives in registers.  */
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:16.098166809 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:58:21.742125973 +0100
@@ -298,8 +298,7 @@ static bool sh_pass_by_reference (cumula
 				  const_tree, bool);
 static bool sh_callee_copies (cumulative_args_t, machine_mode,
 			      const_tree, bool);
-static int sh_arg_partial_bytes (cumulative_args_t, machine_mode,
-			         tree, bool);
+static int sh_arg_partial_bytes (cumulative_args_t, const function_arg_info &);
 static void sh_function_arg_advance (cumulative_args_t, machine_mode,
 				     const_tree, bool);
 static rtx sh_function_arg (cumulative_args_t, machine_mode,
@@ -7992,20 +7991,17 @@ sh_pass_in_reg_p (const CUMULATIVE_ARGS&
 }
 
 static int
-sh_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-		      tree type, bool named ATTRIBUTE_UNUSED)
+sh_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int words = 0;
 
-  if (sh_pass_in_reg_p (*cum, mode, type)
+  if (sh_pass_in_reg_p (*cum, arg.mode, arg.type)
       && !TARGET_FPU_DOUBLE
-      && (sh_round_reg (*cum, mode)
-	  + (mode != BLKmode
-	     ? CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD)
-	     : CEIL (int_size_in_bytes (type), UNITS_PER_WORD))
-	  > NPARM_REGS (mode)))
-    words = NPARM_REGS (mode) - sh_round_reg (*cum, mode);
+      && (sh_round_reg (*cum, arg.mode)
+	  + CEIL (arg.promoted_size_in_bytes (), UNITS_PER_WORD)
+	  > NPARM_REGS (arg.mode)))
+    words = NPARM_REGS (arg.mode) - sh_round_reg (*cum, arg.mode);
 
   return words * UNITS_PER_WORD;
 }
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	2019-08-19 15:58:10.766205389 +0100
+++ gcc/config/sparc/sparc.c	2019-08-19 15:58:21.742125973 +0100
@@ -668,7 +668,7 @@ static pad_direction sparc_function_arg_
 static unsigned int sparc_function_arg_boundary (machine_mode,
 						 const_tree);
 static int sparc_arg_partial_bytes (cumulative_args_t,
-				    machine_mode, tree, bool);
+				    const function_arg_info &);
 static bool sparc_return_in_memory (const_tree, const_tree);
 static rtx sparc_struct_value_rtx (tree, int);
 static rtx sparc_function_value (const_tree, const_tree, bool);
@@ -7533,14 +7533,13 @@ sparc_function_arg_boundary (machine_mod
    mode] will be split between that reg and memory.  */
 
 static int
-sparc_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
-			 tree type, bool named)
+sparc_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
 {
   int slotno, regno, padding;
 
   /* We pass false for incoming here, it doesn't matter.  */
-  slotno = function_arg_slotno (get_cumulative_args (cum), mode, type, named,
-				false, &regno, &padding);
+  slotno = function_arg_slotno (get_cumulative_args (cum), arg.mode, arg.type,
+				arg.named, false, &regno, &padding);
 
   if (slotno == -1)
     return 0;
@@ -7550,7 +7549,7 @@ sparc_arg_partial_bytes (cumulative_args
       /* We are guaranteed by pass_by_reference that the size of the
 	 argument is not greater than 8 bytes, so we only need to return
 	 one word if the argument is partially passed in registers.  */
-      const int size = GET_MODE_SIZE (mode);
+      const int size = GET_MODE_SIZE (arg.mode);
 
       if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
 	return UNITS_PER_WORD;
@@ -7560,33 +7559,33 @@ sparc_arg_partial_bytes (cumulative_args
       /* We are guaranteed by pass_by_reference that the size of the
 	 argument is not greater than 16 bytes, so we only need to return
 	 one word if the argument is partially passed in registers.  */
-      if (type && AGGREGATE_TYPE_P (type))
+      if (arg.aggregate_type_p ())
 	{
-	  const int size = int_size_in_bytes (type);
+	  const int size = int_size_in_bytes (arg.type);
 
 	  if (size > UNITS_PER_WORD
 	      && (slotno == SPARC_INT_ARG_MAX - 1
 		  || slotno == SPARC_FP_ARG_MAX - 1))
 	    return UNITS_PER_WORD;
 	}
-      else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-	       || ((GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-		    || (type && VECTOR_TYPE_P (type)))
-		   && !(TARGET_FPU && named)))
-	{
-	  const int size = (type && VECTOR_FLOAT_TYPE_P (type))
-			   ? int_size_in_bytes (type)
-			   : GET_MODE_SIZE (mode);
+      else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
+	       || ((GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+		    || (arg.type && VECTOR_TYPE_P (arg.type)))
+		   && !(TARGET_FPU && arg.named)))
+	{
+	  const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
+			   ? int_size_in_bytes (arg.type)
+			   : GET_MODE_SIZE (arg.mode);
 
 	  if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
 	    return UNITS_PER_WORD;
 	}
-      else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-	       || (type && VECTOR_TYPE_P (type)))
+      else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
+	       || (arg.type && VECTOR_TYPE_P (arg.type)))
 	{
-	  const int size = (type && VECTOR_FLOAT_TYPE_P (type))
-			   ? int_size_in_bytes (type)
-			   : GET_MODE_SIZE (mode);
+	  const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
+			   ? int_size_in_bytes (arg.type)
+			   : GET_MODE_SIZE (arg.mode);
 
 	  if (size > UNITS_PER_WORD && slotno == SPARC_FP_ARG_MAX - 1)
 	    return UNITS_PER_WORD;
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	2019-03-08 18:15:39.112731182 +0000
+++ gcc/config/v850/v850.c	2019-08-19 15:58:21.742125973 +0100
@@ -196,27 +196,22 @@ v850_function_arg (cumulative_args_t cum
 /* Return the number of bytes which must be put into registers
    for values which are part in registers and part in memory.  */
 static int
-v850_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode,
-                        tree type, bool named)
+v850_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int size, align;
 
-  if (!named)
+  if (!arg.named)
     return 0;
 
-  if (mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  size = arg.promoted_size_in_bytes ();
   if (size < 1)
     size = 1;
   
   if (!TARGET_GCC_ABI)
     align = UNITS_PER_WORD;
-  else if (type)
-    align = TYPE_ALIGN (type) / BITS_PER_UNIT;
+  else if (arg.type)
+    align = TYPE_ALIGN (arg.type) / BITS_PER_UNIT;
   else
     align = size;
 
@@ -228,7 +223,7 @@ v850_arg_partial_bytes (cumulative_args_
   if (cum->nbytes + size <= 4 * UNITS_PER_WORD)
     return 0;
 
-  if (type == NULL_TREE
+  if (arg.type == NULL_TREE
       && cum->nbytes + size > 4 * UNITS_PER_WORD)
     return 0;
 
