[PATCH] Fix PR52678

Richard Guenther rguenther@suse.de
Fri Mar 23 11:32:00 GMT 2012


This patch fixes PR52678 - re-computing the evolution of a loop
PHI node after updating it during prologue loop peeling is fragile
(and I remember several cases in the past where we ICEd here and
adjusted the code).  So, instead of re-computing the evolution
this patch saves the evolution part at analysis time and re-uses
it at this place.

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

Richard.

2012-03-23  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/52678
	* tree-vectorizer.h (struct _stmt_vec_info): Add
	loop_phi_evolution_part member.
	(STMT_VINFO_LOOP_PHI_EVOLUTION_PART): New define.
	* tree-vect-loop.c (vect_analyze_scalar_cycles_1): Initialize
	STMT_VINFO_LOOP_PHI_EVOLUTION_PART.
	* tree-vect-loop-manip.c (vect_update_ivs_after_vectorizer):
	Use the cached evolution part and the PHI nodes value from
	the loop preheader edge instead of re-analyzing the evolution.

	* gfortran.dg/pr52678.f: New testcase.

Index: gcc/tree-vectorizer.h
===================================================================
*** gcc/tree-vectorizer.h	(revision 185724)
--- gcc/tree-vectorizer.h	(working copy)
*************** typedef struct _stmt_vec_info {
*** 476,481 ****
--- 476,488 ----
    tree dr_step;
    tree dr_aligned_to;
  
+   /* For loop PHI nodes, the evolution part of it.  This makes sure
+      this information is still available in vect_update_ivs_after_vectorizer
+      where we may not be able to re-analyze the PHI nodes evolution as
+      peeling for the prologue loop can make it unanalyzable.  The evolution
+      part is still correct though.  */
+   tree loop_phi_evolution_part;
+ 
    /* Used for various bookkeeping purposes, generally holding a pointer to
       some other stmt S that is in some way "related" to this stmt.
       Current use of this field is:
*************** typedef struct _stmt_vec_info {
*** 572,577 ****
--- 579,585 ----
  #define STMT_VINFO_GROUP_SAME_DR_STMT(S)   (S)->same_dr_stmt
  #define STMT_VINFO_GROUP_READ_WRITE_DEPENDENCE(S)  (S)->read_write_dep
  #define STMT_VINFO_STRIDED_ACCESS(S)      ((S)->first_element != NULL && (S)->data_ref_info)
+ #define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part
  
  #define GROUP_FIRST_ELEMENT(S)          (S)->first_element
  #define GROUP_NEXT_ELEMENT(S)           (S)->next_element
Index: gcc/tree-vect-loop.c
===================================================================
*** gcc/tree-vect-loop.c	(revision 185724)
--- gcc/tree-vect-loop.c	(working copy)
*************** vect_analyze_scalar_cycles_1 (loop_vec_i
*** 579,584 ****
--- 579,588 ----
  	  continue;
  	}
  
+       STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo)
+ 	= evolution_part_in_loop_num (access_fn, loop->num);
+       gcc_assert (STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo) != NULL_TREE);
+ 
        if (vect_print_dump_info (REPORT_DETAILS))
  	fprintf (vect_dump, "Detected induction.");
        STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def;
Index: gcc/tree-vect-loop-manip.c
===================================================================
*** gcc/tree-vect-loop-manip.c	(revision 185724)
--- gcc/tree-vect-loop-manip.c	(working copy)
*************** vect_update_ivs_after_vectorizer (loop_v
*** 1797,1809 ****
         !gsi_end_p (gsi) && !gsi_end_p (gsi1);
         gsi_next (&gsi), gsi_next (&gsi1))
      {
-       tree access_fn = NULL;
-       tree evolution_part;
        tree init_expr;
        tree step_expr, off;
        tree type;
        tree var, ni, ni_name;
        gimple_stmt_iterator last_gsi;
  
        phi = gsi_stmt (gsi);
        phi1 = gsi_stmt (gsi1);
--- 1797,1808 ----
         !gsi_end_p (gsi) && !gsi_end_p (gsi1);
         gsi_next (&gsi), gsi_next (&gsi1))
      {
        tree init_expr;
        tree step_expr, off;
        tree type;
        tree var, ni, ni_name;
        gimple_stmt_iterator last_gsi;
+       stmt_vec_info stmt_info;
  
        phi = gsi_stmt (gsi);
        phi1 = gsi_stmt (gsi1);
*************** vect_update_ivs_after_vectorizer (loop_v
*** 1822,1866 ****
  	}
  
        /* Skip reduction phis.  */
!       if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (phi)) == vect_reduction_def)
          {
            if (vect_print_dump_info (REPORT_DETAILS))
              fprintf (vect_dump, "reduc phi. skip.");
            continue;
          }
  
