Commit 173b24b9 by Richard Kenner Committed by Richard Kenner

function.c (keep_stack_depressed): Don't use delete_insn.

	* 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.

From-SVN: r45922
parent bab3db73
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> 2001-09-30 H.J. Lu <hjl@gnu.org>
* acconfig.h (PREFIX_INCLUDE_DIR): New variable. * acconfig.h (PREFIX_INCLUDE_DIR): New variable.
......
...@@ -276,24 +276,6 @@ alias_sets_conflict_p (set1, set2) ...@@ -276,24 +276,6 @@ alias_sets_conflict_p (set1, set2)
return 0; 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 /* 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 has any readonly fields. If any of the fields have types that
contain readonly fields, return true as well. */ contain readonly fields, return true as well. */
......
...@@ -144,6 +144,9 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1]; ...@@ -144,6 +144,9 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
static htab_t const_int_htab; 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 /* 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: shortly thrown away. We use two mechanisms to prevent this waste:
...@@ -182,14 +185,17 @@ static void mark_label_nuses PARAMS ((rtx)); ...@@ -182,14 +185,17 @@ static void mark_label_nuses PARAMS ((rtx));
static hashval_t const_int_htab_hash PARAMS ((const void *)); static hashval_t const_int_htab_hash PARAMS ((const void *));
static int const_int_htab_eq PARAMS ((const void *, static int const_int_htab_eq PARAMS ((const void *,
const void *)); const void *));
static int rtx_htab_mark_1 PARAMS ((void **, void *)); static hashval_t mem_attrs_htab_hash PARAMS ((const void *));
static void rtx_htab_mark PARAMS ((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. /* Probability of the conditional branch currently proceeded by try_split.
Set to -1 otherwise. */ Set to -1 otherwise. */
int split_branch_probability = -1; int split_branch_probability = -1;
/* Returns a hash code for X (which is a really a CONST_INT). */ /* Returns a hash code for X (which is a really a CONST_INT). */
static hashval_t static hashval_t
...@@ -211,26 +217,83 @@ const_int_htab_eq (x, y) ...@@ -211,26 +217,83 @@ const_int_htab_eq (x, y)
return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) 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 /* Returns a hash code for X (which is a really a mem_attrs *). */
rtx). */
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 static int
rtx_htab_mark_1 (x, data) mem_attrs_htab_eq (x, y)
void **x; const void *x;
void *data ATTRIBUTE_UNUSED; const void *y;
{ {
ggc_mark_rtx (*x); mem_attrs *p = (mem_attrs *) x;
return 1; 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 /* This routine is called when we determine that we need a mem_attrs entry.
rtxs). */ It marks the associated decl and RTL as being used, if present. */
static void static void
rtx_htab_mark (htab) mem_attrs_mark (x)
void *htab; const void *x;
{
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;
{ {
htab_traverse (*((htab_t *) htab), rtx_htab_mark_1, NULL); 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 /* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
...@@ -350,7 +413,7 @@ gen_rtx_MEM (mode, addr) ...@@ -350,7 +413,7 @@ gen_rtx_MEM (mode, addr)
/* This field is not cleared by the mere allocation of the rtx, so /* This field is not cleared by the mere allocation of the rtx, so
we clear it here. */ we clear it here. */
MEM_ALIAS_SET (rt) = 0; MEM_ATTRS (rt) = 0;
return rt; return rt;
} }
...@@ -377,9 +440,9 @@ gen_rtx_SUBREG (mode, reg, offset) ...@@ -377,9 +440,9 @@ gen_rtx_SUBREG (mode, reg, offset)
return gen_rtx_fmt_ei (SUBREG, mode, reg, offset); return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
} }
/* Generate a SUBREG representing the least-significant part /* Generate a SUBREG representing the least-significant part of REG if MODE
* of REG if MODE is smaller than mode of REG, otherwise is smaller than mode of REG, otherwise paradoxical SUBREG. */
* paradoxical SUBREG. */
rtx rtx
gen_lowpart_SUBREG (mode, reg) gen_lowpart_SUBREG (mode, reg)
enum machine_mode mode; enum machine_mode mode;
...@@ -557,7 +620,6 @@ gen_rtvec_v (n, argp) ...@@ -557,7 +620,6 @@ gen_rtvec_v (n, argp)
return rt_val; return rt_val;
} }
/* Generate a REG rtx for a new pseudo register of mode MODE. /* Generate a REG rtx for a new pseudo register of mode MODE.
This pseudo is assigned the next sequential register number. */ This pseudo is assigned the next sequential register number. */
...@@ -1569,6 +1631,103 @@ reverse_comparison (insn) ...@@ -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 /* 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.
...@@ -4281,11 +4440,14 @@ init_emit_once (line_numbers) ...@@ -4281,11 +4440,14 @@ init_emit_once (line_numbers)
enum machine_mode mode; enum machine_mode mode;
enum machine_mode double_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 = htab_create (37, const_int_htab_hash,
const_int_htab_eq, NULL); const_int_htab_eq, NULL);
ggc_add_root (&const_int_htab, 1, sizeof (const_int_htab), ggc_add_deletable_htab (const_int_htab, 0, 0);
rtx_htab_mark);
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; no_line_numbers = ! line_numbers;
......
...@@ -643,82 +643,6 @@ maybe_set_unchanging (ref, t) ...@@ -643,82 +643,6 @@ maybe_set_unchanging (ref, t)
RTX_UNCHANGING_P (ref) = 1; 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 /* Return a modified copy of X with its memory address copied
into a temporary register to protect it from side effects. into a temporary register to protect it from side effects.
If X is not a MEM, it is returned unchanged (and not copied). If X is not a MEM, it is returned unchanged (and not copied).
......
...@@ -602,6 +602,9 @@ extern rtx memory_address PARAMS ((enum machine_mode, rtx)); ...@@ -602,6 +602,9 @@ extern rtx memory_address PARAMS ((enum machine_mode, rtx));
/* Like `memory_address' but pretent `flag_force_addr' is 0. */ /* Like `memory_address' but pretent `flag_force_addr' is 0. */
extern rtx memory_address_noforce PARAMS ((enum machine_mode, rtx)); 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 /* 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.
......
...@@ -1406,6 +1406,7 @@ put_var_into_stack (decl) ...@@ -1406,6 +1406,7 @@ put_var_into_stack (decl)
/* Change the CONCAT into a combined MEM for both parts. */ /* Change the CONCAT into a combined MEM for both parts. */
PUT_CODE (reg, MEM); PUT_CODE (reg, MEM);
MEM_ATTRS (reg) = 0;
/* set_mem_attributes uses DECL_RTL to avoid re-generating of /* set_mem_attributes uses DECL_RTL to avoid re-generating of
already computed alias sets. Here we want to re-generate. */ 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, ...@@ -1476,6 +1477,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
PUT_CODE (reg, MEM); PUT_CODE (reg, MEM);
PUT_MODE (reg, decl_mode); PUT_MODE (reg, decl_mode);
XEXP (reg, 0) = XEXP (new, 0); XEXP (reg, 0) = XEXP (new, 0);
MEM_ATTRS (reg) = 0;
/* `volatil' bit means one thing for MEMs, another entirely for REGs. */ /* `volatil' bit means one thing for MEMs, another entirely for REGs. */
MEM_VOLATILE_P (reg) = volatile_p; MEM_VOLATILE_P (reg) = volatile_p;
...@@ -1490,6 +1492,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, 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)); AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
set_mem_alias_set (reg, get_alias_set (type)); set_mem_alias_set (reg, get_alias_set (type));
} }
if (used_p) if (used_p)
schedule_fixup_var_refs (function, reg, type, promoted_mode, ht); schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
} }
...@@ -2840,29 +2843,35 @@ gen_mem_addressof (reg, decl) ...@@ -2840,29 +2843,35 @@ gen_mem_addressof (reg, decl)
RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg); RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
PUT_CODE (reg, MEM); PUT_CODE (reg, MEM);
MEM_ATTRS (reg) = 0;
XEXP (reg, 0) = r; XEXP (reg, 0) = r;
if (decl) if (decl)
{ {
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
enum machine_mode decl_mode enum machine_mode decl_mode
= (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl)) = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
: DECL_MODE (decl)); : DECL_MODE (decl));
rtx decl_rtl = decl ? DECL_RTL_IF_SET (decl) : 0;
PUT_MODE (reg, decl_mode); 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); set_mem_alias_set (reg, set);
if (decl_rtl == reg)
SET_DECL_RTL (decl, reg);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0) if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0); fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
} }
else 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; return reg;
} }
...@@ -7141,8 +7150,11 @@ keep_stack_depressed (seq) ...@@ -7141,8 +7150,11 @@ keep_stack_depressed (seq)
else else
sp_modified_unknown = 1; sp_modified_unknown = 1;
/* Don't allow the SP modification to happen. */ /* Don't allow the SP modification to happen. We don't call
delete_insn (insn); 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))) else if (reg_referenced_p (stack_pointer_rtx, PATTERN (insn)))
{ {
......
...@@ -298,6 +298,9 @@ ggc_mark_rtx_children (r) ...@@ -298,6 +298,9 @@ ggc_mark_rtx_children (r)
have any right poking our noses in? */ have any right poking our noses in? */
switch (code) switch (code)
{ {
case MEM:
ggc_mark (MEM_ATTRS (r));
break;
case JUMP_INSN: case JUMP_INSN:
ggc_mark_rtx (JUMP_LABEL (r)); ggc_mark_rtx (JUMP_LABEL (r));
break; break;
......
...@@ -1130,16 +1130,6 @@ reload (first, global) ...@@ -1130,16 +1130,6 @@ reload (first, global)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
{ {
rtx addr = 0; 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]) if (reg_equiv_mem[i])
addr = XEXP (reg_equiv_mem[i], 0); addr = XEXP (reg_equiv_mem[i], 0);
...@@ -1152,15 +1142,18 @@ reload (first, global) ...@@ -1152,15 +1142,18 @@ reload (first, global)
if (reg_renumber[i] < 0) if (reg_renumber[i] < 0)
{ {
rtx reg = regno_reg_rtx[i]; rtx reg = regno_reg_rtx[i];
PUT_CODE (reg, MEM); PUT_CODE (reg, MEM);
XEXP (reg, 0) = addr; XEXP (reg, 0) = addr;
REG_USERVAR_P (reg) = 0; REG_USERVAR_P (reg) = 0;
RTX_UNCHANGING_P (reg) = is_readonly; if (reg_equiv_memory_loc[i])
MEM_IN_STRUCT_P (reg) = in_struct; MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
MEM_SCALAR_P (reg) = is_scalar; else
/* We have no alias information about this newly created {
MEM. */ RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
set_mem_alias_set (reg, 0); = MEM_SCALAR_P (reg) = 0;
MEM_ATTRS (reg) = 0;
}
} }
else if (reg_equiv_mem[i]) else if (reg_equiv_mem[i])
XEXP (reg_equiv_mem[i], 0) = addr; XEXP (reg_equiv_mem[i], 0) = addr;
......
...@@ -31,8 +31,8 @@ struct function; ...@@ -31,8 +31,8 @@ struct function;
#undef ABS /* Likewise. */ #undef ABS /* Likewise. */
#undef PC /* 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 #define NOOP_MOVE_INSN_CODE INT_MAX
/* Register Transfer Language EXPRESSIONS CODES */ /* Register Transfer Language EXPRESSIONS CODES */
...@@ -71,16 +71,33 @@ typedef struct ...@@ -71,16 +71,33 @@ typedef struct
unsigned min_align: 8; unsigned min_align: 8;
/* Flags: */ /* Flags: */
unsigned base_after_vec: 1; /* BASE is after the ADDR_DIFF_VEC. */ 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 min_after_vec: 1; /* minimum address target label is
unsigned max_after_vec: 1; /* maximum address target label is after the ADDR_DIFF_VEC. */ after the ADDR_DIFF_VEC. */
unsigned min_after_base: 1; /* minimum address target label is after BASE. */ unsigned max_after_vec: 1; /* maximum address target label is
unsigned max_after_base: 1; /* maximum address target label is after BASE. */ 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 - : */ /* Set by the actual branch shortening process - ONLY WHEN OPTIMIZING - : */
unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned. */ unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned. */
unsigned : 2; unsigned : 2;
unsigned scale : 8; unsigned scale : 8;
} addr_diff_vec_flags; } 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. */ /* Common union for an element of an rtx. */
typedef union rtunion_def typedef union rtunion_def
...@@ -97,6 +114,7 @@ typedef union rtunion_def ...@@ -97,6 +114,7 @@ typedef union rtunion_def
struct bitmap_head_def *rtbit; struct bitmap_head_def *rtbit;
tree rttree; tree rttree;
struct basic_block_def *bb; struct basic_block_def *bb;
mem_attrs *rtmem;
} rtunion; } rtunion;
/* RTL expression ("rtx"). */ /* RTL expression ("rtx"). */
...@@ -340,6 +358,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int, ...@@ -340,6 +358,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
#define X0BBDEF(RTX, N) (RTL_CHECK1(RTX, N, '0').bb) #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 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 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 XCWINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtwint)
#define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint) #define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint)
...@@ -862,6 +881,10 @@ extern unsigned int subreg_regno PARAMS ((rtx)); ...@@ -862,6 +881,10 @@ extern unsigned int subreg_regno PARAMS ((rtx));
} \ } \
} while (0) } 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 /* 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 set, and may alias anything. Otherwise, the MEM can only alias
MEMs in the same alias set. This value is set in a MEMs in the same alias set. This value is set in a
...@@ -871,15 +894,30 @@ extern unsigned int subreg_regno PARAMS ((rtx)); ...@@ -871,15 +894,30 @@ extern unsigned int subreg_regno PARAMS ((rtx));
some front-ends, these numbers may correspond in some way to types, some front-ends, these numbers may correspond in some way to types,
or other language-level entities, but they need not, and the or other language-level entities, but they need not, and the
back-end makes no such assumptions. */ 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. */ /* Copy the attributes that apply to memory locations from RHS to LHS. */
#define MEM_COPY_ATTRIBUTES(LHS, RHS) \ #define MEM_COPY_ATTRIBUTES(LHS, RHS) \
(MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \ (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \ MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_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 /* For a LABEL_REF, 1 means that this reference is to a label outside the
loop containing the reference. */ loop containing the reference. */
...@@ -2010,7 +2048,6 @@ extern void init_alias_once PARAMS ((void)); ...@@ -2010,7 +2048,6 @@ extern void init_alias_once PARAMS ((void));
extern void init_alias_analysis PARAMS ((void)); extern void init_alias_analysis PARAMS ((void));
extern void end_alias_analysis PARAMS ((void)); extern void end_alias_analysis PARAMS ((void));
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int)); extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
/* In sibcall.c */ /* In sibcall.c */
typedef enum { typedef enum {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment