public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-29 10:48 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-29 10:48 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9d95b1100e822df989c8bd060fb8983eef6d096b

commit 9d95b1100e822df989c8bd060fb8983eef6d096b
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 ++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 161 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  23 ++++++-
 gcc/tree-vectorizer.h     |  36 +++++++++--
 6 files changed, 211 insertions(+), 49 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index bc913eeeb36..e60b9bd718b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b223956e3af..192803eddfb 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3149,7 +3148,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3258,10 +3257,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3288,7 +3288,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3408,7 +3408,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3430,7 +3430,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3443,6 +3443,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3611,7 +3667,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3675,15 +3731,67 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 ==false && dom1 == false)
+			{
+			  gcc_assert (gsi_bb (to_insert) == gsi_bb (insert_before));
+			  gimple_stmt_iterator it = to_insert;
+			  while (!gsi_end_p (it))
+			    {
+			      if (gsi_stmt (it) == gsi_stmt (insert_before))
+				{
+				  insert_before = to_insert;
+				  break;
+				}
+			      gsi_prev (&it);
+			    }
+			}
+		      else if (dom0)
+			insert_before = to_insert;
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3701,14 +3809,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3720,7 +3823,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9b7b04ce2d3..20ca1bd55f7 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..6f11d98e3f1 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -731,6 +740,11 @@ vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
   if (bb1 != bb2)
     return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
 
+  if (s1 == NULL)
+    return false;
+  else if (s2 == NULL)
+    return true;
+
   /* PHIs in the same basic block are assumed to be
      executed all in parallel, if only one stmt is a PHI,
      it dominates the other stmt in the same basic block.  */
