coarray_data_1.f90: Link against libatomic if target libatomic_available.
[gcc.git] / gcc / stor-layout.c
index 7730ac33e4f62673f021ee95610c2e5e2e2843cb..5d6f2e0166cee4da93235c66dd0d3dfdeefff5a6 100644 (file)
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -298,22 +298,22 @@ finalize_size_functions (void)
    MAX_FIXED_MODE_SIZE.  */
 
 opt_machine_mode
-mode_for_size (unsigned int size, enum mode_class mclass, int limit)
+mode_for_size (poly_uint64 size, enum mode_class mclass, int limit)
 {
   machine_mode mode;
   int i;
 
-  if (limit && size > MAX_FIXED_MODE_SIZE)
+  if (limit && maybe_gt (size, (unsigned int) MAX_FIXED_MODE_SIZE))
     return opt_machine_mode ();
 
   /* Get the first mode which has this size, in the specified class.  */
   FOR_EACH_MODE_IN_CLASS (mode, mclass)
-    if (GET_MODE_PRECISION (mode) == size)
+    if (known_eq (GET_MODE_PRECISION (mode), size))
       return mode;
 
   if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
     for (i = 0; i < NUM_INT_N_ENTS; i ++)
-      if (int_n_data[i].bitsize == size
+      if (known_eq (int_n_data[i].bitsize, size)
          && int_n_enabled_p[i])
        return int_n_data[i].m;
 
@@ -341,7 +341,7 @@ mode_for_size_tree (const_tree size, enum mode_class mclass, int limit)
    SIZE bits.  Abort if no such mode exists.  */
 
 machine_mode
-smallest_mode_for_size (unsigned int size, enum mode_class mclass)
+smallest_mode_for_size (poly_uint64 size, enum mode_class mclass)
 {
   machine_mode mode = VOIDmode;
   int i;
@@ -349,19 +349,18 @@ smallest_mode_for_size (unsigned int size, enum mode_class mclass)
   /* Get the first mode which has at least this size, in the
      specified class.  */
   FOR_EACH_MODE_IN_CLASS (mode, mclass)
-    if (GET_MODE_PRECISION (mode) >= size)
+    if (known_ge (GET_MODE_PRECISION (mode), size))
       break;
 
+  gcc_assert (mode != VOIDmode);
+
   if (mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
     for (i = 0; i < NUM_INT_N_ENTS; i ++)
-      if (int_n_data[i].bitsize >= size
-         && int_n_data[i].bitsize < GET_MODE_PRECISION (mode)
+      if (known_ge (int_n_data[i].bitsize, size)
+         && known_lt (int_n_data[i].bitsize, GET_MODE_PRECISION (mode))
          && int_n_enabled_p[i])
        mode = int_n_data[i].m;
 
-  if (mode == VOIDmode)
-    gcc_unreachable ();
-
   return mode;
 }
 
@@ -380,17 +379,17 @@ int_mode_for_mode (machine_mode mode)
     case MODE_COMPLEX_FLOAT:
     case MODE_FLOAT:
     case MODE_DECIMAL_FLOAT:
-    case MODE_VECTOR_INT:
-    case MODE_VECTOR_FLOAT:
     case MODE_FRACT:
     case MODE_ACCUM:
     case MODE_UFRACT:
     case MODE_UACCUM:
+    case MODE_VECTOR_BOOL:
+    case MODE_VECTOR_INT:
+    case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_FRACT:
     case MODE_VECTOR_ACCUM:
     case MODE_VECTOR_UFRACT:
     case MODE_VECTOR_UACCUM:
-    case MODE_POINTER_BOUNDS:
       return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
 
     case MODE_RANDOM:
@@ -412,7 +411,6 @@ opt_machine_mode
 bitwise_mode_for_mode (machine_mode mode)
 {
   /* Quick exit if we already have a suitable mode.  */
-  unsigned int bitsize = GET_MODE_BITSIZE (mode);
   scalar_int_mode int_mode;
   if (is_a <scalar_int_mode> (mode, &int_mode)
       && GET_MODE_BITSIZE (int_mode) <= MAX_FIXED_MODE_SIZE)
@@ -421,6 +419,8 @@ bitwise_mode_for_mode (machine_mode mode)
   /* Reuse the sanity checks from int_mode_for_mode.  */
   gcc_checking_assert ((int_mode_for_mode (mode), true));
 
+  poly_int64 bitsize = GET_MODE_BITSIZE (mode);
+
   /* Try to replace complex modes with complex modes.  In general we
      expect both components to be processed independently, so we only
      care whether there is a register for the inner mode.  */
@@ -435,7 +435,8 @@ bitwise_mode_for_mode (machine_mode mode)
 
   /* Try to replace vector modes with vector modes.  Also try using vector
      modes if an integer mode would be too big.  */
-  if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
+  if (VECTOR_MODE_P (mode)
+      || maybe_gt (bitsize, MAX_FIXED_MODE_SIZE))
     {
       machine_mode trial = mode;
       if ((GET_MODE_CLASS (trial) == MODE_VECTOR_INT
@@ -476,7 +477,7 @@ bitwise_type_for_mode (machine_mode mode)
    either an integer mode or a vector mode.  */
 
 opt_machine_mode
-mode_for_vector (scalar_mode innermode, unsigned nunits)
+mode_for_vector (scalar_mode innermode, poly_uint64 nunits)
 {
   machine_mode mode;
 
@@ -497,14 +498,14 @@ mode_for_vector (scalar_mode innermode, unsigned nunits)
   /* Do not check vector_mode_supported_p here.  We'll do that
      later in vector_type_mode.  */
   FOR_EACH_MODE_FROM (mode, mode)
-    if (GET_MODE_NUNITS (mode) == nunits
+    if (known_eq (GET_MODE_NUNITS (mode), nunits)
        && GET_MODE_INNER (mode) == innermode)
       return mode;
 
   /* For integers, try mapping it to a same-sized scalar mode.  */
   if (GET_MODE_CLASS (innermode) == MODE_INT)
     {
-      unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
+      poly_uint64 nbits = nunits * GET_MODE_BITSIZE (innermode);
       if (int_mode_for_size (nbits, 0).exists (&mode)
          && have_regs_of_mode[mode])
        return mode;
@@ -518,7 +519,7 @@ mode_for_vector (scalar_mode innermode, unsigned nunits)
    an integer mode or a vector mode.  */
 
 opt_machine_mode
-mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
+mode_for_int_vector (unsigned int int_bits, poly_uint64 nunits)
 {
   scalar_int_mode int_mode;
   machine_mode vec_mode;
@@ -544,7 +545,8 @@ static machine_mode
 mode_for_array (tree elem_type, tree size)
 {
   tree elem_size;
-  unsigned HOST_WIDE_INT int_size, int_elem_size;
+  poly_uint64 int_size, int_elem_size;
+  unsigned HOST_WIDE_INT num_elems;
   bool limit_p;
 
   /* One-element arrays get the component type's mode.  */
@@ -553,14 +555,16 @@ mode_for_array (tree elem_type, tree size)
     return TYPE_MODE (elem_type);
 
   limit_p = true;
-  if (tree_fits_uhwi_p (size) && tree_fits_uhwi_p (elem_size))
+  if (poly_int_tree_p (size, &int_size)
+      && poly_int_tree_p (elem_size, &int_elem_size)
+      && maybe_ne (int_elem_size, 0U)
+      && constant_multiple_p (int_size, int_elem_size, &num_elems))
     {
-      int_size = tree_to_uhwi (size);
-      int_elem_size = tree_to_uhwi (elem_size);
-      if (int_elem_size > 0
-         && int_size % int_elem_size == 0
-         && targetm.array_mode_supported_p (TYPE_MODE (elem_type),
-                                            int_size / int_elem_size))
+      machine_mode elem_mode = TYPE_MODE (elem_type);
+      machine_mode mode;
+      if (targetm.array_mode (elem_mode, num_elems).exists (&mode))
+       return mode;
+      if (targetm.array_mode_supported_p (elem_mode, num_elems))
        limit_p = false;
     }
   return mode_for_size_tree (size, MODE_INT, limit_p).else_blk ();
@@ -751,22 +755,24 @@ layout_decl (tree decl, unsigned int known_align)
     DECL_SIZE_UNIT (decl) = variable_size (DECL_SIZE_UNIT (decl));
 
   /* If requested, warn about definitions of large data objects.  */
-  if (warn_larger_than
-      && (code == VAR_DECL || code == PARM_DECL)
-      && ! DECL_EXTERNAL (decl))
+  if ((code == PARM_DECL || (code == VAR_DECL && !DECL_NONLOCAL_FRAME (decl)))
+      && !DECL_EXTERNAL (decl))
     {
       tree size = DECL_SIZE_UNIT (decl);
 
-      if (size != 0 && TREE_CODE (size) == INTEGER_CST
-         && compare_tree_int (size, larger_than_size) > 0)
+      if (size != 0 && TREE_CODE (size) == INTEGER_CST)
        {
-         int size_as_int = TREE_INT_CST_LOW (size);
-
-         if (compare_tree_int (size, size_as_int) == 0)
-           warning (OPT_Wlarger_than_, "size of %q+D is %d bytes", decl, size_as_int);
-         else
-           warning (OPT_Wlarger_than_, "size of %q+D is larger than %wd bytes",
-                     decl, larger_than_size);
+         /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated
+            as if PTRDIFF_MAX had been specified, with the value
+            being that on the target rather than the host.  */
+         unsigned HOST_WIDE_INT max_size = warn_larger_than_size;
+         if (max_size == HOST_WIDE_INT_MAX)
+           max_size = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+
+         if (compare_tree_int (size, max_size) > 0)
+           warning (OPT_Wlarger_than_, "size of %q+D %E bytes exceeds "
+                    "maximum object size %wu",
+                    decl, size, max_size);
        }
     }
 
@@ -842,6 +848,28 @@ start_record_layout (tree t)
   return rli;
 }
 
+/* Fold sizetype value X to bitsizetype, given that X represents a type
+   size or offset.  */
+
+static tree
+bits_from_bytes (tree x)
+{
+  if (POLY_INT_CST_P (x))
+    /* The runtime calculation isn't allowed to overflow sizetype;
+       increasing the runtime values must always increase the size
+       or offset of the object.  This means that the object imposes
+       a maximum value on the runtime parameters, but we don't record
+       what that is.  */
+    return build_poly_int_cst
+      (bitsizetype,
+       poly_wide_int::from (poly_int_cst_value (x),
+                           TYPE_PRECISION (bitsizetype),
+                           TYPE_SIGN (TREE_TYPE (x))));
+  x = fold_convert (bitsizetype, x);
+  gcc_checking_assert (x);
+  return x;
+}
+
 /* Return the combined bit position for the byte offset OFFSET and the
    bit position BITPOS.
 
@@ -855,8 +883,7 @@ tree
 bit_from_pos (tree offset, tree bitpos)
 {
   return size_binop (PLUS_EXPR, bitpos,
-                    size_binop (MULT_EXPR,
-                                fold_convert (bitsizetype, offset),
+                    size_binop (MULT_EXPR, bits_from_bytes (offset),
                                 bitsize_unit_node));
 }
 
@@ -942,7 +969,7 @@ debug_rli (record_layout_info rli)
   if (!vec_safe_is_empty (rli->pending_statics))
     {
       fprintf (stderr, "pending statics:\n");
-      debug_vec_tree (rli->pending_statics);
+      debug (rli->pending_statics);
     }
 }
 
@@ -1012,7 +1039,7 @@ update_alignment_for_field (record_layout_info rli, tree field,
         the type, except that for zero-size bitfields this only
         applies if there was an immediately prior, nonzero-size
         bitfield.  (That's the way it is, experimentally.) */
-      if ((!is_bitfield && !DECL_PACKED (field))
+      if (!is_bitfield
          || ((DECL_SIZE (field) == NULL_TREE
               || !integer_zerop (DECL_SIZE (field)))
              ? !DECL_PACKED (field)
@@ -1021,7 +1048,10 @@ update_alignment_for_field (record_layout_info rli, tree field,
                 && ! integer_zerop (DECL_SIZE (rli->prev_field)))))
        {
          unsigned int type_align = TYPE_ALIGN (type);
-         type_align = MAX (type_align, desired_align);
+         if (!is_bitfield && DECL_PACKED (field))
+           type_align = desired_align;
+         else
+           type_align = MAX (type_align, desired_align);
          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
          rli->record_align = MAX (rli->record_align, type_align);
@@ -1124,12 +1154,16 @@ handle_warn_if_not_align (tree field, unsigned int record_align)
     warning (opt_w, "alignment %u of %qT is less than %u",
             record_align, context, warn_if_not_align);
 
-  unsigned HOST_WIDE_INT off
-    = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
-       + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) / BITS_PER_UNIT);
-  if ((off % warn_if_not_align) != 0)
-    warning (opt_w, "%q+D offset %wu in %qT isn't aligned to %u",
-            field, off, context, warn_if_not_align);
+  tree off = byte_position (field);
+  if (!multiple_of_p (TREE_TYPE (off), off, size_int (warn_if_not_align)))
+    {
+      if (TREE_CODE (off) == INTEGER_CST)
+       warning (opt_w, "%q+D offset %E in %qT isn%'t aligned to %u",
+                field, off, context, warn_if_not_align);
+      else
+       warning (opt_w, "%q+D offset %E in %qT may not be aligned to %u",
+                field, off, context, warn_if_not_align);
+    }
 }
 
 /* Called from place_field to handle unions.  */
@@ -1273,7 +1307,9 @@ place_field (record_layout_info rli, tree field)
 
   /* Does this field automatically have alignment it needs by virtue
      of the fields that precede it and the record's own alignment?  */
-  if (known_align < desired_align)
+  if (known_align < desired_align
+      && (! targetm.ms_bitfield_layout_p (rli->t)
+         || rli->prev_field == NULL))
     {
       /* No, we need to skip space before this field.
         Bump the cumulative size to multiple of field alignment.  */
@@ -1301,8 +1337,6 @@ place_field (record_layout_info rli, tree field)
 
       if (! TREE_CONSTANT (rli->offset))
        rli->offset_align = desired_align;
-      if (targetm.ms_bitfield_layout_p (rli->t))
-       rli->prev_field = NULL;
     }
 
   /* Handle compatibility with PCC.  Note that if the record has any
@@ -1418,6 +1452,8 @@ place_field (record_layout_info rli, tree field)
       /* This is a bitfield if it exists.  */
       if (rli->prev_field)
        {
+         bool realign_p = known_align < desired_align;
+
          /* If both are bitfields, nonzero, and the same size, this is
             the middle of a run.  Zero declared size fields are special
             and handled as "end of run". (Note: it's nonzero declared
@@ -1451,7 +1487,10 @@ place_field (record_layout_info rli, tree field)
                    rli->remaining_in_alignment = typesize - bitsize;
                }
              else
-               rli->remaining_in_alignment -= bitsize;
+               {
+                 rli->remaining_in_alignment -= bitsize;
+                 realign_p = false;
+               }
            }
          else
            {
@@ -1482,6 +1521,31 @@ place_field (record_layout_info rli, tree field)
                rli->prev_field = NULL;
            }
 
+         /* Does this field automatically have alignment it needs by virtue
+            of the fields that precede it and the record's own alignment?  */
+         if (realign_p)
+           {
+             /* If the alignment is still within offset_align, just align
+                the bit position.  */
+             if (desired_align < rli->offset_align)
+               rli->bitpos = round_up (rli->bitpos, desired_align);
+             else
+               {
+                 /* First adjust OFFSET by the partial bits, then align.  */
+                 tree d = size_binop (CEIL_DIV_EXPR, rli->bitpos,
+                                      bitsize_unit_node);
+                 rli->offset = size_binop (PLUS_EXPR, rli->offset,
+                                           fold_convert (sizetype, d));
+                 rli->bitpos = bitsize_zero_node;
+
+                 rli->offset = round_up (rli->offset,
+                                         desired_align / BITS_PER_UNIT);
+               }
+
+             if (! TREE_CONSTANT (rli->offset))
+               rli->offset_align = desired_align;
+           }
+
          normalize_rli (rli);
         }
 
@@ -1500,7 +1564,7 @@ place_field (record_layout_info rli, tree field)
       if (!DECL_BIT_FIELD_TYPE (field)
          || (prev_saved != NULL
              ? !simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type))
-             : !integer_zerop (DECL_SIZE (field)) ))
+             : !integer_zerop (DECL_SIZE (field))))
        {
          /* Never smaller than a byte for compatibility.  */
          unsigned int type_align = BITS_PER_UNIT;
@@ -1525,7 +1589,8 @@ place_field (record_layout_info rli, tree field)
            }
 
          /* Now align (conventionally) for the new type.  */
-         type_align = TYPE_ALIGN (TREE_TYPE (field));
+         if (! DECL_PACKED (field))
+           type_align = TYPE_ALIGN (TREE_TYPE (field));
 
          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
@@ -1592,19 +1657,50 @@ place_field (record_layout_info rli, tree field)
        = size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
       rli->bitpos = bitsize_zero_node;
       rli->offset_align = MIN (rli->offset_align, desired_align);
+
+      if (!multiple_of_p (bitsizetype, DECL_SIZE (field),
+                         bitsize_int (rli->offset_align)))
+       {
+         tree type = strip_array_types (TREE_TYPE (field));
+         /* The above adjusts offset_align just based on the start of the
+            field.  The field might not have a size that is a multiple of
+            that offset_align though.  If the field is an array of fixed
+            sized elements, assume there can be any multiple of those
+            sizes.  If it is a variable length aggregate or array of
+            variable length aggregates, assume worst that the end is
+            just BITS_PER_UNIT aligned.  */
+         if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+           {
+             if (TREE_INT_CST_LOW (TYPE_SIZE (type)))
+               {
+                 unsigned HOST_WIDE_INT sz
+                   = least_bit_hwi (TREE_INT_CST_LOW (TYPE_SIZE (type)));
+                 rli->offset_align = MIN (rli->offset_align, sz);
+               }
+           }
+         else
+           rli->offset_align = MIN (rli->offset_align, BITS_PER_UNIT);
+       }
     }
   else if (targetm.ms_bitfield_layout_p (rli->t))
     {
       rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
 
-      /* If we ended a bitfield before the full length of the type then
-        pad the struct out to the full length of the last type.  */
-      if ((DECL_CHAIN (field) == NULL
-          || TREE_CODE (DECL_CHAIN (field)) != FIELD_DECL)
-         && DECL_BIT_FIELD_TYPE (field)
+      /* If FIELD is the last field and doesn't end at the full length
+        of the type then pad the struct out to the full length of the
+        last type.  */
+      if (DECL_BIT_FIELD_TYPE (field)
          && !integer_zerop (DECL_SIZE (field)))
-       rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
-                                 bitsize_int (rli->remaining_in_alignment));
+       {
+         /* We have to scan, because non-field DECLS are also here.  */
+         tree probe = field;
+         while ((probe = DECL_CHAIN (probe)))
+           if (TREE_CODE (probe) == FIELD_DECL)
+             break;
+         if (!probe)
+           rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
+                                     bitsize_int (rli->remaining_in_alignment));
+       }
 
       normalize_rli (rli);
     }
@@ -1738,7 +1834,13 @@ compute_record_mode (tree type)
       /* If this field is the whole struct, remember its mode so
         that, say, we can put a double in a class into a DF
         register instead of forcing it to live in the stack.  */
-      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field))
+         /* Partial int types (e.g. __int20) may have TYPE_SIZE equal to
+            wider types (e.g. int32), despite precision being less.  Ensure
+            that the TYPE_MODE of the struct does not get set to the partial
+            int mode if there is a wider type also in the struct.  */
+         && known_gt (GET_MODE_PRECISION (DECL_MODE (field)),
+                      GET_MODE_PRECISION (mode)))
        mode = DECL_MODE (field);
 
       /* With some targets, it is sub-optimal to access an aligned
@@ -1748,11 +1850,20 @@ compute_record_mode (tree type)
     }
 
   /* If we only have one real field; use its mode if that mode's size
-     matches the type's size.  This only applies to RECORD_TYPE.  This
-     does not apply to unions.  */
-  if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
-      && tree_fits_uhwi_p (TYPE_SIZE (type))
-      && GET_MODE_BITSIZE (mode) == tree_to_uhwi (TYPE_SIZE (type)))
+     matches the type's size.  This generally only applies to RECORD_TYPE.
+     For UNION_TYPE, if the widest field is MODE_INT then use that mode.
+     If the widest field is MODE_PARTIAL_INT, and the union will be passed
+     by reference, then use that mode.  */
+  poly_uint64 type_size;
+  if ((TREE_CODE (type) == RECORD_TYPE
+       || (TREE_CODE (type) == UNION_TYPE
+          && (GET_MODE_CLASS (mode) == MODE_INT
+              || (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+                  && targetm.calls.pass_by_reference (pack_cumulative_args (0),
+                                                      mode, type, 0)))))
+      && mode != VOIDmode
+      && poly_int_tree_p (TYPE_SIZE (type), &type_size)
+      && known_eq (GET_MODE_BITSIZE (mode), type_size))
     ;
   else
     mode = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1).else_blk ();
