Commit 5e48d894 by Richard Sandiford Committed by Richard Sandiford

poly_int: cfgexpand stack variables

This patch changes the type of stack_var::size from HOST_WIDE_INT
to poly_uint64.  The difference in signedness is because the
field was set by:

  v->size = tree_to_uhwi (size);

2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* cfgexpand.c (stack_var::size): Change from a HOST_WIDE_INT
	to a poly_uint64.
	(add_stack_var, stack_var_cmp, partition_stack_vars)
	(dump_stack_var_partition): Update accordingly.
	(alloc_stack_frame_space): Take the size as a poly_int64 rather
	than a HOST_WIDE_INT.
	(expand_stack_vars, expand_one_stack_var_1): Handle polynomial sizes.
	(defer_stack_allocation, estimated_stack_frame_size): Likewise.
	(account_stack_vars, expand_one_var): Likewise.  Return a poly_uint64
	rather than a HOST_WIDE_INT.

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

From-SVN: r255922
parent a20c5714
......@@ -2,6 +2,21 @@
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* cfgexpand.c (stack_var::size): Change from a HOST_WIDE_INT
to a poly_uint64.
(add_stack_var, stack_var_cmp, partition_stack_vars)
(dump_stack_var_partition): Update accordingly.
(alloc_stack_frame_space): Take the size as a poly_int64 rather
than a HOST_WIDE_INT.
(expand_stack_vars, expand_one_stack_var_1): Handle polynomial sizes.
(defer_stack_allocation, estimated_stack_frame_size): Likewise.
(account_stack_vars, expand_one_var): Likewise. Return a poly_uint64
rather than a HOST_WIDE_INT.
2017-12-21 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* target.def (return_pops_args): Treat both the input and output
sizes as poly_int64s rather than HOST_WIDE_INTS.
* targhooks.h (default_return_pops_args): Update accordingly.
......@@ -314,7 +314,7 @@ struct stack_var
/* Initially, the size of the variable. Later, the size of the partition,
if this variable becomes it's partition's representative. */
HOST_WIDE_INT size;
poly_uint64 size;
/* The *byte* alignment required for this variable. Or as, with the
size, the alignment for this partition. */
......@@ -390,7 +390,7 @@ align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
Return the frame offset. */
static poly_int64
alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
alloc_stack_frame_space (poly_int64 size, unsigned HOST_WIDE_INT align)
{
poly_int64 offset, new_frame_offset;
......@@ -443,10 +443,10 @@ add_stack_var (tree decl)
tree size = TREE_CODE (decl) == SSA_NAME
? TYPE_SIZE_UNIT (TREE_TYPE (decl))
: DECL_SIZE_UNIT (decl);
v->size = tree_to_uhwi (size);
v->size = tree_to_poly_uint64 (size);
/* Ensure that all variables have size, so that &a != &b for any two
variables that are simultaneously live. */
if (v->size == 0)
if (known_eq (v->size, 0U))
v->size = 1;
v->alignb = align_local_variable (decl);
/* An alignment of zero can mightily confuse us later. */
......@@ -676,8 +676,8 @@ stack_var_cmp (const void *a, const void *b)
size_t ib = *(const size_t *)b;
unsigned int aligna = stack_vars[ia].alignb;
unsigned int alignb = stack_vars[ib].alignb;
HOST_WIDE_INT sizea = stack_vars[ia].size;
HOST_WIDE_INT sizeb = stack_vars[ib].size;
poly_int64 sizea = stack_vars[ia].size;
poly_int64 sizeb = stack_vars[ib].size;
tree decla = stack_vars[ia].decl;
tree declb = stack_vars[ib].decl;
bool largea, largeb;
......@@ -690,10 +690,9 @@ stack_var_cmp (const void *a, const void *b)
return (int)largeb - (int)largea;
/* Secondary compare on size, decreasing */
if (sizea > sizeb)
return -1;
if (sizea < sizeb)
return 1;
int diff = compare_sizes_for_sort (sizeb, sizea);
if (diff != 0)
return diff;
/* Tertiary compare on true alignment, decreasing. */
if (aligna < alignb)
......@@ -904,7 +903,7 @@ partition_stack_vars (void)
{
size_t i = stack_vars_sorted[si];
unsigned int ialign = stack_vars[i].alignb;
HOST_WIDE_INT isize = stack_vars[i].size;
poly_int64 isize = stack_vars[i].size;
/* Ignore objects that aren't partition representatives. If we
see a var that is not a partition representative, it must
......@@ -916,7 +915,7 @@ partition_stack_vars (void)
{
size_t j = stack_vars_sorted[sj];
unsigned int jalign = stack_vars[j].alignb;
HOST_WIDE_INT jsize = stack_vars[j].size;
poly_int64 jsize = stack_vars[j].size;
/* Ignore objects that aren't partition representatives. */
if (stack_vars[j].representative != j)
......@@ -932,8 +931,8 @@ partition_stack_vars (void)
sizes, as the shorter vars wouldn't be adequately protected.
Don't do that for "large" (unsupported) alignment objects,
those aren't protected anyway. */
if ((asan_sanitize_stack_p ())
&& isize != jsize
if (asan_sanitize_stack_p ()
&& maybe_ne (isize, jsize)
&& ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
break;
......@@ -964,9 +963,9 @@ dump_stack_var_partition (void)
if (stack_vars[i].representative != i)
continue;
fprintf (dump_file, "Partition %lu: size " HOST_WIDE_INT_PRINT_DEC
" align %u\n", (unsigned long) i, stack_vars[i].size,
stack_vars[i].alignb);
fprintf (dump_file, "Partition %lu: size ", (unsigned long) i);
print_dec (stack_vars[i].size, dump_file);
fprintf (dump_file, " align %u\n", stack_vars[i].alignb);
for (j = i; j != EOC; j = stack_vars[j].next)
{
......@@ -1042,7 +1041,7 @@ static void
expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
{
size_t si, i, j, n = stack_vars_num;
HOST_WIDE_INT large_size = 0, large_alloc = 0;
poly_uint64 large_size = 0, large_alloc = 0;
rtx large_base = NULL;
unsigned large_align = 0;
bool large_allocation_done = false;
......@@ -1085,8 +1084,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
: DECL_RTL (decl) != pc_rtx)
continue;
large_size += alignb - 1;
large_size &= -(HOST_WIDE_INT)alignb;
large_size = aligned_upper_bound (large_size, alignb);
large_size += stack_vars[i].size;
}
}
......@@ -1125,7 +1123,8 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
HOST_WIDE_INT prev_offset;
if (asan_sanitize_stack_p ()
&& pred
&& frame_offset.is_constant (&prev_offset))
&& frame_offset.is_constant (&prev_offset)
&& stack_vars[i].size.is_constant ())
{
prev_offset = align_base (prev_offset,
MAX (alignb, ASAN_RED_ZONE_SIZE),
......@@ -1184,23 +1183,22 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
/* If there were any variables requiring "large" alignment, allocate
space. */
if (large_size > 0 && ! large_allocation_done)
if (maybe_ne (large_size, 0U) && ! large_allocation_done)
{
poly_int64 loffset;
rtx large_allocsize;
large_allocsize = GEN_INT (large_size);
large_allocsize = gen_int_mode (large_size, Pmode);
get_dynamic_stack_size (&large_allocsize, 0, large_align, NULL);
loffset = alloc_stack_frame_space
(INTVAL (large_allocsize),
(rtx_to_poly_int64 (large_allocsize),
PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT);
large_base = get_dynamic_stack_base (loffset, large_align);
large_allocation_done = true;
}
gcc_assert (large_base != NULL);
large_alloc += alignb - 1;
large_alloc &= -(HOST_WIDE_INT)alignb;
large_alloc = aligned_upper_bound (large_alloc, alignb);
offset = large_alloc;
large_alloc += stack_vars[i].size;
......@@ -1218,15 +1216,15 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
}
}
gcc_assert (large_alloc == large_size);
gcc_assert (known_eq (large_alloc, large_size));
}
/* Take into account all sizes of partitions and reset DECL_RTLs. */
static HOST_WIDE_INT
static poly_uint64
account_stack_vars (void)
{
size_t si, j, i, n = stack_vars_num;
HOST_WIDE_INT size = 0;
poly_uint64 size = 0;
for (si = 0; si < n; ++si)
{
......@@ -1289,19 +1287,19 @@ set_parm_rtl (tree parm, rtx x)
static void
expand_one_stack_var_1 (tree var)
{
HOST_WIDE_INT size;
poly_uint64 size;
poly_int64 offset;
unsigned byte_align;
if (TREE_CODE (var) == SSA_NAME)
{
tree type = TREE_TYPE (var);
size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
size = tree_to_poly_uint64 (TYPE_SIZE_UNIT (type));
byte_align = TYPE_ALIGN_UNIT (type);
}
else
{
size = tree_to_uhwi (DECL_SIZE_UNIT (var));
size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var));
byte_align = align_local_variable (var);
}
......@@ -1513,12 +1511,14 @@ defer_stack_allocation (tree var, bool toplevel)
tree size_unit = TREE_CODE (var) == SSA_NAME
? TYPE_SIZE_UNIT (TREE_TYPE (var))
: DECL_SIZE_UNIT (var);
poly_uint64 size;
/* Whether the variable is small enough for immediate allocation not to be
a problem with regard to the frame size. */
bool smallish
= ((HOST_WIDE_INT) tree_to_uhwi (size_unit)
< PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING));
= (poly_int_tree_p (size_unit, &size)
&& (estimated_poly_value (size)
< PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)));
/* If stack protection is enabled, *all* stack variables must be deferred,
so that we can re-order the strings to the top of the frame.
......@@ -1572,7 +1572,7 @@ defer_stack_allocation (tree var, bool toplevel)
Return stack usage this variable is supposed to take.
*/
static HOST_WIDE_INT
static poly_uint64
expand_one_var (tree var, bool toplevel, bool really_expand)
{
unsigned int align = BITS_PER_UNIT;
......@@ -1615,6 +1615,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
record_alignment_for_reg_var (align);
poly_uint64 size;
if (TREE_CODE (origvar) == SSA_NAME)
{
gcc_assert (!VAR_P (var)
......@@ -1655,7 +1656,8 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
if (really_expand)
expand_one_register_var (origvar);
}
else if (! valid_constant_size_p (DECL_SIZE_UNIT (var)))
else if (!poly_int_tree_p (DECL_SIZE_UNIT (var), &size)
|| !valid_constant_size_p (DECL_SIZE_UNIT (var)))
{
/* Reject variables which cover more than half of the address-space. */
if (really_expand)
......@@ -1677,9 +1679,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
expand_one_stack_var (origvar);
}
return tree_to_uhwi (DECL_SIZE_UNIT (var));
return size;
}
return 0;
}
......@@ -1932,7 +1932,7 @@ fini_vars_expansion (void)
HOST_WIDE_INT
estimated_stack_frame_size (struct cgraph_node *node)
{
HOST_WIDE_INT size = 0;
poly_int64 size = 0;
size_t i;
tree var;
struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
......@@ -1956,7 +1956,7 @@ estimated_stack_frame_size (struct cgraph_node *node)
fini_vars_expansion ();
pop_cfun ();
return size;
return estimated_poly_value (size);
}
/* Helper routine to check if a record or union contains an array field. */
......
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