@@ -1379,12 +1393,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index d9f6a67264d..8f8373ed382 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,15 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi) && bb->prev_bb != NULL)
+	{
+	  bb = bb->prev_bb;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -869,7 +887,12 @@ public:
   {
     const_reverse_iterator begin = region_end;
     if (*begin == NULL)
-      begin = const_reverse_iterator (gsi_last_bb (region_end.bb));
+      {
+	basic_block bb = gsi_bb (region_end);
+	while (gsi_stmt (gsi_last_bb (bb)) == NULL)
+	  bb = bb->prev_bb;
+	begin = const_reverse_iterator (gsi_last_bb (bb));
+      }
     else
       ++begin;
 
@@ -1893,14 +1916,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -1999,6 +2023,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2020,5 +2045,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-29 11:48 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-29 11:48 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9ba53b9347c7bb8cd089ab42f446b431507e5b18

commit 9ba53b9347c7bb8cd089ab42f446b431507e5b18
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 ++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 161 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  23 ++++++-
 gcc/tree-vectorizer.h     |  36 +++++++++--
 6 files changed, 211 insertions(+), 49 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index bc913eeeb36..e60b9bd718b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b223956e3af..192803eddfb 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3149,7 +3148,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3258,10 +3257,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3288,7 +3288,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3408,7 +3408,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3430,7 +3430,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3443,6 +3443,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3611,7 +3667,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3675,15 +3731,67 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 ==false && dom1 == false)
+			{
+			  gcc_assert (gsi_bb (to_insert) == gsi_bb (insert_before));
+			  gimple_stmt_iterator it = to_insert;
+			  while (!gsi_end_p (it))
+			    {
+			      if (gsi_stmt (it) == gsi_stmt (insert_before))
+				{
+				  insert_before = to_insert;
+				  break;
+				}
+			      gsi_prev (&it);
+			    }
+			}
+		      else if (dom0)
+			insert_before = to_insert;
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3701,14 +3809,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3720,7 +3823,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9b7b04ce2d3..20ca1bd55f7 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..6f11d98e3f1 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -731,6 +740,11 @@ vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
   if (bb1 != bb2)
     return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
 
+  if (s1 == NULL)
+    return false;
+  else if (s2 == NULL)
+    return true;
+
   /* PHIs in the same basic block are assumed to be
      executed all in parallel, if only one stmt is a PHI,
      it dominates the other stmt in the same basic block.  */
@@ -1379,12 +1393,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index c393d7e5fa6..8f8373ed382 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,15 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi) && bb->prev_bb != NULL)
+	{
+	  bb = bb->prev_bb;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -869,7 +887,12 @@ public:
   {
     const_reverse_iterator begin = region_end;
     if (*begin == NULL)
-      begin = const_reverse_iterator (gsi_last_bb (gsi_bb (region_end)));
+      {
+	basic_block bb = gsi_bb (region_end);
+	while (gsi_stmt (gsi_last_bb (bb)) == NULL)
+	  bb = bb->prev_bb;
+	begin = const_reverse_iterator (gsi_last_bb (bb));
+      }
     else
       ++begin;
 
@@ -1893,14 +1916,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -1999,6 +2023,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2020,5 +2045,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-29  9:16 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-29  9:16 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:6dd5e8c2b0e5e5136f709ef4e7263a0e841a3a8e

commit 6dd5e8c2b0e5e5136f709ef4e7263a0e841a3a8e
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 ++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 161 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  23 ++++++-
 gcc/tree-vectorizer.h     |  29 +++++++--
 6 files changed, 205 insertions(+), 48 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index bc913eeeb36..e60b9bd718b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b223956e3af..192803eddfb 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3149,7 +3148,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3258,10 +3257,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3288,7 +3288,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3408,7 +3408,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3430,7 +3430,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3443,6 +3443,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3611,7 +3667,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3675,15 +3731,67 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 ==false && dom1 == false)
+			{
+			  gcc_assert (gsi_bb (to_insert) == gsi_bb (insert_before));
+			  gimple_stmt_iterator it = to_insert;
+			  while (!gsi_end_p (it))
+			    {
+			      if (gsi_stmt (it) == gsi_stmt (insert_before))
+				{
+				  insert_before = to_insert;
+				  break;
+				}
+			      gsi_prev (&it);
+			    }
+			}
+		      else if (dom0)
+			insert_before = to_insert;
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3701,14 +3809,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3720,7 +3823,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9b7b04ce2d3..20ca1bd55f7 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..6f11d98e3f1 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -731,6 +740,11 @@ vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
   if (bb1 != bb2)
     return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
 
+  if (s1 == NULL)
+    return false;
+  else if (s2 == NULL)
+    return true;
+
   /* PHIs in the same basic block are assumed to be
      executed all in parallel, if only one stmt is a PHI,
      it dominates the other stmt in the same basic block.  */
@@ -1379,12 +1393,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index d9f6a67264d..f353b4bbc42 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,15 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi) && bb->prev_bb != NULL)
+	{
+	  bb = bb->prev_bb;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -1893,14 +1911,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -1999,6 +2018,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2020,5 +2040,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-29  8:18 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-29  8:18 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5a4502659ad78251c76d6424cbdfcba39acf1bdf

commit 5a4502659ad78251c76d6424cbdfcba39acf1bdf
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 ++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 161 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  18 +++++-
 gcc/tree-vectorizer.h     |  29 +++++++--
 6 files changed, 200 insertions(+), 48 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index bc913eeeb36..e60b9bd718b 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b223956e3af..192803eddfb 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3149,7 +3148,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3258,10 +3257,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3288,7 +3288,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3408,7 +3408,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3430,7 +3430,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3443,6 +3443,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3611,7 +3667,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3675,15 +3731,67 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 ==false && dom1 == false)
+			{
+			  gcc_assert (gsi_bb (to_insert) == gsi_bb (insert_before));
+			  gimple_stmt_iterator it = to_insert;
+			  while (!gsi_end_p (it))
+			    {
+			      if (gsi_stmt (it) == gsi_stmt (insert_before))
+				{
+				  insert_before = to_insert;
+				  break;
+				}
+			      gsi_prev (&it);
+			    }
+			}
+		      else if (dom0)
+			insert_before = to_insert;
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3701,14 +3809,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3720,7 +3823,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9b7b04ce2d3..20ca1bd55f7 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..7fd5cdf7a8d 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -1379,12 +1388,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index d9f6a67264d..f353b4bbc42 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,15 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi) && bb->prev_bb != NULL)
+	{
+	  bb = bb->prev_bb;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -1893,14 +1911,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -1999,6 +2018,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2020,5 +2040,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-26 10:30 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-26 10:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8a3bfb21d53e706217da5e7d73135a7bb7f86fd8

commit 8a3bfb21d53e706217da5e7d73135a7bb7f86fd8
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 +++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 150 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  18 +++++-
 gcc/tree-vectorizer.h     |  29 +++++++--
 6 files changed, 189 insertions(+), 48 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 08c9f119626..348a7b2e767 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b2792c76ad2..5d16edfbab7 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3158,7 +3157,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3267,10 +3266,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3297,7 +3297,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3417,7 +3417,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3439,7 +3439,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3452,6 +3452,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3620,7 +3676,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3684,15 +3740,56 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 == dom1)
