Daily bump.
[gcc.git] / gcc / tree-dfa.c
index 77f3cc0a98dfe9affe14b696d2293598c5072243..9ba627c90b54fb6f76d0171ff16e5aa4d7f06026 100644 (file)
@@ -1,5 +1,5 @@
 /* Data flow functions for trees.
-   Copyright (C) 2001-2014 Free Software Foundation, Inc.
+   Copyright (C) 2001-2019 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -21,34 +21,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "hashtab.h"
+#include "backend.h"
+#include "rtl.h"
 #include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "tree-pretty-print.h"
+#include "fold-const.h"
 #include "stor-layout.h"
-#include "tm_p.h"
-#include "basic-block.h"
 #include "langhooks.h"
-#include "flags.h"
-#include "function.h"
-#include "tree-pretty-print.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
-#include "gimple-ssa.h"
-#include "tree-phinodes.h"
-#include "ssa-iterators.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
-#include "expr.h"
 #include "tree-dfa.h"
-#include "tree-inline.h"
-#include "tree-pass.h"
-#include "params.h"
-#include "wide-int.h"
 
 /* Build and maintain data flow information for trees.  */
 
@@ -86,12 +71,12 @@ renumber_gimple_stmt_uids (void)
       gimple_stmt_iterator bsi;
       for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
-         gimple stmt = gsi_stmt (bsi);
+         gimple *stmt = gsi_stmt (bsi);
          gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
        }
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
-         gimple stmt = gsi_stmt (bsi);
+         gimple *stmt = gsi_stmt (bsi);
          gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
        }
     }
@@ -112,12 +97,12 @@ renumber_gimple_stmt_uids_in_blocks (basic_block *blocks, int n_blocks)
       gimple_stmt_iterator bsi;
       for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
-         gimple stmt = gsi_stmt (bsi);
+         gimple *stmt = gsi_stmt (bsi);
          gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
        }
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
-         gimple stmt = gsi_stmt (bsi);
+         gimple *stmt = gsi_stmt (bsi);
          gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
        }
     }
@@ -199,8 +184,8 @@ dump_dfa_stats (FILE *file)
 
   unsigned long size, total = 0;
   const char * const fmt_str   = "%-30s%-13s%12s\n";
-  const char * const fmt_str_1 = "%-30s%13lu%11lu%c\n";
-  const char * const fmt_str_3 = "%-43s%11lu%c\n";
+  const char * const fmt_str_1 = "%-30s%13lu" PRsa (11) "\n";
+  const char * const fmt_str_3 = "%-43s" PRsa (11) "\n";
   const char *funcname
     = lang_hooks.decl_printable_name (current_function_decl, 2);
 
