Commit 95fe7b48 by Richard Sandiford Committed by Richard Sandiford

poly_int: load_register_parameters

This patch makes load_register_parameters cope with polynomial sizes.
The requirement here is that any register parameters with non-constant
sizes must either have a specific mode (e.g. a variable-length vector
mode) or must be represented with a PARALLEL.  This is in practice
already a requirement for parameters passed in vector registers,
since the default behaviour of splitting parameters into words doesn't
make sense for them.

2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* calls.c (load_register_parameters): Cope with polynomial
	mode sizes.  Require a constant size for BLKmode parameters
	that aren't described by a PARALLEL.  If BLOCK_REG_PADDING
	forces a parameter to be padded at the lsb end in order to
	fill a complete number of words, require the parameter size
	to be ordered wrt UNITS_PER_WORD.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r256161
parent cff7107a
...@@ -2,6 +2,17 @@ ...@@ -2,6 +2,17 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
* calls.c (load_register_parameters): Cope with polynomial
mode sizes. Require a constant size for BLKmode parameters
that aren't described by a PARALLEL. If BLOCK_REG_PADDING
forces a parameter to be padded at the lsb end in order to
fill a complete number of words, require the parameter size
to be ordered wrt UNITS_PER_WORD.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* reload1.c (spill_stack_slot_width): Change element type * reload1.c (spill_stack_slot_width): Change element type
from unsigned int to poly_uint64_pod. from unsigned int to poly_uint64_pod.
(alter_reg): Treat mode sizes as polynomial. (alter_reg): Treat mode sizes as polynomial.
...@@ -2709,7 +2709,8 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2709,7 +2709,8 @@ load_register_parameters (struct arg_data *args, int num_actuals,
{ {
int partial = args[i].partial; int partial = args[i].partial;
int nregs; int nregs;
int size = 0; poly_int64 size = 0;
HOST_WIDE_INT const_size = 0;
rtx_insn *before_arg = get_last_insn (); rtx_insn *before_arg = get_last_insn ();
/* Set non-negative if we must move a word at a time, even if /* Set non-negative if we must move a word at a time, even if
just one word (e.g, partial == 4 && mode == DFmode). Set just one word (e.g, partial == 4 && mode == DFmode). Set
...@@ -2725,8 +2726,12 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2725,8 +2726,12 @@ load_register_parameters (struct arg_data *args, int num_actuals,
} }
else if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode) else if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode)
{ {
size = int_size_in_bytes (TREE_TYPE (args[i].tree_value)); /* Variable-sized parameters should be described by a
nregs = (size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; PARALLEL instead. */
const_size = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
gcc_assert (const_size >= 0);
nregs = (const_size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
size = const_size;
} }
else else
size = GET_MODE_SIZE (args[i].mode); size = GET_MODE_SIZE (args[i].mode);
...@@ -2748,21 +2753,27 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2748,21 +2753,27 @@ load_register_parameters (struct arg_data *args, int num_actuals,
/* Handle case where we have a value that needs shifting /* Handle case where we have a value that needs shifting
up to the msb. eg. a QImode value and we're padding up to the msb. eg. a QImode value and we're padding
upward on a BYTES_BIG_ENDIAN machine. */ upward on a BYTES_BIG_ENDIAN machine. */
if (size < UNITS_PER_WORD if (args[i].locate.where_pad
&& (args[i].locate.where_pad == (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD))
== (BYTES_BIG_ENDIAN ? PAD_UPWARD : PAD_DOWNWARD)))
{ {
rtx x; gcc_checking_assert (ordered_p (size, UNITS_PER_WORD));
int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT; if (maybe_lt (size, UNITS_PER_WORD))
{
/* Assigning REG here rather than a temp makes CALL_FUSAGE rtx x;
report the whole reg as used. Strictly speaking, the poly_int64 shift
call only uses SIZE bytes at the msb end, but it doesn't = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
seem worth generating rtl to say that. */
reg = gen_rtx_REG (word_mode, REGNO (reg)); /* Assigning REG here rather than a temp makes
x = expand_shift (LSHIFT_EXPR, word_mode, reg, shift, reg, 1); CALL_FUSAGE report the whole reg as used.
if (x != reg) Strictly speaking, the call only uses SIZE
emit_move_insn (reg, x); bytes at the msb end, but it doesn't seem worth
generating rtl to say that. */
reg = gen_rtx_REG (word_mode, REGNO (reg));
x = expand_shift (LSHIFT_EXPR, word_mode,
reg, shift, reg, 1);
if (x != reg)
emit_move_insn (reg, x);
}
} }
#endif #endif
} }
...@@ -2777,17 +2788,20 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2777,17 +2788,20 @@ load_register_parameters (struct arg_data *args, int num_actuals,
else if (partial == 0 || args[i].pass_on_stack) else if (partial == 0 || args[i].pass_on_stack)
{ {
/* SIZE and CONST_SIZE are 0 for partial arguments and
the size of a BLKmode type otherwise. */
gcc_checking_assert (known_eq (size, const_size));
rtx mem = validize_mem (copy_rtx (args[i].value)); rtx mem = validize_mem (copy_rtx (args[i].value));
/* Check for overlap with already clobbered argument area, /* Check for overlap with already clobbered argument area,
providing that this has non-zero size. */ providing that this has non-zero size. */
if (is_sibcall if (is_sibcall
&& size != 0 && const_size != 0
&& (mem_might_overlap_already_clobbered_arg_p && (mem_might_overlap_already_clobbered_arg_p
(XEXP (args[i].value, 0), size))) (XEXP (args[i].value, 0), const_size)))
*sibcall_failure = 1; *sibcall_failure = 1;
if (size % UNITS_PER_WORD == 0 if (const_size % UNITS_PER_WORD == 0
|| MEM_ALIGN (mem) % BITS_PER_WORD == 0) || MEM_ALIGN (mem) % BITS_PER_WORD == 0)
move_block_to_reg (REGNO (reg), mem, nregs, args[i].mode); move_block_to_reg (REGNO (reg), mem, nregs, args[i].mode);
else else
...@@ -2797,7 +2811,7 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2797,7 +2811,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
args[i].mode); args[i].mode);
rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1); rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1);
unsigned int bitoff = (nregs - 1) * BITS_PER_WORD; unsigned int bitoff = (nregs - 1) * BITS_PER_WORD;
unsigned int bitsize = size * BITS_PER_UNIT - bitoff; unsigned int bitsize = const_size * BITS_PER_UNIT - bitoff;
rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest, rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest,
word_mode, word_mode, false, word_mode, word_mode, false,
NULL); NULL);
...@@ -2809,7 +2823,7 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2809,7 +2823,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
} }
/* Handle a BLKmode that needs shifting. */ /* Handle a BLKmode that needs shifting. */
if (nregs == 1 && size < UNITS_PER_WORD if (nregs == 1 && const_size < UNITS_PER_WORD
#ifdef BLOCK_REG_PADDING #ifdef BLOCK_REG_PADDING
&& args[i].locate.where_pad == PAD_DOWNWARD && args[i].locate.where_pad == PAD_DOWNWARD
#else #else
...@@ -2818,7 +2832,7 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -2818,7 +2832,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
) )
{ {
rtx dest = gen_rtx_REG (word_mode, REGNO (reg)); rtx dest = gen_rtx_REG (word_mode, REGNO (reg));
int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT; int shift = (UNITS_PER_WORD - const_size) * BITS_PER_UNIT;
enum tree_code dir = (BYTES_BIG_ENDIAN enum tree_code dir = (BYTES_BIG_ENDIAN
? RSHIFT_EXPR : LSHIFT_EXPR); ? RSHIFT_EXPR : LSHIFT_EXPR);
rtx x; rtx x;
......
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