coarray_data_1.f90: Link against libatomic if target libatomic_available.
[gcc.git] / gcc / stor-layout.c
index 58ecd7ba35beec8382fac98407da501ed1b71022..5d6f2e0166cee4da93235c66dd0d3dfdeefff5a6 100644 (file)
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,35 +21,27 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "alias.h"
+#include "target.h"
+#include "function.h"
+#include "rtl.h"
 #include "tree.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "cgraph.h"
+#include "diagnostic-core.h"
 #include "fold-const.h"
 #include "stor-layout.h"
-#include "stringpool.h"
 #include "varasm.h"
 #include "print-tree.h"
-#include "rtl.h"
-#include "tm_p.h"
-#include "flags.h"
-#include "function.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "stmt.h"
-#include "expr.h"
-#include "diagnostic-core.h"
-#include "target.h"
 #include "langhooks.h"
-#include "regs.h"
-#include "params.h"
-#include "cgraph.h"
 #include "tree-inline.h"
-#include "tree-dump.h"
+#include "dumpfile.h"
 #include "gimplify.h"
+#include "attribs.h"
+#include "debug.h"
 
 /* Data type for the expressions representing sizes of data types.
    It is the first integer type laid out.  */
@@ -59,11 +51,6 @@ tree sizetype_tab[(int) stk_type_kind_last];
    The value is measured in bits.  */
 unsigned int maximum_field_alignment = TARGET_DEFAULT_PACK_STRUCT * BITS_PER_UNIT;
 
-/* Nonzero if all REFERENCE_TYPEs are internal and hence should be allocated
-   in the address spaces' address_mode, not pointer_mode.   Set only by
-   internal_reference_types called only by a front end.  */
-static int reference_types_internal = 0;
-
 static tree self_referential_size (tree);
 static void finalize_record_size (record_layout_info);
 static void finalize_type_size (tree);
@@ -72,15 +59,6 @@ static int excess_unit_span (HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT,
                             HOST_WIDE_INT, tree);
 extern void debug_rli (record_layout_info);
 \f
-/* Show that REFERENCE_TYPES are internal and should use address_mode.
-   Called only by front end.  */
-
-void
-internal_reference_types (void)
-{
-  reference_types_internal = 1;
-}
-
 /* Given a size SIZE that may not be a constant, return a SAVE_EXPR
    to serve as the actual size-expression for a type or decl.  */
 
@@ -303,6 +281,10 @@ finalize_size_functions (void)
       allocate_struct_function (fndecl, false);
       set_cfun (NULL);
       dump_function (TDI_original, fndecl);
+
+      /* As these functions are used to describe the layout of variable-length
+         structures, debug info generation needs their implementation.  */
+      debug_hooks->size_function (fndecl);
       gimplify_function_tree (fndecl);
       cgraph_node::finalize_function (fndecl, false);
     }
@@ -310,159 +292,155 @@ finalize_size_functions (void)
   vec_free (size_functions);
 }
 \f
-/* Return the machine mode to use for a nonscalar of SIZE bits.  The
-   mode must be in class MCLASS, and have exactly that many value bits;
-   it may have padding as well.  If LIMIT is nonzero, modes of wider
-   than MAX_FIXED_MODE_SIZE will not be used.  */
+/* Return a machine mode of class MCLASS with SIZE bits of precision,
+   if one exists.  The mode may have padding bits as well the SIZE
+   value bits.  If LIMIT is nonzero, disregard modes wider than
+   MAX_FIXED_MODE_SIZE.  */
 
-machine_mode
-mode_for_size (unsigned int size, enum mode_class mclass, int limit)
+opt_machine_mode
+mode_for_size (poly_uint64 size, enum mode_class mclass, int limit)
 {
   machine_mode mode;
   int i;
 
-  if (limit && size > MAX_FIXED_MODE_SIZE)
-    return BLKmode;
+  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 (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_PRECISION (mode) == size)
+  FOR_EACH_MODE_IN_CLASS (mode, mclass)
+    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;
 
-  return BLKmode;
+  return opt_machine_mode ();
 }
 
 /* Similar, except passed a tree node.  */
 
-machine_mode
+opt_machine_mode
 mode_for_size_tree (const_tree size, enum mode_class mclass, int limit)
 {
   unsigned HOST_WIDE_INT uhwi;
   unsigned int ui;
 
   if (!tree_fits_uhwi_p (size))
-    return BLKmode;
+    return opt_machine_mode ();
   uhwi = tree_to_uhwi (size);
   ui = uhwi;
   if (uhwi != ui)
-    return BLKmode;
+    return opt_machine_mode ();
   return mode_for_size (ui, mclass, limit);
 }
 
-/* Similar, but never return BLKmode; return the narrowest mode that
-   contains at least the requested number of value bits.  */
+/* Return the narrowest mode of class MCLASS that contains at least
+   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;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
-  for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_PRECISION (mode) >= size)
+  FOR_EACH_MODE_IN_CLASS (mode, mclass)
+    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;
 }
 
-/* Find an integer mode of the exact same size, or BLKmode on failure.  */
+/* Return an integer mode of exactly the same size as MODE, if one exists.  */
 
-machine_mode
+opt_scalar_int_mode
 int_mode_for_mode (machine_mode mode)
 {
   switch (GET_MODE_CLASS (mode))
     {
     case MODE_INT:
     case MODE_PARTIAL_INT:
-      break;
+      return as_a <scalar_int_mode> (mode);
 
     case MODE_COMPLEX_INT:
     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:
-      mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
-      break;
+      return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
 
     case MODE_RANDOM:
       if (mode == BLKmode)
-       break;
+       return opt_scalar_int_mode ();
 
-      /* ... fall through ...  */
+      /* fall through */
 
     case MODE_CC:
     default:
       gcc_unreachable ();
     }
-
-  return mode;
 }
 
-/* Find a mode that can be used for efficient bitwise operations on MODE.
-   Return BLKmode if no such mode exists.  */
+/* Find a mode that can be used for efficient bitwise operations on MODE,
+   if one exists.  */
 
-machine_mode
+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);
-  if (SCALAR_INT_MODE_P (mode) && bitsize <= MAX_FIXED_MODE_SIZE)
-    return mode;
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_BITSIZE (int_mode) <= MAX_FIXED_MODE_SIZE)
+    return int_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.  */
   if (COMPLEX_MODE_P (mode))
     {
       machine_mode trial = mode;
-      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
-       trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_COMPLEX_INT
+          || mode_for_size (bitsize, MODE_COMPLEX_INT, false).exists (&trial))
          && have_regs_of_mode[GET_MODE_INNER (trial)])
        return trial;
     }
 
   /* 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 (mode) != MODE_VECTOR_INT)
-       trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_VECTOR_INT
+          || mode_for_size (bitsize, MODE_VECTOR_INT, 0).exists (&trial))
          && have_regs_of_mode[trial]
          && targetm.vector_mode_supported_p (trial))
        return trial;
@@ -478,8 +456,7 @@ bitwise_mode_for_mode (machine_mode mode)
 tree
 bitwise_type_for_mode (machine_mode mode)
 {
-  mode = bitwise_mode_for_mode (mode);
-  if (mode == BLKmode)
+  if (!bitwise_mode_for_mode (mode).exists (&mode))
     return NULL_TREE;
 
   unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode);
@@ -495,12 +472,12 @@ bitwise_type_for_mode (machine_mode mode)
   return inner_type;
 }
 
-/* Find a mode that is suitable for representing a vector with
-   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
-   is no suitable mode.  */
+/* Find a mode that is suitable for representing a vector with NUNITS
+   elements of mode INNERMODE, if one exists.  The returned mode can be
+   either an integer mode or a vector mode.  */
 
-machine_mode
-mode_for_vector (machine_mode innermode, unsigned nunits)
+opt_machine_mode
+mode_for_vector (scalar_mode innermode, poly_uint64 nunits)
 {
   machine_mode mode;
 
@@ -520,23 +497,36 @@ mode_for_vector (machine_mode innermode, unsigned nunits)
 
   /* Do not check vector_mode_supported_p here.  We'll do that
      later in vector_type_mode.  */
-  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_NUNITS (mode) == nunits
+  FOR_EACH_MODE_FROM (mode, mode)
+    if (known_eq (GET_MODE_NUNITS (mode), nunits)
        && GET_MODE_INNER (mode) == innermode)
-      break;
+      return mode;
 
   /* For integers, try mapping it to a same-sized scalar mode.  */
-  if (mode == VOIDmode
-      && GET_MODE_CLASS (innermode) == MODE_INT)
-    mode = mode_for_size (nunits * GET_MODE_BITSIZE (innermode),
-                         MODE_INT, 0);
+  if (GET_MODE_CLASS (innermode) == MODE_INT)
+    {
+      poly_uint64 nbits = nunits * GET_MODE_BITSIZE (innermode);
+      if (int_mode_for_size (nbits, 0).exists (&mode)
+         && have_regs_of_mode[mode])
+       return mode;
+    }
+
+  return opt_machine_mode ();
+}
 
-  if (mode == VOIDmode
-      || (GET_MODE_CLASS (mode) == MODE_INT
-         && !have_regs_of_mode[mode]))
-    return BLKmode;
+/* Return the mode for a vector that has NUNITS integer elements of
+   INT_BITS bits each, if such a mode exists.  The mode can be either
+   an integer mode or a vector mode.  */
 
-  return mode;
+opt_machine_mode
+mode_for_int_vector (unsigned int int_bits, poly_uint64 nunits)
+{
+  scalar_int_mode int_mode;
+  machine_mode vec_mode;
+  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
+      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
+    return vec_mode;
+  return opt_machine_mode ();
 }
 
 /* Return the alignment of MODE. This will be bounded by 1 and
@@ -555,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.  */
@@ -564,17 +555,19 @@ 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);
+  return mode_for_size_tree (size, MODE_INT, limit_p).else_blk ();
 }
 \f
 /* Subroutine of layout_decl: Force alignment required for the data type.
@@ -585,10 +578,12 @@ do_type_align (tree type, tree decl)
 {
   if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
     {
-      DECL_ALIGN (decl) = TYPE_ALIGN (type);
+      SET_DECL_ALIGN (decl, TYPE_ALIGN (type));
       if (TREE_CODE (decl) == FIELD_DECL)
        DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
     }
+  if (TYPE_WARN_IF_NOT_ALIGN (type) > DECL_WARN_IF_NOT_ALIGN (decl))
+    SET_DECL_WARN_IF_NOT_ALIGN (decl, TYPE_WARN_IF_NOT_ALIGN (type));
 }
 
 /* Set the size, mode and alignment of a ..._DECL node.
@@ -616,7 +611,7 @@ layout_decl (tree decl, unsigned int known_align)
     return;
 
   gcc_assert (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL
-             || code == TYPE_DECL ||code == FIELD_DECL);
+             || code == TYPE_DECL || code == FIELD_DECL);
 
   rtl = DECL_RTL_IF_SET (decl);
 
@@ -635,7 +630,7 @@ layout_decl (tree decl, unsigned int known_align)
 
   DECL_UNSIGNED (decl) = TYPE_UNSIGNED (type);
   if (DECL_MODE (decl) == VOIDmode)
-    DECL_MODE (decl) = TYPE_MODE (type);
+    SET_DECL_MODE (decl, TYPE_MODE (type));
 
   if (DECL_SIZE (decl) == 0)
     {
@@ -678,7 +673,7 @@ layout_decl (tree decl, unsigned int known_align)
 #ifdef EMPTY_FIELD_BOUNDARY
                  if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))
                    {
-                     DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;
+                     SET_DECL_ALIGN (decl, EMPTY_FIELD_BOUNDARY);
                      DECL_USER_ALIGN (decl) = 0;
                    }
 #endif
@@ -692,17 +687,18 @@ layout_decl (tree decl, unsigned int known_align)
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
              && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
            {
-             machine_mode xmode
-               = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
-             unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
-
-             if (xmode != BLKmode
-                 && !(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
-                 && (known_align == 0 || known_align >= xalign))
+             machine_mode xmode;
+             if (mode_for_size_tree (DECL_SIZE (decl),
+                                     MODE_INT, 1).exists (&xmode))
                {
-                 DECL_ALIGN (decl) = MAX (xalign, DECL_ALIGN (decl));
-                 DECL_MODE (decl) = xmode;
-                 DECL_BIT_FIELD (decl) = 0;
+                 unsigned int xalign = GET_MODE_ALIGNMENT (xmode);
+                 if (!(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
+                     && (known_align == 0 || known_align >= xalign))
+                   {
+                     SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
+                     SET_DECL_MODE (decl, xmode);
+                     DECL_BIT_FIELD (decl) = 0;
+                   }
                }
            }
 
@@ -725,7 +721,7 @@ layout_decl (tree decl, unsigned int known_align)
         DECL_USER_ALIGN, so we need to check old_user_align instead.  */
       if (packed_p
          && !old_user_align)
-       DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
+       SET_DECL_ALIGN (decl, MIN (DECL_ALIGN (decl), BITS_PER_UNIT));
 
       if (! packed_p && ! DECL_USER_ALIGN (decl))
        {
@@ -733,11 +729,12 @@ layout_decl (tree decl, unsigned int known_align)
             to a lower boundary than alignment of variables unless
             it was overridden by attribute aligned.  */
 #ifdef BIGGEST_FIELD_ALIGNMENT
-         DECL_ALIGN (decl)
-           = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);
+         SET_DECL_ALIGN (decl, MIN (DECL_ALIGN (decl),
+                                    (unsigned) BIGGEST_FIELD_ALIGNMENT));
 #endif
 #ifdef ADJUST_FIELD_ALIGN
-         DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));
+         SET_DECL_ALIGN (decl, ADJUST_FIELD_ALIGN (decl, TREE_TYPE (decl),
+                                                   DECL_ALIGN (decl)));
 #endif
        }
 
@@ -747,7 +744,7 @@ layout_decl (tree decl, unsigned int known_align)
        mfa = maximum_field_alignment;
       /* Should this be controlled by DECL_USER_ALIGN, too?  */
       if (mfa != 0)
-       DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), mfa);
+       SET_DECL_ALIGN (decl, MIN (DECL_ALIGN (decl), mfa));
     }
 
   /* Evaluate nonconstant size only once, either now or as soon as safe.  */
@@ -758,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);
        }
     }
 
@@ -788,17 +787,18 @@ layout_decl (tree decl, unsigned int known_align)
     }
 }
 
-/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
-   a previous call to layout_decl and calls it again.  */
+/* Given a VAR_DECL, PARM_DECL, RESULT_DECL, or FIELD_DECL, clears the
+   results of a previous call to layout_decl and calls it again.  */
 
 void
 relayout_decl (tree decl)
 {
   DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
-  DECL_MODE (decl) = VOIDmode;
+  SET_DECL_MODE (decl, VOIDmode);
   if (!DECL_USER_ALIGN (decl))
-    DECL_ALIGN (decl) = 0;
-  SET_DECL_RTL (decl, 0);
+    SET_DECL_ALIGN (decl, 0);
+  if (DECL_RTL_SET_P (decl))
+    SET_DECL_RTL (decl, 0);
 
   layout_decl (decl, 0);
 }
@@ -848,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.
 
