This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[11/11] Insert pattern statements into vec_basic_blocks


The point of this patch is to put pattern statements in the same
vec_basic_block as the statements they replace, with the pattern
statements for S coming between S and S's original predecessor.
This removes the need to handle them specially in various places.


2018-07-30  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* tree-vectorizer.h (vec_basic_block): Expand comment.
	(_stmt_vec_info::pattern_def_seq): Delete.
	(STMT_VINFO_PATTERN_DEF_SEQ): Likewise.
	(is_main_pattern_stmt_p): New function.
	* tree-vect-loop.c (vect_determine_vf_for_stmt_1): Rename to...
	(vect_determine_vf_for_stmt): ...this, deleting the original
	function with this name.  Remove vectype_maybe_set_p argument
	and test is_pattern_stmt_p instead.  Retain the "examining..."
	message from the previous vect_determine_vf_for_stmt.
	(vect_compute_single_scalar_iteration_cost, vect_update_vf_for_slp)
	(vect_analyze_loop_2): Don't treat pattern statements specially.
	(vect_transform_loop): Likewise.  Use vect_orig_stmt to find the
	insertion point.
	* tree-vect-slp.c (vect_detect_hybrid_slp): Expect pattern statements
	to be in the statement list, without needing to follow
	STMT_VINFO_RELATED_STMT.  Remove PATTERN_DEF_SEQ handling.
	* tree-vect-stmts.c (vect_analyze_stmt): Don't handle pattern
	statements specially.
	(vect_remove_dead_scalar_stmts): Ignore pattern statements.
	* tree-vect-patterns.c (vect_set_pattern_stmt): Insert the pattern
	statement into the vec_basic_block immediately before the statement
	it replaces.
	(append_pattern_def_seq): Likewise.  If the original statement is
	itself a pattern statement, associate the new one with the original
	statement.
	(vect_split_statement): Use append_pattern_def_seq to insert the
	first pattern statement.
	(vect_recog_vector_vector_shift_pattern): Remove mention of
	STMT_VINFO_PATTERN_DEF_SEQ.
	(adjust_bool_stmts): Get the last pattern statement from the
	stmt_vec_info chain.
	(vect_mark_pattern_stmts): Rename to...
	(vect_replace_stmt_with_pattern): ...this.  Remove the
	PATTERN_DEF_SEQ handling and process only the pattern statement given.
	Use append_pattern_def_seq when replacing a pattern statement with
	another pattern statement, and use vec_basic_block::remove instead
	of gsi_remove to remove the old one.
	(vect_pattern_recog_1): Update accordingly.  Remove PATTERN_DEF_SEQ
	handling.  On failure, remove any half-formed pattern sequence from
	the vec_basic_block.  Install the vector type in pattern statements
	that don't yet have one.
	(vect_pattern_recog): Iterate over statements that are added
	by previous recognizers, but skipping those that have already
	been replaced, or the main pattern statement in such a replacement.

