public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Tamar Christina <Tamar.Christina@arm.com>
To: Richard Biener <rguenther@suse.de>,
	Richard Sandiford <Richard.Sandiford@arm.com>
Cc: nd <nd@arm.com>, "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: RE: [PATCH v2 3/16]middle-end Add basic SLP pattern matching scaffolding.
Date: Tue, 3 Nov 2020 15:06:28 +0000	[thread overview]
Message-ID: <VI1PR08MB53250748BBC032014BB94CF0FF110@VI1PR08MB5325.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <nycvar.YFH.7.76.2009291134300.10073@p653.nepu.fhfr.qr>

[-- Attachment #1: Type: text/plain, Size: 5196 bytes --]

Hi Richi,

This is a respin which includes the changes you requested.

Thanks,
Tamar

gcc/ChangeLog:

	* Makefile.in (tree-vect-slp-patterns.o): New.
	* doc/passes.texi: Update documentation.
	* tree-vect-slp.c (vect_print_slp_tree): Add new state.
	(vect_match_slp_patterns_2, vect_match_slp_patterns): New.
	(vect_analyze_slp): Call pattern matcher.
	* tree-vectorizer.h (enum _complex_operation):
	(class vect_pattern_match, class vect_pattern): New.
	* tree-vect-slp-patterns.c: New file.

> -----Original Message-----
> From: rguenther@c653.arch.suse.de <rguenther@c653.arch.suse.de> On
> Behalf Of Richard Biener
> Sent: Tuesday, September 29, 2020 10:42 AM
> To: Richard Sandiford <Richard.Sandiford@arm.com>
> Cc: Tamar Christina <Tamar.Christina@arm.com>; nd <nd@arm.com>; gcc-
> patches@gcc.gnu.org
> Subject: Re: [PATCH v2 3/16]middle-end Add basic SLP pattern matching
> scaffolding.
> 
> On Tue, 29 Sep 2020, Richard Sandiford wrote:
> 
> > Richard Biener <rguenther@suse.de> writes:
> > >> > > @@ -2192,6 +2378,17 @@ vect_analyze_slp_instance (vec_info
> *vinfo,
> > >> > >                               &tree_size, bst_map);
> > >> > >    if (node != NULL)
> > >> > >      {
> > >> > > +      /* Temporarily allow add_stmt calls again.  */
> > >> > > +      vinfo->stmt_vec_info_ro = false;
> > >> > > +
> > >> > > +      /* See if any patterns can be found in the constructed SLP tree
> > >> > > +        before we do any analysis on it.  */
> > >> > > +      vect_match_slp_patterns (node, vinfo, group_size,
> &max_nunits,
> > >> > > +                              matches, &npermutes, &tree_size,
> > >> > > + bst_map);
> > >> > > +
> > >> > > +      /* After this no more add_stmt calls are allowed.  */
> > >> > > +      vinfo->stmt_vec_info_ro = true;
> > >> > > +
> > >> > >
> > >> > > I think this is a bit early to match patterns - I'd defer it to
> > >> > > the point where all entries into the same SLP subgraph are
> > >> > > analyzed, thus somewhere at the end of vect_analyze_slp loop
> > >> > > over all instances and match patterns?  That way phases are more
> clearly separated.
> > >> >
> > >> > That would probably work, my only worry is that the SLP analysis
> > >> > itself may fail and bail out at
> > >> >
> > >> > 	  /* If the loads and stores can be handled with load/store-lane
> > >> > 	     instructions do not generate this SLP instance.  */
> > >> > 	  if (is_a <loop_vec_info> (vinfo)
> > >> > 	      && loads_permuted
> > >> > 	      && dr && vect_store_lanes_supported (vectype, group_size,
> > >> > false))
> > >
> > > Ah, that piece of code.  Yeah, I'm repeatedly running into it as
> > > well - it's a bad hack that stands in the way all the time :/
> >
> > At one point I was wondering about trying to drop the above, vectorise
> > with and without SLP, and then compare their costs, like for
> VECT_COMPARE_COSTS.
> > But that seemed like a dead end with the move to doing everything on
> > the SLP representation.
> 
> Yeah ... though even moving everything to the SLP representation will retain
> the issue since there it will be N group-size 1 SLP instances vs. 1 group-size N
> SLP instance.
> 
> > > I guess we should try moving this upward like to
> > > vect_analyze_loop_2 right before
> > >
> > >   /* Check the SLP opportunities in the loop, analyze and build SLP trees.
> > > */
> > >   ok = vect_analyze_slp (loop_vinfo, *n_stmts);
> > >   if (!ok)
> > >     return ok;
> > >
> > > and there check whether all grouped loads and stores can be handled
> > > with store-/load-lanes (and there are no SLP reduction chains?) in
> > > which case do not try to attempt SLP at all.  Because the testcases
> > > this check was supposed to change were all-load/store-lane or all
> > > SLP so the mixed case is probably not worth special casing.
> > >
> > > Since load-/store-lanes is an arm speciality I tried to only touch
> > > this fragile part with a ten-foot pole ;)  CCing Richard, if he acks
> > > the above I can produce a patch.
> >
> > Yeah, sounds good to me.  Probably also sorth checking whether the
> > likely_max iteration count is high enough to support group_size
> > vectors, if we have enough information to guess that.
> >
> > We could also get the gen* machinery to emit a macro that is true if
> > at least one load/store-lane pattern is defined, so that we can skip
> > the code for non-Arm targets.  I can do that as a follow-up.
> 
> I've had a second look and one complication is that we only elide the SLP
> node if any of the loads are permuted.  So if all loads/stores are unpermuted
> but load/store-lanes would work we'd keep the SLP node.
> 
> Of course without actually building the SLP node we don't know whether the
> loads will be permuted or not ...
> 
> But surely the current place for the check will cause some testcases to
> become hybrid vectorizations which is likely undesirable.
> 
> So we could move the check after all SLP discovery is completed and throw it
> all away if we can and should use load/store-lanes?
> But that might then not solve Tamars issue.
> 
> Richard.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: pr13507.patch --]
[-- Type: text/x-diff; name="pr13507.patch", Size: 21972 bytes --]

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 978a08f7b04bea7e7c41f841dc24b773c1adcfe2..885f15c0d3866a1db749d799caffddfe8a390e0b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1645,6 +1645,7 @@ OBJS = \
 	tree-vect-loop.o \
 	tree-vect-loop-manip.o \
 	tree-vect-slp.o \
+	tree-vect-slp-patterns.o \
 	tree-vectorizer.o \
 	tree-vector-builder.o \
 	tree-vrp.o \
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index a5ae4143a8c1293e674b499120372ee5fe5c412b..c86df5cd843084a5b7933ef99a23386891a7b0c1 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -709,7 +709,8 @@ loop.
 The pass is implemented in @file{tree-vectorizer.c} (the main driver),
 @file{tree-vect-loop.c} and @file{tree-vect-loop-manip.c} (loop specific parts
 and general loop utilities), @file{tree-vect-slp} (loop-aware SLP
-functionality), @file{tree-vect-stmts.c} and @file{tree-vect-data-refs.c}.
+functionality), @file{tree-vect-stmts.c}, @file{tree-vect-data-refs.c} and
+@file{tree-vect-slp-patterns.c} containing the SLP pattern matcher.
 Analysis of data references is in @file{tree-data-ref.c}.
 
 SLP Vectorization.  This pass performs vectorization of straight-line code. The
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
new file mode 100644
index 0000000000000000000000000000000000000000..b81cd6856ad4db5a0cda48ca214389f007e060da
--- /dev/null
+++ b/gcc/tree-vect-slp-patterns.c
@@ -0,0 +1,293 @@
+/* SLP - Pattern matcher on SLP trees
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "optabs-tree.h"
+#include "insn-config.h"
+#include "recog.h"		/* FIXME: for insn_data */
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "gimple-iterator.h"
+#include "cfgloop.h"
+#include "tree-vectorizer.h"
+#include "langhooks.h"
+#include "gimple-walk.h"
+#include "dbgcnt.h"
+#include "tree-vector-builder.h"
+#include "vec-perm-indices.h"
+#include "gimple-fold.h"
+#include "internal-fn.h"
+
+/* SLP Pattern matching mechanism.
+
+  This extension to the SLP vectorizer allows one to transform the generated SLP
+  tree based on any pattern.  The difference between this and the normal vect
+  pattern matcher is that unlike the former, this matcher allows you to match
+  with instructions that do not belong to the same SSA dominator graph.
+
+  The only requirement that this pattern matcher has is that you are only
+  only allowed to either match an entire group or none.
+
+  As an example, the following simple loop:
+
+    double a[restrict N]; double b[restrict N]; double c[restrict N];
+
+    for (int i=0; i < N; i+=2)
+    {
+      c[i] = a[i] - b[i+1];
+      c[i+1] = a[i+1] + b[i];
+    }
+
+  which represents a complex addition on with a rotation of 90* around the
+  argand plane. i.e. if `a` and `b` were complex numbers then this would be the
+  same as `a + (b * I)`.
+
+  Here the expressions for `c[i]` and `c[i+1]` are independent but have to be
+  both recognized in order for the pattern to work.  As an SLP tree this is
+  represented as
+
+                +--------------------------------+
+                |       stmt 0 *_9 = _10;        |
+                |       stmt 1 *_15 = _16;       |
+                +--------------------------------+
+                                |
+                                |
+                                v
+                +--------------------------------+
+                |     stmt 0 _10 = _4 - _8;      |
+                |    stmt 1 _16 = _12 + _14;     |
+                | lane permutation { 0[0] 1[1] } |
+                +--------------------------------+
+                            |        |
+                            |        |
+                            |        |
+               +-----+      |        |      +-----+
+               |     |      |        |      |     |
+         +-----| { } |<-----+        +----->| { } --------+
+         |     |     |   +------------------|     |       |
+         |     +-----+   |                  +-----+       |
+         |        |      |                                |
+         |        |      |                                |
+         |        +------|------------------+             |
+         |               |                  |             |
+         v               v                  v             v
+     +--------------------------+     +--------------------------------+
+     |     stmt 0 _8 = *_7;     |     |        stmt 0 _4 = *_3;        |
+     |    stmt 1 _14 = *_13;    |     |       stmt 1 _12 = *_11;       |
+     | load permutation { 1 0 } |     |    load permutation { 0 1 }    |
+     +--------------------------+     +--------------------------------+
+
+  The pattern matcher allows you to replace both statements 0 and 1 or none at
+  all.  You are also allowed to replace and match on any number of nodes.
+
+  The pattern matcher matches on the representative statement for the SLP node.
+  In the case of two_operators it allows you to match the children of the node.
+  This is done using the method `matches ()`.
+
+  If the pattern can be applied a VecPatternMatch is returned which contains all
+  state information on where the match was found.  This is stored in a list of
+  operations to perform.  If the match cannot be applied then the current
+  pattern is aborted and no changes made to the tree.
+
+  The pattern matcher has two modes:
+
+  1) First in post-order traversal is used to perform a check to see if the
+     pattern can be applied or not. If the pattern can be applied then a second
+     step is performed that allows the pattern to rewrite it's children.  This
+     step is required because the application of a pattern can change the layout
+     of the tree which affects the nodes that are still to be matched.  This is
+     performed using `validate_p ()`.
+
+  2) Also in post-order traversal actually perform the rewriting of the
+     matches found earlier.  This is done by calling `build ()` on all matches
+     that were found earlier.
+
+  The pattern matcher currently only allows you to perform replacements to
+  internal functions.
+
+  Once the patterns are matched it is one way, these cannot be undone.  It is
+  currently not supported to match patterns recursively.
+
+  To add a new pattern, implement the vect_pattern class and add the type to
+  slp_patterns.  */
+
+/*******************************************************************************
+ * Simple vector pattern matcher
+ ******************************************************************************/
+
+/* vect_simple_pattern_match holds contextual information about a single match
+   found in the SLP tree.  The use of the class is to allow you to defer
+   performing any modifications to the SLP tree until they are to be done.  By
+   calling build () the modifications are done in-place as to allow also re-
+   writing of the root node.  */
+
+class vect_simple_pattern_match : public vect_pattern_match
+{
+  protected:
+    uint8_t m_arity;
+    internal_fn m_ifn;
+    vec_info *m_vinfo;
+    int m_num_args;
+    vec<slp_tree> *m_nodes;
+
+  public:
+    vect_simple_pattern_match (uint8_t, internal_fn, vec_info *,
+			       vec<slp_tree> *, int);
+    gcall *build ();
+
+    uint8_t get_arity ()
+    {
+      return this->m_arity;
+    }
+
+    internal_fn get_IFN ()
+    {
+      return this->m_ifn;
+    }
+};
+
+vect_simple_pattern_match::vect_simple_pattern_match (uint8_t arity,
+						      internal_fn ifn,
+						      vec_info *vinfo,
+						      vec<slp_tree> *nodes,
+						      int num_args)
+{
+  /* Number of statements the pattern matches against.  */
+  this->m_arity = arity;
+
+  /* The IFN to create the new statements with.  */
+  this->m_ifn = ifn;
+
+  /* The vectorization information for the current loop.  */
+  this->m_vinfo = vinfo;
+
+  /* The number of arguments required to create the new IFN.  */
+  this->m_num_args = num_args;
+
+  /* The node that contains the statement that is being replaced.  */
+  this->m_nodes = nodes;
+}
+
+/* Create a replacement pattern statement for STMT_INFO and inserts the new
+   statement into NODE.  The statement is created as call to internal
+   function IFN with arguments ARGS.  The arity of IFN needs to match the
+   amount of elements in ARGS.  The scalar type of the statement as TYPE and
+   the corresponding vector type VECTYPE.  These two types are used to
+   construct the new vector only replacement pattern statement.
+
+   Futhermore the new pattern is also added to the vectorization information
+   structure VINFO and the old statement STMT_INFO is marked as unused while
+   the new statement is marked as used and the number of SLP uses of the new
+   statement is incremented.
+
+   The newly created SLP nodes are marked as SLP only and will be dissolved
+   if SLP is aborted.
+
+   The newly created gimple call is returned and the BB remains unchanged.
+*/
+
+gcall *
+vect_simple_pattern_match::build ()
+{
+  stmt_vec_info stmt_info;
+
+  auto_vec<tree> args;
+  args.create (this->m_num_args);
+  args.quick_grow_cleared (this->m_num_args);
+  slp_tree node;
+  unsigned ix;
+  stmt_vec_info call_stmt_info;
+  gcall *call_stmt = NULL;
+
+  FOR_EACH_VEC_ELT (*this->m_nodes, ix, node)
+    {
+      /* Calculate the location of the statement in NODE to replace.  */
+      stmt_info = SLP_TREE_REPRESENTATIVE (node);
+      gimple* old_stmt = STMT_VINFO_STMT (stmt_info);
+      tree type = gimple_expr_type (old_stmt);
+
+      /* Create the argument set for use by gimple_build_call_internal_vec.  */
+      for (int i = 0; i < this->m_num_args; i++)
+	{
+	  tree var = make_temp_ssa_name (type, old_stmt, "_pa");
+	  args[i] = var;
+	}
+
+      /* Create the new pattern statements.  */
+      call_stmt = gimple_build_call_internal_vec (this->m_ifn, args);
+      tree var = make_temp_ssa_name (type, call_stmt, "slp_patt");
+      gimple_call_set_lhs (call_stmt, var);
+      gimple_set_location (call_stmt, gimple_location (old_stmt));
+      gimple_call_set_nothrow (call_stmt, true);
+
+      /* Adjust the book-keeping for the new and old statements for use during
+	 SLP.  This is required to get the right VF and statement during SLP
+	 analysis.  These changes are created after relevancy has been set for
+	 the nodes as such we need to manually update them.  Any changes will be
+	 undone if SLP is cancelled.  */
+      call_stmt_info
+	= this->m_vinfo->add_pattern_stmt (call_stmt, stmt_info);
+      STMT_SLP_TYPE (call_stmt_info) = pure_slp;
+      vect_mark_pattern_stmts (this->m_vinfo, stmt_info, call_stmt,
+			       SLP_TREE_VECTYPE (node));
+
+      /* We have to explicitly mark the old statement as unused because during
+	 statement analysis the original and new pattern statement may require
+	 different level of unrolling.  As an example add/sub when vectorized
+	 without a pattern requires 4 copies, whereas with a COMPLEX_ADD pattern
+	 this only requires 2 copies and the two statement will be treated as
+	 hand unrolled.  That means that the analysis won't happen as it'll find
+	 a mismatch.  So we don't analyze the old statement and if we end up
+	 needing it, e.g. SLP fails then we have to quickly re-analyze it.  */
+      STMT_VINFO_RELEVANT (call_stmt_info) = vect_used_in_scope;
+      STMT_VINFO_SLP_VECT_ONLY (call_stmt_info) = true;
+
+      /* Since we are replacing all the statements in the group with the same
+	 thing it doesn't really matter.  So just set it every time a new stmt
+	 is created.  */
+      SLP_TREE_REPRESENTATIVE (node) = call_stmt_info;
+      SLP_TREE_CODE (node) = CALL_EXPR;
+    }
+  return call_stmt;
+}
+
+/*******************************************************************************
+ * Pattern matching definitions
+ ******************************************************************************/
+
+#define SLP_PATTERN(x) &x::create
+vect_pattern_decl_t slp_patterns[]
+{
+  /* For least amount of back-tracking and more efficient matching
+     order patterns from the largest to the smallest.  Especially if they
+     overlap in what they can detect.  */
+
+};
+#undef SLP_PATTERN
+
+size_t num__slp_patterns = sizeof(slp_patterns)/sizeof(vect_pattern_decl_t);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 30036ec84c74a0e428cc661eacf565224047f9e0..c03fc2fbecad1a2219504ac9daae75495e691775 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1929,6 +1929,13 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc,
 	dump_printf (dump_kind, " %u", j);
       dump_printf (dump_kind, " }\n");
     }
+  if (SLP_TREE_REPRESENTATIVE (node)
+      && STMT_VINFO_SLP_VECT_ONLY (SLP_TREE_REPRESENTATIVE (node)))
+    {
+      dump_printf_loc (metadata, user_loc, "\tSLP Only pattern:\n");
+      dump_printf_loc (dump_kind, user_loc, "\t %G",
+		       STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (node)));
+    }
   if (SLP_TREE_LANE_PERMUTATION (node).exists ())
     {
       dump_printf_loc (metadata, user_loc, "\tlane permutation {");
@@ -2181,6 +2188,147 @@ enum slp_instance_kind {
     slp_inst_kind_ctor
 };
 
+/* Helper function of vect_match_slp_patterns.
+
+   Attempts to match the given pattern PATT_INFO against the slp tree rooted in
+   NODE using VINFO.
+
+   If matching is successful the value in NODE is updated and returned, if not
+   then it is returned unchanged.  */
+
+static bool
+vect_match_slp_patterns_2 (slp_tree *ref_node, vec_info *vinfo,
+			   vect_pattern_decl_t patt_fn, hash_set<slp_tree> *visited)
+{
+  unsigned i;
+  slp_tree node = *ref_node;
+  bool found_p = false, found_rec_p = false;
+  if (!node || visited->contains (node))
+    return false;
+
+  /* Perform recursive matching, it's important to do this after matching things
+     in the current node as the matches here may re-order the nodes below it.
+     As such the pattern that needs to be subsequently match may change.  */
+
+  if (SLP_TREE_CHILDREN (node).exists ()) {
+    slp_tree child;
+    FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+      found_rec_p |= vect_match_slp_patterns_2 (&SLP_TREE_CHILDREN (node)[i],
+						vinfo, patt_fn, visited);
+  }
+
+  vect_pattern *pattern = patt_fn (ref_node, vinfo);
+
+  if (pattern->matches ())
+    {
+      tree vectype = SLP_TREE_VECTYPE (node);
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location,
+			 "Found %s pattern in SLP tree\n",
+			 pattern->get_name ());
+
+      if (pattern->is_optab_supported_p (vectype, OPTIMIZE_FOR_SPEED))
+	{
+	  if (dump_enabled_p ())
+	    dump_printf_loc (MSG_NOTE, vect_location,
+			     "Target supports %s vectorization with mode %T\n",
+			     internal_fn_name (pattern->get_ifn ()), vectype);
+
+	  found_p = true;
+	}
+      else
+	{
+	  if (dump_enabled_p ())
+	    {
+	      if (!vectype)
+		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+				 "Target does not support vector type for %T\n",
+				 SLP_TREE_DEF_TYPE (node));
+	      else
+		dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+				 "Target does not support %s for vector type "
+				 "%T\n", internal_fn_name (pattern->get_ifn ()),
+				 vectype);
+	    }
+          found_p = false;
+	}
+    }
+
+  if (found_p)
+    {
+      /* Find which nodes should be the children of the new node.  */
+      if (!pattern->validate_p ())
+	{
+	  if (dump_enabled_p ())
+	    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+			     "transformation for %s not valid due to post "
+			     "condition\n",
+			     internal_fn_name (pattern->get_ifn ()));
+	  found_p = false;
+	}
+    }
+
+  if (found_p)
+    {
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "Creating vec patterns\n");
+
+      gcall* call_stmt = pattern->build ();
+      if (dump_enabled_p ())
+	dump_printf_loc (MSG_NOTE, vect_location, "\t %p stmt: %G",
+			 node, call_stmt);
+    }
+
+  delete pattern;
+  return found_p | found_rec_p;
+}
+
+/* Applies pattern matching to the given SLP tree rooted in REF_NODE using
+   vec_info VINFO.
+
+   The modified tree is returned.  Patterns are tried in order and multiple
+   patterns may match.  */
+
+static bool
+vect_match_slp_patterns (slp_tree *ref_node, vec_info *vinfo)
+{
+  DUMP_VECT_SCOPE ("vect_match_slp_patterns");
+  bool found_p = false;
+
+  if (dump_enabled_p ())
+    {
+      dump_printf_loc (MSG_NOTE, vect_location, "-- before patt match --\n");
+      vect_print_slp_graph (MSG_NOTE, vect_location, *ref_node);
+      dump_printf_loc (MSG_NOTE, vect_location, "-- end patt --\n");
+    }
+
+  hash_set<slp_tree> *visited = new hash_set<slp_tree> ();
+  for (unsigned x = 0; x < num__slp_patterns; x++)
+    {
+      visited->empty ();
+      found_p |= vect_match_slp_patterns_2 (ref_node, vinfo, slp_patterns[x],
+					    visited);
+    }
+
+  delete visited;
+
+  /* TODO: Remove in final version, only here for generating debug dot graphs
+	   from SLP tree.  */
+
+  if (dump_enabled_p ())
+    {
+      dump_printf_loc (MSG_NOTE, vect_location, "-- start dot --\n");
+      vect_print_slp_graph (MSG_NOTE, vect_location, *ref_node);
+      dump_printf_loc (MSG_NOTE, vect_location, "-- end dot --\n");
+    }
+
+  return found_p;
+}
+
+/* Analyze an SLP instance starting from a group of grouped stores.  Call
+   vect_build_slp_tree to build a tree of packed stmts if possible.
+   Return FALSE if it's impossible to SLP any stmt in the loop.  */
+
 static bool
 vect_analyze_slp_instance (vec_info *vinfo,
 			   scalar_stmts_to_slp_tree_map_t *bst_map,
@@ -2661,6 +2809,10 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size)
 				   max_tree_size);
     }
 
