Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2017-10-23 17:01:15.119130016 +0100
+++ gcc/rtl.h	2017-10-23 17:01:43.314993320 +0100
@@ -187,7 +187,7 @@ struct GTY(()) mem_attrs
 
 struct GTY((for_user)) reg_attrs {
   tree decl;			/* decl corresponding to REG.  */
-  HOST_WIDE_INT offset;		/* Offset from start of DECL.  */
+  poly_int64 offset;		/* Offset from start of DECL.  */
 };
 
 /* Common union for an element of an rtx.  */
@@ -2997,7 +2997,7 @@ subreg_promoted_mode (rtx x)
 extern rtvec gen_rtvec_v (int, rtx *);
 extern rtvec gen_rtvec_v (int, rtx_insn **);
 extern rtx gen_reg_rtx (machine_mode);
-extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, int);
+extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, poly_int64);
 extern rtx gen_reg_rtx_offset (rtx, machine_mode, int);
 extern rtx gen_reg_rtx_and_attrs (rtx);
 extern rtx_code_label *gen_label_rtx (void);
Index: gcc/inchash.h
===================================================================
--- gcc/inchash.h	2017-10-23 17:01:29.530765486 +0100
+++ gcc/inchash.h	2017-10-23 17:01:43.314993320 +0100
@@ -63,6 +63,14 @@ hashval_t iterative_hash_hashval_t (hash
     val = iterative_hash_host_wide_int (v, val);
   }
 
+  /* Add polynomial value V, treating each element as a HOST_WIDE_INT.  */
+  template<unsigned int N, typename T>
+  void add_poly_hwi (const poly_int_pod<N, T> &v)
+  {
+    for (unsigned int i = 0; i < N; ++i)
+      add_hwi (v.coeffs[i]);
+  }
+
   /* Add wide_int-based value V.  */
   template<typename T>
   void add_wide_int (const generic_wide_int<T> &x)
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c	2017-10-23 17:01:15.119130016 +0100
+++ gcc/gengtype.c	2017-10-23 17:01:43.313994743 +0100
@@ -5190,6 +5190,7 @@ #define POS_HERE(Call) do { pos.file = t
       POS_HERE (do_scalar_typedef ("offset_int", &pos));
       POS_HERE (do_scalar_typedef ("widest_int", &pos));
       POS_HERE (do_scalar_typedef ("int64_t", &pos));
+      POS_HERE (do_scalar_typedef ("poly_int64", &pos));
       POS_HERE (do_scalar_typedef ("uint64_t", &pos));
       POS_HERE (do_scalar_typedef ("uint8", &pos));
       POS_HERE (do_scalar_typedef ("uintptr_t", &pos));
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-10-23 17:01:15.119130016 +0100
+++ gcc/emit-rtl.c	2017-10-23 17:01:43.313994743 +0100
@@ -205,7 +205,6 @@ static rtx lookup_const_wide_int (rtx);
 #endif
 static rtx lookup_const_double (rtx);
 static rtx lookup_const_fixed (rtx);
-static reg_attrs *get_reg_attrs (tree, int);
 static rtx gen_const_vector (machine_mode, int);
 static void copy_rtx_if_shared_1 (rtx *orig);
 
@@ -424,7 +423,10 @@ reg_attr_hasher::hash (reg_attrs *x)
 {
   const reg_attrs *const p = x;
 
-  return ((p->offset * 1000) ^ (intptr_t) p->decl);
+  inchash::hash h;
+  h.add_ptr (p->decl);
+  h.add_poly_hwi (p->offset);
+  return h.end ();
 }
 
 /* Returns nonzero if the value represented by X  is the same as that given by
@@ -436,19 +438,19 @@ reg_attr_hasher::equal (reg_attrs *x, re
   const reg_attrs *const p = x;
   const reg_attrs *const q = y;
 
-  return (p->decl == q->decl && p->offset == q->offset);
+  return (p->decl == q->decl && must_eq (p->offset, q->offset));
 }
 /* Allocate a new reg_attrs structure and insert it into the hash table if
    one identical to it is not already in the table.  We are doing this for
    MEM of mode MODE.  */
 
 static reg_attrs *