@@ -216,36 +201,36 @@ dump_dfa_stats (FILE *file)
   size = dfa_stats.num_uses * sizeof (tree *);
   total += size;
   fprintf (file, fmt_str_1, "USE operands", dfa_stats.num_uses,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
   size = dfa_stats.num_defs * sizeof (tree *);
   total += size;
   fprintf (file, fmt_str_1, "DEF operands", dfa_stats.num_defs,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
   size = dfa_stats.num_vuses * sizeof (tree *);
   total += size;
   fprintf (file, fmt_str_1, "VUSE operands", dfa_stats.num_vuses,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
   size = dfa_stats.num_vdefs * sizeof (tree *);
   total += size;
   fprintf (file, fmt_str_1, "VDEF operands", dfa_stats.num_vdefs,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
-  size = dfa_stats.num_phis * sizeof (struct gimple_statement_phi);
+  size = dfa_stats.num_phis * sizeof (struct gphi);
   total += size;
   fprintf (file, fmt_str_1, "PHI nodes", dfa_stats.num_phis,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
   size = dfa_stats.num_phi_args * sizeof (struct phi_arg_d);
   total += size;
   fprintf (file, fmt_str_1, "PHI arguments", dfa_stats.num_phi_args,
-          SCALE (size), LABEL (size));
+          SIZE_AMOUNT (size));
 
   fprintf (file, "---------------------------------------------------------\n");
-  fprintf (file, fmt_str_3, "Total memory used by DFA/SSA data", SCALE (total),
-          LABEL (total));
+  fprintf (file, fmt_str_3, "Total memory used by DFA/SSA data",
+          SIZE_AMOUNT (total));
   fprintf (file, "---------------------------------------------------------\n");
   fprintf (file, "\n");
 
@@ -282,20 +267,20 @@ collect_dfa_stats (struct dfa_stats_d *dfa_stats_p ATTRIBUTE_UNUSED)
   /* Walk all the statements in the function counting references.  */
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple_stmt_iterator si;
-
-      for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+      for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
+          gsi_next (&si))
        {
-         gimple phi = gsi_stmt (si);
+         gphi *phi = si.phi ();
          dfa_stats_p->num_phis++;
          dfa_stats_p->num_phi_args += gimple_phi_num_args (phi);
          if (gimple_phi_num_args (phi) > dfa_stats_p->max_num_phi_args)
            dfa_stats_p->max_num_phi_args = gimple_phi_num_args (phi);
        }
 
-      for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+      for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
+          gsi_next (&si))
        {
-         gimple stmt = gsi_stmt (si);
+         gimple *stmt = gsi_stmt (si);
          dfa_stats_p->num_defs += NUM_SSA_OPERANDS (stmt, SSA_OP_DEF);
          dfa_stats_p->num_uses += NUM_SSA_OPERANDS (stmt, SSA_OP_USE);
          dfa_stats_p->num_vdefs += gimple_vdef (stmt) ? 1 : 0;
@@ -317,12 +302,17 @@ ssa_default_def (struct function *fn, tree var)
 {
   struct tree_decl_minimal ind;
   struct tree_ssa_name in;
-  gcc_assert (TREE_CODE (var) == VAR_DECL
+  gcc_assert (VAR_P (var)
              || TREE_CODE (var) == PARM_DECL
              || TREE_CODE (var) == RESULT_DECL);
+
+  /* Always NULL_TREE for rtl function dumps.  */
+  if (!fn->gimple_df)
+    return NULL_TREE;
+
   in.var = (tree)&ind;
   ind.uid = DECL_UID (var);
-  return (tree) htab_find_with_hash (DEFAULT_DEFS (fn), &in, DECL_UID (var));
+  return DEFAULT_DEFS (fn)->find_with_hash ((tree)&in, DECL_UID (var));
 }
 
 /* Insert the pair VAR's UID, DEF into the default_defs hashtable
@@ -333,34 +323,34 @@ set_ssa_default_def (struct function *fn, tree var, tree def)
 {
   struct tree_decl_minimal ind;
   struct tree_ssa_name in;
-  void **loc;
 
-  gcc_assert (TREE_CODE (var) == VAR_DECL
+  gcc_assert (VAR_P (var)
              || TREE_CODE (var) == PARM_DECL
              || TREE_CODE (var) == RESULT_DECL);
   in.var = (tree)&ind;
   ind.uid = DECL_UID (var);
   if (!def)
     {
-      loc = htab_find_slot_with_hash (DEFAULT_DEFS (fn), &in,
-                                     DECL_UID (var), NO_INSERT);
+      tree *loc = DEFAULT_DEFS (fn)->find_slot_with_hash ((tree)&in,
+                                                         DECL_UID (var),
+                                                         NO_INSERT);
       if (loc)
        {
          SSA_NAME_IS_DEFAULT_DEF (*(tree *)loc) = false;
-         htab_clear_slot (DEFAULT_DEFS (fn), loc);
+         DEFAULT_DEFS (fn)->clear_slot (loc);
        }
       return;
     }
   gcc_assert (TREE_CODE (def) == SSA_NAME && SSA_NAME_VAR (def) == var);
-  loc = htab_find_slot_with_hash (DEFAULT_DEFS (fn), &in,
-                                  DECL_UID (var), INSERT);
+  tree *loc = DEFAULT_DEFS (fn)->find_slot_with_hash ((tree)&in,
+                                                     DECL_UID (var), INSERT);
 
   /* Default definition might be changed by tail call optimization.  */
   if (*loc)
-    SSA_NAME_IS_DEFAULT_DEF (*(tree *) loc) = false;
+    SSA_NAME_IS_DEFAULT_DEF (*loc) = false;
 
    /* Mark DEF as the default definition for VAR.  */
-  *(tree *) loc = def;
+  *loc = def;
   SSA_NAME_IS_DEFAULT_DEF (def) = true;
 }
 
@@ -383,35 +373,40 @@ get_or_create_ssa_default_def (struct function *fn, tree var)
    base variable.  The access range is delimited by bit positions *POFFSET and
    *POFFSET + *PMAX_SIZE.  The access size is *PSIZE bits.  If either
    *PSIZE or *PMAX_SIZE is -1, they could not be determined.  If *PSIZE
-   and *PMAX_SIZE are equal, the access is non-variable.  */
+   and *PMAX_SIZE are equal, the access is non-variable.  If *PREVERSE is
+   true, the storage order of the reference is reversed.  */
 
 tree
-get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
-                        HOST_WIDE_INT *psize,
-                        HOST_WIDE_INT *pmax_size)
+get_ref_base_and_extent (tree exp, poly_int64_pod *poffset,
+                        poly_int64_pod *psize,
+                        poly_int64_pod *pmax_size,
+                        bool *preverse)
 {
-  offset_int bitsize = -1;
-  offset_int maxsize;
+  poly_offset_int bitsize = -1;
+  poly_offset_int maxsize;
   tree size_tree = NULL_TREE;
-  offset_int bit_offset = 0;
+  poly_offset_int bit_offset = 0;
   bool seen_variable_array_ref = false;
 
-  /* First get the final access size from just the outermost expression.  */
+  /* First get the final access size and the storage order from just the
+     outermost expression.  */
   if (TREE_CODE (exp) == COMPONENT_REF)
     size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
   else if (TREE_CODE (exp) == BIT_FIELD_REF)
     size_tree = TREE_OPERAND (exp, 1);
   else if (!VOID_TYPE_P (TREE_TYPE (exp)))
     {
-      enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+      machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
       if (mode == BLKmode)
        size_tree = TYPE_SIZE (TREE_TYPE (exp));
       else
-       bitsize = int (GET_MODE_BITSIZE (mode));
+       bitsize = GET_MODE_BITSIZE (mode);
     }
   if (size_tree != NULL_TREE
-      && TREE_CODE (size_tree) == INTEGER_CST)
-    bitsize = wi::to_offset (size_tree);
+      && poly_int_tree_p (size_tree))
+    bitsize = wi::to_poly_offset (size_tree);
+
+  *preverse = reverse_storage_order_for_component_p (exp);
 
   /* Initially, maxsize is the same as the accessed element size.
      In the following it will only grow (or become -1).  */
@@ -424,7 +419,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
       switch (TREE_CODE (exp))
        {
        case BIT_FIELD_REF:
-         bit_offset += wi::to_offset (TREE_OPERAND (exp, 2));
+         bit_offset += wi::to_poly_offset (TREE_OPERAND (exp, 2));
          break;
 
        case COMPONENT_REF:
@@ -432,10 +427,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
            tree field = TREE_OPERAND (exp, 1);
            tree this_offset = component_ref_field_offset (exp);
 
-           if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
+           if (this_offset && poly_int_tree_p (this_offset))
              {
-               offset_int woffset = wi::lshift (wi::to_offset (this_offset),
-                                                LOG2_BITS_PER_UNIT);
+               poly_offset_int woffset = (wi::to_poly_offset (this_offset)
+                                          << LOG2_BITS_PER_UNIT);
                woffset += wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
                bit_offset += woffset;
 
@@ -443,7 +438,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                   referenced the last field of a struct or a union member
                   then we have to adjust maxsize by the padding at the end
                   of our field.  */
-               if (seen_variable_array_ref && maxsize != -1)
+               if (seen_variable_array_ref)
                  {
                    tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
                    tree next = DECL_CHAIN (field);
@@ -455,19 +450,25 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                        tree fsize = DECL_SIZE_UNIT (field);
                        tree ssize = TYPE_SIZE_UNIT (stype);
                        if (fsize == NULL
-                           || TREE_CODE (fsize) != INTEGER_CST
+                           || !poly_int_tree_p (fsize)
                            || ssize == NULL
-                           || TREE_CODE (ssize) != INTEGER_CST)
+                           || !poly_int_tree_p (ssize))
                          maxsize = -1;
-                       else
+                       else if (known_size_p (maxsize))
                          {
-                           offset_int tem = (wi::to_offset (ssize)
-                                             - wi::to_offset (fsize));
-                           tem = wi::lshift (tem, LOG2_BITS_PER_UNIT);
+                           poly_offset_int tem
+                             = (wi::to_poly_offset (ssize)
+                                - wi::to_poly_offset (fsize));
+                           tem <<= LOG2_BITS_PER_UNIT;
                            tem -= woffset;
                            maxsize += tem;
                          }
                      }
+                   /* An component ref with an adjacent field up in the
+                      structure hierarchy constrains the size of any variable
+                      array ref lower in the access hierarchy.  */
+                   else
+                     seen_variable_array_ref = false;
                  }
              }
            else
@@ -476,10 +477,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                /* We need to adjust maxsize to the whole structure bitsize.
                   But we can subtract any constant offset seen so far,
                   because that would get us out of the structure otherwise.  */
-               if (maxsize != -1
+               if (known_size_p (maxsize)
                    && csize
-                   && TREE_CODE (csize) == INTEGER_CST)
-                 maxsize = wi::to_offset (csize) - bit_offset;
+                   && poly_int_tree_p (csize))
+                 maxsize = wi::to_poly_offset (csize) - bit_offset;
                else
                  maxsize = -1;
              }