+			; // TODO
+		      else if (dom0)
+			insert_before = to_insert;
+
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3710,14 +3807,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3729,7 +3821,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index edd28534cb0..815c73042c6 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..7fd5cdf7a8d 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -1379,12 +1388,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index e4d132493ca..eaa04b03059 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,15 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi) && bb->prev_bb != NULL)
+	{
+	  bb = bb->prev_bb;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -1893,14 +1911,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -2000,6 +2019,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2021,5 +2041,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-25 16:08 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-25 16:08 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:24f3a28f9f63ee02413b03f02144352fe1691d37

commit 24f3a28f9f63ee02413b03f02144352fe1691d37
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 +++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 150 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  18 +++++-
 gcc/tree-vectorizer.h     |  26 ++++++--
 6 files changed, 186 insertions(+), 48 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 08c9f119626..348a7b2e767 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b2792c76ad2..5d16edfbab7 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3158,7 +3157,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3267,10 +3266,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3297,7 +3297,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3417,7 +3417,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3439,7 +3439,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3452,6 +3452,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3620,7 +3676,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3684,15 +3740,56 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      bool dom0 = vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+							      gsi_bb (insert_before),
+							      gsi_stmt (to_insert),
+							      gsi_bb (to_insert));
+		      bool dom1 = vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							      gsi_bb (to_insert),
+							      gsi_stmt (insert_before),
+							      gsi_bb (insert_before));
+		      if (dom0 == dom1)
+			; // TODO
+		      else if (dom0)
+			insert_before = to_insert;
+
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3710,14 +3807,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3729,7 +3821,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index edd28534cb0..815c73042c6 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..7fd5cdf7a8d 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,16 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -1379,12 +1388,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index e4d132493ca..bb18e7b21ac 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -831,7 +841,12 @@ public:
     const const_reverse_iterator &
     operator++ ()
     {
-      gsi_prev (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_prev (&gsi);
+      while (gsi_end_p (gsi))
+	gsi = gsi_after_labels (bb->prev_bb);
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -1893,14 +1908,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -2000,6 +2016,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2021,5 +2038,6 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread
* [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function.
@ 2020-06-25 14:31 Martin Liska
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Liska @ 2020-06-25 14:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:dbd5fbfdb7754d5137637350a4d38ec6fc361517

commit dbd5fbfdb7754d5137637350a4d38ec6fc361517
Author: Martin Liska <mliska@suse.cz>
Date:   Thu Jun 11 13:25:40 2020 +0200

    SLP: vectorize entire function.

Diff:
---
 gcc/tree-vect-data-refs.c |  30 ++++++---
 gcc/tree-vect-loop.c      |   5 +-
 gcc/tree-vect-slp.c       | 152 +++++++++++++++++++++++++++++++++++++---------
 gcc/tree-vect-stmts.c     |   5 +-
 gcc/tree-vectorizer.c     |  23 +++++--
 gcc/tree-vectorizer.h     |  20 +++++-
 6 files changed, 186 insertions(+), 49 deletions(-)

diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index eb8288e7a85..92ad181addb 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2853,10 +2853,10 @@ dr_group_sort_cmp (const void *dra_, const void *drb_)
     return 0;
 
   /* DRs in different loops never belong to the same group.  */
-  loop_p loopa = gimple_bb (DR_STMT (dra))->loop_father;
-  loop_p loopb = gimple_bb (DR_STMT (drb))->loop_father;
-  if (loopa != loopb)
-    return loopa->num < loopb->num ? -1 : 1;
+  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+  if (bb_index1 != bb_index2)
+    return bb_index1 < bb_index2 ? -1 : 1;
 
   /* Ordering of DRs according to base.  */
   cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2962,7 +2962,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
    FORNOW: handle only arrays and pointer accesses.  */
 
 opt_result
-vect_analyze_data_ref_accesses (vec_info *vinfo)
+vect_analyze_data_ref_accesses (vec_info *vinfo,
+				vec<int> *dataref_groups)
 {
   unsigned int i;
   vec<data_reference_p> datarefs = vinfo->shared->datarefs;
@@ -2984,6 +2985,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
   for (i = 0; i < datarefs_copy.length () - 1;)
     {
       data_reference_p dra = datarefs_copy[i];
+      int dra_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
       dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
       stmt_vec_info stmtinfo_a = dr_info_a->stmt;
       stmt_vec_info lastinfo = NULL;
@@ -2996,6 +2998,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
       for (i = i + 1; i < datarefs_copy.length (); ++i)
 	{
 	  data_reference_p drb = datarefs_copy[i];
+	  int drb_group_id = dataref_groups ? (*dataref_groups)[i] : 0;
 	  dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
 	  stmt_vec_info stmtinfo_b = dr_info_b->stmt;
 	  if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
@@ -3008,10 +3011,14 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
 	     matters we can push those to a worklist and re-iterate
 	     over them.  The we can just skip ahead to the next DR here.  */
 
-	  /* DRs in a different loop should not be put into the same
+	  /* DRs in a different BBs should not be put into the same
 	     interleaving group.  */
-	  if (gimple_bb (DR_STMT (dra))->loop_father
-	      != gimple_bb (DR_STMT (drb))->loop_father)
+	  int bb_index1 = gimple_bb (DR_STMT (dra))->index;
+	  int bb_index2 = gimple_bb (DR_STMT (drb))->index;
+	  if (bb_index1 != bb_index2)
+	    break;
+
+	  if (dra_group_id != drb_group_id)
 	    break;
 
 	  /* Check that the data-refs have same first location (except init)
@@ -4070,7 +4077,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
 
 opt_result
 vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
-			       vec<data_reference_p> *datarefs)
+			       vec<data_reference_p> *datarefs,
+			       vec<int> *dataref_groups, int group_id)
 {
   /* We can ignore clobbers for dataref analysis - they are removed during
      loop vectorization and BB vectorization checks dependences with a
@@ -4197,6 +4205,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
 		      newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
 		      free_data_ref (dr);
 		      datarefs->safe_push (newdr);
+		      if (dataref_groups)
+			dataref_groups->safe_push (group_id);
 		      return opt_result::success ();
 		    }
 		}
@@ -4206,6 +4216,8 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
     }
 
   datarefs->safe_push (dr);
+  if (dataref_groups)
+    dataref_groups->safe_push (group_id);
   return opt_result::success ();
 }
 
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 08c9f119626..348a7b2e767 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1788,7 +1788,8 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
 	if (is_gimple_debug (stmt))
 	  continue;
 	++(*n_stmts);
-	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs);
+	opt_result res = vect_find_stmt_data_reference (loop, stmt, datarefs,
+							NULL, 0);
 	if (!res)
 	  {
 	    if (is_gimple_call (stmt) && loop->safelen)
@@ -2010,7 +2011,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
   /* Analyze the access patterns of the data-refs in the loop (consecutive,
      complex, etc.). FORNOW: Only handle consecutive access pattern.  */
 
-  ok = vect_analyze_data_ref_accesses (loop_vinfo);
+  ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
   if (!ok)
     {
       if (dump_enabled_p ())
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index b2792c76ad2..52f3691dc83 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -2636,8 +2636,6 @@ _bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
 	continue;
       add_stmt (stmt);
     }
-
-  bb->aux = this;
 }
 
 
@@ -3127,7 +3125,8 @@ vect_slp_check_for_constructors (bb_vec_info bb_vinfo)
    region.  */
 
 static bool
-vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+		       vec<int> *dataref_groups)
 {
   DUMP_VECT_SCOPE ("vect_slp_analyze_bb");
 
@@ -3158,7 +3157,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
       return false;
     }
 
-  if (!vect_analyze_data_ref_accesses (bb_vinfo))
+  if (!vect_analyze_data_ref_accesses (bb_vinfo, dataref_groups))
     {
      if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -3267,10 +3266,11 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
    given by DATAREFS.  */
 
 static bool
-vect_slp_bb_region (gimple_stmt_iterator region_begin,
-		    gimple_stmt_iterator region_end,
-		    vec<data_reference_p> datarefs,
-		    unsigned int n_stmts)
+vect_slp_region (gimple_stmt_iterator region_begin,
+		 gimple_stmt_iterator region_end,
+		 vec<data_reference_p> datarefs,
+		 vec<int> *dataref_groups,
+		 unsigned int n_stmts)
 {
   bb_vec_info bb_vinfo;
   auto_vector_modes vector_modes;
@@ -3297,7 +3297,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
 	bb_vinfo->shared->check_datarefs ();
       bb_vinfo->vector_mode = next_vector_mode;
 
-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
+      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups)
 	  && dbg_cnt (vect_slp))
 	{
 	  if (dump_enabled_p ())
@@ -3417,7 +3417,7 @@ vect_slp_bb (basic_block bb)
 	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
 	    vect_location = stmt;
 
-	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs))
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs, NULL, 0))
 	    break;
 	}
       if (gsi_end_p (region_begin))
