* rtl.h (MEM_READONLY_P): Replace RTX_UNCHANGING_P.
* alias.c (true_dependence): Update to match new semantics.
(canon_true_dependence, write_dependence_p): Likewise.
(anti_dependence, output_dependence): Update write_dependence_p args.
(unchanging_anti_dependence): Remove.
* calls.c (purge_mem_unchanging_flag): Remove.
(fixup_tail_calls): Don't call it.
(expand_call): Don't add unchanging memory to function usage.
* expr.c (emit_block_move_via_libcall): Likewise.
(clear_storage_via_libcall): Don't clobber RTX_UNCHANGING_P mems.
(get_subtarget): Don't use RTX_UNCHANGING_P.
(expand_assignment, store_constructor, expand_expr_real_1): Likewise.
(do_tablejump): Set MEM_READONLY_P, not RTX_UNCHANGING_P.
* combine.c (get_last_value_validate): Use MEM_READONLY_P.
* cse.c (insert): Don't use RTX_UNCHANGING_P.
(cse_insn, canon_hash): Use MEM_READONLY_P.
* emit-rtl.c (set_mem_attributes_minus_bitpos): Use MEM_READONLY_P
instead of RTX_UNCHANGING_P.
* explow.c (maybe_set_unchanging): Remove.
* expr.h (maybe_set_unchanging): Remove.
* flow.c (insn_dead_p, mark_used_regs): Use anti_dependence.
* function.c (assign_stack_temp_for_type): Don't use RTX_UNCHANGING_P.
(assign_parm_setup_reg, expand_function_start): Likewise.
* integrate.c (copy_rtx_and_substitute): Likewise.
* ra-rewrite.c (emit_colors): Likewise.
* regmove.c (copy_src_to_dest, regmove_optimize): Likewise.
(fixup_match_1): Likewise.
* reload1.c (reload, alter_reg): Likewise.
* local-alloc.c (validate_equiv_mem): Check MEM_READONLY_P,
not RTX_UNCHANGING_P.
(equiv_init_varies_p): Likewise.
* loop-invariant.c (check_maybe_invariant): Likewise.
* resource.c (mark_referenced_resources, mark_set_resources): Likewise.
* loop.c (note_addr_stored): Likewise.
(prescan_loop): Likewise. Don't check function usage for clobbered
unchanging memory.
* rtlanal.c (rtx_unstable_p): Check MEM_READONLY_P,
not RTX_UNCHANGING_P.
(rtx_varies_p, modified_between_p, modified_in_p): Likewise.
* varasm.c (force_const_mem): Likewise.
* stmt.c (expand_decl): Don't set RTX_UNCHANGING_P.
* web.c (entry_register): Likewise.
* tree-gimple.h (get_base_address): Move decl ...
* tree.h: ... here.
* doc/rtl.texi (MEM_READONLY_P): Replace RTX_UNCHANGING_P.
* config/alpha/alpha.c (alpha_set_memflags_1): Rewrite to be
called via for_each_rtx. Copy MEM_SCALAR_P, MEM_NOTRAP_P too.
(alpha_set_memflags): Update to match.
* config/darwin.c (machopic_indirect_data_reference): Set
MEM_READONLY_P instead of RTX_UNCHANGING_P.
(machopic_indirect_call_target): Likewise.
(machopic_legitimize_pic_address): Likewise.
* config/arm/arm.c (legitimize_pic_address, arm_gen_load_multiple,
arm_gen_store_multiple, arm_gen_movmemqi): Likewise.
* config/arm/arm.md (load_multiple, store_multiple): Likewise.
* config/frv/frv.md (symGOT2reg): Likewise.
* config/i386/i386.c (legitimize_pic_address,
legitimize_tls_address, ix86_split_to_parts): Likewise.
* config/ia64/ia64.c (ia64_expand_tls_address): Likewise.
* config/ia64/ia64.md (load_fptr): Likewise.
* config/m32r/m32r.c (m32r_legitimize_pic_address): Likewise.
* config/m68k/m68k.c (legitimize_pic_address): Likewise.
* config/mcore/mcore.c (block_move_sequence): Likewise.
* config/mn10300/mn10300.md (symGOT2reg): Likewise.
* config/pa/pa.c (legitimize_pic_address): Likewise.
* config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Likewise.
(rs6000_emit_move): Likewise.
* config/s390/s390.c (legitimize_pic_address): Likewise.
(legitimize_tls_address): Likewise.
* config/s390/s390.md (casesi): Likewise.
* config/sh/sh.c (prepare_move_operands, sh_reorg): Likewise.
* config/sh/sh.md (symGOT2reg): Likewise.
* config/sparc/sparc.c (legitimize_pic_address): Likewise.
* config/v850/v850.md (casesi): Likewise.
* config/ia64/ia64.c (gen_thread_pointer): Don't set RTX_UNCHANGING_P.
* config/iq2000/iq2000.c (save_restore_insns): Likewise.
* config/mips/mips.c (mips_restore_gp): Likewise.
(mips_save_restore_reg, mips16_gp_pseudo_reg): Likewise.
* config/sh/sh.c (sh_reorg): Likewise.
From-SVN: r86178
+2004-08-18 Richard Henderson <rth@redhat.com>
+
+ * rtl.h (MEM_READONLY_P): Replace RTX_UNCHANGING_P.
+ * alias.c (true_dependence): Update to match new semantics.
+ (canon_true_dependence, write_dependence_p): Likewise.
+ (anti_dependence, output_dependence): Update write_dependence_p args.
+ (unchanging_anti_dependence): Remove.
+ * calls.c (purge_mem_unchanging_flag): Remove.
+ (fixup_tail_calls): Don't call it.
+ (expand_call): Don't add unchanging memory to function usage.
+ * expr.c (emit_block_move_via_libcall): Likewise.
+ (clear_storage_via_libcall): Don't clobber RTX_UNCHANGING_P mems.
+ (get_subtarget): Don't use RTX_UNCHANGING_P.
+ (expand_assignment, store_constructor, expand_expr_real_1): Likewise.
+ (do_tablejump): Set MEM_READONLY_P, not RTX_UNCHANGING_P.
+ * combine.c (get_last_value_validate): Use MEM_READONLY_P.
+ * cse.c (insert): Don't use RTX_UNCHANGING_P.
+ (cse_insn, canon_hash): Use MEM_READONLY_P.
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Use MEM_READONLY_P
+ instead of RTX_UNCHANGING_P.
+ * explow.c (maybe_set_unchanging): Remove.
+ * expr.h (maybe_set_unchanging): Remove.
+ * flow.c (insn_dead_p, mark_used_regs): Use anti_dependence.
+ * function.c (assign_stack_temp_for_type): Don't use RTX_UNCHANGING_P.
+ (assign_parm_setup_reg, expand_function_start): Likewise.
+ * integrate.c (copy_rtx_and_substitute): Likewise.
+ * ra-rewrite.c (emit_colors): Likewise.
+ * regmove.c (copy_src_to_dest, regmove_optimize): Likewise.
+ (fixup_match_1): Likewise.
+ * reload1.c (reload, alter_reg): Likewise.
+ * local-alloc.c (validate_equiv_mem): Check MEM_READONLY_P,
+ not RTX_UNCHANGING_P.
+ (equiv_init_varies_p): Likewise.
+ * loop-invariant.c (check_maybe_invariant): Likewise.
+ * resource.c (mark_referenced_resources, mark_set_resources): Likewise.
+ * loop.c (note_addr_stored): Likewise.
+ (prescan_loop): Likewise. Don't check function usage for clobbered
+ unchanging memory.
+ * rtlanal.c (rtx_unstable_p): Check MEM_READONLY_P,
+ not RTX_UNCHANGING_P.
+ (rtx_varies_p, modified_between_p, modified_in_p): Likewise.
+ * varasm.c (force_const_mem): Likewise.
+ * stmt.c (expand_decl): Don't set RTX_UNCHANGING_P.
+ * web.c (entry_register): Likewise.
+ * tree-gimple.h (get_base_address): Move decl ...
+ * tree.h: ... here.
+ * doc/rtl.texi (MEM_READONLY_P): Replace RTX_UNCHANGING_P.
+
+ * config/alpha/alpha.c (alpha_set_memflags_1): Rewrite to be
+ called via for_each_rtx. Copy MEM_SCALAR_P, MEM_NOTRAP_P too.
+ (alpha_set_memflags): Update to match.
+
+ * config/darwin.c (machopic_indirect_data_reference): Set
+ MEM_READONLY_P instead of RTX_UNCHANGING_P.
+ (machopic_indirect_call_target): Likewise.
+ (machopic_legitimize_pic_address): Likewise.
+ * config/arm/arm.c (legitimize_pic_address, arm_gen_load_multiple,
+ arm_gen_store_multiple, arm_gen_movmemqi): Likewise.
+ * config/arm/arm.md (load_multiple, store_multiple): Likewise.
+ * config/frv/frv.md (symGOT2reg): Likewise.
+ * config/i386/i386.c (legitimize_pic_address,
+ legitimize_tls_address, ix86_split_to_parts): Likewise.
+ * config/ia64/ia64.c (ia64_expand_tls_address): Likewise.
+ * config/ia64/ia64.md (load_fptr): Likewise.
+ * config/m32r/m32r.c (m32r_legitimize_pic_address): Likewise.
+ * config/m68k/m68k.c (legitimize_pic_address): Likewise.
+ * config/mcore/mcore.c (block_move_sequence): Likewise.
+ * config/mn10300/mn10300.md (symGOT2reg): Likewise.
+ * config/pa/pa.c (legitimize_pic_address): Likewise.
+ * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Likewise.
+ (rs6000_emit_move): Likewise.
+ * config/s390/s390.c (legitimize_pic_address): Likewise.
+ (legitimize_tls_address): Likewise.
+ * config/s390/s390.md (casesi): Likewise.
+ * config/sh/sh.c (prepare_move_operands, sh_reorg): Likewise.
+ * config/sh/sh.md (symGOT2reg): Likewise.
+ * config/sparc/sparc.c (legitimize_pic_address): Likewise.
+ * config/v850/v850.md (casesi): Likewise.
+
+ * config/ia64/ia64.c (gen_thread_pointer): Don't set RTX_UNCHANGING_P.
+ * config/iq2000/iq2000.c (save_restore_insns): Likewise.
+ * config/mips/mips.c (mips_restore_gp): Likewise.
+ (mips_save_restore_reg, mips16_gp_pseudo_reg): Likewise.
+ * config/sh/sh.c (sh_reorg): Likewise.
+
2004-08-18 Richard Henderson <rth@redhat.com>
* tree.h (struct tree_decl): Add gimple_formal_temp.
static tree decl_for_component_ref (tree);
static rtx adjust_offset_for_component_ref (tree, rtx);
static int nonoverlapping_memrefs_p (rtx, rtx);
-static int write_dependence_p (rtx, rtx, int, int);
+static int write_dependence_p (rtx, rtx, int);
static int nonlocal_mentioned_p_1 (rtx *, void *);
static int nonlocal_mentioned_p (rtx);
if (DIFFERENT_ALIAS_SETS_P (x, mem))
return 0;
- /* Unchanging memory can't conflict with non-unchanging memory.
- A non-unchanging read can conflict with a non-unchanging write.
- An unchanging read can conflict with an unchanging write since
- there may be a single store to this address to initialize it.
- Note that an unchanging store can conflict with a non-unchanging read
- since we have to make conservative assumptions when we have a
- record with readonly fields and we are copying the whole thing.
- Just fall through to the code below to resolve potential conflicts.
- This won't handle all cases optimally, but the possible performance
- loss should be negligible. */
- if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
+ /* Read-only memory is by definition never modified, and therefore can't
+ conflict with anything. We don't expect to find read-only set on MEM,
+ but stupid user tricks can produce them, so don't abort. */
+ if (MEM_READONLY_P (x))
return 0;
if (nonoverlapping_memrefs_p (mem, x))
if (DIFFERENT_ALIAS_SETS_P (x, mem))
return 0;
- /* If X is an unchanging read, then it can't possibly conflict with any
- non-unchanging store. It may conflict with an unchanging write though,
- because there may be a single store to this address to initialize it.
- Just fall through to the code below to resolve the case where we have
- both an unchanging read and an unchanging write. This won't handle all
- cases optimally, but the possible performance loss should be
- negligible. */
- if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
+ /* Read-only memory is by definition never modified, and therefore can't
+ conflict with anything. We don't expect to find read-only set on MEM,
+ but stupid user tricks can produce them, so don't abort. */
+ if (MEM_READONLY_P (x))
return 0;
if (nonoverlapping_memrefs_p (x, mem))
}
/* Returns nonzero if a write to X might alias a previous read from
- (or, if WRITEP is nonzero, a write to) MEM. If CONSTP is nonzero,
- honor the RTX_UNCHANGING_P flags on X and MEM. */
+ (or, if WRITEP is nonzero, a write to) MEM. */
static int
-write_dependence_p (rtx mem, rtx x, int writep, int constp)
+write_dependence_p (rtx mem, rtx x, int writep)
{
rtx x_addr, mem_addr;
rtx fixed_scalar;
if (DIFFERENT_ALIAS_SETS_P (x, mem))
return 0;
- if (constp)
- {
- /* Unchanging memory can't conflict with non-unchanging memory. */
- if (RTX_UNCHANGING_P (x) != RTX_UNCHANGING_P (mem))
- return 0;
-
- /* 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 (! writep && RTX_UNCHANGING_P (mem))
- return 0;
- }
+ /* A read from read-only memory can't conflict with read-write memory. */
+ if (!writep && MEM_READONLY_P (mem))
+ return 0;
if (nonoverlapping_memrefs_p (x, mem))
return 0;
int
anti_dependence (rtx mem, rtx x)
{
- return write_dependence_p (mem, x, /*writep=*/0, /*constp*/1);
+ return write_dependence_p (mem, x, /*writep=*/0);
}
/* Output dependence: X is written after store in MEM takes place. */
int
output_dependence (rtx mem, rtx x)
{
- return write_dependence_p (mem, x, /*writep=*/1, /*constp*/1);
-}
-
-/* Unchanging anti dependence: Like anti_dependence but ignores
- the UNCHANGING_RTX_P property on const variable references. */
-
-int
-unchanging_anti_dependence (rtx mem, rtx x)
-{
- return write_dependence_p (mem, x, /*writep=*/0, /*constp*/0);
+ return write_dependence_p (mem, x, /*writep=*/1);
}
\f
/* A subroutine of nonlocal_mentioned_p, returns 1 if *LOC mentions
}
}
-/* Clear RTX_UNCHANGING_P flag of incoming argument MEMs. */
-
-static void
-purge_mem_unchanging_flag (rtx x)
-{
- RTX_CODE code;
- int i, j;
- const char *fmt;
-
- if (x == NULL_RTX)
- return;
-
- code = GET_CODE (x);
-
- if (code == MEM)
- {
- if (RTX_UNCHANGING_P (x)
- && (XEXP (x, 0) == current_function_internal_arg_pointer
- || (GET_CODE (XEXP (x, 0)) == PLUS
- && XEXP (XEXP (x, 0), 0) ==
- current_function_internal_arg_pointer
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)))
- RTX_UNCHANGING_P (x) = 0;
- return;
- }
-
- /* Scan all subexpressions. */
- fmt = GET_RTX_FORMAT (code);
- for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
- {
- if (*fmt == 'e')
- purge_mem_unchanging_flag (XEXP (x, i));
- else if (*fmt == 'E')
- for (j = 0; j < XVECLEN (x, i); j++)
- purge_mem_unchanging_flag (XVECEXP (x, i, j));
- }
-}
-
-
/* Generate all the code for a function call
and return an rtx for its value.
Store the value in TARGET (specified as an rtx) if convenient.
if (args[i].aligned_regs)
free (args[i].aligned_regs);
- /* If this function is returning into a memory location marked as
- readonly, it means it is initializing that location. We normally treat
- functions as not clobbering such locations, so we need to specify that
- this one does. We do this by adding the appropriate CLOBBER to the
- CALL_INSN function usage list. This cannot be done by emitting a
- standalone CLOBBER after the call because the latter would be ignored
- by at least the delay slot scheduling pass. We do this now instead of
- adding to call_fusage before the call to emit_call_1 because TARGET
- may be modified in the meantime. */
- if (structure_value_addr != 0 && target != 0
- && MEM_P (target) && RTX_UNCHANGING_P (target))
- add_function_usage_to
- (last_call_insn (),
- gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_CLOBBER (VOIDmode, target),
- NULL_RTX));
-
insns = get_insns ();
end_sequence ();
void
fixup_tail_calls (void)
{
- rtx insn;
- tree arg;
-
purge_reg_equiv_notes ();
-
- /* A sibling call sequence also may invalidate RTX_UNCHANGING_P
- flag of some incoming arguments MEM RTLs, because it can write into
- those slots. We clear all those bits now.
-
- This is (slight) overkill, we could keep track of which arguments
- we actually write into. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- purge_mem_unchanging_flag (PATTERN (insn));
- }
-
- /* Similarly, invalidate RTX_UNCHANGING_P for any incoming
- arguments passed in registers. */
- for (arg = DECL_ARGUMENTS (current_function_decl);
- arg;
- arg = TREE_CHAIN (arg))
- {
- if (REG_P (DECL_RTL (arg)))
- RTX_UNCHANGING_P (DECL_RTL (arg)) = false;
- }
}
/* Traverse an argument list in VALUES and expand all complex
/* If this is a memory reference, make sure that there were
no stores after it that might have clobbered the value. We don't
have alias info, so we assume any store invalidates it. */
- else if (MEM_P (x) && ! RTX_UNCHANGING_P (x)
+ else if (MEM_P (x) && !MEM_READONLY_P (x)
&& INSN_CUID (insn) <= mem_last_set)
{
if (replace)
/* Subfunction of the following function. Update the flags of any MEM
found in part of X. */
-static void
-alpha_set_memflags_1 (rtx x, int in_struct_p, int volatile_p, int unchanging_p)
+static int
+alpha_set_memflags_1 (rtx *xp, void *data)
{
- int i;
-
- switch (GET_CODE (x))
- {
- case SEQUENCE:
- abort ();
-
- case PARALLEL:
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
- unchanging_p);
- break;
+ rtx x = *xp, orig = (rtx) data;
- case INSN:
- alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
- unchanging_p);
- break;
+ if (GET_CODE (x) != MEM)
+ return 0;
- case SET:
- alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
- unchanging_p);
- alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
- unchanging_p);
- break;
+ MEM_VOLATILE_P (x) = MEM_VOLATILE_P (orig);
+ MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (orig);
+ MEM_SCALAR_P (x) = MEM_SCALAR_P (orig);
+ MEM_NOTRAP_P (x) = MEM_NOTRAP_P (orig);
+ MEM_READONLY_P (x) = MEM_READONLY_P (orig);
- case MEM:
- MEM_IN_STRUCT_P (x) = in_struct_p;
- MEM_VOLATILE_P (x) = volatile_p;
- RTX_UNCHANGING_P (x) = unchanging_p;
- /* Sadly, we cannot use alias sets because the extra aliasing
- produced by the AND interferes. Given that two-byte quantities
- are the only thing we would be able to differentiate anyway,
- there does not seem to be any point in convoluting the early
- out of the alias check. */
- break;
+ /* Sadly, we cannot use alias sets because the extra aliasing
+ produced by the AND interferes. Given that two-byte quantities
+ are the only thing we would be able to differentiate anyway,
+ there does not seem to be any point in convoluting the early
+ out of the alias check. */
- default:
- break;
- }
+ return -1;
}
/* Given INSN, which is an INSN list or the PATTERN of a single insn
void
alpha_set_memflags (rtx insn, rtx ref)
{
- int in_struct_p, volatile_p, unchanging_p;
+ rtx *base_ptr;
if (GET_CODE (ref) != MEM)
return;
- in_struct_p = MEM_IN_STRUCT_P (ref);
- volatile_p = MEM_VOLATILE_P (ref);
- unchanging_p = RTX_UNCHANGING_P (ref);
-
/* This is only called from alpha.md, after having had something
generated from one of the insn patterns. So if everything is
zero, the pattern is already up-to-date. */
- if (! in_struct_p && ! volatile_p && ! unchanging_p)
+ if (!MEM_VOLATILE_P (ref)
+ && !MEM_IN_STRUCT_P (ref)
+ && !MEM_SCALAR_P (ref)
+ && !MEM_NOTRAP_P (ref)
+ && !MEM_READONLY_P (ref))
return;
- alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
+ if (INSN_P (insn))
+ base_ptr = &PATTERN (insn);
+ else
+ base_ptr = &insn;
+ for_each_rtx (base_ptr, alpha_set_memflags_1, (void *) ref);
}
\f
/* Internal routine for alpha_emit_set_const to check for N or below insns. */
pic_ref = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
address));
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
}
insn = emit_move_insn (reg, pic_ref);
for (i = 0; i < count; i++)
{
mem = gen_rtx_MEM (SImode, plus_constant (from, i * 4 * sign));
- RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_READONLY_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
MEM_SCALAR_P (mem) = scalar_p;
emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
for (j = 0; i < count; i++, j++)
{
mem = gen_rtx_MEM (SImode, plus_constant (from, j * 4 * sign));
- RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_READONLY_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
MEM_SCALAR_P (mem) = scalar_p;
XVECEXP (result, 0, i)
for (i = 0; i < count; i++)
{
mem = gen_rtx_MEM (SImode, plus_constant (to, i * 4 * sign));
- RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_READONLY_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
MEM_SCALAR_P (mem) = scalar_p;
emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
for (j = 0; i < count; i++, j++)
{
mem = gen_rtx_MEM (SImode, plus_constant (to, j * 4 * sign));
- RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_READONLY_P (mem) = unchanging_p;
MEM_IN_STRUCT_P (mem) = in_struct_p;
MEM_SCALAR_P (mem) = scalar_p;
st_dst = XEXP (operands[0], 0);
st_src = XEXP (operands[1], 0);
- dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
+ dst_unchanging_p = MEM_READONLY_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_unchanging_p = MEM_READONLY_P (operands[1]);
src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
src_scalar_p = MEM_SCALAR_P (operands[1]);
else
{
mem = gen_rtx_MEM (SImode, dst);
- RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_READONLY_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));
rtx sreg;
mem = gen_rtx_MEM (SImode, src);
- RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_READONLY_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_READONLY_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);
abort ();
mem = gen_rtx_MEM (SImode, src);
- RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_READONLY_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);
while (last_bytes)
{
mem = gen_rtx_MEM (QImode, plus_constant (dst, last_bytes - 1));
- RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_READONLY_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_lowpart (QImode, part_bytes_reg));
if (last_bytes > 1)
{
mem = gen_rtx_MEM (HImode, dst);
- RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_READONLY_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_lowpart (HImode, part_bytes_reg));
if (last_bytes)
{
mem = gen_rtx_MEM (QImode, dst);
- RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_READONLY_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_lowpart (QImode, part_bytes_reg));
operands[3]
= arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[1], 0)),
- TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
- MEM_IN_STRUCT_P(operands[1]),
+ TRUE, FALSE, MEM_READONLY_P (operands[1]),
+ MEM_IN_STRUCT_P (operands[1]),
MEM_SCALAR_P (operands[1]));
"
)
operands[3]
= arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[0], 0)),
- TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
- MEM_IN_STRUCT_P(operands[0]),
+ TRUE, FALSE, MEM_READONLY_P (operands[0]),
+ MEM_IN_STRUCT_P (operands[0]),
MEM_SCALAR_P (operands[0]));
"
)
SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
- RTX_UNCHANGING_P (ptr_ref) = 1;
+ MEM_READONLY_P (ptr_ref) = 1;
return ptr_ref;
}
XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
- RTX_UNCHANGING_P (target) = 1;
+ MEM_READONLY_P (target) = 1;
}
return target;
emit_insn (gen_macho_high (temp_reg, asym));
mem = gen_rtx_MEM (GET_MODE (orig),
gen_rtx_LO_SUM (Pmode, temp_reg, asym));
- RTX_UNCHANGING_P (mem) = 1;
+ MEM_READONLY_P (mem) = 1;
emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
#else
/* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
mem = gen_rtx_MEM (GET_MODE (orig),
gen_rtx_LO_SUM (Pmode,
hi_sum_reg, offset));
- RTX_UNCHANGING_P (mem) = 1;
+ MEM_READONLY_P (mem) = 1;
insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
REG_NOTES (insn));
emit_move_insn (reg, pic_ref);
pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
#endif
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
}
else
{
gen_rtx_LO_SUM (Pmode,
hi_sum_reg, offset)));
pic_ref = reg;
- RTX_UNCHANGING_P (pic_ref) = 1;
#else
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_HIGH (Pmode, offset)));
gen_rtx_LO_SUM (Pmode, reg, offset)));
pic_ref = gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, reg);
- RTX_UNCHANGING_P (pic_ref) = 1;
#endif
}
else
else
pic_ref = gen_rtx_PLUS (Pmode, base, orig);
- if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
- RTX_UNCHANGING_P (pic_ref) = 1;
-
if (reg && is_complex)
{
emit_move_insn (reg, pic_ref);
&& GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
{
rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
-
- addr = gen_rtx_MEM (GET_MODE (orig), addr);
- RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
+ addr = replace_equiv_address (orig, addr);
emit_move_insn (reg, addr);
pic_ref = reg;
}
insn = emit_insn (gen_symGOT2reg_i (operands[0], operands[1], operands[2], operands[3]));
- RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
+ MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
REG_NOTES (insn));
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
set_mem_alias_set (new, ix86_GOT_alias_set ());
if (reg == 0)
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
set_mem_alias_set (new, ix86_GOT_alias_set ());
if (reg == 0)
if (pic)
off = gen_rtx_PLUS (Pmode, pic, off);
off = gen_rtx_MEM (Pmode, off);
- RTX_UNCHANGING_P (off) = 1;
+ MEM_READONLY_P (off) = 1;
set_mem_alias_set (off, ix86_GOT_alias_set ());
if (TARGET_64BIT || TARGET_GNU_TLS)
/* Optimize constant pool reference to immediates. This is used by fp
moves, that force all constants to memory to allow combining. */
- if (GET_CODE (operand) == MEM && RTX_UNCHANGING_P (operand))
+ if (GET_CODE (operand) == MEM && MEM_READONLY_P (operand))
{
rtx tmp = maybe_get_pool_constant (operand);
if (tmp)
gen_thread_pointer (void)
{
if (!thread_pointer_rtx)
- {
- thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
- RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
- }
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
return thread_pointer_rtx;
}
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ MEM_READONLY_P (tga_op1) = 1;
tga_op2 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
- RTX_UNCHANGING_P (tga_op2) = 1;
+ MEM_READONLY_P (tga_op2) = 1;
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
LCT_CONST, Pmode, 2, tga_op1,
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ MEM_READONLY_P (tga_op1) = 1;
tga_op2 = const0_rtx;
tmp = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_tprel (tmp, op1));
tmp = gen_rtx_MEM (Pmode, tmp);
- RTX_UNCHANGING_P (tmp) = 1;
+ MEM_READONLY_P (tmp) = 1;
tmp = force_reg (Pmode, tmp);
if (!register_operand (op0, Pmode))
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = gen_rtx_MEM (DImode, operands[2]);
- RTX_UNCHANGING_P (operands[3]) = 1;
+ MEM_READONLY_P (operands[3]) = 1;
})
(define_insn "*load_fptr_internal1"
gen_rtx_PLUS (Pmode, base_reg_rtx,
GEN_INT (gp_offset - base_offset)));
- if (! current_function_calls_eh_return)
- RTX_UNCHANGING_P (mem_rtx) = 1;
-
reg_rtx = gen_rtx_REG (gpr_mode, regno);
if (store_p)
emit_insn (gen_addsi3 (address, address, pic_offset_table_rtx));
pic_ref = gen_rtx_MEM (Pmode, address);
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
insn = emit_move_insn (reg, pic_ref);
current_function_uses_pic_offset_table = 1;
#if 0
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, orig));
current_function_uses_pic_offset_table = 1;
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
emit_move_insn (reg, pic_ref);
return reg;
}
#endif
gen_rtx_PLUS (Pmode, src, GEN_INT (offset_ld)));
- RTX_UNCHANGING_P (srcp) = RTX_UNCHANGING_P (src_mem);
+ MEM_READONLY_P (srcp) = MEM_READONLY_P (src_mem);
MEM_VOLATILE_P (srcp) = MEM_VOLATILE_P (src_mem);
MEM_IN_STRUCT_P (srcp) = 1;
emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
#endif
gen_rtx_PLUS (Pmode, dest, GEN_INT (offset_st)));
- RTX_UNCHANGING_P (dstp) = RTX_UNCHANGING_P (dst_mem);
+ MEM_READONLY_P (dstp) = MEM_READONLY_P (dst_mem);
MEM_VOLATILE_P (dstp) = MEM_VOLATILE_P (dst_mem);
MEM_IN_STRUCT_P (dstp) = 1;
emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
: stack_pointer_rtx,
current_function_outgoing_args_size);
slot = gen_rtx_MEM (Pmode, address);
- RTX_UNCHANGING_P (slot) = 1;
emit_move_insn (pic_offset_table_rtx, slot);
if (!TARGET_EXPLICIT_RELOCS)
rtx mem;
mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
- if (!current_function_calls_eh_return)
- RTX_UNCHANGING_P (mem) = 1;
fn (gen_rtx_REG (mode, regno), mem);
}
rtx insn, scan;
cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
- RTX_UNCHANGING_P (cfun->machine->mips16_gp_pseudo_rtx) = 1;
/* We want to initialize this to a value which gcc will believe
is constant. */
{
rtx insn = emit_insn (gen_symGOT2reg_i (operands[0], operands[1]));
- RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
+ MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
REG_NOTES (insn));
current_function_uses_pic_offset_table = 1;
MEM_NOTRAP_P (pic_ref) = 1;
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
mark_reg_pointer (reg, BITS_PER_UNIT);
insn = emit_move_insn (reg, pic_ref);
tmp2 = gen_reg_rtx (Pmode);
tmp3 = gen_reg_rtx (Pmode);
mem = gen_rtx_MEM (Pmode, tmp1);
- RTX_UNCHANGING_P (mem) = 1;
+ MEM_READONLY_P (mem) = 1;
first = emit_insn (gen_load_toc_v4_PIC_1b (tempLR, lab,
gsym));
= gen_rtx_MEM (mode,
create_TOC_reference (XEXP (operands[1], 0)));
set_mem_alias_set (operands[1], get_TOC_alias_set ());
- RTX_UNCHANGING_P (operands[1]) = 1;
+ MEM_READONLY_P (operands[1]) = 1;
}
}
break;
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
emit_move_insn (reg, new);
new = reg;
}
emit_move_insn (temp, new);
new = gen_rtx_MEM (Pmode, temp);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
emit_move_insn (reg, new);
new = reg;
}
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
emit_move_insn (reg, new);
new = reg;
}
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
}
emit_move_insn (temp, new);
new = gen_rtx_MEM (Pmode, temp);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
}
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
temp = gen_reg_rtx (Pmode);
new = temp;
new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ MEM_READONLY_P (new) = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
temp = gen_reg_rtx (Pmode);
emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
index = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, index));
- RTX_UNCHANGING_P (index) = 1;
+ MEM_READONLY_P (index) = 1;
MEM_NOTRAP_P (index) = 1;
emit_move_insn (target, index);
emit_insn (gen_load_gbr (tmp2));
tmp = gen_reg_rtx (Pmode);
emit_insn (gen_symTPOFF2reg (tmp, op1));
- RTX_UNCHANGING_P (tmp) = 1;
+ MEM_READONLY_P (tmp) = 1;
if (register_operand (op0, Pmode))
op1 = op0;
/* Remove the clobber of r0. */
*clobberp = gen_rtx_CLOBBER (GET_MODE (clobber),
gen_rtx_SCRATCH (Pmode));
- RTX_UNCHANGING_P (newsrc) = 1;
}
/* This is a mova needing a label. Create it. */
else if (GET_CODE (src) == UNSPEC
lab = add_constant (src, mode, 0);
newsrc = gen_rtx_MEM (mode,
gen_rtx_LABEL_REF (VOIDmode, lab));
- RTX_UNCHANGING_P (newsrc) = 1;
+ MEM_READONLY_P (newsrc) = 1;
}
*patp = gen_rtx_SET (VOIDmode, dst, newsrc);
INSN_CODE (scan) = -1;
PUT_MODE (gotsym, Pmode);
insn = emit_insn (gen_symGOT_load (operands[0], gotsym));
- RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
+ MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1;
DONE;
}")
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, address));
current_function_uses_pic_offset_table = 1;
- RTX_UNCHANGING_P (pic_ref) = 1;
+ MEM_READONLY_P (pic_ref) = 1;
insn = emit_move_insn (reg, pic_ref);
/* Put a REG_EQUAL note on this insn, so that it can be optimized
by loop. */
emit_insn (gen_addsi3 (reg, reg, tableaddress));
/* Load the table entry. */
mem = gen_rtx_MEM (CASE_VECTOR_MODE, reg);
- RTX_UNCHANGING_P (mem) = 1;
+ MEM_READONLY_P (mem) = 1;
if (! TARGET_BIG_SWITCH)
{
rtx reg2 = gen_reg_rtx (HImode);
elt->related_value = 0;
elt->in_memory = 0;
elt->mode = mode;
- elt->is_const = (CONSTANT_P (x)
- /* GNU C++ takes advantage of this for `this'
- (and other const values). */
- || (REG_P (x)
- && RTX_UNCHANGING_P (x)
- && REGNO (x) >= FIRST_PSEUDO_REGISTER)
- || fixed_base_plus_p (x));
+ elt->is_const = (CONSTANT_P (x) || fixed_base_plus_p (x));
if (table[hash])
table[hash]->prev_same_hash = elt;
Store 1 in do_not_record if any subexpression is volatile.
Store 1 in hash_arg_in_memory if X contains a MEM rtx
- which does not have the RTX_UNCHANGING_P bit set.
+ which does not have the MEM_READONLY_P bit set.
Note that cse_insn knows that the hash code of a MEM expression
is just (int) MEM plus the hash code of the address. */
do_not_record = 1;
return 0;
}
- if (! RTX_UNCHANGING_P (x) || fixed_base_plus_p (XEXP (x, 0)))
+ if (!MEM_READONLY_P (x))
hash_arg_in_memory = 1;
/* Now that we have already found this special case,
hash += (unsigned) USE;
x = XEXP (x, 0);
- if (! RTX_UNCHANGING_P (x) || fixed_base_plus_p (XEXP (x, 0)))
+ if (!MEM_READONLY_P (x))
hash_arg_in_memory = 1;
/* Now that we have already found this special case,
sets[i].dest_hash, GET_MODE (dest));
elt->in_memory = (MEM_P (sets[i].inner_dest)
- && (! RTX_UNCHANGING_P (sets[i].inner_dest)
- || fixed_base_plus_p (XEXP (sets[i].inner_dest,
- 0))));
+ && !MEM_READONLY_P (sets[i].inner_dest));
/* If we have (set (subreg:m1 (reg:m2 foo) 0) (bar:m1)), M1 is no
narrower than M2, and both M1 and M2 are the same number of words,
resulted from an in-line function call.
Stored in the @code{integrated} field and printed as @samp{/i}.
-@findex RTX_UNCHANGING_P
-@cindex @code{reg} and @samp{/u}
+@findex MEM_READONLY_P
@cindex @code{mem} and @samp{/u}
-@cindex @code{concat} and @samp{/u}
-@cindex @code{unchanging}, in @code{reg} and @code{mem}
-@item RTX_UNCHANGING_P (@var{x})
-Nonzero in a @code{reg}, @code{mem}, or @code{concat} if the register or
-memory is set at most once, anywhere. This does not mean that it is
-function invariant.
-
-GCC uses this flag to determine whether two references conflict. As
-implemented by @code{true_dependence} in @file{alias.c} for memory
-references, unchanging memory can't conflict with non-unchanging memory;
-a non-unchanging read can conflict with a non-unchanging write; an
-unchanging read can conflict with an unchanging write (since there may
-be a single store to this address to initialize it); and an unchanging
-store can conflict with a non-unchanging read. This means we must make
-conservative assumptions when choosing the value of this flag for a
-memory reference to an object containing both unchanging and
-non-unchanging fields: we must set the flag when writing to the object
-and clear it when reading from the object.
+@cindex @code{unchanging}, in @code{mem}
+@item MEM_READONLY_P (@var{x})
+Nonzero in a @code{mem}, if the memory is statically allocated and read-only.
+
+Read-only in this context never modified during the lifetime of the
+program, not necessarily in ROM or in write-disabled pages. A common
+example of the later is a shared library's global offset table. This
+table is initialized by the runtime loader, so the memory is technically
+writable, but after control is transfered from the runtime loader to the
+application, this memory will never be subsequently modified.
Stored in the @code{unchanging} field and printed as @samp{/u}.
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) || (t != type && TREE_READONLY (t))))
- || (! TYPE_P (t) && TREE_CONSTANT (t)));
MEM_POINTER (ref) = POINTER_TYPE_P (type);
MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (t);
the expression. */
if (! TYPE_P (t))
{
- maybe_set_unchanging (ref, t);
+ tree base = get_base_address (t);
+ if (base && DECL_P (base)
+ && TREE_READONLY (base)
+ && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
+ MEM_READONLY_P (ref) = 1;
+
if (TREE_THIS_VOLATILE (t))
MEM_VOLATILE_P (ref) = 1;
return replace_equiv_address (ref, XEXP (ref, 0));
}
\f
-/* Given REF, either a MEM or a REG, and T, either the type of X or
- the expression corresponding to REF, set RTX_UNCHANGING_P if
- appropriate. */
-
-void
-maybe_set_unchanging (rtx ref, tree t)
-{
- /* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
- initialization is only executed once, or whose initializer always
- has the same value. Currently we simplify this to PARM_DECLs in the
- first case, and decls with TREE_CONSTANT initializers in the second.
-
- We cannot do this for non-static aggregates, because of the double
- writes that can be generated by store_constructor, depending on the
- contents of the initializer. Yes, this does eliminate a good fraction
- of the number of uses of RTX_UNCHANGING_P for a language like Ada.
- It also eliminates a good quantity of bugs. Let this be incentive to
- eliminate RTX_UNCHANGING_P entirely in favor of a more reliable
- solution, perhaps based on alias sets. */
-
- if ((TREE_READONLY (t) && DECL_P (t)
- && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t)))
- && (TREE_CODE (t) == PARM_DECL
- || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
- || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
- RTX_UNCHANGING_P (ref) = 1;
-}
-\f
/* Return a modified copy of X with its memory address copied
into a temporary register to protect it from side effects.
If X is not a MEM, it is returned unchanged (and not copied).
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
- /* If we are initializing a readonly value, show the above call clobbered
- it. Otherwise, a load from it may erroneously be hoisted from a loop, or
- the delay slot scheduler might overlook conflicts and take nasty
- decisions. */
- if (RTX_UNCHANGING_P (dst))
- add_function_usage_to
- (last_call_insn (), gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_CLOBBER (VOIDmode, dst),
- NULL_RTX));
-
return retval;
}
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
- /* If we are initializing a readonly value, show the above call
- clobbered it. Otherwise, a load from it may erroneously be
- hoisted from a loop. */
- if (RTX_UNCHANGING_P (object))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
-
return retval;
}
|| x == 0
/* Only registers can be subtargets. */
|| !REG_P (x)
- /* If the register is readonly, it can't be set more than once. */
- || RTX_UNCHANGING_P (x)
/* Don't use hard regs to avoid extending their life. */
|| REGNO (x) < FIRST_PSEUDO_REGISTER
? 0 : x);
MEM_VOLATILE_P (to_rtx) = 1;
}
- if (TREE_CODE (to) == COMPONENT_REF
- && TREE_READONLY (TREE_OPERAND (to, 1))
- /* We can't assert that a MEM won't be set more than once
- if the component is not addressable because another
- non-addressable component may be referenced by the same MEM. */
- && ! (MEM_P (to_rtx) && ! can_address_p (to)))
- {
- if (to_rtx == orig_to_rtx)
- to_rtx = copy_rtx (to_rtx);
- RTX_UNCHANGING_P (to_rtx) = 1;
- }
-
if (MEM_P (to_rtx) && ! can_address_p (to))
{
if (to_rtx == orig_to_rtx)
|| ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
== size)))
{
- rtx xtarget = target;
-
- if (readonly_fields_p (type))
- {
- xtarget = copy_rtx (xtarget);
- RTX_UNCHANGING_P (xtarget) = 1;
- }
-
- clear_storage (xtarget, GEN_INT (size));
+ clear_storage (target, GEN_INT (size));
cleared = 1;
}
highest_pow2_factor (offset));
}
- if (TREE_READONLY (field))
- {
- if (MEM_P (to_rtx))
- to_rtx = copy_rtx (to_rtx);
-
- RTX_UNCHANGING_P (to_rtx) = 1;
- }
-
#ifdef WORD_REGISTER_OPERATIONS
/* If this initializes a field that is smaller than a word, at the
start of a word, try to widen it to a full word.
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
- /* If we are writing to this object and its type is a record with
- readonly fields, we must mark it as readonly so it will
- conflict with readonly references to those fields. */
- if (modifier == EXPAND_WRITE && readonly_fields_p (type))
- RTX_UNCHANGING_P (temp) = 1;
-
return temp;
}
index = memory_address_noforce (CASE_VECTOR_MODE, index);
temp = gen_reg_rtx (CASE_VECTOR_MODE);
vector = gen_rtx_MEM (CASE_VECTOR_MODE, index);
- RTX_UNCHANGING_P (vector) = 1;
+ MEM_READONLY_P (vector) = 1;
MEM_NOTRAP_P (vector) = 1;
convert_move (temp, vector, 0);
valid address. */
extern rtx validize_mem (rtx);
-/* Given REF, either a MEM or a REG, and T, either the type of X or
- the expression corresponding to REF, set RTX_UNCHANGING_P if
- appropriate. */
-extern void maybe_set_unchanging (rtx, tree);
-
/* 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. */
rtx_equal_p does not check the alias set or flags, we also
must have the potential for them to conflict (anti_dependence). */
for (temp = pbi->mem_set_list; temp != 0; temp = XEXP (temp, 1))
- if (unchanging_anti_dependence (r, XEXP (temp, 0)))
+ if (anti_dependence (r, XEXP (temp, 0)))
{
rtx mem = XEXP (temp, 0);
while (temp)
{
next = XEXP (temp, 1);
- if (unchanging_anti_dependence (XEXP (temp, 0), x))
+ if (anti_dependence (XEXP (temp, 0), x))
{
/* Splice temp out of the list. */
if (prev)
/* If a type is specified, set the relevant flags. */
if (type != 0)
{
- RTX_UNCHANGING_P (slot) = (lang_hooks.honor_readonly
- && TYPE_READONLY (type));
MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
}
SET_DECL_RTL (parm, x);
}
else
- {
- SET_DECL_RTL (parm, parmreg);
- maybe_set_unchanging (DECL_RTL (parm), parm);
- }
+ SET_DECL_RTL (parm, parmreg);
/* Copy the value into the register. */
if (data->nominal_mode != data->passed_mode
set_decl_incoming_rtl (parm, static_chain_incoming_rtx);
SET_DECL_RTL (parm, local);
- maybe_set_unchanging (local, parm);
mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
emit_move_insn (local, static_chain_incoming_rtx);
rtl is ever emitted.
If FOR_LHS is nonzero, if means we are processing something that will
- be the LHS of a SET. In that case, we copy RTX_UNCHANGING_P even if
- inlining since we need to be conservative in how it is set for
- such cases.
+ be the LHS of a SET.
Handle constants that need to be placed in the constant pool by
calling `force_const_mem'. */
map->reg_map[regno] = gen_reg_rtx (mode);
REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
- RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
/* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
if (REG_POINTER (map->x_regno_reg_rtx[regno]))
if (find_reg_note (insn, REG_DEAD, reg))
return 1;
- if (CALL_P (insn) && ! RTX_UNCHANGING_P (memref)
+ if (CALL_P (insn) && ! MEM_READONLY_P (memref)
&& ! CONST_OR_PURE_CALL_P (insn))
return 0;
switch (code)
{
case MEM:
- return ! RTX_UNCHANGING_P (x) || equiv_init_varies_p (XEXP (x, 0));
+ return !MEM_READONLY_P (x) || equiv_init_varies_p (XEXP (x, 0));
case CONST:
case CONST_INT:
/* Just handle the most trivial case where we load from an unchanging
location (most importantly, pic tables). */
- if (RTX_UNCHANGING_P (x))
+ if (MEM_READONLY_P (x))
break;
return false;
loop_info->has_call = 1;
if (can_throw_internal (insn))
loop_info->has_multiple_exit_targets = 1;
-
- /* Calls initializing constant objects have CLOBBER of MEM /u in the
- attached FUNCTION_USAGE expression list, not accounted for by the
- code above. We should note these to avoid missing dependencies in
- later references. */
- {
- rtx fusage_entry;
-
- for (fusage_entry = CALL_INSN_FUNCTION_USAGE (insn);
- fusage_entry; fusage_entry = XEXP (fusage_entry, 1))
- {
- rtx fusage = XEXP (fusage_entry, 0);
-
- if (GET_CODE (fusage) == CLOBBER
- && MEM_P (XEXP (fusage, 0))
- && RTX_UNCHANGING_P (XEXP (fusage, 0)))
- {
- note_stores (fusage, note_addr_stored, loop_info);
- if (! loop_info->first_loop_store_insn
- && loop_info->store_mems)
- loop_info->first_loop_store_insn = insn;
- }
- }
- }
break;
case JUMP_INSN:
if (loop_info->unknown_constant_address_altered)
{
rtx mem = gen_rtx_MEM (BLKmode, const0_rtx);
-
- RTX_UNCHANGING_P (mem) = 1;
+ MEM_READONLY_P (mem) = 1;
loop_info->store_mems
= gen_rtx_EXPR_LIST (VOIDmode, mem, loop_info->store_mems);
}
/* BLKmode MEM means all memory is clobbered. */
if (GET_MODE (x) == BLKmode)
{
- if (RTX_UNCHANGING_P (x))
+ if (MEM_READONLY_P (x))
loop_info->unknown_constant_address_altered = 1;
else
loop_info->unknown_address_altered = 1;
return 0;
case REG:
- /* We used to check RTX_UNCHANGING_P (x) here, but that is invalid
- since the reg might be set by initialization within the loop. */
-
if ((x == frame_pointer_rtx || x == hard_frame_pointer_rtx
|| x == arg_pointer_rtx || x == pic_offset_table_rtx)
&& ! current_function_has_nonlocal_goto)
place = assign_stack_local (PSEUDO_REGNO_MODE (web->regno),
total_size,
inherent_size == total_size ? 0 : -1);
- RTX_UNCHANGING_P (place) =
- RTX_UNCHANGING_P (regno_reg_rtx[web->regno]);
set_mem_alias_set (place, new_alias_set ());
}
else
if (REG_P (src)
&& REG_LIVE_LENGTH (REGNO (src)) > 0
&& REG_P (dest)
- && !RTX_UNCHANGING_P (dest)
&& REG_LIVE_LENGTH (REGNO (dest)) > 0
&& (set = single_set (insn)) != NULL_RTX
&& !reg_mentioned_p (dest, SET_SRC (set))
if (!REG_P (dst)
|| REGNO (dst) < FIRST_PSEUDO_REGISTER
|| REG_LIVE_LENGTH (REGNO (dst)) < 0
- || RTX_UNCHANGING_P (dst)
|| GET_MODE (src) != GET_MODE (dst))
continue;
rtx src_note = find_reg_note (insn, REG_DEAD, src), dst_note = NULL_RTX;
int length, s_length;
- /* If SRC is marked as unchanging, we may not change it.
- ??? Maybe we could get better code by removing the unchanging bit
- instead, and changing it back if we don't succeed? */
- if (RTX_UNCHANGING_P (src))
- return 0;
-
if (! src_note)
{
/* Look for (set (regX) (op regA constX))
mentioning SRC or mentioning / changing DST . If in doubt, presume
it is unstable.
The rationale is that we want to check if we can move an insn easily
- while just paying attention to SRC and DST. A register is considered
- stable if it has the RTX_UNCHANGING_P bit set, but that would still
- leave the burden to update REG_DEAD / REG_UNUSED notes, so we don't
- want any registers but SRC and DST. */
+ while just paying attention to SRC and DST. */
static int
stable_and_no_regs_but_for_p (rtx x, rtx src, rtx dst)
{
MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
else
{
- RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
- = MEM_SCALAR_P (reg) = 0;
+ MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
MEM_ATTRS (reg) = 0;
}
}
below. */
adjust = inherent_size - total_size;
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
-
/* Nothing can alias this slot except this pseudo. */
set_mem_alias_set (x, new_alias_set ());
}
case MEM:
/* If this memory shouldn't change, it really isn't referencing
memory. */
- if (RTX_UNCHANGING_P (x))
+ if (MEM_READONLY_P (x))
res->unch_memory = 1;
else
res->memory = 1;
if (in_dest)
{
res->memory = 1;
- res->unch_memory |= RTX_UNCHANGING_P (x);
+ res->unch_memory |= MEM_READONLY_P (x);
res->volatil |= MEM_VOLATILE_P (x);
}
They are always in the same basic block as this insn. */
#define LOG_LINKS(INSN) XEXP(INSN, 7)
-#define RTX_UNCHANGING_P(RTX) \
- (RTL_FLAG_CHECK3("RTX_UNCHANGING_P", (RTX), REG, MEM, CONCAT)->unchanging)
#define RTX_FRAME_RELATED_P(RTX) \
(RTL_FLAG_CHECK5("RTX_FRAME_RELATED_P", (RTX), INSN, CALL_INSN, \
JUMP_INSN, BARRIER, SET)->frame_related)
#define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT (RTX, 6, ASM_OPERANDS)
#endif
+/* 1 if RTX is a mem that is statically allocated in read-only memory. */
+#define MEM_READONLY_P(RTX) \
+ (RTL_FLAG_CHECK1("MEM_READONLY_P", (RTX), MEM)->unchanging)
+
/* 1 if RTX is a mem and we should keep the alias set for this mem
unchanged when we access a component. Set to 1, or example, when we
are already in a non-addressable component of an aggregate. */
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \
MEM_NOTRAP_P (LHS) = MEM_NOTRAP_P (RHS), \
- RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS), \
+ MEM_READONLY_P (LHS) = MEM_READONLY_P (RHS), \
MEM_KEEP_ALIAS_SET_P (LHS) = MEM_KEEP_ALIAS_SET_P (RHS), \
MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
extern int read_dependence (rtx, rtx);
extern int anti_dependence (rtx, rtx);
extern int output_dependence (rtx, rtx);
-extern int unchanging_anti_dependence (rtx, rtx);
extern void mark_constant_function (void);
extern void init_alias_once (void);
extern void init_alias_analysis (void);
switch (code)
{
case MEM:
- return ! RTX_UNCHANGING_P (x) || rtx_unstable_p (XEXP (x, 0));
+ return !MEM_READONLY_P (x) || rtx_unstable_p (XEXP (x, 0));
case CONST:
case CONST_INT:
/* As in rtx_varies_p, we have to use the actual rtx, not reg number. */
if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
/* The arg pointer varies if it is not a fixed register. */
- || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])
- || RTX_UNCHANGING_P (x))
+ || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM]))
return 0;
#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
/* ??? When call-clobbered, the value is stable modulo the restore
switch (code)
{
case MEM:
- return ! RTX_UNCHANGING_P (x) || rtx_varies_p (XEXP (x, 0), for_alias);
+ return !MEM_READONLY_P (x) || rtx_varies_p (XEXP (x, 0), for_alias);
case CONST:
case CONST_INT:
return 1;
case MEM:
- if (RTX_UNCHANGING_P (x))
+ if (MEM_READONLY_P (x))
return 0;
if (modified_between_p (XEXP (x, 0), start, end))
return 1;
return 1;
case MEM:
- if (RTX_UNCHANGING_P (x))
+ if (MEM_READONLY_P (x))
return 0;
if (modified_in_p (XEXP (x, 0), insn))
return 1;
mark_reg_pointer (DECL_RTL (decl),
TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
}
-
- maybe_set_unchanging (DECL_RTL (decl), decl);
}
else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
extern void gimplify_and_add (tree, tree *);
/* Miscellaneous helpers. */
-extern tree get_base_address (tree t);
extern void gimple_add_tmp_var (tree);
extern tree gimple_current_bind_expr (void);
extern void gimple_push_bind_expr (tree);
extern bool in_gimple_form;
/* In tree-ssa-loop-niter.c. */
-
tree lower_bound_in_type (tree, tree);
tree upper_bound_in_type (tree, tree);
/* In tree-ssa-threadupdate.c. */
extern bool thread_through_all_blocks (void);
+/* In tree-gimple.c. */
+extern tree get_base_address (tree t);
+
#endif /* GCC_TREE_H */
char *unlikely_text_section_name = NULL;
-/* RTX_UNCHANGING_P in a MEM can mean it is stored into, for initialization.
- So giving constant the alias set for the type will allow such
- initializations to appear to conflict with the load of the constant. We
- avoid this by giving all constants an alias set for just constants.
- Since there will be no stores to that alias set, nothing will ever
- conflict with them. */
+/* We give all constants their own alias set. Perhaps redundant with
+ MEM_READONLY_P, but pre-dates it. */
static HOST_WIDE_INT const_alias_set;
/* Construct the MEM. */
desc->mem = def = gen_rtx_MEM (mode, symbol);
set_mem_attributes (def, lang_hooks.types.type_for_mode (mode, 0), 1);
- RTX_UNCHANGING_P (def) = 1;
+ MEM_READONLY_P (def) = 1;
/* If we're dropping a label to the constant pool, make sure we
don't delete it. */
REG_USERVAR_P (newreg) = REG_USERVAR_P (reg);
REG_POINTER (newreg) = REG_POINTER (reg);
REG_LOOP_TEST_P (newreg) = REG_LOOP_TEST_P (reg);
- RTX_UNCHANGING_P (newreg) = RTX_UNCHANGING_P (reg);
REG_ATTRS (newreg) = REG_ATTRS (reg);
if (dump_file)
fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg),