This refactors BB vectorization in preparation to make it work
on sub-BB granularity.

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

Richard.

2015-11-03  Richard Biener  <rguent...@suse.de>

        * tree-vect-data-refs.c (vect_analyze_data_refs): Do not collect
        data references here.
        * tree-vect-loop.c: Include cgraph.h.
        (vect_analyze_loop_2): Collect data references here.
        * tree-vect-slp.c (find_bb_location): Inline ...
        (vect_slp_bb): ... here.  Renamed from vect_slp_analyze_bb.
        Factor in vect_slp_transform_bb.
        (vect_slp_transform_bb): Removed.
        (vect_slp_analyze_bb_1): Collect data references here.
        * tree-vectorizer.c (pass_slp_vectorize::execute): Call
        vect_slp_bb.
        * tree-vectorizer.h (vect_slp_bb): Declare.
        (vect_slp_analyze_bb): Remove.
        (vect_slp_transform_bb): Remove.
        (find_bb_location): Remove.
        (vect_analyze_data_refs): Remove stmt count reference parameter.

Index: trunk/gcc/tree-vect-data-refs.c
===================================================================
*** trunk.orig/gcc/tree-vect-data-refs.c        2015-11-03 12:57:31.538588865 
+0100
--- trunk/gcc/tree-vect-data-refs.c     2015-11-03 15:05:51.537766823 +0100
*************** vect_check_gather_scatter (gimple *stmt,
*** 3286,3297 ****
  */
  
  bool
! vect_analyze_data_refs (vec_info *vinfo, int *min_vf, unsigned *n_stmts)
  {
    struct loop *loop = NULL;
-   basic_block bb = NULL;
    unsigned int i;
-   vec<data_reference_p> datarefs;
    struct data_reference *dr;
    tree scalar_type;
  
--- 3286,3295 ----
  */
  
  bool
! vect_analyze_data_refs (vec_info *vinfo, int *min_vf)
  {
    struct loop *loop = NULL;
    unsigned int i;
    struct data_reference *dr;
    tree scalar_type;
  
*************** vect_analyze_data_refs (vec_info *vinfo,
*** 3300,3405 ****
                       "=== vect_analyze_data_refs ===\n");
  
    if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
!     {
!       basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
! 
!       loop = LOOP_VINFO_LOOP (loop_vinfo);
!       datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
!       if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)))
!       {
!         if (dump_enabled_p ())
!           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                            "not vectorized: loop contains function calls"
!                            " or data references that cannot be analyzed\n");
!         return false;
!       }
! 
!       for (i = 0; i < loop->num_nodes; i++)
!       {
!         gimple_stmt_iterator gsi;
! 
!         for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
!           {
!             gimple *stmt = gsi_stmt (gsi);
!             if (is_gimple_debug (stmt))
!               continue;
!             ++*n_stmts;
!             if (!find_data_references_in_stmt (loop, stmt, &datarefs))
!               {
!                 if (is_gimple_call (stmt) && loop->safelen)
!                   {
!                     tree fndecl = gimple_call_fndecl (stmt), op;
!                     if (fndecl != NULL_TREE)
!                       {
!                         struct cgraph_node *node = cgraph_node::get (fndecl);
!                         if (node != NULL && node->simd_clones != NULL)
!                           {
!                             unsigned int j, n = gimple_call_num_args (stmt);
!                             for (j = 0; j < n; j++)
!                               {
!                                 op = gimple_call_arg (stmt, j);
!                                 if (DECL_P (op)
!                                     || (REFERENCE_CLASS_P (op)
!                                         && get_base_address (op)))
!                                   break;
!                               }
!                             op = gimple_call_lhs (stmt);
!                             /* Ignore #pragma omp declare simd functions
!                                if they don't have data references in the
!                                call stmt itself.  */
!                             if (j == n
!                                 && !(op
!                                      && (DECL_P (op)
!                                          || (REFERENCE_CLASS_P (op)
!                                              && get_base_address (op)))))
!                               continue;
!                           }
!                       }
!                   }
!                 LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs;
!                 if (dump_enabled_p ())
!                   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                                    "not vectorized: loop contains function "
!                                    "calls or data references that cannot "
!                                    "be analyzed\n");
!                 return false;
!               }
!           }
!       }
! 
!       LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs;
!     }
!   else
!     {
!       bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
!       gimple_stmt_iterator gsi;
! 
!       bb = BB_VINFO_BB (bb_vinfo);
!       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
!       {
!         gimple *stmt = gsi_stmt (gsi);
!         if (is_gimple_debug (stmt))
!           continue;
!         ++*n_stmts;
!         if (!find_data_references_in_stmt (NULL, stmt,
!                                            &BB_VINFO_DATAREFS (bb_vinfo)))
!           {
!             /* Mark the rest of the basic-block as unvectorizable.  */
!             for (; !gsi_end_p (gsi); gsi_next (&gsi))
!               {
!                 stmt = gsi_stmt (gsi);
!                 STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)) = false;
!               }
!             break;
!           }
!       }
! 
!       datarefs = BB_VINFO_DATAREFS (bb_vinfo);
!     }
  
    /* Go through the data-refs, check that the analysis succeeded.  Update
       pointer from stmt_vec_info struct to DR and vectype.  */
  
    FOR_EACH_VEC_ELT (datarefs, i, dr)
      {
        gimple *stmt;
--- 3298,3309 ----
                       "=== vect_analyze_data_refs ===\n");
  
    if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
