I was looking again at:
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg00294.html
and was comparing the RTL {true,output,anti}_dependence functions.
output_dependence and anti_dependence call fixed_scalar_and_varying_struct_p
with rtx_addr_varies_p. Many places also call true_dependence with
rtx_addr_varies_p (which then gets passed to fixed_scalar_and_varying_struct_p).
But this doesn't seem to make much sense. rtx_addr_varies_p checks
whether an rtx X includes a MEM with a varying address, whereas
fixed_scalar_and_varying_struct_p passes an _address_ rather than a MEM.
So in these cases fixed_scalar_and_varying_struct_p effectively becomes
a no-op on targets that don't allow MEMs in addresses and takes on
suspicious semantics for those that do. In the former case, every
address is treated as "unvarying" and f_s_a_v_s_p always returns null.
In the latter case, things like REG addresses are (wrongly) treated as
unvarying while a MEM address might correctly be treated as varying,
leading to false positives.
It looks like this goes back to when fixed_scalar_and_varying_struct_p
was added in r24759 (1999). The anti_dependence change went from applying
rtx_addr_varies_p to the MEM to applying rtx_addr_varies_p to the address:
@@ -1234,16 +1279,25 @@ anti_dependence (mem, 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)));
This seems to have percolated into:
expr.c:safe_from_p
gcse.c:mems_conflict_for_gcse_p
gcse.c:compute_transp
postreload.c:find_mem_conflicts
store-motion.c:load_kills_store
which all pass rtx_addr_varies_p to true_dependence.
AIUI, the true_dependence varies_p parameter exists for the benefit
of CSE, so that it can use its local cse_rtx_varies_p function.
All other callers should be using rtx_varies_p instead. Question is,
should I make that change, or is it time to get rid of
fixed_scalar_and_varying_struct_p instead?
Richard