Index: gcc/tree-vectorizer.h
===================================================================
*** gcc/tree-vectorizer.h	2018-07-30 12:32:46.658356275 +0100
--- gcc/tree-vectorizer.h	2018-07-30 12:32:49.898327734 +0100
*************** #define SLP_TREE_TWO_OPERATORS(S)		 (S)-
*** 172,178 ****
  #define SLP_TREE_DEF_TYPE(S)			 (S)->def_type
  
  /* Information about the phis and statements in a block that we're trying
!    to vectorize, in their original order.  */
  class vec_basic_block
  {
  public:
--- 172,184 ----
  #define SLP_TREE_DEF_TYPE(S)			 (S)->def_type
  
  /* Information about the phis and statements in a block that we're trying
!    to vectorize.  This includes the phis and statements that were in the
!    original scalar code, in their original order.  It also includes any
!    pattern statements that the vectorizer has created to replace some
!    of the scalar ones.  Such pattern statements come immediately before
!    the statement that they replace; that is, all pattern statements P for
!    which vect_orig_stmt (P) == S form a sequence that comes immediately
!    before S.  */
  class vec_basic_block
  {
  public:
*************** struct _stmt_vec_info {
*** 870,880 ****
          pattern).  */
    stmt_vec_info related_stmt;
  
-   /* Used to keep a sequence of def stmts of a pattern stmt if such exists.
-      The sequence is attached to the original statement rather than the
-      pattern statement.  */
-   gimple_seq pattern_def_seq;
- 
    /* List of datarefs that are known to have the same alignment as the dataref
       of this stmt.  */
    vec<dr_p> same_align_refs;
--- 876,881 ----
*************** #define STMT_VINFO_DR_INFO(S) \
*** 1048,1054 ****
  
  #define STMT_VINFO_IN_PATTERN_P(S)         (S)->in_pattern_p
  #define STMT_VINFO_RELATED_STMT(S)         (S)->related_stmt
- #define STMT_VINFO_PATTERN_DEF_SEQ(S)      (S)->pattern_def_seq
  #define STMT_VINFO_SAME_ALIGN_REFS(S)      (S)->same_align_refs
  #define STMT_VINFO_SIMD_CLONE_INFO(S)	   (S)->simd_clone_info
  #define STMT_VINFO_DEF_TYPE(S)             (S)->def_type
--- 1049,1054 ----
*************** is_pattern_stmt_p (stmt_vec_info stmt_in
*** 1176,1181 ****
--- 1176,1192 ----
    return stmt_info->pattern_stmt_p;
  }
  
+ /* Return TRUE if a statement represented by STMT_INFO is the final
+    statement in a pattern.  */
+ 
+ static inline bool
+ is_main_pattern_stmt_p (stmt_vec_info stmt_info)
+ {
+   stmt_vec_info orig_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
+   return (is_pattern_stmt_p (stmt_info)
+ 	  && STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt_info);
+ }
+ 
  /* If STMT_INFO is a pattern statement, return the statement that it
     replaces, otherwise return STMT_INFO itself.  */
  
Index: gcc/tree-vect-loop.c
===================================================================
*** gcc/tree-vect-loop.c	2018-07-30 12:32:46.654356310 +0100
--- gcc/tree-vect-loop.c	2018-07-30 12:32:49.894327770 +0100
*************** Software Foundation; either version 3, o
*** 155,172 ****
  
  static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *);
  
! /* Subroutine of vect_determine_vf_for_stmt that handles only one
!    statement.  VECTYPE_MAYBE_SET_P is true if STMT_VINFO_VECTYPE
!    may already be set for general statements (not just data refs).  */
  
  static bool
! vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
! 			      bool vectype_maybe_set_p,
! 			      poly_uint64 *vf,
! 			      vec<stmt_vec_info > *mask_producers)
  {
    gimple *stmt = stmt_info->stmt;
  
    if ((!STMT_VINFO_RELEVANT_P (stmt_info)
         && !STMT_VINFO_LIVE_P (stmt_info))
        || gimple_clobber_p (stmt))
--- 155,178 ----
  
  static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *);
  
! /* Subroutine of vect_determine_vectorization_factor.  Set the vector
!    type of STMT_INFO and update the vectorization factor VF accordingly.
!    If the statement produces a mask result whose vector type can only be
!    calculated later, add it to MASK_PRODUCERS.  Return true on success
!    or false if something prevented vectorization.  */
  
  static bool
! vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
! 			    vec<stmt_vec_info > *mask_producers)
  {
    gimple *stmt = stmt_info->stmt;
  
+   if (dump_enabled_p ())
+     {
+       dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
+       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
+     }
+ 
    if ((!STMT_VINFO_RELEVANT_P (stmt_info)
         && !STMT_VINFO_LIVE_P (stmt_info))
        || gimple_clobber_p (stmt))
*************** vect_determine_vf_for_stmt_1 (stmt_vec_i
*** 188,194 ****
  	   that contain a data ref, or for "pattern-stmts" (stmts generated
  	   by the vectorizer to represent/replace a certain idiom).  */
  	gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
! 		     || vectype_maybe_set_p)
  		    && STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
        else if (stmt_vectype == boolean_type_node)
  	mask_producers->safe_push (stmt_info);
--- 194,200 ----
  	   that contain a data ref, or for "pattern-stmts" (stmts generated
  	   by the vectorizer to represent/replace a certain idiom).  */
  	gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
! 		     || is_pattern_stmt_p (stmt_info))
  		    && STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
        else if (stmt_vectype == boolean_type_node)
  	mask_producers->safe_push (stmt_info);
*************** vect_determine_vf_for_stmt_1 (stmt_vec_i
*** 202,263 ****
    return true;
  }
  
