rtl.texi (MEM_OFFSET_KNOWN_P): Document.

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.

From-SVN: r176477
This commit is contained in:
Richard Sandiford 2011-07-19 17:43:27 +00:00 committed by Richard Sandiford
parent f5541398ef
commit 527210c448
15 changed files with 142 additions and 86 deletions

View File

@ -1,3 +1,39 @@
2011-07-19 Richard Sandiford <rdsandiford@googlemail.com>
* 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.
2011-07-19 Richard Sandiford <rdsandiford@googlemail.com>
* doc/rtl.texi (MEM_SIZE_KNOWN_P): Document.

View File

@ -162,7 +162,6 @@ static const_rtx fixed_scalar_and_varying_struct_p (const_rtx, const_rtx, rtx, r
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 mem)
/* 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 mem)
/* 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, const_rtx y, bool loop_invariant)
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, const_rtx y, bool loop_invariant)
/* 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, const_rtx y, bool loop_invariant)
/* 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, const_rtx y, bool loop_invariant)
/* 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. */

View File

@ -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);

View File

@ -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))

View File

@ -13765,13 +13765,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)
@ -13797,7 +13793,9 @@ r10k_needs_protection_p_1 (rtx *loc, void *data)
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))

View File

@ -409,9 +409,15 @@ and @code{TREE_OPERAND (@var{x}, 0)} contains the declaration,
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})

View File

@ -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;
}

View File

@ -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 int align)
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 int align)
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);
}

View File

@ -33,7 +33,10 @@ extern void set_mem_addr_space (rtx, addr_space_t);
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);

View File

@ -2577,14 +2577,12 @@ assign_parm_find_stack_rtl (tree parm, struct assign_parm_data_one *data)
&& 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_parm_data_all *all, tree parm,
/* ??? 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);
}
}

View File

@ -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));

View File

@ -6137,8 +6137,8 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
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);

View File

@ -1302,9 +1302,11 @@ do { \
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)

View File

@ -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);

View File

@ -365,7 +365,7 @@ typedef const struct value_chain_def *const_value_chain;
#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;