!     loop = LOOP_VINFO_LOOP (loop_vinfo);
  
    /* Go through the data-refs, check that the analysis succeeded.  Update
       pointer from stmt_vec_info struct to DR and vectype.  */
  
+   vec<data_reference_p> datarefs = vinfo->datarefs;
    FOR_EACH_VEC_ELT (datarefs, i, dr)
      {
        gimple *stmt;
Index: trunk/gcc/tree-vect-loop.c
===================================================================
*** trunk.orig/gcc/tree-vect-loop.c     2015-11-02 12:37:11.007248642 +0100
--- trunk/gcc/tree-vect-loop.c  2015-11-03 13:48:50.290127748 +0100
*************** along with GCC; see the file COPYING3.
*** 46,51 ****
--- 46,52 ----
  #include "tree-scalar-evolution.h"
  #include "tree-vectorizer.h"
  #include "gimple-fold.h"
+ #include "cgraph.h"
  
  /* Loop Vectorization Pass.
  
*************** vect_analyze_loop_2 (loop_vec_info loop_
*** 1584,1596 ****
    unsigned int n_stmts = 0;
  
    /* Find all data references in the loop (which correspond to vdefs/vuses)
!      and analyze their evolution in the loop.  Also adjust the minimal
!      vectorization factor according to the loads and stores.
  
!      FORNOW: Handle only simple, array references, which
!      alignment can be forced, and aligned pointer-references.  */
  
!   ok = vect_analyze_data_refs (loop_vinfo, &min_vf, &n_stmts);
    if (!ok)
      {
        if (dump_enabled_p ())
--- 1585,1658 ----
    unsigned int n_stmts = 0;
  
    /* Find all data references in the loop (which correspond to vdefs/vuses)
!      and analyze their evolution in the loop.  */
  
!   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
! 
!   loop_p loop = LOOP_VINFO_LOOP (loop_vinfo);
!   if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)))
!     {
!       if (dump_enabled_p ())
!       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                        "not vectorized: loop contains function calls"
!                        " or data references that cannot be analyzed\n");
!       return false;
!     }
! 
!   for (unsigned i = 0; i < loop->num_nodes; i++)
!     for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]);
!        !gsi_end_p (gsi); gsi_next (&gsi))
!       {
!       gimple *stmt = gsi_stmt (gsi);
!       if (is_gimple_debug (stmt))
!         continue;
!       ++n_stmts;
!       if (!find_data_references_in_stmt (loop, stmt,
!                                          &LOOP_VINFO_DATAREFS (loop_vinfo)))
!         {
!           if (is_gimple_call (stmt) && loop->safelen)
!             {
!               tree fndecl = gimple_call_fndecl (stmt), op;
!               if (fndecl != NULL_TREE)
!                 {
!                   cgraph_node *node = cgraph_node::get (fndecl);
!                   if (node != NULL && node->simd_clones != NULL)
!                     {
!                       unsigned int j, n = gimple_call_num_args (stmt);
!                       for (j = 0; j < n; j++)
!                         {
!                           op = gimple_call_arg (stmt, j);
!                           if (DECL_P (op)
!                               || (REFERENCE_CLASS_P (op)
!                                   && get_base_address (op)))
!                             break;
!                         }
!                       op = gimple_call_lhs (stmt);
!                       /* Ignore #pragma omp declare simd functions
!                          if they don't have data references in the
!                          call stmt itself.  */
!                       if (j == n
!                           && !(op
!                                && (DECL_P (op)
!                                    || (REFERENCE_CLASS_P (op)
!                                        && get_base_address (op)))))
!                         continue;
!                     }
!                 }
!             }
!           if (dump_enabled_p ())
!             dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                              "not vectorized: loop contains function "
!                              "calls or data references that cannot "
!                              "be analyzed\n");
!           return false;
!         }
!       }
! 
!   /* Analyze the data references and also adjust the minimal
!      vectorization factor according to the loads and stores.  */
  
!   ok = vect_analyze_data_refs (loop_vinfo, &min_vf);
    if (!ok)
      {
        if (dump_enabled_p ())
Index: trunk/gcc/tree-vect-slp.c
===================================================================
*** trunk.orig/gcc/tree-vect-slp.c      2015-11-03 12:57:31.538588865 +0100
--- trunk/gcc/tree-vect-slp.c   2015-11-03 14:04:53.845935110 +0100
*************** along with GCC; see the file COPYING3.
*** 40,67 ****
  #include "tree-vectorizer.h"
  #include "langhooks.h"
  #include "gimple-walk.h"
! 
! /* Extract the location of the basic block in the source code.
!    Return the basic block location if succeed and NULL if not.  */
! 
! source_location
! find_bb_location (basic_block bb)
! {
!   gimple *stmt = NULL;
!   gimple_stmt_iterator si;
! 
!   if (!bb)
!     return UNKNOWN_LOCATION;
! 
!   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
!     {
!       stmt = gsi_stmt (si);
!       if (gimple_location (stmt) != UNKNOWN_LOCATION)
!         return gimple_location (stmt);
!     }
! 
!   return UNKNOWN_LOCATION;
! }
  
  
  /* Recursively free the memory allocated for the SLP tree rooted at NODE.  */
--- 40,46 ----
  #include "tree-vectorizer.h"
  #include "langhooks.h"
  #include "gimple-walk.h"
! #include "dbgcnt.h"
  
  
  /* Recursively free the memory allocated for the SLP tree rooted at NODE.  */
*************** vect_slp_analyze_bb_1 (basic_block bb)
*** 2361,2367 ****
    if (!bb_vinfo)
      return NULL;
  
!   if (!vect_analyze_data_refs (bb_vinfo, &min_vf, &n_stmts))
      {
        if (dump_enabled_p ())
          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
--- 2340,2370 ----
    if (!bb_vinfo)
      return NULL;
  
!   /* Gather all data references in the basic-block.  */
! 
!   for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
!        !gsi_end_p (gsi); gsi_next (&gsi))
!     {
!       gimple *stmt = gsi_stmt (gsi);
!       if (is_gimple_debug (stmt))
!       continue;
!       ++n_stmts;
!       if (!find_data_references_in_stmt (NULL, stmt,
!                                        &BB_VINFO_DATAREFS (bb_vinfo)))
!       {
!         /* Mark the rest of the basic-block as unvectorizable.  */
!         for (; !gsi_end_p (gsi); gsi_next (&gsi))
!           {
!             stmt = gsi_stmt (gsi);
!             STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)) = false;
!           }
!         break;
!       }
!     }
! 
!   /* Analyze the data references.  */
! 
!   if (!vect_analyze_data_refs (bb_vinfo, &min_vf))
      {
        if (dump_enabled_p ())
          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
*************** vect_slp_analyze_bb_1 (basic_block bb)
*** 2499,2506 ****
  }
  
  
