* rtl.h (rtx_def): Update documentation.
(MEM_IN_STRUCT_P): Likewise.
(MEM_SCALAR_P): New macro.
(MEM_COPY_ATTRIBUTES): Likewise.
(MEM_SET_IN_STRUCT_P): Likewise.
* rtl.texi (MEM_SCALAR_P): Document.
* alias.c (canon_rtx): Use MEM_COPY_ATTRIBUTES.
(fixed_scalar_and_varying_struct_p): New function. Use
MEM_SCALAR_P rather than !MEM_IN_STRUCT_P.
(aliases_everything_p): Likewise.
(true_dependence): Use them.
(write_dependence_p): New function, containing code common to
anti_dependence and output_dependence.
(anti_dependence): Use it.
(output_dependence): Likewise.
* calls.c (save_fixed_argument_area): Don't clear
MEM_IN_STRUCT_P.
(expand_call): Use MEM_SET_IN_STRUCT_P.
(emit_library_call): Don't clear MEM_IN_STRUCT_P.
(emit_library_call_value): Likewise.
(store_one_arg): Use MEM_SET_IN_STRUCT_P.
* combine.c (simplify_rtx): Use MEM_COPY_ATTRIBUTES.
(make_extraction): Likewise.
(simplify_shift_const): Likewise.
(gen_lowpart_for_combine): Likewise.
* cse.c (gen_lowpart_if_possible): Use MEM_COPY_ATTRIBUTES.
* emit-rtl.c (operand_subword): Likewise.
(change_address): Likewise.
* explow.c (stabilize): Use MEM_COPY_ATTRIBUTES.
* expr.c (protect_from_queue): Use MEM_COPY_ATTRIBUTES.
(emit_group_store): Use MEM_SET_IN_STRUCT_P.
(copy_blkmode_from_reg): Likewise.
(store_field): Likewise.
(expand_expr): Remove bogus guesswork setting MEM_IN_STRUCT_P
heuristically. Use MEM_SET_IN_STRUCT_P.
(get_memory_rtx): Likewise.
* final.c (alter_subreg): Use MEM_COPY_ATTRIBUTES.
* function.c (assign_stack_temp): Clear MEM_SCALAR_P and
MEM_ALIAS_SET on newly returned MEMs.
(assign_temp): Use MEM_SET_IN_STRUCT_P.
(put_reg_into_stack): Likewise.
(fixup_var_refs1): Use MEM_COPY_ATTRIBUTES.
(gen_mem_addressof): Use MEM_SET_IN_STRUCT_P.
(assign_parms): Likewise.
(expand_function): Likewise.
* integrate.c (expand_inline_function): Likewise.
(copy_rtx_and_substitute): Use MEM_COPY_ATTRIBUTES.
* loop.c (note_addr_stored): Remove check on MEM_IN_STRUCT_P.
* optabs.c (gen_move_insn): Use MEM_COPY_ATTRIBUTES.
* print-rtl.c (print_rtx): Print /f for frame_related.
* recog.c (validate_replace_rtx_1): Use MEM_COPY_ATTRIBUTES.
* reload1.c (reload): Copy MEM_SCALAR_P as well.
* stmt.c (expand_decl): Use MEM_SET_IN_STRUCT_P.
(expand_anon_union_decl): Use MEM_COPY_ATTRIBUTES.
* varasm.c (make_decl_rtl): Use MEM_SET_IN_STRUCT_P.
(output_constant_def): Likewise.
* a29k.c (a29k_set_memflags_1): Take scalar_p.
Set MEM_SCALAR_P.
(a29k_set_memflags): Use it.
* alpha.c (get_aligned_mem): Use MEM_COPY_ATTRIBUTES.
* c4x.c (c4x_scan_for_ld): Likewise.
* h8300.c (fix_bit_operand): Likewise.
* m88k.c (legitimize_address): Likewise.
(block_move_loop): Likewise.
(block_move_no_loop): Likewise.
(block_move_sequence): Likewise.
(m88k_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
* mips/abi64.h (SETUP_INCOMING_VARARGS): Likewise.
* rs6000.c (expand_block_move_insn): Use MEM_COPY_ATTRIBUTES.
* sh.c (sh_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
* arm.h (arm_gen_load_multiple): Take scalar_p.
(arm_store_load_multiple): Likewise.
* arm.c (arm_gen_load_multiple): Likewise.
(arm_gen_store_multiple): Likewise.
(arm_gen_movstrqi): Treat MEM_SCALAR_P like MEM_IN_STRUCT_P.
From-SVN: r24759
+Tue Jan 19 10:24:53 1999 Mark Mitchell <mark@markmitchell.com>
+
+ * rtl.h (rtx_def): Update documentation.
+ (MEM_IN_STRUCT_P): Likewise.
+ (MEM_SCALAR_P): New macro.
+ (MEM_COPY_ATTRIBUTES): Likewise.
+ (MEM_SET_IN_STRUCT_P): Likewise.
+ * rtl.texi (MEM_SCALAR_P): Document.
+ * alias.c (canon_rtx): Use MEM_COPY_ATTRIBUTES.
+ (fixed_scalar_and_varying_struct_p): New function. Use
+ MEM_SCALAR_P rather than !MEM_IN_STRUCT_P.
+ (aliases_everything_p): Likewise.
+ (true_dependence): Use them.
+ (write_dependence_p): New function, containing code common to
+ anti_dependence and output_dependence.
+ (anti_dependence): Use it.
+ (output_dependence): Likewise.
+ * calls.c (save_fixed_argument_area): Don't clear
+ MEM_IN_STRUCT_P.
+ (expand_call): Use MEM_SET_IN_STRUCT_P.
+ (emit_library_call): Don't clear MEM_IN_STRUCT_P.
+ (emit_library_call_value): Likewise.
+ (store_one_arg): Use MEM_SET_IN_STRUCT_P.
+ * combine.c (simplify_rtx): Use MEM_COPY_ATTRIBUTES.
+ (make_extraction): Likewise.
+ (simplify_shift_const): Likewise.
+ (gen_lowpart_for_combine): Likewise.
+ * cse.c (gen_lowpart_if_possible): Use MEM_COPY_ATTRIBUTES.
+ * emit-rtl.c (operand_subword): Likewise.
+ (change_address): Likewise.
+ * explow.c (stabilize): Use MEM_COPY_ATTRIBUTES.
+ * expr.c (protect_from_queue): Use MEM_COPY_ATTRIBUTES.
+ (emit_group_store): Use MEM_SET_IN_STRUCT_P.
+ (copy_blkmode_from_reg): Likewise.
+ (store_field): Likewise.
+ (expand_expr): Remove bogus guesswork setting MEM_IN_STRUCT_P
+ heuristically. Use MEM_SET_IN_STRUCT_P.
+ (get_memory_rtx): Likewise.
+ * final.c (alter_subreg): Use MEM_COPY_ATTRIBUTES.
+ * function.c (assign_stack_temp): Clear MEM_SCALAR_P and
+ MEM_ALIAS_SET on newly returned MEMs.
+ (assign_temp): Use MEM_SET_IN_STRUCT_P.
+ (put_reg_into_stack): Likewise.
+ (fixup_var_refs1): Use MEM_COPY_ATTRIBUTES.
+ (gen_mem_addressof): Use MEM_SET_IN_STRUCT_P.
+ (assign_parms): Likewise.
+ (expand_function): Likewise.
+ * integrate.c (expand_inline_function): Likewise.
+ (copy_rtx_and_substitute): Use MEM_COPY_ATTRIBUTES.
+ * loop.c (note_addr_stored): Remove check on MEM_IN_STRUCT_P.
+ * optabs.c (gen_move_insn): Use MEM_COPY_ATTRIBUTES.
+ * print-rtl.c (print_rtx): Print /f for frame_related.
+ * recog.c (validate_replace_rtx_1): Use MEM_COPY_ATTRIBUTES.
+ * reload1.c (reload): Copy MEM_SCALAR_P as well.
+ * stmt.c (expand_decl): Use MEM_SET_IN_STRUCT_P.
+ (expand_anon_union_decl): Use MEM_COPY_ATTRIBUTES.
+ * varasm.c (make_decl_rtl): Use MEM_SET_IN_STRUCT_P.
+ (output_constant_def): Likewise.
+ * a29k.c (a29k_set_memflags_1): Take scalar_p.
+ Set MEM_SCALAR_P.
+ (a29k_set_memflags): Use it.
+ * alpha.c (get_aligned_mem): Use MEM_COPY_ATTRIBUTES.
+ * c4x.c (c4x_scan_for_ld): Likewise.
+ * h8300.c (fix_bit_operand): Likewise.
+ * m88k.c (legitimize_address): Likewise.
+ (block_move_loop): Likewise.
+ (block_move_no_loop): Likewise.
+ (block_move_sequence): Likewise.
+ (m88k_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
+ * mips/abi64.h (SETUP_INCOMING_VARARGS): Likewise.
+ * rs6000.c (expand_block_move_insn): Use MEM_COPY_ATTRIBUTES.
+ * sh.c (sh_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
+ * arm.h (arm_gen_load_multiple): Take scalar_p.
+ (arm_store_load_multiple): Likewise.
+ * arm.c (arm_gen_load_multiple): Likewise.
+ (arm_gen_store_multiple): Likewise.
+ (arm_gen_movstrqi): Treat MEM_SCALAR_P like MEM_IN_STRUCT_P.
+
Tue Jan 19 12:30:37 EST 1999 Andrew MacLeod <amacleod@cygnus.com>
* optabs.c (emit_libcall_block): Add a REG_EH_REGION reg note to all
static int insert_subset_children PROTO((splay_tree_node,
void*));
static alias_set_entry get_alias_set_entry PROTO((int));
+static rtx fixed_scalar_and_varying_struct_p PROTO((rtx, rtx, int (*)(rtx)));
+static int aliases_everything_p PROTO((rtx));
+static int write_dependence_p PROTO((rtx, rtx, int));
/* Set up all info needed to perform alias analysis on memory references. */
if (addr != XEXP (x, 0))
{
rtx new = gen_rtx_MEM (GET_MODE (x), addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
x = new;
}
return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
}
+/* Returns MEM1 if and only if MEM1 is a scalar at a fixed address and
+ MEM2 is a reference to a structure at a varying address, or returns
+ MEM2 if vice versa. Otherwise, returns NULL_RTX. If a non-NULL
+ value is returned MEM1 and MEM2 can never alias. VARIES_P is used
+ to decide whether or not an address may vary; it should return
+ nozero whenever variation is possible. */
+
+rtx
+fixed_scalar_and_varying_struct_p (mem1, mem2, varies_p)
+ rtx mem1;
+ rtx mem2;
+ int (*varies_p) PROTO((rtx));
+{
+ rtx mem1_addr = XEXP (mem1, 0);
+ rtx mem2_addr = XEXP (mem2, 0);
+
+ if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+ && !varies_p (mem1_addr) && varies_p (mem2_addr))
+ /* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
+ varying address. */
+ return mem1;
+
+ if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+ && varies_p (mem1_addr) && !varies_p (mem2_addr))
+ /* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
+ varying address. */
+ return mem2;
+
+ return NULL_RTX;
+}
+
+/* Returns nonzero if something about the mode or address format MEM1
+ indicates that it might well alias *anything*. */
+
+int
+aliases_everything_p (mem)
+ rtx mem;
+{
+ if (GET_MODE (mem) == QImode)
+ /* ANSI C says that a `char*' can point to anything. */
+ return 1;
+
+ if (GET_CODE (XEXP (mem, 0)) == AND)
+ /* If the address is an AND, its very hard to know at what it is
+ actually pointing. */
+ return 1;
+
+ return 0;
+}
+
/* True dependence: X is read after store in MEM takes place. */
int
SIZE_FOR_MODE (x), x_addr, 0))
return 0;
- /* If both references are struct references, or both are not, nothing
- is known about aliasing.
-
- If either reference is QImode or BLKmode, ANSI C permits aliasing.
-
- If both addresses are constant, or both are not, nothing is known
- about aliasing. */
- if (MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (mem)
- || mem_mode == QImode || mem_mode == BLKmode
- || GET_MODE (x) == QImode || GET_MODE (x) == BLKmode
- || GET_CODE (x_addr) == AND || GET_CODE (mem_addr) == AND
- || varies (x_addr) == varies (mem_addr))
+ if (aliases_everything_p (x))
return 1;
- /* One memory reference is to a constant address, one is not.
- One is to a structure, the other is not.
+ /* We cannot use aliases_everyting_p to test MEM, since we must look
+ at MEM_MODE, rather than GET_MODE (MEM). */
+ if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
+ return 1;
- If either memory reference is a variable structure the other is a
- fixed scalar and there is no aliasing. */
- if ((MEM_IN_STRUCT_P (mem) && varies (mem_addr))
- || (MEM_IN_STRUCT_P (x) && varies (x_addr)))
- return 0;
+ /* In true_dependence we also allow BLKmode to alias anything. Why
+ don't we do this in anti_dependence and output_dependence? */
+ if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
+ return 1;
- return 1;
+ return !fixed_scalar_and_varying_struct_p (mem, x, varies);
}
-/* Anti dependence: X is written after read in MEM takes place. */
+/* Returns non-zero if a write to X might alias a previous read from
+ (or, if WRITEP is non-zero, a write to) MEM. */
int
-anti_dependence (mem, x)
+write_dependence_p (mem, x, writep)
rtx mem;
rtx x;
+ int writep;
{
rtx x_addr, mem_addr;
+ rtx fixed_scalar;
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
/* If MEM is an unchanging read, then it can't possibly conflict with
the store to X, because there is at most one store to MEM, and it must
have occurred somewhere before MEM. */
- if (RTX_UNCHANGING_P (mem))
+ if (!writep && RTX_UNCHANGING_P (mem))
return 0;
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x),
x_addr = XEXP (x, 0);
mem_addr = XEXP (mem, 0);
- return (memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
- SIZE_FOR_MODE (x), x_addr, 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && GET_CODE (mem_addr) != AND
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && GET_CODE (x_addr) != AND
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
+ SIZE_FOR_MODE (x), x_addr, 0))
+ return 0;
+
+ fixed_scalar
+ = fixed_scalar_and_varying_struct_p (mem, x, rtx_addr_varies_p);
+
+ return (!(fixed_scalar == mem && !aliases_everything_p (x))
+ && !(fixed_scalar == x && !aliases_everything_p (mem)));
+}
+
+/* Anti dependence: X is written after read in MEM takes place. */
+
+int
+anti_dependence (mem, x)
+ rtx mem;
+ rtx x;
+{
+ return write_dependence_p (mem, x, /*writep=*/0);
}
/* Output dependence: X is written after store in MEM takes place. */
register rtx mem;
register rtx x;
{
- if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
- return 1;
-
- if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x),
- GET_MODE (mem)))
- return 0;
-
- x = canon_rtx (x);
- mem = canon_rtx (mem);
-
- if (DIFFERENT_ALIAS_SETS_P (x, mem))
- return 0;
-
- return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
- SIZE_FOR_MODE (x), XEXP (x, 0), 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && GET_CODE (XEXP (mem, 0)) != AND
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && GET_CODE (XEXP (x, 0)) != AND
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ return write_dependence_p (mem, x, /*writep=*/1);
}
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
emit_block_move (validize_mem (save_area), stack_area,
GEN_INT (num_to_save),
PARM_BOUNDARY / BITS_PER_UNIT);
copy = assign_stack_temp (TYPE_MODE (type), size, 0);
}
- MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
store_expr (args[i].tree_value, copy, 0);
is_const = 0;
addr = plus_constant (addr, arg_offset);
args[i].stack = gen_rtx_MEM (args[i].mode, addr);
- MEM_IN_STRUCT_P (args[i].stack)
- = AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value));
+ MEM_SET_IN_STRUCT_P
+ (args[i].stack,
+ AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value)));
if (GET_CODE (slot_offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (slot_offset));
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
memory_address (TYPE_MODE (TREE_TYPE (exp)),
structure_value_addr));
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target,
+ AGGREGATE_TYPE_P (TREE_TYPE (exp)));
}
}
else if (pcc_struct_value)
never use this value more than once in one expression. */
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
copy_to_reg (valreg));
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp)));
}
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
if (target == 0)
{
target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0);
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp)));
preserve_temp_slots (target);
}
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
emit_block_move (validize_mem (save_area), stack_area,
GEN_INT (num_to_save),
PARM_BOUNDARY / BITS_PER_UNIT);
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
emit_block_move (validize_mem (save_area), stack_area,
GEN_INT (num_to_save),
PARM_BOUNDARY / BITS_PER_UNIT);
{
arg->save_area = assign_stack_temp (BLKmode,
arg->size.constant, 0);
- MEM_IN_STRUCT_P (arg->save_area)
- = AGGREGATE_TYPE_P (TREE_TYPE (arg->tree_value));
+ MEM_SET_IN_STRUCT_P (arg->save_area,
+ AGGREGATE_TYPE_P (TREE_TYPE
+ (arg->tree_value)));
preserve_temp_slots (arg->save_area);
emit_block_move (validize_mem (arg->save_area), stack_area,
GEN_INT (arg->size.constant),
plus_constant (XEXP (inner, 0),
(SUBREG_WORD (x) * UNITS_PER_WORD
+ endian_offset)));
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (inner);
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (inner);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (new, inner);
}
else if (GET_CODE (inner) == REG)
{
rtx newmem = gen_rtx_MEM (wanted_inner_mode,
plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (newmem, inner);
inner = newmem;
}
}
plus_constant (XEXP (varop, 0),
count / BITS_PER_UNIT));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (varop);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (varop);
+ MEM_COPY_ATTRIBUTES (new, varop);
varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
: ZERO_EXTEND, mode, new);
count = 0;
}
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
return new;
}
found in part of X. */
static void
-a29k_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
+a29k_set_memflags_1 (x, in_struct_p, scalar_p, volatile_p, unchanging_p)
rtx x;
- int in_struct_p, volatile_p, unchanging_p;
+ int in_struct_p, scalar_p, volatile_p, unchanging_p;
{
int i;
case MEM:
MEM_IN_STRUCT_P (x) = in_struct_p;
+ MEM_SCALAR_P (x) = scalar_p;
MEM_VOLATILE_P (x) = volatile_p;
RTX_UNCHANGING_P (x) = unchanging_p;
break;
/* Note that it is always safe to get these flags, though they won't
be what we think if REF is not a MEM. */
int in_struct_p = MEM_IN_STRUCT_P (ref);
+ int scalar_p = MEM_IN_SCALAR_P (ref);
int volatile_p = MEM_VOLATILE_P (ref);
int unchanging_p = RTX_UNCHANGING_P (ref);
|| (! in_struct_p && ! volatile_p && ! unchanging_p))
return;
- a29k_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
+ a29k_set_memflags_1 (insn, in_struct_p, scalar_p, volatile_p, unchanging_p);
}
\f
/* Return 1 if OP is a comparison operator that we have in floating-point. */
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
*paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
- MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);
- MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);
+ MEM_COPY_ATTRIBUTES (*paligned_mem, ref);
RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);
/* Sadly, we cannot use alias sets here because we may overlap other
rtx
arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
- in_struct_p)
+ in_struct_p, scalar_p)
int base_regno;
int count;
rtx from;
int write_back;
int unchanging_p;
int in_struct_p;
+ int scalar_p;
{
int i = 0, j;
rtx result;
mem = gen_rtx (MEM, SImode, plus_constant (from, j * 4 * sign));
RTX_UNCHANGING_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
-
+ MEM_SCALAR_P (mem) = scalar_p;
XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode,
gen_rtx (REG, SImode, base_regno + j),
mem);
rtx
arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
- in_struct_p)
+ in_struct_p, scalar_p)
int base_regno;
int count;
rtx to;
int write_back;
int unchanging_p;
int in_struct_p;
+ int scalar_p;
{
int i = 0, j;
rtx result;
mem = gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign));
RTX_UNCHANGING_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
+ MEM_SCALAR_P (mem) = scalar_p;
XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode, mem,
gen_rtx (REG, SImode, base_regno + j));
rtx part_bytes_reg = NULL;
rtx mem;
int dst_unchanging_p, dst_in_struct_p, src_unchanging_p, src_in_struct_p;
+ int dst_scalar_p, src_scalar_p;
if (GET_CODE (operands[2]) != CONST_INT
|| GET_CODE (operands[3]) != CONST_INT
dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
+ dst_scalar_p = MEM_SCALAR_P (operands[0]);
src_unchanging_p = RTX_UNCHANGING_P (operands[1]);
src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
+ src_scalar_p = MEM_SCALAR_P (operands[1]);
fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
fin_src = src = copy_to_mode_reg (SImode, st_src);
{
if (in_words_to_go > 4)
emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
- src_unchanging_p, src_in_struct_p));
+ src_unchanging_p,
+ src_in_struct_p,
+ src_scalar_p));
else
emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
FALSE, src_unchanging_p,
- src_in_struct_p));
+ src_in_struct_p, src_scalar_p));
if (out_words_to_go)
{
if (out_words_to_go > 4)
emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
dst_unchanging_p,
- dst_in_struct_p));
+ dst_in_struct_p,
+ dst_scalar_p));
else if (out_words_to_go != 1)
emit_insn (arm_gen_store_multiple (0, out_words_to_go,
dst, TRUE,
(last_bytes == 0
? FALSE : TRUE),
dst_unchanging_p,
- dst_in_struct_p));
+ dst_in_struct_p,
+ dst_scalar_p));
else
{
mem = gen_rtx (MEM, SImode, dst);
RTX_UNCHANGING_P (mem) = dst_unchanging_p;
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, gen_rtx (REG, SImode, 0));
if (last_bytes != 0)
emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
mem = gen_rtx (MEM, SImode, src);
RTX_UNCHANGING_P (mem) = src_unchanging_p;
MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ MEM_SCALAR_P (mem) = src_scalar_p;
emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
mem = gen_rtx (MEM, SImode, dst);
RTX_UNCHANGING_P (mem) = dst_unchanging_p;
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, sreg);
emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
in_words_to_go--;
mem = gen_rtx (MEM, SImode, src);
RTX_UNCHANGING_P (mem) = src_unchanging_p;
MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ MEM_SCALAR_P (mem) = src_scalar_p;
part_bytes_reg = copy_to_mode_reg (SImode, mem);
}
mem = gen_rtx (MEM, QImode, plus_constant (dst, last_bytes - 1));
RTX_UNCHANGING_P (mem) = dst_unchanging_p;
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
mem = gen_rtx (MEM, QImode, dst);
RTX_UNCHANGING_P (mem) = dst_unchanging_p;
MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ MEM_SCALAR_P (mem) = dst_scalar_p;
emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
union tree_node *,
union tree_node * */);
struct rtx_def *arm_gen_load_multiple (/* int, int, struct rtx_def *,
- int, int, int, int */);
+ int, int, int, int, int */);
struct rtx_def *arm_gen_store_multiple (/* int, int, struct rtx_def *,
- int, int, int, int */);
+ int, int, int, int, int */);
int arm_gen_movstrqi (/* struct rtx_def ** */);
struct rtx_def *gen_rotated_half_load (/* struct rtx_def * */);
enum machine_mode arm_select_cc_mode (/* enum rtx_code, struct rtx_def *,
op0));
/* Use change_address? */
- MEM_VOLATILE_P (*newop) = MEM_VOLATILE_P (operand);
RTX_UNCHANGING_P (*newop) = RTX_UNCHANGING_P (operand);
- MEM_IN_STRUCT_P (*newop) = MEM_IN_STRUCT_P (operand);
+ MEM_COPY_ATTRIBUTES (*newop, operand);
break;
default:
mem = gen_rtx (MEM, GET_MODE (operands[0]),
copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[0]);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[0]);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[0]);
+ MEM_COPY_ATTRIBUTES (mem, operands[0]);
operands[0] = mem;
}
mem = gen_rtx (MEM, GET_MODE (operands[1]),
copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[1]);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[1]);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[1]);
+ MEM_COPY_ATTRIBUTES (mem, operands[0]);
operands[1] = mem;
}
return 0;
{
new = gen_rtx (MEM, GET_MODE (orig), new);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig);
+ MEM_COPY_ATTRIBUTES (new, orig);
}
return new;
}
gen_rtx (REG, Pmode, 3),
offset_rtx));
RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
- MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
- MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
+ MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
emit_insn (gen_call_movstrsi_loop
(gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)),
gen_rtx (REG, Pmode, 3),
offset_rtx));
RTX_UNCHANGING_P (value_rtx) = RTX_UNCHANGING_P (src_mem);
- MEM_VOLATILE_P (value_rtx) = MEM_VOLATILE_P (src_mem);
- MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem);
+ MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
value_reg = ((((most - (size - remainder)) / align) & 1) == 0
? (align == 8 ? 6 : 5) : 4);
gen_rtx (PLUS, Pmode, src,
GEN_INT (offset_ld)));
RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
- MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
- MEM_IN_STRUCT_P (srcp) = MEM_IN_STRUCT_P (src_mem);
+ MEM_COPY_ATTRIBUTES (srcp, src_mem);
emit_insn (gen_rtx (SET, VOIDmode, temp[next], srcp));
offset_ld += amount[next];
active[next] = TRUE;
gen_rtx (PLUS, Pmode, dest,
GEN_INT (offset_st)));
RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dest_mem);
- MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dest_mem);
- MEM_IN_STRUCT_P (dstp) = MEM_IN_STRUCT_P (dest_mem);
+ MEM_COPY_ATTRIBUTES (dstp, dest_mem);
emit_insn (gen_rtx (SET, VOIDmode, dstp, temp[phase]));
offset_st += amount[phase];
}
/* Allocate the va_list constructor */
block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
- MEM_IN_STRUCT_P (block) = 1;
+ MEM_SET_IN_STRUCT_P (block, 1);
RTX_UNCHANGING_P (block) = 1;
RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
/* Allocate the register space, and store it as the __va_reg member. */
addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
- MEM_IN_STRUCT_P (addr) = 1;
+ MEM_SET_IN_STRUCT_P (addr, 1);
RTX_UNCHANGING_P (addr) = 1;
RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
emit_move_insn (change_address (block, Pmode,
so that the insn scheduler won't assume that these \
stores can't possibly overlap with the va_arg loads. */ \
if (mips_abi != ABI_EABI && BYTES_BIG_ENDIAN) \
- MEM_IN_STRUCT_P (mem) = 1; \
+ MEM_SET_IN_STRUCT_P (mem, 1); \
move_block_from_reg \
((CUM).arg_words + GP_ARG_FIRST + mips_off, \
mem, \
rtx mem = gen_rtx_MEM (mode, addr);
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (orig_mem);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (orig_mem);
+ MEM_COPY_ATTRIBUTES (mem, orig_mem);
#ifdef MEM_UNALIGNED_P
MEM_UNALIGNED_P (mem) = MEM_UNALIGNED_P (orig_mem);
#endif
bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
regbuf = assign_stack_local (BLKmode, bufsize, 0);
- MEM_IN_STRUCT_P (regbuf) = 1;
+ MEM_SET_IN_STRUCT_P (regbuf, 1);
/* Save int args.
This is optimized to only save the regs that are necessary. Explicitly
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
if (! memory_address_p (mode, XEXP (new, 0)))
return 0;
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
return new;
}
else
new = gen_rtx_MEM (word_mode, addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op);
+ MEM_COPY_ATTRIBUTES (new, op);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
return new;
return memref;
new = gen_rtx_MEM (mode, addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref);
+ MEM_COPY_ATTRIBUTES (new, memref);
return new;
}
\f
/* Mark returned memref with in_struct if it's in an array or
structure. Copy const and volatile from original memref. */
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
+ MEM_COPY_ATTRIBUTES (mem, x);
+ if (GET_CODE (addr) == PLUS)
+ MEM_SET_IN_STRUCT_P (mem, 1);
/* Since the new MEM is just like the old X, it can alias only
the things that X could. */
register rtx y = XEXP (x, 0);
register rtx new = gen_rtx_MEM (GET_MODE (x), QUEUED_VAR (y));
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
if (QUEUED_INSN (y))
mem_in_struct_p set; we might not. */
dst = copy_rtx (orig_dst);
- MEM_IN_STRUCT_P (dst) = 1;
+ MEM_SET_IN_STRUCT_P (dst, 1);
}
/* Process the pieces. */
if (tgtblk == 0)
{
tgtblk = assign_stack_temp (BLKmode, bytes, 0);
- MEM_IN_STRUCT_P (tgtblk) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
preserve_temp_slots (tgtblk);
}
GET_MODE_SIZE (GET_MODE (target)), 0);
rtx blk_object = copy_rtx (object);
- MEM_IN_STRUCT_P (object) = 1;
- MEM_IN_STRUCT_P (blk_object) = 1;
+ MEM_SET_IN_STRUCT_P (object, 1);
+ MEM_SET_IN_STRUCT_P (blk_object, 1);
PUT_MODE (blk_object, BLKmode);
if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
plus_constant (addr,
(bitpos
/ BITS_PER_UNIT))));
- MEM_IN_STRUCT_P (to_rtx) = 1;
+ MEM_SET_IN_STRUCT_P (to_rtx, 1);
MEM_ALIAS_SET (to_rtx) = alias_set;
return store_expr (exp, to_rtx, value_mode != VOIDmode);
|| (TREE_CODE (exp1) == ADDR_EXPR
&& (exp2 = TREE_OPERAND (exp1, 0))
&& AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
- MEM_IN_STRUCT_P (temp) = 1;
-
- /* If the pointer is actually a REFERENCE_TYPE, this could be pointing
- into some aggregate too. In theory we could fold this into the
- previous check and use rtx_addr_varies_p there too.
-
- However, this seems safer. */
- if (!MEM_IN_STRUCT_P (temp)
- && (TREE_CODE (TREE_TYPE (exp1)) == REFERENCE_TYPE
- /* This may have been an array reference to the first element
- that was optimized away from being an addition. */
- || (TREE_CODE (exp1) == NOP_EXPR
- && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp1, 0)))
- == REFERENCE_TYPE)
- || ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp1, 0)))
- == POINTER_TYPE)
- && (AGGREGATE_TYPE_P
- (TREE_TYPE (TREE_TYPE
- (TREE_OPERAND (exp1, 0))))))))))
- MEM_IN_STRUCT_P (temp) = ! rtx_addr_varies_p (temp);
+ MEM_SET_IN_STRUCT_P (temp, 1);
MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
MEM_ALIAS_SET (temp) = get_alias_set (exp);
emit_move_insn (new, op0);
op0 = copy_rtx (new);
PUT_MODE (op0, BLKmode);
- MEM_IN_STRUCT_P (op0) = 1;
+ MEM_SET_IN_STRUCT_P (op0, 1);
}
return op0;
if (GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), alignment);
- MEM_IN_STRUCT_P (op0) = 1;
+ MEM_SET_IN_STRUCT_P (op0, 1);
MEM_VOLATILE_P (op0) |= volatilep;
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS
is_aggregate = AGGREGATE_TYPE_P (type);
}
- MEM_IN_STRUCT_P (mem) = is_aggregate;
+ MEM_SET_IN_STRUCT_P (mem, is_aggregate);
return mem;
}
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (y);
+ MEM_COPY_ATTRIBUTES (x, y);
MEM_ALIAS_SET (x) = MEM_ALIAS_SET (y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
}
set from before. */
RTX_UNCHANGING_P (p->slot) = 0;
MEM_IN_STRUCT_P (p->slot) = 0;
+ MEM_SCALAR_P (p->slot) = 0;
+ MEM_ALIAS_SET (p->slot) = 0;
return p->slot;
}
\f
size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
tmp = assign_stack_temp (mode, size, keep);
- MEM_IN_STRUCT_P (tmp) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type));
return tmp;
}
previously generated stack slot, then we need to copy the bit in
case it was set for other reasons. For instance, it is set for
__builtin_va_alist. */
- MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type) | MEM_IN_STRUCT_P (new);
+ MEM_SET_IN_STRUCT_P (reg,
+ AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
MEM_ALIAS_SET (reg) = get_alias_set (type);
/* Now make sure that all refs to the variable, previously made
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (tem, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
+ MEM_COPY_ATTRIBUTES (newmem, tem);
/* Make the change and see if the insn remains valid. */
INSN_CODE (insn) = -1;
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (tem, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
+ MEM_COPY_ATTRIBUTES (newmem, tem);
/* Make the change and see if the insn remains valid. */
INSN_CODE (insn) = -1;
PUT_CODE (reg, MEM);
PUT_MODE (reg, DECL_MODE (decl));
MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
- MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. Likewise if it
is readonly. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
MEM_ALIAS_SET (stack_parm) = get_alias_set (parm);
}
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
#endif /* 0 */
/* If this is a memory ref that contains aggregate
components, mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
{
DECL_RTL (parm)
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
- MEM_IN_STRUCT_P (DECL_RTL (parm)) = aggregate;
+ MEM_SET_IN_STRUCT_P (DECL_RTL (parm), aggregate);
}
else
DECL_RTL (parm) = parmreg;
else
copy = assign_stack_temp (TYPE_MODE (type),
int_size_in_bytes (type), 1);
- MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
RTX_UNCHANGING_P (copy) = TREE_READONLY (parm);
store_expr (parm, copy, 0);
GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
if (promoted_mode != nominal_mode)
DECL_RTL (result)
= gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm));
- MEM_IN_STRUCT_P (DECL_RTL (result)) = AGGREGATE_TYPE_P (restype);
+ MEM_SET_IN_STRUCT_P (DECL_RTL (result),
+ AGGREGATE_TYPE_P (restype));
}
if (TREE_THIS_VOLATILE (parm))
{
DECL_RTL (DECL_RESULT (subr))
= gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address);
- MEM_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)))
- = AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)),
+ AGGREGATE_TYPE_P (TREE_TYPE
+ (DECL_RESULT
+ (subr))));
}
}
else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
return;
for (i = 0; i < loop_store_mems_idx; i++)
- if (rtx_equal_p (XEXP (loop_store_mems[i], 0), XEXP (x, 0))
- && MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (loop_store_mems[i]))
+ if (rtx_equal_p (XEXP (loop_store_mems[i], 0), XEXP (x, 0)))
{
/* We are storing at the same address as previously noted. Save the
wider reference. */
{
x = gen_rtx_MEM (tmode, XEXP (x1, 0));
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
+ MEM_COPY_ATTRIBUTES (x, x1);
copy_replacements (x1, x);
}
{
y = gen_rtx_MEM (tmode, XEXP (y1, 0));
RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
- MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
- MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
+ MEM_COPY_ATTRIBUTES (y, y1);
copy_replacements (y1, y);
}
}
if (in_rtx->integrated)
fputs ("/i", outfile);
+ if (in_rtx->frame_related)
+ fputs ("/f", outfile);
+
if (GET_MODE (in_rtx) != VOIDmode)
{
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (to);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (to);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (to);
+ MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
return;
}
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (to, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (to);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (to);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to);
+ MEM_COPY_ATTRIBUTES (newmem, to);
validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
validate_change (object, &XEXP (x, 0), newmem, 1);
{
rtx addr = 0;
int in_struct = 0;
+ int is_scalar;
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]);
}
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. */
MEM_ALIAS_SET (reg) = 0;
In a REG, nonzero means this reg refers to the return value
of the current function. */
unsigned integrated : 1;
- /* Nonzero if this rtx is related to the call frame, either changing how
- we compute the frame address or saving and restoring registers in
- the prologue and epilogue. */
+ /* 1 in an INSN if this rtx is related to the call frame,
+ either changing how we compute the frame address or saving and
+ restoring registers in the prologue and epilogue.
+ 1 in a MEM if the MEM refers to a scalar, rather than a member of
+ an aggregate. */
unsigned frame_related : 1;
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
Also in an ASM_OPERANDS rtx. */
#define MEM_VOLATILE_P(RTX) ((RTX)->volatil)
-/* For a MEM rtx, 1 if it refers to a field of an aggregate. */
+/* For a MEM rtx, 1 if it refers to a field of an aggregate. If zero,
+ RTX may or may not refer to a field of an aggregate. */
#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
+/* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may
+ not refer to a scalar.*/
+#define MEM_SCALAR_P(RTX) ((RTX)->frame_related)
+
+/* Copy the MEM_VOLATILE_P, MEM_IN_STRUCT_P, and MEM_SCALAR_P
+ attributes 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)) \
+
+/* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
+ RTX. Otherwise, vice versa. Use this macro only when you are
+ *sure* that you know that the MEM is in a structure, or is a
+ scalar. VAL is evaluated only once. */
+#define MEM_SET_IN_STRUCT_P(RTX, VAL) \
+ ((VAL) ? (MEM_IN_STRUCT_P (RTX) = 1, MEM_SCALAR_P (RTX) = 0) \
+ : (MEM_IN_STRUCT_P (RTX) = 0, MEM_SCALAR_P (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
@cindex @code{in_struct}, in @code{mem}
@cindex @samp{/s} in RTL dump
@item MEM_IN_STRUCT_P (@var{x})
-In @code{mem} expressions, nonzero for reference to an entire
-structure, union or array, or to a component of one. Zero for
-references to a scalar variable or through a pointer to a scalar.
-Stored in the @code{in_struct} field and printed as @samp{/s}.
+In @code{mem} expressions, nonzero for reference to an entire structure,
+union or array, or to a component of one. Zero for references to a
+scalar variable or through a pointer to a scalar. Stored in the
+@code{in_struct} field and printed as @samp{/s}. If both this flag and
+MEM_SCALAR_P are clear, then we don't know whether this MEM is in a
+structure or not. Both flags should never be simultaneously set.
+
+@findex MEM_SCALAR_P
+@cindex @code{mem} and @samp{/f}
+@cindex @code{frame_related}, in@code{mem}
+@cindex @samp{/f} in RTL dump
+@item MEM_SCALAR_P (@var{x})
+In @code{mem} expressions, nonzero for reference to a scalar known not
+to be a member of a structure, union, or array. Zero for such
+references and for indirections through pointers, even pointers pointing
+to scalar types. If both this flag and MEM_STRUCT_P are clear, then we
+don't know whether this MEM is in a structure or not. Both flags should
+never be simultaneously set.
@findex MEM_ALIAS_SET
@item MEM_ALIAS_SET (@var{x})
/* An initializer is going to decide the size of this array.
Until we know the size, represent its address with a reg. */
DECL_RTL (decl) = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl), AGGREGATE_TYPE_P (type));
}
else if (DECL_MODE (decl) != BLKmode
/* If -ffloat-store, don't put explicit float vars
+ BITS_PER_UNIT - 1)
/ BITS_PER_UNIT),
1);
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Set alignment we actually gave this decl. */
DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
#if 0
/* If this is in memory because of -ffloat-store,
set the volatile bit, to prevent optimizations from
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Indicate the alignment we actually gave this variable. */
#ifdef STACK_BOUNDARY
else
{
DECL_RTL (decl_elt) = gen_rtx_MEM (mode, copy_rtx (XEXP (x, 0)));
- MEM_IN_STRUCT_P (DECL_RTL (decl_elt)) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (DECL_RTL (decl_elt), x);
RTX_UNCHANGING_P (DECL_RTL (decl_elt)) = RTX_UNCHANGING_P (x);
}
}
if (TREE_READONLY (decl))
RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
- MEM_IN_STRUCT_P (DECL_RTL (decl))
- = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Optionally set flags or add text to the name to record information
such as that it is a function name.
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), def);
RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1;
if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
- MEM_IN_STRUCT_P (TREE_CST_RTL (exp)) = 1;
+ MEM_SET_IN_STRUCT_P (TREE_CST_RTL (exp), 1);
pop_obstacks ();