@@ -860,14 +882,9 @@ start_record_layout (tree t)
 tree
 bit_from_pos (tree offset, tree bitpos)
 {
-  if (TREE_CODE (offset) == PLUS_EXPR)
-    offset = size_binop (PLUS_EXPR,
-                        fold_convert (bitsizetype, TREE_OPERAND (offset, 0)),
-                        fold_convert (bitsizetype, TREE_OPERAND (offset, 1)));
-  else
-    offset = fold_convert (bitsizetype, offset);
   return size_binop (PLUS_EXPR, bitpos,
-                    size_binop (MULT_EXPR, offset, bitsize_unit_node));
+                    size_binop (MULT_EXPR, bits_from_bytes (offset),
+                                bitsize_unit_node));
 }
 
 /* Return the combined truncated byte position for the byte offset OFFSET and
@@ -952,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);
     }
 }
 
@@ -1022,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)
@@ -1031,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);
@@ -1050,7 +1070,7 @@ update_alignment_for_field (record_layout_info rli, tree field,
 
 #ifdef ADJUST_FIELD_ALIGN
          if (! TYPE_USER_ALIGN (type))
-           type_align = ADJUST_FIELD_ALIGN (field, type_align);
+           type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
 #endif
 
          /* Targets might chose to handle unnamed and hence possibly
@@ -1091,6 +1111,61 @@ update_alignment_for_field (record_layout_info rli, tree field,
   return desired_align;
 }
 
+/* Issue a warning if the record alignment, RECORD_ALIGN, is less than
+   the field alignment of FIELD or FIELD isn't aligned. */
+
+static void
+handle_warn_if_not_align (tree field, unsigned int record_align)
+{
+  tree type = TREE_TYPE (field);
+
+  if (type == error_mark_node)
+    return;
+
+  unsigned int warn_if_not_align = 0;
+
+  int opt_w = 0;
+
+  if (warn_if_not_aligned)
+    {
+      warn_if_not_align = DECL_WARN_IF_NOT_ALIGN (field);
+      if (!warn_if_not_align)
+       warn_if_not_align = TYPE_WARN_IF_NOT_ALIGN (type);
+      if (warn_if_not_align)
+       opt_w = OPT_Wif_not_aligned;
+    }
+
+  if (!warn_if_not_align
+      && warn_packed_not_aligned
+      && lookup_attribute ("aligned", TYPE_ATTRIBUTES (type)))
+    {
+      warn_if_not_align = TYPE_ALIGN (type);
+      opt_w = OPT_Wpacked_not_aligned;
+    }
+
+  if (!warn_if_not_align)
+    return;
+
+  tree context = DECL_CONTEXT (field);
+
+  warn_if_not_align /= BITS_PER_UNIT;
+  record_align /= BITS_PER_UNIT;
+  if ((record_align % warn_if_not_align) != 0)
+    warning (opt_w, "alignment %u of %qT is less than %u",
+            record_align, 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.  */
 
 static void
@@ -1101,6 +1176,7 @@ place_union_field (record_layout_info rli, tree field)
   DECL_FIELD_OFFSET (field) = size_zero_node;
   DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
   SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
+  handle_warn_if_not_align (field, rli->record_align);
 
   /* If this is an ERROR_MARK return *after* having set the
      field at the start of the union. This helps when parsing
@@ -1108,6 +1184,10 @@ place_union_field (record_layout_info rli, tree field)
   if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
     return;
 
+  if (AGGREGATE_TYPE_P (TREE_TYPE (field))
+      && TYPE_TYPELESS_STORAGE (TREE_TYPE (field)))
+    TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
   /* We assume the union's size will be a multiple of a byte so we don't
      bother with BITPOS.  */
   if (TREE_CODE (rli->t) == UNION_TYPE)
@@ -1156,7 +1236,7 @@ place_field (record_layout_info rli, tree field)
      really like a structure field.  If it is a FUNCTION_DECL, it's a
      method.  In both cases, all we do is lay out the decl, and we do
      it *after* the record is laid out.  */
-  if (TREE_CODE (field) == VAR_DECL)
+  if (VAR_P (field))
     {
       vec_safe_push (rli->pending_statics, field);
       return;
@@ -1182,20 +1262,23 @@ place_field (record_layout_info rli, tree field)
       DECL_FIELD_OFFSET (field) = rli->offset;
       DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
       SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
+      handle_warn_if_not_align (field, rli->record_align);
       return;
     }
 
+  if (AGGREGATE_TYPE_P (type)
+      && TYPE_TYPELESS_STORAGE (type))
+    TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
   /* Work out the known alignment so far.  Note that A & (-A) is the
      value of the least-significant bit in A that is one.  */
   if (! integer_zerop (rli->bitpos))
-    known_align = (tree_to_uhwi (rli->bitpos)
-                  & - tree_to_uhwi (rli->bitpos));
+    known_align = least_bit_hwi (tree_to_uhwi (rli->bitpos));
   else if (integer_zerop (rli->offset))
     known_align = 0;
   else if (tree_fits_uhwi_p (rli->offset))
     known_align = (BITS_PER_UNIT
-                  * (tree_to_uhwi (rli->offset)
-                     & - tree_to_uhwi (rli->offset)));
+                  * least_bit_hwi (tree_to_uhwi (rli->offset)));
   else
     known_align = rli->offset_align;
 
@@ -1224,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.  */
@@ -1252,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
@@ -1280,7 +1363,7 @@ place_field (record_layout_info rli, tree field)
 
 #ifdef ADJUST_FIELD_ALIGN
       if (! TYPE_USER_ALIGN (type))
-       type_align = ADJUST_FIELD_ALIGN (field, type_align);
+       type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
 #endif
 
       /* A bit field may not span more units of alignment of its type
@@ -1301,6 +1384,9 @@ place_field (record_layout_info rli, tree field)
 
       if (! DECL_PACKED (field))
        TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
+
+      SET_TYPE_WARN_IF_NOT_ALIGN (rli->t,
+                                 TYPE_WARN_IF_NOT_ALIGN (type));
     }
 
 #ifdef BITFIELD_NBYTES_LIMITED
@@ -1323,7 +1409,7 @@ place_field (record_layout_info rli, tree field)
 
 #ifdef ADJUST_FIELD_ALIGN
       if (! TYPE_USER_ALIGN (type))
-       type_align = ADJUST_FIELD_ALIGN (field, type_align);
+       type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
 #endif
 
       if (maximum_field_alignment != 0)
@@ -1339,6 +1425,8 @@ place_field (record_layout_info rli, tree field)
        rli->bitpos = round_up (rli->bitpos, type_align);
 
       TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
+      SET_TYPE_WARN_IF_NOT_ALIGN (rli->t,
+                                 TYPE_WARN_IF_NOT_ALIGN (type));
     }
 #endif
 
@@ -1364,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
@@ -1397,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
            {
@@ -1428,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);
         }
 
@@ -1446,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;
@@ -1471,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);
@@ -1489,6 +1608,7 @@ place_field (record_layout_info rli, tree field)
   DECL_FIELD_OFFSET (field) = rli->offset;
   DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
   SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
+  handle_warn_if_not_align (field, rli->record_align);
 
   /* Evaluate nonconstant offsets only once, either now or as soon as safe.  */
   if (TREE_CODE (DECL_FIELD_OFFSET (field)) != INTEGER_CST)
@@ -1498,14 +1618,12 @@ place_field (record_layout_info rli, tree field)
      approximate this by seeing if its position changed), lay out the field
      again; perhaps we can use an integral mode for it now.  */
   if (! integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
-    actual_align = (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
-                   & - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)));
+    actual_align = least_bit_hwi (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)));
   else if (integer_zerop (DECL_FIELD_OFFSET (field)))
     actual_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
   else if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
     actual_align = (BITS_PER_UNIT
-                  * (tree_to_uhwi (DECL_FIELD_OFFSET (field))
-                     & - tree_to_uhwi (DECL_FIELD_OFFSET (field))));
+                   * least_bit_hwi (tree_to_uhwi (DECL_FIELD_OFFSET (field))));
   else
     actual_align = DECL_OFFSET_ALIGN (field);
   /* ACTUAL_ALIGN is still the actual alignment *within the record* .
@@ -1539,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);
     }
@@ -1578,10 +1727,10 @@ finalize_record_size (record_layout_info rli)
 
   /* Determine the desired alignment.  */
 #ifdef ROUND_TYPE_ALIGN
-  TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
-                                         rli->record_align);
+  SET_TYPE_ALIGN (rli->t, ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
+                                           rli->record_align));
 #else
-  TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
+  SET_TYPE_ALIGN (rli->t, MAX (TYPE_ALIGN (rli->t), rli->record_align));
 #endif
 
   /* Compute the size so far.  Be sure to allow for extra bits in the
@@ -1685,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
@@ -1695,27 +1850,38 @@ 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)))
-    SET_TYPE_MODE (type, mode);
+     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
-    SET_TYPE_MODE (type, mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1));
+    mode = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1).else_blk ();
 
   /* If structure's known alignment is less than what the scalar
      mode would need, and it matters, then stick with BLKmode.  */
-  if (TYPE_MODE (type) != BLKmode
+  if (mode != BLKmode
       && STRICT_ALIGNMENT
       && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
-           || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
+           || TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (mode)))
     {
       /* If this is the only reason this type is BLKmode, then
         don't force containing types to be BLKmode.  */
       TYPE_NO_FORCE_BLK (type) = 1;
-      SET_TYPE_MODE (type, BLKmode);
+      mode = BLKmode;
     }
+
+  SET_TYPE_MODE (type, mode);
 }
 
 /* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
@@ -1738,15 +1904,15 @@ finalize_type_size (tree type)
         alignment of one of the fields.  */
       if (mode_align >= TYPE_ALIGN (type))
        {
-         TYPE_ALIGN (type) = mode_align;
+         SET_TYPE_ALIGN (type, mode_align);
          TYPE_USER_ALIGN (type) = 0;
        }
     }
 
   /* Do machine-dependent extra alignment.  */
 #ifdef ROUND_TYPE_ALIGN
-  TYPE_ALIGN (type)
-    = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
+  SET_TYPE_ALIGN (type,
+                  ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT));
 #endif
 
   /* If we failed to find a simple way to calculate the unit size
@@ -1774,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))
@@ -1786,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);
@@ -1799,9 +1969,10 @@ finalize_type_size (tree type)
            valign = MAX (valign, TYPE_ALIGN (variant));
          else
            TYPE_USER_ALIGN (variant) = user_align;
-         TYPE_ALIGN (variant) = valign;
+         SET_TYPE_ALIGN (variant, valign);
          TYPE_PRECISION (variant) = precision;
          SET_TYPE_MODE (variant, mode);
+         TYPE_EMPTY_P (variant) = empty_p;
        }
     }
 }
@@ -1828,6 +1999,11 @@ start_bitfield_representative (tree field)
   DECL_SIZE_UNIT (repr) = DECL_SIZE_UNIT (field);
   DECL_PACKED (repr) = DECL_PACKED (field);
   DECL_CONTEXT (repr) = DECL_CONTEXT (field);
+  /* There are no indirect accesses to this field.  If we introduce
+     some then they have to use the record alias set.  This makes
+     sure to properly conflict with [indirect] accesses to addressable
+     fields of the bitfield group.  */
+  DECL_NONADDRESSABLE_P (repr) = 1;
   return repr;
 }
 
@@ -1838,7 +2014,6 @@ static void
 finish_bitfield_representative (tree repr, tree field)
 {
   unsigned HOST_WIDE_INT bitsize, maxbitsize;
-  machine_mode mode;
   tree nextf, size;
 
   size = size_diffop (DECL_FIELD_OFFSET (field),
@@ -1881,13 +2056,14 @@ finish_bitfield_representative (tree repr, tree field)
     }
   else
     {
-      /* ???  If you consider that tail-padding of this struct might be
-         re-used when deriving from it we cannot really do the following
-        and thus need to set maxsize to bitsize?  Also we cannot
-        generally rely on maxsize to fold to an integer constant, so
-        use bitsize as fallback for this case.  */
-      tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)),
-                                 DECL_FIELD_OFFSET (repr));
+      /* Note that if the C++ FE sets up tail-padding to be re-used it
+         creates a as-base variant of the type with TYPE_SIZE adjusted
+        accordingly.  So it is safe to include tail-padding here.  */
+      tree aggsize = lang_hooks.types.unit_size_without_reusable_padding
+                                                       (DECL_CONTEXT (field));
+      tree maxsize = size_diffop (aggsize, DECL_FIELD_OFFSET (repr));
+      /* We cannot generally rely on maxsize to fold to an integer constant,
+        so use bitsize as fallback for this case.  */
       if (tree_fits_uhwi_p (maxsize))
        maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
                      - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
@@ -1902,16 +2078,15 @@ finish_bitfield_representative (tree repr, tree field)
   gcc_assert (maxbitsize % BITS_PER_UNIT == 0);
 
   /* Find the smallest nice mode to use.  */
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_BITSIZE (mode) >= bitsize)
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
+    if (GET_MODE_BITSIZE (mode_iter.require ()) >= bitsize)
       break;
-  if (mode != VOIDmode
-      && (GET_MODE_BITSIZE (mode) > maxbitsize
-         || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE))
-    mode = VOIDmode;
 
-  if (mode == VOIDmode)
+  scalar_int_mode mode;
+  if (!mode_iter.exists (&mode)
+      || GET_MODE_BITSIZE (mode) > maxbitsize
+      || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE)
     {
       /* We really want a BLKmode representative only as a last resort,
          considering the member b in
@@ -1923,7 +2098,7 @@ finish_bitfield_representative (tree repr, tree field)
         [0, 15] HImode for a and b, [8, 23] HImode for c.  */
       DECL_SIZE (repr) = bitsize_int (bitsize);
       DECL_SIZE_UNIT (repr) = size_int (bitsize / BITS_PER_UNIT);
-      DECL_MODE (repr) = BLKmode;
+      SET_DECL_MODE (repr, BLKmode);
       TREE_TYPE (repr) = build_array_type_nelts (unsigned_char_type_node,
                                                 bitsize / BITS_PER_UNIT);
     }
