aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-05-14 11:13:51 +0200
committerRichard Biener <rguenther@suse.de>2024-05-14 19:00:27 +0200
commitc290e6a0b7a9de5692963affc6627a4af7dc2411 (patch)
treef7b8f3cda47d4876fa4d6318f1ed559e40fe3b99
parent54ba8d44bbd703bca6984700b4d6f978890097e2 (diff)
downloadgcc-c290e6a0b7a9de5692963affc6627a4af7dc2411.zip
gcc-c290e6a0b7a9de5692963affc6627a4af7dc2411.tar.gz
gcc-c290e6a0b7a9de5692963affc6627a4af7dc2411.tar.bz2
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.
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c10
-rw-r--r--gcc/tree-data-ref.cc22
-rw-r--r--gcc/tree-loop-distribution.cc4
-rw-r--r--gcc/tree-ssa-alias.cc5
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 0000000..238a009
--- /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 f37734b..db15ddb 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 45932ba..668dc42 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 e7c1c1a..374ba04 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);