Index: gcc/target.def
===================================================================
--- gcc/target.def	2019-08-19 15:58:58.017863486 +0100
+++ gcc/target.def	2019-08-19 15:59:04.289818104 +0100
@@ -4630,11 +4630,11 @@ false.",
    Need audit to verify that this is the case.  */
 DEFHOOK
 (must_pass_in_stack,
- "This target hook should return @code{true} if we should not pass @var{type}\n\
+ "This target hook should return @code{true} if we should not pass @var{arg}\n\
 solely in registers.  The file @file{expr.h} defines a\n\
 definition that is usually appropriate, refer to @file{expr.h} for additional\n\
 documentation.",
- bool, (machine_mode mode, const_tree type),
+ bool, (const function_arg_info &arg),
  must_pass_in_stack_var_size_or_pad)
 
 /* Return true if type TYPE, mode MODE, which is passed by reference,
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2019-08-19 15:58:58.013863514 +0100
+++ gcc/doc/tm.texi	2019-08-19 15:59:04.289818104 +0100
@@ -4012,8 +4012,8 @@ defined, the argument will be computed i
 a register.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (machine_mode @var{mode}, const_tree @var{type})
-This target hook should return @code{true} if we should not pass @var{type}
+@deftypefn {Target Hook} bool TARGET_MUST_PASS_IN_STACK (const function_arg_info @var{&arg})
+This target hook should return @code{true} if we should not pass @var{arg}
 solely in registers.  The file @file{expr.h} defines a
 definition that is usually appropriate, refer to @file{expr.h} for additional
 documentation.
Index: gcc/calls.h
===================================================================
--- gcc/calls.h	2019-08-19 15:58:57.997863631 +0100
+++ gcc/calls.h	2019-08-19 15:59:04.261818304 +0100
@@ -108,8 +108,8 @@ extern int setjmp_call_p (const_tree);
 extern bool gimple_maybe_alloca_call_p (const gimple *);
 extern bool gimple_alloca_call_p (const gimple *);
 extern bool alloca_call_p (const_tree);
-extern bool must_pass_in_stack_var_size (machine_mode, const_tree);
-extern bool must_pass_in_stack_var_size_or_pad (machine_mode, const_tree);
+extern bool must_pass_in_stack_var_size (const function_arg_info &);
+extern bool must_pass_in_stack_var_size_or_pad (const function_arg_info &);
 extern bool must_pass_va_arg_in_stack (tree);
 extern rtx prepare_call_address (tree, rtx, rtx, rtx *, int, int);
 extern bool shift_return_value (machine_mode, bool, rtx);
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	2019-08-19 15:58:57.993863659 +0100
+++ gcc/calls.c	2019-08-19 15:59:04.261818304 +0100
@@ -2139,7 +2139,7 @@ initialize_argument_information (int num
       if (args[i].reg)
 	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);
+      args[i].pass_on_stack = targetm.calls.must_pass_in_stack (arg);
 
       /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
 	 it means that we are to pass this arg in the register(s) designated
@@ -5839,22 +5839,21 @@ store_one_arg (struct arg_data *arg, rtx
   return sibcall_failure;
 }
 
-/* Nonzero if we do not know how to pass TYPE solely in registers.  */
+/* Nonzero if we do not know how to pass ARG solely in registers.  */
 
 bool
-must_pass_in_stack_var_size (machine_mode mode ATTRIBUTE_UNUSED,
-			     const_tree type)
+must_pass_in_stack_var_size (const function_arg_info &arg)
 {
-  if (!type)
+  if (!arg.type)
     return false;
 
   /* If the type has variable size...  */
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST)
     return true;
 
   /* If the type is marked as addressable (it is required
      to be constructed into the stack)...  */
-  if (TREE_ADDRESSABLE (type))
+  if (TREE_ADDRESSABLE (arg.type))
     return true;
 
   return false;