@@ -3439,7 +3439,7 @@ vect_slp_bb (basic_block bb)
 			     "not vectorized: too many instructions in "
 			     "basic block.\n");
 	}
-      else if (vect_slp_bb_region (region_begin, region_end, datarefs, insns))
+      else if (vect_slp_region (region_begin, region_end, datarefs, NULL, insns))
 	any_vectorized = true;
 
       if (gsi_end_p (region_end))
@@ -3452,6 +3452,62 @@ vect_slp_bb (basic_block bb)
   return any_vectorized;
 }
 
+bool
+vect_slp_function ()
+{
+  basic_block bb;
+  vec_info_shared shared;
+  vec<data_reference_p> datarefs = vNULL;
+  vec<int> dataref_groups = vNULL;
+  bool any_vectorized = false;
+  int insns = 0;
+  gimple_stmt_iterator region_begin
+    = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+  // TODO
+  while (gsi_stmt (region_begin) == NULL)
+    {
+      basic_block next_bb = region_begin.bb->next_bb;
+      if (next_bb == NULL)
+	return false;
+      region_begin = gsi_after_labels (next_bb);
+    }
+
+  gimple_stmt_iterator region_end
+    = gsi_last_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+  if (!gsi_end_p (region_end))
+    gsi_next (&region_end);
+  int current_group = 0;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (gimple_stmt_iterator gsi = gsi_after_labels (bb); !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  gimple *stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    continue;
+
+	  insns++;
+
+	  if (gimple_location (stmt) != UNKNOWN_LOCATION)
+	    vect_location = stmt;
+
+	  if (!vect_find_stmt_data_reference (NULL, stmt, &datarefs,
+					      &dataref_groups, current_group))
+	    ++current_group;
+	}
+
+      ++current_group;
+    }
+
+  if (vect_slp_region (region_begin, region_end, datarefs, &dataref_groups,
+		       insns))
+    any_vectorized = true;
+
+  return any_vectorized;
+}
+
+
 
 /* Build a variable-length vector in which the elements in ELTS are repeated
    to a fill NRESULTS vectors of type VECTOR_TYPE.  Store the vectors in
@@ -3620,7 +3676,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
   constant_p = true;
   tree_vector_builder elts (vector_type, nunits, 1);
   elts.quick_grow (nunits);
-  stmt_vec_info insert_after = NULL;
+  gimple_stmt_iterator insert_before = gsi_none ();
   for (j = 0; j < number_of_copies; j++)
     {
       tree op;
@@ -3684,15 +3740,58 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 	     when a def is inside the analyzed region since we cannot
 	     simply insert at the BB start in this case.  */
 	  stmt_vec_info opdef;
