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

Reply via email to