@@ -1932,7 +2107,7 @@ finish_bitfield_representative (tree repr, tree field)
       unsigned HOST_WIDE_INT modesize = GET_MODE_BITSIZE (mode);
       DECL_SIZE (repr) = bitsize_int (modesize);
       DECL_SIZE_UNIT (repr) = size_int (modesize / BITS_PER_UNIT);
-      DECL_MODE (repr) = mode;
+      SET_DECL_MODE (repr, mode);
       TREE_TYPE (repr) = lang_hooks.types.type_for_mode (mode, 1);
     }
 
@@ -2046,11 +2221,16 @@ finish_record_layout (record_layout_info rli, int free_p)
   /* Compute bitfield representatives.  */
   finish_bitfield_layout (rli->t);
 
-  /* Propagate TYPE_PACKED to variants.  With C++ templates,
-     handle_packed_attribute is too early to do this.  */
+  /* Propagate TYPE_PACKED and TYPE_REVERSE_STORAGE_ORDER to variants.
+     With C++ templates, it is too early to do this when the attribute
+     is being parsed.  */
   for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
        variant = TYPE_NEXT_VARIANT (variant))
-    TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
+    {
+      TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
+      TYPE_REVERSE_STORAGE_ORDER (variant)
+       = TYPE_REVERSE_STORAGE_ORDER (rli->t);
+    }
 
   /* Lay out any static members.  This is done now because their type
      may use the record's type.  */
@@ -2088,8 +2268,10 @@ finish_builtin_struct (tree type, const char *name, tree fields,
 
   if (align_type)
     {
-      TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
+      SET_TYPE_ALIGN (type, TYPE_ALIGN (align_type));
       TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
+      SET_TYPE_WARN_IF_NOT_ALIGN (type,
+                                 TYPE_WARN_IF_NOT_ALIGN (align_type));
     }
 
   layout_type (type);
@@ -2139,68 +2321,79 @@ layout_type (tree type)
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
-      SET_TYPE_MODE (type,
-                    smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      /* Don't set TYPE_PRECISION here, as it may be set by a bitfield.  */
-      TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-      break;
+      {
+       scalar_int_mode mode
+         = smallest_int_mode_for_size (TYPE_PRECISION (type));
+       SET_TYPE_MODE (type, mode);
+       TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+       /* Don't set TYPE_PRECISION here, as it may be set by a bitfield.  */
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+       break;
+      }
 
     case REAL_TYPE:
-      SET_TYPE_MODE (type,
-                    mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-      break;
+      {
+       /* Allow the caller to choose the type mode, which is how decimal
+          floats are distinguished from binary ones.  */
+       if (TYPE_MODE (type) == VOIDmode)
+         SET_TYPE_MODE
+           (type, float_mode_for_size (TYPE_PRECISION (type)).require ());
+       scalar_float_mode mode = as_a <scalar_float_mode> (TYPE_MODE (type));
+       TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+       break;
+      }
 
    case FIXED_POINT_TYPE:
-     /* TYPE_MODE (type) has been set already.  */
-     TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-     TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-     break;
+     {
+       /* TYPE_MODE (type) has been set already.  */
+       scalar_mode mode = SCALAR_TYPE_MODE (type);
+       TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+       break;
+     }
 
     case COMPLEX_TYPE:
       TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
       SET_TYPE_MODE (type,
-                    mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)),
-                                   (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
-                                    ? MODE_COMPLEX_FLOAT : MODE_COMPLEX_INT),
-                                    0));
+                    GET_MODE_COMPLEX_MODE (TYPE_MODE (TREE_TYPE (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 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,
-                        mode_for_vector (TYPE_MODE (innertype), nunits));
+                        mode_for_vector (SCALAR_TYPE_MODE (innertype),
+                                         nunits).else_blk ());
 
        TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
        /* Several boolean vector elements may fit in a single unit.  */
-       if (VECTOR_BOOLEAN_TYPE_P (type))
+       if (VECTOR_BOOLEAN_TYPE_P (type)
+           && type->type_common.mode != BLKmode)
          TYPE_SIZE_UNIT (type)
            = size_int (GET_MODE_SIZE (type->type_common.mode));
        else
          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.
           This prevents ABI changes depending on whether or not native
           vector modes are supported.  */
-       TYPE_ALIGN (type) = targetm.vector_alignment (type);
+       SET_TYPE_ALIGN (type, targetm.vector_alignment (type));
 
        /* However, if the underlying mode requires a bigger alignment than
           what the target hook provides, we cannot use the mode.  For now,
@@ -2212,22 +2405,17 @@ layout_type (tree type)
 
     case VOID_TYPE:
       /* This is an incomplete type and so doesn't have a size.  */
-      TYPE_ALIGN (type) = 1;
+      SET_TYPE_ALIGN (type, 1);
       TYPE_USER_ALIGN (type) = 0;
       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);
       /* A pointer might be MODE_PARTIAL_INT, but ptrdiff_t must be
         integral, which may be an __intN.  */
-      SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
+      SET_TYPE_MODE (type, int_mode_for_size (POINTER_SIZE, 0).require ());
       TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
@@ -2236,7 +2424,8 @@ layout_type (tree type)
       /* It's hard to see what the mode and size of a function ought to
         be, but we do know the alignment is FUNCTION_BOUNDARY, so
         make it consistent with that.  */
-      SET_TYPE_MODE (type, mode_for_size (FUNCTION_BOUNDARY, MODE_INT, 0));
+      SET_TYPE_MODE (type,
+                    int_mode_for_size (FUNCTION_BOUNDARY, 0).else_blk ());
       TYPE_SIZE (type) = bitsize_int (FUNCTION_BOUNDARY);
       TYPE_SIZE_UNIT (type) = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
       break;
@@ -2244,13 +2433,7 @@ layout_type (tree type)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
-       machine_mode mode = TYPE_MODE (type);
-       if (TREE_CODE (type) == REFERENCE_TYPE && reference_types_internal)
-         {
-           addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
-           mode = targetm.addr_space.address_mode (as);
-         }
-
+       scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
        TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
        TYPE_UNSIGNED (type) = 1;