@@ -5865,28 +5864,28 @@ must_pass_in_stack_var_size (machine_mod
 /* ??? Should be able to merge these two by examining BLOCK_REG_PADDING.  */
 
 bool
-must_pass_in_stack_var_size_or_pad (machine_mode mode, const_tree type)
+must_pass_in_stack_var_size_or_pad (const function_arg_info &arg)
 {
-  if (!type)
+  if (!arg.type)
     return false;
 
   /* If the type has variable size...  */
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST)
     return true;
 
   /* If the type is marked as addressable (it is required
      to be constructed into the stack)...  */
-  if (TREE_ADDRESSABLE (type))
+  if (TREE_ADDRESSABLE (arg.type))
     return true;
 
-  if (TYPE_EMPTY_P (type))
+  if (TYPE_EMPTY_P (arg.type))
     return false;
 
   /* If the padding and mode of the type is such that a copy into
      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)
-      && (targetm.calls.function_arg_padding (mode, type)
+  if (arg.mode == BLKmode
+      && int_size_in_bytes (arg.type) % (PARM_BOUNDARY / BITS_PER_UNIT)
+      && (targetm.calls.function_arg_padding (arg.mode, arg.type)
 	  == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
     return true;
 
@@ -5899,7 +5898,8 @@ must_pass_in_stack_var_size_or_pad (mach
 bool
 must_pass_va_arg_in_stack (tree type)
 {
-  return targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);
+  function_arg_info arg (type, /*named=*/false);
+  return targetm.calls.must_pass_in_stack (arg);
 }
 
 /* Tell the garbage collector about GTY markers in this source file.  */