@@ -493,17 +494,18 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
            tree low_bound, unit_size;
 
            /* If the resulting bit-offset is constant, track it.  */
-           if (TREE_CODE (index) == INTEGER_CST
+           if (poly_int_tree_p (index)
                && (low_bound = array_ref_low_bound (exp),
-                   TREE_CODE (low_bound) == INTEGER_CST)
+                   poly_int_tree_p (low_bound))
                && (unit_size = array_ref_element_size (exp),
                    TREE_CODE (unit_size) == INTEGER_CST))
              {
-               offset_int woffset
-                 = wi::sext (wi::to_offset (index) - wi::to_offset (low_bound),
+               poly_offset_int woffset
+                 = wi::sext (wi::to_poly_offset (index)
+                             - wi::to_poly_offset (low_bound),
                              TYPE_PRECISION (TREE_TYPE (index)));
                woffset *= wi::to_offset (unit_size);
-               woffset = wi::lshift (woffset, LOG2_BITS_PER_UNIT);
+               woffset <<= LOG2_BITS_PER_UNIT;
                bit_offset += woffset;
 
                /* An array ref with a constant index up in the structure
@@ -517,16 +519,59 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                /* We need to adjust maxsize to the whole array bitsize.
                   But we can subtract any constant offset seen so far,
                   because that would get us outside of the array otherwise.  */
-               if (maxsize != -1
+               if (known_size_p (maxsize)
                    && asize
-                   && TREE_CODE (asize) == INTEGER_CST)
-                 maxsize = wi::to_offset (asize) - bit_offset;
+                   && poly_int_tree_p (asize))
+                 maxsize = wi::to_poly_offset (asize) - bit_offset;
                else
                  maxsize = -1;
 
                /* Remember that we have seen an array ref with a variable
                   index.  */
                seen_variable_array_ref = true;
+
+               wide_int min, max;
+               if (TREE_CODE (index) == SSA_NAME
+                   && (low_bound = array_ref_low_bound (exp),
+                       poly_int_tree_p (low_bound))
+                   && (unit_size = array_ref_element_size (exp),
+                       TREE_CODE (unit_size) == INTEGER_CST)
+                   && get_range_info (index, &min, &max) == VR_RANGE)
+                 {
+                   poly_offset_int lbound = wi::to_poly_offset (low_bound);
+                   /* Try to constrain maxsize with range information.  */
+                   offset_int omax
+                     = offset_int::from (max, TYPE_SIGN (TREE_TYPE (index)));
+                   if (known_lt (lbound, omax))
+                     {
+                       poly_offset_int rmaxsize;
+                       rmaxsize = (omax - lbound + 1)
+                           * wi::to_offset (unit_size) << LOG2_BITS_PER_UNIT;
+                       if (!known_size_p (maxsize)
+                           || known_lt (rmaxsize, maxsize))
+                         {
+                           /* If we know an upper bound below the declared
+                              one this is no longer variable.  */
+                           if (known_size_p (maxsize))
+                             seen_variable_array_ref = false;
+                           maxsize = rmaxsize;
+                         }
+                     }
+                   /* Try to adjust bit_offset with range information.  */
+                   offset_int omin
+                     = offset_int::from (min, TYPE_SIGN (TREE_TYPE (index)));
+                   if (known_le (lbound, omin))
+                     {
+                       poly_offset_int woffset
+                         = wi::sext (omin - lbound,
+                                     TYPE_PRECISION (TREE_TYPE (index)));
+                       woffset *= wi::to_offset (unit_size);
+                       woffset <<= LOG2_BITS_PER_UNIT;
+                       bit_offset += woffset;
+                       if (known_size_p (maxsize))
+                         maxsize -= woffset;
+                     }
+                 }
              }
          }
          break;
