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.sandif...@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);
!               }
!           }
!       }
  }

Reply via email to