diff options
author | Richard Biener <rguenther@suse.de> | 2024-05-14 11:13:51 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2024-05-14 19:00:27 +0200 |
commit | c290e6a0b7a9de5692963affc6627a4af7dc2411 (patch) | |
tree | f7b8f3cda47d4876fa4d6318f1ed559e40fe3b99 /gcc | |
parent | 54ba8d44bbd703bca6984700b4d6f978890097e2 (diff) | |
download | gcc-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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ldist-40.c | 10 | ||||
-rw-r--r-- | gcc/tree-data-ref.cc | 22 | ||||
-rw-r--r-- | gcc/tree-loop-distribution.cc | 4 | ||||
-rw-r--r-- | 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 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); |