Patchwork [4/5] MEM_OFFSET and MEM_OFFSET_KNOWN_P

login
register
mail settings
Submitter Richard Sandiford
Date July 17, 2011, 2:32 p.m.
Message ID <871uxpugdz.fsf@firetop.home>
Download mbox | patch
Permalink /patch/105063/
State New
Headers show

Comments

Richard Sandiford - July 17, 2011, 2:32 p.m.
This patch makes the mechanical MEM_OFFSET interface change,
along the same lines as the MEM_SIZE one.

Richard


gcc/
	* doc/rtl.texi (MEM_OFFSET_KNOWN_P): Document.
	(MEM_OFFSET): Change from returning an rtx to returning a
	HOST_WIDE_INT.
	* rtl.h (MEM_OFFSET_KNOWN_P): New macro.
	(MEM_OFFSET): Return a HOST_WIDE_INT rather than an rtx.
	* emit-rtl.h (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_offset): Declare.
	* alias.c (ao_ref_from_mem): Adjust uses of MEM_OFFSET, using
	MEM_OFFSET_KNOWN_P to test whether the offset is known, and
	MEM_OFFSET to get a HOST_WIDE_INT offset.
	(nonoverlapping_memrefs_p): Likewise.  Adjust calls to...
	(adjust_offset_for_component_ref): Take a bool "known_p"
	parameter and a HOST_WIDE_INT "offset" parameter.
	* builtins.c (get_memory_rtx): As for ao_ref_from_mem.
	Adjust calls to set_mem_offset, passing a HOST_WIDE_INT rather
	than an rtx.  Use clear_mem_offset to clear the offset.
	* cfgcleanup.c (merge_memattrs): Likewise.
	* dwarf2out.c (tls_mem_loc_descriptor): Likewise.
	* function.c (assign_parm_find_stack_rtl): Likewise.
	(assign_parm_setup_stack): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* reload.c (find_reloads_subreg_address): Likewise.
	* simplify-rtx.c (delegitimize_mem_from_attrs): Likewise.
	* var-tracking.c (INT_MEM_OFFSET): Likewise.
	* emit-rtl.c (set_reg_attrs_from_value): Likewise.
	(get_mem_align_offset): Likewise.
	(set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
	(clear_mem_offset): New function.
	* config/mips/mips.c (r10k_safe_mem_expr_p): Take a HOST_WIDE_INT
	offset rather than an rtx.  Assume both the expressio and offset
	are available.
	(r10k_needs_protection_p_1): Update accordingly, checking the
	expression and offset availability here instead.
Richard Guenther - July 18, 2011, 9:37 a.m.
On Sun, Jul 17, 2011 at 4:32 PM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> This patch makes the mechanical MEM_OFFSET interface change,
> along the same lines as the MEM_SIZE one.

Ok if there are no objections from target maintainers.

Thanks,
Richard.

> Richard
>
>
> gcc/
>        * doc/rtl.texi (MEM_OFFSET_KNOWN_P): Document.
>        (MEM_OFFSET): Change from returning an rtx to returning a
>        HOST_WIDE_INT.
>        * rtl.h (MEM_OFFSET_KNOWN_P): New macro.
>        (MEM_OFFSET): Return a HOST_WIDE_INT rather than an rtx.
>        * emit-rtl.h (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_offset): Declare.
>        * alias.c (ao_ref_from_mem): Adjust uses of MEM_OFFSET, using
>        MEM_OFFSET_KNOWN_P to test whether the offset is known, and
>        MEM_OFFSET to get a HOST_WIDE_INT offset.
>        (nonoverlapping_memrefs_p): Likewise.  Adjust calls to...
>        (adjust_offset_for_component_ref): Take a bool "known_p"
>        parameter and a HOST_WIDE_INT "offset" parameter.
>        * builtins.c (get_memory_rtx): As for ao_ref_from_mem.
>        Adjust calls to set_mem_offset, passing a HOST_WIDE_INT rather
>        than an rtx.  Use clear_mem_offset to clear the offset.
>        * cfgcleanup.c (merge_memattrs): Likewise.
>        * dwarf2out.c (tls_mem_loc_descriptor): Likewise.
>        * function.c (assign_parm_find_stack_rtl): Likewise.
>        (assign_parm_setup_stack): Likewise.
>        * print-rtl.c (print_rtx): Likewise.
>        * reload.c (find_reloads_subreg_address): Likewise.
>        * simplify-rtx.c (delegitimize_mem_from_attrs): Likewise.
>        * var-tracking.c (INT_MEM_OFFSET): Likewise.
>        * emit-rtl.c (set_reg_attrs_from_value): Likewise.
>        (get_mem_align_offset): Likewise.
>        (set_mem_offset): Take a HOST_WIDE_INT rather than an rtx.
>        (clear_mem_offset): New function.
>        * config/mips/mips.c (r10k_safe_mem_expr_p): Take a HOST_WIDE_INT
>        offset rather than an rtx.  Assume both the expressio and offset
>        are available.
>        (r10k_needs_protection_p_1): Update accordingly, checking the
>        expression and offset availability here instead.
>
> Index: gcc/doc/rtl.texi
> ===================================================================
> --- gcc/doc/rtl.texi    2011-07-17 10:53:19.000000000 +0100
> +++ gcc/doc/rtl.texi    2011-07-17 10:54:22.000000000 +0100
> @@ -409,9 +409,15 @@ and @code{TREE_OPERAND (@var{x}, 0)} con
>  or another @code{COMPONENT_REF}, or null if there is no compile-time
>  object associated with the reference.
>
> +@findex MEM_OFFSET_KNOWN_P
> +@item MEM_OFFSET_KNOWN_P (@var{x})
> +True if the offset of the memory reference from @code{MEM_EXPR} is known.
> +@samp{MEM_OFFSET (@var{x})} provides the offset if so.
> +
>  @findex MEM_OFFSET
>  @item MEM_OFFSET (@var{x})
> -The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
> +The offset from the start of @code{MEM_EXPR}.  The value is only valid if
> +@samp{MEM_OFFSET_KNOWN_P (@var{x})} is true.
>
>  @findex MEM_SIZE_KNOWN_P
>  @item MEM_SIZE_KNOWN_P (@var{x})
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h   2011-07-17 10:18:59.000000000 +0100
> +++ gcc/rtl.h   2011-07-17 10:38:53.000000000 +0100
> @@ -1302,9 +1302,11 @@ #define MEM_ALIAS_SET(RTX) (get_mem_attr
>    refer to part of a DECL.  It may also be a COMPONENT_REF.  */
>  #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
>
> -/* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
> -   RTX that is always a CONST_INT.  */
> -#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
> +/* For a MEM rtx, true if its MEM_OFFSET is known.  */
> +#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
> +
> +/* For a MEM rtx, the offset from the start of MEM_EXPR.  */
> +#define MEM_OFFSET(RTX) INTVAL (get_mem_attrs (RTX)->offset)
>
>  /* For a MEM rtx, the address space.  */
>  #define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
> Index: gcc/emit-rtl.h
> ===================================================================
> --- gcc/emit-rtl.h      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/emit-rtl.h      2011-07-17 10:38:53.000000000 +0100
> @@ -33,7 +33,10 @@ extern void set_mem_addr_space (rtx, add
>  extern void set_mem_expr (rtx, tree);
>
>  /* Set the offset for MEM to OFFSET.  */
> -extern void set_mem_offset (rtx, rtx);
> +extern void set_mem_offset (rtx, HOST_WIDE_INT);
> +
> +/* Clear the offset recorded for MEM.  */
> +extern void clear_mem_offset (rtx);
>
>  /* Set the size for MEM to SIZE.  */
>  extern void set_mem_size (rtx, HOST_WIDE_INT);
> Index: gcc/alias.c
> ===================================================================
> --- gcc/alias.c 2011-07-17 10:18:59.000000000 +0100
> +++ gcc/alias.c 2011-07-17 10:43:20.000000000 +0100
> @@ -162,7 +162,6 @@ static const_rtx fixed_scalar_and_varyin
>  static int aliases_everything_p (const_rtx);
>  static bool nonoverlapping_component_refs_p (const_tree, const_tree);
>  static tree decl_for_component_ref (tree);
> -static rtx adjust_offset_for_component_ref (tree, rtx);
>  static int write_dependence_p (const_rtx, const_rtx, int);
>
>  static void memory_modified_1 (rtx, const_rtx, void *);
> @@ -315,7 +314,7 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>
>   /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
>      Keep points-to related information though.  */
> -  if (!MEM_OFFSET (mem)
> +  if (!MEM_OFFSET_KNOWN_P (mem)
>       || !MEM_SIZE_KNOWN_P (mem))
>     {
>       ref->ref = NULL_TREE;
> @@ -328,12 +327,11 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
>   /* If the base decl is a parameter we can have negative MEM_OFFSET in
>      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
>      here.  */
> -  if (INTVAL (MEM_OFFSET (mem)) < 0
> -      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
> -         * BITS_PER_UNIT) == ref->size)
> +  if (MEM_OFFSET (mem) < 0
> +      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
>     return true;
>
> -  ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
> +  ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
>   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
>
>   /* The MEM may extend into adjacent fields, so adjust max_size if
> @@ -2201,34 +2199,33 @@ decl_for_component_ref (tree x)
>   return x && DECL_P (x) ? x : NULL_TREE;
>  }
>
> -/* Walk up the COMPONENT_REF list and adjust OFFSET to compensate for the
> -   offset of the field reference.  */
> +/* Walk up the COMPONENT_REF list in X and adjust *OFFSET to compensate
> +   for the offset of the field reference.  *KNOWN_P says whether the
> +   offset is known.  */
>
> -static rtx
> -adjust_offset_for_component_ref (tree x, rtx offset)
> +static void
> +adjust_offset_for_component_ref (tree x, bool *known_p,
> +                                HOST_WIDE_INT *offset)
>  {
> -  HOST_WIDE_INT ioffset;
> -
> -  if (! offset)
> -    return NULL_RTX;
> -
> -  ioffset = INTVAL (offset);
> +  if (!*known_p)
> +    return;
>   do
>     {
> -      tree offset = component_ref_field_offset (x);
> +      tree xoffset = component_ref_field_offset (x);
>       tree field = TREE_OPERAND (x, 1);
>
> -      if (! host_integerp (offset, 1))
> -       return NULL_RTX;
> -      ioffset += (tree_low_cst (offset, 1)
> +      if (! host_integerp (xoffset, 1))
> +       {
> +         *known_p = false;
> +         return;
> +       }
> +      *offset += (tree_low_cst (xoffset, 1)
>                  + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
>                     / BITS_PER_UNIT));
>
>       x = TREE_OPERAND (x, 0);
>     }
>   while (x && TREE_CODE (x) == COMPONENT_REF);
> -
> -  return GEN_INT (ioffset);
>  }
>
>  /* Return nonzero if we can determine the exprs corresponding to memrefs
> @@ -2241,7 +2238,8 @@ nonoverlapping_memrefs_p (const_rtx x, c
>   tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
>   rtx rtlx, rtly;
>   rtx basex, basey;
> -  rtx moffsetx, moffsety;
> +  bool moffsetx_known_p, moffsety_known_p;
> +  HOST_WIDE_INT moffsetx = 0, moffsety = 0;
>   HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
>
>   /* Unless both have exprs, we can't tell anything.  */
> @@ -2250,9 +2248,9 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>   /* For spill-slot accesses make sure we have valid offsets.  */
>   if ((exprx == get_spill_slot_decl (false)
> -       && ! MEM_OFFSET (x))
> +       && ! MEM_OFFSET_KNOWN_P (x))
>       || (expry == get_spill_slot_decl (false)
> -         && ! MEM_OFFSET (y)))
> +         && ! MEM_OFFSET_KNOWN_P (y)))
>     return 0;
>
>   /* If both are field references, we may be able to determine something.  */
> @@ -2263,23 +2261,27 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>
>   /* If the field reference test failed, look at the DECLs involved.  */
> -  moffsetx = MEM_OFFSET (x);
> +  moffsetx_known_p = MEM_OFFSET_KNOWN_P (x);
> +  if (moffsetx_known_p)
> +    moffsetx = MEM_OFFSET (x);
>   if (TREE_CODE (exprx) == COMPONENT_REF)
>     {
>       tree t = decl_for_component_ref (exprx);
>       if (! t)
>        return 0;
> -      moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
> +      adjust_offset_for_component_ref (exprx, &moffsetx_known_p, &moffsetx);
>       exprx = t;
>     }
>
> -  moffsety = MEM_OFFSET (y);
> +  moffsety_known_p = MEM_OFFSET_KNOWN_P (y);
> +  if (moffsety_known_p)
> +    moffsety = MEM_OFFSET (y);
>   if (TREE_CODE (expry) == COMPONENT_REF)
>     {
>       tree t = decl_for_component_ref (expry);
>       if (! t)
>        return 0;
> -      moffsety = adjust_offset_for_component_ref (expry, moffsety);
> +      adjust_offset_for_component_ref (expry, &moffsety_known_p, &moffsety);
>       expry = t;
>     }
>
> @@ -2346,17 +2348,17 @@ nonoverlapping_memrefs_p (const_rtx x, c
>
>   /* If we have an offset for either memref, it can update the values computed
>      above.  */
> -  if (moffsetx)
> -    offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
> -  if (moffsety)
> -    offsety += INTVAL (moffsety), sizey -= INTVAL (moffsety);
> +  if (moffsetx_known_p)
> +    offsetx += moffsetx, sizex -= moffsetx;
> +  if (moffsety_known_p)
> +    offsety += moffsety, sizey -= moffsety;
>
>   /* If a memref has both a size and an offset, we can use the smaller size.
>      We can't do this if the offset isn't known because we must view this
>      memref as being anywhere inside the DECL's MEM.  */
> -  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
> +  if (MEM_SIZE_KNOWN_P (x) && moffsetx_known_p)
>     sizex = MEM_SIZE (x);
> -  if (MEM_SIZE_KNOWN_P (y) && moffsety)
> +  if (MEM_SIZE_KNOWN_P (y) && moffsety_known_p)
>     sizey = MEM_SIZE (y);
>
>   /* Put the values of the memref with the lower offset in X's values.  */
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/builtins.c      2011-07-17 10:38:53.000000000 +0100
> @@ -1238,9 +1238,8 @@ get_memory_rtx (tree exp, tree len)
>
>          gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
>
> -         if (MEM_OFFSET (mem)
> -             && CONST_INT_P (MEM_OFFSET (mem)))
> -           offset = INTVAL (MEM_OFFSET (mem));
> +         if (MEM_OFFSET_KNOWN_P (mem))
> +           offset = MEM_OFFSET (mem);
>
>          if (offset >= 0 && len && host_integerp (len, 0))
>            length = tree_low_cst (len, 0);
> @@ -1295,7 +1294,10 @@ get_memory_rtx (tree exp, tree len)
>          if (mem_expr != MEM_EXPR (mem))
>            {
>              set_mem_expr (mem, mem_expr);
> -             set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
> +             if (offset >= 0)
> +               set_mem_offset (mem, offset);
> +             else
> +               clear_mem_offset (mem);
>            }
>        }
>       set_mem_alias_set (mem, 0);
> Index: gcc/cfgcleanup.c
> ===================================================================
> --- gcc/cfgcleanup.c    2011-07-17 10:18:59.000000000 +0100
> +++ gcc/cfgcleanup.c    2011-07-17 10:38:53.000000000 +0100
> @@ -895,13 +895,15 @@ merge_memattrs (rtx x, rtx y)
>            {
>              set_mem_expr (x, 0);
>              set_mem_expr (y, 0);
> -             set_mem_offset (x, 0);
> -             set_mem_offset (y, 0);
> +             clear_mem_offset (x);
> +             clear_mem_offset (y);
>            }
> -         else if (MEM_OFFSET (x) != MEM_OFFSET (y))
> +         else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y)
> +                  || (MEM_OFFSET_KNOWN_P (x)
> +                      && MEM_OFFSET (x) != MEM_OFFSET (y)))
>            {
> -             set_mem_offset (x, 0);
> -             set_mem_offset (y, 0);
> +             clear_mem_offset (x);
> +             clear_mem_offset (y);
>            }
>
>          if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
> Index: gcc/dwarf2out.c
> ===================================================================
> --- gcc/dwarf2out.c     2011-07-17 10:18:59.000000000 +0100
> +++ gcc/dwarf2out.c     2011-07-17 10:38:53.000000000 +0100
> @@ -10453,7 +10453,7 @@ tls_mem_loc_descriptor (rtx mem)
>   tree base;
>   dw_loc_descr_ref loc_result;
>
> -  if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
> +  if (MEM_EXPR (mem) == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
>     return NULL;
>
>   base = get_base_address (MEM_EXPR (mem));
> @@ -10466,8 +10466,8 @@ tls_mem_loc_descriptor (rtx mem)
>   if (loc_result == NULL)
>     return NULL;
>
> -  if (INTVAL (MEM_OFFSET (mem)))
> -    loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
> +  if (MEM_OFFSET (mem))
> +    loc_descr_plus_const (&loc_result, MEM_OFFSET (mem));
>
>   return loc_result;
>  }
> Index: gcc/function.c
> ===================================================================
> --- gcc/function.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/function.c      2011-07-17 10:38:53.000000000 +0100
> @@ -2577,14 +2577,12 @@ assign_parm_find_stack_rtl (tree parm, s
>          && data->promoted_mode != DECL_MODE (parm))
>        {
>          set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
> -         if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
> +         if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
>            {
>              int offset = subreg_lowpart_offset (DECL_MODE (parm),
>                                                  data->promoted_mode);
>              if (offset)
> -               set_mem_offset (stack_parm,
> -                               plus_constant (MEM_OFFSET (stack_parm),
> -                                              -offset));
> +               set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
>            }
>        }
>     }
> @@ -3198,10 +3196,9 @@ assign_parm_setup_stack (struct assign_p
>          /* ??? This may need a big-endian conversion on sparc64.  */
>          data->stack_parm
>            = adjust_address (data->stack_parm, data->nominal_mode, 0);
> -         if (offset && MEM_OFFSET (data->stack_parm))
> +         if (offset && MEM_OFFSET_KNOWN_P (data->stack_parm))
>            set_mem_offset (data->stack_parm,
> -                           plus_constant (MEM_OFFSET (data->stack_parm),
> -                                          offset));
> +                           MEM_OFFSET (data->stack_parm) + offset);
>        }
>     }
>
> Index: gcc/print-rtl.c
> ===================================================================
> --- gcc/print-rtl.c     2011-07-17 10:18:59.000000000 +0100
> +++ gcc/print-rtl.c     2011-07-17 10:38:53.000000000 +0100
> @@ -597,9 +597,8 @@ print_rtx (const_rtx in_rtx)
>       if (MEM_EXPR (in_rtx))
>        print_mem_expr (outfile, MEM_EXPR (in_rtx));
>
> -      if (MEM_OFFSET (in_rtx))
> -       fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
> -                INTVAL (MEM_OFFSET (in_rtx)));
> +      if (MEM_OFFSET_KNOWN_P (in_rtx))
> +       fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
>
>       if (MEM_SIZE_KNOWN_P (in_rtx))
>        fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
> Index: gcc/reload.c
> ===================================================================
> --- gcc/reload.c        2011-07-17 10:18:59.000000000 +0100
> +++ gcc/reload.c        2011-07-17 10:38:53.000000000 +0100
> @@ -6137,8 +6137,8 @@ find_reloads_subreg_address (rtx x, int
>
>              XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
>              PUT_MODE (tem, GET_MODE (x));
> -             if (MEM_OFFSET (tem))
> -               set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
> +             if (MEM_OFFSET_KNOWN_P (tem))
> +               set_mem_offset (tem, MEM_OFFSET (tem) + offset);
>              if (MEM_SIZE_KNOWN_P (tem)
>                  && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
>                set_mem_size (tem, outer_size);
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c  2011-07-17 10:03:00.000000000 +0100
> +++ gcc/simplify-rtx.c  2011-07-17 10:38:53.000000000 +0100
> @@ -268,7 +268,7 @@ delegitimize_mem_from_attrs (rtx x)
>      use their base addresses as equivalent.  */
>   if (MEM_P (x)
>       && MEM_EXPR (x)
> -      && MEM_OFFSET (x))
> +      && MEM_OFFSET_KNOWN_P (x))
>     {
>       tree decl = MEM_EXPR (x);
>       enum machine_mode mode = GET_MODE (x);
> @@ -321,7 +321,7 @@ delegitimize_mem_from_attrs (rtx x)
>        {
>          rtx newx;
>
> -         offset += INTVAL (MEM_OFFSET (x));
> +         offset += MEM_OFFSET (x);
>
>          newx = DECL_RTL (decl);
>
> Index: gcc/var-tracking.c
> ===================================================================
> --- gcc/var-tracking.c  2011-07-17 10:18:59.000000000 +0100
> +++ gcc/var-tracking.c  2011-07-17 10:38:53.000000000 +0100
> @@ -365,7 +365,7 @@ typedef const struct value_chain_def *co
>  #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 (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
> +#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
>
>  /* Alloc pool for struct attrs_def.  */
>  static alloc_pool attrs_pool;
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/emit-rtl.c      2011-07-17 10:38:53.000000000 +0100
> @@ -969,9 +969,9 @@ set_reg_attrs_from_value (rtx reg, rtx x
>   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
>   if (MEM_P (x))
>     {
> -      if (MEM_OFFSET (x) && CONST_INT_P (MEM_OFFSET (x)))
> -       REG_ATTRS (reg)
> -         = get_reg_attrs (MEM_EXPR (x), INTVAL (MEM_OFFSET (x)) + offset);
> +      if (MEM_OFFSET_KNOWN_P (x))
> +       REG_ATTRS (reg) = get_reg_attrs (MEM_EXPR (x),
> +                                        MEM_OFFSET (x) + offset);
>       if (MEM_POINTER (x))
>        mark_reg_pointer (reg, 0);
>     }
> @@ -1460,14 +1460,13 @@ get_mem_align_offset (rtx mem, unsigned
>   unsigned HOST_WIDE_INT offset;
>
>   /* This function can't use
> -     if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
> -        || !CONST_INT_P (MEM_OFFSET (mem))
> +     if (!MEM_EXPR (mem) || !MEM_OFFSET_KNOWN_P (mem)
>         || (MAX (MEM_ALIGN (mem),
>                  get_object_alignment (MEM_EXPR (mem), align))
>             < align))
>        return -1;
>      else
> -       return (- INTVAL (MEM_OFFSET (mem))) & (align / BITS_PER_UNIT - 1);
> +       return (- MEM_OFFSET (mem)) & (align / BITS_PER_UNIT - 1);
>      for two reasons:
>      - COMPONENT_REFs in MEM_EXPR can have NULL first operand,
>        for <variable>.  get_inner_reference doesn't handle it and
> @@ -1477,12 +1476,10 @@ get_mem_align_offset (rtx mem, unsigned
>        isn't sufficiently aligned, the object it is in might be.  */
>   gcc_assert (MEM_P (mem));
>   expr = MEM_EXPR (mem);
> -  if (expr == NULL_TREE
> -      || MEM_OFFSET (mem) == NULL_RTX
> -      || !CONST_INT_P (MEM_OFFSET (mem)))
> +  if (expr == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
>     return -1;
>
> -  offset = INTVAL (MEM_OFFSET (mem));
> +  offset = MEM_OFFSET (mem);
>   if (DECL_P (expr))
>     {
>       if (DECL_ALIGN (expr) < align)
> @@ -1901,12 +1898,24 @@ set_mem_expr (rtx mem, tree expr)
>  /* Set the offset of MEM to OFFSET.  */
>
>  void
> -set_mem_offset (rtx mem, rtx offset)
> +set_mem_offset (rtx mem, HOST_WIDE_INT offset)
>  {
>   struct mem_attrs attrs;
>
>   attrs = *get_mem_attrs (mem);
> -  attrs.offset = offset;
> +  attrs.offset = GEN_INT (offset);
> +  set_mem_attrs (mem, &attrs);
> +}
> +
> +/* Clear the offset of MEM.  */
> +
> +void
> +clear_mem_offset (rtx mem)
> +{
> +  struct mem_attrs attrs;
> +
> +  attrs = *get_mem_attrs (mem);
> +  attrs.offset = NULL_RTX;
>   set_mem_attrs (mem, &attrs);
>  }
>
> Index: gcc/config/mips/mips.c
> ===================================================================
> --- gcc/config/mips/mips.c      2011-07-17 10:18:59.000000000 +0100
> +++ gcc/config/mips/mips.c      2011-07-17 10:38:53.000000000 +0100
> @@ -13777,13 +13777,9 @@ r10k_safe_address_p (rtx x, rtx insn)
>    a link-time-constant address.  */
>
>  static bool
> -r10k_safe_mem_expr_p (tree expr, rtx offset)
> +r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
>  {
> -  if (expr == NULL_TREE
> -      || offset == NULL_RTX
> -      || !CONST_INT_P (offset)
> -      || INTVAL (offset) < 0
> -      || INTVAL (offset) >= int_size_in_bytes (TREE_TYPE (expr)))
> +  if (offset < 0 || offset >= int_size_in_bytes (TREE_TYPE (expr)))
>     return false;
>
>   while (TREE_CODE (expr) == COMPONENT_REF)
> @@ -13809,7 +13805,9 @@ r10k_needs_protection_p_1 (rtx *loc, voi
>   if (!MEM_P (mem))
>     return 0;
>
> -  if (r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
> +  if (MEM_EXPR (mem)
> +      && MEM_OFFSET_KNOWN_P (mem)
> +      && r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
>     return -1;
>
>   if (r10k_safe_address_p (XEXP (mem, 0), (rtx) data))
>

Patch

Index: gcc/doc/rtl.texi
===================================================================
--- gcc/doc/rtl.texi	2011-07-17 10:53:19.000000000 +0100
+++ gcc/doc/rtl.texi	2011-07-17 10:54:22.000000000 +0100
@@ -409,9 +409,15 @@  and @code{TREE_OPERAND (@var{x}, 0)} con
 or another @code{COMPONENT_REF}, or null if there is no compile-time
 object associated with the reference.
 
+@findex MEM_OFFSET_KNOWN_P
+@item MEM_OFFSET_KNOWN_P (@var{x})
+True if the offset of the memory reference from @code{MEM_EXPR} is known.
+@samp{MEM_OFFSET (@var{x})} provides the offset if so.
+
 @findex MEM_OFFSET
 @item MEM_OFFSET (@var{x})
-The offset from the start of @code{MEM_EXPR} as a @code{CONST_INT} rtx.
+The offset from the start of @code{MEM_EXPR}.  The value is only valid if
+@samp{MEM_OFFSET_KNOWN_P (@var{x})} is true.
 
 @findex MEM_SIZE_KNOWN_P
 @item MEM_SIZE_KNOWN_P (@var{x})
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2011-07-17 10:18:59.000000000 +0100
+++ gcc/rtl.h	2011-07-17 10:38:53.000000000 +0100
@@ -1302,9 +1302,11 @@  #define MEM_ALIAS_SET(RTX) (get_mem_attr
    refer to part of a DECL.  It may also be a COMPONENT_REF.  */
 #define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
 
-/* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
-   RTX that is always a CONST_INT.  */
-#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
+/* For a MEM rtx, true if its MEM_OFFSET is known.  */
+#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset != NULL_RTX)
+
+/* For a MEM rtx, the offset from the start of MEM_EXPR.  */
+#define MEM_OFFSET(RTX) INTVAL (get_mem_attrs (RTX)->offset)
 
 /* For a MEM rtx, the address space.  */
 #define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
Index: gcc/emit-rtl.h
===================================================================
--- gcc/emit-rtl.h	2011-07-17 10:18:59.000000000 +0100
+++ gcc/emit-rtl.h	2011-07-17 10:38:53.000000000 +0100
@@ -33,7 +33,10 @@  extern void set_mem_addr_space (rtx, add
 extern void set_mem_expr (rtx, tree);
 
 /* Set the offset for MEM to OFFSET.  */
-extern void set_mem_offset (rtx, rtx);
+extern void set_mem_offset (rtx, HOST_WIDE_INT);
+
+/* Clear the offset recorded for MEM.  */
+extern void clear_mem_offset (rtx);
 
 /* Set the size for MEM to SIZE.  */
 extern void set_mem_size (rtx, HOST_WIDE_INT);
Index: gcc/alias.c
===================================================================
--- gcc/alias.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/alias.c	2011-07-17 10:43:20.000000000 +0100
@@ -162,7 +162,6 @@  static const_rtx fixed_scalar_and_varyin
 static int aliases_everything_p (const_rtx);
 static bool nonoverlapping_component_refs_p (const_tree, const_tree);
 static tree decl_for_component_ref (tree);
-static rtx adjust_offset_for_component_ref (tree, rtx);
 static int write_dependence_p (const_rtx, const_rtx, int);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
@@ -315,7 +314,7 @@  ao_ref_from_mem (ao_ref *ref, const_rtx
 
   /* If MEM_OFFSET or MEM_SIZE are unknown we have to punt.
      Keep points-to related information though.  */
-  if (!MEM_OFFSET (mem)
+  if (!MEM_OFFSET_KNOWN_P (mem)
       || !MEM_SIZE_KNOWN_P (mem))
     {
       ref->ref = NULL_TREE;
@@ -328,12 +327,11 @@  ao_ref_from_mem (ao_ref *ref, const_rtx
   /* If the base decl is a parameter we can have negative MEM_OFFSET in
      case of promoted subregs on bigendian targets.  Trust the MEM_EXPR
      here.  */
-  if (INTVAL (MEM_OFFSET (mem)) < 0
-      && ((MEM_SIZE (mem) + INTVAL (MEM_OFFSET (mem)))
-	  * BITS_PER_UNIT) == ref->size)
+  if (MEM_OFFSET (mem) < 0
+      && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size)
     return true;
 
-  ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT;
+  ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT;
   ref->size = MEM_SIZE (mem) * BITS_PER_UNIT;
 
   /* The MEM may extend into adjacent fields, so adjust max_size if
@@ -2201,34 +2199,33 @@  decl_for_component_ref (tree x)
   return x && DECL_P (x) ? x : NULL_TREE;
 }
 
-/* Walk up the COMPONENT_REF list and adjust OFFSET to compensate for the
-   offset of the field reference.  */
+/* Walk up the COMPONENT_REF list in X and adjust *OFFSET to compensate
+   for the offset of the field reference.  *KNOWN_P says whether the
+   offset is known.  */
 
-static rtx
-adjust_offset_for_component_ref (tree x, rtx offset)
+static void
+adjust_offset_for_component_ref (tree x, bool *known_p,
+				 HOST_WIDE_INT *offset)
 {
-  HOST_WIDE_INT ioffset;
-
-  if (! offset)
-    return NULL_RTX;
-
-  ioffset = INTVAL (offset);
+  if (!*known_p)
+    return;
   do
     {
-      tree offset = component_ref_field_offset (x);
+      tree xoffset = component_ref_field_offset (x);
       tree field = TREE_OPERAND (x, 1);
 
-      if (! host_integerp (offset, 1))
-	return NULL_RTX;
-      ioffset += (tree_low_cst (offset, 1)
+      if (! host_integerp (xoffset, 1))
+	{
+	  *known_p = false;
+	  return;
+	}
+      *offset += (tree_low_cst (xoffset, 1)
 		  + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 		     / BITS_PER_UNIT));
 
       x = TREE_OPERAND (x, 0);
     }
   while (x && TREE_CODE (x) == COMPONENT_REF);
-
-  return GEN_INT (ioffset);
 }
 
 /* Return nonzero if we can determine the exprs corresponding to memrefs
@@ -2241,7 +2238,8 @@  nonoverlapping_memrefs_p (const_rtx x, c
   tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
   rtx rtlx, rtly;
   rtx basex, basey;
-  rtx moffsetx, moffsety;
+  bool moffsetx_known_p, moffsety_known_p;
+  HOST_WIDE_INT moffsetx = 0, moffsety = 0;
   HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
 
   /* Unless both have exprs, we can't tell anything.  */
@@ -2250,9 +2248,9 @@  nonoverlapping_memrefs_p (const_rtx x, c
 
   /* For spill-slot accesses make sure we have valid offsets.  */
   if ((exprx == get_spill_slot_decl (false)
-       && ! MEM_OFFSET (x))
+       && ! MEM_OFFSET_KNOWN_P (x))
       || (expry == get_spill_slot_decl (false)
-	  && ! MEM_OFFSET (y)))
+	  && ! MEM_OFFSET_KNOWN_P (y)))
     return 0;
 
   /* If both are field references, we may be able to determine something.  */
@@ -2263,23 +2261,27 @@  nonoverlapping_memrefs_p (const_rtx x, c
 
 
   /* If the field reference test failed, look at the DECLs involved.  */
-  moffsetx = MEM_OFFSET (x);
+  moffsetx_known_p = MEM_OFFSET_KNOWN_P (x);
+  if (moffsetx_known_p)
+    moffsetx = MEM_OFFSET (x);
   if (TREE_CODE (exprx) == COMPONENT_REF)
     {
       tree t = decl_for_component_ref (exprx);
       if (! t)
 	return 0;
-      moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
+      adjust_offset_for_component_ref (exprx, &moffsetx_known_p, &moffsetx);
       exprx = t;
     }
 
-  moffsety = MEM_OFFSET (y);
+  moffsety_known_p = MEM_OFFSET_KNOWN_P (y);
+  if (moffsety_known_p)
+    moffsety = MEM_OFFSET (y);
   if (TREE_CODE (expry) == COMPONENT_REF)
     {
       tree t = decl_for_component_ref (expry);
       if (! t)
 	return 0;
-      moffsety = adjust_offset_for_component_ref (expry, moffsety);
+      adjust_offset_for_component_ref (expry, &moffsety_known_p, &moffsety);
       expry = t;
     }
 
@@ -2346,17 +2348,17 @@  nonoverlapping_memrefs_p (const_rtx x, c
 
   /* If we have an offset for either memref, it can update the values computed
      above.  */
-  if (moffsetx)
-    offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
-  if (moffsety)
-    offsety += INTVAL (moffsety), sizey -= INTVAL (moffsety);
+  if (moffsetx_known_p)
+    offsetx += moffsetx, sizex -= moffsetx;
+  if (moffsety_known_p)
+    offsety += moffsety, sizey -= moffsety;
 
   /* If a memref has both a size and an offset, we can use the smaller size.
      We can't do this if the offset isn't known because we must view this
      memref as being anywhere inside the DECL's MEM.  */
-  if (MEM_SIZE_KNOWN_P (x) && moffsetx)
+  if (MEM_SIZE_KNOWN_P (x) && moffsetx_known_p)
     sizex = MEM_SIZE (x);
-  if (MEM_SIZE_KNOWN_P (y) && moffsety)
+  if (MEM_SIZE_KNOWN_P (y) && moffsety_known_p)
     sizey = MEM_SIZE (y);
 
   /* Put the values of the memref with the lower offset in X's values.  */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/builtins.c	2011-07-17 10:38:53.000000000 +0100
@@ -1238,9 +1238,8 @@  get_memory_rtx (tree exp, tree len)
 
 	  gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
 
-	  if (MEM_OFFSET (mem)
-	      && CONST_INT_P (MEM_OFFSET (mem)))
-	    offset = INTVAL (MEM_OFFSET (mem));
+	  if (MEM_OFFSET_KNOWN_P (mem))
+	    offset = MEM_OFFSET (mem);
 
 	  if (offset >= 0 && len && host_integerp (len, 0))
 	    length = tree_low_cst (len, 0);
@@ -1295,7 +1294,10 @@  get_memory_rtx (tree exp, tree len)
 	  if (mem_expr != MEM_EXPR (mem))
 	    {
 	      set_mem_expr (mem, mem_expr);
-	      set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
+	      if (offset >= 0)
+		set_mem_offset (mem, offset);
+	      else
+		clear_mem_offset (mem);
 	    }
 	}
       set_mem_alias_set (mem, 0);
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/cfgcleanup.c	2011-07-17 10:38:53.000000000 +0100
@@ -895,13 +895,15 @@  merge_memattrs (rtx x, rtx y)
 	    {
 	      set_mem_expr (x, 0);
 	      set_mem_expr (y, 0);
-	      set_mem_offset (x, 0);
-	      set_mem_offset (y, 0);
+	      clear_mem_offset (x);
+	      clear_mem_offset (y);
 	    }
-	  else if (MEM_OFFSET (x) != MEM_OFFSET (y))
+	  else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y)
+		   || (MEM_OFFSET_KNOWN_P (x)
+		       && MEM_OFFSET (x) != MEM_OFFSET (y)))
 	    {
-	      set_mem_offset (x, 0);
-	      set_mem_offset (y, 0);
+	      clear_mem_offset (x);
+	      clear_mem_offset (y);
 	    }
 
 	  if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y))
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/dwarf2out.c	2011-07-17 10:38:53.000000000 +0100
@@ -10453,7 +10453,7 @@  tls_mem_loc_descriptor (rtx mem)
   tree base;
   dw_loc_descr_ref loc_result;
 
-  if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
+  if (MEM_EXPR (mem) == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
     return NULL;
 
   base = get_base_address (MEM_EXPR (mem));
@@ -10466,8 +10466,8 @@  tls_mem_loc_descriptor (rtx mem)
   if (loc_result == NULL)
     return NULL;
 
-  if (INTVAL (MEM_OFFSET (mem)))
-    loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
+  if (MEM_OFFSET (mem))
+    loc_descr_plus_const (&loc_result, MEM_OFFSET (mem));
 
   return loc_result;
 }
Index: gcc/function.c
===================================================================
--- gcc/function.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/function.c	2011-07-17 10:38:53.000000000 +0100
@@ -2577,14 +2577,12 @@  assign_parm_find_stack_rtl (tree parm, s
 	  && data->promoted_mode != DECL_MODE (parm))
 	{
 	  set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
-	  if (MEM_EXPR (stack_parm) && MEM_OFFSET (stack_parm))
+	  if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
 	    {
 	      int offset = subreg_lowpart_offset (DECL_MODE (parm),
 						  data->promoted_mode);
 	      if (offset)
-		set_mem_offset (stack_parm,
-				plus_constant (MEM_OFFSET (stack_parm),
-					       -offset));
+		set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
 	    }
 	}
     }
@@ -3198,10 +3196,9 @@  assign_parm_setup_stack (struct assign_p
 	  /* ??? This may need a big-endian conversion on sparc64.  */
 	  data->stack_parm
 	    = adjust_address (data->stack_parm, data->nominal_mode, 0);
-	  if (offset && MEM_OFFSET (data->stack_parm))
+	  if (offset && MEM_OFFSET_KNOWN_P (data->stack_parm))
 	    set_mem_offset (data->stack_parm,
-			    plus_constant (MEM_OFFSET (data->stack_parm),
-					   offset));
+			    MEM_OFFSET (data->stack_parm) + offset);
 	}
     }
 
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/print-rtl.c	2011-07-17 10:38:53.000000000 +0100
@@ -597,9 +597,8 @@  print_rtx (const_rtx in_rtx)
       if (MEM_EXPR (in_rtx))
 	print_mem_expr (outfile, MEM_EXPR (in_rtx));
 
-      if (MEM_OFFSET (in_rtx))
-	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
-		 INTVAL (MEM_OFFSET (in_rtx)));
+      if (MEM_OFFSET_KNOWN_P (in_rtx))
+	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
 
       if (MEM_SIZE_KNOWN_P (in_rtx))
 	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/reload.c	2011-07-17 10:38:53.000000000 +0100
@@ -6137,8 +6137,8 @@  find_reloads_subreg_address (rtx x, int
 
 	      XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
 	      PUT_MODE (tem, GET_MODE (x));
-	      if (MEM_OFFSET (tem))
-		set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
+	      if (MEM_OFFSET_KNOWN_P (tem))
+		set_mem_offset (tem, MEM_OFFSET (tem) + offset);
 	      if (MEM_SIZE_KNOWN_P (tem)
 		  && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
 		set_mem_size (tem, outer_size);
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	2011-07-17 10:03:00.000000000 +0100
+++ gcc/simplify-rtx.c	2011-07-17 10:38:53.000000000 +0100
@@ -268,7 +268,7 @@  delegitimize_mem_from_attrs (rtx x)
      use their base addresses as equivalent.  */
   if (MEM_P (x)
       && MEM_EXPR (x)
-      && MEM_OFFSET (x))
+      && MEM_OFFSET_KNOWN_P (x))
     {
       tree decl = MEM_EXPR (x);
       enum machine_mode mode = GET_MODE (x);
@@ -321,7 +321,7 @@  delegitimize_mem_from_attrs (rtx x)
 	{
 	  rtx newx;
 
-	  offset += INTVAL (MEM_OFFSET (x));
+	  offset += MEM_OFFSET (x);
 
 	  newx = DECL_RTL (decl);
 
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/var-tracking.c	2011-07-17 10:38:53.000000000 +0100
@@ -365,7 +365,7 @@  typedef const struct value_chain_def *co
 #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 (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
+#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
 
 /* Alloc pool for struct attrs_def.  */
 static alloc_pool attrs_pool;
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/emit-rtl.c	2011-07-17 10:38:53.000000000 +0100
@@ -969,9 +969,9 @@  set_reg_attrs_from_value (rtx reg, rtx x
   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
   if (MEM_P (x))
     {
-      if (MEM_OFFSET (x) && CONST_INT_P (MEM_OFFSET (x)))
-	REG_ATTRS (reg)
-	  = get_reg_attrs (MEM_EXPR (x), INTVAL (MEM_OFFSET (x)) + offset);
+      if (MEM_OFFSET_KNOWN_P (x))
+	REG_ATTRS (reg) = get_reg_attrs (MEM_EXPR (x),
+					 MEM_OFFSET (x) + offset);
       if (MEM_POINTER (x))
 	mark_reg_pointer (reg, 0);
     }
@@ -1460,14 +1460,13 @@  get_mem_align_offset (rtx mem, unsigned
   unsigned HOST_WIDE_INT offset;
 
   /* This function can't use
-     if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
-	 || !CONST_INT_P (MEM_OFFSET (mem))
+     if (!MEM_EXPR (mem) || !MEM_OFFSET_KNOWN_P (mem)
 	 || (MAX (MEM_ALIGN (mem),
 	          get_object_alignment (MEM_EXPR (mem), align))
 	     < align))
        return -1;
      else
-       return (- INTVAL (MEM_OFFSET (mem))) & (align / BITS_PER_UNIT - 1);
+       return (- MEM_OFFSET (mem)) & (align / BITS_PER_UNIT - 1);
      for two reasons:
      - COMPONENT_REFs in MEM_EXPR can have NULL first operand,
        for <variable>.  get_inner_reference doesn't handle it and
@@ -1477,12 +1476,10 @@  get_mem_align_offset (rtx mem, unsigned
        isn't sufficiently aligned, the object it is in might be.  */
   gcc_assert (MEM_P (mem));
   expr = MEM_EXPR (mem);
-  if (expr == NULL_TREE
-      || MEM_OFFSET (mem) == NULL_RTX
-      || !CONST_INT_P (MEM_OFFSET (mem)))
+  if (expr == NULL_TREE || !MEM_OFFSET_KNOWN_P (mem))
     return -1;
 
-  offset = INTVAL (MEM_OFFSET (mem));
+  offset = MEM_OFFSET (mem);
   if (DECL_P (expr))
     {
       if (DECL_ALIGN (expr) < align)
@@ -1901,12 +1898,24 @@  set_mem_expr (rtx mem, tree expr)
 /* Set the offset of MEM to OFFSET.  */
 
 void
-set_mem_offset (rtx mem, rtx offset)
+set_mem_offset (rtx mem, HOST_WIDE_INT offset)
 {
   struct mem_attrs attrs;
 
   attrs = *get_mem_attrs (mem);
-  attrs.offset = offset;
+  attrs.offset = GEN_INT (offset);
+  set_mem_attrs (mem, &attrs);
+}
+
+/* Clear the offset of MEM.  */
+
+void
+clear_mem_offset (rtx mem)
+{
+  struct mem_attrs attrs;
+
+  attrs = *get_mem_attrs (mem);
+  attrs.offset = NULL_RTX;
   set_mem_attrs (mem, &attrs);
 }
 
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2011-07-17 10:18:59.000000000 +0100
+++ gcc/config/mips/mips.c	2011-07-17 10:38:53.000000000 +0100
@@ -13777,13 +13777,9 @@  r10k_safe_address_p (rtx x, rtx insn)
    a link-time-constant address.  */
 
 static bool
-r10k_safe_mem_expr_p (tree expr, rtx offset)
+r10k_safe_mem_expr_p (tree expr, HOST_WIDE_INT offset)
 {
-  if (expr == NULL_TREE
-      || offset == NULL_RTX
-      || !CONST_INT_P (offset)
-      || INTVAL (offset) < 0
-      || INTVAL (offset) >= int_size_in_bytes (TREE_TYPE (expr)))
+  if (offset < 0 || offset >= int_size_in_bytes (TREE_TYPE (expr)))
     return false;
 
   while (TREE_CODE (expr) == COMPONENT_REF)
@@ -13809,7 +13805,9 @@  r10k_needs_protection_p_1 (rtx *loc, voi
   if (!MEM_P (mem))
     return 0;
 
-  if (r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
+  if (MEM_EXPR (mem)
+      && MEM_OFFSET_KNOWN_P (mem)
+      && r10k_safe_mem_expr_p (MEM_EXPR (mem), MEM_OFFSET (mem)))
     return -1;
 
   if (r10k_safe_address_p (XEXP (mem, 0), (rtx) data))