public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] [autovect] don't allow changing order of computation
@ 2007-08-04 10:56 Dorit Nuzman
  0 siblings, 0 replies; only message in thread
From: Dorit Nuzman @ 2007-08-04 10:56 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1723 bytes --]


Don't allow changing the order of the computation in the inner-loop during
outer-loop vectorization.

Rational: The vectorized inner-loop executes sequentially (each vectorized
inner-loop iteration contributes to VF outer-loop iterations in parallel).
Reductions in the inner-loop are therefore also computed in order (which is
why we don't need to worry if reassociation/fast-math etc allowed). There
were a few remaining bits that did change the order of the computation in
the inner-loop - the WIDEN_MULT_EVEN/ODD idioms and the widening
reduction-patterns DOT_PROD and WIDEN_SUM. So this patch makes sure we
don't use these idioms in the inner-loop when vectorizing the outer-loop.

This also makes this fix -
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00013.html - redundant.

Bootstrapped with vectorization enabled on powerpc64-linux and tested on
the vectorizer testcases on powerpc64-linux and i386-linux.
Committed to autovect-branch.

dorit

        * tree-vect-analyze.c (vect_mark_relevant): Revert last change.
        * tree-vectorize.c (supportable_widening_operation): Don't allow
        unrodered vectorization in the inner-loop when doing outer-loop
        vectorization.
        * tree-vect-patterns.c (vect_recog_dot_prod_pattern): Don't allow
        in the inner-loop when doing outer-loop vectorization. Add
        documentation and printout.
        (vect_recog_widen_sum_pattern): Likewise.

        * gcc.dg/vect/vect-outer-4g.c: Add check for pattern not allowed.
Make
        check-loop in main unvectorizable.
        * gcc.dg/vect/vect-outer-4k.c: Likewise.
        * gcc.dg/vect/vect-outer-4l.c: Likewise.
        * gcc.dg/vect/vect-outer-4f.c: Likewise.

(See attached file: aug4.txt)

[-- Attachment #2: aug4.txt --]
[-- Type: text/plain, Size: 12701 bytes --]

Index: testsuite/gcc.dg/vect/vect-outer-4g.c
===================================================================
*** testsuite/gcc.dg/vect/vect-outer-4g.c	(revision 127202)
--- testsuite/gcc.dg/vect/vect-outer-4g.c	(working copy)
*************** foo (){
*** 26,31 ****
--- 26,41 ----
    return s;
  }
  
+ unsigned int
+ bar (int i, unsigned int diff, unsigned short *in)
+ {
+     int j;
+     for (j = 0; j < M; j+=8) {
+       diff += in[j+i];
+     }
+     return diff;
+ }
+ 
  int main (void)
  {
    int i, j;
*************** int main (void)
*** 42,50 ****
  
    for (i = 0; i < N; i++) {
      diff = 0;
!     for (j = 0; j < M; j+=8) {
!       diff += in[j+i];
!     }
      s += diff;
    }
  
--- 52,58 ----
  
    for (i = 0; i < N; i++) {
      diff = 0;
!     diff = bar (i, diff, in);
      s += diff;
    }
  
*************** int main (void)
*** 55,58 ****
--- 63,67 ----
  }
  
  /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: not allowed" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-outer-4k.c
===================================================================
*** testsuite/gcc.dg/vect/vect-outer-4k.c	(revision 127202)
--- testsuite/gcc.dg/vect/vect-outer-4k.c	(working copy)
*************** foo (){
*** 26,31 ****
--- 26,41 ----
    return s;
  }
  
+ unsigned int
+ bar (int i, unsigned int diff, unsigned short *in)
+ {
+     int j;
+     for (j = 0; j < M; j+=8) {
+       diff += in[j+i];
+     }
+     return diff;
+ }
+ 
  int main (void)
  {
    int i, j;
*************** int main (void)
*** 42,50 ****
  
    for (i = 0; i < N; i++) {
      diff = 0;
!     for (j = 0; j < M; j+=8) {
!       diff += in[j+i];
!     }
      s += (diff>>3);
    }
  
--- 52,58 ----
  
    for (i = 0; i < N; i++) {
      diff = 0;
!     diff = bar (i, diff, in);
      s += (diff>>3);
    }
  
*************** int main (void)
*** 55,58 ****
--- 63,67 ----
  }
  
  /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* }  } } */