- /* Subroutine of vect_determine_vectorization_factor.  Set the vector
-    types of STMT_INFO and all attached pattern statements and update
-    the vectorization factor VF accordingly.  If some of the statements
-    produce a mask result whose vector type can only be calculated later,
-    add them to MASK_PRODUCERS.  Return true on success or false if
-    something prevented vectorization.  */
- 
- static bool
- vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
- 			    vec<stmt_vec_info > *mask_producers)
- {
-   vec_info *vinfo = stmt_info->vinfo;
-   if (dump_enabled_p ())
-     {
-       dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: ");
-       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
-     }
-   if (!vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers))
-     return false;
- 
-   if (STMT_VINFO_IN_PATTERN_P (stmt_info)
-       && STMT_VINFO_RELATED_STMT (stmt_info))
-     {
-       gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
-       stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
- 
-       /* If a pattern statement has def stmts, analyze them too.  */
-       for (gimple_stmt_iterator si = gsi_start (pattern_def_seq);
- 	   !gsi_end_p (si); gsi_next (&si))
- 	{
- 	  stmt_vec_info def_stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
- 	  if (dump_enabled_p ())
- 	    {
- 	      dump_printf_loc (MSG_NOTE, vect_location,
- 			       "==> examining pattern def stmt: ");
- 	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- 				def_stmt_info->stmt, 0);
- 	    }
- 	  if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true,
- 					     vf, mask_producers))
- 	    return false;
- 	}
- 
-       if (dump_enabled_p ())
- 	{
- 	  dump_printf_loc (MSG_NOTE, vect_location,
- 			   "==> examining pattern statement: ");
- 	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
- 	}
-       if (!vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers))
- 	return false;
-     }
- 
-   return true;
- }
- 
  /* Function vect_determine_vectorization_factor
  
     Determine the vectorization factor (VF).  VF is the number of data elements
--- 208,213 ----
*************** vect_compute_single_scalar_iteration_cos
*** 1078,1086 ****
            /* Skip stmts that are not vectorized inside the loop.  */
            if (stmt_info
                && !STMT_VINFO_RELEVANT_P (stmt_info)
!               && (!STMT_VINFO_LIVE_P (stmt_info)
!                   || !VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
! 	      && !STMT_VINFO_IN_PATTERN_P (stmt_info))
              continue;
  
  	  vect_cost_for_stmt kind;
--- 1028,1035 ----
            /* Skip stmts that are not vectorized inside the loop.  */
            if (stmt_info
                && !STMT_VINFO_RELEVANT_P (stmt_info)
! 	      && (!VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))
! 		  || !STMT_VINFO_LIVE_P (stmt_info)))
              continue;
  
  	  vect_cost_for_stmt kind;
*************** vect_update_vf_for_slp (loop_vec_info lo
*** 1394,1407 ****
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       {
! 	stmt_vec_info final_info = vect_stmt_to_vectorize (stmt_info);
! 	if ((STMT_VINFO_RELEVANT_P (final_info)
! 	     || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (final_info)))
! 	    && !PURE_SLP_STMT (final_info))
! 	  /* STMT needs both SLP and loop-based vectorization.  */
! 	  only_slp_in_loop = false;
!       }
  
    if (only_slp_in_loop)
      {
--- 1343,1353 ----
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       if ((STMT_VINFO_RELEVANT_P (stmt_info)
! 	   || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
! 	  && !PURE_SLP_STMT (stmt_info))
! 	/* STMT needs both SLP and loop-based vectorization.  */
! 	only_slp_in_loop = false;
  
    if (only_slp_in_loop)
      {
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 2164,2181 ****
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       {
! 	STMT_SLP_TYPE (stmt_info) = loop_vect;
! 	if (STMT_VINFO_IN_PATTERN_P (stmt_info))
! 	  {
! 	    gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
! 	    STMT_SLP_TYPE (STMT_VINFO_RELATED_STMT (stmt_info)) = loop_vect;
! 	    for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq);
! 		 !gsi_end_p (pi); gsi_next (&pi))
! 	      STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi)))
! 		= loop_vect;
! 	  }
!       }
  
    /* Free optimized alias test DDRS.  */
    LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).truncate (0);
--- 2110,2116 ----
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       STMT_SLP_TYPE (stmt_info) = loop_vect;
  
    /* Free optimized alias test DDRS.  */
    LOOP_VINFO_LOWER_BOUNDS (loop_vinfo).truncate (0);
