Makefile.in (print-rtl.o): Depend on TREE_H.

* Makefile.in (print-rtl.o): Depend on TREE_H.
	* alias.c (get_alias_set): Make two passes over objects to first
	see if inner object is access via restricted pointer.
	Defer allocating alias set for restricted pointer until here.
	Call find_placeholder with second arg nonzero.
	Minor cleanups.
	* emit-rtl.c (set_mem_attributes): Set more attributes.
	(set_mem_align, change_address, adjust_address_1): New functions.
	(change_address_1): Now static.
	(adjust_address, adjust_address_nv): Deleted.
	(replace_equiv_address): Call change_address_1.
	* expr.c (get_inner_reference): Handle PLACEHOLDER_EXPR.
	(find_placeholder): Get starting point from PLIST arg.
	(expand_expr, case PLACEHOLDER_EXPR): Initialize find_placeholder arg.
	* expr.h (set_mem_align, change_address, adjust_address_1): New decls.
	(adjust_address, adjust_address_nv): New macros.
	* print-rtl.c (tree.h): New include.
	(print_rtx, case MEM): Print all memory attributes.

From-SVN: r46313
This commit is contained in:
Richard Kenner 2001-10-17 09:31:36 +00:00 committed by Richard Kenner
parent 4d8f669f94
commit 738cc47245
7 changed files with 264 additions and 121 deletions

View File

@ -1,3 +1,24 @@
Wed Oct 17 05:26:39 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (print-rtl.o): Depend on TREE_H.
* alias.c (get_alias_set): Make two passes over objects to first
see if inner object is access via restricted pointer.
Defer allocating alias set for restricted pointer until here.
Call find_placeholder with second arg nonzero.
Minor cleanups.
* emit-rtl.c (set_mem_attributes): Set more attributes.
(set_mem_align, change_address, adjust_address_1): New functions.
(change_address_1): Now static.
(adjust_address, adjust_address_nv): Deleted.
(replace_equiv_address): Call change_address_1.
* expr.c (get_inner_reference): Handle PLACEHOLDER_EXPR.
(find_placeholder): Get starting point from PLIST arg.
(expand_expr, case PLACEHOLDER_EXPR): Initialize find_placeholder arg.
* expr.h (set_mem_align, change_address, adjust_address_1): New decls.
(adjust_address, adjust_address_nv): New macros.
* print-rtl.c (tree.h): New include.
(print_rtx, case MEM): Print all memory attributes.
2001-10-17 Richard Henderson <rth@redhat.com> 2001-10-17 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (direct_call_operand): Don't fall off end. * config/alpha/alpha.c (direct_call_operand): Don't fall off end.

View File

@ -1381,8 +1381,8 @@ rtl-error.o: rtl-error.c system.h $(RTL_H) $(INSN_ATTR_H) insn-config.h \
rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \ print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(BASIC_BLOCK_H)
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) hard-reg-set.h rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) hard-reg-set.h

View File

