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));
rtx
gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
{
- register int i; /* Array indices... */
- register const char *fmt; /* Current rtx's format... */
- register rtx rt_val; /* RTX to return to caller... */
+ int i; /* Array indices... */
+ const char *fmt; /* Current rtx's format... */
+ rtx rt_val; /* RTX to return to caller... */
VA_OPEN (p, mode);
VA_FIXEDARG (p, enum rtx_code, code);
int n;
rtx *argp;
{
- register int i;
- register rtvec rt_val;
+ int i;
+ rtvec rt_val;
if (n == 0)
return NULL_RTVEC; /* Don't allocate an empty rtvec... */
enum machine_mode mode;
{
struct function *f = cfun;
- register rtx val;
+ rtx val;
/* Don't let anything called after initial flow analysis create new
registers. */
register. */
int
subreg_hard_regno (x, check_mode)
- register rtx x;
+ rtx x;
int check_mode;
{
enum machine_mode mode = GET_MODE (x);
rtx
gen_lowpart_common (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
int msize = GET_MODE_SIZE (mode);
int xsize = GET_MODE_SIZE (GET_MODE (x));
rtx
gen_realpart (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
if (WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
rtx
gen_imagpart (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
rtx
gen_lowpart (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
rtx result = gen_lowpart_common (mode, x);
else if (GET_CODE (x) == MEM)
{
/* The only additional case we can do is MEM. */
- register int offset = 0;
+ int offset = 0;
if (WORDS_BIG_ENDIAN)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
rtx
gen_highpart (mode, x)
enum machine_mode mode;
- register rtx x;
+ rtx x;
{
unsigned int msize = GET_MODE_SIZE (mode);
rtx result;
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
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);
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;
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. */
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)))
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);
+}
\f
-/* 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;
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
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
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);
}
\f
rtx
gen_label_rtx ()
{
- register rtx label;
+ rtx label;
label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX,
NULL_RTX, label_num++, NULL, NULL);
copy_rtx_if_shared (orig)
rtx orig;
{
- register rtx x = orig;
- register int i;
- register enum rtx_code code;
- register const char *format_ptr;
+ rtx x = orig;
+ int i;
+ enum rtx_code code;
+ const char *format_ptr;
int copied = 0;
if (x == 0)
if (x->used)
{
- register rtx copy;
+ rtx copy;
copy = rtx_alloc (code);
memcpy (copy, x,
case 'E':
if (XVEC (x, i) != NULL)
{
- register int j;
+ int j;
int len = XVECLEN (x, i);
if (copied && len > 0)
reset_used_flags (x)
rtx x;
{
- register int i, j;
- register enum rtx_code code;
- register const char *format_ptr;
+ int i, j;
+ enum rtx_code code;
+ const char *format_ptr;
if (x == 0)
return;
mark_label_nuses(x)
rtx x;
{
- register enum rtx_code code;
- register int i, j;
- register const char *fmt;
+ enum rtx_code code;
+ int i, j;
+ const char *fmt;
code = GET_CODE (x);
if (code == LABEL_REF)
make_insn_raw (pattern)
rtx pattern;
{
- register rtx insn;
+ rtx insn;
insn = rtx_alloc (INSN);
make_jump_insn_raw (pattern)
rtx pattern;
{
- register rtx insn;
+ rtx insn;
insn = rtx_alloc (JUMP_INSN);
INSN_UID (insn) = cur_insn_uid++;
make_call_insn_raw (pattern)
rtx pattern;
{
- register rtx insn;
+ rtx insn;
insn = rtx_alloc (CALL_INSN);
INSN_UID (insn) = cur_insn_uid++;
void
add_insn (insn)
- register rtx insn;
+ rtx insn;
{
PREV_INSN (insn) = last_insn;
NEXT_INSN (insn) = 0;
rtx
emit_insn_before (pattern, before)
- register rtx pattern, before;
+ rtx pattern, before;
{
- register rtx insn = before;
+ rtx insn = before;
if (GET_CODE (pattern) == SEQUENCE)
{
- register int i;
+ int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
rtx
emit_jump_insn_before (pattern, before)
- register rtx pattern, before;
+ rtx pattern, before;
{
- register rtx insn;
+ rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_before (pattern, before);
rtx
emit_call_insn_before (pattern, before)
- register rtx pattern, before;
+ rtx pattern, before;
{
- register rtx insn;
+ rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_before (pattern, before);
rtx
emit_barrier_before (before)
- register rtx before;
+ rtx before;
{
- register rtx insn = rtx_alloc (BARRIER);
+ rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
int subtype;
rtx before;
{
- register rtx note = rtx_alloc (NOTE);
+ rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
rtx
emit_insn_after (pattern, after)
- register rtx pattern, after;
+ rtx pattern, after;
{
- register rtx insn = after;
+ rtx insn = after;
if (GET_CODE (pattern) == SEQUENCE)
{
- register int i;
+ int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
rtx
emit_jump_insn_after (pattern, after)
- register rtx pattern, after;
+ rtx pattern, after;
{
- register rtx insn;
+ rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_after (pattern, after);
rtx
emit_barrier_after (after)
- register rtx after;
+ rtx after;
{
- register rtx insn = rtx_alloc (BARRIER);
+ rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
int subtype;
rtx after;
{
- register rtx note = rtx_alloc (NOTE);
+ rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
int line;
rtx after;
{
- register rtx note;
+ rtx note;
if (no_line_numbers && line > 0)
{
if (GET_CODE (pattern) == SEQUENCE)
{
- register int i;
+ int i;
for (i = 0; i < XVECLEN (pattern, 0); i++)
{
rtx
emit_insns_after (first, after)
- register rtx first;
- register rtx after;
+ rtx first;
+ rtx after;
{
- register rtx last;
- register rtx after_after;
+ rtx last;
+ rtx after_after;
basic_block bb;
if (!after)
return emit_insn (pattern);
else
{
- register rtx insn = make_jump_insn_raw (pattern);
+ rtx insn = make_jump_insn_raw (pattern);
add_insn (insn);
return insn;
}
return emit_insn (pattern);
else
{
- register rtx insn = make_call_insn_raw (pattern);
+ rtx insn = make_call_insn_raw (pattern);
add_insn (insn);
PUT_CODE (insn, CALL_INSN);
return insn;
rtx
emit_barrier ()
{
- register rtx barrier = rtx_alloc (BARRIER);
+ rtx barrier = rtx_alloc (BARRIER);
INSN_UID (barrier) = cur_insn_uid++;
add_insn (barrier);
return barrier;
const char *file;
int line;
{
- register rtx note;
+ rtx note;
if (line > 0)
{
}
if (GET_CODE (x) == PARALLEL)
{
- register int j;
+ int j;
for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
return CALL_INSN;
return emit_insn (x);
else if (code == JUMP_INSN)
{
- register rtx insn = emit_jump_insn (x);
+ rtx insn = emit_jump_insn (x);
if (any_uncondjump_p (insn) || GET_CODE (x) == RETURN)
return emit_barrier ();
return insn;
rtx
copy_insn_1 (orig)
- register rtx orig;
+ rtx orig;
{
- register rtx copy;
- register int i, j;
- register RTX_CODE code;
- register const char *format_ptr;
+ rtx copy;
+ int i, j;
+ RTX_CODE code;
+ const char *format_ptr;
code = GET_CODE (orig);