-	  if (TREE_CODE (orig_op) == SSA_NAME
-	      && !SSA_NAME_IS_DEFAULT_DEF (orig_op)
-	      && is_a <bb_vec_info> (vinfo)
-	      && (opdef = vinfo->lookup_def (orig_op)))
+	  if (is_a <bb_vec_info> (vinfo))
 	    {
-	      if (!insert_after)
-		insert_after = opdef;
-	      else
-		insert_after = get_later_stmt (insert_after, opdef);
+	      gimple_stmt_iterator to_insert = gsi_none ();
+	      if (TREE_CODE (orig_op) == SSA_NAME)
+		{
+		  if (SSA_NAME_IS_DEFAULT_DEF (orig_op))
+		    to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+		  else if ((opdef = vinfo->lookup_def (orig_op)))
+		    {
+		      to_insert = gsi_for_stmt (opdef->stmt);
+		      gsi_next (&to_insert);
+		    }
+
+		  else
+		    {
+		      gimple *def = SSA_NAME_DEF_STMT (orig_op);
+		      if (is_a<gphi *> (def))
+			to_insert = gsi_after_labels (gimple_bb (def));
+		      else
+			{
+			  to_insert = gsi_for_stmt (def);
+			  gsi_next (&to_insert);
+			}
+		    }
+		}
+	      else if (CONSTANT_CLASS_P (orig_op)
+		       || TREE_CODE (orig_op) == ADDR_EXPR)
+		to_insert = gsi_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb);
+
+	      if (gsi_bb (to_insert))
+		{
+		  if (gsi_bb (insert_before))
+		    {
+		      if (vect_stmt_dominates_stmt_p (gsi_stmt (insert_before),
+						      gsi_bb (insert_before),
+						      gsi_stmt (to_insert),
+						      gsi_bb (to_insert),
+						      false))
+			insert_before = to_insert;
+		      else if (vect_stmt_dominates_stmt_p (gsi_stmt (to_insert),
+							   gsi_bb (to_insert),
+							   gsi_stmt (insert_before),
+							   gsi_bb (insert_before),
+							   false))
+			;
+		      else
+			gcc_unreachable ();
+
+		    }
+		  else
+		    insert_before = to_insert;
+		}
 	    }
 
           if (number_of_places_left_in_vector == 0)
@@ -3710,14 +3809,9 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  vec_cst = permute_results[number_of_vectors - j - 1];
 		}
 	      tree init;
-	      if (insert_after)
-		{
-		  gimple_stmt_iterator gsi = gsi_for_stmt (insert_after->stmt);
-		  /* vect_init_vector inserts before.  */
-		  gsi_next (&gsi);
-		  init = vect_init_vector (vinfo, NULL, vec_cst,
-					   vector_type, &gsi);
-		}
+	      if (gsi_bb (insert_before))
+		init = vect_init_vector (vinfo, NULL, vec_cst,
+					 vector_type, &insert_before);
 	      else
 		init = vect_init_vector (vinfo, NULL, vec_cst,
 					 vector_type, NULL);
@@ -3729,7 +3823,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node)
 		  ctor_seq = NULL;
 		}
 	      voprnds.quick_push (init);
-	      insert_after = NULL;
+	      insert_before = gsi_none ();
               number_of_places_left_in_vector = nunits;
 	      constant_p = true;
 	      elts.new_vector (vector_type, nunits, 1);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index edd28534cb0..815c73042c6 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1334,8 +1334,9 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
       else
        {
           bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
-	  gimple_stmt_iterator gsi_region_begin = bb_vinfo->region_begin;
-	  gsi_insert_before (&gsi_region_begin, new_stmt, GSI_SAME_STMT);
+	  gimple_stmt_iterator gsi
+	    = gsi_after_labels (gsi_bb (bb_vinfo->region_begin));
+	  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
        }
     }
 
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 78d9da689c8..877d31aa101 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -717,7 +717,17 @@ bool
 vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
 {
   basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+  return vect_stmt_dominates_stmt_p (s1, bb1, s2, bb2, true);
+}
+
+/* Returns true if S1 dominates S2.  Any of S1 and S2 can be null
+  and then basic blocks BB1 and BB2 are compared.  */
 
+bool
+vect_stmt_dominates_stmt_p (gimple *s1, basic_block bb1,
+			    gimple *s2, basic_block bb2,
+			    bool handle_out_of_region)
+{
   /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
      SSA_NAME.  Assume it lives at the beginning of function and
      thus dominates everything.  */
@@ -752,7 +762,7 @@ vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
       if (gsi_stmt (gsi1) == s2)
 	return true;
     }
