The following fixes PR69783, a missed optimization after my fix to
vectorizer runtime alias test merging.  While I still don't understand
the existing test guarding the merging (I've just fixed up things to
its assumptions based on the original posting), the following patch
adds two trivially correct cases applying before it which restores
the alias check reduction for the testcase (to 2 instead of 3 even).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

If any other issue with the old test comes up (I still believe the
condition is bogus) I'll simply remove it.

Richard.

2016-02-15  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/69783
        * tree-vect-data-refs.c (vect_prune_runtime_alias_test_list):
        Add trivially correct cases.

        * gcc.dg/vect/pr69783.c: New testcase.

Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c   (revision 233369)
--- gcc/tree-vect-data-refs.c   (working copy)
*************** vect_prune_runtime_alias_test_list (loop
*** 3089,3094 ****
--- 3089,3118 ----
            = tree_to_shwi (dr_a2->offset) - tree_to_shwi (dr_a1->offset);
  
  
+         bool do_remove = false;
+ 
+         /* If the left segment does not extend beyond the start of the
+            right segment the new segment length is that of the right
+            plus the segment distance.  */
+         if (tree_fits_uhwi_p (dr_a1->seg_len)
+             && compare_tree_int (dr_a1->seg_len, diff) <= 0)
+           {
+             dr_a1->seg_len = size_binop (PLUS_EXPR, dr_a2->seg_len,
+                                          size_int (diff));
+             do_remove = true;
+           }
+         /* Generally the new segment length is the maximum of the
+            left segment size and the right segment size plus the distance.
+            ???  We can also build tree MAX_EXPR here but it's not clear this
+            is profitable.  */
+         else if (tree_fits_uhwi_p (dr_a1->seg_len)
+                  && tree_fits_uhwi_p (dr_a2->seg_len))
+           {
+             unsigned HOST_WIDE_INT seg_len_a1 = tree_to_uhwi (dr_a1->seg_len);
+             unsigned HOST_WIDE_INT seg_len_a2 = tree_to_uhwi (dr_a2->seg_len);
+             dr_a1->seg_len = size_int (MAX (seg_len_a1, diff + seg_len_a2));
+             do_remove = true;
+           }
          /* Now we check if the following condition is satisfied:
  
             DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
*************** vect_prune_runtime_alias_test_list (loop
*** 3101,3139 ****
             one above:
  
             1: DIFF <= MIN_SEG_LEN_B
!            2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B
! 
!            */
  
!         unsigned HOST_WIDE_INT min_seg_len_b
!           = (tree_fits_uhwi_p (dr_b1->seg_len)
!              ? tree_to_uhwi (dr_b1->seg_len)
!              : vect_factor);
! 
!         if (diff <= min_seg_len_b
!             || (tree_fits_uhwi_p (dr_a1->seg_len)
!                 && diff - tree_to_uhwi (dr_a1->seg_len) < min_seg_len_b))
            {
              if (dump_enabled_p ())
                {
                  dump_printf_loc (MSG_NOTE, vect_location,
                                   "merging ranges for ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
!                                    DR_REF (dr_a1->dr));
                  dump_printf (MSG_NOTE,  ", ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
!                                    DR_REF (dr_b1->dr));
                  dump_printf (MSG_NOTE,  " and ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
!                                    DR_REF (dr_a2->dr));
                  dump_printf (MSG_NOTE,  ", ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
!                                    DR_REF (dr_b2->dr));
                  dump_printf (MSG_NOTE, "\n");
                }
- 
-             dr_a1->seg_len = size_binop (PLUS_EXPR,
-                                          dr_a2->seg_len, size_int (diff));
              comp_alias_ddrs.ordered_remove (i--);
            }
        }
--- 3125,3163 ----
             one above:
  
             1: DIFF <= MIN_SEG_LEN_B
!            2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B  */
!         else
!           {
!             unsigned HOST_WIDE_INT min_seg_len_b
!               = (tree_fits_uhwi_p (dr_b1->seg_len)
!                  ? tree_to_uhwi (dr_b1->seg_len)
!                  : vect_factor);
! 
!             if (diff <= min_seg_len_b
!                 || (tree_fits_uhwi_p (dr_a1->seg_len)
!                     && diff - tree_to_uhwi (dr_a1->seg_len) < min_seg_len_b))
!               {
!                 dr_a1->seg_len = size_binop (PLUS_EXPR,
!                                              dr_a2->seg_len, size_int (diff));
!                 do_remove = true;
!               }
!           }
  
!         if (do_remove)
            {
              if (dump_enabled_p ())
                {
                  dump_printf_loc (MSG_NOTE, vect_location,
                                   "merging ranges for ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a1->dr));
                  dump_printf (MSG_NOTE,  ", ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b1->dr));
                  dump_printf (MSG_NOTE,  " and ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a2->dr));
                  dump_printf (MSG_NOTE,  ", ");
!                 dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b2->dr));
                  dump_printf (MSG_NOTE, "\n");
                }
              comp_alias_ddrs.ordered_remove (i--);
            }
        }
Index: gcc/testsuite/gcc.dg/vect/pr69783.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/pr69783.c (revision 0)
--- gcc/testsuite/gcc.dg/vect/pr69783.c (working copy)
***************
*** 0 ****
--- 1,39 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_float } */
+ /* { dg-additional-options "-Ofast -funroll-loops" } */
+ 
+ #define NXX 516
+ #define NYY 516
+ #define IND(x,y) ((x) + (y)*NXX)
+ float **In, **Out, **V;
+ 
+ void foo(int I, int J, int K1, int K2, int L1, int L2 )
+ {
+   for(int i=0; i < I; i++)
+     {
+       float *v = V[i];
+ 
+       for(int j=0; j < J; j++)
+       {
+         float *in = In[j];
+         float *out = Out[j];
+         for(int l=L1; l<L2; l++)
+           {
+             for(int k=K1; k<K2; k++)
+               {
+                 float sum = 0;
+                 int offset = 0;
+                 for(int m=-2; m<=2; m++)
+                   {
+                     for(int n=-2; n<=2; n++, offset++)
+                       sum += in[IND((k+n), (l+m))] * v[offset];
+                   }
+                 out[IND(k,l)] = sum;
+               }
+           }
+ 
+       }
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump "improved number of alias checks from \[0-9\]* 
to 2" "vect" } } */

Reply via email to