aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-10-01 11:00:47 +0000
committerRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-10-01 11:00:47 +0000
commit755e421f01ff514056a2c663117a1716b275210b (patch)
treea2295f973363e17dc793a7b1597e907c1198e6a0
parentc95c69d9680fe28b6cbf1df2fe24d2b9c6130af6 (diff)
* function.c (keep_stack_depressed): Don't use delete_insn.
* expr.h (set_mem_alias_set): Move decl to here. * rtl.h (mem_attrs): New typedef and struct. (union rtunion_def): Add field for mem_attrs. (X0MEMATTR, MEM_ATTRS): New macros. (MEM_ALIAS_SET): Use MEM_ATTRS. (MEM_DECL, MEM_OFFSET, MEM_SIZE, MEM_ALIGN): New macros. (MEM_COPY_ATTRIBUTES): Copy MEM_ATTRS. (set_mem_alias_set): Delete decl from here. * alias.c (set_mem_alias_set): Delete from here. * emit-rtl.c (mem_attrs_htab): New variable. (rtx_htab_mark, rtx_htab_mark_1): Deleted. (mem_attrs_htab_hash, mem_attrs_htab_eq): New functions. (mem_attrs_mark, get_mem_attrs): Likewise. (gen_rtx_MEM): Clear MEM_ATTRS. (set_mem_attributes): Move to here. (set_mem_alias_set): Likewise, and call get_mem_attrs. (init_emit_once): const_int_htab now deletable htab. Initialize mem_attrs_htab. * explow.c (set_mem_attributes): Delete from here. * function.c (put_var_into_stack): Clear MEM_ATTRS. (gen_mem_addressof): Likewise; rework to use set_mem_attributes. * ggc-common.c (ggc_mark_rtx_children, case MEM): New case. * reload1.c (reload): Rework changing REG to MEM. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@45922 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog29
-rw-r--r--gcc/alias.c18
-rw-r--r--gcc/emit-rtl.c208
-rw-r--r--gcc/explow.c76
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/function.c32
-rw-r--r--gcc/ggc-common.c3
-rw-r--r--gcc/reload1.c25
-rw-r--r--gcc/rtl.h57
9 files changed, 298 insertions, 153 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 450742836df..8993b5ac05b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,32 @@
+Mon Oct 1 06:43:41 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * function.c (keep_stack_depressed): Don't use delete_insn.
+
+ * expr.h (set_mem_alias_set): Move decl to here.
+ * rtl.h (mem_attrs): New typedef and struct.
+ (union rtunion_def): Add field for mem_attrs.
+ (X0MEMATTR, MEM_ATTRS): New macros.
+ (MEM_ALIAS_SET): Use MEM_ATTRS.
+ (MEM_DECL, MEM_OFFSET, MEM_SIZE, MEM_ALIGN): New macros.
+ (MEM_COPY_ATTRIBUTES): Copy MEM_ATTRS.
+ (set_mem_alias_set): Delete decl from here.
+
+ * alias.c (set_mem_alias_set): Delete from here.
+ * emit-rtl.c (mem_attrs_htab): New variable.
+ (rtx_htab_mark, rtx_htab_mark_1): Deleted.
+ (mem_attrs_htab_hash, mem_attrs_htab_eq): New functions.
+ (mem_attrs_mark, get_mem_attrs): Likewise.
+ (gen_rtx_MEM): Clear MEM_ATTRS.
+ (set_mem_attributes): Move to here.
+ (set_mem_alias_set): Likewise, and call get_mem_attrs.
+ (init_emit_once): const_int_htab now deletable htab.
+ Initialize mem_attrs_htab.
+ * explow.c (set_mem_attributes): Delete from here.
+ * function.c (put_var_into_stack): Clear MEM_ATTRS.
+ (gen_mem_addressof): Likewise; rework to use set_mem_attributes.
+ * ggc-common.c (ggc_mark_rtx_children, case MEM): New case.
+ * reload1.c (reload): Rework changing REG to MEM.
+
2001-09-30 H.J. Lu <hjl@gnu.org>
* acconfig.h (PREFIX_INCLUDE_DIR): New variable.
diff --git a/gcc/alias.c b/gcc/alias.c
index abb593a6d9d..bf7c5e33e4f 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -276,24 +276,6 @@ alias_sets_conflict_p (set1, set2)
return 0;
}
-/* Set the alias set of MEM to SET. */
-
-void
-set_mem_alias_set (mem, set)
- rtx mem;
- HOST_WIDE_INT set;
-{
- /* We would like to do this test but can't yet since when converting a
- REG to a MEM, the alias set field is undefined. */
-#if 0
- /* If the new and old alias sets don't conflict, something is wrong. */
- if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
- abort ();
-#endif
-
- MEM_ALIAS_SET (mem) = set;
-}
-
/* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
has any readonly fields. If any of the fields have types that
contain readonly fields, return true as well. */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index f33df263382..eeb5128fec9 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -144,6 +144,9 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
static htab_t const_int_htab;
+/* A hash table storing memory attribute structures. */
+static htab_t mem_attrs_htab;
+
/* start_sequence and gen_sequence can make a lot of rtx expressions which are
shortly thrown away. We use two mechanisms to prevent this waste:
@@ -182,13 +185,16 @@ static void mark_label_nuses PARAMS ((rtx));
static hashval_t const_int_htab_hash PARAMS ((const void *));
static int const_int_htab_eq PARAMS ((const void *,
const void *));
-static int rtx_htab_mark_1 PARAMS ((void **, void *));
-static void rtx_htab_mark PARAMS ((void *));
+static hashval_t mem_attrs_htab_hash PARAMS ((const void *));
+static int mem_attrs_htab_eq PARAMS ((const void *,
+ const void *));
+static void mem_attrs_mark PARAMS ((const void *));
+static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx,
+ rtx, unsigned int));
/* Probability of the conditional branch currently proceeded by try_split.
Set to -1 otherwise. */
int split_branch_probability = -1;
-
/* Returns a hash code for X (which is a really a CONST_INT). */
@@ -211,26 +217,83 @@ const_int_htab_eq (x, y)
return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y));
}
-/* Mark the hash-table element X (which is really a pointer to an
- rtx). */
+/* Returns a hash code for X (which is a really a mem_attrs *). */
+
+static hashval_t
+mem_attrs_htab_hash (x)
+ const void *x;
+{
+ mem_attrs *p = (mem_attrs *) x;
+
+ return (p->alias ^ (p->align * 1000)
+ ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
+ ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
+ ^ (long) p->decl);
+}
+
+/* Returns non-zero if the value represented by X (which is really a
+ mem_attrs *) is the same as that given by Y (which is also really a
+ mem_attrs *). */
static int
-rtx_htab_mark_1 (x, data)
- void **x;
- void *data ATTRIBUTE_UNUSED;
+mem_attrs_htab_eq (x, y)
+ const void *x;
+ const void *y;
{
- ggc_mark_rtx (*x);
- return 1;
+ 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
+ && p->size == q->size && p->align == q->align);
}
-/* Mark all the elements of HTAB (which is really an htab_t full of
- rtxs). */
+/* This routine is called when we determine that we need a mem_attrs entry.
+ It marks the associated decl and RTL as being used, if present. */
static void
-rtx_htab_mark (htab)
- void *htab;
+mem_attrs_mark (x)
+ const void *x;
{
- htab_traverse (*((htab_t *) htab), rtx_htab_mark_1, NULL);
+ mem_attrs *p = (mem_attrs *) x;
+
+ if (p->decl)
+ ggc_mark_tree (p->decl);
+
+ if (p->offset)
+ ggc_mark_rtx (p->offset);
+
+ if (p->size)
+ ggc_mark_rtx (p->size);
+}
+
+/* Allocate a new mem_attrs structure and insert it into the hash table if
+ one identical to it is not already in the table. */
+
+static mem_attrs *
+get_mem_attrs (alias, decl, offset, size, align)
+ HOST_WIDE_INT alias;
+ tree decl;
+ rtx offset;
+ rtx size;
+ unsigned int align;
+{
+ mem_attrs attrs;
+ void **slot;
+
+ attrs.alias = alias;
+ attrs.decl = decl;
+ attrs.offset = offset;
+ attrs.size = size;
+ attrs.align = align;
+
+ slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT);
+ if (*slot == 0)
+ {
+ *slot = ggc_alloc (sizeof (mem_attrs));
+ memcpy (*slot, &attrs, sizeof (mem_attrs));
+ }
+
+ return *slot;
}
/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
@@ -350,7 +413,7 @@ gen_rtx_MEM (mode, addr)
/* This field is not cleared by the mere allocation of the rtx, so
we clear it here. */
- MEM_ALIAS_SET (rt) = 0;
+ MEM_ATTRS (rt) = 0;
return rt;
}
@@ -377,9 +440,9 @@ gen_rtx_SUBREG (mode, reg, offset)
return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
}
-/* Generate a SUBREG representing the least-significant part
- * of REG if MODE is smaller than mode of REG, otherwise
- * paradoxical SUBREG. */
+/* Generate a SUBREG representing the least-significant part of REG if MODE
+ is smaller than mode of REG, otherwise paradoxical SUBREG. */
+
rtx
gen_lowpart_SUBREG (mode, reg)
enum machine_mode mode;
@@ -556,7 +619,6 @@ gen_rtvec_v (n, argp)
return rt_val;
}
-
/* Generate a REG rtx for a new pseudo register of mode MODE.
This pseudo is assigned the next sequential register number. */
@@ -1569,6 +1631,103 @@ reverse_comparison (insn)
}
}
+
+/* Given REF, a MEM, and T, either the type of X or the expression
+ corresponding to REF, set the memory attributes. OBJECTP is nonzero
+ if we are making a new object of this type. */
+
+void
+set_mem_attributes (ref, t, objectp)
+ rtx ref;
+ tree t;
+ int objectp;
+{
+ tree type;
+
+ /* It can happen that type_for_mode was given a mode for which there
+ is no language-level type. In which case it returns NULL, which
+ we can see here. */
+ if (t == NULL_TREE)
+ return;
+
+ 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
+ set_mem_attributes. */
+ if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
+ abort ();
+
+ set_mem_alias_set (ref, get_alias_set (t));
+
+ MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
+ MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
+
+ /* If we are making an object of this type, we know that it is a scalar if
+ the type is not an aggregate. */
+ 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
+ to deduce some more information about the expression. */
+ if (TYPE_P (t))
+ return;
+
+ maybe_set_unchanging (ref, t);
+ 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);
+
+ /* 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. */
+ if (DECL_P (t))
+ MEM_SCALAR_P (ref) = 1;
+ else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
+ || TREE_CODE (t) == ARRAY_RANGE_REF
+ || TREE_CODE (t) == BIT_FIELD_REF)
+ MEM_IN_STRUCT_P (ref) = 1;
+}
+
+/* Set the alias set of MEM to SET. */
+
+void
+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. */
+#if 0
+#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)))
+ abort ();
+#endif
+#endif
+
+ MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (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.
@@ -4281,11 +4440,14 @@ init_emit_once (line_numbers)
enum machine_mode mode;
enum machine_mode double_mode;
- /* Initialize the CONST_INT hash table. */
+ /* Initialize the CONST_INT and memory attribute hash tables. */
const_int_htab = htab_create (37, const_int_htab_hash,
const_int_htab_eq, NULL);
- ggc_add_root (&const_int_htab, 1, sizeof (const_int_htab),
- rtx_htab_mark);
+ ggc_add_deletable_htab (const_int_htab, 0, 0);
+
+ mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
+ mem_attrs_htab_eq, NULL);
+ ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark);
no_line_numbers = ! line_numbers;
diff --git a/gcc/explow.c b/gcc/explow.c
index d01067de7ff..85c3a7dc77b 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -642,82 +642,6 @@ maybe_set_unchanging (ref, t)
|| TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
RTX_UNCHANGING_P (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
- if we are making a new object of this type. */
-
-void
-set_mem_attributes (ref, t, objectp)
- rtx ref;
- tree t;
- int objectp;
-{
- tree type;
-
- /* It can happen that type_for_mode was given a mode for which there
- is no language-level type. In which case it returns NULL, which
- we can see here. */
- if (t == NULL_TREE)
- return;
-
- 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
- set_mem_attributes. */
- if (DECL_P (t) && ref == DECL_RTL_IF_SET (t))
- abort ();
-
- set_mem_alias_set (ref, get_alias_set (t));
-
- MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
- MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
-
- /* If we are making an object of this type, we know that it is a scalar if
- the type is not an aggregate. */
- 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
- to deduce some more information about the expression. */
- if (TYPE_P (t))
- return;
-
- maybe_set_unchanging (ref, t);
- 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);
-
- /* 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. */
- if (DECL_P (t))
- MEM_SCALAR_P (ref) = 1;
- else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
- || TREE_CODE (t) == ARRAY_RANGE_REF
- || TREE_CODE (t) == BIT_FIELD_REF)
- MEM_IN_STRUCT_P (ref) = 1;
-}
/* Return a modified copy of X with its memory address copied
into a temporary register to protect it from side effects.
diff --git a/gcc/expr.h b/gcc/expr.h
index e340b8bf950..9addf7f7326 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -602,6 +602,9 @@ extern rtx memory_address PARAMS ((enum machine_mode, rtx));
/* Like `memory_address' but pretent `flag_force_addr' is 0. */
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));
+
/* 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.
diff --git a/gcc/function.c b/gcc/function.c
index c6fa510ef40..fed2b3b68c7 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -1406,6 +1406,7 @@ put_var_into_stack (decl)
/* Change the CONCAT into a combined MEM for both parts. */
PUT_CODE (reg, MEM);
+ MEM_ATTRS (reg) = 0;
/* set_mem_attributes uses DECL_RTL to avoid re-generating of
already computed alias sets. Here we want to re-generate. */
@@ -1476,6 +1477,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
PUT_CODE (reg, MEM);
PUT_MODE (reg, decl_mode);
XEXP (reg, 0) = XEXP (new, 0);
+ MEM_ATTRS (reg) = 0;
/* `volatil' bit means one thing for MEMs, another entirely for REGs. */
MEM_VOLATILE_P (reg) = volatile_p;
@@ -1490,6 +1492,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
set_mem_alias_set (reg, get_alias_set (type));
}
+
if (used_p)
schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
}
@@ -2840,29 +2843,35 @@ gen_mem_addressof (reg, decl)
RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
PUT_CODE (reg, MEM);
+ MEM_ATTRS (reg) = 0;
XEXP (reg, 0) = r;
+
if (decl)
{
tree type = TREE_TYPE (decl);
enum machine_mode decl_mode
= (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
: DECL_MODE (decl));
+ rtx decl_rtl = decl ? DECL_RTL_IF_SET (decl) : 0;
PUT_MODE (reg, decl_mode);
- MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
- MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
+
+ /* Clear DECL_RTL momentarily so functions below will work
+ properly, then set it again. */
+ if (decl_rtl == reg)
+ SET_DECL_RTL (decl, 0);
+
+ set_mem_attributes (reg, decl, 1);
set_mem_alias_set (reg, set);
+ if (decl_rtl == reg)
+ SET_DECL_RTL (decl, reg);
+
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
}
else
- {
- /* We have no alias information about this newly created MEM. */
- set_mem_alias_set (reg, 0);
-
- fixup_var_refs (reg, GET_MODE (reg), 0, 0);
- }
+ fixup_var_refs (reg, GET_MODE (reg), 0, 0);
return reg;
}
@@ -7141,8 +7150,11 @@ keep_stack_depressed (seq)
else
sp_modified_unknown = 1;
- /* Don't allow the SP modification to happen. */
- delete_insn (insn);
+ /* Don't allow the SP modification to happen. We don't call
+ delete_insn here since INSN isn't in any chain. */
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
}
else if (reg_referenced_p (stack_pointer_rtx, PATTERN (insn)))
{
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 80de3802fed..53057c8a75b 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -298,6 +298,9 @@ ggc_mark_rtx_children (r)
have any right poking our noses in? */
switch (code)
{
+ case MEM:
+ ggc_mark (MEM_ATTRS (r));
+ break;
case JUMP_INSN:
ggc_mark_rtx (JUMP_LABEL (r));
break;
diff --git a/gcc/reload1.c b/gcc/reload1.c
index bc3456f931c..7828bf5a27b 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1130,16 +1130,6 @@ reload (first, global)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
{
rtx addr = 0;
- int in_struct = 0;
- int is_scalar = 0;
- int is_readonly = 0;
-
- if (reg_equiv_memory_loc[i])
- {
- in_struct = MEM_IN_STRUCT_P (reg_equiv_memory_loc[i]);
- is_scalar = MEM_SCALAR_P (reg_equiv_memory_loc[i]);
- is_readonly = RTX_UNCHANGING_P (reg_equiv_memory_loc[i]);
- }
if (reg_equiv_mem[i])
addr = XEXP (reg_equiv_mem[i], 0);
@@ -1152,15 +1142,18 @@ reload (first, global)
if (reg_renumber[i] < 0)
{
rtx reg = regno_reg_rtx[i];
+
PUT_CODE (reg, MEM);
XEXP (reg, 0) = addr;
REG_USERVAR_P (reg) = 0;
- RTX_UNCHANGING_P (reg) = is_readonly;
- MEM_IN_STRUCT_P (reg) = in_struct;
- MEM_SCALAR_P (reg) = is_scalar;
- /* We have no alias information about this newly created
- MEM. */
- set_mem_alias_set (reg, 0);
+ if (reg_equiv_memory_loc[i])
+ MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
+ else
+ {
+ RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
+ = MEM_SCALAR_P (reg) = 0;
+ MEM_ATTRS (reg) = 0;
+ }
}
else if (reg_equiv_mem[i])
XEXP (reg_equiv_mem[i], 0) = addr;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index d9b9294f33c..983036fae1b 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -31,8 +31,8 @@ struct function;
#undef ABS /* Likewise. */
#undef PC /* Likewise. */
-/* Value used by some passes to "recognize" noop moves as valid instructions.
- */
+/* Value used by some passes to "recognize" noop moves as valid
+ instructions. */
#define NOOP_MOVE_INSN_CODE INT_MAX
/* Register Transfer Language EXPRESSIONS CODES */
@@ -71,16 +71,33 @@ typedef struct
unsigned min_align: 8;
/* Flags: */
unsigned base_after_vec: 1; /* BASE is after the ADDR_DIFF_VEC. */
- unsigned min_after_vec: 1; /* minimum address target label is after the ADDR_DIFF_VEC. */
- unsigned max_after_vec: 1; /* maximum address target label is after the ADDR_DIFF_VEC. */
- unsigned min_after_base: 1; /* minimum address target label is after BASE. */
- unsigned max_after_base: 1; /* maximum address target label is after BASE. */
+ unsigned min_after_vec: 1; /* minimum address target label is
+ after the ADDR_DIFF_VEC. */
+ unsigned max_after_vec: 1; /* maximum address target label is
+ after the ADDR_DIFF_VEC. */
+ unsigned min_after_base: 1; /* minimum address target label is
+ after BASE. */
+ unsigned max_after_base: 1; /* maximum address target label is
+ after BASE. */
/* Set by the actual branch shortening process - ONLY WHEN OPTIMIZING - : */
unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned. */
unsigned : 2;
unsigned scale : 8;
} addr_diff_vec_flags;
+/* Structure used to describe the attributes of a MEM. These are hashed
+ so MEMs that the same attributes share a data structure. This means
+ they cannot be modified in place. If any element is nonzero, it means
+ the value of the corresponding attribute is unknown. */
+typedef struct
+{
+ HOST_WIDE_INT alias; /* Memory alias set. */
+ tree decl; /* decl 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 bytes. */
+} mem_attrs;
+
/* Common union for an element of an rtx. */
typedef union rtunion_def
@@ -97,6 +114,7 @@ typedef union rtunion_def
struct bitmap_head_def *rtbit;
tree rttree;
struct basic_block_def *bb;
+ mem_attrs *rtmem;
} rtunion;
/* RTL expression ("rtx"). */
@@ -340,6 +358,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
#define X0BBDEF(RTX, N) (RTL_CHECK1(RTX, N, '0').bb)
#define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
#define X0CSELIB(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_cselib)
+#define X0MEMATTR(RTX, N) (RTL_CHECK1(RTX, N, '0').rtmem)
#define XCWINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtwint)
#define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint)
@@ -862,6 +881,10 @@ extern unsigned int subreg_regno PARAMS ((rtx));
} \
} while (0)
+/* The memory attribute block. We provide access macros for each value
+ in the block and provide defaults if none specified. */
+#define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)
+
/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
set, and may alias anything. Otherwise, the MEM can only alias
MEMs in the same alias set. This value is set in a
@@ -871,15 +894,30 @@ extern unsigned int subreg_regno PARAMS ((rtx));
some front-ends, these numbers may correspond in some way to types,
or other language-level entities, but they need not, and the
back-end makes no such assumptions. */
-#define MEM_ALIAS_SET(RTX) XCWINT(RTX, 1, MEM)
+#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)
+
+/* For a MEM rtx, the offset from the start of MEM_DECL, if known, as a
+ RTX that is always a CONST_INT. */
+#define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
+
+/* For a MEM rtx, the size in bytes of the MEM, if known, as an RTX that
+ is always a CONST_INT. */
+#define MEM_SIZE(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->size)
+
+/* For a MEM rtx, the alignment in bytes. */
+#define MEM_ALIGN(RTX) (MEM_ATTRS (RTX) == 0 ? 1 : MEM_ATTRS (RTX)->align)
/* Copy the attributes that apply to memory locations from RHS to LHS. */
#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
(MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \
- MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS), \
- RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS))
+ RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS), \
+ MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
/* For a LABEL_REF, 1 means that this reference is to a label outside the
loop containing the reference. */
@@ -2010,7 +2048,6 @@ extern void init_alias_once PARAMS ((void));
extern void init_alias_analysis PARAMS ((void));
extern void end_alias_analysis PARAMS ((void));
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
-extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
/* In sibcall.c */
typedef enum {