+ /* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: not allowed" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-outer-4l.c
===================================================================
*** testsuite/gcc.dg/vect/vect-outer-4l.c	(revision 127202)
--- testsuite/gcc.dg/vect/vect-outer-4l.c	(working copy)
*************** foo (){
*** 28,33 ****
--- 28,43 ----
    return s;
  }
  
+ unsigned int
+ bar (int i, unsigned int diff, unsigned short *in)
+ {
+     int j;
+     for (j = 0; j < M; j+=8) {
+       diff += in[j+i];
+     }
+     return diff;
+ }
+ 
  int main (void)
  {
    int i, j;
*************** int main (void)
*** 45,53 ****
    for (i = 0; i < N; i++) {
      arr[i] = 3;
      diff = 0;
!     for (j = 0; j < M; j+=8) {
!       diff += in[j+i];
!     }
      s += diff;
    }
  
--- 55,61 ----
    for (i = 0; i < N; i++) {
      arr[i] = 3;
      diff = 0;
!     diff = bar (i, diff, in);
      s += diff;
    }
  
*************** int main (void)
*** 58,61 ****
--- 66,70 ----
  }
  
  /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: not allowed" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-outer-4f.c
===================================================================
*** testsuite/gcc.dg/vect/vect-outer-4f.c	(revision 127202)
--- testsuite/gcc.dg/vect/vect-outer-4f.c	(working copy)
*************** int main (void)
*** 50,53 ****
--- 50,54 ----
  }
  
  /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: not allowed" 1 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
Index: tree-vectorizer.c
===================================================================
*** tree-vectorizer.c	(revision 127201)
--- tree-vectorizer.c	(working copy)
*************** supportable_widening_operation (enum tre
*** 1936,1941 ****
--- 1936,1943 ----
                                  enum tree_code *code1, enum tree_code *code2)
  {
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info);
+   struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
    bool ordered_p;
    enum machine_mode vec_mode;
    enum insn_code icode1, icode2;
*************** supportable_widening_operation (enum tre
*** 1958,1967 ****
       Some targets can take advantage of this and generate more efficient code.
       For example, targets like Altivec, that support widen_mult using a sequence
       of {mult_even,mult_odd} generate the following vectors:
!         vect1: [res1,res3,res5,res7], vect2: [res2,res4,res6,res8].  */
  
     if (STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
!        || STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer_by_reduction)
       ordered_p = false;
     else
       ordered_p = true;
--- 1960,1974 ----
       Some targets can take advantage of this and generate more efficient code.
       For example, targets like Altivec, that support widen_mult using a sequence
       of {mult_even,mult_odd} generate the following vectors:
!         vect1: [res1,res3,res5,res7], vect2: [res2,res4,res6,res8].
! 
!      When vectorizaing outer-loops, we execute the inner-loop sequentially
!      (each vectorized inner-loop iteration contributes to VF outer-loop 
!      iterations in parallel). We therefore don't allow to change the order 
!      of the computation in the inner-loop during outer-loop vectorization.  */
  
     if (STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction
!        && !nested_in_vect_loop_p (vect_loop, stmt))
       ordered_p = false;
     else
       ordered_p = true;
Index: tree-vect-analyze.c
===================================================================
*** tree-vect-analyze.c	(revision 127201)
--- tree-vect-analyze.c	(working copy)
*************** vect_mark_relevant (VEC(tree,heap) **wor
*** 3108,3145 ****
  
        pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
  
!       /* One exception to the above is when the pattern-stmt is an
! 	 "unordered reduction" operation, whose results are used in the
! 	 outer-loop, in which case the order of the generated 
! 	 results is important, and therefore we can't vectorize the pattern. 
! 
! 	 An "unordered reduction" is a reduction that is vectorized without 
! 	 preserving all the intermediate results, like widen_sum and dot_prod, 
! 	 that produce only N/2 results (by summing up pairs of intermediate 
! 	 results). If these results are actually used (e.g., stored, in an 
! 	 outer-loop), we need to have all N results (and in the right order). 
! 	 Therefore, in such a case, we cannot vectorize the reduction pattern,
! 	 and need to resort to vectorizing the original stmts.  */
!       if ((TREE_CODE (GIMPLE_STMT_OPERAND (pattern_stmt, 1)) == WIDEN_SUM_EXPR
! 	   || TREE_CODE (GIMPLE_STMT_OPERAND (pattern_stmt,1)) == DOT_PROD_EXPR)
! 	  && (relevant == vect_used_in_outer 
! 	      || relevant == vect_used_in_outer_by_reduction))
!         {
! 	  if (vect_print_dump_info (REPORT_DETAILS))
! 	    fprintf (vect_dump, "skip unordered reduction pattern.");
! 	  STMT_VINFO_RELATED_STMT (stmt_info) = NULL_TREE;
! 	  STMT_VINFO_IN_PATTERN_P (stmt_info) = false;
! 	}
!       else
! 	{
! 	  if (vect_print_dump_info (REPORT_DETAILS))
! 	    fprintf (vect_dump, "last stmt in pattern. don't mark relevant/live.");
! 	  stmt_info = vinfo_for_stmt (pattern_stmt);
! 	  gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
! 	  save_relevant = STMT_VINFO_RELEVANT (stmt_info);
! 	  save_live_p = STMT_VINFO_LIVE_P (stmt_info);
! 	  stmt = pattern_stmt;
! 	}
      }
  
    STMT_VINFO_LIVE_P (stmt_info) |= live_p;
