]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/var-tracking.c
[Ada] Fix small oversight in latest change for Replace_Discriminants
[thirdparty/gcc.git] / gcc / var-tracking.c
index e3542d31e1515cb2c1c62166b1411715a78eabd8..fc861a0d8ce0e389e8680f83f12acdfb4ab80de6 100644 (file)
@@ -1,5 +1,5 @@
 /* Variable tracking routines for the GNU compiler.
-   Copyright (C) 2002-2015 Free Software Foundation, Inc.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
-#include "cfghooks.h"
+#include "target.h"
 #include "rtl.h"
-#include "alias.h"
 #include "tree.h"
+#include "cfghooks.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "insn-config.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic.h"
 #include "varasm.h"
 #include "stor-layout.h"
 #include "cfgrtl.h"
 #include "cfganal.h"
-#include "tm_p.h"
-#include "flags.h"
-#include "insn-config.h"
 #include "reload.h"
-#include "alloc-pool.h"
-#include "regs.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
 #include "calls.h"
-#include "emit-rtl.h"
-#include "stmt.h"
-#include "expr.h"
-#include "tree-pass.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
 #include "cselib.h"
-#include "target.h"
-#include "params.h"
-#include "diagnostic.h"
 #include "tree-pretty-print.h"
-#include "recog.h"
 #include "rtl-iter.h"
 #include "fibonacci_heap.h"
+#include "print-rtl.h"
+#include "function-abi.h"
 
 typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
 typedef fibonacci_node <long, basic_block_def> bb_heap_node_t;
@@ -248,10 +243,10 @@ dv_as_opaque (decl_or_value dv)
    register is described by a chain of these structures.
    The chains are pretty short (usually 1 or 2 elements) and thus
    chain is the best data structure.  */
-typedef struct attrs_def
+struct attrs
 {
   /* Pointer to next member of the list.  */
-  struct attrs_def *next;
+  attrs *next;
 
   /* The rtx of register.  */
   rtx loc;
@@ -261,7 +256,7 @@ typedef struct attrs_def
 
   /* Offset from start of DECL.  */
   HOST_WIDE_INT offset;
-} *attrs;
+};
 
 /* Structure for chaining the locations.  */
 struct location_chain
@@ -357,7 +352,7 @@ struct variable_part
 
 /* Enumeration type used to discriminate various types of one-part
    variables.  */
-typedef enum onepart_enum
+enum onepart_enum
 {
   /* Not a one-part variable.  */
   NOT_ONEPART = 0,
@@ -367,10 +362,10 @@ typedef enum onepart_enum
   ONEPART_DEXPR = 2,
   /* A VALUE.  */
   ONEPART_VALUE = 3
-} onepart_enum_t;
+};
 
 /* Structure describing where the variable is located.  */
-typedef struct variable_def
+struct variable
 {
   /* The declaration of the variable, or an RTL value being handled
      like a declaration.  */
@@ -391,28 +386,35 @@ typedef struct variable_def
 
   /* The variable parts.  */
   variable_part var_part[1];
-} *variable;
-typedef const struct variable_def *const_variable;
+};
 
 /* Pointer to the BB's information specific to variable tracking pass.  */
-#define VTI(BB) ((variable_tracking_info) (BB)->aux)
+#define VTI(BB) ((variable_tracking_info *) (BB)->aux)
 
-/* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
-#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
+/* Return MEM_OFFSET (MEM) as a HOST_WIDE_INT, or 0 if we can't.  */
 
-#if ENABLE_CHECKING && (GCC_VERSION >= 2007)
+static inline HOST_WIDE_INT
+int_mem_offset (const_rtx mem)
+{
+  HOST_WIDE_INT offset;
+  if (MEM_OFFSET_KNOWN_P (mem) && MEM_OFFSET (mem).is_constant (&offset))
+    return offset;
+  return 0;
+}
+
+#if CHECKING_P && (GCC_VERSION >= 2007)
 
 /* Access VAR's Ith part's offset, checking that it's not a one-part
    variable.  */
 #define VAR_PART_OFFSET(var, i) __extension__                  \
-(*({  variable const __v = (var);                              \
+(*({  variable *const __v = (var);                             \
       gcc_checking_assert (!__v->onepart);                     \
       &__v->var_part[(i)].aux.offset; }))
 
 /* Access VAR's one-part auxiliary data, checking that it is a
    one-part variable.  */
 #define VAR_LOC_1PAUX(var) __extension__                       \
-(*({  variable const __v = (var);                              \
+(*({  variable *const __v = (var);                             \
       gcc_checking_assert (__v->onepart);                      \
       &__v->var_part[0].aux.onepaux; }))
 
@@ -471,19 +473,19 @@ static void variable_htab_free (void *);
 
 /* Variable hashtable helpers.  */
 
-struct variable_hasher : pointer_hash <variable_def>
+struct variable_hasher : pointer_hash <variable>
 {
   typedef void *compare_type;
-  static inline hashval_t hash (const variable_def *);
-  static inline bool equal (const variable_def *, const void *);
-  static inline void remove (variable_def *);
+  static inline hashval_t hash (const variable *);
+  static inline bool equal (const variable *, const void *);
+  static inline void remove (variable *);
 };
 
 /* The hash function for variable_htab, computes the hash value
    from the declaration of variable X.  */
 
 inline hashval_t
-variable_hasher::hash (const variable_def *v)
+variable_hasher::hash (const variable *v)
 {
   return dv_htab_hash (v->dv);
 }
@@ -491,7 +493,7 @@ variable_hasher::hash (const variable_def *v)
 /* Compare the declaration of variable X with declaration Y.  */
 
 inline bool
-variable_hasher::equal (const variable_def *v, const void *y)
+variable_hasher::equal (const variable *v, const void *y)
 {
   decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
 
@@ -501,7 +503,7 @@ variable_hasher::equal (const variable_def *v, const void *y)
 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
 
 inline void
-variable_hasher::remove (variable_def *var)
+variable_hasher::remove (variable *var)
 {
   variable_htab_free (var);
 }
@@ -541,7 +543,7 @@ struct dataflow_set
   HOST_WIDE_INT stack_adjust;
 
   /* Attributes for registers (lists of attrs).  */
-  attrs regs[FIRST_PSEUDO_REGISTER];
+  attrs *regs[FIRST_PSEUDO_REGISTER];
 
   /* Variable locations.  */
   shared_hash *vars;
@@ -552,7 +554,7 @@ struct dataflow_set
 
 /* The structure (one for each basic block) containing the information
    needed for variable tracking.  */
-typedef struct variable_tracking_info_def
+struct variable_tracking_info
 {
   /* The vector of micro operations.  */
   vec<micro_operation> mos;
@@ -573,20 +575,20 @@ typedef struct variable_tracking_info_def
   /* Has the block been flooded in VTA?  */
   bool flooded;
 
-} *variable_tracking_info;
+};
 
 /* Alloc pool for struct attrs_def.  */
-object_allocator<attrs_def> attrs_def_pool ("attrs_def pool");
+object_allocator<attrs> attrs_pool ("attrs pool");
 
 /* Alloc pool for struct variable_def with MAX_VAR_PARTS entries.  */
 
 static pool_allocator var_pool
-  ("variable_def pool", sizeof (variable_def) +
-   (MAX_VAR_PARTS - 1) * sizeof (((variable)NULL)->var_part[0]));
+  ("variable_def pool", sizeof (variable) +
+   (MAX_VAR_PARTS - 1) * sizeof (((variable *)NULL)->var_part[0]));
 
 /* Alloc pool for struct variable_def with a single var_part entry.  */
 static pool_allocator valvar_pool
-  ("small variable_def pool", sizeof (variable_def));
+  ("small variable_def pool", sizeof (variable));
 
 /* Alloc pool for struct location_chain.  */
 static object_allocator<location_chain> location_chain_pool
@@ -616,14 +618,14 @@ static shared_hash *empty_shared_hash;
 static bitmap scratch_regs = NULL;
 
 #ifdef HAVE_window_save
-typedef struct GTY(()) parm_reg {
+struct GTY(()) parm_reg {
   rtx outgoing;
   rtx incoming;
-} parm_reg_t;
+};
 
 
 /* Vector of windowed parameter registers, if any.  */
-static vec<parm_reg_t, va_gc> *windowed_parm_regs = NULL;
+static vec<parm_reg, va_gc> *windowed_parm_regs = NULL;
 #endif
 
 /* Variable used to tell whether cselib_process_insn called our hook.  */
@@ -636,15 +638,15 @@ static void insn_stack_adjust_offset_pre_post (rtx_insn *, HOST_WIDE_INT *,
                                               HOST_WIDE_INT *);
 static bool vt_stack_adjustments (void);
 
-static void init_attrs_list_set (attrs *);
-static void attrs_list_clear (attrs *);
-static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
-static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
-static void attrs_list_copy (attrs *, attrs);
-static void attrs_list_union (attrs *, attrs);
+static void init_attrs_list_set (attrs **);
+static void attrs_list_clear (attrs **);
+static attrs *attrs_list_member (attrs *, decl_or_value, HOST_WIDE_INT);
+static void attrs_list_insert (attrs **, decl_or_value, HOST_WIDE_INT, rtx);
+static void attrs_list_copy (attrs **, attrs *);
+static void attrs_list_union (attrs **, attrs *);
 
-static variable_def **unshare_variable (dataflow_set *set, variable_def **slot,
-                                       variable var, enum var_init_status);
+static variable **unshare_variable (dataflow_set *set, variable **slot,
+                                       variable *var, enum var_init_status);
 static void vars_copy (variable_table_type *, variable_table_type *);
 static tree var_debug_decl (tree);
 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
@@ -662,49 +664,47 @@ static void dataflow_set_clear (dataflow_set *);
 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
 static int variable_union_info_cmp_pos (const void *, const void *);
 static void dataflow_set_union (dataflow_set *, dataflow_set *);
-static location_chain *find_loc_in_1pdv (rtx, variable, variable_table_type *);
+static location_chain *find_loc_in_1pdv (rtx, variable *,
+                                        variable_table_type *);
 static bool canon_value_cmp (rtx, rtx);
 static int loc_cmp (rtx, rtx);
 static bool variable_part_different_p (variable_part *, variable_part *);
-static bool onepart_variable_different_p (variable, variable);
-static bool variable_different_p (variable, variable);
+static bool onepart_variable_different_p (variable *, variable *);
+static bool variable_different_p (variable *, variable *);
 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
 static void dataflow_set_destroy (dataflow_set *);
 
-static bool contains_symbol_ref (rtx);
 static bool track_expr_p (tree, bool);
-static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
 static void add_uses_1 (rtx *, void *);
 static void add_stores (rtx, const_rtx, void *);
 static bool compute_bb_dataflow (basic_block);
 static bool vt_find_locations (void);
 
-static void dump_attrs_list (attrs);
-static void dump_var (variable);
+static void dump_attrs_list (attrs *);
+static void dump_var (variable *);
 static void dump_vars (variable_table_type *);
 static void dump_dataflow_set (dataflow_set *);
 static void dump_dataflow_sets (void);
 
 static void set_dv_changed (decl_or_value, bool);
-static void variable_was_changed (variable, dataflow_set *);
-static variable_def **set_slot_part (dataflow_set *, rtx, variable_def **,
-                                    decl_or_value, HOST_WIDE_INT,
-                                    enum var_init_status, rtx);
+static void variable_was_changed (variable *, dataflow_set *);
+static variable **set_slot_part (dataflow_set *, rtx, variable **,
+                                decl_or_value, HOST_WIDE_INT,
+                                enum var_init_status, rtx);
 static void set_variable_part (dataflow_set *, rtx,
                               decl_or_value, HOST_WIDE_INT,
                               enum var_init_status, rtx, enum insert_option);
-static variable_def **clobber_slot_part (dataflow_set *, rtx,
-                                        variable_def **, HOST_WIDE_INT, rtx);
+static variable **clobber_slot_part (dataflow_set *, rtx,
+                                    variable **, HOST_WIDE_INT, rtx);
 static void clobber_variable_part (dataflow_set *, rtx,
                                   decl_or_value, HOST_WIDE_INT, rtx);
-static variable_def **delete_slot_part (dataflow_set *, rtx, variable_def **,
-                                       HOST_WIDE_INT);
+static variable **delete_slot_part (dataflow_set *, rtx, variable **,
+                                   HOST_WIDE_INT);
 static void delete_variable_part (dataflow_set *, rtx,
                                  decl_or_value, HOST_WIDE_INT);
 static void emit_notes_in_bb (basic_block, dataflow_set *);
 static void vt_emit_notes (void);
 
-static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
 static void vt_add_function_parameters (void);
 static bool vt_initialize (void);
 static void vt_finalize (void);
@@ -879,7 +879,7 @@ vt_stack_adjustments (void)
             pointer is often restored via a load-multiple instruction
             and so no stack_adjust offset is recorded for it.  This means
             that the stack offset at the end of the epilogue block is the
-            the same as the offset before the epilogue, whereas other paths
+            same as the offset before the epilogue, whereas other paths
             to the exit block will have the correct stack_adjust.
 
             It is safe to ignore these differences because (a) we never
@@ -918,23 +918,24 @@ static HOST_WIDE_INT cfa_base_offset;
    or hard_frame_pointer_rtx.  */
 
 static inline rtx
-compute_cfa_pointer (HOST_WIDE_INT adjustment)
+compute_cfa_pointer (poly_int64 adjustment)
 {
   return plus_constant (Pmode, cfa_base_rtx, adjustment + cfa_base_offset);
 }
 
 /* Adjustment for hard_frame_pointer_rtx to cfa base reg,
    or -1 if the replacement shouldn't be done.  */
-static HOST_WIDE_INT hard_frame_pointer_adjustment = -1;
+static poly_int64 hard_frame_pointer_adjustment = -1;
 
 /* Data for adjust_mems callback.  */
 
-struct adjust_mem_data
+class adjust_mem_data
 {
+public:
   bool store;
   machine_mode mem_mode;
   HOST_WIDE_INT stack_adjust;
-  rtx_expr_list *side_effects;
+  auto_vec<rtx> side_effects;
 };
 
 /* Helper for adjust_mems.  Return true if X is suitable for
@@ -965,6 +966,24 @@ use_narrower_mode_test (rtx x, const_rtx subreg)
          case MULT:
            break;
          case ASHIFT:
+           if (GET_MODE (XEXP (x, 1)) != VOIDmode)
+             {
+               enum machine_mode mode = GET_MODE (subreg);
+               rtx op1 = XEXP (x, 1);
+               enum machine_mode op1_mode = GET_MODE (op1);
+               if (GET_MODE_PRECISION (as_a <scalar_int_mode> (mode))
+                   < GET_MODE_PRECISION (as_a <scalar_int_mode> (op1_mode)))
+                 {
+                   poly_uint64 byte = subreg_lowpart_offset (mode, op1_mode);
+                   if (GET_CODE (op1) == SUBREG || GET_CODE (op1) == CONCAT)
+                     {
+                       if (!simplify_subreg (mode, op1, op1_mode, byte))
+                         return false;
+                     }
+                   else if (!validate_subreg (mode, op1_mode, op1, byte))
+                     return false;
+                 }
+             }
            iter.substitute (XEXP (x, 0));
            break;
          default:
@@ -977,7 +996,7 @@ use_narrower_mode_test (rtx x, const_rtx subreg)
 /* Transform X into narrower mode MODE from wider mode WMODE.  */
 
 static rtx
-use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
+use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode)
 {
   rtx op0, op1;
   if (CONSTANT_P (x))
@@ -998,7 +1017,8 @@ use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
       /* Ensure shift amount is not wider than mode.  */
       if (GET_MODE (op1) == VOIDmode)
        op1 = lowpart_subreg (mode, op1, wmode);
-      else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1)))
+      else if (GET_MODE_PRECISION (mode)
+              < GET_MODE_PRECISION (as_a <scalar_int_mode> (GET_MODE (op1))))
        op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
       return simplify_gen_binary (ASHIFT, mode, op0, op1);
     default:
@@ -1011,10 +1031,12 @@ use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
 static rtx
 adjust_mems (rtx loc, const_rtx old_rtx, void *data)
 {
-  struct adjust_mem_data *amd = (struct adjust_mem_data *) data;
+  class adjust_mem_data *amd = (class adjust_mem_data *) data;
   rtx mem, addr = loc, tem;
   machine_mode mem_mode_save;
   bool store_save;
+  scalar_int_mode tem_mode, tem_subreg_mode;
+  poly_int64 size;
   switch (GET_CODE (loc))
     {
     case REG:
@@ -1028,7 +1050,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
        return compute_cfa_pointer (amd->stack_adjust);
       else if (loc == hard_frame_pointer_rtx
               && frame_pointer_needed
-              && hard_frame_pointer_adjustment != -1
+              && maybe_ne (hard_frame_pointer_adjustment, -1)
               && cfa_base_rtx)
        return compute_cfa_pointer (hard_frame_pointer_adjustment);
       gcc_checking_assert (loc != virtual_incoming_args_rtx);
@@ -1059,33 +1081,29 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
       return mem;
     case PRE_INC:
     case PRE_DEC:
-      addr = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
-                          gen_int_mode (GET_CODE (loc) == PRE_INC
-                                        ? GET_MODE_SIZE (amd->mem_mode)
-                                        : -GET_MODE_SIZE (amd->mem_mode),
-                                        GET_MODE (loc)));
+      size = GET_MODE_SIZE (amd->mem_mode);
+      addr = plus_constant (GET_MODE (loc), XEXP (loc, 0),
+                           GET_CODE (loc) == PRE_INC ? size : -size);
+      /* FALLTHRU */
     case POST_INC:
     case POST_DEC:
       if (addr == loc)
        addr = XEXP (loc, 0);
       gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
-      tem = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
-                         gen_int_mode ((GET_CODE (loc) == PRE_INC
-                                        || GET_CODE (loc) == POST_INC)
-                                       ? GET_MODE_SIZE (amd->mem_mode)
-                                       : -GET_MODE_SIZE (amd->mem_mode),
-                                       GET_MODE (loc)));
+      size = GET_MODE_SIZE (amd->mem_mode);
+      tem = plus_constant (GET_MODE (loc), XEXP (loc, 0),
+                          (GET_CODE (loc) == PRE_INC
+                           || GET_CODE (loc) == POST_INC) ? size : -size);
       store_save = amd->store;
       amd->store = false;
       tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data);
       amd->store = store_save;
-      amd->side_effects = alloc_EXPR_LIST (0,
-                                          gen_rtx_SET (XEXP (loc, 0), tem),
-                                          amd->side_effects);
+      amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
       return addr;
     case PRE_MODIFY:
       addr = XEXP (loc, 1);
+      /* FALLTHRU */
     case POST_MODIFY:
       if (addr == loc)
        addr = XEXP (loc, 0);
@@ -1096,9 +1114,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
       tem = simplify_replace_fn_rtx (XEXP (loc, 1), old_rtx,
                                     adjust_mems, data);
       amd->store = store_save;
-      amd->side_effects = alloc_EXPR_LIST (0,
-                                          gen_rtx_SET (XEXP (loc, 0), tem),
-                                          amd->side_effects);
+      amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
       return addr;
     case SUBREG:
       /* First try without delegitimization of whole MEMs and
@@ -1125,22 +1141,20 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
       if (tem == NULL_RTX)
        tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
     finish_subreg:
-      if (MAY_HAVE_DEBUG_INSNS
+      if (MAY_HAVE_DEBUG_BIND_INSNS
          && GET_CODE (tem) == SUBREG
          && (GET_CODE (SUBREG_REG (tem)) == PLUS
              || GET_CODE (SUBREG_REG (tem)) == MINUS
              || GET_CODE (SUBREG_REG (tem)) == MULT
              || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
-         && (GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
-             || GET_MODE_CLASS (GET_MODE (tem)) == MODE_PARTIAL_INT)
-         && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
-             || GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_PARTIAL_INT)
-         && GET_MODE_PRECISION (GET_MODE (tem))
-            < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (tem)))
+         && is_a <scalar_int_mode> (GET_MODE (tem), &tem_mode)
+         && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (tem)),
+                                    &tem_subreg_mode)
+         && (GET_MODE_PRECISION (tem_mode)
+             < GET_MODE_PRECISION (tem_subreg_mode))
          && subreg_lowpart_p (tem)
          && use_narrower_mode_test (SUBREG_REG (tem), tem))
-       return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
-                                 GET_MODE (SUBREG_REG (tem)));
+       return use_narrower_mode (SUBREG_REG (tem), tem_mode, tem_subreg_mode);
       return tem;
     case ASM_OPERANDS:
       /* Don't do any replacements in second and following
@@ -1192,7 +1206,6 @@ adjust_mem_stores (rtx loc, const_rtx expr, void *data)
 static void
 adjust_insn (basic_block bb, rtx_insn *insn)
 {
-  struct adjust_mem_data amd;
   rtx set;
 
 #ifdef HAVE_window_save
@@ -1203,7 +1216,7 @@ adjust_insn (basic_block bb, rtx_insn *insn)
     {
       unsigned int i, nregs = vec_safe_length (windowed_parm_regs);
       rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2));
-      parm_reg_t *p;
+      parm_reg *p;
 
       FOR_EACH_VEC_SAFE_ELT (windowed_parm_regs, i, p)
        {
@@ -1221,12 +1234,12 @@ adjust_insn (basic_block bb, rtx_insn *insn)
     }
 #endif
 
+  adjust_mem_data amd;
   amd.mem_mode = VOIDmode;
   amd.stack_adjust = -VTI (bb)->out.stack_adjust;
-  amd.side_effects = NULL;
 
   amd.store = true;
-  note_stores (PATTERN (insn), adjust_mem_stores, &amd);
+  note_stores (insn, adjust_mem_stores, &amd);
 
   amd.store = false;
   if (GET_CODE (PATTERN (insn)) == PARALLEL
@@ -1289,10 +1302,10 @@ adjust_insn (basic_block bb, rtx_insn *insn)
        validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true);
     }
 
-  if (amd.side_effects)
+  if (!amd.side_effects.is_empty ())
     {
-      rtx *pat, new_pat, s;
-      int i, oldn, newn;
+      rtx *pat, new_pat;
+      int i, oldn;
 
       pat = &PATTERN (insn);
       if (GET_CODE (*pat) == COND_EXEC)
@@ -1301,17 +1314,18 @@ adjust_insn (basic_block bb, rtx_insn *insn)
        oldn = XVECLEN (*pat, 0);
       else
        oldn = 1;
-      for (s = amd.side_effects, newn = 0; s; newn++)
-       s = XEXP (s, 1);
+      unsigned int newn = amd.side_effects.length ();
       new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn));
       if (GET_CODE (*pat) == PARALLEL)
        for (i = 0; i < oldn; i++)
          XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i);
       else
        XVECEXP (new_pat, 0, 0) = *pat;
-      for (s = amd.side_effects, i = oldn; i < oldn + newn; i++, s = XEXP (s, 1))
-       XVECEXP (new_pat, 0, i) = XEXP (s, 0);
-      free_EXPR_LIST_list (&amd.side_effects);
+
+      rtx effect;
+      unsigned int j;
+      FOR_EACH_VEC_ELT_REVERSE (amd.side_effects, j, effect)
+       XVECEXP (new_pat, 0, j + oldn) = effect;
       validate_change (NULL_RTX, pat, new_pat, true);
     }
 }
@@ -1334,12 +1348,12 @@ dv_as_rtx (decl_or_value dv)
 /* Return nonzero if a decl_or_value must not have more than one
    variable part.  The returned value discriminates among various
    kinds of one-part DVs ccording to enum onepart_enum.  */
-static inline onepart_enum_t
+static inline onepart_enum
 dv_onepart_p (decl_or_value dv)
 {
   tree decl;
 
-  if (!MAY_HAVE_DEBUG_INSNS)
+  if (!MAY_HAVE_DEBUG_BIND_INSNS)
     return NOT_ONEPART;
 
   if (dv_is_value_p (dv))
@@ -1358,16 +1372,16 @@ dv_onepart_p (decl_or_value dv)
 
 /* Return the variable pool to be used for a dv of type ONEPART.  */
 static inline pool_allocator &
-onepart_pool (onepart_enum_t onepart)
+onepart_pool (onepart_enum onepart)
 {
   return onepart ? valvar_pool : var_pool;
 }
 
 /* Allocate a variable_def from the corresponding variable pool.  */
-static inline variable_def *
-onepart_pool_allocate (onepart_enum_t onepart)
+static inline variable *
+onepart_pool_allocate (onepart_enum onepart)
 {
-  return (variable_def*) onepart_pool (onepart).allocate ();
+  return (variable*) onepart_pool (onepart).allocate ();
 }
 
 /* Build a decl_or_value out of a decl.  */
@@ -1425,7 +1439,7 @@ debug_dv (decl_or_value dv)
     debug_generic_stmt (dv_as_decl (dv));
 }
 
-static void loc_exp_dep_clear (variable var);
+static void loc_exp_dep_clear (variable *var);
 
 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
 
@@ -1433,7 +1447,7 @@ static void
 variable_htab_free (void *elem)
 {
   int i;
-  variable var = (variable) elem;
+  variable *var = (variable *) elem;
   location_chain *node, *next;
 
   gcc_checking_assert (var->refcount > 0);
@@ -1468,7 +1482,7 @@ variable_htab_free (void *elem)
 /* Initialize the set (array) SET of attrs to empty lists.  */
 
 static void
-init_attrs_list_set (attrs *set)
+init_attrs_list_set (attrs **set)
 {
   int i;
 
@@ -1479,9 +1493,9 @@ init_attrs_list_set (attrs *set)
 /* Make the list *LISTP empty.  */
 
 static void
-attrs_list_clear (attrs *listp)
+attrs_list_clear (attrs **listp)
 {
-  attrs list, next;
+  attrs *list, *next;
 
   for (list = *listp; list; list = next)
     {
@@ -1493,8 +1507,8 @@ attrs_list_clear (attrs *listp)
 
 /* Return true if the pair of DECL and OFFSET is the member of the LIST.  */
 
-static attrs
-attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
+static attrs *
+attrs_list_member (attrs *list, decl_or_value dv, HOST_WIDE_INT offset)
 {
   for (; list; list = list->next)
     if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
@@ -1505,10 +1519,10 @@ attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
 
 static void
-attrs_list_insert (attrs *listp, decl_or_value dv,
+attrs_list_insert (attrs **listp, decl_or_value dv,
                   HOST_WIDE_INT offset, rtx loc)
 {
-  attrs list = new attrs_def;
+  attrs *list = new attrs;
   list->loc = loc;
   list->dv = dv;
   list->offset = offset;
@@ -1519,12 +1533,12 @@ attrs_list_insert (attrs *listp, decl_or_value dv,
 /* Copy all nodes from SRC and create a list *DSTP of the copies.  */
 
 static void
-attrs_list_copy (attrs *dstp, attrs src)
+attrs_list_copy (attrs **dstp, attrs *src)
 {
   attrs_list_clear (dstp);
   for (; src; src = src->next)
     {
-      attrs n = new attrs_def;
+      attrs *n = new attrs;
       n->loc = src->loc;
       n->dv = src->dv;
       n->offset = src->offset;
@@ -1536,7 +1550,7 @@ attrs_list_copy (attrs *dstp, attrs src)
 /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
 
 static void
-attrs_list_union (attrs *dstp, attrs src)
+attrs_list_union (attrs **dstp, attrs *src)
 {
   for (; src; src = src->next)
     {
@@ -1549,7 +1563,7 @@ attrs_list_union (attrs *dstp, attrs src)
    *DSTP.  */
 
 static void
-attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
+attrs_list_mpdv_union (attrs **dstp, attrs *src, attrs *src2)
 {
   gcc_assert (!*dstp);
   for (; src; src = src->next)
@@ -1586,7 +1600,7 @@ shared_hash_htab (shared_hash *vars)
 /* Return true if VAR is shared, or maybe because VARS is shared.  */
 
 static inline bool
-shared_var_p (variable var, shared_hash *vars)
+shared_var_p (variable *var, shared_hash *vars)
 {
   /* Don't count an entry in the changed_variables table as a duplicate.  */
   return ((var->refcount > 1 + (int) var->in_changed_variables)
@@ -1633,7 +1647,7 @@ shared_hash_destroy (shared_hash *vars)
 /* Unshare *PVARS if shared and return slot for DV.  If INS is
    INSERT, insert it if not already present.  */
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
                                 hashval_t dvhash, enum insert_option ins)
 {
@@ -1642,7 +1656,7 @@ shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
   return shared_hash_htab (*pvars)->find_slot_with_hash (dv, dvhash, ins);
 }
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
                               enum insert_option ins)
 {
@@ -1653,7 +1667,7 @@ shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
    If it is not present, insert it only VARS is not shared, otherwise
    return NULL.  */
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
 {
   return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash,
@@ -1661,7 +1675,7 @@ shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
                                                       ? NO_INSERT : INSERT);
 }
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
@@ -1669,14 +1683,14 @@ shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
 
 /* Return slot for DV only if it is already present in the hash table.  */
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot_noinsert_1 (shared_hash *vars, decl_or_value dv,
                                  hashval_t dvhash)
 {
   return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash, NO_INSERT);
 }
 
-static inline variable_def **
+static inline variable **
 shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
@@ -1685,13 +1699,13 @@ shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
 /* Return variable for DV or NULL if not already present in the hash
    table.  */
 
-static inline variable
+static inline variable *
 shared_hash_find_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
 {
   return shared_hash_htab (vars)->find_with_hash (dv, dvhash);
 }
 
-static inline variable
+static inline variable *
 shared_hash_find (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
@@ -1717,11 +1731,11 @@ static bool dst_can_be_shared;
 
 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
 
-static variable_def **
-unshare_variable (dataflow_set *set, variable_def **slot, variable var,
+static variable **
+unshare_variable (dataflow_set *set, variable **slot, variable *var,
                  enum var_init_status initialized)
 {
-  variable new_var;
+  variable *new_var;
   int i;
 
   new_var = onepart_pool_allocate (var->onepart);
@@ -1784,7 +1798,7 @@ unshare_variable (dataflow_set *set, variable_def **slot, variable var,
   *slot = new_var;
   if (var->in_changed_variables)
     {
-      variable_def **cslot
+      variable **cslot
        = changed_variables->find_slot_with_hash (var->dv,
                                                  dv_htab_hash (var->dv),
                                                  NO_INSERT);
@@ -1803,11 +1817,11 @@ static void
 vars_copy (variable_table_type *dst, variable_table_type *src)
 {
   variable_iterator_type hi;
-  variable var;
+  variable *var;
 
   FOR_EACH_HASH_TABLE_ELEMENT (*src, var, variable, hi)
     {
-      variable_def **dstp;
+      variable **dstp;
       var->refcount++;
       dstp = dst->find_slot_with_hash (var->dv, dv_htab_hash (var->dv),
                                       INSERT);
@@ -1820,8 +1834,7 @@ vars_copy (variable_table_type *dst, variable_table_type *src)
 static inline tree
 var_debug_decl (tree decl)
 {
-  if (decl && TREE_CODE (decl) == VAR_DECL
-      && DECL_HAS_DEBUG_EXPR_P (decl))
+  if (decl && VAR_P (decl) && DECL_HAS_DEBUG_EXPR_P (decl))
     {
       tree debugdecl = DECL_DEBUG_EXPR (decl);
       if (DECL_P (debugdecl))
@@ -1838,7 +1851,7 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
                  decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
                  enum insert_option iopt)
 {
-  attrs node;
+  attrs *node;
   bool decl_p = dv_is_decl_p (dv);
 
   if (decl_p)
@@ -1853,6 +1866,32 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
 }
 
+/* Return true if we should track a location that is OFFSET bytes from
+   a variable.  Store the constant offset in *OFFSET_OUT if so.  */
+
+static bool
+track_offset_p (poly_int64 offset, HOST_WIDE_INT *offset_out)
+{
+  HOST_WIDE_INT const_offset;
+  if (!offset.is_constant (&const_offset)
+      || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1))
+    return false;
+  *offset_out = const_offset;
+  return true;
+}
+
+/* Return the offset of a register that track_offset_p says we
+   should track.  */
+
+static HOST_WIDE_INT
+get_tracked_reg_offset (rtx loc)
+{
+  HOST_WIDE_INT offset;
+  if (!track_offset_p (REG_OFFSET (loc), &offset))
+    gcc_unreachable ();
+  return offset;
+}
+
 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
 
 static void
@@ -1860,7 +1899,7 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
             rtx set_src)
 {
   tree decl = REG_EXPR (loc);
-  HOST_WIDE_INT offset = REG_OFFSET (loc);
+  HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
 
   var_reg_decl_set (set, loc, initialized,
                    dv_from_decl (decl), offset, set_src, INSERT);
@@ -1869,7 +1908,7 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
 static enum var_init_status
 get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
 {
-  variable var;
+  variable *var;
   int i;
   enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
 
@@ -1906,9 +1945,9 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
                        enum var_init_status initialized, rtx set_src)
 {
   tree decl = REG_EXPR (loc);
-  HOST_WIDE_INT offset = REG_OFFSET (loc);
-  attrs node, next;
-  attrs *nextp;
+  HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
+  attrs *node, *next;
+  attrs **nextp;
 
   decl = var_debug_decl (decl);
 
@@ -1944,13 +1983,13 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
 static void
 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
 {
-  attrs *nextp = &set->regs[REGNO (loc)];
-  attrs node, next;
+  attrs **nextp = &set->regs[REGNO (loc)];
+  attrs *node, *next;
 
-  if (clobber)
+  HOST_WIDE_INT offset;
+  if (clobber && track_offset_p (REG_OFFSET (loc), &offset))
     {
       tree decl = REG_EXPR (loc);
-      HOST_WIDE_INT offset = REG_OFFSET (loc);
 
       decl = var_debug_decl (decl);
 
@@ -1976,8 +2015,8 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
 static void
 var_regno_delete (dataflow_set *set, int regno)
 {
-  attrs *reg = &set->regs[regno];
-  attrs node, next;
+  attrs **reg = &set->regs[regno];
+  attrs *node, *next;
 
   for (node = *reg; node; node = next)
     {
@@ -1993,7 +2032,7 @@ static bool
 negative_power_of_two_p (HOST_WIDE_INT i)
 {
   unsigned HOST_WIDE_INT x = -(unsigned HOST_WIDE_INT)i;
-  return x == (x & -x);
+  return pow2_or_zerop (x);
 }
 
 /* Strip constant offsets and alignments off of LOC.  Return the base
@@ -2067,7 +2106,7 @@ get_addr_from_local_cache (dataflow_set *set, rtx const loc)
 {
   rtx x;
   decl_or_value dv;
-  variable var;
+  variable *var;
   location_chain *l;
 
   gcc_checking_assert (GET_CODE (loc) == VALUE);
@@ -2137,7 +2176,7 @@ get_addr_from_local_cache (dataflow_set *set, rtx const loc)
 static rtx
 vt_canonicalize_addr (dataflow_set *set, rtx oloc)
 {
-  HOST_WIDE_INT ofst = 0;
+  poly_int64 ofst = 0, term;
   machine_mode mode = GET_MODE (oloc);
   rtx loc = oloc;
   rtx x;
@@ -2146,9 +2185,9 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc)
   while (retry)
     {
       while (GET_CODE (loc) == PLUS
-            && GET_CODE (XEXP (loc, 1)) == CONST_INT)
+            && poly_int_rtx_p (XEXP (loc, 1), &term))
        {
-         ofst += INTVAL (XEXP (loc, 1));
+         ofst += term;
          loc = XEXP (loc, 0);
        }
 
@@ -2173,10 +2212,11 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc)
            loc = get_addr_from_global_cache (loc);
 
          /* Consolidate plus_constants.  */
-         while (ofst && GET_CODE (loc) == PLUS
-                && GET_CODE (XEXP (loc, 1)) == CONST_INT)
+         while (maybe_ne (ofst, 0)
+                && GET_CODE (loc) == PLUS
+                && poly_int_rtx_p (XEXP (loc, 1), &term))
            {
-             ofst += INTVAL (XEXP (loc, 1));
+             ofst += term;
              loc = XEXP (loc, 0);
            }
 
@@ -2192,12 +2232,10 @@ vt_canonicalize_addr (dataflow_set *set, rtx oloc)
     }
 
   /* Add OFST back in.  */
-  if (ofst)
+  if (maybe_ne (ofst, 0))
     {
       /* Don't build new RTL if we can help it.  */
-      if (GET_CODE (oloc) == PLUS
-         && XEXP (oloc, 0) == loc
-         && INTVAL (XEXP (oloc, 1)) == ofst)
+      if (strip_offset (oloc, &term) == loc && known_eq (term, ofst))
        return oloc;
 
       loc = plus_constant (mode, loc, ofst);
@@ -2232,18 +2270,18 @@ struct overlapping_mems
 };
 
 /* Remove all MEMs that overlap with COMS->LOC from the location list
-   of a hash table entry for a value.  COMS->ADDR must be a
+   of a hash table entry for a onepart variable.  COMS->ADDR must be a
    canonicalized form of COMS->LOC's address, and COMS->LOC must be
    canonicalized itself.  */
 
 int
-drop_overlapping_mem_locs (variable_def **slot, overlapping_mems *coms)
+drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
 {
   dataflow_set *set = coms->set;
   rtx mloc = coms->loc, addr = coms->addr;
-  variable var = *slot;
+  variable *var = *slot;
 
-  if (var->onepart == ONEPART_VALUE)
+  if (var->onepart != NOT_ONEPART)
     {
       location_chain *loc, **locp;
       bool changed = false;
@@ -2346,7 +2384,7 @@ var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
             rtx set_src)
 {
   tree decl = MEM_EXPR (loc);
-  HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
+  HOST_WIDE_INT offset = int_mem_offset (loc);
 
   var_mem_decl_set (set, loc, initialized,
                    dv_from_decl (decl), offset, set_src, INSERT);
@@ -2364,7 +2402,7 @@ var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
                        enum var_init_status initialized, rtx set_src)
 {
   tree decl = MEM_EXPR (loc);
-  HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
+  HOST_WIDE_INT offset = int_mem_offset (loc);
 
   clobber_overlapping_mems (set, loc);
   decl = var_debug_decl (decl);
@@ -2385,7 +2423,7 @@ static void
 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
 {
   tree decl = MEM_EXPR (loc);
-  HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
+  HOST_WIDE_INT offset = int_mem_offset (loc);
 
   clobber_overlapping_mems (set, loc);
   decl = var_debug_decl (decl);
@@ -2512,7 +2550,7 @@ local_get_addr_clear_given_value (rtx const &, rtx *slot, rtx x)
 static void
 val_reset (dataflow_set *set, decl_or_value dv)
 {
-  variable var = shared_hash_find (set->vars, dv) ;
+  variable *var = shared_hash_find (set->vars, dv) ;
   location_chain *node;
   rtx cval;
 
@@ -2565,7 +2603,7 @@ val_reset (dataflow_set *set, decl_or_value dv)
     {
       decl_or_value cdv = dv_from_value (cval);
 
-      /* Keep the remaining values connected, accummulating links
+      /* Keep the remaining values connected, accumulating links
         in the canonical value.  */
       for (node = var->var_part[0].loc_chain; node; node = node->next)
        {
@@ -2618,7 +2656,7 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn)
 
   if (REG_P (loc))
     {
-      attrs node, found = NULL;
+      attrs *node, *found = NULL;
 
       for (node = set->regs[REGNO (loc)]; node; node = node->next)
        if (dv_is_value_p (node->dv)
@@ -2734,10 +2772,10 @@ variable_union_info_cmp_pos (const void *n1, const void *n2)
    we keep the newest locations in the beginning.  */
 
 static int
-variable_union (variable src, dataflow_set *set)
+variable_union (variable *src, dataflow_set *set)
 {
-  variable dst;
-  variable_def **dstp;
+  variable *dst;
+  variable **dstp;
   int i, j, k;
 
   dstp = shared_hash_find_slot (set->vars, src->dv);
@@ -2886,7 +2924,7 @@ variable_union (variable src, dataflow_set *set)
                {
                  dstp = unshare_variable (set, dstp, dst,
                                           VAR_INIT_STATUS_UNKNOWN);
-                 dst = (variable)*dstp;
+                 dst = (variable *)*dstp;
                }
            }
 
@@ -3118,7 +3156,7 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
   else
     {
       variable_iterator_type hi;
-      variable var;
+      variable *var;
 
       FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (src->vars),
                                   var, variable, hi)
@@ -3160,7 +3198,7 @@ set_dv_changed (decl_or_value dv, bool newv)
     case ONEPART_DEXPR:
       if (newv)
        NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv))) = false;
-      /* Fall through...  */
+      /* Fall through.  */
 
     default:
       DECL_CHANGED (dv_as_decl (dv)) = newv;
@@ -3184,7 +3222,7 @@ dv_changed_p (decl_or_value dv)
    be in star-canonical form.  */
 
 static location_chain *
-find_loc_in_1pdv (rtx loc, variable var, variable_table_type *vars)
+find_loc_in_1pdv (rtx loc, variable *var, variable_table_type *vars)
 {
   location_chain *node;
   enum rtx_code loc_code;
@@ -3203,7 +3241,7 @@ find_loc_in_1pdv (rtx loc, variable var, variable_table_type *vars)
   for (node = var->var_part[0].loc_chain; node; node = node->next)
     {
       decl_or_value dv;
-      variable rvar;
+      variable *rvar;
 
       if (GET_CODE (node->loc) != loc_code)
        {
@@ -3298,7 +3336,7 @@ insert_into_intersection (location_chain **nodep, rtx loc,
 
 static void
 intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
-                     location_chain *s1node, variable s2var)
+                     location_chain *s1node, variable *s2var)
 {
   dataflow_set *s1set = dsm->cur;
   dataflow_set *s2set = dsm->src;
@@ -3343,7 +3381,7 @@ intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
          && !VALUE_RECURSED_INTO (s1node->loc))
        {
          decl_or_value dv = dv_from_value (s1node->loc);
-         variable svar = shared_hash_find (s1set->vars, dv);
+         variable *svar = shared_hash_find (s1set->vars, dv);
          if (svar)
            {
              if (svar->n_var_parts == 1)
@@ -3500,6 +3538,12 @@ loc_cmp (rtx x, rtx y)
        else
          return 1;
 
+      case 'p':
+       r = compare_sizes_for_sort (SUBREG_BYTE (x), SUBREG_BYTE (y));
+       if (r != 0)
+         return r;
+       break;
+
       case 'V':
       case 'E':
        /* Compare the vector length first.  */
@@ -3571,14 +3615,13 @@ loc_cmp (rtx x, rtx y)
   return 0;
 }
 
-#if ENABLE_CHECKING
 /* Check the order of entries in one-part variables.   */
 
 int
-canonicalize_loc_order_check (variable_def **slot,
+canonicalize_loc_order_check (variable **slot,
                              dataflow_set *data ATTRIBUTE_UNUSED)
 {
-  variable var = *slot;
+  variable *var = *slot;
   location_chain *node, *next;
 
 #ifdef ENABLE_RTL_CHECKING
@@ -3603,7 +3646,6 @@ canonicalize_loc_order_check (variable_def **slot,
 
   return 1;
 }
-#endif
 
 /* Mark with VALUE_RECURSED_INTO values that have neighbors that are
    more likely to be chosen as canonical for an equivalence set.
@@ -3611,9 +3653,9 @@ canonicalize_loc_order_check (variable_def **slot,
    the connections bidirectional.  */
 
 int
-canonicalize_values_mark (variable_def **slot, dataflow_set *set)
+canonicalize_values_mark (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
   rtx val;
   location_chain *node;
@@ -3633,7 +3675,7 @@ canonicalize_values_mark (variable_def **slot, dataflow_set *set)
        else
          {
            decl_or_value odv = dv_from_value (node->loc);
-           variable_def **oslot;
+           variable **oslot;
            oslot = shared_hash_find_slot_noinsert (set->vars, odv);
 
            set_slot_part (set, val, oslot, odv, 0,
@@ -3650,14 +3692,14 @@ canonicalize_values_mark (variable_def **slot, dataflow_set *set)
    variables, canonicalizing equivalence sets into star shapes.  */
 
 int
-canonicalize_values_star (variable_def **slot, dataflow_set *set)
+canonicalize_values_star (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
   location_chain *node;
   decl_or_value cdv;
   rtx val, cval;
-  variable_def **cslot;
+  variable **cslot;
   bool has_value;
   bool has_marks;
 
@@ -3774,7 +3816,7 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
          }
        else if (GET_CODE (node->loc) == REG)
          {
-           attrs list = set->regs[REGNO (node->loc)], *listp;
+           attrs *list = set->regs[REGNO (node->loc)], **listp;
 
            /* Change an existing attribute referring to dv so that it
               refers to cdv, removing any duplicate this might
@@ -3832,17 +3874,16 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
            else
              gcc_unreachable ();
 
-#if ENABLE_CHECKING
-           while (list)
-             {
-               if (list->offset == 0
-                   && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
-                       || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
-                 gcc_unreachable ();
+           if (flag_checking)
+             while (list)
+               {
+                 if (list->offset == 0
+                     && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
+                         || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
+                   gcc_unreachable ();
 
-               list = list->next;
-             }
-#endif
+                 list = list->next;
+               }
          }
       }
 
@@ -3871,15 +3912,15 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
    get to a variable that references another member of the set.  */
 
 int
-canonicalize_vars_star (variable_def **slot, dataflow_set *set)
+canonicalize_vars_star (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
   location_chain *node;
   rtx cval;
   decl_or_value cdv;
-  variable_def **cslot;
-  variable cvar;
+  variable **cslot;
+  variable *cvar;
   location_chain *cnode;
 
   if (!var->onepart || var->onepart == ONEPART_VALUE)
@@ -3929,13 +3970,13 @@ canonicalize_vars_star (variable_def **slot, dataflow_set *set)
    intersection.  */
 
 static int
-variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
+variable_merge_over_cur (variable *s1var, struct dfset_merge *dsm)
 {
   dataflow_set *dst = dsm->dst;
-  variable_def **dstslot;
-  variable s2var, dvar = NULL;
+  variable **dstslot;
+  variable *s2var, *dvar = NULL;
   decl_or_value dv = s1var->dv;
-  onepart_enum_t onepart = s1var->onepart;
+  onepart_enum onepart = s1var->onepart;
   rtx val;
   hashval_t dvhash;
   location_chain *node, **nodep;
@@ -4033,7 +4074,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
 
       if (GET_CODE (node->loc) == REG)
        {
-         attrs list;
+         attrs *list;
 
          for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
            if (GET_MODE (node->loc) == GET_MODE (list->loc)
@@ -4129,7 +4170,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
              if (GET_CODE (node->loc) == VALUE)
                {
                  decl_or_value dv = dv_from_value (node->loc);
-                 variable_def **slot = NULL;
+                 variable **slot = NULL;
 
                  if (shared_hash_shared (dst->vars))
                    slot = shared_hash_find_slot_noinsert (dst->vars, dv);
@@ -4138,7 +4179,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
                                                          INSERT);
                  if (!*slot)
                    {
-                     variable var = onepart_pool_allocate (ONEPART_VALUE);
+                     variable *var = onepart_pool_allocate (ONEPART_VALUE);
                      var->dv = dv;
                      var->refcount = 1;
                      var->n_var_parts = 1;
@@ -4189,14 +4230,14 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
    variable_merge_over_cur().  */
 
 static int
-variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
+variable_merge_over_src (variable *s2var, struct dfset_merge *dsm)
 {
   dataflow_set *dst = dsm->dst;
   decl_or_value dv = s2var->dv;
 
   if (!s2var->onepart)
     {
-      variable_def **dstp = shared_hash_find_slot (dst->vars, dv);
+      variable **dstp = shared_hash_find_slot (dst->vars, dv);
       *dstp = s2var;
       s2var->refcount++;
       return 1;
@@ -4218,7 +4259,7 @@ dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
   int i;
   size_t src1_elems, src2_elems;
   variable_iterator_type hi;
-  variable var;
+  variable *var;
 
   src1_elems = shared_hash_htab (src1->vars)->elements ();
   src2_elems = shared_hash_htab (src2->vars)->elements ();
@@ -4256,7 +4297,7 @@ static void
 dataflow_set_equiv_regs (dataflow_set *set)
 {
   int i;
-  attrs list, *listp;
+  attrs *list, **listp;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -4311,7 +4352,7 @@ dataflow_set_equiv_regs (dataflow_set *set)
        if (list->offset == 0 && dv_onepart_p (list->dv))
          {
            rtx cval = canon[(int)GET_MODE (list->loc)];
-           variable_def **slot;
+           variable **slot;
 
            if (!cval)
              continue;
@@ -4335,7 +4376,7 @@ dataflow_set_equiv_regs (dataflow_set *set)
    be unshared and 1-part.  */
 
 static void
-remove_duplicate_values (variable var)
+remove_duplicate_values (variable *var)
 {
   location_chain *node, **nodep;
 
@@ -4383,10 +4424,10 @@ struct dfset_post_merge
    variables that don't have value numbers for them.  */
 
 int
-variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
+variable_post_merge_new_vals (variable **slot, dfset_post_merge *dfpm)
 {
   dataflow_set *set = dfpm->set;
-  variable var = *slot;
+  variable *var = *slot;
   location_chain *node;
 
   if (!var->onepart || !var->n_var_parts)
@@ -4405,7 +4446,7 @@ variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
            gcc_assert (!VALUE_RECURSED_INTO (node->loc));
          else if (GET_CODE (node->loc) == REG)
            {
-             attrs att, *attp, *curp = NULL;
+             attrs *att, **attp, **curp = NULL;
 
              if (var->refcount != 1)
                {
@@ -4519,13 +4560,13 @@ variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
    chosen expression.  */
 
 int
-variable_post_merge_perm_vals (variable_def **pslot, dfset_post_merge *dfpm)
+variable_post_merge_perm_vals (variable **pslot, dfset_post_merge *dfpm)
 {
   dataflow_set *set = dfpm->set;
-  variable pvar = *pslot, var;
+  variable *pvar = *pslot, *var;
   location_chain *pnode;
   decl_or_value dv;
-  attrs att;
+  attrs *att;
 
   gcc_assert (dv_is_value_p (pvar->dv)
              && pvar->n_var_parts == 1);
@@ -4606,7 +4647,7 @@ find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
 {
   location_chain *node;
   decl_or_value dv;
-  variable var;
+  variable *var;
   location_chain *where = NULL;
 
   if (!val)
@@ -4631,7 +4672,7 @@ find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
   for (node = var->var_part[0].loc_chain; node; node = node->next)
     if (MEM_P (node->loc)
        && MEM_EXPR (node->loc) == expr
-       && INT_MEM_OFFSET (node->loc) == 0)
+       && int_mem_offset (node->loc) == 0)
       {
        where = node;
        break;
@@ -4674,9 +4715,9 @@ mem_dies_at_call (rtx mem)
    the variable itself, directly or within a VALUE.  */
 
 int
-dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
     {
@@ -4693,11 +4734,11 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
        {
          for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
            {
-             /* We want to remove dying MEMs that doesn't refer to DECL.  */
+             /* We want to remove dying MEMs that don't refer to DECL.  */
              if (GET_CODE (loc->loc) == MEM
                  && (MEM_EXPR (loc->loc) != decl
-                     || INT_MEM_OFFSET (loc->loc) != 0)
-                 && !mem_dies_at_call (loc->loc))
+                     || int_mem_offset (loc->loc) != 0)
+                 && mem_dies_at_call (loc->loc))
                break;
              /* We want to move here MEMs that do refer to DECL.  */
              else if (GET_CODE (loc->loc) == VALUE
@@ -4740,7 +4781,7 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
 
          if (GET_CODE (loc->loc) != MEM
              || (MEM_EXPR (loc->loc) == decl
-                 && INT_MEM_OFFSET (loc->loc) == 0)
+                 && int_mem_offset (loc->loc) == 0)
              || !mem_dies_at_call (loc->loc))
            {
              if (old_loc != loc->loc && emit_notes)
@@ -4780,14 +4821,14 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
 }
 
 /* Remove all MEMs from the location list of a hash table entry for a
-   value.  */
+   onepart variable.  */
 
 int
-dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
-  if (var->onepart == ONEPART_VALUE)
+  if (var->onepart != NOT_ONEPART)
     {
       location_chain *loc, **locp;
       bool changed = false;
@@ -4859,15 +4900,14 @@ dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
 {
   unsigned int r;
   hard_reg_set_iterator hrsi;
-  HARD_REG_SET invalidated_regs;
 
-  get_call_reg_set_usage (call_insn, &invalidated_regs,
-                         regs_invalidated_by_call);
+  HARD_REG_SET callee_clobbers
+    = insn_callee_abi (call_insn).full_reg_clobbers ();
 
-  EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi)
+  EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, r, hrsi)
     var_regno_delete (set, r);
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     {
       set->traversed_vars = set->vars;
       shared_hash_htab (set->vars)
@@ -4906,7 +4946,7 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2)
    They must be in canonical order.  */
 
 static bool
-onepart_variable_different_p (variable var1, variable var2)
+onepart_variable_different_p (variable *var1, variable *var2)
 {
   location_chain *lc1, *lc2;
 
@@ -4932,10 +4972,67 @@ onepart_variable_different_p (variable var1, variable var2)
   return lc1 != lc2;
 }
 
+/* Return true if one-part variables VAR1 and VAR2 are different.
+   They must be in canonical order.  */
+
+static void
+dump_onepart_variable_differences (variable *var1, variable *var2)
+{
+  location_chain *lc1, *lc2;
+
+  gcc_assert (var1 != var2);
+  gcc_assert (dump_file);
+  gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
+  gcc_assert (var1->n_var_parts == 1
+             && var2->n_var_parts == 1);
+
+  lc1 = var1->var_part[0].loc_chain;
+  lc2 = var2->var_part[0].loc_chain;
+
+  gcc_assert (lc1 && lc2);
+
+  while (lc1 && lc2)
+    {
+      switch (loc_cmp (lc1->loc, lc2->loc))
+       {
+       case -1:
+         fprintf (dump_file, "removed: ");
+         print_rtl_single (dump_file, lc1->loc);
+         lc1 = lc1->next;
+         continue;
+       case 0:
+         break;
+       case 1:
+         fprintf (dump_file, "added: ");
+         print_rtl_single (dump_file, lc2->loc);
+         lc2 = lc2->next;
+         continue;
+       default:
+         gcc_unreachable ();
+       }
+      lc1 = lc1->next;
+      lc2 = lc2->next;
+    }
+
+  while (lc1)
+    {
+      fprintf (dump_file, "removed: ");
+      print_rtl_single (dump_file, lc1->loc);
+      lc1 = lc1->next;
+    }
+
+  while (lc2)
+    {
+      fprintf (dump_file, "added: ");
+      print_rtl_single (dump_file, lc2->loc);
+      lc2 = lc2->next;
+    }
+}
+
 /* Return true if variables VAR1 and VAR2 are different.  */
 
 static bool
-variable_different_p (variable var1, variable var2)
+variable_different_p (variable *var1, variable *var2)
 {
   int i;
 
@@ -4974,20 +5071,33 @@ static bool
 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
 {
   variable_iterator_type hi;
-  variable var1;
+  variable *var1;
+  bool diffound = false;
+  bool details = (dump_file && (dump_flags & TDF_DETAILS));
+
+#define RETRUE                                 \
+  do                                           \
+    {                                          \
+      if (!details)                            \
+       return true;                            \
+      else                                     \
+       diffound = true;                        \
+    }                                          \
+  while (0)
 
   if (old_set->vars == new_set->vars)
     return false;
 
   if (shared_hash_htab (old_set->vars)->elements ()
       != shared_hash_htab (new_set->vars)->elements ())
-    return true;
+    RETRUE;
 
   FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (old_set->vars),
                               var1, variable, hi)
     {
       variable_table_type *htab = shared_hash_htab (new_set->vars);
-      variable var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+      variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+
       if (!var2)
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4995,26 +5105,49 @@ dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
              fprintf (dump_file, "dataflow difference found: removal of:\n");
              dump_var (var1);
            }
-         return true;
+         RETRUE;
        }
-
-      if (variable_different_p (var1, var2))
+      else if (variable_different_p (var1, var2))
        {
-         if (dump_file && (dump_flags & TDF_DETAILS))
+         if (details)
            {
              fprintf (dump_file, "dataflow difference found: "
                       "old and new follow:\n");
              dump_var (var1);
+             if (dv_onepart_p (var1->dv))
+               dump_onepart_variable_differences (var1, var2);
              dump_var (var2);
            }
-         return true;
+         RETRUE;
        }
     }
 
-  /* No need to traverse the second hashtab, if both have the same number
-     of elements and the second one had all entries found in the first one,
-     then it can't have any extra entries.  */
-  return false;
+  /* There's no need to traverse the second hashtab unless we want to
+     print the details.  If both have the same number of elements and
+     the second one had all entries found in the first one, then the
+     second can't have any extra entries.  */
+  if (!details)
+    return diffound;
+
+  FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (new_set->vars),
+                              var1, variable, hi)
+    {
+      variable_table_type *htab = shared_hash_htab (old_set->vars);
+      variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+      if (!var2)
+       {
+         if (details)
+           {
+             fprintf (dump_file, "dataflow difference found: addition of:\n");
+             dump_var (var1);
+           }
+         RETRUE;
+       }
+    }
+
+#undef RETRUE
+
+  return diffound;
 }
 
 /* Free the contents of dataflow set SET.  */
@@ -5031,40 +5164,26 @@ dataflow_set_destroy (dataflow_set *set)
   set->vars = NULL;
 }
 
-/* Return true if RTL X contains a SYMBOL_REF.  */
+/* Return true if T is a tracked parameter with non-degenerate record type.  */
 
 static bool
-contains_symbol_ref (rtx x)
+tracked_record_parameter_p (tree t)
 {
-  const char *fmt;
-  RTX_CODE code;
-  int i;
+  if (TREE_CODE (t) != PARM_DECL)
+    return false;
 
-  if (!x)
+  if (DECL_MODE (t) == BLKmode)
     return false;
 
-  code = GET_CODE (x);
-  if (code == SYMBOL_REF)
-    return true;
+  tree type = TREE_TYPE (t);
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return false;
 
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (contains_symbol_ref (XEXP (x, i)))
-           return true;
-       }
-      else if (fmt[i] == 'E')
-       {
-         int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           if (contains_symbol_ref (XVECEXP (x, i, j)))
-             return true;
-       }
-    }
+  if (TYPE_FIELDS (type) == NULL_TREE
+      || DECL_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
+    return false;
 
-  return false;
+  return true;
 }
 
 /* Shall EXPR be tracked?  */
@@ -5079,7 +5198,7 @@ track_expr_p (tree expr, bool need_rtl)
     return DECL_RTL_SET_P (expr);
 
   /* If EXPR is not a parameter or a variable do not track it.  */
-  if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
+  if (!VAR_P (expr) && TREE_CODE (expr) != PARM_DECL)
     return 0;
 
   /* It also must have a name...  */
@@ -5095,7 +5214,7 @@ track_expr_p (tree expr, bool need_rtl)
      don't need to track this expression if the ultimate declaration is
      ignored.  */
   realdecl = expr;
-  if (TREE_CODE (realdecl) == VAR_DECL && DECL_HAS_DEBUG_EXPR_P (realdecl))
+  if (VAR_P (realdecl) && DECL_HAS_DEBUG_EXPR_P (realdecl))
     {
       realdecl = DECL_DEBUG_EXPR (realdecl);
       if (!DECL_P (realdecl))
@@ -5104,21 +5223,20 @@ track_expr_p (tree expr, bool need_rtl)
              || (TREE_CODE (realdecl) == MEM_REF
                  && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
            {
-             HOST_WIDE_INT bitsize, bitpos, maxsize;
+             HOST_WIDE_INT bitsize, bitpos;
+             bool reverse;
              tree innerdecl
-               = get_ref_base_and_extent (realdecl, &bitpos, &bitsize,
-                                          &maxsize);
-             if (!DECL_P (innerdecl)
+               = get_ref_base_and_extent_hwi (realdecl, &bitpos,
+                                              &bitsize, &reverse);
+             if (!innerdecl
+                 || !DECL_P (innerdecl)
                  || DECL_IGNORED_P (innerdecl)
-                 /* Do not track declarations for parts of tracked parameters
-                    since we want to track them as a whole instead.  */
-                 || (TREE_CODE (innerdecl) == PARM_DECL
-                     && DECL_MODE (innerdecl) != BLKmode
-                     && TREE_CODE (TREE_TYPE (innerdecl)) != UNION_TYPE)
+                 /* Do not track declarations for parts of tracked record
+                    parameters since we want to track them as a whole.  */
+                 || tracked_record_parameter_p (innerdecl)
                  || TREE_STATIC (innerdecl)
-                 || bitsize <= 0
-                 || bitpos + bitsize > 256
-                 || bitsize != maxsize)
+                 || bitsize == 0
+                 || bitpos + bitsize > 256)
                return 0;
              else
                realdecl = expr;
@@ -5147,7 +5265,7 @@ track_expr_p (tree expr, bool need_rtl)
      char **_dl_argv;
   */
   if (decl_rtl && MEM_P (decl_rtl)
-      && contains_symbol_ref (XEXP (decl_rtl, 0)))
+      && contains_symbol_ref_p (XEXP (decl_rtl, 0)))
     return 0;
 
   /* If RTX is a memory it should not be very large (because it would be
@@ -5155,11 +5273,12 @@ track_expr_p (tree expr, bool need_rtl)
   if (decl_rtl && MEM_P (decl_rtl))
     {
       /* Do not track structures and arrays.  */
-      if (GET_MODE (decl_rtl) == BLKmode
-         || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
+      if ((GET_MODE (decl_rtl) == BLKmode
+          || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
+         && !tracked_record_parameter_p (realdecl))
        return 0;
       if (MEM_SIZE_KNOWN_P (decl_rtl)
-         && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS)
+         && maybe_gt (MEM_SIZE (decl_rtl), MAX_VAR_PARTS))
        return 0;
     }
 
@@ -5172,10 +5291,10 @@ track_expr_p (tree expr, bool need_rtl)
    EXPR+OFFSET.  */
 
 static bool
-same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
+same_variable_part_p (rtx loc, tree expr, poly_int64 offset)
 {
   tree expr2;
-  HOST_WIDE_INT offset2;
+  poly_int64 offset2;
 
   if (! DECL_P (expr))
     return false;
@@ -5188,7 +5307,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
   else if (MEM_P (loc))
     {
       expr2 = MEM_EXPR (loc);
-      offset2 = INT_MEM_OFFSET (loc);
+      offset2 = int_mem_offset (loc);
     }
   else
     return false;
@@ -5199,7 +5318,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
   expr = var_debug_decl (expr);
   expr2 = var_debug_decl (expr2);
 
-  return (expr == expr2 && offset == offset2);
+  return (expr == expr2 && known_eq (offset, offset2));
 }
 
 /* LOC is a REG or MEM that we would like to track if possible.
@@ -5213,7 +5332,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
    from EXPR in *OFFSET_OUT (if nonnull).  */
 
 static bool
-track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
+track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
             machine_mode *mode_out, HOST_WIDE_INT *offset_out)
 {
   machine_mode mode;
@@ -5229,7 +5348,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
       machine_mode pseudo_mode;
 
       pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
-      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
+      if (paradoxical_subreg_p (mode, pseudo_mode))
        {
          offset += byte_lowpart_offset (pseudo_mode, mode);
          mode = pseudo_mode;
@@ -5243,23 +5362,24 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
      because the real and imaginary parts are represented as separate
      pseudo registers, even if the whole complex value fits into one
      hard register.  */
-  if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
+  if ((paradoxical_subreg_p (mode, DECL_MODE (expr))
        || (store_reg_p
           && !COMPLEX_MODE_P (DECL_MODE (expr))
-          && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
-      && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
+          && hard_regno_nregs (REGNO (loc), DECL_MODE (expr)) == 1))
+      && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0))
     {
       mode = DECL_MODE (expr);
       offset = 0;
     }
 
-  if (offset < 0 || offset >= MAX_VAR_PARTS)
+  HOST_WIDE_INT const_offset;
+  if (!track_offset_p (offset, &const_offset))
     return false;
 
   if (mode_out)
     *mode_out = mode;
   if (offset_out)
-    *offset_out = offset;
+    *offset_out = const_offset;
   return true;
 }
 
@@ -5270,7 +5390,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
 static rtx
 var_lowpart (machine_mode mode, rtx loc)
 {
-  unsigned int offset, reg_offset, regno;
+  unsigned int regno;
 
   if (GET_MODE (loc) == mode)
     return loc;
@@ -5278,12 +5398,12 @@ var_lowpart (machine_mode mode, rtx loc)
   if (!REG_P (loc) && !MEM_P (loc))
     return NULL;
 
-  offset = byte_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc));
 
   if (MEM_P (loc))
     return adjust_address_nv (loc, mode, offset);
 
-  reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
                                             reg_offset, mode);
   return gen_rtx_REG_offset (loc, mode, regno, offset);
@@ -5456,13 +5576,13 @@ use_type (rtx loc, struct count_use_info *cui, machine_mode *modep)
        return MO_CLOBBER;
       else if (target_for_debug_bind (var_debug_decl (expr)))
        return MO_CLOBBER;
-      else if (track_loc_p (loc, expr, INT_MEM_OFFSET (loc),
+      else if (track_loc_p (loc, expr, int_mem_offset (loc),
                            false, modep, NULL)
               /* Multi-part variables shouldn't refer to one-part
                  variable names such as VALUEs (never happens) or
                  DEBUG_EXPRs (only happens in the presence of debug
                  insns).  */
-              && (!MAY_HAVE_DEBUG_INSNS
+              && (!MAY_HAVE_DEBUG_BIND_INSNS
                   || !rtx_debug_expr_p (XEXP (loc, 0))))
        return MO_USE;
       else
@@ -5723,7 +5843,7 @@ add_uses_1 (rtx *x, void *cui)
    compile time for ridiculously complex expressions, although they're
    seldom useful, and they may often have to be discarded as not
    representable anyway.  */
-#define EXPR_USE_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH))
+#define EXPR_USE_DEPTH (param_max_vartrack_expr_depth)
 
 /* Attempt to reverse the EXPR operation in the debug info and record
    it in the cselib table.  Say for reg1 = reg2 + 6 even when reg2 is
@@ -5783,7 +5903,7 @@ reverse_op (rtx val, const_rtx expr, rtx_insn *insn)
        && (GET_CODE (l->loc) != CONST || !references_value_p (l->loc, 0)))
       return;
     /* Avoid creating too large locs lists.  */
-    else if (count == PARAM_VALUE (PARAM_MAX_VARTRACK_REVERSE_OP_SIZE))
+    else if (count == param_max_vartrack_reverse_op_size)
       return;
 
   switch (GET_CODE (src))
@@ -5820,11 +5940,6 @@ reverse_op (rtx val, const_rtx expr, rtx_insn *insn)
            return;
        }
       ret = simplify_gen_binary (code, GET_MODE (val), val, arg);
-      if (ret == val)
-       /* Ensure ret isn't VALUE itself (which can happen e.g. for
-          (plus (reg1) (reg2)) when reg2 is known to be 0), as that
-          breaks a lot of routines during var-tracking.  */
-       ret = gen_rtx_fmt_ee (PLUS, GET_MODE (val), val, const0_rtx);
       break;
     default:
       gcc_unreachable ();
@@ -5865,7 +5980,9 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
          mo.type = MO_CLOBBER;
          mo.u.loc = loc;
          if (GET_CODE (expr) == SET
-             && SET_DEST (expr) == loc
+             && (SET_DEST (expr) == loc
+                 || (GET_CODE (SET_DEST (expr)) == STRICT_LOW_PART
+                     && XEXP (SET_DEST (expr), 0) == loc))
              && !unsuitable_loc (SET_SRC (expr))
              && find_use_val (loc, mode, cui))
            {
@@ -5956,7 +6073,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
              rtx xexpr = gen_rtx_SET (loc, src);
              if (same_variable_part_p (SET_SRC (xexpr),
                                        MEM_EXPR (loc),
-                                       INT_MEM_OFFSET (loc)))
+                                       int_mem_offset (loc)))
                mo.type = MO_COPY;
              else
                mo.type = MO_SET;
@@ -5979,18 +6096,11 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
   resolve = preserve = !cselib_preserved_value_p (v);
 
   /* We cannot track values for multiple-part variables, so we track only
-     locations for tracked parameters passed either by invisible reference
-     or directly in multiple locations.  */
+     locations for tracked record parameters.  */
   if (track_p
       && REG_P (loc)
       && REG_EXPR (loc)
-      && TREE_CODE (REG_EXPR (loc)) == PARM_DECL
-      && DECL_MODE (REG_EXPR (loc)) != BLKmode
-      && TREE_CODE (TREE_TYPE (REG_EXPR (loc))) != UNION_TYPE
-      && ((MEM_P (DECL_INCOMING_RTL (REG_EXPR (loc)))
-          && XEXP (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) != arg_pointer_rtx)
-          || (GET_CODE (DECL_INCOMING_RTL (REG_EXPR (loc))) == PARALLEL
-             && XVECLEN (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) > 1)))
+      && tracked_record_parameter_p (REG_EXPR (loc)))
     {
       /* Although we don't use the value here, it could be used later by the
         mere virtue of its existence as the operand of the reverse operation
@@ -6002,10 +6112,24 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
     }
 
   if (loc == stack_pointer_rtx
-      && hard_frame_pointer_adjustment != -1
+      && (maybe_ne (hard_frame_pointer_adjustment, -1)
+         || (!frame_pointer_needed && !ACCUMULATE_OUTGOING_ARGS))
       && preserve)
     cselib_set_value_sp_based (v);
 
+  /* Don't record MO_VAL_SET for VALUEs that can be described using
+     cfa_base_rtx or cfa_base_rtx + CONST_INT, cselib already knows
+     all the needed equivalences and they shouldn't change depending
+     on which register holds that VALUE in some instruction.  */
+  if (!frame_pointer_needed
+      && cfa_base_rtx
+      && cselib_sp_derived_value_p (v))
+    {
+      if (preserve)
+       preserve_value (v);
+      return;
+    }
+
   nloc = replace_expr_with_values (oloc);
   if (nloc)
     oloc = nloc;
@@ -6182,14 +6306,12 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
                  && targetm.calls.struct_value_rtx (type, 0) == 0)
                {
                  tree struct_addr = build_pointer_type (TREE_TYPE (type));
-                 machine_mode mode = TYPE_MODE (struct_addr);
+                 function_arg_info arg (struct_addr, /*named=*/true);
                  rtx reg;
                  INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
                                        nargs + 1);
-                 reg = targetm.calls.function_arg (args_so_far, mode,
-                                                   struct_addr, true);
-                 targetm.calls.function_arg_advance (args_so_far, mode,
-                                                     struct_addr, true);
+                 reg = targetm.calls.function_arg (args_so_far, arg);
+                 targetm.calls.function_arg_advance (args_so_far, arg);
                  if (reg == NULL_RTX)
                    {
                      for (; link; link = XEXP (link, 1))
@@ -6207,11 +6329,9 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
                                      nargs);
              if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
                {
-                 machine_mode mode;
                  t = TYPE_ARG_TYPES (type);
-                 mode = TYPE_MODE (TREE_VALUE (t));
-                 this_arg = targetm.calls.function_arg (args_so_far, mode,
-                                                        TREE_VALUE (t), true);
+                 function_arg_info arg (TREE_VALUE (t), /*named=*/true);
+                 this_arg = targetm.calls.function_arg (args_so_far, arg);
                  if (this_arg && !REG_P (this_arg))
                    this_arg = NULL_RTX;
                  else if (this_arg == NULL_RTX)
@@ -6247,18 +6367,19 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
        else if (REG_P (x))
          {
            cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
+           scalar_int_mode mode;
            if (val && cselib_preserved_value_p (val))
              item = val->val_rtx;
-           else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
-                    || GET_MODE_CLASS (GET_MODE (x)) == MODE_PARTIAL_INT)
+           else if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
              {
-               machine_mode mode = GET_MODE (x);
-
-               while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode
-                      && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
+               opt_scalar_int_mode mode_iter;
+               FOR_EACH_WIDER_MODE (mode_iter, mode)
                  {
-                   rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
+                   mode = mode_iter.require ();
+                   if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
+                     break;
 
+                   rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
                    if (reg == NULL_RTX || !REG_P (reg))
                      continue;
                    val = cselib_lookup (reg, mode, 0, VOIDmode);
@@ -6277,14 +6398,13 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
 
            if (!frame_pointer_needed)
              {
-               struct adjust_mem_data amd;
+               class adjust_mem_data amd;
                amd.mem_mode = VOIDmode;
                amd.stack_adjust = -VTI (bb)->out.stack_adjust;
-               amd.side_effects = NULL;
                amd.store = true;
                mem = simplify_replace_fn_rtx (mem, NULL_RTX, adjust_mems,
                                               &amd);
-               gcc_assert (amd.side_effects == NULL_RTX);
+               gcc_assert (amd.side_effects.is_empty ());
              }
            val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode);
            if (val && cselib_preserved_value_p (val))
@@ -6294,8 +6414,9 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
              {
                /* For non-integer stack argument see also if they weren't
                   initialized by integers.  */
-               machine_mode imode = int_mode_for_mode (GET_MODE (mem));
-               if (imode != GET_MODE (mem) && imode != BLKmode)
+               scalar_int_mode imode;
+               if (int_mode_for_mode (GET_MODE (mem)).exists (&imode)
+                   && imode != GET_MODE (mem))
                  {
                    val = cselib_lookup (adjust_address_nv (mem, imode, 0),
                                         imode, 0, VOIDmode);
@@ -6318,30 +6439,24 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
          }
        if (t && t != void_list_node)
          {
-           tree argtype = TREE_VALUE (t);
-           machine_mode mode = TYPE_MODE (argtype);
            rtx reg;
-           if (pass_by_reference (&args_so_far_v, mode, argtype, true))
-             {
-               argtype = build_pointer_type (argtype);
-               mode = TYPE_MODE (argtype);
-             }
-           reg = targetm.calls.function_arg (args_so_far, mode,
-                                             argtype, true);
-           if (TREE_CODE (argtype) == REFERENCE_TYPE
-               && INTEGRAL_TYPE_P (TREE_TYPE (argtype))
+           function_arg_info arg (TREE_VALUE (t), /*named=*/true);
+           apply_pass_by_reference_rules (&args_so_far_v, arg);
+           reg = targetm.calls.function_arg (args_so_far, arg);
+           if (TREE_CODE (arg.type) == REFERENCE_TYPE
+               && INTEGRAL_TYPE_P (TREE_TYPE (arg.type))
                && reg
                && REG_P (reg)
-               && GET_MODE (reg) == mode
-               && (GET_MODE_CLASS (mode) == MODE_INT
-                   || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+               && GET_MODE (reg) == arg.mode
+               && (GET_MODE_CLASS (arg.mode) == MODE_INT
+                   || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT)
                && REG_P (x)
                && REGNO (x) == REGNO (reg)
-               && GET_MODE (x) == mode
+               && GET_MODE (x) == arg.mode
                && item)
              {
                machine_mode indmode
-                 = TYPE_MODE (TREE_TYPE (argtype));
+                 = TYPE_MODE (TREE_TYPE (arg.type));
                rtx mem = gen_rtx_MEM (indmode, x);
                cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
                if (val && cselib_preserved_value_p (val))
@@ -6381,8 +6496,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
                        }
                  }
              }
-           targetm.calls.function_arg_advance (args_so_far, mode,
-                                               argtype, true);
+           targetm.calls.function_arg_advance (args_so_far, arg);
            t = TREE_CHAIN (t);
          }
       }
@@ -6531,7 +6645,7 @@ add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_sets)
      insert notes before it without worrying about any
      notes that MO_USEs might emit after the insn.  */
   cui.store_p = true;
-  note_stores (PATTERN (insn), add_stores, &cui);
+  note_stores (insn, add_stores, &cui);
   n2 = VTI (bb)->mos.length () - 1;
   mos = VTI (bb)->mos.address ();
 
@@ -6589,7 +6703,7 @@ find_src_set_src (dataflow_set *set, rtx src)
 {
   tree decl = NULL_TREE;   /* The variable being copied around.          */
   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
-  variable var;
+  variable *var;
   location_chain *nextp;
   int i;
   bool found;
@@ -6638,7 +6752,7 @@ compute_bb_dataflow (basic_block bb)
   dataflow_set_copy (&old_out, out);
   dataflow_set_copy (out, in);
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     local_get_addr_cache = new hash_map<rtx, rtx>;
 
   FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo)
@@ -6920,7 +7034,7 @@ compute_bb_dataflow (basic_block bb)
        }
     }
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     {
       delete local_get_addr_cache;
       local_get_addr_cache = NULL;
@@ -6930,10 +7044,9 @@ compute_bb_dataflow (basic_block bb)
        ->traverse <dataflow_set *, canonicalize_values_mark> (out);
       shared_hash_htab (out->vars)
        ->traverse <dataflow_set *, canonicalize_values_star> (out);
-#if ENABLE_CHECKING
-      shared_hash_htab (out->vars)
-       ->traverse <dataflow_set *, canonicalize_loc_order_check> (out);
-#endif
+      if (flag_checking)
+       shared_hash_htab (out->vars)
+         ->traverse <dataflow_set *, canonicalize_loc_order_check> (out);
     }
   changed = dataflow_set_different (&old_out, out);
   dataflow_set_destroy (&old_out);
@@ -6947,14 +7060,14 @@ vt_find_locations (void)
 {
   bb_heap_t *worklist = new bb_heap_t (LONG_MIN);
   bb_heap_t *pending = new bb_heap_t (LONG_MIN);
-  sbitmap visited, in_worklist, in_pending;
+  sbitmap in_worklist, in_pending;
   basic_block bb;
   edge e;
   int *bb_order;
   int *rc_order;
   int i;
   int htabsz = 0;
-  int htabmax = PARAM_VALUE (PARAM_MAX_VARTRACK_SIZE);
+  int htabmax = param_max_vartrack_size;
   bool success = true;
 
   timevar_push (TV_VAR_TRACKING_DATAFLOW);
@@ -6967,7 +7080,7 @@ vt_find_locations (void)
     bb_order[rc_order[i]] = i;
   free (rc_order);
 
-  visited = sbitmap_alloc (last_basic_block_for_fn (cfun));
+  auto_sbitmap visited (last_basic_block_for_fn (cfun));
   in_worklist = sbitmap_alloc (last_basic_block_for_fn (cfun));
   in_pending = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_clear (in_worklist);
@@ -7008,7 +7121,7 @@ vt_find_locations (void)
              else
                oldinsz = oldoutsz = 0;
 
-             if (MAY_HAVE_DEBUG_INSNS)
+             if (MAY_HAVE_DEBUG_BIND_INSNS)
                {
                  dataflow_set *in = &VTI (bb)->in, *first_out = NULL;
                  bool first = true, adjust = false;
@@ -7038,13 +7151,14 @@ vt_find_locations (void)
                  if (adjust)
                    {
                      dataflow_post_merge_adjust (in, &VTI (bb)->permp);
-#if ENABLE_CHECKING
-                     /* Merge and merge_adjust should keep entries in
-                        canonical order.  */
-                     shared_hash_htab (in->vars)
-                       ->traverse <dataflow_set *,
-                                   canonicalize_loc_order_check> (in);
-#endif
+
+                     if (flag_checking)
+                       /* Merge and merge_adjust should keep entries in
+                          canonical order.  */
+                       shared_hash_htab (in->vars)
+                         ->traverse <dataflow_set *,
+                                     canonicalize_loc_order_check> (in);
+
                      if (dst_can_be_shared)
                        {
                          shared_hash_destroy (in->vars);
@@ -7068,10 +7182,10 @@ vt_find_locations (void)
 
              if (htabmax && htabsz > htabmax)
                {
-                 if (MAY_HAVE_DEBUG_INSNS)
+                 if (MAY_HAVE_DEBUG_BIND_INSNS)
                    inform (DECL_SOURCE_LOCATION (cfun->decl),
                            "variable tracking size limit exceeded with "
-                           "-fvar-tracking-assignments, retrying without");
+                           "%<-fvar-tracking-assignments%>, retrying without");
                  else
                    inform (DECL_SOURCE_LOCATION (cfun->decl),
                            "variable tracking size limit exceeded");
@@ -7128,14 +7242,13 @@ vt_find_locations (void)
        }
     }
 
-  if (success && MAY_HAVE_DEBUG_INSNS)
+  if (success && MAY_HAVE_DEBUG_BIND_INSNS)
     FOR_EACH_BB_FN (bb, cfun)
       gcc_assert (VTI (bb)->flooded);
 
   free (bb_order);
   delete worklist;
   delete pending;
-  sbitmap_free (visited);
   sbitmap_free (in_worklist);
   sbitmap_free (in_pending);
 
@@ -7146,7 +7259,7 @@ vt_find_locations (void)
 /* Print the content of the LIST to dump file.  */
 
 static void
-dump_attrs_list (attrs list)
+dump_attrs_list (attrs *list)
 {
   for (; list; list = list->next)
     {
@@ -7162,9 +7275,9 @@ dump_attrs_list (attrs list)
 /* Print the information about variable *SLOT to dump file.  */
 
 int
-dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
+dump_var_tracking_slot (variable **slot, void *data ATTRIBUTE_UNUSED)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   dump_var (var);
 
@@ -7175,7 +7288,7 @@ dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
 /* Print the information about variable VAR to dump file.  */
 
 static void
-dump_var (variable var)
+dump_var (variable *var)
 {
   int i;
   location_chain *node;
@@ -7222,7 +7335,7 @@ dump_var (variable var)
 static void
 dump_vars (variable_table_type *vars)
 {
-  if (vars->elements () > 0)
+  if (!vars->is_empty ())
     {
       fprintf (dump_file, "Variables:\n");
       vars->traverse <void *, dump_var_tracking_slot> (NULL);
@@ -7270,12 +7383,12 @@ dump_dataflow_sets (void)
 /* Return the variable for DV in dropped_values, inserting one if
    requested with INSERT.  */
 
-static inline variable
+static inline variable *
 variable_from_dropped (decl_or_value dv, enum insert_option insert)
 {
-  variable_def **slot;
-  variable empty_var;
-  onepart_enum_t onepart;
+  variable **slot;
+  variable *empty_var;
+  onepart_enum onepart;
 
   slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv), insert);
 
@@ -7310,9 +7423,9 @@ variable_from_dropped (decl_or_value dv, enum insert_option insert)
 /* Recover the one-part aux from dropped_values.  */
 
 static struct onepart_aux *
-recover_dropped_1paux (variable var)
+recover_dropped_1paux (variable *var)
 {
-  variable dvar;
+  variable *dvar;
 
   gcc_checking_assert (var->onepart);
 
@@ -7337,13 +7450,13 @@ recover_dropped_1paux (variable var)
    if it has no locations delete it from SET's hash table.  */
 
 static void
-variable_was_changed (variable var, dataflow_set *set)
+variable_was_changed (variable *var, dataflow_set *set)
 {
   hashval_t hash = dv_htab_hash (var->dv);
 
   if (emit_notes)
     {
-      variable_def **slot;
+      variable **slot;
 
       /* Remember this decl or VALUE has been added to changed_variables.  */
       set_dv_changed (var->dv, true);
@@ -7352,7 +7465,7 @@ variable_was_changed (variable var, dataflow_set *set)
 
       if (*slot)
        {
-         variable old_var = *slot;
+         variable *old_var = *slot;
          gcc_assert (old_var->in_changed_variables);
          old_var->in_changed_variables = false;
          if (var != old_var && var->onepart)
@@ -7369,9 +7482,9 @@ variable_was_changed (variable var, dataflow_set *set)
 
       if (set && var->n_var_parts == 0)
        {
-         onepart_enum_t onepart = var->onepart;
-         variable empty_var = NULL;
-         variable_def **dslot = NULL;
+         onepart_enum onepart = var->onepart;
+         variable *empty_var = NULL;
+         variable **dslot = NULL;
 
          if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
            {
@@ -7433,7 +7546,7 @@ variable_was_changed (variable var, dataflow_set *set)
       gcc_assert (set);
       if (var->n_var_parts == 0)
        {
-         variable_def **slot;
+         variable **slot;
 
        drop_var:
          slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
@@ -7454,7 +7567,7 @@ variable_was_changed (variable var, dataflow_set *set)
    have, if it should be inserted.  */
 
 static inline int
-find_variable_location_part (variable var, HOST_WIDE_INT offset,
+find_variable_location_part (variable *var, HOST_WIDE_INT offset,
                             int *insertion_point)
 {
   int pos, low, high;
@@ -7492,16 +7605,16 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
   return -1;
 }
 
-static variable_def **
-set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+set_slot_part (dataflow_set *set, rtx loc, variable **slot,
               decl_or_value dv, HOST_WIDE_INT offset,
               enum var_init_status initialized, rtx set_src)
 {
   int pos;
   location_chain *node, *next;
   location_chain **nextp;
-  variable var;
-  onepart_enum_t onepart;
+  variable *var;
+  onepart_enum onepart;
 
   var = *slot;
 
@@ -7752,7 +7865,7 @@ set_variable_part (dataflow_set *set, rtx loc,
                   enum var_init_status initialized, rtx set_src,
                   enum insert_option iopt)
 {
-  variable_def **slot;
+  variable **slot;
 
   if (iopt == NO_INSERT)
     slot = shared_hash_find_slot_noinsert (set->vars, dv);
@@ -7770,11 +7883,11 @@ set_variable_part (dataflow_set *set, rtx loc,
    The variable part is specified by variable's declaration or value
    DV and offset OFFSET.  */
 
-static variable_def **
-clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+clobber_slot_part (dataflow_set *set, rtx loc, variable **slot,
                   HOST_WIDE_INT offset, rtx set_src)
 {
-  variable var = *slot;
+  variable *var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);
 
   if (pos >= 0)
@@ -7794,8 +7907,8 @@ clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
            {
              if (REG_P (node->loc))
                {
-                 attrs anode, anext;
-                 attrs *anextp;
+                 attrs *anode, *anext;
+                 attrs **anextp;
 
                  /* Remove the variable part from the register's
                     list, but preserve any other variable parts
@@ -7833,7 +7946,7 @@ static void
 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
                       HOST_WIDE_INT offset, rtx set_src)
 {
-  variable_def **slot;
+  variable **slot;
 
   if (!dv_as_opaque (dv)
       || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
@@ -7850,11 +7963,11 @@ clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
    variable part is specified by its SET->vars slot SLOT and offset
    OFFSET and the part's location by LOC.  */
 
-static variable_def **
-delete_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+delete_slot_part (dataflow_set *set, rtx loc, variable **slot,
                  HOST_WIDE_INT offset)
 {
-  variable var = *slot;
+  variable *var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);
 
   if (pos >= 0)
@@ -7941,7 +8054,7 @@ static void
 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
                      HOST_WIDE_INT offset)
 {
-  variable_def **slot = shared_hash_find_slot_noinsert (set->vars, dv);
+  variable **slot = shared_hash_find_slot_noinsert (set->vars, dv);
   if (!slot)
     return;
 
@@ -7951,8 +8064,9 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
 
 /* Structure for passing some other parameters to function
    vt_expand_loc_callback.  */
-struct expand_loc_callback_data
+class expand_loc_callback_data
 {
+public:
   /* The variables and values active at this point.  */
   variable_table_type *vars;
 
@@ -7977,7 +8091,7 @@ struct expand_loc_callback_data
    room for COUNT dependencies.  */
 
 static void
-loc_exp_dep_alloc (variable var, int count)
+loc_exp_dep_alloc (variable *var, int count)
 {
   size_t allocsize;
 
@@ -8025,7 +8139,7 @@ loc_exp_dep_alloc (variable var, int count)
    removing them from the back-links lists too.  */
 
 static void
-loc_exp_dep_clear (variable var)
+loc_exp_dep_clear (variable *var)
 {
   while (VAR_LOC_DEP_VEC (var) && !VAR_LOC_DEP_VEC (var)->is_empty ())
     {
@@ -8043,10 +8157,10 @@ loc_exp_dep_clear (variable var)
    back-links in VARS.  */
 
 static void
-loc_exp_insert_dep (variable var, rtx x, variable_table_type *vars)
+loc_exp_insert_dep (variable *var, rtx x, variable_table_type *vars)
 {
   decl_or_value dv;
-  variable xvar;
+  variable *xvar;
   loc_exp_dep *led;
 
   dv = dv_from_rtx (x);
@@ -8093,7 +8207,7 @@ loc_exp_insert_dep (variable var, rtx x, variable_table_type *vars)
    true if we found any pending-recursion results.  */
 
 static bool
-loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
+loc_exp_dep_set (variable *var, rtx result, rtx *value, int count,
                 variable_table_type *vars)
 {
   bool pending_recursion = false;
@@ -8123,14 +8237,14 @@ loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
    attempt to compute a current location.  */
 
 static void
-notify_dependents_of_resolved_value (variable ivar, variable_table_type *vars)
+notify_dependents_of_resolved_value (variable *ivar, variable_table_type *vars)
 {
   loc_exp_dep *led, *next;
 
   for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
     {
       decl_or_value dv = led->dv;
-      variable var;
+      variable *var;
 
       next = led->next;
 
@@ -8215,10 +8329,11 @@ update_depth (expand_depth saved_depth, expand_depth best_depth)
    it is pending recursion resolution.  */
 
 static inline rtx
-vt_expand_var_loc_chain (variable var, bitmap regs, void *data, bool *pendrecp)
+vt_expand_var_loc_chain (variable *var, bitmap regs, void *data,
+                        bool *pendrecp)
 {
-  struct expand_loc_callback_data *elcd
-    = (struct expand_loc_callback_data *) data;
+  class expand_loc_callback_data *elcd
+    = (class expand_loc_callback_data *) data;
   location_chain *loc, *next;
   rtx result = NULL;
   int first_child, result_first_child, last_child;
@@ -8356,10 +8471,10 @@ vt_expand_loc_callback (rtx x, bitmap regs,
                        int max_depth ATTRIBUTE_UNUSED,
                        void *data)
 {
-  struct expand_loc_callback_data *elcd
-    = (struct expand_loc_callback_data *) data;
+  class expand_loc_callback_data *elcd
+    = (class expand_loc_callback_data *) data;
   decl_or_value dv;
-  variable var;
+  variable *var;
   rtx result, subreg;
   bool pending_recursion = false;
   bool from_empty = false;
@@ -8380,7 +8495,7 @@ vt_expand_loc_callback (rtx x, bitmap regs,
 
       /* Invalid SUBREGs are ok in debug info.  ??? We could try
         alternate expansions for the VALUE as well.  */
-      if (!result)
+      if (!result && GET_MODE (subreg) != VOIDmode)
        result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
@@ -8514,10 +8629,10 @@ resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending)
 static rtx
 vt_expand_loc (rtx loc, variable_table_type *vars)
 {
-  struct expand_loc_callback_data data;
+  class expand_loc_callback_data data;
   rtx result;
 
-  if (!MAY_HAVE_DEBUG_INSNS)
+  if (!MAY_HAVE_DEBUG_BIND_INSNS)
     return loc;
 
   INIT_ELCD (data, vars);
@@ -8534,9 +8649,9 @@ vt_expand_loc (rtx loc, variable_table_type *vars)
    in VARS, updating their CUR_LOCs in the process.  */
 
 static rtx
-vt_expand_1pvar (variable var, variable_table_type *vars)
+vt_expand_1pvar (variable *var, variable_table_type *vars)
 {
-  struct expand_loc_callback_data data;
+  class expand_loc_callback_data data;
   rtx loc;
 
   gcc_checking_assert (var->onepart && var->n_var_parts == 1);
@@ -8560,9 +8675,9 @@ vt_expand_1pvar (variable var, variable_table_type *vars)
    before or after instruction INSN.  */
 
 int
-emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
+emit_note_insn_var_location (variable **varp, emit_note_data *data)
 {
-  variable var = *varp;
+  variable *var = *varp;
   rtx_insn *insn = data->insn;
   enum emit_note_where where = data->where;
   variable_table_type *vars = data->vars;
@@ -8572,7 +8687,6 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
   bool complete;
   enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
   HOST_WIDE_INT last_limit;
-  tree type_size_unit;
   HOST_WIDE_INT offsets[MAX_VAR_PARTS];
   rtx loc[MAX_VAR_PARTS];
   tree decl;
@@ -8594,7 +8708,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
     {
       machine_mode mode, wider_mode;
       rtx loc2;
-      HOST_WIDE_INT offset;
+      HOST_WIDE_INT offset, size, wider_size;
 
       if (i == 0 && var->onepart)
        {
@@ -8649,15 +8763,22 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
       mode = GET_MODE (var->var_part[i].cur_loc);
       if (mode == VOIDmode && var->onepart)
        mode = DECL_MODE (decl);
-      last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+      /* We ony track subparts of constant-sized objects, since at present
+        there's no representation for polynomial pieces.  */
+      if (!GET_MODE_SIZE (mode).is_constant (&size))
+       {
+         complete = false;
+         continue;
+       }
+      last_limit = offsets[n_var_parts] + size;
 
       /* Attempt to merge adjacent registers or memory.  */
-      wider_mode = GET_MODE_WIDER_MODE (mode);
       for (j = i + 1; j < var->n_var_parts; j++)
        if (last_limit <= VAR_PART_OFFSET (var, j))
          break;
       if (j < var->n_var_parts
-         && wider_mode != VOIDmode
+         && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
+         && GET_MODE_SIZE (wider_mode).is_constant (&wider_size)
          && var->var_part[j].cur_loc
          && mode == GET_MODE (var->var_part[j].cur_loc)
          && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
@@ -8666,10 +8787,11 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
          && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
        {
          rtx new_loc = NULL;
+         poly_int64 offset2;
 
          if (REG_P (loc[n_var_parts])
-             && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
-                == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
+             && hard_regno_nregs (REGNO (loc[n_var_parts]), mode) * 2
+                == hard_regno_nregs (REGNO (loc[n_var_parts]), wider_mode)
              && end_hard_regno (mode, REGNO (loc[n_var_parts]))
                 == REGNO (loc2))
            {
@@ -8690,20 +8812,13 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
          else if (MEM_P (loc[n_var_parts])
                   && GET_CODE (XEXP (loc2, 0)) == PLUS
                   && REG_P (XEXP (XEXP (loc2, 0), 0))
-                  && CONST_INT_P (XEXP (XEXP (loc2, 0), 1)))
+                  && poly_int_rtx_p (XEXP (XEXP (loc2, 0), 1), &offset2))
            {
-             if ((REG_P (XEXP (loc[n_var_parts], 0))
-                  && rtx_equal_p (XEXP (loc[n_var_parts], 0),
-                                  XEXP (XEXP (loc2, 0), 0))
-                  && INTVAL (XEXP (XEXP (loc2, 0), 1))
-                     == GET_MODE_SIZE (mode))
-                 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
-                     && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1))
-                     && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
-                                     XEXP (XEXP (loc2, 0), 0))
-                     && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
-                        + GET_MODE_SIZE (mode)
-                        == INTVAL (XEXP (XEXP (loc2, 0), 1))))
+             poly_int64 end1 = size;
+             rtx base1 = strip_offset_and_add (XEXP (loc[n_var_parts], 0),
+                                               &end1);
+             if (rtx_equal_p (base1, XEXP (XEXP (loc2, 0), 0))
+                 && known_eq (end1, offset2))
                new_loc = adjust_address_nv (loc[n_var_parts],
                                             wider_mode, 0);
            }
@@ -8712,14 +8827,15 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
            {
              loc[n_var_parts] = new_loc;
              mode = wider_mode;
-             last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+             last_limit = offsets[n_var_parts] + wider_size;
              i = j;
            }
        }
       ++n_var_parts;
     }
-  type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl));
-  if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
+  poly_uint64 type_size_unit
+    = tree_to_poly_uint64 (TYPE_SIZE_UNIT (TREE_TYPE (decl)));
+  if (maybe_lt (poly_uint64 (last_limit), type_size_unit))
     complete = false;
 
   if (! flag_var_tracking_uninit)
@@ -8764,14 +8880,12 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
       /* Make sure that the call related notes come first.  */
       while (NEXT_INSN (insn)
             && NOTE_P (insn)
-            && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
-                 && NOTE_DURING_CALL_P (insn))
-                || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION))
+            && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
+            && NOTE_DURING_CALL_P (insn))
        insn = NEXT_INSN (insn);
       if (NOTE_P (insn)
-         && ((NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
-              && NOTE_DURING_CALL_P (insn))
-             || NOTE_KIND (insn) == NOTE_INSN_CALL_ARG_LOCATION))
+         && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
+         && NOTE_DURING_CALL_P (insn))
        note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
       else
        note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
@@ -8791,10 +8905,10 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
    values) entries that aren't user variables.  */
 
 int
-var_track_values_to_stack (variable_def **slot,
+var_track_values_to_stack (variable **slot,
                           vec<rtx, va_heap> *changed_values_stack)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   if (var->onepart == ONEPART_VALUE)
     changed_values_stack->safe_push (dv_as_value (var->dv));
@@ -8810,8 +8924,8 @@ static void
 remove_value_from_changed_variables (rtx val)
 {
   decl_or_value dv = dv_from_rtx (val);
-  variable_def **slot;
-  variable var;
+  variable **slot;
+  variable *var;
 
   slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
                                                NO_INSERT);
@@ -8829,8 +8943,8 @@ static void
 notify_dependents_of_changed_value (rtx val, variable_table_type *htab,
                                    vec<rtx, va_heap> *changed_values_stack)
 {
-  variable_def **slot;
-  variable var;
+  variable **slot;
+  variable *var;
   loc_exp_dep *led;
   decl_or_value dv = dv_from_rtx (val);
 
@@ -8846,7 +8960,7 @@ notify_dependents_of_changed_value (rtx val, variable_table_type *htab,
   while ((led = VAR_LOC_DEP_LST (var)))
     {
       decl_or_value ldv = led->dv;
-      variable ivar;
+      variable *ivar;
 
       /* Deactivate and remove the backlink, as it was “used up”.  It
         makes no sense to attempt to notify the same entity again:
@@ -8950,10 +9064,10 @@ emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
   emit_note_data data;
   variable_table_type *htab = shared_hash_htab (vars);
 
-  if (!changed_variables->elements ())
+  if (changed_variables->is_empty ())
     return;
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     process_changed_values (htab);
 
   data.insn = insn;
@@ -8968,9 +9082,9 @@ emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
    same variable in hash table DATA or is not there at all.  */
 
 int
-emit_notes_for_differences_1 (variable_def **slot, variable_table_type *new_vars)
+emit_notes_for_differences_1 (variable **slot, variable_table_type *new_vars)
 {
-  variable old_var, new_var;
+  variable *old_var, *new_var;
 
   old_var = *slot;
   new_var = new_vars->find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));
@@ -8978,7 +9092,7 @@ emit_notes_for_differences_1 (variable_def **slot, variable_table_type *new_vars
   if (!new_var)
     {
       /* Variable has disappeared.  */
-      variable empty_var = NULL;
+      variable *empty_var = NULL;
 
       if (old_var->onepart == ONEPART_VALUE
          || old_var->onepart == ONEPART_DEXPR)
@@ -9040,9 +9154,9 @@ emit_notes_for_differences_1 (variable_def **slot, variable_table_type *new_vars
    table DATA.  */
 
 int
-emit_notes_for_differences_2 (variable_def **slot, variable_table_type *old_vars)
+emit_notes_for_differences_2 (variable **slot, variable_table_type *old_vars)
 {
-  variable old_var, new_var;
+  variable *old_var, *new_var;
 
   new_var = *slot;
   old_var = old_vars->find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
@@ -9114,7 +9228,6 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
            emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
            {
              rtx arguments = mo->u.loc, *p = &arguments;
-             rtx_note *note;
              while (*p)
                {
                  XEXP (XEXP (*p, 0), 1)
@@ -9122,7 +9235,11 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
                                     shared_hash_htab (set->vars));
                  /* If expansion is successful, keep it in the list.  */
                  if (XEXP (XEXP (*p, 0), 1))
-                   p = &XEXP (*p, 1);
+                   {
+                     XEXP (XEXP (*p, 0), 1)
+                       = copy_rtx_if_shared (XEXP (XEXP (*p, 0), 1));
+                     p = &XEXP (*p, 1);
+                   }
                  /* Otherwise, if the following item is data_value for it,
                     drop it too too.  */
                  else if (XEXP (*p, 1)
@@ -9138,8 +9255,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
                  else
                    *p = XEXP (*p, 1);
                }
-             note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn);
-             NOTE_VAR_LOCATION (note) = arguments;
+             add_reg_note (insn, REG_CALL_ARG_LOCATION, arguments);
            }
            break;
 
@@ -9426,7 +9542,7 @@ vt_emit_notes (void)
   basic_block bb;
   dataflow_set cur;
 
-  gcc_assert (!changed_variables->elements ());
+  gcc_assert (changed_variables->is_empty ());
 
   /* Free memory occupied by the out hash tables, as they aren't used
      anymore.  */
@@ -9437,10 +9553,8 @@ vt_emit_notes (void)
      delete_variable_part).  */
   emit_notes = true;
 
-  if (MAY_HAVE_DEBUG_INSNS)
-    {
-      dropped_values = new variable_table_type (cselib_get_next_uid () * 2);
-    }
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
+    dropped_values = new variable_table_type (cselib_get_next_uid () * 2);
 
   dataflow_set_init (&cur);
 
@@ -9450,13 +9564,13 @@ vt_emit_notes (void)
         subsequent basic blocks.  */
       emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
 
-      if (MAY_HAVE_DEBUG_INSNS)
+      if (MAY_HAVE_DEBUG_BIND_INSNS)
        local_get_addr_cache = new hash_map<rtx, rtx>;
 
       /* Emit the notes for the changes in the basic block itself.  */
       emit_notes_in_bb (bb, &cur);
 
-      if (MAY_HAVE_DEBUG_INSNS)
+      if (MAY_HAVE_DEBUG_BIND_INSNS)
        delete local_get_addr_cache;
       local_get_addr_cache = NULL;
 
@@ -9464,14 +9578,15 @@ vt_emit_notes (void)
         again.  */
       dataflow_set_clear (&VTI (bb)->in);
     }
-#ifdef ENABLE_CHECKING
-  shared_hash_htab (cur.vars)
-    ->traverse <variable_table_type *, emit_notes_for_differences_1>
-      (shared_hash_htab (empty_shared_hash));
-#endif
+
+  if (flag_checking)
+    shared_hash_htab (cur.vars)
+      ->traverse <variable_table_type *, emit_notes_for_differences_1>
+       (shared_hash_htab (empty_shared_hash));
+
   dataflow_set_destroy (&cur);
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     delete dropped_values;
   dropped_values = NULL;
 
@@ -9482,7 +9597,7 @@ vt_emit_notes (void)
    assign declaration to *DECLP and offset to *OFFSETP, and return true.  */
 
 static bool
-vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
+vt_get_decl_and_offset (rtx rtl, tree *declp, poly_int64 *offsetp)
 {
   if (REG_P (rtl))
     {
@@ -9508,8 +9623,10 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
            decl = REG_EXPR (reg);
          if (REG_EXPR (reg) != decl)
            break;
-         if (REG_OFFSET (reg) < offset)
-           offset = REG_OFFSET (reg);
+         HOST_WIDE_INT this_offset;
+         if (!track_offset_p (REG_OFFSET (reg), &this_offset))
+           break;
+         offset = MIN (offset, this_offset);
        }
 
       if (i == len)
@@ -9524,7 +9641,7 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
       if (MEM_ATTRS (rtl))
        {
          *declp = MEM_EXPR (rtl);
-         *offsetp = INT_MEM_OFFSET (rtl);
+         *offsetp = int_mem_offset (rtl);
          return true;
        }
     }
@@ -9553,9 +9670,10 @@ vt_add_function_parameter (tree parm)
   rtx incoming = DECL_INCOMING_RTL (parm);
   tree decl;
   machine_mode mode;
-  HOST_WIDE_INT offset;
+  poly_int64 offset;
   dataflow_set *out;
   decl_or_value dv;
+  bool incoming_ok = true;
 
   if (TREE_CODE (parm) != PARM_DECL)
     return;
@@ -9570,20 +9688,17 @@ vt_add_function_parameter (tree parm)
      rewrite the incoming location of parameters passed on the stack
      into MEMs based on the argument pointer, so that incoming doesn't
      depend on a pseudo.  */
+  poly_int64 incoming_offset = 0;
   if (MEM_P (incoming)
-      && (XEXP (incoming, 0) == crtl->args.internal_arg_pointer
-         || (GET_CODE (XEXP (incoming, 0)) == PLUS
-             && XEXP (XEXP (incoming, 0), 0)
-                == crtl->args.internal_arg_pointer
-             && CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
+      && (strip_offset (XEXP (incoming, 0), &incoming_offset)
+         == crtl->args.internal_arg_pointer))
     {
       HOST_WIDE_INT off = -FIRST_PARM_OFFSET (current_function_decl);
-      if (GET_CODE (XEXP (incoming, 0)) == PLUS)
-       off += INTVAL (XEXP (XEXP (incoming, 0), 1));
       incoming
        = replace_equiv_address_nv (incoming,
                                    plus_constant (Pmode,
-                                                  arg_pointer_rtx, off));
+                                                  arg_pointer_rtx,
+                                                  off + incoming_offset));
     }
 
 #ifdef HAVE_window_save
@@ -9596,7 +9711,7 @@ vt_add_function_parameter (tree parm)
          && HARD_REGISTER_P (incoming)
          && OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
        {
-         parm_reg_t p;
+         parm_reg p;
          p.incoming = incoming;
          incoming
            = gen_rtx_REG_offset (incoming, GET_MODE (incoming),
@@ -9613,7 +9728,7 @@ vt_add_function_parameter (tree parm)
          for (i = 0; i < XVECLEN (incoming, 0); i++)
            {
              rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
-             parm_reg_t p;
+             parm_reg p;
              p.incoming = reg;
              reg = gen_rtx_REG_offset (reg, GET_MODE (reg),
                                        OUTGOING_REGNO (REGNO (reg)), 0);
@@ -9633,7 +9748,7 @@ vt_add_function_parameter (tree parm)
          rtx reg = XEXP (incoming, 0);
          if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
            {
-             parm_reg_t p;
+             parm_reg p;
              p.incoming = reg;
              reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
              p.outgoing = reg;
@@ -9646,6 +9761,7 @@ vt_add_function_parameter (tree parm)
 
   if (!vt_get_decl_and_offset (incoming, &decl, &offset))
     {
+      incoming_ok = false;
       if (MEM_P (incoming))
        {
          /* This means argument is passed by invisible reference.  */
@@ -9676,7 +9792,8 @@ vt_add_function_parameter (tree parm)
       offset = 0;
     }
 
-  if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
+  HOST_WIDE_INT const_offset;
+  if (!track_loc_p (incoming, parm, offset, false, &mode, &const_offset))
     return;
 
   out = &VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out;
@@ -9697,7 +9814,7 @@ vt_add_function_parameter (tree parm)
         arguments passed by invisible reference aren't dealt with
         above: incoming-rtl will have Pmode rather than the
         expected mode for the type.  */
-      if (offset)
+      if (const_offset)
        return;
 
       lowpart = var_lowpart (mode, incoming);
@@ -9712,7 +9829,7 @@ vt_add_function_parameter (tree parm)
       if (val)
        {
          preserve_value (val);
-         set_variable_part (out, val->val_rtx, dv, offset,
+         set_variable_part (out, val->val_rtx, dv, const_offset,
                             VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
          dv = dv_from_value (val->val_rtx);
        }
@@ -9733,9 +9850,9 @@ vt_add_function_parameter (tree parm)
     {
       incoming = var_lowpart (mode, incoming);
       gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
-      attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
+      attrs_list_insert (&out->regs[REGNO (incoming)], dv, const_offset,
                         incoming);
-      set_variable_part (out, incoming, dv, offset,
+      set_variable_part (out, incoming, dv, const_offset,
                         VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
       if (dv_is_value_p (dv))
        {
@@ -9763,20 +9880,26 @@ vt_add_function_parameter (tree parm)
     {
       int i;
 
+      /* The following code relies on vt_get_decl_and_offset returning true for
+        incoming, which might not be always the case.  */
+      if (!incoming_ok)
+       return;
       for (i = 0; i < XVECLEN (incoming, 0); i++)
        {
          rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
-         offset = REG_OFFSET (reg);
+         /* vt_get_decl_and_offset has already checked that the offset
+            is a valid variable part.  */
+         const_offset = get_tracked_reg_offset (reg);
          gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
-         attrs_list_insert (&out->regs[REGNO (reg)], dv, offset, reg);
-         set_variable_part (out, reg, dv, offset,
+         attrs_list_insert (&out->regs[REGNO (reg)], dv, const_offset, reg);
+         set_variable_part (out, reg, dv, const_offset,
                             VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
        }
     }
   else if (MEM_P (incoming))
     {
       incoming = var_lowpart (mode, incoming);
-      set_variable_part (out, incoming, dv, offset,
+      set_variable_part (out, incoming, dv, const_offset,
                         VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
     }
 }
@@ -9790,8 +9913,7 @@ vt_add_function_parameters (void)
 
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm; parm = DECL_CHAIN (parm))
-    if (!POINTER_BOUNDS_P (parm))
-      vt_add_function_parameter (parm);
+    vt_add_function_parameter (parm);
 
   if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
     {
@@ -9831,7 +9953,7 @@ vt_init_cfa_base (void)
       cfa_base_rtx = NULL_RTX;
       return;
     }
-  if (!MAY_HAVE_DEBUG_INSNS)
+  if (!MAY_HAVE_DEBUG_BIND_INSNS)
     return;
 
   /* Tell alias analysis that cfa_base_rtx should share
@@ -9847,6 +9969,35 @@ vt_init_cfa_base (void)
   cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx));
 }
 
+/* Reemit INSN, a MARKER_DEBUG_INSN, as a note.  */
+
+static rtx_insn *
+reemit_marker_as_note (rtx_insn *insn)
+{
+  gcc_checking_assert (DEBUG_MARKER_INSN_P (insn));
+
+  enum insn_note kind = INSN_DEBUG_MARKER_KIND (insn);
+
+  switch (kind)
+    {
+    case NOTE_INSN_BEGIN_STMT:
+    case NOTE_INSN_INLINE_ENTRY:
+      {
+       rtx_insn *note = NULL;
+       if (cfun->debug_nonbind_markers)
+         {
+           note = emit_note_before (kind, insn);
+           NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn);
+         }
+       delete_insn (insn);
+       return note;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Allocate and initialize the data structures for variable tracking
    and parse the RTL to get the micro operations.  */
 
@@ -9854,11 +10005,11 @@ static bool
 vt_initialize (void)
 {
   basic_block bb;
-  HOST_WIDE_INT fp_cfa_offset = -1;
+  poly_int64 fp_cfa_offset = -1;
 
-  alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
+  alloc_aux_for_blocks (sizeof (variable_tracking_info));
 
-  empty_shared_hash = new shared_hash;
+  empty_shared_hash = shared_hash_pool.allocate ();
   empty_shared_hash->refcount = 1;
   empty_shared_hash->htab = new variable_table_type (1);
   changed_variables = new variable_table_type (10);
@@ -9873,7 +10024,7 @@ vt_initialize (void)
       VTI (bb)->permp = NULL;
     }
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     {
       cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
       scratch_regs = BITMAP_ALLOC (NULL);
@@ -9886,7 +10037,7 @@ vt_initialize (void)
       global_get_addr_cache = NULL;
     }
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     {
       rtx reg, expr;
       int ofst;
@@ -9907,19 +10058,25 @@ vt_initialize (void)
       preserve_value (val);
       if (reg != hard_frame_pointer_rtx && fixed_regs[REGNO (reg)])
        cselib_preserve_cfa_base_value (val, REGNO (reg));
-      expr = plus_constant (GET_MODE (stack_pointer_rtx),
-                           stack_pointer_rtx, -ofst);
-      cselib_add_permanent_equiv (val, expr, get_insns ());
-
       if (ofst)
        {
-         val = cselib_lookup_from_insn (stack_pointer_rtx,
-                                        GET_MODE (stack_pointer_rtx), 1,
-                                        VOIDmode, get_insns ());
-         preserve_value (val);
+         cselib_val *valsp
+           = cselib_lookup_from_insn (stack_pointer_rtx,
+                                      GET_MODE (stack_pointer_rtx), 1,
+                                      VOIDmode, get_insns ());
+         preserve_value (valsp);
          expr = plus_constant (GET_MODE (reg), reg, ofst);
-         cselib_add_permanent_equiv (val, expr, get_insns ());
+         /* This cselib_add_permanent_equiv call needs to be done before
+            the other cselib_add_permanent_equiv a few lines later,
+            because after that one is done, cselib_lookup on this expr
+            will due to the cselib SP_DERIVED_VALUE_P optimizations
+            return valsp and so no permanent equivalency will be added.  */
+         cselib_add_permanent_equiv (valsp, expr, get_insns ());
        }
+
+      expr = plus_constant (GET_MODE (stack_pointer_rtx),
+                           stack_pointer_rtx, -ofst);
+      cselib_add_permanent_equiv (val, expr, get_insns ());
     }
 
   /* In order to factor out the adjustments made to the stack pointer or to
@@ -9969,7 +10126,7 @@ vt_initialize (void)
        {
          if (GET_CODE (elim) == PLUS)
            {
-             fp_cfa_offset -= INTVAL (XEXP (elim, 1));
+             fp_cfa_offset -= rtx_to_poly_int64 (XEXP (elim, 1));
              elim = XEXP (elim, 0);
            }
          if (elim != hard_frame_pointer_rtx)
@@ -10010,13 +10167,13 @@ vt_initialize (void)
 
   vt_add_function_parameters ();
 
+  bool record_sp_value = false;
   FOR_EACH_BB_FN (bb, cfun)
     {
       rtx_insn *insn;
-      HOST_WIDE_INT pre, post = 0;
       basic_block first_bb, last_bb;
 
-      if (MAY_HAVE_DEBUG_INSNS)
+      if (MAY_HAVE_DEBUG_BIND_INSNS)
        {
          cselib_record_sets_hook = add_with_sets;
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -10024,6 +10181,15 @@ vt_initialize (void)
                     cselib_get_next_uid ());
        }
 
+      if (MAY_HAVE_DEBUG_BIND_INSNS
+         && cfa_base_rtx
+         && !frame_pointer_needed
+         && record_sp_value)
+       cselib_record_sp_cfa_base_equiv (-cfa_base_offset
+                                        - VTI (bb)->in.stack_adjust,
+                                        BB_HEAD (bb));
+      record_sp_value = true;
+
       first_bb = bb;
       for (;;)
        {
@@ -10043,11 +10209,14 @@ vt_initialize (void)
        {
          HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
          VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
-         for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
-              insn = NEXT_INSN (insn))
+
+         rtx_insn *next;
+         FOR_BB_INSNS_SAFE (bb, insn, next)
            {
              if (INSN_P (insn))
                {
+                 HOST_WIDE_INT pre = 0, post = 0;
+
                  if (!frame_pointer_needed)
                    {
                      insn_stack_adjust_offset_pre_post (insn, &pre, &post);
@@ -10061,20 +10230,32 @@ vt_initialize (void)
                            log_op_type (PATTERN (insn), bb, insn,
                                         MO_ADJUST, dump_file);
                          VTI (bb)->mos.safe_push (mo);
-                         VTI (bb)->out.stack_adjust += pre;
                        }
                    }
 
                  cselib_hook_called = false;
                  adjust_insn (bb, insn);
-                 if (MAY_HAVE_DEBUG_INSNS)
+
+                 if (pre)
+                   VTI (bb)->out.stack_adjust += pre;
+
+                 if (DEBUG_MARKER_INSN_P (insn))
+                   {
+                     reemit_marker_as_note (insn);
+                     continue;
+                   }
+
+                 if (MAY_HAVE_DEBUG_BIND_INSNS)
                    {
                      if (CALL_P (insn))
                        prepare_call_arguments (bb, insn);
                      cselib_process_insn (insn);
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        {
-                         print_rtl_single (dump_file, insn);
+                         if (dump_flags & TDF_SLIM)
+                           dump_insn_slim (dump_file, insn);
+                         else
+                           print_rtl_single (dump_file, insn);
                          dump_cselib_table (dump_file);
                        }
                    }
@@ -10082,7 +10263,7 @@ vt_initialize (void)
                    add_with_sets (insn, 0, 0);
                  cancel_changes (0);
 
-                 if (!frame_pointer_needed && post)
+                 if (post)
                    {
                      micro_operation mo;
                      mo.type = MO_ADJUST;
@@ -10095,14 +10276,14 @@ vt_initialize (void)
                      VTI (bb)->out.stack_adjust += post;
                    }
 
-                 if (fp_cfa_offset != -1
-                     && hard_frame_pointer_adjustment == -1
+                 if (maybe_ne (fp_cfa_offset, -1)
+                     && known_eq (hard_frame_pointer_adjustment, -1)
                      && fp_setter_insn (insn))
                    {
                      vt_init_cfa_base ();
                      hard_frame_pointer_adjustment = fp_cfa_offset;
                      /* Disassociate sp from fp now.  */
-                     if (MAY_HAVE_DEBUG_INSNS)
+                     if (MAY_HAVE_DEBUG_BIND_INSNS)
                        {
                          cselib_val *v;
                          cselib_invalidate_rtx (stack_pointer_rtx);
@@ -10122,7 +10303,7 @@ vt_initialize (void)
 
       bb = last_bb;
 
-      if (MAY_HAVE_DEBUG_INSNS)
+      if (MAY_HAVE_DEBUG_BIND_INSNS)
        {
          cselib_preserve_only_values ();
          cselib_reset_table (cselib_get_next_uid ());
@@ -10142,10 +10323,40 @@ vt_initialize (void)
 
 static int debug_label_num = 1;
 
-/* Get rid of all debug insns from the insn stream.  */
+/* Remove from the insn stream a single debug insn used for
+   variable tracking at assignments.  */
 
-static void
-delete_debug_insns (void)
+static inline void
+delete_vta_debug_insn (rtx_insn *insn)
+{
+  if (DEBUG_MARKER_INSN_P (insn))
+    {
+      reemit_marker_as_note (insn);
+      return;
+    }
+
+  tree decl = INSN_VAR_LOCATION_DECL (insn);
+  if (TREE_CODE (decl) == LABEL_DECL
+      && DECL_NAME (decl)
+      && !DECL_RTL_SET_P (decl))
+    {
+      PUT_CODE (insn, NOTE);
+      NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL;
+      NOTE_DELETED_LABEL_NAME (insn)
+       = IDENTIFIER_POINTER (DECL_NAME (decl));
+      SET_DECL_RTL (decl, insn);
+      CODE_LABEL_NUMBER (insn) = debug_label_num++;
+    }
+  else
+    delete_insn (insn);
+}
+
+/* Remove from the insn stream all debug insns used for variable
+   tracking at assignments.  USE_CFG should be false if the cfg is no
+   longer usable.  */
+
+void
+delete_vta_debug_insns (bool use_cfg)
 {
   basic_block bb;
   rtx_insn *insn, *next;
@@ -10153,27 +10364,20 @@ delete_debug_insns (void)
   if (!MAY_HAVE_DEBUG_INSNS)
     return;
 
-  FOR_EACH_BB_FN (bb, cfun)
-    {
-      FOR_BB_INSNS_SAFE (bb, insn, next)
+  if (use_cfg)
+    FOR_EACH_BB_FN (bb, cfun)
+      {
+       FOR_BB_INSNS_SAFE (bb, insn, next)
+         if (DEBUG_INSN_P (insn))
+           delete_vta_debug_insn (insn);
+      }
+  else
+    for (insn = get_insns (); insn; insn = next)
+      {
+       next = NEXT_INSN (insn);
        if (DEBUG_INSN_P (insn))
-         {
-           tree decl = INSN_VAR_LOCATION_DECL (insn);
-           if (TREE_CODE (decl) == LABEL_DECL
-               && DECL_NAME (decl)
-               && !DECL_RTL_SET_P (decl))
-             {
-               PUT_CODE (insn, NOTE);
-               NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL;
-               NOTE_DELETED_LABEL_NAME (insn)
-                 = IDENTIFIER_POINTER (DECL_NAME (decl));
-               SET_DECL_RTL (decl, insn);
-               CODE_LABEL_NUMBER (insn) = debug_label_num++;
-             }
-           else
-             delete_insn (insn);
-         }
-    }
+         delete_vta_debug_insn (insn);
+      }
 }
 
 /* Run a fast, BB-local only version of var tracking, to take care of
@@ -10186,7 +10390,7 @@ static void
 vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
 {
   /* ??? Just skip it all for now.  */
-  delete_debug_insns ();
+  delete_vta_debug_insns (true);
 }
 
 /* Free the data structures needed for variable tracking.  */
@@ -10216,12 +10420,12 @@ vt_finalize (void)
   empty_shared_hash->htab = NULL;
   delete changed_variables;
   changed_variables = NULL;
-  attrs_def_pool.release ();
+  attrs_pool.release ();
   var_pool.release ();
   location_chain_pool.release ();
   shared_hash_pool.release ();
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     {
       if (global_get_addr_cache)
        delete global_get_addr_cache;
@@ -10251,17 +10455,23 @@ variable_tracking_main_1 (void)
 {
   bool success;
 
-  if (flag_var_tracking_assignments < 0
+  /* We won't be called as a separate pass if flag_var_tracking is not
+     set, but final may call us to turn debug markers into notes.  */
+  if ((!flag_var_tracking && MAY_HAVE_DEBUG_INSNS)
+      || flag_var_tracking_assignments < 0
       /* Var-tracking right now assumes the IR doesn't contain
         any pseudos at this point.  */
       || targetm.no_register_allocation)
     {
-      delete_debug_insns ();
+      delete_vta_debug_insns (true);
       return 0;
     }
 
-  if (n_basic_blocks_for_fn (cfun) > 500 &&
-      n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
+  if (!flag_var_tracking)
+    return 0;
+
+  if (n_basic_blocks_for_fn (cfun) > 500
+      && n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
     {
       vt_debug_insns_local (true);
       return 0;
@@ -10281,7 +10491,7 @@ variable_tracking_main_1 (void)
     {
       vt_finalize ();
 
-      delete_debug_insns ();
+      delete_vta_debug_insns (true);
 
       /* This is later restored by our caller.  */
       flag_var_tracking_assignments = 0;