! bb_vec_info
! vect_slp_analyze_bb (basic_block bb)
  {
    bb_vec_info bb_vinfo;
    int insns = 0;
--- 2502,2512 ----
  }
  
  
! /* Main entry for the BB vectorizer.  Analyze and transform BB, returns
!    true if anything in the basic-block was vectorized.  */
! 
! bool
! vect_slp_bb (basic_block bb)
  {
    bb_vec_info bb_vinfo;
    int insns = 0;
*************** vect_slp_analyze_bb (basic_block bb)
*** 2517,2522 ****
--- 2523,2530 ----
            && !gimple_nop_p (stmt)
            && gimple_code (stmt) != GIMPLE_LABEL)
          insns++;
+       if (gimple_location (stmt) != UNKNOWN_LOCATION)
+       vect_location = gimple_location (stmt);
      }
  
    if (insns > PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB))
*************** vect_slp_analyze_bb (basic_block bb)
*** 2526,2532 ****
                         "not vectorized: too many instructions in "
                         "basic block.\n");
  
!       return NULL;
      }
  
    /* Autodetect first vector size we try.  */
--- 2534,2540 ----
                         "not vectorized: too many instructions in "
                         "basic block.\n");
  
!       return false;
      }
  
    /* Autodetect first vector size we try.  */
*************** vect_slp_analyze_bb (basic_block bb)
*** 2537,2550 ****
      {
        bb_vinfo = vect_slp_analyze_bb_1 (bb);
        if (bb_vinfo)
!         return bb_vinfo;
  
        destroy_bb_vec_info (bb_vinfo);
  
        vector_sizes &= ~current_vector_size;
        if (vector_sizes == 0
            || current_vector_size == 0)
!         return NULL;
  
        /* Try the next biggest vector size.  */
        current_vector_size = 1 << floor_log2 (vector_sizes);
--- 2545,2577 ----
      {
        bb_vinfo = vect_slp_analyze_bb_1 (bb);
        if (bb_vinfo)
!       {
!         if (!dbg_cnt (vect_slp))
!           {
!             destroy_bb_vec_info (bb_vinfo);
!             return false;
!           }
! 
!         if (dump_enabled_p ())
!           dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB\n");
! 
!         vect_schedule_slp (bb_vinfo);
! 
!         if (dump_enabled_p ())
!           dump_printf_loc (MSG_NOTE, vect_location,
!                            "BASIC BLOCK VECTORIZED\n");
! 
!         destroy_bb_vec_info (bb_vinfo);
! 
!         return true;
!       }
  
        destroy_bb_vec_info (bb_vinfo);
  
        vector_sizes &= ~current_vector_size;
        if (vector_sizes == 0
            || current_vector_size == 0)
!         return false;
  
        /* Try the next biggest vector size.  */
        current_vector_size = 1 << floor_log2 (vector_sizes);
*************** vect_schedule_slp (vec_info *vinfo)
*** 3533,3580 ****
  
    return is_store;
  }
- 
- 
- /* Vectorize the basic block.  */
- 
- void
- vect_slp_transform_bb (basic_block bb)
- {
-   bb_vec_info bb_vinfo = vec_info_for_bb (bb);
-   gimple_stmt_iterator si;
- 
-   gcc_assert (bb_vinfo);
- 
-   if (dump_enabled_p ())
-     dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB\n");
- 
-   for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
-     {
-       gimple *stmt = gsi_stmt (si);
-       stmt_vec_info stmt_info;
- 
-       if (dump_enabled_p ())
-         {
-           dump_printf_loc (MSG_NOTE, vect_location,
-                            "------>SLPing statement: ");
-           dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
-           dump_printf (MSG_NOTE, "\n");
-         }
- 
-       stmt_info = vinfo_for_stmt (stmt);
-       gcc_assert (stmt_info);
- 
-       /* Schedule all the SLP instances when the first SLP stmt is reached.  
*/
-       if (STMT_SLP_TYPE (stmt_info))
-         {
-           vect_schedule_slp (bb_vinfo);
-           break;
-         }
-     }
- 
-   if (dump_enabled_p ())
-     dump_printf_loc (MSG_NOTE, vect_location,
-                    "BASIC BLOCK VECTORIZED\n");
- 
-   destroy_bb_vec_info (bb_vinfo);
- }
--- 3560,3562 ----
Index: trunk/gcc/tree-vectorizer.c
===================================================================
*** trunk.orig/gcc/tree-vectorizer.c    2015-11-02 12:37:10.986248408 +0100
--- trunk/gcc/tree-vectorizer.c 2015-11-03 14:03:39.794106576 +0100
*************** pass_slp_vectorize::execute (function *f
*** 696,713 ****
  
    FOR_EACH_BB_FN (bb, fun)
      {
!       vect_location = find_bb_location (bb);
! 
!       if (vect_slp_analyze_bb (bb))
!         {
!           if (!dbg_cnt (vect_slp))
!             break;
! 
!           vect_slp_transform_bb (bb);
!           if (dump_enabled_p ())
!             dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
!                            "basic block vectorized\n");
!         }
      }
  
    free_stmt_vec_info_vec ();
--- 696,704 ----
  
    FOR_EACH_BB_FN (bb, fun)
      {
!       if (vect_slp_bb (bb))
!       dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
!                        "basic block vectorized\n");
      }
  
    free_stmt_vec_info_vec ();
Index: trunk/gcc/tree-vectorizer.h
===================================================================
*** trunk.orig/gcc/tree-vectorizer.h    2015-11-03 12:57:31.538588865 +0100
--- trunk/gcc/tree-vectorizer.h 2015-11-03 14:33:42.315259421 +0100
*************** extern bool vect_analyze_data_ref_access
*** 1010,1016 ****
  extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
  extern tree vect_check_gather_scatter (gimple *, loop_vec_info, tree *, tree 
*,
                                       int *);
! extern bool vect_analyze_data_refs (vec_info *, int *, unsigned *);
  extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
                                      tree *, gimple_stmt_iterator *,
                                      gimple **, bool, bool *,
--- 1010,1016 ----
  extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
  extern tree vect_check_gather_scatter (gimple *, loop_vec_info, tree *, tree 
*,
                                       int *);
! extern bool vect_analyze_data_refs (vec_info *, int *);
  extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
                                      tree *, gimple_stmt_iterator *,
                                      gimple **, bool, bool *,
*************** extern bool vect_make_slp_decision (loop
*** 1072,1081 ****
  extern void vect_detect_hybrid_slp (loop_vec_info);
  extern void vect_get_slp_defs (vec<tree> , slp_tree,
                               vec<vec<tree> > *, int);
! 
! extern source_location find_bb_location (basic_block);
! extern bb_vec_info vect_slp_analyze_bb (basic_block);
! extern void vect_slp_transform_bb (basic_block);
  
  /* In tree-vect-patterns.c.  */
  /* Pattern recognition functions.
--- 1072,1078 ----
  extern void vect_detect_hybrid_slp (loop_vec_info);
  extern void vect_get_slp_defs (vec<tree> , slp_tree,
                               vec<vec<tree> > *, int);
! extern bool vect_slp_bb (basic_block);
  
  /* In tree-vect-patterns.c.  */
  /* Pattern recognition functions.

Reply via email to