@@ -1829,6 +1940,9 @@ finalize_type_size (tree type)
       && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
     TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
 
+  /* Handle empty records as per the x86-64 psABI.  */
+  TYPE_EMPTY_P (type) = targetm.calls.empty_record_p (type);
+
   /* Also layout any other variants of the type.  */
   if (TYPE_NEXT_VARIANT (type)
       || type != TYPE_MAIN_VARIANT (type))
@@ -1841,6 +1955,7 @@ finalize_type_size (tree type)
       unsigned int precision = TYPE_PRECISION (type);
       unsigned int user_align = TYPE_USER_ALIGN (type);
       machine_mode mode = TYPE_MODE (type);
+      bool empty_p = TYPE_EMPTY_P (type);
 
       /* Copy it into all variants.  */
       for (variant = TYPE_MAIN_VARIANT (type);
@@ -1857,6 +1972,7 @@ finalize_type_size (tree type)
          SET_TYPE_ALIGN (variant, valign);
          TYPE_PRECISION (variant) = precision;
          SET_TYPE_MODE (variant, mode);
+         TYPE_EMPTY_P (variant) = empty_p;
        }
     }
 }
@@ -2248,11 +2364,9 @@ layout_type (tree type)
 
     case VECTOR_TYPE:
       {
-       int nunits = TYPE_VECTOR_SUBPARTS (type);
+       poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (type);
        tree innertype = TREE_TYPE (type);
 
-       gcc_assert (!(nunits & (nunits - 1)));
-
        /* Find an appropriate mode for the vector type.  */
        if (TYPE_MODE (type) == VOIDmode)
          SET_TYPE_MODE (type,
@@ -2270,9 +2384,10 @@ layout_type (tree type)
          TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
                                                   TYPE_SIZE_UNIT (innertype),
                                                   size_int (nunits));
-       TYPE_SIZE (type) = int_const_binop (MULT_EXPR,
-                                           TYPE_SIZE (innertype),
-                                           bitsize_int (nunits));
+       TYPE_SIZE (type) = int_const_binop
+         (MULT_EXPR,
+          bits_from_bytes (TYPE_SIZE_UNIT (type)),
+          bitsize_int (BITS_PER_UNIT));
 
        /* For vector types, we do not default to the mode's alignment.
           Instead, query a target hook, defaulting to natural alignment.
@@ -2295,11 +2410,6 @@ layout_type (tree type)
       SET_TYPE_MODE (type, VOIDmode);
       break;
 
-    case POINTER_BOUNDS_TYPE:
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-      break;
-
     case OFFSET_TYPE:
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE_UNITS);
@@ -2385,8 +2495,7 @@ layout_type (tree type)
              length = size_zero_node;
 
            TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
-                                          fold_convert (bitsizetype,
-                                                        length));
+                                          bits_from_bytes (length));
 
            /* If we know the size of the element, calculate the total size
               directly, rather than do some division thing below.  This
@@ -2728,15 +2837,15 @@ fixup_unsigned_type (tree type)
 
 bit_field_mode_iterator
 ::bit_field_mode_iterator (HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
-                          HOST_WIDE_INT bitregion_start,
-                          HOST_WIDE_INT bitregion_end,
+                          poly_int64 bitregion_start,
+                          poly_int64 bitregion_end,
                           unsigned int align, bool volatilep)
 : m_mode (NARROWEST_INT_MODE), m_bitsize (bitsize),
   m_bitpos (bitpos), m_bitregion_start (bitregion_start),
   m_bitregion_end (bitregion_end), m_align (align),
   m_volatilep (volatilep), m_count (0)
 {
-  if (!m_bitregion_end)
+  if (known_eq (m_bitregion_end, 0))
     {
       /* We can assume that any aligned chunk of ALIGN bits that overlaps
         the bitfield is mapped and won't trap, provided that ALIGN isn't
@@ -2746,8 +2855,8 @@ bit_field_mode_iterator
        = MIN (align, MAX (BIGGEST_ALIGNMENT, BITS_PER_WORD));
       if (bitsize <= 0)
        bitsize = 1;
-      m_bitregion_end = bitpos + bitsize + units - 1;
-      m_bitregion_end -= m_bitregion_end % units + 1;
+      HOST_WIDE_INT end = bitpos + bitsize + units - 1;
+      m_bitregion_end = end - end % units - 1;
     }
 }
 
@@ -2784,10 +2893,11 @@ bit_field_mode_iterator::next_mode (scalar_int_mode *out_mode)
 
       /* Stop if the mode goes outside the bitregion.  */
       HOST_WIDE_INT start = m_bitpos - substart;
-      if (m_bitregion_start && start < m_bitregion_start)
+      if (maybe_ne (m_bitregion_start, 0)
+         && maybe_lt (start, m_bitregion_start))
        break;
       HOST_WIDE_INT end = start + unit;
-      if (end > m_bitregion_end + 1)
+      if (maybe_gt (end, m_bitregion_end + 1))
        break;
 
       /* Stop if the mode requires too much alignment.  */
@@ -2843,8 +2953,7 @@ bit_field_mode_iterator::prefer_smaller_modes ()
 
 bool
 get_best_mode (int bitsize, int bitpos,
-              unsigned HOST_WIDE_INT bitregion_start,
-              unsigned HOST_WIDE_INT bitregion_end,
+              poly_uint64 bitregion_start, poly_uint64 bitregion_end,
               unsigned int align,
               unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep,
               scalar_int_mode *best_mode)