*************** vect_transform_loop (loop_vec_info loop_
*** 8371,8392 ****
  	    loop_vinfo->remove_stmt (stmt_info);
  	  else
  	    {
! 	      gimple_stmt_iterator si = gsi_for_stmt (stmt_info->stmt);
! 	      if (STMT_VINFO_IN_PATTERN_P (stmt_info))
! 		{
! 		  gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
! 		  for (gimple_stmt_iterator subsi = gsi_start (def_seq);
! 		       !gsi_end_p (subsi); gsi_next (&subsi))
! 		    {
! 		      stmt_vec_info pat_stmt_info
! 			= loop_vinfo->lookup_stmt (gsi_stmt (subsi));
! 		      vect_transform_loop_stmt (loop_vinfo, pat_stmt_info,
! 						&si);
! 		    }
! 		  stmt_vec_info pat_stmt_info
! 		    = STMT_VINFO_RELATED_STMT (stmt_info);
! 		  vect_transform_loop_stmt (loop_vinfo, pat_stmt_info, &si);
! 		}
  	      vect_transform_loop_stmt (loop_vinfo, stmt_info, &si);
  	    }
  	}
--- 8306,8313 ----
  	    loop_vinfo->remove_stmt (stmt_info);
  	  else
  	    {
! 	      stmt_vec_info place = vect_orig_stmt (stmt_info);
! 	      gimple_stmt_iterator si = gsi_for_stmt (place->stmt);
  	      vect_transform_loop_stmt (loop_vinfo, stmt_info, &si);
  	    }
  	}
Index: gcc/tree-vect-slp.c
===================================================================
*** gcc/tree-vect-slp.c	2018-07-30 12:32:46.654356310 +0100
--- gcc/tree-vect-slp.c	2018-07-30 12:32:49.894327770 +0100
*************** vect_detect_hybrid_slp (loop_vec_info lo
*** 2411,2428 ****
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       if (STMT_VINFO_IN_PATTERN_P (stmt_info))
  	{
  	  walk_stmt_info wi;
  	  memset (&wi, 0, sizeof (wi));
  	  wi.info = loop_vinfo;
! 	  gimple_stmt_iterator gsi2
! 	    = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)->stmt);
! 	  walk_gimple_stmt (&gsi2, vect_detect_hybrid_slp_2,
  			    vect_detect_hybrid_slp_1, &wi);
- 	  walk_gimple_seq (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
- 			   vect_detect_hybrid_slp_2,
- 			   vect_detect_hybrid_slp_1, &wi);
  	}
  
    /* Then walk the SLP instance trees marking stmts with uses in
--- 2411,2424 ----
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (loop_vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       if (is_pattern_stmt_p (stmt_info))
  	{
  	  walk_stmt_info wi;
  	  memset (&wi, 0, sizeof (wi));
  	  wi.info = loop_vinfo;
! 	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt_info->stmt);
! 	  walk_gimple_stmt (&gsi, vect_detect_hybrid_slp_2,
  			    vect_detect_hybrid_slp_1, &wi);
  	}
  
    /* Then walk the SLP instance trees marking stmts with uses in
Index: gcc/tree-vect-stmts.c
===================================================================
*** gcc/tree-vect-stmts.c	2018-07-30 12:32:46.658356275 +0100
--- gcc/tree-vect-stmts.c	2018-07-30 12:32:49.898327734 +0100
*************** vect_analyze_stmt (stmt_vec_info stmt_in
*** 9384,9394 ****
  		   slp_tree node, slp_instance node_instance,
  		   stmt_vector_for_cost *cost_vec)
  {
-   vec_info *vinfo = stmt_info->vinfo;
    bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
    enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
    bool ok;
-   gimple_seq pattern_def_seq;
  
    if (dump_enabled_p ())
      {
--- 9384,9392 ----
*************** vect_analyze_stmt (stmt_vec_info stmt_in
*** 9405,9498 ****
        return false;
      }
  
-   if (STMT_VINFO_IN_PATTERN_P (stmt_info)
-       && node == NULL
-       && (pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info)))
-     {
-       gimple_stmt_iterator si;
- 
-       for (si = gsi_start (pattern_def_seq); !gsi_end_p (si); gsi_next (&si))
- 	{
- 	  stmt_vec_info pattern_def_stmt_info
- 	    = vinfo->lookup_stmt (gsi_stmt (si));
- 	  if (STMT_VINFO_RELEVANT_P (pattern_def_stmt_info)
- 	      || STMT_VINFO_LIVE_P (pattern_def_stmt_info))
- 	    {
- 	      /* Analyze def stmt of STMT if it's a pattern stmt.  */
- 	      if (dump_enabled_p ())
- 		{
- 		  dump_printf_loc (MSG_NOTE, vect_location,
- 				   "==> examining pattern def statement: ");
- 		  dump_gimple_stmt (MSG_NOTE, TDF_SLIM,
- 				    pattern_def_stmt_info->stmt, 0);
- 		}
- 
- 	      if (!vect_analyze_stmt (pattern_def_stmt_info,
- 				      need_to_vectorize, node, node_instance,
- 				      cost_vec))
- 		return false;
- 	    }
- 	}
-     }
- 
    /* Skip stmts that do not need to be vectorized. In loops this is expected
       to include:
       - the COND_EXPR which is the loop exit condition
       - any LABEL_EXPRs in the loop
       - computations that are used only for array indexing or loop control.
       In basic blocks we only analyze statements that are a part of some SLP
!      instance, therefore, all the statements are relevant.
! 
!      Pattern statement needs to be analyzed instead of the original statement
!      if the original statement is not relevant.  Otherwise, we analyze both
!      statements.  In basic blocks we are called from some SLP instance
!      traversal, don't analyze pattern stmts instead, the pattern stmts
!      already will be part of SLP instance.  */
  
