rtl.h (mem_attrs): Rename decl to expr; adjust all users.
* rtl.h (mem_attrs): Rename decl to expr; adjust all users. (MEM_EXPR): Rename from MEM_DECL; adjust all users. * emit-rtl.c (set_mem_expr): Rename from set_mem_decl. * expr.h, final.c, reload1.c: Adjust users. * alias.c (nonoverlapping_component_refs_p): New. (decl_for_component_ref, adjust_offset_for_component_ref): New. (nonoverlapping_memrefs_p): Use them. * emit-rtl.c (component_ref_for_mem_expr): New. (set_mem_attributes): Use it. (set_mem_offset): New. * expr.c (expand_assignment): Call set_mem_attributes for inner references; adjust the memory offset as needed. * print-rtl.c (print_mem_expr): New. (print_rtx): Use it. From-SVN: r47534
This commit is contained in:
parent
3d55d21291
commit
998d7deb14
@ -1,3 +1,21 @@
|
||||
2001-12-02 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* rtl.h (mem_attrs): Rename decl to expr; adjust all users.
|
||||
(MEM_EXPR): Rename from MEM_DECL; adjust all users.
|
||||
* emit-rtl.c (set_mem_expr): Rename from set_mem_decl.
|
||||
* expr.h, final.c, reload1.c: Adjust users.
|
||||
|
||||
* alias.c (nonoverlapping_component_refs_p): New.
|
||||
(decl_for_component_ref, adjust_offset_for_component_ref): New.
|
||||
(nonoverlapping_memrefs_p): Use them.
|
||||
* emit-rtl.c (component_ref_for_mem_expr): New.
|
||||
(set_mem_attributes): Use it.
|
||||
(set_mem_offset): New.
|
||||
* expr.c (expand_assignment): Call set_mem_attributes for
|
||||
inner references; adjust the memory offset as needed.
|
||||
* print-rtl.c (print_mem_expr): New.
|
||||
(print_rtx): Use it.
|
||||
|
||||
Sun Dec 2 09:22:25 2001 Douglas B. Rupp <rupp@gnat.com>
|
||||
|
||||
* config/x-interix3 (SYSTEM_HEADER_DIR): Put back default.
|
||||
|
164
gcc/alias.c
164
gcc/alias.c
@ -103,6 +103,9 @@ static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT));
|
||||
static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
|
||||
int (*) (rtx, int)));
|
||||
static int aliases_everything_p PARAMS ((rtx));
|
||||
static bool nonoverlapping_component_refs_p PARAMS ((tree, tree));
|
||||
static tree decl_for_component_ref PARAMS ((tree));
|
||||
static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx));
|
||||
static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx));
|
||||
static int write_dependence_p PARAMS ((rtx, rtx, int));
|
||||
static int nonlocal_mentioned_p PARAMS ((rtx));
|
||||
@ -1736,23 +1739,158 @@ aliases_everything_p (mem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if we can deterimine the decls corresponding to memrefs
|
||||
/* Return true if we can determine that the fields referenced cannot
|
||||
overlap for any pair of objects. */
|
||||
|
||||
static bool
|
||||
nonoverlapping_component_refs_p (x, y)
|
||||
tree x, y;
|
||||
{
|
||||
tree fieldx, fieldy, typex, typey, orig_y;
|
||||
|
||||
do
|
||||
{
|
||||
/* The comparison has to be done at a common type, since we don't
|
||||
know how the inheritance heirarchy works. */
|
||||
orig_y = y;
|
||||
do
|
||||
{
|
||||
fieldx = TREE_OPERAND (x, 1);
|
||||
typex = DECL_FIELD_CONTEXT (fieldx);
|
||||
|
||||
y = orig_y;
|
||||
do
|
||||
{
|
||||
fieldy = TREE_OPERAND (y, 1);
|
||||
typey = DECL_FIELD_CONTEXT (fieldy);
|
||||
|
||||
if (typex == typey)
|
||||
goto found;
|
||||
|
||||
y = TREE_OPERAND (y, 0);
|
||||
}
|
||||
while (y && TREE_CODE (y) == COMPONENT_REF);
|
||||
|
||||
x = TREE_OPERAND (x, 0);
|
||||
}
|
||||
while (x && TREE_CODE (x) == COMPONENT_REF);
|
||||
|
||||
/* Never found a common type. */
|
||||
return false;
|
||||
|
||||
found:
|
||||
/* If we're left with accessing different fields of a structure,
|
||||
then no overlap. */
|
||||
if (TREE_CODE (typex) == RECORD_TYPE
|
||||
&& fieldx != fieldy)
|
||||
return true;
|
||||
|
||||
/* The comparison on the current field failed. If we're accessing
|
||||
a very nested structure, look at the next outer level. */
|
||||
x = TREE_OPERAND (x, 0);
|
||||
y = TREE_OPERAND (y, 0);
|
||||
}
|
||||
while (x && y
|
||||
&& TREE_CODE (x) == COMPONENT_REF
|
||||
&& TREE_CODE (y) == COMPONENT_REF);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Look at the bottom of the COMPONENT_REF list for a DECL, and return it. */
|
||||
|
||||
static tree
|
||||
decl_for_component_ref (x)
|
||||
tree x;
|
||||
{
|
||||
do
|
||||
{
|
||||
x = TREE_OPERAND (x, 0);
|
||||
}
|
||||
while (x && TREE_CODE (x) == COMPONENT_REF);
|
||||
|
||||
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. */
|
||||
|
||||
static rtx
|
||||
adjust_offset_for_component_ref (x, offset)
|
||||
tree x;
|
||||
rtx offset;
|
||||
{
|
||||
HOST_WIDE_INT ioffset;
|
||||
|
||||
if (! offset)
|
||||
return NULL_RTX;
|
||||
|
||||
ioffset = INTVAL (offset);
|
||||
do
|
||||
{
|
||||
tree field = TREE_OPERAND (x, 1);
|
||||
|
||||
if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
|
||||
return NULL_RTX;
|
||||
ioffset += (tree_low_cst (DECL_FIELD_OFFSET (field), 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 deterimine the exprs corresponding to memrefs
|
||||
X and Y and they do not overlap. */
|
||||
|
||||
static int
|
||||
nonoverlapping_memrefs_p (x, y)
|
||||
rtx x, y;
|
||||
{
|
||||
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
|
||||
rtx rtlx, rtly;
|
||||
rtx basex, basey;
|
||||
rtx moffsetx, moffsety;
|
||||
HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
|
||||
|
||||
/* Unless both have decls, we can't tell anything. */
|
||||
if (MEM_DECL (x) == 0 || MEM_DECL (y) == 0)
|
||||
/* Unless both have exprs, we can't tell anything. */
|
||||
if (exprx == 0 || expry == 0)
|
||||
return 0;
|
||||
|
||||
rtlx = DECL_RTL (MEM_DECL (x));
|
||||
rtly = DECL_RTL (MEM_DECL (y));
|
||||
/* If both are field references, we may be able to determine something. */
|
||||
if (TREE_CODE (exprx) == COMPONENT_REF
|
||||
&& TREE_CODE (expry) == COMPONENT_REF
|
||||
&& nonoverlapping_component_refs_p (exprx, expry))
|
||||
return 1;
|
||||
|
||||
/* If the field reference test failed, look at the DECLs involved. */
|
||||
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);
|
||||
exprx = t;
|
||||
}
|
||||
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);
|
||||
expry = t;
|
||||
}
|
||||
|
||||
if (! DECL_P (exprx) || ! DECL_P (expry))
|
||||
return 0;
|
||||
|
||||
rtlx = DECL_RTL (exprx);
|
||||
rtly = DECL_RTL (expry);
|
||||
|
||||
/* If either RTL is not a MEM, it must be a REG or CONCAT, meaning they
|
||||
can't overlap unless they are the same because we never reuse that part
|
||||
@ -1784,26 +1922,26 @@ nonoverlapping_memrefs_p (x, y)
|
||||
|| (CONSTANT_P (basey) && REG_P (basex)
|
||||
&& REGNO_PTR_FRAME_P (REGNO (basex))));
|
||||
|
||||
sizex = (GET_CODE (rtlx) != MEM ? GET_MODE_SIZE (GET_MODE (rtlx))
|
||||
sizex = (GET_CODE (rtlx) != MEM ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
|
||||
: MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
|
||||
: -1);
|
||||
sizey = (GET_CODE (rtly) != MEM ? GET_MODE_SIZE (GET_MODE (rtly))
|
||||
sizey = (GET_CODE (rtly) != MEM ? (int) GET_MODE_SIZE (GET_MODE (rtly))
|
||||
: MEM_SIZE (rtly) ? INTVAL (MEM_SIZE (rtly)) :
|
||||
-1);
|
||||
|
||||
/* If we have an offset for either memref, it can update the values computed
|
||||
above. */
|
||||
if (MEM_OFFSET (x))
|
||||
offsetx += INTVAL (MEM_OFFSET (x)), sizex -= INTVAL (MEM_OFFSET (x));
|
||||
if (MEM_OFFSET (y))
|
||||
offsety += INTVAL (MEM_OFFSET (y)), sizey -= INTVAL (MEM_OFFSET (y));
|
||||
if (moffsetx)
|
||||
offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
|
||||
if (moffsety)
|
||||
offsety += INTVAL (moffsety), sizey -= INTVAL (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 (x) && MEM_OFFSET (x))
|
||||
if (MEM_SIZE (x) && moffsetx)
|
||||
sizex = INTVAL (MEM_SIZE (x));
|
||||
if (MEM_SIZE (y) && MEM_OFFSET (y))
|
||||
if (MEM_SIZE (y) && moffsety)
|
||||
sizey = INTVAL (MEM_SIZE (y));
|
||||
|
||||
/* Put the values of the memref with the lower offset in X's values. */
|
||||
|
112
gcc/emit-rtl.c
112
gcc/emit-rtl.c
@ -195,6 +195,7 @@ static void mem_attrs_mark PARAMS ((const void *));
|
||||
static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx,
|
||||
rtx, unsigned int,
|
||||
enum machine_mode));
|
||||
static tree component_ref_for_mem_expr PARAMS ((tree));
|
||||
|
||||
/* Probability of the conditional branch currently proceeded by try_split.
|
||||
Set to -1 otherwise. */
|
||||
@ -232,7 +233,7 @@ mem_attrs_htab_hash (x)
|
||||
return (p->alias ^ (p->align * 1000)
|
||||
^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
|
||||
^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
|
||||
^ (long) p->decl);
|
||||
^ (size_t) p->expr);
|
||||
}
|
||||
|
||||
/* Returns non-zero if the value represented by X (which is really a
|
||||
@ -247,7 +248,7 @@ mem_attrs_htab_eq (x, y)
|
||||
mem_attrs *p = (mem_attrs *) x;
|
||||
mem_attrs *q = (mem_attrs *) y;
|
||||
|
||||
return (p->alias == q->alias && p->decl == q->decl && p->offset == q->offset
|
||||
return (p->alias == q->alias && p->expr == q->expr && p->offset == q->offset
|
||||
&& p->size == q->size && p->align == q->align);
|
||||
}
|
||||
|
||||
@ -260,8 +261,8 @@ mem_attrs_mark (x)
|
||||
{
|
||||
mem_attrs *p = (mem_attrs *) x;
|
||||
|
||||
if (p->decl)
|
||||
ggc_mark_tree (p->decl);
|
||||
if (p->expr)
|
||||
ggc_mark_tree (p->expr);
|
||||
|
||||
if (p->offset)
|
||||
ggc_mark_rtx (p->offset);
|
||||
@ -275,9 +276,9 @@ mem_attrs_mark (x)
|
||||
MEM of mode MODE. */
|
||||
|
||||
static mem_attrs *
|
||||
get_mem_attrs (alias, decl, offset, size, align, mode)
|
||||
get_mem_attrs (alias, expr, offset, size, align, mode)
|
||||
HOST_WIDE_INT alias;
|
||||
tree decl;
|
||||
tree expr;
|
||||
rtx offset;
|
||||
rtx size;
|
||||
unsigned int align;
|
||||
@ -287,7 +288,7 @@ get_mem_attrs (alias, decl, offset, size, align, mode)
|
||||
void **slot;
|
||||
|
||||
/* If everything is the default, we can just return zero. */
|
||||
if (alias == 0 && decl == 0 && offset == 0
|
||||
if (alias == 0 && expr == 0 && offset == 0
|
||||
&& (size == 0
|
||||
|| (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
|
||||
&& (align == BITS_PER_UNIT
|
||||
@ -295,7 +296,7 @@ get_mem_attrs (alias, decl, offset, size, align, mode)
|
||||
return 0;
|
||||
|
||||
attrs.alias = alias;
|
||||
attrs.decl = decl;
|
||||
attrs.expr = expr;
|
||||
attrs.offset = offset;
|
||||
attrs.size = size;
|
||||
attrs.align = align;
|
||||
@ -1636,6 +1637,26 @@ reverse_comparison (insn)
|
||||
}
|
||||
}
|
||||
|
||||
/* Within a MEM_EXPR, we care about either (1) a component ref of a decl,
|
||||
or (2) a component ref of something variable. Represent the later with
|
||||
a NULL expression. */
|
||||
|
||||
static tree
|
||||
component_ref_for_mem_expr (ref)
|
||||
tree ref;
|
||||
{
|
||||
tree inner = TREE_OPERAND (ref, 0);
|
||||
|
||||
if (TREE_CODE (inner) == COMPONENT_REF)
|
||||
inner = component_ref_for_mem_expr (inner);
|
||||
else if (! DECL_P (inner))
|
||||
inner = NULL_TREE;
|
||||
|
||||
if (inner == TREE_OPERAND (ref, 0))
|
||||
return ref;
|
||||
else
|
||||
return build (COMPONENT_REF, TREE_TYPE (ref), inner, TREE_OPERAND (ref, 1));
|
||||
}
|
||||
|
||||
/* Given REF, a MEM, and T, either the type of X or the expression
|
||||
corresponding to REF, set the memory attributes. OBJECTP is nonzero
|
||||
@ -1648,7 +1669,7 @@ set_mem_attributes (ref, t, objectp)
|
||||
int objectp;
|
||||
{
|
||||
HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);
|
||||
tree decl = MEM_DECL (ref);
|
||||
tree expr = MEM_EXPR (ref);
|
||||
rtx offset = MEM_OFFSET (ref);
|
||||
rtx size = MEM_SIZE (ref);
|
||||
unsigned int align = MEM_ALIGN (ref);
|
||||
@ -1716,8 +1737,8 @@ set_mem_attributes (ref, t, objectp)
|
||||
/* If this is a decl, set the attributes of the MEM from it. */
|
||||
if (DECL_P (t))
|
||||
{
|
||||
decl = t;
|
||||
offset = GEN_INT (0);
|
||||
expr = t;
|
||||
offset = const0_rtx;
|
||||
size = (DECL_SIZE_UNIT (t)
|
||||
&& host_integerp (DECL_SIZE_UNIT (t), 1)
|
||||
? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
|
||||
@ -1732,11 +1753,51 @@ set_mem_attributes (ref, t, objectp)
|
||||
align = CONSTANT_ALIGNMENT (t, align);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If this is a field reference and not a bit-field, record it. */
|
||||
/* ??? There is some information that can be gleened from bit-fields,
|
||||
such as the word offset in the structure that might be modified.
|
||||
But skip it for now. */
|
||||
else if (TREE_CODE (t) == COMPONENT_REF
|
||||
&& ! DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
|
||||
{
|
||||
expr = component_ref_for_mem_expr (t);
|
||||
offset = const0_rtx;
|
||||
/* ??? Any reason the field size would be different than
|
||||
the size we got from the type? */
|
||||
}
|
||||
|
||||
/* If this is an array reference, look for an outer field reference. */
|
||||
else if (TREE_CODE (t) == ARRAY_REF)
|
||||
{
|
||||
tree off_tree = size_zero_node;
|
||||
|
||||
do
|
||||
{
|
||||
off_tree
|
||||
= fold (build (PLUS_EXPR, sizetype,
|
||||
fold (build (MULT_EXPR, sizetype,
|
||||
TREE_OPERAND (t, 1),
|
||||
TYPE_SIZE_UNIT (TREE_TYPE (t)))),
|
||||
off_tree));
|
||||
t = TREE_OPERAND (t, 0);
|
||||
}
|
||||
while (TREE_CODE (t) == ARRAY_REF);
|
||||
|
||||
if (TREE_CODE (t) == COMPONENT_REF)
|
||||
{
|
||||
expr = component_ref_for_mem_expr (t);
|
||||
if (host_integerp (off_tree, 1))
|
||||
offset = GEN_INT (tree_low_cst (off_tree, 1));
|
||||
/* ??? Any reason the field size would be different than
|
||||
the size we got from the type? */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the attributes we computed above. */
|
||||
MEM_ATTRS (ref)
|
||||
= get_mem_attrs (alias, decl, offset, size, align, GET_MODE (ref));
|
||||
= get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
|
||||
|
||||
/* If this is already known to be a scalar or aggregate, we are done. */
|
||||
if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
|
||||
@ -1763,7 +1824,7 @@ set_mem_alias_set (mem, set)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
|
||||
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
|
||||
MEM_SIZE (mem), MEM_ALIGN (mem),
|
||||
GET_MODE (mem));
|
||||
}
|
||||
@ -1775,22 +1836,33 @@ set_mem_align (mem, align)
|
||||
rtx mem;
|
||||
unsigned int align;
|
||||
{
|
||||
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_DECL (mem),
|
||||
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
|
||||
MEM_OFFSET (mem), MEM_SIZE (mem), align,
|
||||
GET_MODE (mem));
|
||||
}
|
||||
|
||||
/* Set the decl for MEM to DECL. */
|
||||
/* Set the expr for MEM to EXPR. */
|
||||
|
||||
void
|
||||
set_mem_decl (mem, decl)
|
||||
set_mem_expr (mem, expr)
|
||||
rtx mem;
|
||||
tree decl;
|
||||
tree expr;
|
||||
{
|
||||
MEM_ATTRS (mem)
|
||||
= get_mem_attrs (MEM_ALIAS_SET (mem), decl, MEM_OFFSET (mem),
|
||||
= get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
|
||||
MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
|
||||
}
|
||||
|
||||
/* Set the offset of MEM to OFFSET. */
|
||||
|
||||
void
|
||||
set_mem_offset (mem, offset)
|
||||
rtx mem, offset;
|
||||
{
|
||||
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
|
||||
offset, MEM_SIZE (mem), MEM_ALIGN (mem),
|
||||
GET_MODE (mem));
|
||||
}
|
||||
|
||||
/* Return a memory reference like MEMREF, but with its mode changed to MODE
|
||||
and its address changed to ADDR. (VOIDmode means don't change the mode.
|
||||
@ -1907,7 +1979,7 @@ adjust_address_1 (memref, mode, offset, validate, adjust)
|
||||
else if (MEM_SIZE (memref))
|
||||
size = plus_constant (MEM_SIZE (memref), -offset);
|
||||
|
||||
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
|
||||
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
|
||||
memoffset, size, memalign, GET_MODE (new));
|
||||
|
||||
/* At some point, we should validate that this offset is within the object,
|
||||
@ -1948,7 +2020,7 @@ offset_address (memref, offset, pow2)
|
||||
|
||||
/* Update the alignment to reflect the offset. Reset the offset, which
|
||||
we don't know. */
|
||||
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
|
||||
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
|
||||
0, 0, MIN (MEM_ALIGN (memref),
|
||||
pow2 * BITS_PER_UNIT),
|
||||
GET_MODE (new));
|
||||
|
21
gcc/expr.c
21
gcc/expr.c
@ -3603,7 +3603,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
|
||||
}
|
||||
|
||||
emit_move_insn (dest, x);
|
||||
|
||||
}
|
||||
|
||||
if (current_function_check_memory_usage && ! in_check_memory_usage)
|
||||
@ -3768,6 +3767,26 @@ expand_assignment (to, from, want_value, suggest_reg)
|
||||
highest_pow2_factor (offset));
|
||||
}
|
||||
|
||||
if (GET_CODE (to_rtx) == MEM)
|
||||
{
|
||||
tree old_expr = MEM_EXPR (to_rtx);
|
||||
|
||||
/* If the field is at offset zero, we could have been given the
|
||||
DECL_RTX of the parent struct. Don't munge it. */
|
||||
to_rtx = shallow_copy_rtx (to_rtx);
|
||||
|
||||
set_mem_attributes (to_rtx, to, 0);
|
||||
|
||||
/* If we changed MEM_EXPR, that means we're now referencing
|
||||
the COMPONENT_REF, which means that MEM_OFFSET must be
|
||||
relative to that field. But we've not yet reflected BITPOS
|
||||
in TO_RTX. This will be done in store_field. Adjust for
|
||||
that by biasing MEM_OFFSET by -bitpos. */
|
||||
if (MEM_EXPR (to_rtx) != old_expr && MEM_OFFSET (to_rtx)
|
||||
&& (bitpos / BITS_PER_UNIT) != 0)
|
||||
set_mem_offset (to_rtx, GEN_INT (INTVAL (MEM_OFFSET (to_rtx))
|
||||
- (bitpos / BITS_PER_UNIT)));
|
||||
}
|
||||
|
||||
/* Deal with volatile and readonly fields. The former is only done
|
||||
for MEM. Also set MEM_KEEP_ALIAS_SET_P if needed. */
|
||||
|
@ -614,8 +614,11 @@ extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
|
||||
/* Set the alignment of MEM to ALIGN bits. */
|
||||
extern void set_mem_align PARAMS ((rtx, unsigned int));
|
||||
|
||||
/* Set the DECL for MEM to DECL. */
|
||||
extern void set_mem_decl PARAMS ((rtx, tree));
|
||||
/* Set the expr for MEM to EXPR. */
|
||||
extern void set_mem_expr PARAMS ((rtx, tree));
|
||||
|
||||
/* Set the offset for MEM to OFFSET. */
|
||||
extern void set_mem_offset PARAMS ((rtx, rtx));
|
||||
|
||||
/* Return a memory reference like MEMREF, but with its mode changed
|
||||
to MODE and its address changed to ADDR.
|
||||
|
35
gcc/final.c
35
gcc/final.c
@ -245,7 +245,7 @@ static int add_bb_string PARAMS ((const char *, int));
|
||||
static void notice_source_line PARAMS ((rtx));
|
||||
static rtx walk_alter_subreg PARAMS ((rtx *));
|
||||
static void output_asm_name PARAMS ((void));
|
||||
static tree get_decl_from_op PARAMS ((rtx, int *));
|
||||
static tree get_mem_expr_from_op PARAMS ((rtx, int *));
|
||||
static void output_asm_operand_names PARAMS ((rtx *, int *, int));
|
||||
static void output_operand PARAMS ((rtx, int));
|
||||
#ifdef LEAF_REGISTERS
|
||||
@ -3302,16 +3302,16 @@ output_asm_name ()
|
||||
}
|
||||
}
|
||||
|
||||
/* If OP is a REG or MEM and we can find a decl corresponding to it or
|
||||
its address, return that decl. Set *PADDRESSP to 1 if the decl
|
||||
/* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it
|
||||
or its address, return that expr . Set *PADDRESSP to 1 if the expr
|
||||
corresponds to the address of the object and 0 if to the object. */
|
||||
|
||||
static tree
|
||||
get_decl_from_op (op, paddressp)
|
||||
get_mem_expr_from_op (op, paddressp)
|
||||
rtx op;
|
||||
int *paddressp;
|
||||
{
|
||||
tree decl;
|
||||
tree expr;
|
||||
int inner_addressp;
|
||||
|
||||
*paddressp = 0;
|
||||
@ -3321,8 +3321,8 @@ get_decl_from_op (op, paddressp)
|
||||
else if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
|
||||
if (MEM_DECL (op) != 0)
|
||||
return MEM_DECL (op);
|
||||
if (MEM_EXPR (op) != 0)
|
||||
return MEM_EXPR (op);
|
||||
|
||||
/* Otherwise we have an address, so indicate it and look at the address. */
|
||||
*paddressp = 1;
|
||||
@ -3331,18 +3331,18 @@ get_decl_from_op (op, paddressp)
|
||||
/* First check if we have a decl for the address, then look at the right side
|
||||
if it is a PLUS. Otherwise, strip off arithmetic and keep looking.
|
||||
But don't allow the address to itself be indirect. */
|
||||
if ((decl = get_decl_from_op (op, &inner_addressp)) && ! inner_addressp)
|
||||
return decl;
|
||||
if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
|
||||
return expr;
|
||||
else if (GET_CODE (op) == PLUS
|
||||
&& (decl = get_decl_from_op (XEXP (op, 1), &inner_addressp)))
|
||||
return decl;
|
||||
&& (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
|
||||
return expr;
|
||||
|
||||
while (GET_RTX_CLASS (GET_CODE (op)) == '1'
|
||||
|| GET_RTX_CLASS (GET_CODE (op)) == '2')
|
||||
op = XEXP (op, 0);
|
||||
|
||||
decl = get_decl_from_op (op, &inner_addressp);
|
||||
return inner_addressp ? 0 : decl;
|
||||
expr = get_mem_expr_from_op (op, &inner_addressp);
|
||||
return inner_addressp ? 0 : expr;
|
||||
}
|
||||
|
||||
/* Output operand names for assembler instructions. OPERANDS is the
|
||||
@ -3361,13 +3361,14 @@ output_asm_operand_names (operands, oporder, nops)
|
||||
for (i = 0; i < nops; i++)
|
||||
{
|
||||
int addressp;
|
||||
tree decl = get_decl_from_op (operands[oporder[i]], &addressp);
|
||||
tree expr = get_mem_expr_from_op (operands[oporder[i]], &addressp);
|
||||
|
||||
if (decl && DECL_NAME (decl))
|
||||
if (expr)
|
||||
{
|
||||
fprintf (asm_out_file, "%c%s %s%s",
|
||||
fprintf (asm_out_file, "%c%s %s",
|
||||
wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START,
|
||||
addressp ? "*" : "", IDENTIFIER_POINTER (DECL_NAME (decl)));
|
||||
addressp ? "*" : "");
|
||||
print_mem_expr (asm_out_file, expr);
|
||||
wrote = 1;
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,28 @@ int dump_for_graph;
|
||||
/* Nonzero to dump all call_placeholder alternatives. */
|
||||
static int debug_call_placeholder_verbose;
|
||||
|
||||
void
|
||||
print_mem_expr (outfile, expr)
|
||||
FILE *outfile;
|
||||
tree expr;
|
||||
{
|
||||
if (TREE_CODE (expr) == COMPONENT_REF)
|
||||
{
|
||||
if (TREE_OPERAND (expr, 0))
|
||||
print_mem_expr (outfile, TREE_OPERAND (expr, 0));
|
||||
else
|
||||
fputs (" <variable>", outfile);
|
||||
fprintf (outfile, ".%s",
|
||||
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (expr, 1))));
|
||||
}
|
||||
else if (DECL_NAME (expr))
|
||||
fprintf (outfile, " %s", IDENTIFIER_POINTER (DECL_NAME (expr)));
|
||||
else if (TREE_CODE (expr) == RESULT_DECL)
|
||||
fputs (" <result>", outfile);
|
||||
else
|
||||
fputs (" <anonymous>", outfile);
|
||||
}
|
||||
|
||||
/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */
|
||||
|
||||
static void
|
||||
@ -456,12 +478,9 @@ print_rtx (in_rtx)
|
||||
case MEM:
|
||||
fputs (" [", outfile);
|
||||
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
|
||||
if (MEM_DECL (in_rtx))
|
||||
fprintf (outfile, " %s",
|
||||
DECL_NAME (MEM_DECL (in_rtx))
|
||||
? IDENTIFIER_POINTER (DECL_NAME (MEM_DECL (in_rtx)))
|
||||
: TREE_CODE (MEM_DECL (in_rtx)) == RESULT_DECL ? "<result>"
|
||||
: "<anonymous>");
|
||||
|
||||
if (MEM_EXPR (in_rtx))
|
||||
print_mem_expr (outfile, MEM_EXPR (in_rtx));
|
||||
|
||||
if (MEM_OFFSET (in_rtx))
|
||||
{
|
||||
|
@ -2059,7 +2059,7 @@ alter_reg (i, from_reg)
|
||||
if (from_reg != -1 && spill_stack_slot[from_reg] == x)
|
||||
x = copy_rtx (x);
|
||||
|
||||
set_mem_decl (x, REGNO_DECL (i));
|
||||
set_mem_expr (x, REGNO_DECL (i));
|
||||
}
|
||||
|
||||
/* Save the stack slot for later. */
|
||||
|
@ -92,7 +92,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
HOST_WIDE_INT alias; /* Memory alias set. */
|
||||
tree decl; /* decl corresponding to MEM. */
|
||||
tree expr; /* expr corresponding to MEM. */
|
||||
rtx offset; /* Offset from start of DECL, as CONST_INT. */
|
||||
rtx size; /* Size in bytes, as a CONST_INT. */
|
||||
unsigned int align; /* Alignment of MEM in bits. */
|
||||
@ -904,10 +904,10 @@ extern unsigned int subreg_regno PARAMS ((rtx));
|
||||
#define MEM_ALIAS_SET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->alias)
|
||||
|
||||
/* For a MEM rtx, the decl it is known to refer to, if it is known to
|
||||
refer to part of a DECL. */
|
||||
#define MEM_DECL(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->decl)
|
||||
refer to part of a DECL. It may also be a COMPONENT_REF. */
|
||||
#define MEM_EXPR(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->expr)
|
||||
|
||||
/* For a MEM rtx, the offset from the start of MEM_DECL, if known, as a
|
||||
/* 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) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
|
||||
|
||||
@ -1865,6 +1865,7 @@ extern void debug_rtx_list PARAMS ((rtx, int));
|
||||
extern void debug_rtx_range PARAMS ((rtx, rtx));
|
||||
extern rtx debug_rtx_find PARAMS ((rtx, int));
|
||||
#ifdef BUFSIZ
|
||||
extern void print_mem_expr PARAMS ((FILE *, tree));
|
||||
extern void print_rtl PARAMS ((FILE *, rtx));
|
||||
extern void print_simple_rtl PARAMS ((FILE *, rtx));
|
||||
extern int print_rtl_single PARAMS ((FILE *, rtx));
|
||||
|
Loading…
Reference in New Issue
Block a user