+  /* See if any patterns can be found in the SLP tree.  */
+  FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (vinfo), i, instance)
+    vect_match_slp_patterns (&SLP_INSTANCE_TREE (instance), vinfo);
+
   /* The map keeps a reference on SLP nodes built, release that.  */
   for (scalar_stmts_to_slp_tree_map_t::iterator it = bst_map->begin ();
        it != bst_map->end (); ++it)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 4bd454cfb185d7036843fc7140b073f525b2ec6a..b813508d3ceaf4c54f612bc10f9aa42ffe0ce0dd 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -27,6 +27,7 @@ typedef class _stmt_vec_info *stmt_vec_info;
 #include "tree-hash-traits.h"
 #include "target.h"
 #include "alloc-pool.h"
+#include "internal-fn.h"
 
 
 /* Used for naming of new temporaries.  */
@@ -1995,4 +1996,86 @@ 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 *);
 
+/* SLP Pattern matcher types, tree-vect-slp-patterns.c.  */
+
+enum _complex_operation : unsigned;
+
+class vect_pattern_match
+{
+  public:
+    virtual gcall *build () = 0;
+    virtual internal_fn get_IFN () = 0;
+    virtual uint8_t get_arity () = 0;
+    virtual ~vect_pattern_match () {};
+};
+
+class vect_pattern
+{
+  protected:
+    uint8_t m_arity;
+    uint8_t m_num_args;
+    internal_fn m_ifn;
+    slp_tree *m_node;
+    vec_info *m_vinfo;
+    vect_pattern_match* m_match;
+    vec<slp_tree> m_ops;
+    vect_pattern (slp_tree *node, vec_info *vinfo)
+    {
+      this->m_ifn = IFN_LAST;
+      this->m_node = node;
+      this->m_vinfo = vinfo;
+      this->m_match = NULL;
+      this->m_ops.create (0);
+    }
+
+  public:
+    static vect_pattern* create (slp_tree *node, vec_info *vinfo);
+    virtual bool matches () = 0;
+    virtual bool matches (enum _complex_operation, vec<slp_tree>)
+    {
+      return false;
+    }
+
+    virtual const char* get_name () = 0;
+    virtual ~vect_pattern ()
+    {
+	this->m_ops.release ();
+    }
+
+    virtual gcall *build ()
+    {
+      if (this->m_match == NULL)
+       return NULL;
+
+      return this->m_match->build ();
+    }
+
+    virtual bool validate_p ()
+    {
+      return true;
+    }
+
+    virtual uint8_t get_arity ()
+    {
+      return this->m_arity;
+    }
+
+    virtual bool is_optab_supported_p (tree vectype, optimization_type opt_type)
+    {
+      if (!vectype)
+        return false;
+
+      return direct_internal_fn_supported_p (this->m_ifn, vectype, opt_type);
+    }
+
+    virtual internal_fn get_ifn ()
+    {
+      return this->m_ifn;
+    }
+};
+
+typedef vect_pattern* (*vect_pattern_decl_t) (slp_tree *, vec_info *);
+extern vect_pattern_decl_t slp_patterns[];
+extern size_t num__slp_patterns;
+
 #endif  /* GCC_TREE_VECTORIZER_H  */


  reply	other threads:[~2020-11-03 15:06 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-25 14:27 Tamar Christina
2020-09-28 12:36 ` Richard Biener
2020-09-28 14:56   ` Tamar Christina
2020-09-28 17:24     ` Tamar Christina
2020-09-29  6:45       ` Richard Biener
2020-09-29  9:25         ` Richard Sandiford
2020-09-29  9:42           ` Richard Biener
2020-11-03 15:06             ` Tamar Christina [this message]
2020-11-04 12:40               ` Richard Biener
2020-11-04 13:37                 ` Tamar Christina
2020-11-04 14:04                   ` Richard Biener
2020-11-04 14:36                     ` Tamar Christina
2020-11-04 15:14                       ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=VI1PR08MB53250748BBC032014BB94CF0FF110@VI1PR08MB5325.eurprd08.prod.outlook.com \
    --to=tamar.christina@arm.com \
    --cc=Richard.Sandiford@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=nd@arm.com \
    --cc=rguenther@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).