aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-loop-distribution.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2021-04-07 13:17:05 +0200
committerRichard Biener <rguenther@suse.de>2021-04-07 13:25:06 +0200
commitc01ae2ab6b227e21835d128c90e974dce4604be9 (patch)
tree27b82badec76eac80372b97548289cf35fb33a92 /gcc/tree-loop-distribution.c
parent0d6ad10c170e3670f0b5e3709e0fa6e76b7065b3 (diff)
downloadgcc-c01ae2ab6b227e21835d128c90e974dce4604be9.zip
gcc-c01ae2ab6b227e21835d128c90e974dce4604be9.tar.gz
gcc-c01ae2ab6b227e21835d128c90e974dce4604be9.tar.bz2
tree-optimization/99954 - fix loop distribution memcpy classification
This fixes bogus classification of a copy as memcpy. We cannot use plain dependence analysis to decide between memcpy and memmove when it computes no dependence. Instead we have to try harder later which the patch does for the gcc.dg/tree-ssa/ldist-24.c testcase by resorting to tree-affine to compute the difference between src and dest and compare against the copy size. 2021-04-07 Richard Biener <rguenther@suse.de> PR tree-optimization/99954 * tree-loop-distribution.c: Include tree-affine.h. (generate_memcpy_builtin): Try using tree-affine to prove non-overlap. (loop_distribution::classify_builtin_ldst): Always classify as PKIND_MEMMOVE. * gcc.dg/torture/pr99954.c: New testcase.
Diffstat (limited to 'gcc/tree-loop-distribution.c')
-rw-r--r--gcc/tree-loop-distribution.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 583bb06..8b91a30 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -115,6 +115,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vectorizer.h"
#include "tree-eh.h"
#include "gimple-fold.h"
+#include "tree-affine.h"
#define MAX_DATAREFS_NUM \
@@ -1212,6 +1213,18 @@ generate_memcpy_builtin (class loop *loop, partition *partition)
kind = BUILT_IN_MEMCPY;
else
kind = BUILT_IN_MEMMOVE;
+ /* Try harder if we're copying a constant size. */
+ if (kind == BUILT_IN_MEMMOVE && poly_int_tree_p (nb_bytes))
+ {
+ aff_tree asrc, adest;
+ tree_to_aff_combination (src, ptr_type_node, &asrc);
+ tree_to_aff_combination (dest, ptr_type_node, &adest);
+ aff_combination_scale (&adest, -1);
+ aff_combination_add (&asrc, &adest);
+ if (aff_comb_cannot_overlap_p (&asrc, wi::to_poly_widest (nb_bytes),
+ wi::to_poly_widest (nb_bytes)))
+ kind = BUILT_IN_MEMCPY;
+ }
dest = force_gimple_operand_gsi (&gsi, dest, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
@@ -1759,11 +1772,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 memcpy if no dependence between load and store. */
+ /* Classify as memmove 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_MEMCPY;
+ partition->kind = PKIND_MEMMOVE;
return;
}