-   stmt_vec_info pattern_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
    if (!STMT_VINFO_RELEVANT_P (stmt_info)
        && !STMT_VINFO_LIVE_P (stmt_info))
      {
-       if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- 	  && pattern_stmt_info
- 	  && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
- 	      || STMT_VINFO_LIVE_P (pattern_stmt_info)))
-         {
-           /* Analyze PATTERN_STMT instead of the original stmt.  */
- 	  stmt_info = pattern_stmt_info;
-           if (dump_enabled_p ())
-             {
-               dump_printf_loc (MSG_NOTE, vect_location,
-                                "==> examining pattern statement: ");
- 	      dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0);
-             }
-         }
-       else
-         {
-           if (dump_enabled_p ())
-             dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n");
- 
-           return true;
-         }
-     }
-   else if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- 	   && node == NULL
- 	   && pattern_stmt_info
- 	   && (STMT_VINFO_RELEVANT_P (pattern_stmt_info)
- 	       || STMT_VINFO_LIVE_P (pattern_stmt_info)))
-     {
-       /* Analyze PATTERN_STMT too.  */
        if (dump_enabled_p ())
!         {
!           dump_printf_loc (MSG_NOTE, vect_location,
!                            "==> examining pattern statement: ");
! 	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt_info->stmt, 0);
!         }
! 
!       if (!vect_analyze_stmt (pattern_stmt_info, need_to_vectorize, node,
! 			      node_instance, cost_vec))
!         return false;
!    }
  
    switch (STMT_VINFO_DEF_TYPE (stmt_info))
      {
--- 9403,9423 ----
        return false;
      }
  
    /* Skip stmts that do not need to be vectorized. In loops this is expected
       to include:
       - the COND_EXPR which is the loop exit condition
       - any LABEL_EXPRs in the loop
       - computations that are used only for array indexing or loop control.
       In basic blocks we only analyze statements that are a part of some SLP
!      instance, therefore, all the statements are relevant.  */
  
    if (!STMT_VINFO_RELEVANT_P (stmt_info)
        && !STMT_VINFO_LIVE_P (stmt_info))
      {
        if (dump_enabled_p ())
! 	dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n");
!       return true;
!     }
  
    switch (STMT_VINFO_DEF_TYPE (stmt_info))
      {
*************** vect_remove_dead_scalar_stmts (vec_info
*** 10915,10921 ****
  	   stmt_info = prev_stmt_info)
  	{
  	  prev_stmt_info = stmt_info->prev;
! 	  vect_maybe_remove_scalar_stmt (stmt_info);
  	}
      }
  }
--- 10840,10847 ----
  	   stmt_info = prev_stmt_info)
  	{
  	  prev_stmt_info = stmt_info->prev;
! 	  if (!is_pattern_stmt_p (stmt_info))
! 	    vect_maybe_remove_scalar_stmt (stmt_info);
  	}
      }
  }
Index: gcc/tree-vect-patterns.c
===================================================================
*** gcc/tree-vect-patterns.c	2018-07-30 12:32:42.786390386 +0100
--- gcc/tree-vect-patterns.c	2018-07-30 12:32:49.894327770 +0100
*************** vect_init_pattern_stmt (gimple *pattern_
*** 125,151 ****
  vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
  		       tree vectype)
  {
!   STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
!   STMT_VINFO_RELATED_STMT (orig_stmt_info)
      = vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
  }
  