-  if (gimple_uid (gsi_stmt (gsi1)) == -1u)
+  if (handle_out_of_region && gimple_uid (gsi_stmt (gsi1)) == -1u)
     return false;
 
   gimple_stmt_iterator gsi2 = gsi_for_stmt (s2);
@@ -764,7 +774,7 @@ vect_stmt_dominates_stmt_p (gimple *s1, gimple *s2)
       if (gsi_stmt (gsi2) == s1)
 	return true;
     }
-  if (gimple_uid (gsi_stmt (gsi2)) == -1u)
+  if (handle_out_of_region && gimple_uid (gsi_stmt (gsi2)) == -1u)
     return false;
 
   if (gimple_uid (gsi_stmt (gsi1)) <= gimple_uid (gsi_stmt (gsi2)))
@@ -1379,12 +1389,17 @@ pass_slp_vectorize::execute (function *fun)
 	}
     }
 
-  FOR_EACH_BB_FN (bb, fun)
+  if (vect_slp_function ())
     {
+      // TODO: change to function vectorized
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
+    }
+  else
+    FOR_EACH_BB_FN (bb, fun)
       if (vect_slp_bb (bb))
 	if (dump_enabled_p ())
 	  dump_printf_loc (MSG_NOTE, vect_location, "basic block vectorized\n");
-    }
 
   if (!in_loop_pipeline)
     {
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index e4d132493ca..0638ac1df0a 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -802,7 +802,17 @@ public:
     const const_iterator &
     operator++ ()
     {
-      gsi_next (&gsi); return *this;
+      basic_block bb = gimple_bb (gsi_stmt (gsi));
+      gsi_next (&gsi);
+      while (gsi_end_p (gsi))
+	{
+	  bb = bb->next_bb;
+	  if (bb == NULL)
+	    break;
+	  gsi = gsi_after_labels (bb);
+	}
+
+      return *this;
     }
 
     gimple *operator* () const { return gsi_stmt (gsi); }
@@ -1893,14 +1903,15 @@ extern opt_result vect_analyze_data_refs_alignment (loop_vec_info);
 extern opt_result vect_verify_datarefs_alignment (loop_vec_info);
 extern bool vect_slp_analyze_and_verify_instance_alignment (vec_info *,
 							    slp_instance);
-extern opt_result vect_analyze_data_ref_accesses (vec_info *);
+extern opt_result vect_analyze_data_ref_accesses (vec_info *, vec<int> *);
 extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info);
 extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
 				      tree, int, internal_fn *, tree *);
 extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
 				       gather_scatter_info *);
 extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
-						 vec<data_reference_p> *);
+						 vec<data_reference_p> *,
+						 vec<int> *, int);
 extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
 extern void vect_record_base_alignments (vec_info *);
 extern tree vect_create_data_ref_ptr (vec_info *,
@@ -2000,6 +2011,7 @@ extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
 			       unsigned n = -1U);
 extern bool vect_slp_bb (basic_block);
+extern bool vect_slp_function ();
 extern stmt_vec_info vect_find_last_scalar_stmt_in_slp (slp_tree);
 extern stmt_vec_info vect_find_first_scalar_stmt_in_slp (slp_tree);
 extern bool is_simple_and_all_uses_invariant (stmt_vec_info, loop_vec_info);
@@ -2021,5 +2033,7 @@ unsigned vectorize_loops (void);
 void vect_free_loop_info_assumptions (class loop *);
 gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL);
 bool vect_stmt_dominates_stmt_p (gimple *, gimple *);
+bool vect_stmt_dominates_stmt_p (gimple *, basic_block, gimple *, basic_block,
+				 bool);
 
 #endif  /* GCC_TREE_VECTORIZER_H  */


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-06-29 11:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-29 10:48 [gcc(refs/users/marxin/heads/slp-function-v7)] SLP: vectorize entire function Martin Liska
  -- strict thread matches above, loose matches on Subject: below --
2020-06-29 11:48 Martin Liska
2020-06-29  9:16 Martin Liska
2020-06-29  8:18 Martin Liska
2020-06-26 10:30 Martin Liska
2020-06-25 16:08 Martin Liska
2020-06-25 14:31 Martin Liska

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