Commit b12cdd6e by Richard Sandiford Committed by Richard Sandiford

Add a apply_pass_by_reference_rules helper

This patch adds a helper routine that applies pass-by-reference
semantics to an existing function_arg_info.

The c6x part means that c6x_function_arg and c6x_function_arg_advance
see the same "named" value as pass_by_reference did, rather than
pass_by_reference seeing "true" and the others seeing "false".
This doesn't matter because the c6x port doesn't care about namedness.

The rs6000.c patch removes an assignment to "type", but the only
later code to use it was the patched promote_mode line.

(The reason for patching these places despite the above is that
often target code gets used as a basis for new targets or changes
to existing ones.)

2019-08-20  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* 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.

From-SVN: r274704
parent 0ffef200
2019-08-20 Richard Sandiford <richard.sandiford@arm.com> 2019-08-20 Richard Sandiford <richard.sandiford@arm.com>
* 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 <richard.sandiford@arm.com>
* target.def (must_pass_in_stack): Take a function_arg_info instead * target.def (must_pass_in_stack): Take a function_arg_info instead
of a mode and a type. of a mode and a type.
* doc/tm.texi: Regenerate. * doc/tm.texi: Regenerate.
......
...@@ -935,6 +935,22 @@ pass_va_arg_by_reference (tree type) ...@@ -935,6 +935,22 @@ pass_va_arg_by_reference (tree type)
return pass_by_reference (NULL, function_arg_info (type, /*named=*/false)); 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 /* Return true if ARG, which is passed by reference, should be callee
copied instead of caller copied. */ copied instead of caller copied. */
......
...@@ -118,6 +118,8 @@ extern void fixup_tail_calls (void); ...@@ -118,6 +118,8 @@ extern void fixup_tail_calls (void);
extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info); extern bool pass_by_reference (CUMULATIVE_ARGS *, function_arg_info);
extern bool pass_va_arg_by_reference (tree); 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 *, extern bool reference_callee_copied (CUMULATIVE_ARGS *,
const function_arg_info &); const function_arg_info &);
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]); extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
......
...@@ -1088,8 +1088,6 @@ c6x_call_saved_register_used (tree call_expr) ...@@ -1088,8 +1088,6 @@ c6x_call_saved_register_used (tree call_expr)
cumulative_args_t cum; cumulative_args_t cum;
HARD_REG_SET call_saved_regset; HARD_REG_SET call_saved_regset;
tree parameter; tree parameter;
machine_mode mode;
tree type;
rtx parm_rtx; rtx parm_rtx;
int i; int i;
...@@ -1107,19 +1105,9 @@ c6x_call_saved_register_used (tree call_expr) ...@@ -1107,19 +1105,9 @@ c6x_call_saved_register_used (tree call_expr)
if (TREE_CODE (parameter) == ERROR_MARK) if (TREE_CODE (parameter) == ERROR_MARK)
return true; return true;
type = TREE_TYPE (parameter); function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
gcc_assert (type); 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); parm_rtx = c6x_function_arg (cum, arg);
c6x_function_arg_advance (cum, arg); c6x_function_arg_advance (cum, arg);
......
...@@ -2170,7 +2170,6 @@ rs6000_pass_by_reference (cumulative_args_t, const function_arg_info &arg) ...@@ -2170,7 +2170,6 @@ rs6000_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
static bool static bool
rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
{ {
machine_mode mode;
int unsignedp; int unsignedp;
rtx entry_parm; rtx entry_parm;
...@@ -2193,16 +2192,14 @@ rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) ...@@ -2193,16 +2192,14 @@ rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type)
type = TREE_TYPE (first_field (type)); type = TREE_TYPE (first_field (type));
/* See if this arg was passed by invisible reference. */ /* See if this arg was passed by invisible reference. */
if (pass_by_reference (get_cumulative_args (args_so_far), function_arg_info arg (type, /*named=*/true);
function_arg_info (type, /*named=*/true))) apply_pass_by_reference_rules (get_cumulative_args (args_so_far), arg);
type = build_pointer_type (type);
/* Find mode as it is passed by the ABI. */ /* Find mode as it is passed by the ABI. */
unsignedp = TYPE_UNSIGNED (type); 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. */ /* 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)) if (rs6000_must_pass_in_stack (arg))
return true; return true;
......
...@@ -13309,8 +13309,6 @@ s390_call_saved_register_used (tree call_expr) ...@@ -13309,8 +13309,6 @@ s390_call_saved_register_used (tree call_expr)
CUMULATIVE_ARGS cum_v; CUMULATIVE_ARGS cum_v;
cumulative_args_t cum; cumulative_args_t cum;
tree parameter; tree parameter;
machine_mode mode;
tree type;
rtx parm_rtx; rtx parm_rtx;
int reg, i; int reg, i;
...@@ -13327,22 +13325,12 @@ s390_call_saved_register_used (tree call_expr) ...@@ -13327,22 +13325,12 @@ s390_call_saved_register_used (tree call_expr)
if (TREE_CODE (parameter) == ERROR_MARK) if (TREE_CODE (parameter) == ERROR_MARK)
return true; 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 /* We assume that in the target function all parameters are
named. This only has an impact on vector argument register named. This only has an impact on vector argument register
usage none of which is call-saved. */ usage none of which is call-saved. */
if (pass_by_reference (&cum_v, function_arg_info (type, /*named=*/true))) function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
{ apply_pass_by_reference_rules (&cum_v, arg);
mode = Pmode;
type = build_pointer_type (type);
}
function_arg_info arg (type, mode, /*named=*/true);
parm_rtx = s390_function_arg (cum, arg); parm_rtx = s390_function_arg (cum, arg);
s390_function_arg_advance (cum, arg); s390_function_arg_advance (cum, arg);
......
...@@ -2456,11 +2456,11 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, ...@@ -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. */ /* See if this arg was passed by invisible reference. */
{ {
function_arg_info arg (passed_type, passed_mode, data->named_arg); 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; data->passed_pointer = true;
passed_mode = nominal_mode = TYPE_MODE (nominal_type); passed_mode = nominal_mode = arg.mode;
} }
} }
......
...@@ -6426,28 +6426,24 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) ...@@ -6426,28 +6426,24 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
} }
if (t && t != void_list_node) if (t && t != void_list_node)
{ {
tree argtype = TREE_VALUE (t);
rtx reg; rtx reg;
function_arg_info orig_arg (argtype, /*named=*/true); function_arg_info arg (TREE_VALUE (t), /*named=*/true);
if (pass_by_reference (&args_so_far_v, orig_arg)) apply_pass_by_reference_rules (&args_so_far_v, arg);
argtype = build_pointer_type (argtype);
machine_mode mode = TYPE_MODE (argtype);
function_arg_info arg (argtype, /*named=*/true);
reg = targetm.calls.function_arg (args_so_far, arg); reg = targetm.calls.function_arg (args_so_far, arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE if (TREE_CODE (arg.type) == REFERENCE_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (argtype)) && INTEGRAL_TYPE_P (TREE_TYPE (arg.type))
&& reg && reg
&& REG_P (reg) && REG_P (reg)
&& GET_MODE (reg) == mode && GET_MODE (reg) == arg.mode
&& (GET_MODE_CLASS (mode) == MODE_INT && (GET_MODE_CLASS (arg.mode) == MODE_INT
|| GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT)
&& REG_P (x) && REG_P (x)
&& REGNO (x) == REGNO (reg) && REGNO (x) == REGNO (reg)
&& GET_MODE (x) == mode && GET_MODE (x) == arg.mode
&& item) && item)
{ {
machine_mode indmode machine_mode indmode
= TYPE_MODE (TREE_TYPE (argtype)); = TYPE_MODE (TREE_TYPE (arg.type));
rtx mem = gen_rtx_MEM (indmode, x); rtx mem = gen_rtx_MEM (indmode, x);
cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode); cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
if (val && cselib_preserved_value_p (val)) if (val && cselib_preserved_value_p (val))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment