https://gcc.gnu.org/g:c290e6a0b7a9de5692963affc6627a4af7dc2411

commit r15-491-gc290e6a0b7a9de5692963affc6627a4af7dc2411
Author: Richard Biener <rguent...@suse.de>
Date:   Tue May 14 11:13:51 2024 +0200

    tree-optimization/99954 - redo loop distribution memcpy recognition fix
    
    The following revisits the fix for PR99954 which was observed as
    causing missed memcpy recognition and instead using memmove for
    non-aliasing copies.  While the original fix mitigated bogus
    recognition of memcpy the root cause was not properly identified.
    The root cause is dr_analyze_indices "failing" to handle union
    references and leaving the DRs indices in a state that's not correctly
    handled by dr_may_alias.  The following mitigates this there
    appropriately, restoring memcpy recognition for non-aliasing copies.
    
    This makes us run into a latent issue in ptr_deref_may_alias_decl_p
    when the pointer is something like &MEM[0].a in which case we fail
    to handle non-SSA name pointers.  Add code similar to what we have
    in ptr_derefs_may_alias_p.
    
            PR tree-optimization/99954
            * tree-data-ref.cc (dr_may_alias_p): For bases that are
            not completely analyzed fall back to TBAA and points-to.
            * tree-loop-distribution.cc
            (loop_distribution::classify_builtin_ldst): When there
            is no dependence again classify as memcpy.
            * tree-ssa-alias.cc (ptr_deref_may_alias_decl_p): Verify
            the pointer is an SSA name.
    
            * gcc.dg/tree-ssa/ldist-40.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c | 10 ++++++++++
 gcc/tree-data-ref.cc                     | 22 ++++++++++++++++++++++
 gcc/tree-loop-distribution.cc            |  4 ++--
 gcc/tree-ssa-alias.cc                    |  5 +++++
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c
new file mode 100644
index 000000000000..238a0098352a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ldist-details" } */
+
+void copy_a_to_b (char * __restrict b, char * a, int n)
+{
+  for (int i = 0; i < n; ++i)
+    b[i] = a[i];
+}
+
+/* { dg-final { scan-tree-dump "generated memcpy" "ldist" } } */
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index f37734b53409..db15ddb43ded 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -3066,6 +3066,28 @@ dr_may_alias_p (const struct data_reference *a, const 
struct data_reference *b,
        return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a),
                                       TREE_OPERAND (addr_b, 0));
     }
+  /* If dr_analyze_innermost failed to handle a component we are
+     possibly left with a non-base in which case we didn't analyze
+     a possible evolution of the base when analyzing a loop.  */
+  else if (loop_nest
+          && (handled_component_p (addr_a) || handled_component_p (addr_b)))
+    {
+      /* For true dependences we can apply TBAA.  */
+      if (flag_strict_aliasing
+         && DR_IS_WRITE (a) && DR_IS_READ (b)
+         && !alias_sets_conflict_p (get_alias_set (DR_REF (a)),
+                                    get_alias_set (DR_REF (b))))
+       return false;
+      if (TREE_CODE (addr_a) == MEM_REF)
+       return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0),
+                                      build_fold_addr_expr (addr_b));
+      else if (TREE_CODE (addr_b) == MEM_REF)
+       return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a),
+                                      TREE_OPERAND (addr_b, 0));
+      else
+       return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a),
+                                      build_fold_addr_expr (addr_b));
+    }
 
   /* Otherwise DR_BASE_OBJECT is an access that covers the whole object
      that is being subsetted in the loop nest.  */
diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
index 45932bae5e7f..668dc4204490 100644
--- a/gcc/tree-loop-distribution.cc
+++ b/gcc/tree-loop-distribution.cc
@@ -1840,11 +1840,11 @@ loop_distribution::classify_builtin_ldst (loop_p loop, 
struct graph *rdg,
   /* Now check that if there is a dependence.  */
   ddr_p ddr = get_data_dependence (rdg, src_dr, dst_dr);
 
-  /* Classify as memmove if no dependence between load and store.  */
+  /* Classify as memcpy if no dependence between load and store.  */
   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
     {
       partition->builtin = alloc_builtin (dst_dr, src_dr, base, src_base, 
size);
-      partition->kind = PKIND_MEMMOVE;
+      partition->kind = PKIND_MEMCPY;
       return;
     }
 
diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc
index e7c1c1aa6243..374ba04e6fd0 100644
--- a/gcc/tree-ssa-alias.cc
+++ b/gcc/tree-ssa-alias.cc
@@ -294,6 +294,11 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
   if (!may_be_aliased (decl))
     return false;
 
+  /* From here we require a SSA name pointer.  Anything else aliases.  */
+  if (TREE_CODE (ptr) != SSA_NAME
+      || !POINTER_TYPE_P (TREE_TYPE (ptr)))
+    return true;
+
   /* If we do not have useful points-to information for this pointer
      we cannot disambiguate anything else.  */
   pi = SSA_NAME_PTR_INFO (ptr);

Reply via email to