-get_reg_attrs (tree decl, int offset)
+get_reg_attrs (tree decl, poly_int64 offset)
 {
   reg_attrs attrs;
 
   /* If everything is the default, we can just return zero.  */
-  if (decl == 0 && offset == 0)
+  if (decl == 0 && known_zero (offset))
     return 0;
 
   attrs.decl = decl;
@@ -1241,10 +1243,10 @@ reg_is_parm_p (rtx reg)
    to the REG_OFFSET.  */
 
 static void
-update_reg_offset (rtx new_rtx, rtx reg, int offset)
+update_reg_offset (rtx new_rtx, rtx reg, poly_int64 offset)
 {
   REG_ATTRS (new_rtx) = get_reg_attrs (REG_EXPR (reg),
-				   REG_OFFSET (reg) + offset);
+				       REG_OFFSET (reg) + offset);
 }
 
 /* Generate a register with same attributes as REG, but with OFFSET
@@ -1252,7 +1254,7 @@ update_reg_offset (rtx new_rtx, rtx reg,
 
 rtx
 gen_rtx_REG_offset (rtx reg, machine_mode mode, unsigned int regno,
-		    int offset)
+		    poly_int64 offset)
 {
   rtx new_rtx = gen_rtx_REG (mode, regno);
 
@@ -1288,7 +1290,7 @@ adjust_reg_mode (rtx reg, machine_mode m
 void
 set_reg_attrs_from_value (rtx reg, rtx x)
 {
-  int offset;
+  poly_int64 offset;
   bool can_be_reg_pointer = true;
 
   /* Don't call mark_reg_pointer for incompatible pointer sign
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	2017-10-23 17:01:15.119130016 +0100
+++ gcc/print-rtl.c	2017-10-23 17:01:43.314993320 +0100
@@ -178,6 +178,23 @@ print_mem_expr (FILE *outfile, const_tre
   fputc (' ', outfile);
   print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags);
 }
+
+/* Print X to FILE.  */
+
+static void
+print_poly_int (FILE *file, poly_int64 x)
+{
+  HOST_WIDE_INT const_x;
+  if (x.is_constant (&const_x))
+    fprintf (file, HOST_WIDE_INT_PRINT_DEC, const_x);
+  else
+    {
+      fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC, x.coeffs[0]);
+      for (int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
+	fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, x.coeffs[i]);
+      fprintf (file, "]");
+    }
+}
 #endif
 
 /* Subroutine of print_rtx_operand for handling code '0'.
@@ -499,9 +516,11 @@ rtx_writer::print_rtx_operand_code_r (co
       if (REG_EXPR (in_rtx))
 	print_mem_expr (m_outfile, REG_EXPR (in_rtx));
 
-      if (REG_OFFSET (in_rtx))
-	fprintf (m_outfile, "+" HOST_WIDE_INT_PRINT_DEC,
-		 REG_OFFSET (in_rtx));
+      if (maybe_nonzero (REG_OFFSET (in_rtx)))
+	{
+	  fprintf (m_outfile, "+");
+	  print_poly_int (m_outfile, REG_OFFSET (in_rtx));
+	}
       fputs (" ]", m_outfile);
     }
   if (regno != ORIGINAL_REGNO (in_rtx))
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2017-10-23 17:01:15.119130016 +0100
+++ gcc/var-tracking.c	2017-10-23 17:01:43.315991896 +0100
@@ -673,7 +673,6 @@ static bool dataflow_set_different (data
 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);
@@ -704,7 +703,6 @@ static void delete_variable_part (datafl
 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);
@@ -1850,6 +1848,32 @@ var_reg_decl_set (dataflow_set *set, rtx
   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
@@ -1857,7 +1881,7 @@ var_reg_set (dataflow_set *set, rtx loc,
 	     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);
@@ -1903,7 +1927,7 @@ var_reg_delete_and_set (dataflow_set *se
 			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;
 
@@ -1944,10 +1968,10 @@ var_reg_delete (dataflow_set *set, rtx l
   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);
 
@@ -5245,10 +5269,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;
@@ -5272,7 +5296,7 @@ same_variable_part_p (rtx loc, tree expr
   expr = var_debug_decl (expr);
   expr2 = var_debug_decl (expr2);
 
-  return (expr == expr2 && offset == offset2);
+  return (expr == expr2 && must_eq (offset, offset2));
 }
 
 /* LOC is a REG or MEM that we would like to track if possible.
@@ -5286,7 +5310,7 @@ same_variable_part_p (rtx loc, tree expr
    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;
@@ -5320,19 +5344,20 @@ track_loc_p (rtx loc, tree expr, HOST_WI
        || (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)
+      && known_zero (offset + byte_lowpart_offset (DECL_MODE (expr), mode)))
     {
       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;
 }
 
@@ -9544,7 +9569,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))
     {
@@ -9570,8 +9595,10 @@ vt_get_decl_and_offset (rtx rtl, tree *d
 	    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)
@@ -9615,7 +9642,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;
 
@@ -9738,7 +9765,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;
@@ -9759,7 +9787,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);
@@ -9774,7 +9802,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);
 	}
@@ -9795,9 +9823,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))
 	{
@@ -9828,17 +9856,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);
     }
 }