! /* Add NEW_STMT to STMT_INFO's pattern definition statements.  If VECTYPE
!    is nonnull, record that NEW_STMT's vector type is VECTYPE, which might
!    be different from the vector type of the final pattern statement.  */
  
  static inline void
  append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
  			tree vectype = NULL_TREE)
  {
!   vec_info *vinfo = stmt_info->vinfo;
!   if (vectype)
!     {
!       stmt_vec_info new_stmt_info = vinfo->add_stmt (new_stmt);
!       STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
!     }
!   gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
! 				      new_stmt);
  }
  
  /* The caller wants to perform new operations on vect_external variable
--- 125,150 ----
  vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
  		       tree vectype)
  {
!   stmt_vec_info pattern_stmt_info
      = vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, vectype);
+   orig_stmt_info->block->add_before (pattern_stmt_info, orig_stmt_info);
+   STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
+   STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt_info;
  }
  
! /* Add NEW_STMT to the pattern statements that replace STMT_INFO.
!    If VECTYPE is nonnull, record that NEW_STMT's vector type is VECTYPE,
!    which might be different from the vector type of the final pattern
!    statement.  */
  
  static inline void
  append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
  			tree vectype = NULL_TREE)
  {
!   stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info);
!   stmt_vec_info new_stmt_info
!     = vect_init_pattern_stmt (new_stmt, orig_stmt_info, vectype);
!   stmt_info->block->add_before (new_stmt_info, stmt_info);
  }
  
  /* The caller wants to perform new operations on vect_external variable
*************** vect_split_statement (stmt_vec_info stmt
*** 633,643 ****
  {
    if (is_pattern_stmt_p (stmt2_info))
      {
-       /* STMT2_INFO is part of a pattern.  Get the statement to which
- 	 the pattern is attached.  */
-       stmt_vec_info orig_stmt2_info = STMT_VINFO_RELATED_STMT (stmt2_info);
-       vect_init_pattern_stmt (stmt1, orig_stmt2_info, vectype);
- 
        if (dump_enabled_p ())
  	{
  	  dump_printf_loc (MSG_NOTE, vect_location,
--- 632,637 ----
*************** vect_split_statement (stmt_vec_info stmt
*** 645,650 ****
--- 639,647 ----
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
  	}
  
+       /* Insert STMT1_INFO before STMT2_INFO.  */
+       append_pattern_def_seq (stmt2_info, stmt1, vectype);
+ 
        /* Since STMT2_INFO is a pattern statement, we can change it
  	 in-situ without worrying about changing the code for the
  	 containing block.  */
*************** vect_split_statement (stmt_vec_info stmt
*** 658,675 ****
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
  	}
  
-       gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt2_info);
-       if (STMT_VINFO_RELATED_STMT (orig_stmt2_info) == stmt2_info)
- 	/* STMT2_INFO is the actual pattern statement.  Add STMT1
- 	   to the end of the definition sequence.  */
- 	gimple_seq_add_stmt_without_update (def_seq, stmt1);
-       else
- 	{
- 	  /* STMT2_INFO belongs to the definition sequence.  Insert STMT1
- 	     before it.  */
- 	  gimple_stmt_iterator gsi = gsi_for_stmt (stmt2_info->stmt, def_seq);
- 	  gsi_insert_before_without_update (&gsi, stmt1, GSI_SAME_STMT);
- 	}
        return true;
      }
    else
--- 655,660 ----
*************** vect_split_statement (stmt_vec_info stmt
*** 689,698 ****
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
  	}
  
!       /* Add STMT1 as a singleton pattern definition sequence.  */
!       gimple_seq *def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (stmt2_info);
!       vect_init_pattern_stmt (stmt1, stmt2_info, vectype);
!       gimple_seq_add_stmt_without_update (def_seq, stmt1);
  
        /* Build the second of the two pattern statements.  */
        tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL);
--- 674,681 ----
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt2_info->stmt, 0);
  	}
  
!       /* Insert STMT1_INFO before STMT2_INFO.  */
!       append_pattern_def_seq (stmt2_info, stmt1, vectype);
  
        /* Build the second of the two pattern statements.  */
        tree new_lhs = vect_recog_temp_ssa_var (lhs_type, NULL);
