diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5a198c95dc..8a68093c64a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-08-20 Richard Sandiford + + * calls.h (apply_pass_by_reference_rules): Declare. + * calls.c (apply_pass_by_reference_rules): New function. + * config/c6x/c6x.c (c6x_call_saved_register_used): Use it. + * config/rs6000/rs6000-call.c (rs6000_parm_needs_stack): Likewise. + * config/s390/s390.c (s390_call_saved_register_used): Likewise. + * function.c (assign_parm_find_data_types): Likewise. + * var-tracking.c (prepare_call_arguments): Likewise. + 2019-08-20 Richard Sandiford * target.def (must_pass_in_stack): Take a function_arg_info instead diff --git a/gcc/calls.c b/gcc/calls.c index 1f691e84dfe..6f573f3b26e 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -935,6 +935,22 @@ pass_va_arg_by_reference (tree type) return pass_by_reference (NULL, function_arg_info (type, /*named=*/false)); } +/* Decide whether ARG, which occurs in the state described by CA, + should be passed by reference. Return true if so and update + ARG accordingly. */ + +bool +apply_pass_by_reference_rules (CUMULATIVE_ARGS *ca, function_arg_info &arg) +{ + if (pass_by_reference (ca, arg)) + { + arg.type = build_pointer_type (arg.type); + arg.mode = TYPE_MODE (arg.type); + return true; + } + return false; +} + /* Return true if ARG, which is passed by reference, should be callee copied instead of caller copied. */ diff --git a/gcc/calls.h b/gcc/calls.h index 5e8c576424a..01ab3905a3a 100644 --- a/gcc/calls.h +++ b/gcc/calls.h @@ -118,6 +118,8 @@ extern void fixup_tail_calls (void); extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info); extern bool pass_va_arg_by_reference (tree); +extern bool apply_pass_by_reference_rules (CUMULATIVE_ARGS *, + function_arg_info &); extern bool reference_callee_copied (CUMULATIVE_ARGS *, const function_arg_info &); extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]); diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c index 37da9a419db..8477d35e1e7 100644 --- a/gcc/config/c6x/c6x.c +++ b/gcc/config/c6x/c6x.c @@ -1088,8 +1088,6 @@ c6x_call_saved_register_used (tree call_expr) cumulative_args_t cum; HARD_REG_SET call_saved_regset; tree parameter; - machine_mode mode; - tree type; rtx parm_rtx; int i; @@ -1107,19 +1105,9 @@ c6x_call_saved_register_used (tree call_expr) if (TREE_CODE (parameter) == ERROR_MARK) return true; - type = TREE_TYPE (parameter); - gcc_assert (type); + function_arg_info arg (TREE_TYPE (parameter), /*named=*/true); + apply_pass_by_reference_rules (&cum_v, arg); - mode = TYPE_MODE (type); - gcc_assert (mode); - - if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true))) - { - mode = Pmode; - type = build_pointer_type (type); - } - - function_arg_info arg (type, mode, /*named=*/false); parm_rtx = c6x_function_arg (cum, arg); c6x_function_arg_advance (cum, arg); diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index fb87bb2f2cb..7280a4ed9c8 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -2170,7 +2170,6 @@ rs6000_pass_by_reference (cumulative_args_t, const function_arg_info &arg) static bool rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) { - machine_mode mode; int unsignedp; rtx entry_parm; @@ -2193,16 +2192,14 @@ rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) type = TREE_TYPE (first_field (type)); /* See if this arg was passed by invisible reference. */ - if (pass_by_reference (get_cumulative_args (args_so_far), - function_arg_info (type, /*named=*/true))) - type = build_pointer_type (type); + function_arg_info arg (type, /*named=*/true); + apply_pass_by_reference_rules (get_cumulative_args (args_so_far), arg); /* Find mode as it is passed by the ABI. */ unsignedp = TYPE_UNSIGNED (type); - mode = promote_mode (type, TYPE_MODE (type), &unsignedp); + arg.mode = promote_mode (arg.type, arg.mode, &unsignedp); /* If we must pass in stack, we need a stack. */ - function_arg_info arg (type, mode, /*named=*/true); if (rs6000_must_pass_in_stack (arg)) return true; diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 3ad4a185e20..fa17d7d5d08 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -13309,8 +13309,6 @@ s390_call_saved_register_used (tree call_expr) CUMULATIVE_ARGS cum_v; cumulative_args_t cum; tree parameter; - machine_mode mode; - tree type; rtx parm_rtx; int reg, i; @@ -13327,22 +13325,12 @@ s390_call_saved_register_used (tree call_expr) if (TREE_CODE (parameter) == ERROR_MARK) return true; - type = TREE_TYPE (parameter); - gcc_assert (type); - - mode = TYPE_MODE (type); - gcc_assert (mode); - /* We assume that in the target function all parameters are named. This only has an impact on vector argument register usage none of which is call-saved. */ - if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true))) - { - mode = Pmode; - type = build_pointer_type (type); - } + function_arg_info arg (TREE_TYPE (parameter), /*named=*/true); + apply_pass_by_reference_rules (&cum_v, arg); - function_arg_info arg (type, mode, /*named=*/true); parm_rtx = s390_function_arg (cum, arg); s390_function_arg_advance (cum, arg); diff --git a/gcc/function.c b/gcc/function.c index 46ed75c77be..265bcd19f50 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2456,11 +2456,11 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, /* See if this arg was passed by invisible reference. */ { function_arg_info arg (passed_type, passed_mode, data->named_arg); - if (pass_by_reference (&all->args_so_far_v, arg)) + if (apply_pass_by_reference_rules (&all->args_so_far_v, arg)) { - passed_type = nominal_type = build_pointer_type (passed_type); + passed_type = nominal_type = arg.type; data->passed_pointer = true; - passed_mode = nominal_mode = TYPE_MODE (nominal_type); + passed_mode = nominal_mode = arg.mode; } } diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 8b1d4476e22..af18528b6d7 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -6426,28 +6426,24 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) } if (t && t != void_list_node) { - tree argtype = TREE_VALUE (t); rtx reg; - function_arg_info orig_arg (argtype, /*named=*/true); - if (pass_by_reference (&args_so_far_v, orig_arg)) - argtype = build_pointer_type (argtype); - machine_mode mode = TYPE_MODE (argtype); - function_arg_info arg (argtype, /*named=*/true); + function_arg_info arg (TREE_VALUE (t), /*named=*/true); + apply_pass_by_reference_rules (&args_so_far_v, arg); reg = targetm.calls.function_arg (args_so_far, arg); - if (TREE_CODE (argtype) == REFERENCE_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (argtype)) + if (TREE_CODE (arg.type) == REFERENCE_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (arg.type)) && reg && REG_P (reg) - && GET_MODE (reg) == mode - && (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) + && GET_MODE (reg) == arg.mode + && (GET_MODE_CLASS (arg.mode) == MODE_INT + || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT) && REG_P (x) && REGNO (x) == REGNO (reg) - && GET_MODE (x) == mode + && GET_MODE (x) == arg.mode && item) { machine_mode indmode - = TYPE_MODE (TREE_TYPE (argtype)); + = TYPE_MODE (TREE_TYPE (arg.type)); rtx mem = gen_rtx_MEM (indmode, x); cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode); if (val && cselib_preserved_value_p (val))