poly_int: cfgexpand stack variables
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 21 Dec 2017 07:01:10 +0000 (07:01 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 21 Dec 2017 07:01:10 +0000 (07:01 +0000)
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

gcc/ChangeLog
gcc/cfgexpand.c

index 729ce4eaf03d8b916756efce3392db6fda97dfe0..30abd3dea011cd3163125affcd30c5f48145a7b8 100644 (file)
@@ -1,3 +1,18 @@
+2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
+           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>
index 32c48ac6a3b3f147e1e2321179deb707109a988d..60fb137a540ad546a08f9623b30e3a5c80854892 100644 (file)
@@ -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. */