!       access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi));
!       gcc_assert (access_fn);
!       /* We can end up with an access_fn like
!            (short int) {(short unsigned int) i_49, +, 1}_1
! 	 for further analysis we need to strip the outer cast but we
! 	 need to preserve the original type.  */
!       type = TREE_TYPE (access_fn);
!       STRIP_NOPS (access_fn);
!       evolution_part =
! 	 unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
!       gcc_assert (evolution_part != NULL_TREE);
  
        /* FORNOW: We do not support IVs whose evolution function is a polynomial
           of degree >= 2 or exponential.  */
!       gcc_assert (!tree_is_chrec (evolution_part));
  
!       step_expr = evolution_part;
!       init_expr = unshare_expr (initial_condition_in_loop_num (access_fn,
! 							       loop->num));
!       init_expr = fold_convert (type, init_expr);
  
        off = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
  			 fold_convert (TREE_TYPE (step_expr), niters),
  			 step_expr);
!       if (POINTER_TYPE_P (TREE_TYPE (init_expr)))
  	ni = fold_build_pointer_plus (init_expr, off);
        else
! 	ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr),
! 			  init_expr,
! 			  fold_convert (TREE_TYPE (init_expr), off));
  
!       var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
        add_referenced_var (var);
  
        last_gsi = gsi_last_bb (exit_bb);
--- 1821,1854 ----
  	}
  
        /* Skip reduction phis.  */
!       stmt_info = vinfo_for_stmt (phi);
!       if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
          {
            if (vect_print_dump_info (REPORT_DETAILS))
              fprintf (vect_dump, "reduc phi. skip.");
            continue;
          }
  
!       type = TREE_TYPE (gimple_phi_result (phi));
!       step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_info);
!       step_expr = unshare_expr (step_expr);
  
        /* FORNOW: We do not support IVs whose evolution function is a polynomial
           of degree >= 2 or exponential.  */
!       gcc_assert (!tree_is_chrec (step_expr));
  
!       init_expr = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
  
        off = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr),
  			 fold_convert (TREE_TYPE (step_expr), niters),
  			 step_expr);
!       if (POINTER_TYPE_P (type))
  	ni = fold_build_pointer_plus (init_expr, off);
        else
! 	ni = fold_build2 (PLUS_EXPR, type,
! 			  init_expr, fold_convert (type, off));
  
!       var = create_tmp_var (type, "tmp");
        add_referenced_var (var);
  
        last_gsi = gsi_last_bb (exit_bb);
Index: gcc/testsuite/gfortran.dg/pr52678.f
===================================================================
*** gcc/testsuite/gfortran.dg/pr52678.f	(revision 0)
--- gcc/testsuite/gfortran.dg/pr52678.f	(revision 0)
***************
*** 0 ****
--- 1,18 ----
+ ! { dg-do compile }
+ ! { dg-options "-O -ftree-vectorize" }
+       SUBROUTINE OpenAD_set_ref_state(DRF, RHOFACF, RHOFACC)
+       real(8) DRF(1 : 15)
+       real(8) RHOFACF(1 : 16)
+       real(8) RHOFACC(1 : 15)
+       integer, dimension(:), allocatable :: oad_it
+       integer :: oad_it_ptr
+       INTEGER(8) OpenAD_Symbol_188
+       INTEGER(4) K
+           OpenAD_Symbol_188 = 0
+           DO K = 2, 15, 1
+             RHOFACF(INT(K)) = ((RHOFACC(K) * DRF(K + (-1)) + RHOFACC(K +
+      + (-1)) * DRF(K)) /(DRF(K) + DRF(K + (-1))))
+             OpenAD_Symbol_188 = (INT(OpenAD_Symbol_188) + INT(1))
+           END DO
+           oad_it(oad_it_ptr) = OpenAD_Symbol_188
+       end subroutine OpenAD_set_ref_state



More information about the Gcc-patches mailing list