@@ -2263,8 +2446,6 @@ layout_type (tree type)
        tree index = TYPE_DOMAIN (type);
        tree element = TREE_TYPE (type);
 
-       build_pointer_type (element);
-
        /* We need to know both bounds in order to compute the size.  */
        if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
            && TYPE_SIZE (element))
@@ -2292,9 +2473,11 @@ layout_type (tree type)
                    && tree_int_cst_lt (ub, lb))
                  {
                    lb = wide_int_to_tree (ssizetype,
-                                          offset_int::from (lb, SIGNED));
+                                          offset_int::from (wi::to_wide (lb),
+                                                            SIGNED));
                    ub = wide_int_to_tree (ssizetype,
-                                          offset_int::from (ub, SIGNED));
+                                          offset_int::from (wi::to_wide (ub),
+                                                            SIGNED));
                  }
                length
                  = fold_convert (sizetype,
@@ -2312,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
@@ -2332,12 +2514,15 @@ layout_type (tree type)
          align = MAX (align, TYPE_ALIGN (type));
        else
          TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
+       if (!TYPE_WARN_IF_NOT_ALIGN (type))
+         SET_TYPE_WARN_IF_NOT_ALIGN (type,
+                                     TYPE_WARN_IF_NOT_ALIGN (element));
 #ifdef ROUND_TYPE_ALIGN
        align = ROUND_TYPE_ALIGN (type, align, BITS_PER_UNIT);
 #else
        align = MAX (align, BITS_PER_UNIT);
 #endif
-       TYPE_ALIGN (type) = align;
+       SET_TYPE_ALIGN (type, align);
        SET_TYPE_MODE (type, BLKmode);
        if (TYPE_SIZE (type) != 0
            && ! targetm.member_type_forces_blk (type, VOIDmode)
@@ -2356,6 +2541,8 @@ layout_type (tree type)
                SET_TYPE_MODE (type, BLKmode);
              }
          }
+       if (AGGREGATE_TYPE_P (element))
+         TYPE_TYPELESS_STORAGE (type) = TYPE_TYPELESS_STORAGE (element);
        /* When the element size is constant, check that it is at least as
           large as the element alignment.  */
        if (TYPE_SIZE_UNIT (element)
@@ -2428,53 +2615,12 @@ min_align_of_type (tree type)
 #endif
       unsigned int field_align = align;
 #ifdef ADJUST_FIELD_ALIGN
-      tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, type);
-      field_align = ADJUST_FIELD_ALIGN (field, field_align);
-      ggc_free (field);
+      field_align = ADJUST_FIELD_ALIGN (NULL_TREE, type, field_align);
 #endif
       align = MIN (align, field_align);
     }
   return align / BITS_PER_UNIT;
 }
-
-/* Vector types need to re-check the target flags each time we report
-   the machine mode.  We need to do this because attribute target can
-   change the result of vector_mode_supported_p and have_regs_of_mode
-   on a per-function basis.  Thus the TYPE_MODE of a VECTOR_TYPE can
-   change on a per-function basis.  */
-/* ??? Possibly a better solution is to run through all the types
-   referenced by a function and re-compute the TYPE_MODE once, rather
-   than make the TYPE_MODE macro call a function.  */
-
-machine_mode
-vector_type_mode (const_tree t)
-{
-  machine_mode mode;
-
-  gcc_assert (TREE_CODE (t) == VECTOR_TYPE);
-
-  mode = t->type_common.mode;
-  if (VECTOR_MODE_P (mode)
-      && (!targetm.vector_mode_supported_p (mode)
-         || !have_regs_of_mode[mode]))
-    {
-      machine_mode innermode = TREE_TYPE (t)->type_common.mode;
-
-      /* For integers, try mapping it to a same-sized scalar mode.  */
-      if (GET_MODE_CLASS (innermode) == MODE_INT)
-       {
-         mode = mode_for_size (TYPE_VECTOR_SUBPARTS (t)
-                               * GET_MODE_BITSIZE (innermode), MODE_INT, 0);
-
-         if (mode != VOIDmode && have_regs_of_mode[mode])
-           return mode;
-       }
-
-      return BLKmode;
-    }
-
-  return mode;
-}
 \f
 /* Create and return a type for signed integers of PRECISION bits.  */
 
@@ -2516,13 +2662,9 @@ make_fract_type (int precision, int unsignedp, int satp)
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UFRACT, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_FRACT, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
@@ -2542,13 +2684,9 @@ make_accum_type (int precision, int unsignedp, int satp)
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UACCUM, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_ACCUM, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
@@ -2591,9 +2729,8 @@ initialize_sizetypes (void)
     }
 
   bprecision
-    = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
-  bprecision
-    = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
+    = MIN (precision + LOG2_BITS_PER_UNIT + 1, MAX_FIXED_MODE_SIZE);
+  bprecision = GET_MODE_PRECISION (smallest_int_mode_for_size (bprecision));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
@@ -2608,17 +2745,18 @@ initialize_sizetypes (void)
   TYPE_UNSIGNED (bitsizetype) = 1;
 
   /* Now layout both types manually.  */
-  SET_TYPE_MODE (sizetype, smallest_mode_for_size (precision, MODE_INT));
-  TYPE_ALIGN (sizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (sizetype));
+  scalar_int_mode mode = smallest_int_mode_for_size (precision);
+  SET_TYPE_MODE (sizetype, mode);
+  SET_TYPE_ALIGN (sizetype, GET_MODE_ALIGNMENT (TYPE_MODE (sizetype)));
   TYPE_SIZE (sizetype) = bitsize_int (precision);
-  TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
+  TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (mode));
   set_min_and_max_values_for_integral_type (sizetype, precision, UNSIGNED);
 
-  SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
-  TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
+  mode = smallest_int_mode_for_size (bprecision);
+  SET_TYPE_MODE (bitsizetype, mode);
+  SET_TYPE_ALIGN (bitsizetype, GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype)));
   TYPE_SIZE (bitsizetype) = bitsize_int (bprecision);
