diff mbox series

tree-optimization/99954 - redo loop distribution memcpy recognition fix

Message ID 20240514092253.2CAF9137C3@imap1.dmz-prg2.suse.org
State New
Headers show
Series tree-optimization/99954 - redo loop distribution memcpy recognition fix | expand

Commit Message

Richard Biener May 14, 2024, 9:22 a.m. UTC
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.

Boostrap and regtest running on x86_64-unknown-linux-gnu.

 	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.

 	* gcc.dg/tree-ssa/ldist-40.c: New testcase.
---
  gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c | 10 ++++++++++
  gcc/tree-data-ref.cc                     | 21 +++++++++++++++++++++
  gcc/tree-loop-distribution.cc            |  4 ++--
  3 files changed, 33 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c
diff mbox series

Patch

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 00000000000..238a0098352
--- /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 f37734b5340..9d3f5d7507f 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -3066,6 +3066,27 @@  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.  */
+  else if (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 45932bae5e7..668dc420449 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;
      }