@@ -565,11 +610,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
             base type boundary.  This needs to include possible trailing
             padding that is there for alignment purposes.  */
          if (seen_variable_array_ref
-             && maxsize != -1
+             && known_size_p (maxsize)
              && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
-                 || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
-                 || (bit_offset + maxsize
-                     == wi::to_offset (TYPE_SIZE (TREE_TYPE (exp))))))
+                 || !poly_int_tree_p (TYPE_SIZE (TREE_TYPE (exp)))
+                 || (maybe_eq
+                     (bit_offset + maxsize,
+                      wi::to_poly_offset (TYPE_SIZE (TREE_TYPE (exp)))))))
            maxsize = -1;
 
          /* Hand back the decl for MEM[&decl, off].  */
@@ -579,12 +625,13 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
              else
                {
-                 offset_int off = mem_ref_offset (exp);
-                 off = wi::lshift (off, LOG2_BITS_PER_UNIT);
+                 poly_offset_int off = mem_ref_offset (exp);
+                 off <<= LOG2_BITS_PER_UNIT;
                  off += bit_offset;
-                 if (wi::fits_shwi_p (off))
+                 poly_int64 off_hwi;
+                 if (off.to_shwi (&off_hwi))
                    {
-                     bit_offset = off;
+                     bit_offset = off_hwi;
                      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                    }
                }
