t-aarch64-linux (MULTILIB_OSDIRNAMES): Handle multi-arch for ilp32.
[gcc.git] / gcc / var-tracking.c
index b30a0ebcc3a68fdd30cdb87eda62ddcd59bdddef..77281fb45ee228e8cb802bcf61aff989c9b2c580 100644 (file)
@@ -390,8 +390,16 @@ struct variable
 /* Pointer to the BB's information specific to variable tracking pass.  */
 #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.  */
+
+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)
 
@@ -666,7 +674,6 @@ static bool dataflow_set_different (dataflow_set *, dataflow_set *);
 static void dataflow_set_destroy (dataflow_set *);
 
 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);
@@ -697,7 +704,6 @@ static void delete_variable_part (dataflow_set *, rtx,
 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);
@@ -970,7 +976,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))
@@ -991,7 +997,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:
@@ -1008,6 +1015,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
   rtx mem, addr = loc, tem;
   machine_mode mem_mode_save;
   bool store_save;
+  scalar_int_mode tem_mode, tem_subreg_mode;
   switch (GET_CODE (loc))
     {
     case REG:
@@ -1116,22 +1124,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
@@ -1330,7 +1336,7 @@ 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))
@@ -1843,6 +1849,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
@@ -1850,7 +1882,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);
@@ -1896,7 +1928,7 @@ 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);
+  HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
   attrs *node, *next;
   attrs **nextp;
 
@@ -1937,10 +1969,10 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
   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);
 
@@ -2336,7 +2368,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);
@@ -2354,7 +2386,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);
@@ -2375,7 +2407,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);
@@ -2555,7 +2587,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)
        {
@@ -3490,6 +3522,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.  */
@@ -4618,7 +4656,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;
@@ -4683,7 +4721,7 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
              /* 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)
+                     || int_mem_offset (loc->loc) != 0)
                  && mem_dies_at_call (loc->loc))
                break;
              /* We want to move here MEMs that do refer to DECL.  */
@@ -4727,7 +4765,7 @@ dataflow_set_preserve_mem_locs (variable **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)
@@ -4854,7 +4892,7 @@ dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
   EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 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)
@@ -5170,20 +5208,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, &reverse);
-             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 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;
@@ -5220,11 +5258,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;
     }
 
@@ -5237,10 +5276,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;
@@ -5253,7 +5292,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;
@@ -5264,7 +5303,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.
@@ -5278,7 +5317,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;
@@ -5294,7 +5333,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;
@@ -5308,23 +5347,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;
 }
 
@@ -5335,7 +5375,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;
@@ -5343,12 +5383,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);
@@ -5521,13 +5561,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
@@ -6016,7 +6056,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;
@@ -6300,18 +6340,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);
@@ -6346,8 +6387,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);
@@ -6690,7 +6732,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)
@@ -6972,7 +7014,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;
@@ -7059,7 +7101,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;
@@ -7120,7 +7162,7 @@ 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");
@@ -7180,7 +7222,7 @@ 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);
 
@@ -8569,7 +8611,7 @@ vt_expand_loc (rtx loc, variable_table_type *vars)
   struct expand_loc_callback_data data;
   rtx result;
 
-  if (!MAY_HAVE_DEBUG_INSNS)
+  if (!MAY_HAVE_DEBUG_BIND_INSNS)
     return loc;
 
   INIT_ELCD (data, vars);
@@ -8704,12 +8746,11 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data)
       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
 
       /* 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)
          && 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]))
@@ -8720,8 +8761,8 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data)
          rtx new_loc = NULL;
 
          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))
            {
@@ -9005,7 +9046,7 @@ emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
   if (!changed_variables->elements ())
     return;
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     process_changed_values (htab);
 
   data.insn = insn;
@@ -9489,10 +9530,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);
 
@@ -9502,13 +9541,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;
 
@@ -9524,7 +9563,7 @@ vt_emit_notes (void)
 
   dataflow_set_destroy (&cur);
 
-  if (MAY_HAVE_DEBUG_INSNS)
+  if (MAY_HAVE_DEBUG_BIND_INSNS)
     delete dropped_values;
   dropped_values = NULL;
 
@@ -9535,7 +9574,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))
     {
@@ -9561,8 +9600,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)
@@ -9577,7 +9618,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;
        }
     }
@@ -9606,7 +9647,7 @@ 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;
 
@@ -9729,7 +9770,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;
@@ -9750,7 +9792,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);
@@ -9765,7 +9807,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);
        }
@@ -9786,9 +9828,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))
        {
@@ -9819,17 +9861,19 @@ vt_add_function_parameter (tree parm)
       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);
     }
 }
@@ -9884,7 +9928,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
@@ -9900,6 +9944,34 @@ 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:
+      {
+       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.  */
 
@@ -9926,7 +9998,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);
@@ -9939,7 +10011,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;
@@ -10069,7 +10141,7 @@ vt_initialize (void)
       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))
@@ -10096,8 +10168,9 @@ 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))
                {
@@ -10120,7 +10193,13 @@ vt_initialize (void)
 
                  cselib_hook_called = false;
                  adjust_insn (bb, insn);
-                 if (MAY_HAVE_DEBUG_INSNS)
+                 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);
@@ -10155,7 +10234,7 @@ vt_initialize (void)
                      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);
@@ -10175,7 +10254,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 ());
@@ -10195,10 +10274,11 @@ vt_initialize (void)
 
 static int debug_label_num = 1;
 
-/* Get rid of all debug insns from the insn stream.  */
+/* Remove from the insn stream all debug insns used for variable
+   tracking at assignments.  */
 
 static void
-delete_debug_insns (void)
+delete_vta_debug_insns (void)
 {
   basic_block bb;
   rtx_insn *insn, *next;
@@ -10211,6 +10291,12 @@ delete_debug_insns (void)
       FOR_BB_INSNS_SAFE (bb, insn, next)
        if (DEBUG_INSN_P (insn))
          {
+           if (DEBUG_MARKER_INSN_P (insn))
+             {
+               reemit_marker_as_note (insn);
+               continue;
+             }
+
            tree decl = INSN_VAR_LOCATION_DECL (insn);
            if (TREE_CODE (decl) == LABEL_DECL
                && DECL_NAME (decl)
@@ -10239,7 +10325,7 @@ static void
 vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
 {
   /* ??? Just skip it all for now.  */
-  delete_debug_insns ();
+  delete_vta_debug_insns ();
 }
 
 /* Free the data structures needed for variable tracking.  */
@@ -10274,7 +10360,7 @@ vt_finalize (void)
   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;
@@ -10304,17 +10390,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 ();
       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;
@@ -10334,7 +10426,7 @@ variable_tracking_main_1 (void)
     {
       vt_finalize ();
 
-      delete_debug_insns ();
+      delete_vta_debug_insns ();
 
       /* This is later restored by our caller.  */
       flag_var_tracking_assignments = 0;