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) *,

Reply via email to