@ -458,7 +458,6 @@ HOST_WIDE_INT
get_alias_set (t) get_alias_set (t)
tree t; tree t;
{ {
tree orig_t;
HOST_WIDE_INT set; HOST_WIDE_INT set;
/* If we're not doing any alias analysis, just assume everything /* If we're not doing any alias analysis, just assume everything
@ -473,12 +472,74 @@ get_alias_set (t)
language-specific routine may make mutually-recursive calls to each other language-specific routine may make mutually-recursive calls to each other
to figure out what to do. At each juncture, we see if this is a tree to figure out what to do. At each juncture, we see if this is a tree
that the language may need to handle specially. First handle things that that the language may need to handle specially. First handle things that
aren't types and start by removing nops since we care only about the aren't types. */
actual object. Also replace PLACEHOLDER_EXPRs and pick up the outermost
object that we could have a pointer to. */
if (! TYPE_P (t)) if (! TYPE_P (t))
{ {
/* Remove any NOPs and see what any PLACEHOLD_EXPRs will expand to. */ tree inner = t;
tree placeholder_ptr = 0;
/* First see if the actual object referenced is an INDIRECT_REF from a
restrict-qualified pointer or a "void *". Start by removing nops
since we care only about the actual object. Also replace
PLACEHOLDER_EXPRs. */
while (((TREE_CODE (inner) == NOP_EXPR
|| TREE_CODE (inner) == CONVERT_EXPR)
&& (TYPE_MODE (TREE_TYPE (inner))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (inner, 0)))))
|| TREE_CODE (inner) == NON_LVALUE_EXPR
|| TREE_CODE (inner) == PLACEHOLDER_EXPR
|| handled_component_p (inner))
{
if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
inner = find_placeholder (inner, &placeholder_ptr);
else
inner = TREE_OPERAND (inner, 0);
}
/* Check for accesses through restrict-qualified pointers. */
if (TREE_CODE (inner) == INDIRECT_REF)
{
tree decl = find_base_decl (TREE_OPERAND (inner, 0));
if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
{
/* If we haven't computed the actual alias set, do it now. */
if (DECL_POINTER_ALIAS_SET (decl) == -2)
{
/* No two restricted pointers can point at the same thing.
However, a restricted pointer can point at the same thing
as an unrestricted pointer, if that unrestricted pointer
is based on the restricted pointer. So, we make the
alias set for the restricted pointer a subset of the
alias set for the type pointed to by the type of the
decl. */
HOST_WIDE_INT pointed_to_alias_set
= get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
if (pointed_to_alias_set == 0)
/* It's not legal to make a subset of alias set zero. */
;
else
{
DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
record_alias_subset (pointed_to_alias_set,
DECL_POINTER_ALIAS_SET (decl));
}
}
/* We use the alias set indicated in the declaration. */
return DECL_POINTER_ALIAS_SET (decl);
}
/* If we have an INDIRECT_REF via a void pointer, we don't
know anything about what that might alias. */
else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE)
return 0;
}
/* Otherwise, pick up the outermost object that we could have a pointer
to, processing conversion and PLACEHOLDER_EXPR as above. */
placeholder_ptr = 0;
while (((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR) while (((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
&& (TYPE_MODE (TREE_TYPE (t)) && (TYPE_MODE (TREE_TYPE (t))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))))) == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))))
@ -492,44 +553,22 @@ get_alias_set (t)
return set; return set;
if (TREE_CODE (t) == PLACEHOLDER_EXPR) if (TREE_CODE (t) == PLACEHOLDER_EXPR)
t = find_placeholder (t, 0); t = find_placeholder (t, &placeholder_ptr);
else else
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
} }
/* Now give the language a chance to do something but record what we /* Give the language another chance to do something. */
gave it this time. */
orig_t = t;
if ((set = lang_get_alias_set (t)) != -1) if ((set = lang_get_alias_set (t)) != -1)
return set; return set;
/* Check for accesses through restrict-qualified pointers. */ /* If we've already determined the alias set for a decl, just return
if (TREE_CODE (t) == INDIRECT_REF) it. This is necessary for C++ anonymous unions, whose component
{ variables don't look like union members (boo!). */
tree decl = find_base_decl (TREE_OPERAND (t, 0));
if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
/* We use the alias set indicated in the declaration. */
return DECL_POINTER_ALIAS_SET (decl);
/* If we have an INDIRECT_REF via a void pointer, we don't
know anything about what that might alias. */
if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE)
return 0;
}
/* If we've already determined the alias set for this decl, just
return it. This is necessary for C++ anonymous unions, whose
component variables don't look like union members (boo!). */
if (TREE_CODE (t) == VAR_DECL if (TREE_CODE (t) == VAR_DECL
&& DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM) && DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)
return MEM_ALIAS_SET (DECL_RTL (t)); return MEM_ALIAS_SET (DECL_RTL (t));
/* Give the language another chance to do something special. */
if (orig_t != t
&& (set = lang_get_alias_set (t)) != -1)
return set;
/* Now all we care about is the type. */ /* Now all we care about is the type. */
t = TREE_TYPE (t); t = TREE_TYPE (t);
} }
@ -537,16 +576,12 @@ get_alias_set (t)
/* Variant qualifiers don't affect the alias set, so get the main /* Variant qualifiers don't affect the alias set, so get the main
variant. If this is a type with a known alias set, return it. */ variant. If this is a type with a known alias set, return it. */
t = TYPE_MAIN_VARIANT (t); t = TYPE_MAIN_VARIANT (t);
if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t)) if (TYPE_ALIAS_SET_KNOWN_P (t))
return TYPE_ALIAS_SET (t); return TYPE_ALIAS_SET (t);
/* See if the language has special handling for this type. */ /* See if the language has special handling for this type. */
if ((set = lang_get_alias_set (t)) != -1) if ((set = lang_get_alias_set (t)) != -1)
{ return set;
/* If the alias set is now known, we are done. */
if (TYPE_ALIAS_SET_KNOWN_P (t))
return TYPE_ALIAS_SET (t);
}
/* There are no objects of FUNCTION_TYPE, so there's no point in /* There are no objects of FUNCTION_TYPE, so there's no point in
using up an alias set for them. (There are, of course, pointers using up an alias set for them. (There are, of course, pointers

View File

@ -178,6 +178,8 @@ static rtx make_jump_insn_raw PARAMS ((rtx));
static rtx make_call_insn_raw PARAMS ((rtx)); static rtx make_call_insn_raw PARAMS ((rtx));
static rtx find_line_note PARAMS ((rtx)); static rtx find_line_note PARAMS ((rtx));
static void mark_sequence_stack PARAMS ((struct sequence_stack *)); static void mark_sequence_stack PARAMS ((struct sequence_stack *));
static rtx change_address_1 PARAMS ((rtx, enum machine_mode, rtx,
int));
static void unshare_all_rtl_1 PARAMS ((rtx)); static void unshare_all_rtl_1 PARAMS ((rtx));
static void unshare_all_decls PARAMS ((tree)); static void unshare_all_decls PARAMS ((tree));
static void reset_used_decls PARAMS ((tree)); static void reset_used_decls PARAMS ((tree));
@ -1652,14 +1654,6 @@ set_mem_attributes (ref, t, objectp)
type = TYPE_P (t) ? t : TREE_TYPE (t); type = TYPE_P (t) ? t : TREE_TYPE (t);
/* Get the alias set from the expression or type (perhaps using a
front-end routine) and then copy bits from the type. */
/* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY (type)
here, because, in C and C++, the fact that a location is accessed
through a const expression does not mean that the value there can
never change. */
/* If we have already set DECL_RTL = ref, get_alias_set will get the /* If we have already set DECL_RTL = ref, get_alias_set will get the
wrong answer, as it assumes that DECL_RTL already has the right alias wrong answer, as it assumes that DECL_RTL already has the right alias
info. Callers should not set DECL_RTL until after the call to info. Callers should not set DECL_RTL until after the call to
@ -1667,8 +1661,15 @@ set_mem_attributes (ref, t, objectp)
if (DECL_P (t) && ref == DECL_RTL_IF_SET (t)) if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
abort (); abort ();
/* Get the alias set from the expression or type (perhaps using a
front-end routine). */
set_mem_alias_set (ref, get_alias_set (t)); set_mem_alias_set (ref, get_alias_set (t));
/* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY (type)
here, because, in C and C++, the fact that a location is accessed
through a const expression does not mean that the value there can
never change. */
MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type); MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type); MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
@ -1677,7 +1678,14 @@ set_mem_attributes (ref, t, objectp)
if (objectp && ! AGGREGATE_TYPE_P (type)) if (objectp && ! AGGREGATE_TYPE_P (type))
MEM_SCALAR_P (ref) = 1; MEM_SCALAR_P (ref) = 1;
/* If T is a type, this is all we can do. Otherwise, we may be able /* If the size is known, we can set that. */
if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
MEM_ATTRS (ref)
= get_mem_attrs (MEM_ALIAS_SET (ref), MEM_DECL (ref), MEM_OFFSET (ref),
GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1)),
MEM_ALIGN (ref));
/* If T is a type, there's nothing more we can do. Otherwise, we may be able
to deduce some more information about the expression. */ to deduce some more information about the expression. */
if (TYPE_P (t)) if (TYPE_P (t))
return; return;
@ -1686,17 +1694,27 @@ set_mem_attributes (ref, t, objectp)
if (TREE_THIS_VOLATILE (t)) if (TREE_THIS_VOLATILE (t))
MEM_VOLATILE_P (ref) = 1; MEM_VOLATILE_P (ref) = 1;
/* Now see if we can say more about whether it's an aggregate or
scalar. If we already know it's an aggregate, don't bother. */
if (MEM_IN_STRUCT_P (ref))
return;
/* Now remove any NOPs: they don't change what the underlying object is. /* Now remove any NOPs: they don't change what the underlying object is.
Likewise for SAVE_EXPR. */ Likewise for SAVE_EXPR. */
while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
|| TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR) || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
/* If this is a decl, set the attributes of the MEM from it. */
if (DECL_P (t))
MEM_ATTRS (ref)
= get_mem_attrs
(MEM_ALIAS_SET (ref), t, GEN_INT (0),
(TYPE_SIZE_UNIT (TREE_TYPE (t))
&& host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (t)), 1))
? GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (t)), 1))
: 0, DECL_ALIGN (t) / BITS_PER_UNIT);
/* Now see if we can say more about whether it's an aggregate or
scalar. If we already know it's an aggregate, don't bother. */
if (MEM_IN_STRUCT_P (ref))
return;
/* Since we already know the type isn't an aggregate, if this is a decl, /* Since we already know the type isn't an aggregate, if this is a decl,
it must be a scalar. Or if it is a reference into an aggregate, it must be a scalar. Or if it is a reference into an aggregate,
this is part of an aggregate. Otherwise we don't know. */ this is part of an aggregate. Otherwise we don't know. */
@ -1715,7 +1733,6 @@ set_mem_alias_set (mem, set)
rtx mem; rtx mem;
HOST_WIDE_INT set; HOST_WIDE_INT set;
{ {
/* It would be nice to enable this check, but we can't quite yet. */
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */ /* If the new and old alias sets don't conflict, something is wrong. */
if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem))) if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
@ -1725,15 +1742,25 @@ set_mem_alias_set (mem, set)
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem), MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
MEM_SIZE (mem), MEM_ALIGN (mem)); MEM_SIZE (mem), MEM_ALIGN (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.
NULL for ADDR means don't change the address.)
VALIDATE is nonzero if the returned memory location is required to be
valid. */
rtx /* Set the alignment of MEM to ALIGN. */
void
set_mem_align (mem, align)
rtx mem;
unsigned int align;
{
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_DECL (mem),
MEM_OFFSET (mem), MEM_SIZE (mem), align);
}
/* 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.
NULL for ADDR means don't change the address.) VALIDATE is nonzero if the
returned memory location is required to be valid. The memory
attributes are not changed. */
static rtx
change_address_1 (memref, mode, addr, validate) change_address_1 (memref, mode, addr, validate)
rtx memref; rtx memref;
enum machine_mode mode; enum machine_mode mode;
@ -1768,21 +1795,42 @@ change_address_1 (memref, mode, addr, validate)
return new; return new;
} }
/* Return a memory reference like MEMREF, but with its mode changed /* Like change_address_1 with VALIDATE nonzero, but we are not saying in what
to MODE and its address offset by OFFSET bytes. */ way we are changing MEMREF, so we only preserve the alias set. */
rtx rtx
adjust_address (memref, mode, offset) change_address (memref, mode, addr)
rtx memref;
enum machine_mode mode;
rtx addr;
{
rtx new = change_address_1 (memref, mode, addr, 1);
enum machine_mode mmode = GET_MODE (new);
MEM_ATTRS (new)
= get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0,
mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode)),
(mmode == BLKmode ? 1
: GET_MODE_ALIGNMENT (mmode) / BITS_PER_UNIT));
return new;
}
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. If VALIDATE is
nonzero, the memory address is forced to be valid. */
rtx
adjust_address_1 (memref, mode, offset, validate)
rtx memref; rtx memref;
enum machine_mode mode; enum machine_mode mode;
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
int validate;
{ {
/* For now, this is just a wrapper for change_address, but eventually
will do memref tracking. */
rtx addr = XEXP (memref, 0); rtx addr = XEXP (memref, 0);
rtx new;
/* ??? Prefer to create garbage instead of creating shared rtl. */ rtx memoffset = MEM_OFFSET (memref);
addr = copy_rtx (addr); unsigned int memalign = MEM_ALIGN (memref);
/* If MEMREF is a LO_SUM and the offset is within the alignment of the /* If MEMREF is a LO_SUM and the offset is within the alignment of the
object, we can merge it into the LO_SUM. */ object, we can merge it into the LO_SUM. */
@ -1792,36 +1840,36 @@ adjust_address (memref, mode, offset)
< GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT) < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0), addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset)); plus_constant (XEXP (addr, 1), offset));
else if (offset == 0)
/* ??? Prefer to create garbage instead of creating shared rtl. */
addr = copy_rtx (addr);
else else
addr = plus_constant (addr, offset); addr = plus_constant (addr, offset);
return change_address (memref, mode, addr); new = change_address_1 (memref, mode, addr, validate);
}
/* Likewise, but the reference is not required to be valid. */ /* Compute the new values of the memory attributes due to this adjustment.
We add the offsets and update the alignment. */
if (memoffset)
memoffset = GEN_INT (offset + INTVAL (memoffset));
rtx /* If the offset is negative, don't try to update the alignment. If it's
adjust_address_nv (memref, mode, offset) zero, the alignment hasn't changed. Otherwise, the known alignment may
rtx memref; be less strict. */
enum machine_mode mode; if (offset < 0)
HOST_WIDE_INT offset; memalign = 1;
{
/* For now, this is just a wrapper for change_address, but eventually
will do memref tracking. */
rtx addr = XEXP (memref, 0);
/* If MEMREF is a LO_SUM and the offset is within the size of the while (offset > 0 && (offset % memalign) != 0)
object, we can merge it into the LO_SUM. */ memalign >>= 1;
if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
&& offset >= 0
&& (unsigned HOST_WIDE_INT) offset
< GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
addr = gen_rtx_LO_SUM (mode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
else
addr = plus_constant (addr, offset);
return change_address_1 (memref, mode, addr, 0); MEM_ATTRS (new)
= get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref), memoffset,
mode == BLKmode
? 0 : GEN_INT (GET_MODE_SIZE (mode)), memalign);
/* At some point, we should validate that this offset is within the object,
if all the appropriate values are known. */
return new;
} }
/* Return a memory reference like MEMREF, but with its address changed to /* Return a memory reference like MEMREF, but with its address changed to
@ -1834,10 +1882,11 @@ replace_equiv_address (memref, addr)
rtx memref; rtx memref;
rtx addr; rtx addr;
{ {
/* For now, this is just a wrapper for change_address, but eventually /* change_address_1 copies the memory attribute structure without change
will do memref tracking. */ and that's exactly what we want here. */
return change_address (memref, VOIDmode, addr); return change_address_1 (memref, VOIDmode, addr, 1);
} }
/* Likewise, but the reference is not required to be valid. */ /* Likewise, but the reference is not required to be valid. */
rtx rtx
@ -1845,8 +1894,6 @@ replace_equiv_address_nv (memref, addr)
rtx memref; rtx memref;
rtx addr; rtx addr;
{ {
/* For now, this is just a wrapper for change_address, but eventually
will do memref tracking. */
return change_address_1 (memref, VOIDmode, addr, 0); return change_address_1 (memref, VOIDmode, addr, 0);
} }