@@ -598,17 +645,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
       exp = TREE_OPERAND (exp, 0);
     }
 
-  /* We need to deal with variable arrays ending structures.  */
-  if (seen_variable_array_ref
-      && maxsize != -1
-      && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
-         || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
-         || (bit_offset + maxsize
-             == wi::to_offset (TYPE_SIZE (TREE_TYPE (exp))))))
-    maxsize = -1;
-
  done:
-  if (!wi::fits_shwi_p (bitsize) || wi::neg_p (bitsize))
+  if (!bitsize.to_shwi (psize) || maybe_lt (*psize, 0))
     {
       *poffset = 0;
       *psize = -1;
@@ -617,9 +655,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
       return exp;
     }
 
-  *psize = bitsize.to_shwi ();
-
-  if (!wi::fits_shwi_p (bit_offset))
+  /* ???  Due to negative offsets in ARRAY_REF we can end up with
+     negative bit_offset here.  We might want to store a zero offset
+     in this case.  */
+  if (!bit_offset.to_shwi (poffset))
     {
       *poffset = 0;
       *pmax_size = -1;
@@ -631,33 +670,223 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 
   if (DECL_P (exp))
     {
+      if (VAR_P (exp)
+         && ((flag_unconstrained_commons && DECL_COMMON (exp))
+             || (DECL_EXTERNAL (exp) && seen_variable_array_ref)))
+       {
+         tree sz_tree = TYPE_SIZE (TREE_TYPE (exp));
+         /* If size is unknown, or we have read to the end, assume there
+            may be more to the structure than we are told.  */
+         if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+             || (seen_variable_array_ref
+                 && (sz_tree == NULL_TREE
+                     || !poly_int_tree_p (sz_tree)
+                     || maybe_eq (bit_offset + maxsize,
+                                  wi::to_poly_offset (sz_tree)))))
+           maxsize = -1;
+       }
       /* If maxsize is unknown adjust it according to the size of the
          base decl.  */
-      if (maxsize == -1
-         && DECL_SIZE (exp)
-         && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST)
-       maxsize = wi::to_offset (DECL_SIZE (exp)) - bit_offset;
+      else if (!known_size_p (maxsize)
+              && DECL_SIZE (exp)
+              && poly_int_tree_p (DECL_SIZE (exp)))
+       maxsize = wi::to_poly_offset (DECL_SIZE (exp)) - bit_offset;
     }
   else if (CONSTANT_CLASS_P (exp))
     {
       /* If maxsize is unknown adjust it according to the size of the
          base type constant.  */
-      if (maxsize == -1
+      if (!known_size_p (maxsize)
          && TYPE_SIZE (TREE_TYPE (exp))
-         && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
-       maxsize = (wi::to_offset (TYPE_SIZE (TREE_TYPE (exp)))
+         && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (exp))))
+       maxsize = (wi::to_poly_offset (TYPE_SIZE (TREE_TYPE (exp)))
                   - bit_offset);
     }
 