--- 3108,3120 ----
  
        pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
  
!       if (vect_print_dump_info (REPORT_DETAILS))
!         fprintf (vect_dump, "last stmt in pattern. don't mark relevant/live.");
!       stmt_info = vinfo_for_stmt (pattern_stmt);
!       gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
!       save_relevant = STMT_VINFO_RELEVANT (stmt_info);
!       save_live_p = STMT_VINFO_LIVE_P (stmt_info);
!       stmt = pattern_stmt;
      }
  
    STMT_VINFO_LIVE_P (stmt_info) |= live_p;
Index: tree-vect-patterns.c
===================================================================
*** tree-vect-patterns.c	(revision 127201)
--- tree-vect-patterns.c	(working copy)
*************** widened_name_p (tree name, tree use_stmt
*** 149,155 ****
     * Return value: A new stmt that will be used to replace the sequence of
     stmts that constitute the pattern. In this case it will be:
          WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
! */
  
  static tree
  vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
--- 149,162 ----
     * Return value: A new stmt that will be used to replace the sequence of
     stmts that constitute the pattern. In this case it will be:
          WIDEN_DOT_PRODUCT <x_t, y_t, sum_0>
! 
!    Note: The dot-prod idiom is a widening reduction pattern that is
!          vectorized without preserving all the intermediate results. It
!          produces only N/2 (widened) results (by summing up pairs of
!          intermediate results) rather than all N results.  Therefore, we
!          cannot allow this pattern when we want to get all the results and in
!          the correct order (as is the case when this computation is in an
!          inner-loop nested in an outer-loop that us being vectorized).  */
  
  static tree
  vect_recog_dot_prod_pattern (tree last_stmt, tree *type_in, tree *type_out)
*************** vect_recog_dot_prod_pattern (tree last_s
*** 322,327 ****
--- 329,344 ----
        fprintf (vect_dump, "vect_recog_dot_prod_pattern: detected: ");
        print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
      }
+ 
+   /* We don't allow changing the order of the computation in the inner-loop
+      when doing outer-loop vectorization.  */
+   if (nested_in_vect_loop_p (loop, last_stmt))
+     {
+       if (vect_print_dump_info (REPORT_DETAILS))
+         fprintf (vect_dump, "vect_recog_dot_prod_pattern: not allowed.");
+       return NULL;
+     }
+ 
    return pattern_expr;
  }
  
*************** vect_recog_pow_pattern (tree last_stmt, 
*** 548,554 ****
     * Return value: A new stmt that will be used to replace the sequence of
     stmts that constitute the pattern. In this case it will be:
          WIDEN_SUM <x_t, sum_0>
! */
  
  static tree
  vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
--- 565,578 ----
     * Return value: A new stmt that will be used to replace the sequence of
     stmts that constitute the pattern. In this case it will be:
          WIDEN_SUM <x_t, sum_0>
! 
!    Note: The widneing-sum idiom is a widening reduction pattern that is 
! 	 vectorized without preserving all the intermediate results. It
!          produces only N/2 (widened) results (by summing up pairs of 
! 	 intermediate results) rather than all N results.  Therefore, we 
! 	 cannot allow this pattern when we want to get all the results and in 
! 	 the correct order (as is the case when this computation is in an 
! 	 inner-loop nested in an outer-loop that us being vectorized).  */
  
  static tree
  vect_recog_widen_sum_pattern (tree last_stmt, tree *type_in, tree *type_out)
*************** vect_recog_widen_sum_pattern (tree last_
*** 558,563 ****
--- 582,589 ----
    stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
    tree type, half_type;
    tree pattern_expr;
+   loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+   struct loop *loop = LOOP_VINFO_LOOP (loop_info);
  
    if (TREE_CODE (last_stmt) != GIMPLE_MODIFY_STMT)
      return NULL;
*************** vect_recog_widen_sum_pattern (tree last_
*** 607,612 ****
--- 633,648 ----
        fprintf (vect_dump, "vect_recog_widen_sum_pattern: detected: ");
        print_generic_expr (vect_dump, pattern_expr, TDF_SLIM);
      }
+ 
+   /* We don't allow changing the order of the computation in the inner-loop
+      when doing outer-loop vectorization.  */
+   if (nested_in_vect_loop_p (loop, last_stmt))
+     {
+       if (vect_print_dump_info (REPORT_DETAILS))
+         fprintf (vect_dump, "vect_recog_widen_sum_pattern: not allowed.");
+       return NULL;
+     }
+ 
    return pattern_expr;
  }
  

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-08-04 10:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-04 10:56 [patch] [autovect] don't allow changing order of computation Dorit Nuzman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).