#include "basic-block.h"
#include "ggc.h"
#include "debug.h"
+#include "langhooks.h"
/* Commonly used modes. */
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));
+ rtx, unsigned int,
+ enum machine_mode));
/* Probability of the conditional branch currently proceeded by try_split.
Set to -1 otherwise. */
}
/* Allocate a new mem_attrs structure and insert it into the hash table if
- one identical to it is not already in the table. */
+ one identical to it is not already in the table. We are doing this for
+ MEM of mode MODE. */
static mem_attrs *
-get_mem_attrs (alias, decl, offset, size, align)
+get_mem_attrs (alias, decl, offset, size, align, mode)
HOST_WIDE_INT alias;
tree decl;
rtx offset;
rtx size;
unsigned int align;
+ enum machine_mode mode;
{
mem_attrs attrs;
void **slot;
+ /* If everything is the default, we can just return zero. */
+ if (alias == 0 && decl == 0 && offset == 0
+ && (size == 0
+ || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
+ && (align == 1
+ || (mode != BLKmode && align == GET_MODE_ALIGNMENT (mode))))
+ return 0;
+
attrs.alias = alias;
attrs.decl = decl;
attrs.offset = offset;
only at run-time. */
rtx
-gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2)
+gen_rtx_CONST_DOUBLE (mode, arg0, arg1)
enum machine_mode mode;
- rtx arg0;
- HOST_WIDE_INT arg1, arg2;
+ HOST_WIDE_INT arg0, arg1;
{
rtx r = rtx_alloc (CONST_DOUBLE);
int i;
PUT_MODE (r, mode);
- XEXP (r, 0) = arg0;
- X0EXP (r, 1) = NULL_RTX;
+ X0EXP (r, 0) = NULL_RTX;
+ XWINT (r, 1) = arg0;
XWINT (r, 2) = arg1;
- XWINT (r, 3) = arg2;
- for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 3; --i)
+ for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 2; --i)
XWINT (r, i) = 0;
return r;
case CONST_DOUBLE:
{
- rtx arg0 = va_arg (p, rtx);
+ HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
- HOST_WIDE_INT arg2 = va_arg (p, HOST_WIDE_INT);
- rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2);
+
+ rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1);
}
break;
tree t;
int objectp;
{
+ HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);
+ tree decl = MEM_DECL (ref);
+ rtx offset = MEM_OFFSET (ref);
+ rtx size = MEM_SIZE (ref);
+ unsigned int align = MEM_ALIGN (ref);
tree type;
/* It can happen that type_for_mode was given a mode for which there
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));
+ front-end routine) and use it. */
+ alias = get_alias_set (t);
MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
RTX_UNCHANGING_P (ref)
- |= (lang_hooks.honor_readonly
- && (TYPE_READONLY (type) || TREE_READONLY (t)));
+ |= ((lang_hooks.honor_readonly
+ && (TYPE_READONLY (type) || TREE_READONLY (t)))
+ || (! TYPE_P (t) && TREE_CONSTANT (t)));
- /* 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))
+ /* If we are making an object of this type, or if this is a DECL, we know
+ that it is a scalar if the type is not an aggregate. */
+ if ((objectp || DECL_P (t)) && ! AGGREGATE_TYPE_P (type))
MEM_SCALAR_P (ref) = 1;
/* 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;
+ size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1));
+
+ /* If T is not a type, we may be able to deduce some more information about
+ the expression. */
+ if (! TYPE_P (t))
+ {
+ maybe_set_unchanging (ref, t);
+ if (TREE_THIS_VOLATILE (t))
+ MEM_VOLATILE_P (ref) = 1;
+
+ /* 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 expression can't be addressed (e.g., it contains a reference
+ to a non-addressable field), show we don't change its alias set. */
+ if (! can_address_p (t))
+ MEM_KEEP_ALIAS_SET_P (ref) = 1;
+
+ /* If this is a decl, set the attributes of the MEM from it. */
+ if (DECL_P (t))
+ {
+ decl = t;
+ offset = GEN_INT (0);
+ size = (DECL_SIZE_UNIT (t)
+ && host_integerp (DECL_SIZE_UNIT (t), 1)
+ ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
+ align = DECL_ALIGN (t);
+ }
- maybe_set_unchanging (ref, t);
- if (TREE_THIS_VOLATILE (t))
- MEM_VOLATILE_P (ref) = 1;
-
- /* 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);
-
- /* If this is an INDIRECT_REF, we know its alignment. */
- if (TREE_CODE (t) == INDIRECT_REF)
- set_mem_align (ref, TYPE_ALIGN (type) / 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))
+ /* If this is an INDIRECT_REF, we know its alignment. */
+ else if (TREE_CODE (t) == INDIRECT_REF)
+ align = TYPE_ALIGN (type);
+
+ /* Likewise for constants. */
+ else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+ {
+ align = TYPE_ALIGN (type);
+#ifdef CONSTANT_ALIGNMENT
+ align = CONSTANT_ALIGNMENT (t, align);
+#endif
+ }
+ }
+
+ /* Now set the attributes we computed above. */
+ MEM_ATTRS (ref)
+ = get_mem_attrs (alias, decl, offset, size, align, GET_MODE (ref));
+
+ /* If this is already known to be a scalar or aggregate, we are done. */
+ if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_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. */
- if (DECL_P (t))
- MEM_SCALAR_P (ref) = 1;
+ /* If it is a reference into an aggregate, this is part of an aggregate.
+ Otherwise we don't know. */
else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
|| TREE_CODE (t) == ARRAY_RANGE_REF
|| TREE_CODE (t) == BIT_FIELD_REF)
#endif
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
- MEM_SIZE (mem), MEM_ALIGN (mem));
+ MEM_SIZE (mem), MEM_ALIGN (mem),
+ GET_MODE (mem));
}
-/* Set the alignment of MEM to ALIGN. */
+/* Set the alignment of MEM to ALIGN bits. */
void
set_mem_align (mem, align)
unsigned int align;
{
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_DECL (mem),
- MEM_OFFSET (mem), MEM_SIZE (mem), align);
+ MEM_OFFSET (mem), MEM_SIZE (mem), align,
+ GET_MODE (mem));
+}
+
+/* Set the decl for MEM to DECL. */
+
+void
+set_mem_decl (mem, decl)
+ rtx mem;
+ tree decl;
+{
+ MEM_ATTRS (mem)
+ = get_mem_attrs (MEM_ALIAS_SET (mem), decl, MEM_OFFSET (mem),
+ MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
}
\f
/* Return a memory reference like MEMREF, but with its mode changed to MODE
= 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));
+ : GET_MODE_ALIGNMENT (mmode) / BITS_PER_UNIT),
+ mmode);
return new;
}
rtx addr = XEXP (memref, 0);
rtx new;
rtx memoffset = MEM_OFFSET (memref);
+ rtx size = 0;
unsigned int memalign = MEM_ALIGN (memref);
/* If MEMREF is a LO_SUM and the offset is within the alignment of the
lowest-order set bit in OFFSET, but don't change the alignment if OFFSET
if zero. */
if (offset != 0)
- memalign = MIN (memalign, offset & -offset);
+ memalign = MIN (memalign, (offset & -offset) * BITS_PER_UNIT);
- MEM_ATTRS (new)
- = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref), memoffset,
- mode == BLKmode
- ? 0 : GEN_INT (GET_MODE_SIZE (mode)), memalign);
+ /* We can compute the size in a number of ways. */
+ if (mode != BLKmode)
+ size = GEN_INT (GET_MODE_SIZE (mode));
+ else if (MEM_SIZE (memref))
+ size = plus_constant (MEM_SIZE (memref), -offset);
+
+ MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+ memoffset, size, memalign, GET_MODE (new));
/* 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
- ADDR. The caller is asserting that the actual piece of memory pointed
- to is the same, just the form of the address is being changed, such as
- by putting something into a register. */
+/* Return a memory reference like MEMREF, but whose address is changed by
+ adding OFFSET, an RTX, to it. POW2 is the highest power of two factor
+ known to be in OFFSET (possibly 1). */
rtx
offset_address (memref, offset, pow2)
/* Update the alignment to reflect the offset. Reset the offset, which
we don't know. */
MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
- 0, 0, MIN (MEM_ALIGN (memref), pow2));
+ 0, 0, MIN (MEM_ALIGN (memref),
+ pow2 * BITS_PER_UNIT),
+ GET_MODE (new));
return new;
}
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
note of this type already exists, remove it first. */
-void
+rtx
set_unique_reg_note (insn, kind, datum)
rtx insn;
enum reg_note kind;
{
rtx note = find_reg_note (insn, kind, NULL_RTX);
- /* First remove the note if there already is one. */
+ /* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes.
+ It serves no useful purpose and breaks eliminate_regs. */
+ if ((kind == REG_EQUAL || kind == REG_EQUIV)
+ && GET_CODE (datum) == ASM_OPERANDS)
+ return NULL_RTX;
+
if (note)
- remove_note (insn, note);
+ {
+ XEXP (note, 0) = datum;
+ return note;
+ }
REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn));
+ return REG_NOTES (insn);
}
\f
/* Return an indication of which type of insn should have X as a body.
CONST_DOUBLE_HIGH (tem) = 0;
memcpy (&CONST_DOUBLE_LOW (tem), &u, sizeof u);
- CONST_DOUBLE_MEM (tem) = cc0_rtx;
CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
PUT_MODE (tem, mode);