-  /* ???  Due to negative offsets in ARRAY_REF we can end up with
-     negative bit_offset here.  We might want to store a zero offset
-     in this case.  */
-  *poffset = bit_offset.to_shwi ();
-  if (!wi::fits_shwi_p (maxsize) || wi::neg_p (maxsize))
+  if (!maxsize.to_shwi (pmax_size)
+      || maybe_lt (*pmax_size, 0)
+      || !endpoint_representable_p (*poffset, *pmax_size))
     *pmax_size = -1;
-  else
-    *pmax_size = maxsize.to_shwi ();
 
+  /* Punt if *POFFSET + *PSIZE overflows in HOST_WIDE_INT, the callers don't
+     check for such overflows individually and assume it works.  */
+  if (!endpoint_representable_p (*poffset, *psize))
+    {
+      *poffset = 0;
+      *psize = -1;
+      *pmax_size = -1;
+
+      return exp;
+    }
+
+  return exp;
+}
+
+/* Like get_ref_base_and_extent, but for cases in which we only care
+   about constant-width accesses at constant offsets.  Return null
+   if the access is anything else.  */
+
+tree
+get_ref_base_and_extent_hwi (tree exp, HOST_WIDE_INT *poffset,
+                            HOST_WIDE_INT *psize, bool *preverse)
+{
+  poly_int64 offset, size, max_size;
+  HOST_WIDE_INT const_offset, const_size;
+  bool reverse;
+  tree decl = get_ref_base_and_extent (exp, &offset, &size, &max_size,
+                                      &reverse);
+  if (!offset.is_constant (&const_offset)
+      || !size.is_constant (&const_size)
+      || const_offset < 0
+      || !known_size_p (max_size)
+      || maybe_ne (max_size, const_size))
+    return NULL_TREE;
+
+  *poffset = const_offset;
+  *psize = const_size;
+  *preverse = reverse;
+  return decl;
+}
+
+/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
+   denotes the starting address of the memory access EXP.
+   Returns NULL_TREE if the offset is not constant or any component
+   is not BITS_PER_UNIT-aligned.
+   VALUEIZE if non-NULL is used to valueize SSA names.  It should return
+   its argument or a constant if the argument is known to be constant.  */
+
+tree
+get_addr_base_and_unit_offset_1 (tree exp, poly_int64_pod *poffset,
+                                tree (*valueize) (tree))
+{
+  poly_int64 byte_offset = 0;
+
+  /* Compute cumulative byte-offset for nested component-refs and array-refs,
+     and find the ultimate containing object.  */
+  while (1)
+    {
+      switch (TREE_CODE (exp))
+       {
+       case BIT_FIELD_REF:
+         {
+           poly_int64 this_byte_offset;
+           poly_uint64 this_bit_offset;
+           if (!poly_int_tree_p (TREE_OPERAND (exp, 2), &this_bit_offset)
+               || !multiple_p (this_bit_offset, BITS_PER_UNIT,
+                               &this_byte_offset))
+             return NULL_TREE;
+           byte_offset += this_byte_offset;
+         }
+         break;
+
+       case COMPONENT_REF:
+         {
+           tree field = TREE_OPERAND (exp, 1);
+           tree this_offset = component_ref_field_offset (exp);
+           poly_int64 hthis_offset;
+
+           if (!this_offset
+               || !poly_int_tree_p (this_offset, &hthis_offset)
+               || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+                   % BITS_PER_UNIT))
+             return NULL_TREE;
+
+           hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+                            / BITS_PER_UNIT);
+           byte_offset += hthis_offset;
+         }
+         break;
+
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         {
+           tree index = TREE_OPERAND (exp, 1);
+           tree low_bound, unit_size;
+
+           if (valueize
+               && TREE_CODE (index) == SSA_NAME)
+             index = (*valueize) (index);
+
+           /* If the resulting bit-offset is constant, track it.  */
+           if (poly_int_tree_p (index)
+               && (low_bound = array_ref_low_bound (exp),
+                   poly_int_tree_p (low_bound))
+               && (unit_size = array_ref_element_size (exp),
+                   TREE_CODE (unit_size) == INTEGER_CST))
+             {
+               poly_offset_int woffset
+                 = wi::sext (wi::to_poly_offset (index)
+                             - wi::to_poly_offset (low_bound),
+                             TYPE_PRECISION (TREE_TYPE (index)));
+               woffset *= wi::to_offset (unit_size);
+               byte_offset += woffset.force_shwi ();
+             }
+           else
+             return NULL_TREE;
+         }
+         break;
+
+       case REALPART_EXPR:
+         break;
+
+       case IMAGPART_EXPR:
+         byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+         break;
+
+       case VIEW_CONVERT_EXPR:
+         break;
+
+       case MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (!integer_zerop (TREE_OPERAND (exp, 1)))
+                 {
+                   poly_offset_int off = mem_ref_offset (exp);
+                   byte_offset += off.force_shwi ();
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+
+       case TARGET_MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+                 return NULL_TREE;
+               if (!integer_zerop (TMR_OFFSET (exp)))
+                 {
+                   poly_offset_int off = mem_ref_offset (exp);
+                   byte_offset += off.force_shwi ();
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+
+       default:
+         goto done;
+       }
+
+      exp = TREE_OPERAND (exp, 0);
+    }
+done:
+
+  *poffset = byte_offset;
   return exp;
 }
 