*************** vect_recog_rotate_pattern (stmt_vec_info
*** 2164,2170 ****
      i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
      with a shift/rotate which has same type on both operands, in the
      second case just b_T op c_T, in the first case with added cast
!     from a_t to c_T in STMT_VINFO_PATTERN_DEF_SEQ.
  
    Output:
  
--- 2147,2153 ----
      i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
      with a shift/rotate which has same type on both operands, in the
      second case just b_T op c_T, in the first case with added cast
!     from a_t to c_T beforehand.
  
    Output:
  
*************** adjust_bool_stmts (hash_set <gimple *> &
*** 3518,3526 ****
      adjust_bool_pattern (gimple_assign_lhs (bool_stmts[i]),
  			 out_type, stmt_info, defs);
  
!   /* Pop the last pattern seq stmt and install it as pattern root for STMT.  */
!   gimple *pattern_stmt
!     = gimple_seq_last_stmt (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
    return gimple_assign_lhs (pattern_stmt);
  }
  
--- 3501,3508 ----
      adjust_bool_pattern (gimple_assign_lhs (bool_stmts[i]),
  			 out_type, stmt_info, defs);
  
!   /* Return the result of the last statement we emitted.  */
!   gimple *pattern_stmt = stmt_info->prev->stmt;
    return gimple_assign_lhs (pattern_stmt);
  }
  
*************** static vect_recog_func vect_vect_recog_f
*** 4676,4689 ****
  
  const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
  
! /* Mark statements that are involved in a pattern.  */
  
  static inline void
! vect_mark_pattern_stmts (stmt_vec_info orig_stmt_info, gimple *pattern_stmt,
!                          tree pattern_vectype)
  {
-   gimple *def_seq = STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
- 
    gimple *orig_pattern_stmt = NULL;
    if (is_pattern_stmt_p (orig_stmt_info))
      {
--- 4658,4671 ----
  
  const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
  
! /* Replace ORIG_STMT_INFO with PATTERN_STMT, using PATTERN_VECTYPE as
!    the vector type for PATTERN_STMT.  */
  
  static inline void
! vect_replace_stmt_with_pattern (stmt_vec_info orig_stmt_info,
! 				gimple *pattern_stmt,
! 				tree pattern_vectype)
  {
    gimple *orig_pattern_stmt = NULL;
    if (is_pattern_stmt_p (orig_stmt_info))
      {
*************** vect_mark_pattern_stmts (stmt_vec_info o
*** 4710,4741 ****
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
  	}
  
-       /* Switch to the statement that ORIG replaces.  */
-       orig_stmt_info = STMT_VINFO_RELATED_STMT (orig_stmt_info);
- 
        /* We shouldn't be replacing the main pattern statement.  */
!       gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info)->stmt
! 		  != orig_pattern_stmt);
!     }
  
!   if (def_seq)
!     for (gimple_stmt_iterator si = gsi_start (def_seq);
! 	 !gsi_end_p (si); gsi_next (&si))
!       vect_init_pattern_stmt (gsi_stmt (si), orig_stmt_info, pattern_vectype);
! 
!   if (orig_pattern_stmt)
!     {
!       vect_init_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
! 
!       /* Insert all the new pattern statements before the original one.  */
!       gimple_seq *orig_def_seq = &STMT_VINFO_PATTERN_DEF_SEQ (orig_stmt_info);
!       gimple_stmt_iterator gsi = gsi_for_stmt (orig_pattern_stmt,
! 					       orig_def_seq);
!       gsi_insert_seq_before_without_update (&gsi, def_seq, GSI_SAME_STMT);
!       gsi_insert_before_without_update (&gsi, pattern_stmt, GSI_SAME_STMT);
  
        /* Remove the pattern statement that this new pattern replaces.  */
!       gsi_remove (&gsi, false);
      }
    else
      vect_set_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
--- 4692,4705 ----
  	  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
  	}
  
        /* We shouldn't be replacing the main pattern statement.  */
!       gcc_assert (!is_main_pattern_stmt_p (orig_stmt_info));
  
!       /* Insert the new pattern statement before the original one.  */
!       append_pattern_def_seq (orig_stmt_info, pattern_stmt, pattern_vectype);
  
        /* Remove the pattern statement that this new pattern replaces.  */
!       orig_stmt_info->block->remove (orig_stmt_info);
      }
    else
      vect_set_pattern_stmt (pattern_stmt, orig_stmt_info, pattern_vectype);
*************** vect_mark_pattern_stmts (stmt_vec_info o
*** 4762,4791 ****
  static void
  vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info)
  {
-   vec_info *vinfo = stmt_info->vinfo;
    gimple *pattern_stmt;
    loop_vec_info loop_vinfo;
    tree pattern_vectype;
  
!   /* If this statement has already been replaced with pattern statements,
!      leave the original statement alone, since the first match wins.
!      Instead try to match against the definition statements that feed
!      the main pattern statement.  */
!   if (STMT_VINFO_IN_PATTERN_P (stmt_info))
!     {
!       gimple_stmt_iterator gsi;
!       for (gsi = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
! 	   !gsi_end_p (gsi); gsi_next (&gsi))
! 	vect_pattern_recog_1 (recog_func, vinfo->lookup_stmt (gsi_stmt (gsi)));
!       return;
!     }
! 
!   gcc_assert (!STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
    pattern_stmt = recog_func->fn (stmt_info, &pattern_vectype);
    if (!pattern_stmt)
      {
!       /* Clear any half-formed pattern definition sequence.  */
!       STMT_VINFO_PATTERN_DEF_SEQ (stmt_info) = NULL;
        return;
      }
  
--- 4726,4742 ----
  static void
  vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info)
  {
    gimple *pattern_stmt;
    loop_vec_info loop_vinfo;
    tree pattern_vectype;
  
!   stmt_vec_info prev_stmt_info = stmt_info->prev;
    pattern_stmt = recog_func->fn (stmt_info, &pattern_vectype);
    if (!pattern_stmt)
      {
!       /* Delete any half-formed pattern sequence.  */
!       while (stmt_info->prev != prev_stmt_info)
! 	stmt_info->block->remove (prev_stmt_info);
        return;
      }
  
*************** vect_pattern_recog_1 (vect_recog_func *r
*** 4800,4807 ****
        dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
      }
  
    /* Mark the stmts that are involved in the pattern. */
!   vect_mark_pattern_stmts (stmt_info, pattern_stmt, pattern_vectype);
  
    /* Patterns cannot be vectorized using SLP, because they change the order of
       computation.  */
--- 4751,4765 ----
        dump_gimple_stmt (MSG_NOTE, TDF_SLIM, pattern_stmt, 0);
      }
  
+   /* Install the vector type in pattern definition statements that
+      don't yet have one.  */
+   for (stmt_vec_info pat_stmt_info = stmt_info->prev;
+        pat_stmt_info != prev_stmt_info; pat_stmt_info = pat_stmt_info->prev)
+     if (!STMT_VINFO_VECTYPE (pat_stmt_info))
+       STMT_VINFO_VECTYPE (pat_stmt_info) = pattern_vectype;
+ 
    /* Mark the stmts that are involved in the pattern. */
!   vect_replace_stmt_with_pattern (stmt_info, pattern_stmt, pattern_vectype);
  
    /* Patterns cannot be vectorized using SLP, because they change the order of
       computation.  */
*************** vect_pattern_recog (vec_info *vinfo)
*** 4903,4910 ****
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       if (STMT_VINFO_VECTORIZABLE (stmt_info))
! 	/* Scan over all generic vect_recog_xxx_pattern functions.  */
! 	for (unsigned int j = 0; j < NUM_PATTERNS; j++)
! 	  vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j], stmt_info);
  }
--- 4861,4887 ----
    vec_basic_block *vec_bb;
    FOR_EACH_VEC_ELT (vinfo->blocks, i, vec_bb)
      FOR_EACH_VEC_BB_STMT (vec_bb, stmt_info)
!       {
! 	stmt_vec_info begin_prev = stmt_info->prev;
! 	if (STMT_VINFO_VECTORIZABLE (stmt_info))
! 	  /* Scan over all generic vect_recog_xxx_pattern functions.  */
! 	  for (unsigned int j = 0; j < NUM_PATTERNS; j++)
! 	    {
! 	      stmt_vec_info curr_prev;
! 	      /* Scan over STMT_INFO and any pattern definition statements
! 		 that were introduced by previous recognizers.  */
! 	      for (stmt_vec_info curr_info = stmt_info;
! 		   curr_info != begin_prev; curr_info = curr_prev)
! 		{
! 		  curr_prev = curr_info->prev;
! 		  /* The first match wins, so skip statements that have
! 		     already been replaced, and the final statement with
! 		     which they were replaced.  */
! 		  if (!STMT_VINFO_IN_PATTERN_P (curr_info)
! 		      && !is_main_pattern_stmt_p (curr_info))
! 		    vect_pattern_recog_1 (&vect_vect_recog_func_ptrs[j],
! 					  curr_info);
! 		}
! 	    }
!       }
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]