This fixes PR54132 where loop distribution pattern matching thinks that every loop that copies contiguous memory regions and has a dependence between input and output can be representet by a memmove. Not. Obviously.
Thus, fixed by doing proper dependence checks. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-09-19 Richard Guenther <rguent...@suse.de> PR tree-optimization/54132 * tree-loop-distribution.c (classify_partition): Properly check dependences for memmove. * tree-data-ref.h (compute_affine_dependence): Declare. * tree-data-ref.c (compute_affine_dependence): Export. * gcc.dg/tree-ssa/ldist-21.c: New testcase. * gcc.dg/torture/pr54132.c: Likewise. Index: gcc/tree-loop-distribution.c =================================================================== *** gcc/tree-loop-distribution.c (revision 191415) --- gcc/tree-loop-distribution.c (working copy) *************** classify_partition (loop_p loop, struct *** 1011,1016 **** --- 1011,1049 ---- || !operand_equal_p (DR_STEP (single_store), DR_STEP (single_load), 0)) return; + /* Now check that if there is a dependence this dependence is + of a suitable form for memmove. */ + VEC(loop_p, heap) *loops = NULL; + ddr_p ddr; + VEC_safe_push (loop_p, heap, loops, loop); + ddr = initialize_data_dependence_relation (single_load, single_store, + loops); + compute_affine_dependence (ddr, loop); + VEC_free (loop_p, heap, loops); + if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + { + free_dependence_relation (ddr); + return; + } + if (DDR_ARE_DEPENDENT (ddr) != chrec_known) + { + if (DDR_NUM_DIST_VECTS (ddr) == 0) + { + free_dependence_relation (ddr); + return; + } + lambda_vector dist_v; + FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v) + { + int dist = dist_v[index_in_loop_nest (loop->num, + DDR_LOOP_NEST (ddr))]; + if (dist > 0 && !DDR_REVERSED_P (ddr)) + { + free_dependence_relation (ddr); + return; + } + } + } partition->kind = PKIND_MEMCPY; partition->main_dr = single_store; partition->secondary_dr = single_load; Index: gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c (working copy) *************** *** 0 **** --- 1,11 ---- + /* { dg-do compile } */ + /* { dg-options "-O3 -fdump-tree-ldist-details" } */ + + void bar(char *p, int n) + { + int i; + for (i = 1; i < n; i++) + p[i-1] = p[i]; + } + + /* { dg-final { scan-tree-dump "generated memmove" "ldist" } } */ Index: gcc/testsuite/gcc.dg/torture/pr54132.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr54132.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr54132.c (working copy) *************** *** 0 **** --- 1,18 ---- + /* { dg-do run } */ + + extern void abort (void); + void foo(char *p, int n) + { + int i; + for (i = 1; i < n; i++) + p[i] = p[i - 1]; + } + int main() + { + char a[1024]; + a[0] = 1; + foo (a, 1024); + if (a[1023] != 1) + abort (); + return 0; + } Index: gcc/tree-data-ref.c =================================================================== *** gcc/tree-data-ref.c (revision 191415) --- gcc/tree-data-ref.c (working copy) *************** ddr_consistent_p (FILE *file, *** 4130,4136 **** relation the first time we detect a CHREC_KNOWN element for a given subscript. */ ! static void compute_affine_dependence (struct data_dependence_relation *ddr, struct loop *loop_nest) { --- 4130,4136 ---- relation the first time we detect a CHREC_KNOWN element for a given subscript. */ ! void compute_affine_dependence (struct data_dependence_relation *ddr, struct loop *loop_nest) { Index: gcc/tree-data-ref.h =================================================================== *** gcc/tree-data-ref.h (revision 191415) --- gcc/tree-data-ref.h (working copy) *************** struct data_reference *create_data_ref ( *** 396,401 **** --- 396,403 ---- extern bool find_loop_nest (struct loop *, VEC (loop_p, heap) **); extern struct data_dependence_relation *initialize_data_dependence_relation (struct data_reference *, struct data_reference *, VEC (loop_p, heap) *); + extern void compute_affine_dependence (struct data_dependence_relation *, + loop_p); extern void compute_self_dependence (struct data_dependence_relation *); extern bool compute_all_dependences (VEC (data_reference_p, heap) *, VEC (ddr_p, heap) **, VEC (loop_p, heap) *,