@@ -667,7 +896,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
    is not BITS_PER_UNIT-aligned.  */
 
 tree
-get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset)
+get_addr_base_and_unit_offset (tree exp, poly_int64_pod *poffset)
 {
   return get_addr_base_and_unit_offset_1 (exp, poffset, NULL);
 }
@@ -676,7 +905,7 @@ get_addr_base_and_unit_offset (tree exp, HOST_WIDE_INT *poffset)
    SSA_NAME_OCCURS_IN_ABNORMAL_PHI set, otherwise false.  */
 
 bool
-stmt_references_abnormal_ssa_name (gimple stmt)
+stmt_references_abnormal_ssa_name (gimple *stmt)
 {
   ssa_op_iter oi;
   use_operand_p use_p;
@@ -690,13 +919,35 @@ stmt_references_abnormal_ssa_name (gimple stmt)
   return false;
 }
 
+/* If STMT takes any abnormal PHI values as input, replace them with
+   local copies.  */
+
+void
+replace_abnormal_ssa_names (gimple *stmt)
+{
+  ssa_op_iter oi;
+  use_operand_p use_p;
+
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, oi, SSA_OP_USE)
+    {
+      tree op = USE_FROM_PTR (use_p);
+      if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
+       {
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         tree new_name = make_ssa_name (TREE_TYPE (op));
+         gassign *assign = gimple_build_assign (new_name, op);
+         gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
+         SET_USE (use_p, new_name);
+       }
+    }
+}
+
 /* Pair of tree and a sorting index, for dump_enumerated_decls.  */
-struct GTY(()) numbered_tree_d
+struct GTY(()) numbered_tree
 {
   tree t;
   int num;
 };
-typedef struct numbered_tree_d numbered_tree;
 
 
 /* Compare two declarations references by their DECL_UID / sequence number.
@@ -739,8 +990,11 @@ dump_enumerated_decls_push (tree *tp, int *walk_subtrees, void *data)
    FILE is the dump file where to output the list and FLAGS is as in
    print_generic_expr.  */
 void
-dump_enumerated_decls (FILE *file, int flags)
+dump_enumerated_decls (FILE *file, dump_flags_t flags)
 {
+  if (!cfun->cfg)
+    return;
+
   basic_block bb;
   struct walk_stmt_info wi;
   auto_vec<numbered_tree, 40> decl_list;