aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-10-17 09:31:36 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2001-10-17 05:31:36 -0400
commit738cc472453eb61b6d18e223877e5380d7adb0dd (patch)
tree3f3a09b804dc2ad899529714f44003c6933712ab
parent4d8f669f9481e4154eea13098cb6def6b64bcb1f (diff)
downloadgcc-738cc472453eb61b6d18e223877e5380d7adb0dd.zip
gcc-738cc472453eb61b6d18e223877e5380d7adb0dd.tar.gz
gcc-738cc472453eb61b6d18e223877e5380d7adb0dd.tar.bz2
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
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/Makefile.in4
-rw-r--r--gcc/alias.c115
-rw-r--r--gcc/emit-rtl.c157
-rw-r--r--gcc/expr.c21
-rw-r--r--gcc/expr.h30
-rw-r--r--gcc/print-rtl.c29
7 files changed, 260 insertions, 117 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 33bf8b2..751e583 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* config/alpha/alpha.c (direct_call_operand): Don't fall off end.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0184816..27a3111 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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
$(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 \
- $(BASIC_BLOCK_H)
+print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
+ hard-reg-set.h $(BASIC_BLOCK_H)
$(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
diff --git a/gcc/alias.c b/gcc/alias.c
index 53de65f..af0141f 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -99,7 +99,7 @@ static int can_address_p PARAMS ((tree));
static rtx find_base_value PARAMS ((rtx));
static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
static int insert_subset_children PARAMS ((splay_tree_node, void*));
-static tree find_base_decl PARAMS ((tree));
+static tree find_base_decl PARAMS ((tree));
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)));
@@ -458,7 +458,6 @@ HOST_WIDE_INT
get_alias_set (t)
tree t;
{
- tree orig_t;
HOST_WIDE_INT set;
/* If we're not doing any alias analysis, just assume everything
@@ -473,14 +472,76 @@ get_alias_set (t)
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
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
- actual object. Also replace PLACEHOLDER_EXPRs and pick up the outermost
- object that we could have a pointer to. */
+ aren't types. */
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)
- && (TYPE_MODE (TREE_TYPE (t))
+ && (TYPE_MODE (TREE_TYPE (t))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))))
|| TREE_CODE (t) == NON_LVALUE_EXPR
|| TREE_CODE (t) == PLACEHOLDER_EXPR
@@ -492,44 +553,22 @@ get_alias_set (t)
return set;
if (TREE_CODE (t) == PLACEHOLDER_EXPR)
- t = find_placeholder (t, 0);
+ t = find_placeholder (t, &placeholder_ptr);
else
t = TREE_OPERAND (t, 0);
}
- /* Now give the language a chance to do something but record what we
- gave it this time. */
- orig_t = t;
+ /* Give the language another chance to do something. */
if ((set = lang_get_alias_set (t)) != -1)
return set;
- /* Check for accesses through restrict-qualified pointers. */
- if (TREE_CODE (t) == INDIRECT_REF)
- {
- 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 we've already determined the alias set for a 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
&& DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)
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. */
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. If this is a type with a known alias set, return it. */
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);
/* See if the language has special handling for this type. */
if ((set = lang_get_alias_set (t)) != -1)
- {
- /* If the alias set is now known, we are done. */
- if (TYPE_ALIAS_SET_KNOWN_P (t))
- return TYPE_ALIAS_SET (t);
- }
+ return set;
/* 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
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index eaaf20c..50819c6 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -178,6 +178,8 @@ static rtx make_jump_insn_raw PARAMS ((rtx));
static rtx make_call_insn_raw PARAMS ((rtx));
static rtx find_line_note PARAMS ((rtx));
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_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);
- /* 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
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
@@ -1667,8 +1661,15 @@ set_mem_attributes (ref, t, objectp)
if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
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));
+ /* 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_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
@@ -1677,7 +1678,14 @@ set_mem_attributes (ref, t, objectp)
if (objectp && ! AGGREGATE_TYPE_P (type))
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. */
if (TYPE_P (t))
return;
@@ -1686,17 +1694,27 @@ set_mem_attributes (ref, t, objectp)
if (TREE_THIS_VOLATILE (t))
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.
Likewise for SAVE_EXPR. */
while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
|| TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
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,
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. */
@@ -1715,7 +1733,6 @@ set_mem_alias_set (mem, set)
rtx mem;
HOST_WIDE_INT set;
{
- /* It would be nice to enable this check, but we can't quite yet. */
#ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */
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_SIZE (mem), MEM_ALIGN (mem));
}
+
+/* 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. */
+/* 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. */
-rtx
+static rtx
change_address_1 (memref, mode, addr, validate)
rtx memref;
enum machine_mode mode;
@@ -1768,60 +1795,81 @@ change_address_1 (memref, mode, addr, validate)
return new;
}
-/* Return a memory reference like MEMREF, but with its mode changed
- to MODE and its address offset by OFFSET bytes. */
+/* Like change_address_1 with VALIDATE nonzero, but we are not saying in what
+ way we are changing MEMREF, so we only preserve the alias set. */
rtx
-adjust_address (memref, mode, offset)
+change_address (memref, mode, addr)
rtx memref;
enum machine_mode mode;
- HOST_WIDE_INT offset;
+ rtx addr;
{
- /* For now, this is just a wrapper for change_address, but eventually
- will do memref tracking. */
- rtx addr = XEXP (memref, 0);
-
- /* ??? Prefer to create garbage instead of creating shared rtl. */
- addr = copy_rtx (addr);
+ rtx new = change_address_1 (memref, mode, addr, 1);
+ enum machine_mode mmode = GET_MODE (new);
- /* If MEMREF is a LO_SUM and the offset is within the alignment of the
- object, we can merge it into the LO_SUM. */
- 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 (Pmode, XEXP (addr, 0),
- plus_constant (XEXP (addr, 1), offset));
- else
- addr = plus_constant (addr, offset);
+ 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 change_address (memref, mode, addr);
+ return new;
}
-/* Likewise, but the reference is not required to be valid. */
+/* 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_nv (memref, mode, offset)
+adjust_address_1 (memref, mode, offset, validate)
rtx memref;
enum machine_mode mode;
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 new;
+ rtx memoffset = MEM_OFFSET (memref);
+ unsigned int memalign = MEM_ALIGN (memref);
- /* If MEMREF is a LO_SUM and the offset is within the size 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. */
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),
+ addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
+ else if (offset == 0)
+ /* ??? Prefer to create garbage instead of creating shared rtl. */
+ addr = copy_rtx (addr);
else
addr = plus_constant (addr, offset);
- return change_address_1 (memref, mode, addr, 0);
+ new = change_address_1 (memref, mode, addr, validate);
+
+ /* 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));
+
+ /* If the offset is negative, don't try to update the alignment. If it's
+ zero, the alignment hasn't changed. Otherwise, the known alignment may
+ be less strict. */
+ if (offset < 0)
+ memalign = 1;
+
+ while (offset > 0 && (offset % memalign) != 0)
+ memalign >>= 1;
+
+ 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
@@ -1834,10 +1882,11 @@ replace_equiv_address (memref, addr)
rtx memref;
rtx addr;
{
- /* For now, this is just a wrapper for change_address, but eventually
- will do memref tracking. */
- return change_address (memref, VOIDmode, addr);
+ /* change_address_1 copies the memory attribute structure without change
+ and that's exactly what we want here. */
+ return change_address_1 (memref, VOIDmode, addr, 1);
}
+
/* Likewise, but the reference is not required to be valid. */
rtx
@@ -1845,8 +1894,6 @@ replace_equiv_address_nv (memref, addr)
rtx memref;
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);
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 1c81f73..e06d4b1 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5403,6 +5403,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
tree offset = size_zero_node;
tree bit_offset = bitsize_zero_node;
unsigned int alignment = BIGGEST_ALIGNMENT;
+ tree placeholder_ptr = 0;
tree tem;
/* 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));
}
+ else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
+ {
+ exp = find_placeholder (exp, &placeholder_ptr);
+ continue;
+ }
else if (TREE_CODE (exp) != NON_LVALUE_EXPR
&& ! ((TREE_CODE (exp) == NOP_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
PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
- PLACEHOLDER_EXPR or a pointer type to it. For further information,
- see tree.def. If no such object is found, abort. If PLIST is nonzero,
- it is a location into which a pointer into the placeholder list at
- which the object is found is placed. */
+ PLACEHOLDER_EXPR or a pointer type to it. For further information, see
+ tree.def. If no such object is found, abort. If PLIST is nonzero, it is
+ a location which initially points to a starting location in the
+ 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
find_placeholder (exp, plist)
@@ -5974,7 +5981,9 @@ find_placeholder (exp, plist)
tree type = TREE_TYPE (exp);
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))
{
tree need_type = TYPE_MAIN_VARIANT (type);
@@ -6550,7 +6559,7 @@ expand_expr (exp, target, tmode, modifier)
case PLACEHOLDER_EXPR:
{
tree old_list = placeholder_list;
- tree placeholder_expr;
+ tree placeholder_expr = 0;
exp = find_placeholder (exp, &placeholder_expr);
placeholder_list = TREE_CHAIN (placeholder_expr);
diff --git a/gcc/expr.h b/gcc/expr.h
index a518cf0..af79fd5 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -500,10 +500,11 @@ extern rtx force_operand PARAMS ((rtx, rtx));
/* 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 or a pointer type to it. For further information,
- see tree.def. If no such object is found, abort. If PLIST is nonzero,
- it is a location into which a pointer into the placeholder list at
- which the object is found is placed. */
+ PLACEHOLDER_EXPR or a pointer type to it. For further information, see
+ tree.def. If no such object is found, abort. If PLIST is nonzero, it is
+ a location which initially points to a starting location in the
+ 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 *));
/* 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. */
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
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. */
-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)
+ NULL for ADDR means don't change the address.) */
+extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx));
/* Return a memory reference like MEMREF, but with its mode changed
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. */
-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
ADDR. The caller is asserting that the actual piece of memory pointed
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index f2025b5..3d78dd3 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -23,6 +23,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.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 "flags.h"
#include "hard-reg-set.h"
@@ -446,8 +451,30 @@ print_rtx (in_rtx)
switch (GET_CODE (in_rtx))
{
case MEM:
- fputc (' ', outfile);
+ fputs (" [", outfile);
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;
#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64