View File

@ -5403,6 +5403,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
tree offset = size_zero_node; tree offset = size_zero_node;
tree bit_offset = bitsize_zero_node; tree bit_offset = bitsize_zero_node;
unsigned int alignment = BIGGEST_ALIGNMENT; unsigned int alignment = BIGGEST_ALIGNMENT;
tree placeholder_ptr = 0;
tree tem; tree tem;
/* First get the mode, signedness, and size. We do this from just the /* First get the mode, signedness, and size. We do this from just the
@ -5500,6 +5501,11 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
unit_size)); unit_size));
} }
else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
{
exp = find_placeholder (exp, &placeholder_ptr);
continue;
}
else if (TREE_CODE (exp) != NON_LVALUE_EXPR else if (TREE_CODE (exp) != NON_LVALUE_EXPR
&& ! ((TREE_CODE (exp) == NOP_EXPR && ! ((TREE_CODE (exp) == NOP_EXPR
|| TREE_CODE (exp) == CONVERT_EXPR) || TREE_CODE (exp) == CONVERT_EXPR)
@ -5961,10 +5967,11 @@ check_max_integer_computation_mode (exp)
/* Return an object on the placeholder list that matches EXP, a /* Return an object on the placeholder list that matches EXP, a
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
PLACEHOLDER_EXPR or a pointer type to it. For further information, PLACEHOLDER_EXPR or a pointer type to it. For further information, see
see tree.def. If no such object is found, abort. If PLIST is nonzero, tree.def. If no such object is found, abort. If PLIST is nonzero, it is
it is a location into which a pointer into the placeholder list at a location which initially points to a starting location in the
which the object is found is placed. */ placeholder list (zero means start of the list) and where a pointer into
the placeholder list at which the object is found is placed. */
tree tree
find_placeholder (exp, plist) find_placeholder (exp, plist)
@ -5974,7 +5981,9 @@ find_placeholder (exp, plist)
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
tree placeholder_expr; tree placeholder_expr;
for (placeholder_expr = placeholder_list; placeholder_expr != 0; for (placeholder_expr
= plist && *plist ? TREE_CHAIN (*plist) : placeholder_list;
placeholder_expr != 0;
placeholder_expr = TREE_CHAIN (placeholder_expr)) placeholder_expr = TREE_CHAIN (placeholder_expr))
{ {
tree need_type = TYPE_MAIN_VARIANT (type); tree need_type = TYPE_MAIN_VARIANT (type);
@ -6550,7 +6559,7 @@ expand_expr (exp, target, tmode, modifier)
case PLACEHOLDER_EXPR: case PLACEHOLDER_EXPR:
{ {
tree old_list = placeholder_list; tree old_list = placeholder_list;
tree placeholder_expr; tree placeholder_expr = 0;
exp = find_placeholder (exp, &placeholder_expr); exp = find_placeholder (exp, &placeholder_expr);
placeholder_list = TREE_CHAIN (placeholder_expr); placeholder_list = TREE_CHAIN (placeholder_expr);

View File

@ -500,10 +500,11 @@ extern rtx force_operand PARAMS ((rtx, rtx));
/* Return an object on the placeholder list that matches EXP, a /* Return an object on the placeholder list that matches EXP, a
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
PLACEHOLDER_EXPR or a pointer type to it. For further information, PLACEHOLDER_EXPR or a pointer type to it. For further information, see
see tree.def. If no such object is found, abort. If PLIST is nonzero, tree.def. If no such object is found, abort. If PLIST is nonzero, it is
it is a location into which a pointer into the placeholder list at a location which initially points to a starting location in the
which the object is found is placed. */ placeholder list (zero means start of the list) and where a pointer into
the placeholder list at which the object is found is placed. */
extern tree find_placeholder PARAMS ((tree, tree *)); extern tree find_placeholder PARAMS ((tree, tree *));
/* Generate code for computing expression EXP. /* Generate code for computing expression EXP.
@ -611,23 +612,26 @@ extern rtx memory_address_noforce PARAMS ((enum machine_mode, rtx));
/* Set the alias set of MEM to SET. */ /* Set the alias set of MEM to SET. */
extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT)); extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
/* Set the alignment of MEM to ALIGN. */
extern void set_mem_align PARAMS ((rtx, unsigned int));
/* Return a memory reference like MEMREF, but with its mode changed /* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address changed to ADDR. to MODE and its address changed to ADDR.
(VOIDmode means don't change the mode. (VOIDmode means don't change the mode.
NULL for ADDR means don't change the address.) NULL for ADDR means don't change the address.) */
VALIDATE is nonzero if the returned memory location is required to be extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx));
valid. */
extern rtx change_address_1 PARAMS ((rtx, enum machine_mode, rtx, int));
#define change_address(MEMREF, MODE, ADDR) \
change_address_1 (MEMREF, MODE, ADDR, 1)
/* Return a memory reference like MEMREF, but with its mode changed /* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. */ to MODE and its address offset by OFFSET bytes. */
extern rtx adjust_address PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT)); #define adjust_address(MEMREF, MODE, OFFSET) \
adjust_address_1 (MEMREF, MODE, OFFSET, 1)
/* Likewise, but the reference is not required to be valid. */ /* Likewise, but the reference is not required to be valid. */
extern rtx adjust_address_nv PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT)); #define adjust_address_nv(MEMREF, MODE, OFFSET) \
adjust_address_1 (MEMREF, MODE, OFFSET, 0)
extern rtx adjust_address_1 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT,
int));
/* Return a memory reference like MEMREF, but with its address changed to /* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed ADDR. The caller is asserting that the actual piece of memory pointed

View File

@ -23,6 +23,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "rtl.h" #include "rtl.h"
/* We don't want the tree code checking code for the access to the
DECL_NAME to be included in the gen* programs. */
#undef ENABLE_TREE_CHECKING
#include "tree.h"
#include "real.h" #include "real.h"
#include "flags.h" #include "flags.h"
#include "hard-reg-set.h" #include "hard-reg-set.h"
@ -446,8 +451,30 @@ print_rtx (in_rtx)
switch (GET_CODE (in_rtx)) switch (GET_CODE (in_rtx))
{ {
case MEM: case MEM:
fputc (' ', outfile); fputs (" [", outfile);
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx)); fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
if (MEM_DECL (in_rtx) && DECL_NAME (MEM_DECL (in_rtx)))
fprintf (outfile, " %s",
IDENTIFIER_POINTER (DECL_NAME (MEM_DECL (in_rtx))));
if (MEM_OFFSET (in_rtx))
{
fputc ('+', outfile);
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC,
INTVAL (MEM_OFFSET (in_rtx)));
}
if (MEM_SIZE (in_rtx))
{
fputs (" S", outfile);
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC,
INTVAL (MEM_SIZE (in_rtx)));
}
if (MEM_ALIGN (in_rtx) != 1)
fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
fputc (']', outfile);
break; break;
#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64