Index: gcc/function.c
===================================================================
--- gcc/function.c	2019-08-19 15:58:58.013863514 +0100
+++ gcc/function.c	2019-08-19 15:59:04.289818104 +0100
@@ -2552,8 +2552,7 @@ assign_parm_find_entry_rtl (struct assig
 
   /* If this parameter was passed both in registers and in the stack, use
      the copy on the stack.  */
-  if (targetm.calls.must_pass_in_stack (data->promoted_mode,
-					data->passed_type))
+  if (targetm.calls.must_pass_in_stack (arg))
     entry_parm = 0;
 
   if (entry_parm)
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2019-08-19 15:58:58.017863486 +0100
+++ gcc/targhooks.c	2019-08-19 15:59:04.289818104 +0100
@@ -323,7 +323,7 @@ default_cxx_get_cookie_size (tree type)
 hook_pass_by_reference_must_pass_in_stack (cumulative_args_t,
 					   const function_arg_info &arg)
 {
-  return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+  return targetm.calls.must_pass_in_stack (arg);
 }
 
 /* Return true if a parameter follows callee copies conventions.  This
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	2019-08-19 15:58:50.309919261 +0100
+++ gcc/config/alpha/alpha.c	2019-08-19 15:59:04.265818276 +0100
@@ -5585,7 +5585,7 @@ alpha_function_arg (cumulative_args_t cu
 
       num_args = cum->num_args;
       if (num_args >= 6
-	  || targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+	  || targetm.calls.must_pass_in_stack (arg))
 	return NULL_RTX;
     }
 #elif TARGET_ABI_OSF
@@ -5596,7 +5596,7 @@ alpha_function_arg (cumulative_args_t cu
 
       if (arg.end_marker_p ())
 	basereg = 16;
-      else if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      else if (targetm.calls.must_pass_in_stack (arg))
 	return NULL_RTX;
     }
 #else
@@ -5613,7 +5613,7 @@ alpha_function_arg_advance (cumulative_a
 			    const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-  bool onstack = targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+  bool onstack = targetm.calls.must_pass_in_stack (arg);
   int increment = onstack ? 6 : ALPHA_ARG_SIZE (arg.mode, arg.type);
 
 #if TARGET_ABI_OSF
Index: gcc/config/cr16/cr16.c
===================================================================
--- gcc/config/cr16/cr16.c	2019-08-19 15:58:50.317919202 +0100
+++ gcc/config/cr16/cr16.c	2019-08-19 15:59:04.273818218 +0100
@@ -606,7 +606,7 @@ cr16_function_arg (cumulative_args_t cum
   if (arg.end_marker_p ())
     return NULL_RTX;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
     return NULL_RTX;
 
   if (arg.mode == BLKmode)
@@ -672,7 +672,7 @@ cr16_function_arg_advance (cumulative_ar
   if (!cum->last_parm_in_reg)
     return;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type) || (cum->ints < 0))
+  if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
     return;
 
   if ((arg.mode == SImode) || (arg.mode == HImode)
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/cris/cris.c	2019-08-19 15:59:04.273818218 +0100
@@ -4046,7 +4046,7 @@ cris_setup_incoming_varargs (cumulative_
 static bool
 cris_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
 {
-  return (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  return (targetm.calls.must_pass_in_stack (arg)
 	  || CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8);
 }
 
@@ -4111,7 +4111,7 @@ cris_function_value_regno_p (const unsig
 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 (arg.mode, arg.type)
+      && !targetm.calls.must_pass_in_stack (arg)
       && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 4
       && CRIS_FUNCTION_ARG_SIZE (arg.mode, arg.type) <= 8)
     return UNITS_PER_WORD;
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/iq2000/iq2000.c	2019-08-19 15:59:04.277818191 +0100
@@ -2300,7 +2300,7 @@ iq2000_pass_by_reference (cumulative_arg
   /* We must pass by reference if we would be both passing in registers
      and the stack.  This is because any subsequent partial arg would be
      handled incorrectly in this case.  */
-  if (cum && targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (cum && targetm.calls.must_pass_in_stack (arg))
      {
        /* Don't pass the actual CUM to FUNCTION_ARG, because we would
 	  get double copies of any offsets generated for small structs
Index: gcc/config/lm32/lm32.c
===================================================================
--- gcc/config/lm32/lm32.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/lm32/lm32.c	2019-08-19 15:59:04.277818191 +0100
@@ -629,7 +629,7 @@ lm32_function_arg (cumulative_args_t cum
     /* Compute operand 2 of the call insn.  */
     return GEN_INT (0);
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return NULL_RTX;
 
   if (!arg.named
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c	2019-08-19 15:58:50.329919117 +0100
+++ gcc/config/mcore/mcore.c	2019-08-19 15:59:04.281818160 +0100
@@ -2713,7 +2713,8 @@ mcore_num_arg_regs (machine_mode mode, c
 {
   int size;
 
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  function_arg_info arg (const_cast<tree> (type), mode, /*named=*/true);
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
   if (type && mode == BLKmode)
@@ -2803,7 +2804,7 @@ mcore_function_arg (cumulative_args_t cu
   if (!arg.named || arg.end_marker_p ())
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
   arg_reg = ROUND_REG (*get_cumulative_args (cum), arg.mode);
@@ -2848,7 +2849,7 @@ mcore_arg_partial_bytes (cumulative_args
   if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
       
   /* REG is not the *hardware* register number of the register that holds
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2019-08-19 15:58:58.005863572 +0100
+++ gcc/config/mips/mips.c	2019-08-19 15:59:04.281818160 +0100
@@ -6252,7 +6252,7 @@ mips_pass_by_reference (cumulative_args_
   else
     {
       /* If we have a variable-sized parameter, we have no choice.  */
-      return targetm.calls.must_pass_in_stack (arg.mode, arg.type);
+      return targetm.calls.must_pass_in_stack (arg);
     }
 }
 
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c	2019-08-19 15:58:58.005863572 +0100
+++ gcc/config/mmix/mmix.c	2019-08-19 15:59:04.281818160 +0100
@@ -621,7 +621,7 @@ mmix_function_arg_advance (cumulative_ar
   CUMULATIVE_ARGS *argsp = get_cumulative_args (argsp_v);
   int arg_size = MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type);
 
-  argsp->regs = ((targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  argsp->regs = ((targetm.calls.must_pass_in_stack (arg)
 		  || (arg_size > 8
 		      && !TARGET_LIBFUNC
 		      && !argsp->lib))
@@ -647,7 +647,7 @@ mmix_function_arg_1 (const cumulative_ar
       : NULL_RTX;
 
   return (argsp->regs < MMIX_MAX_ARGS_IN_REGS
-	  && !targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+	  && !targetm.calls.must_pass_in_stack (arg)
 	  && (GET_MODE_BITSIZE (arg.mode) <= 64
 	      || argsp->lib
 	      || TARGET_LIBFUNC))
@@ -686,7 +686,7 @@ mmix_pass_by_reference (cumulative_args_
 
   /* FIXME: Check: I'm not sure the must_pass_in_stack check is
      necessary.  */
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return true;
 
   if (MMIX_FUNCTION_ARG_SIZE (arg.mode, arg.type) > 8
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	2019-08-19 15:58:58.013863514 +0100
+++ gcc/config/sh/sh.c	2019-08-19 15:59:04.285818131 +0100
@@ -7901,7 +7901,7 @@ sh_pass_by_reference (cumulative_args_t
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return true;
 
   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  That function
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c	2019-08-19 15:58:50.341919030 +0100
+++ gcc/config/stormy16/stormy16.c	2019-08-19 15:59:04.285818131 +0100
@@ -1239,7 +1239,7 @@ xstormy16_function_arg (cumulative_args_
 
   if (arg.end_marker_p ())
     return const0_rtx;
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+  if (targetm.calls.must_pass_in_stack (arg)
       || (*cum + XSTORMY16_WORD_SIZE (arg.type, arg.mode)
 	  > NUM_ARGUMENT_REGISTERS))
     return NULL_RTX;
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	2019-08-19 15:58:50.341919030 +0100
+++ gcc/config/xtensa/xtensa.c	2019-08-19 15:59:04.285818131 +0100
@@ -2118,7 +2118,7 @@ xtensa_function_arg_advance (cumulative_
 	   / UNITS_PER_WORD);
 
   if (*arg_words < max
-      && (targetm.calls.must_pass_in_stack (arg.mode, arg.type)
+      && (targetm.calls.must_pass_in_stack (arg)
 	  || *arg_words + words > max))
     *arg_words = max;
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	2019-08-19 15:58:50.317919202 +0100
+++ gcc/config/arm/arm.c	2019-08-19 15:59:04.269818249 +0100
@@ -219,7 +219,7 @@ static bool arm_promote_prototypes (cons
 static bool arm_default_short_enums (void);
 static bool arm_align_anon_bitfield (void);
 static bool arm_return_in_msb (const_tree);
-static bool arm_must_pass_in_stack (machine_mode, const_tree);
+static bool arm_must_pass_in_stack (const function_arg_info &);
 static bool arm_return_in_memory (const_tree, const_tree);
 #if ARM_UNWIND_INFO
 static void arm_unwind_emit (FILE *, rtx_insn *);
@@ -15382,12 +15382,12 @@ arm_reload_out_hi (rtx *operands)
    (padded to the size of a word) should be passed in a register.  */
 
 static bool
-arm_must_pass_in_stack (machine_mode mode, const_tree type)
+arm_must_pass_in_stack (const function_arg_info &arg)
 {
   if (TARGET_AAPCS_BASED)
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
   else
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
 }
 
 
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/fr30/fr30.c	2019-08-19 15:59:04.273818218 +0100
@@ -116,7 +116,7 @@ struct fr30_frame_info
 static void fr30_setup_incoming_varargs (cumulative_args_t,
 					 const function_arg_info &,
 					 int *, int);
-static bool fr30_must_pass_in_stack (machine_mode, const_tree);
+static bool fr30_must_pass_in_stack (const function_arg_info &);
 static int fr30_arg_partial_bytes (cumulative_args_t,
 				   const function_arg_info &);
 static rtx fr30_function_arg (cumulative_args_t, const function_arg_info &);
@@ -129,7 +129,7 @@ static bool fr30_function_value_regno_p
 static bool fr30_can_eliminate (const int, const int);
 static void fr30_asm_trampoline_template (FILE *);
 static void fr30_trampoline_init (rtx, tree, rtx);
-static int fr30_num_arg_regs (machine_mode, const_tree);
+static int fr30_num_arg_regs (const function_arg_info &);
 
 #define FRAME_POINTER_MASK 	(1 << (FRAME_POINTER_REGNUM))
 #define RETURN_POINTER_MASK 	(1 << (RETURN_POINTER_REGNUM))
@@ -480,7 +480,7 @@ fr30_setup_incoming_varargs (cumulative_
     /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
        arg must not be treated as an anonymous arg.  */
     /* ??? This is a pointer increment, which makes no sense.  */
-    arg_regs_used_so_far += fr30_num_arg_regs (arg.mode, arg.type);
+    arg_regs_used_so_far += fr30_num_arg_regs (arg);
 
   size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
 
@@ -743,30 +743,20 @@ fr30_function_value_regno_p (const unsig
    in registers.  */
 
 static bool
-fr30_must_pass_in_stack (machine_mode mode, const_tree type)
+fr30_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (mode == BLKmode)
-    return true;
-  if (type == NULL)
-    return false;
-  return AGGREGATE_TYPE_P (type);
+  return arg.mode == BLKmode || arg.aggregate_type_p ();
 }
 
-/* Compute the number of word sized registers needed to hold a
-   function argument of mode INT_MODE and tree type TYPE.  */
+/* Compute the number of word sized registers needed to hold function
+   argument ARG.  */
 static int
-fr30_num_arg_regs (machine_mode mode, const_tree type)
+fr30_num_arg_regs (const function_arg_info &arg)
 {
-  int size;
-
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
-  if (type && mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  int size = arg.promoted_size_in_bytes ();
   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 }
 
@@ -792,7 +782,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 (arg.mode, arg.type) <= FR30_NUM_ARG_REGS)
+  if (*cum + fr30_num_arg_regs (arg) <= FR30_NUM_ARG_REGS)
     return 0;
   
   return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
@@ -804,7 +794,7 @@ fr30_function_arg (cumulative_args_t cum
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
   if (!arg.named
-      || fr30_must_pass_in_stack (arg.mode, arg.type)
+      || fr30_must_pass_in_stack (arg)
       || *cum >= FR30_NUM_ARG_REGS)
     return NULL_RTX;
   else
@@ -817,7 +807,7 @@ fr30_function_arg_advance (cumulative_ar
 			   const function_arg_info &arg)
 {
   if (arg.named)
-    *get_cumulative_args (cum) += fr30_num_arg_regs (arg.mode, arg.type);
+    *get_cumulative_args (cum) += fr30_num_arg_regs (arg);
 }
 
 /*}}}*/
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/frv/frv.c	2019-08-19 15:59:04.273818218 +0100
@@ -379,7 +379,7 @@ static void frv_output_const_unspec		(FI
 						 const struct frv_unspec *);
 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 bool frv_must_pass_in_stack (const function_arg_info &);
 static int frv_arg_partial_bytes (cumulative_args_t,
 				  const function_arg_info &);
 static rtx frv_function_arg (cumulative_args_t, const function_arg_info &);
@@ -3077,13 +3077,9 @@ frv_init_cumulative_args (CUMULATIVE_ARG
    in registers.  */
 
 static bool
-frv_must_pass_in_stack (machine_mode mode, const_tree type)
+frv_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (mode == BLKmode)
-    return true;
-  if (type == NULL)
-    return false;
-  return AGGREGATE_TYPE_P (type);
+  return arg.mode == BLKmode || arg.aggregate_type_p ();
 }
 
 /* If defined, a C expression that gives the alignment boundary, in bits, of an
Index: gcc/config/gcn/gcn.c
===================================================================
--- gcc/config/gcn/gcn.c	2019-08-19 15:58:50.321919175 +0100
+++ gcc/config/gcn/gcn.c	2019-08-19 15:59:04.273818218 +0100
@@ -2200,22 +2200,16 @@ gcn_function_value_regno_p (const unsign
   return n == RETURN_VALUE_REG;
 }
 
-/* Calculate the number of registers required to hold a function argument
-   of MODE and TYPE.  */
+/* Calculate the number of registers required to hold function argument
+   ARG.  */
 
 static int
-num_arg_regs (machine_mode mode, const_tree type)
+num_arg_regs (const function_arg_info &arg)
 {
-  int size;
-
-  if (targetm.calls.must_pass_in_stack (mode, type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return 0;
 
-  if (type && mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else
-    size = GET_MODE_SIZE (mode);
-
+  int size = arg.promoted_size_in_bytes ();
   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 }
 
@@ -2263,11 +2257,11 @@ gcn_function_arg (cumulative_args_t cum_
       if (!arg.named || arg.end_marker_p ())
 	return 0;
 
-      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      if (targetm.calls.must_pass_in_stack (arg))
 	return 0;
 
       int reg_num = FIRST_PARM_REG + cum->num;
-      int num_regs = num_arg_regs (arg.mode, arg.type);
+      int num_regs = num_arg_regs (arg);
       if (num_regs > 0)
 	while (reg_num % num_regs != 0)
 	  reg_num++;
@@ -2323,7 +2317,7 @@ gcn_function_arg_advance (cumulative_arg
       if (!arg.named)
 	return;
 
-      int num_regs = num_arg_regs (arg.mode, arg.type);
+      int num_regs = num_arg_regs (arg);
       if (num_regs > 0)
 	while ((FIRST_PARM_REG + cum->num) % num_regs != 0)
 	  cum->num++;
@@ -2355,14 +2349,14 @@ gcn_arg_partial_bytes (cumulative_args_t
   if (!arg.named)
     return 0;
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     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 (arg.mode, arg.type) <= NUM_PARM_REGS)
+  if (cum->num + num_arg_regs (arg) <= NUM_PARM_REGS)
     return 0;
 
   return (NUM_PARM_REGS - cum->num) * UNITS_PER_WORD;
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2019-08-19 15:58:50.325919144 +0100
+++ gcc/config/i386/i386.c	2019-08-19 15:59:04.277818191 +0100
@@ -1455,19 +1455,19 @@ ix86_function_arg_regno_p (int regno)
   return false;
 }
 
-/* Return if we do not know how to pass TYPE solely in registers.  */
+/* Return if we do not know how to pass ARG solely in registers.  */
 
 static bool
-ix86_must_pass_in_stack (machine_mode mode, const_tree type)
+ix86_must_pass_in_stack (const function_arg_info &arg)
 {
-  if (must_pass_in_stack_var_size_or_pad (mode, type))
+  if (must_pass_in_stack_var_size_or_pad (arg))
     return true;
 
   /* For 32-bit, we want TImode aggregates to go on the stack.  But watch out!
      The layout_type routine is crafty and tries to trick us into passing
      currently unsupported vector types on the stack by using TImode.  */
-  return (!TARGET_64BIT && mode == TImode
-	  && type && TREE_CODE (type) != VECTOR_TYPE);
+  return (!TARGET_64BIT && arg.mode == TImode
+	  && arg.type && TREE_CODE (arg.type) != VECTOR_TYPE);
 }
 
 /* It returns the size, in bytes, of the area reserved for arguments passed
@@ -2062,9 +2062,13 @@ classify_argument (machine_mode mode, co
   if (bytes < 0)
     return 0;
 
-  if (mode != VOIDmode
-      && targetm.calls.must_pass_in_stack (mode, type))
-    return 0;
+  if (mode != VOIDmode)
+    {
+      /* The value of "named" doesn't matter.  */
+      function_arg_info arg (const_cast<tree> (type), mode, /*named=*/true);
+      if (targetm.calls.must_pass_in_stack (arg))
+	return 0;
+    }
 
   if (type && AGGREGATE_TYPE_P (type))
     {
Index: gcc/config/nds32/nds32.c
===================================================================
--- gcc/config/nds32/nds32.c	2019-08-19 15:58:50.333919085 +0100
+++ gcc/config/nds32/nds32.c	2019-08-19 15:59:04.285818131 +0100
@@ -1951,16 +1951,16 @@ nds32_function_arg (cumulative_args_t ca
 }
 
 static bool
-nds32_must_pass_in_stack (machine_mode mode, const_tree type)
+nds32_must_pass_in_stack (const function_arg_info &arg)
 {
   /* Return true if a type must be passed in memory.
      If it is NOT using hard float abi, small aggregates can be
      passed in a register even we are calling a variadic function.
      So there is no need to take padding into consideration.  */
   if (TARGET_HARD_FLOAT)
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
   else
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
 }
 
 static int
Index: gcc/config/rs6000/rs6000-internal.h
===================================================================
--- gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/rs6000/rs6000-internal.h	2019-08-19 15:59:04.285818131 +0100
@@ -156,7 +156,7 @@ extern void setup_incoming_varargs (cumu
 				    const function_arg_info &, int *, int);
 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 bool rs6000_must_pass_in_stack (const function_arg_info &);
 extern int rs6000_arg_partial_bytes (cumulative_args_t,
 				     const function_arg_info &);
 extern void rs6000_function_arg_advance (cumulative_args_t,
Index: gcc/config/rs6000/rs6000-call.c
===================================================================
--- gcc/config/rs6000/rs6000-call.c	2019-08-19 15:58:50.337919057 +0100
+++ gcc/config/rs6000/rs6000-call.c	2019-08-19 15:59:04.285818131 +0100
@@ -816,12 +816,12 @@ rs6000_promote_function_mode (const_tree
 /* Return true if TYPE must be passed on the stack and not in registers.  */
 
 bool
-rs6000_must_pass_in_stack (machine_mode mode, const_tree type)
+rs6000_must_pass_in_stack (const function_arg_info &arg)
 {
   if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT)
-    return must_pass_in_stack_var_size (mode, type);
+    return must_pass_in_stack_var_size (arg);
   else
-    return must_pass_in_stack_var_size_or_pad (mode, type);
+    return must_pass_in_stack_var_size_or_pad (arg);
 }
 
 static inline bool
@@ -2202,11 +2202,11 @@ rs6000_parm_needs_stack (cumulative_args
   mode = promote_mode (type, TYPE_MODE (type), &unsignedp);
 
   /* If we must pass in stack, we need a stack.  */
-  if (rs6000_must_pass_in_stack (mode, type))
+  function_arg_info arg (type, mode, /*named=*/true);
+  if (rs6000_must_pass_in_stack (arg))
     return true;
 
   /* If there is no incoming register, we need a stack.  */
-  function_arg_info arg (type, mode, /*named=*/true);
   entry_parm = rs6000_function_arg (args_so_far, arg);
   if (entry_parm == NULL)
     return true;
@@ -2457,7 +2457,7 @@ setup_incoming_varargs (cumulative_args_
       first_reg_offset = next_cum.words;
       save_area = crtl->args.internal_arg_pointer;
 
-      if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+      if (targetm.calls.must_pass_in_stack (arg))
 	first_reg_offset += rs6000_arg_size (TYPE_MODE (arg.type), arg.type);
     }
 
