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