From 5e48d89420f8b16c1eddb9b568c4fee74eefbd45 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 21 Dec 2017 07:01:10 +0000 Subject: [PATCH] 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 Alan Hayward David Sherwood 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 Co-Authored-By: David Sherwood From-SVN: r255922 --- gcc/ChangeLog | 15 +++++++++ gcc/cfgexpand.c | 82 ++++++++++++++++++++++++------------------------- 2 files changed, 56 insertions(+), 41 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 729ce4eaf03..30abd3dea01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2017-12-21 Richard Sandiford + Alan Hayward + David Sherwood + + * 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 Alan Hayward David Sherwood diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 32c48ac6a3b..60fb137a540 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -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. */ -- 2.30.2