-  TYPE_SIZE_UNIT (bitsizetype)
-    = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
+  TYPE_SIZE_UNIT (bitsizetype) = size_int (GET_MODE_SIZE (mode));
   set_min_and_max_values_for_integral_type (bitsizetype, bprecision, UNSIGNED);
 
   /* Create the signed variants of *sizetype.  */
@@ -2655,8 +2793,7 @@ set_min_and_max_values_for_integral_type (tree type,
 
 /* Set the extreme values of TYPE based on its precision in bits,
    then lay it out.  Used when make_signed_type won't do
-   because the tree code is not INTEGER_TYPE.
-   E.g. for Pascal, when the -fsigned-char option is given.  */
+   because the tree code is not INTEGER_TYPE.  */
 
 void
 fixup_signed_type (tree type)
@@ -2700,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 (GET_CLASS_NARROWEST_MODE (MODE_INT)), m_bitsize (bitsize),
+: 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
@@ -2718,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;
     }
 }
 
@@ -2728,14 +2865,15 @@ bit_field_mode_iterator
    available, storing it in *OUT_MODE if so.  */
 
 bool
-bit_field_mode_iterator::next_mode (machine_mode *out_mode)
+bit_field_mode_iterator::next_mode (scalar_int_mode *out_mode)
 {
-  for (; m_mode != VOIDmode; m_mode = GET_MODE_WIDER_MODE (m_mode))
+  scalar_int_mode mode;
+  for (; m_mode.exists (&mode); m_mode = GET_MODE_WIDER_MODE (mode))
     {
-      unsigned int unit = GET_MODE_BITSIZE (m_mode);
+      unsigned int unit = GET_MODE_BITSIZE (mode);
 
       /* Skip modes that don't have full precision.  */
-      if (unit != GET_MODE_PRECISION (m_mode))
+      if (unit != GET_MODE_PRECISION (mode))
        continue;
 
       /* Stop if the mode is too wide to handle efficiently.  */
@@ -2755,19 +2893,20 @@ bit_field_mode_iterator::next_mode (machine_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.  */
-      if (GET_MODE_ALIGNMENT (m_mode) > m_align
-         && SLOW_UNALIGNED_ACCESS (m_mode, m_align))
+      if (GET_MODE_ALIGNMENT (mode) > m_align
+         && targetm.slow_unaligned_access (mode, m_align))
        break;
 
-      *out_mode = m_mode;
-      m_mode = GET_MODE_WIDER_MODE (m_mode);
+      *out_mode = mode;
+      m_mode = GET_MODE_WIDER_MODE (mode);
       m_count++;
       return true;
     }
@@ -2794,12 +2933,14 @@ bit_field_mode_iterator::prefer_smaller_modes ()
    memory access to that range.  Otherwise, we are allowed to touch
    any adjacent non bit-fields.
 
-   The underlying object is known to be aligned to a boundary of ALIGN bits.
-   If LARGEST_MODE is not VOIDmode, it means that we should not use a mode
-   larger than LARGEST_MODE (usually SImode).
+   The chosen mode must have no more than LARGEST_MODE_BITSIZE bits.
+   INT_MAX is a suitable value for LARGEST_MODE_BITSIZE if the caller
+   doesn't want to apply a specific limit.
 
    If no mode meets all these conditions, we return VOIDmode.
 
+   The underlying object is known to be aligned to a boundary of ALIGN bits.
+
    If VOLATILEP is false and SLOW_BYTE_ACCESS is false, we return the
    smallest mode meeting these conditions.
 
@@ -2810,17 +2951,17 @@ bit_field_mode_iterator::prefer_smaller_modes ()
    If VOLATILEP is true the narrow_volatile_bitfields target hook is used to
    decide which of the above modes should be used.  */
 
-machine_mode
+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,
-              machine_mode largest_mode, bool volatilep)
+              unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep,
+              scalar_int_mode *best_mode)
 {
   bit_field_mode_iterator iter (bitsize, bitpos, bitregion_start,
                                bitregion_end, align, volatilep);
-  machine_mode widest_mode = VOIDmode;
-  machine_mode mode;
+  scalar_int_mode mode;
+  bool found = false;
   while (iter.next_mode (&mode)
         /* ??? For historical reasons, reject modes that would normally
            receive greater alignment, even if unaligned accesses are
@@ -2879,22 +3020,23 @@ get_best_mode (int bitsize, int bitpos,
            so that the final bitfield reference still has a MEM_EXPR
            and MEM_OFFSET.  */
         && GET_MODE_ALIGNMENT (mode) <= align
-        && (largest_mode == VOIDmode
-            || GET_MODE_SIZE (mode) <= GET_MODE_SIZE (largest_mode)))
+        && GET_MODE_BITSIZE (mode) <= largest_mode_bitsize)
     {
-      widest_mode = mode;
+      *best_mode = mode;
+      found = true;
       if (iter.prefer_smaller_modes ())
        break;
     }
-  return widest_mode;
+
+  return found;
 }
 
 /* Gets minimal and maximal values for MODE (signed or unsigned depending on
    SIGN).  The returned constants are made to be usable in TARGET_MODE.  */
 
 void
-get_mode_bounds (machine_mode mode, int sign,
-                machine_mode target_mode,
+get_mode_bounds (scalar_int_mode mode, int sign,
+                scalar_int_mode target_mode,
                 rtx *mmin, rtx *mmax)
 {
   unsigned size = GET_MODE_PRECISION (mode);
@@ -2918,13 +3060,13 @@ get_mode_bounds (machine_mode mode, int sign,
     }
   else if (sign)
     {
-      min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1));
-      max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1;
+      min_val = -(HOST_WIDE_INT_1U << (size - 1));
+      max_val = (HOST_WIDE_INT_1U << (size - 1)) - 1;
     }
   else
     {
       min_val = 0;
-      max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1;
+      max_val = (HOST_WIDE_INT_1U << (size - 1) << 1) - 1;
     }
 
   *mmin = gen_int_mode (min_val, target_mode);