[8/n] PR85694: Make patterns check for target support
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 20 Jun 2018 08:16:08 +0000 (08:16 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 20 Jun 2018 08:16:08 +0000 (08:16 +0000)
This patch makes pattern recognisers do their own checking for vector
types and target support.  Previously some recognisers did this
themselves and some left it to vect_pattern_recog_1.

Doing this means we can get rid of the type_in argument, which was
ignored if the recogniser did its own checking.  It also means
we create fewer junk statements.

2018-06-20  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* tree-vectorizer.h (NUM_PATTERNS, vect_recog_func_ptr): Move to
tree-vect-patterns.c.
* tree-vect-patterns.c (vect_supportable_direct_optab_p): New function.
(vect_recog_dot_prod_pattern): Use it.  Remove the type_in argument.
(vect_recog_sad_pattern): Likewise.
(vect_recog_widen_sum_pattern): Likewise.
(vect_recog_pow_pattern): Likewise.  Check for a null vectype.
(vect_recog_widen_shift_pattern): Remove the type_in argument.
(vect_recog_rotate_pattern): Likewise.
(vect_recog_mult_pattern): Likewise.
(vect_recog_vector_vector_shift_pattern): Likewise.
(vect_recog_divmod_pattern): Likewise.
(vect_recog_mixed_size_cond_pattern): Likewise.
(vect_recog_bool_pattern): Likewise.
(vect_recog_mask_conversion_pattern): Likewise.
(vect_try_gather_scatter_pattern): Likewise.
(vect_recog_widen_mult_pattern): Likewise.  Check for a null vectype.
(vect_recog_over_widening_pattern): Likewise.
(vect_recog_gather_scatter_pattern): Likewise.
(vect_recog_func_ptr): Move from tree-vectorizer.h
(vect_vect_recog_func_ptrs): Move further down the file.
(vect_recog_func): Likewise.  Remove the third argument.
(NUM_PATTERNS): Define based on vect_vect_recog_func_ptrs.
(vect_pattern_recog_1): Expect the pattern function to do any
necessary target tests.  Also expect it to provide a vector type.
Remove the type_in handling.

From-SVN: r261791

gcc/ChangeLog
gcc/tree-vect-patterns.c
gcc/tree-vectorizer.h

index 384c6ad49f63ccbb192990a2257899b655ea52c6..ff47deb5e5b2f2f0a524e7d65213bdb5a735a6cd 100644 (file)
@@ -1,3 +1,32 @@
+2018-06-20  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * tree-vectorizer.h (NUM_PATTERNS, vect_recog_func_ptr): Move to
+       tree-vect-patterns.c.
+       * tree-vect-patterns.c (vect_supportable_direct_optab_p): New function.
+       (vect_recog_dot_prod_pattern): Use it.  Remove the type_in argument.
+       (vect_recog_sad_pattern): Likewise.
+       (vect_recog_widen_sum_pattern): Likewise.
+       (vect_recog_pow_pattern): Likewise.  Check for a null vectype.
+       (vect_recog_widen_shift_pattern): Remove the type_in argument.
+       (vect_recog_rotate_pattern): Likewise.
+       (vect_recog_mult_pattern): Likewise.
+       (vect_recog_vector_vector_shift_pattern): Likewise.
+       (vect_recog_divmod_pattern): Likewise.
+       (vect_recog_mixed_size_cond_pattern): Likewise.
+       (vect_recog_bool_pattern): Likewise.
+       (vect_recog_mask_conversion_pattern): Likewise.
+       (vect_try_gather_scatter_pattern): Likewise.
+       (vect_recog_widen_mult_pattern): Likewise.  Check for a null vectype.
+       (vect_recog_over_widening_pattern): Likewise.
+       (vect_recog_gather_scatter_pattern): Likewise.
+       (vect_recog_func_ptr): Move from tree-vectorizer.h
+       (vect_vect_recog_func_ptrs): Move further down the file.
+       (vect_recog_func): Likewise.  Remove the third argument.
+       (NUM_PATTERNS): Define based on vect_vect_recog_func_ptrs.
+       (vect_pattern_recog_1): Expect the pattern function to do any
+       necessary target tests.  Also expect it to provide a vector type.
+       Remove the type_in handling.
+
 2018-06-20  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vect-patterns.c (vect_pattern_detected): New function.
index 3d7f866fe375364e41e866fec957ee3b2b821e76..a07b1a991591fd4b8dd9ee635512115ad38bc05f 100644 (file)
@@ -47,66 +47,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "omp-simd-clone.h"
 #include "predict.h"
 
-/* Pattern recognition functions  */
-static gimple *vect_recog_widen_sum_pattern (vec<gimple *> *, tree *,
-                                           tree *);
-static gimple *vect_recog_widen_mult_pattern (vec<gimple *> *, tree *,
-                                            tree *);
-static gimple *vect_recog_dot_prod_pattern (vec<gimple *> *, tree *,
-                                          tree *);
-static gimple *vect_recog_sad_pattern (vec<gimple *> *, tree *,
-                                     tree *);
-static gimple *vect_recog_pow_pattern (vec<gimple *> *, tree *, tree *);
-static gimple *vect_recog_over_widening_pattern (vec<gimple *> *, tree *,
-                                                 tree *);
-static gimple *vect_recog_widen_shift_pattern (vec<gimple *> *,
-                                       tree *, tree *);
-static gimple *vect_recog_rotate_pattern (vec<gimple *> *, tree *, tree *);
-static gimple *vect_recog_vector_vector_shift_pattern (vec<gimple *> *,
-                                                     tree *, tree *);
-static gimple *vect_recog_divmod_pattern (vec<gimple *> *,
-                                        tree *, tree *);
-
-static gimple *vect_recog_mult_pattern (vec<gimple *> *,
-                                      tree *, tree *);
-
-static gimple *vect_recog_mixed_size_cond_pattern (vec<gimple *> *,
-                                                 tree *, tree *);
-static gimple *vect_recog_bool_pattern (vec<gimple *> *, tree *, tree *);
-static gimple *vect_recog_mask_conversion_pattern (vec<gimple *> *, tree *, tree *);
-static gimple *vect_recog_gather_scatter_pattern (vec<gimple *> *, tree *,
-                                                 tree *);
-
-struct vect_recog_func
-{
-  vect_recog_func_ptr fn;
-  const char *name;
-};
-
-/* Note that ordering matters - the first pattern matching on a stmt
-   is taken which means usually the more complex one needs to preceed
-   the less comples onex (widen_sum only after dot_prod or sad for example).  */
-static vect_recog_func vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
-      { vect_recog_widen_mult_pattern, "widen_mult" },
-      { vect_recog_dot_prod_pattern, "dot_prod" },
-      { vect_recog_sad_pattern, "sad" },
-      { vect_recog_widen_sum_pattern, "widen_sum" },
-      { vect_recog_pow_pattern, "pow" },
-      { vect_recog_widen_shift_pattern, "widen_shift" },
-      { vect_recog_over_widening_pattern, "over_widening" },
-      { vect_recog_rotate_pattern, "rotate" },
-      { vect_recog_vector_vector_shift_pattern, "vector_vector_shift" },
-      {        vect_recog_divmod_pattern, "divmod" },
-      {        vect_recog_mult_pattern, "mult" },
-      {        vect_recog_mixed_size_cond_pattern, "mixed_size_cond" },
-      {        vect_recog_bool_pattern, "bool" },
-      /* This must come before mask conversion, and includes the parts
-        of mask conversion that are needed for gather and scatter
-        internal functions.  */
-      { vect_recog_gather_scatter_pattern, "gather_scatter" },
-      {        vect_recog_mask_conversion_pattern, "mask_conversion" }
-};
-
 /* Report that we've found an instance of pattern PATTERN in
    statement STMT.  */
 
@@ -134,6 +74,49 @@ new_pattern_def_seq (stmt_vec_info stmt_info, gimple *stmt)
   append_pattern_def_seq (stmt_info, stmt);
 }
 
+/* Return true if the target supports a vector version of CODE,
+   where CODE is known to map to a direct optab.  ITYPE specifies
+   the type of (some of) the scalar inputs and OTYPE specifies the
+   type of the scalar result.
+
+   If CODE allows the inputs and outputs to have different type
+   (such as for WIDEN_SUM_EXPR), it is the input mode rather
+   than the output mode that determines the appropriate target pattern.
+   Operand 0 of the target pattern then specifies the mode that the output
+   must have.
+
+   When returning true, set *VECOTYPE_OUT to the vector version of OTYPE.
+   Also set *VECITYPE_OUT to the vector version of ITYPE if VECITYPE_OUT
+   is nonnull.  */
+
+static bool
+vect_supportable_direct_optab_p (tree otype, tree_code code,
+                                tree itype, tree *vecotype_out,
+                                tree *vecitype_out = NULL)
+{
+  tree vecitype = get_vectype_for_scalar_type (itype);
+  if (!vecitype)
+    return false;
+
+  tree vecotype = get_vectype_for_scalar_type (otype);
+  if (!vecotype)
+    return false;
+
+  optab optab = optab_for_tree_code (code, vecitype, optab_default);
+  if (!optab)
+    return false;
+
+  insn_code icode = optab_handler (optab, TYPE_MODE (vecitype));
+  if (icode == CODE_FOR_nothing
+      || insn_data[icode].operand[0].mode != TYPE_MODE (vecotype))
+    return false;
+
+  *vecotype_out = vecotype;
+  if (vecitype_out)
+    *vecitype_out = vecitype;
+  return true;
+}
+
 /* Check whether STMT2 is in the same loop or basic block as STMT1.
    Which of the two applies depends on whether we're currently doing
    loop-based or basic-block-based vectorization, as determined by
@@ -293,8 +276,6 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo)
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output  of this pattern.
 
    * Return value: A new stmt that will be used to replace the sequence of
@@ -310,8 +291,7 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_vinfo)
          inner-loop nested in an outer-loop that us being vectorized).  */
 
 static gimple *
-vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
-                            tree *type_out)
+vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *stmt, *last_stmt = (*stmts)[0];
   tree oprnd0, oprnd1;
@@ -448,8 +428,9 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
   vect_pattern_detected ("vect_recog_dot_prod_pattern", last_stmt);
 
   half_type = TREE_TYPE (oprnd00);
-  *type_in = half_type;
-  *type_out = type;
+  if (!vect_supportable_direct_optab_p (type, DOT_PROD_EXPR, half_type,
+                                       type_out))
+    return NULL;
 
   var = vect_recog_temp_ssa_var (type, NULL);
   pattern_stmt = gimple_build_assign (var, DOT_PROD_EXPR,
@@ -489,8 +470,6 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the sequence of
@@ -499,8 +478,7 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_in,
   */
 
 static gimple *
-vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in,
-                            tree *type_out)
+vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = (*stmts)[0];
   tree sad_oprnd0, sad_oprnd1;
@@ -641,8 +619,9 @@ vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in,
 
   vect_pattern_detected ("vect_recog_sad_pattern", last_stmt);
 
-  *type_in = TREE_TYPE (sad_oprnd0);
-  *type_out = sum_type;
+  if (!vect_supportable_direct_optab_p (sum_type, SAD_EXPR,
+                                       TREE_TYPE (sad_oprnd0), type_out))
+    return NULL;
 
   tree var = vect_recog_temp_ssa_var (sum_type, NULL);
   gimple *pattern_stmt = gimple_build_assign (var, SAD_EXPR, sad_oprnd0,
@@ -778,8 +757,6 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code,
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the sequence of
@@ -790,8 +767,7 @@ vect_handle_widen_op_by_const (gimple *stmt, enum tree_code code,
 */
 
 static gimple *
-vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
-                               tree *type_in, tree *type_out)
+vect_recog_widen_mult_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   gimple *def_stmt0, *def_stmt1;
@@ -933,8 +909,9 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
                                          &dummy_int, &dummy_vec))
     return NULL;
 
-  *type_in = vectype;
   *type_out = get_vectype_for_scalar_type (type);
+  if (!*type_out)
+    return NULL;
 
   /* Pattern supported. Create a stmt to be used to replace the pattern: */
   var = vect_recog_temp_ssa_var (itype, NULL);
@@ -989,8 +966,6 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the sequence of
@@ -1001,8 +976,7 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
 */
 
 static gimple *
-vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
-                       tree *type_out)
+vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = (*stmts)[0];
   tree base, exp;
@@ -1072,12 +1046,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
                  if (node->simd_clones == NULL)
                    return NULL;
                }
+             *type_out = get_vectype_for_scalar_type (TREE_TYPE (base));
+             if (!*type_out)
+               return NULL;
              stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
              tree def = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
              gimple *g = gimple_build_assign (def, MULT_EXPR, exp, logc);
              new_pattern_def_seq (stmt_vinfo, g);
-             *type_in = TREE_TYPE (base);
-             *type_out = NULL_TREE;
              tree res = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
              g = gimple_build_call (exp_decl, 1, def);
              gimple_call_set_lhs (g, res);
@@ -1091,15 +1066,15 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
   /* We now have a pow or powi builtin function call with a constant
      exponent.  */
 
-  *type_out = NULL_TREE;
-
   /* Catch squaring.  */
   if ((tree_fits_shwi_p (exp)
        && tree_to_shwi (exp) == 2)
       || (TREE_CODE (exp) == REAL_CST
           && real_equal (&TREE_REAL_CST (exp), &dconst2)))
     {
-      *type_in = TREE_TYPE (base);
+      if (!vect_supportable_direct_optab_p (TREE_TYPE (base), MULT_EXPR,
+                                           TREE_TYPE (base), type_out))
+       return NULL;
 
       var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
       stmt = gimple_build_assign (var, MULT_EXPR, base, base);
@@ -1110,9 +1085,9 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
   if (TREE_CODE (exp) == REAL_CST
       && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
     {
-      *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
-      if (*type_in
-         && direct_internal_fn_supported_p (IFN_SQRT, *type_in,
+      *type_out = get_vectype_for_scalar_type (TREE_TYPE (base));
+      if (*type_out
+         && direct_internal_fn_supported_p (IFN_SQRT, *type_out,
                                             OPTIMIZE_FOR_SPEED))
        {
          gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
@@ -1150,8 +1125,6 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the sequence of
@@ -1167,8 +1140,7 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
         inner-loop nested in an outer-loop that us being vectorized).  */
 
 static gimple *
-vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in,
-                             tree *type_out)
+vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *stmt, *last_stmt = (*stmts)[0];
   tree oprnd0, oprnd1;
@@ -1223,14 +1195,15 @@ vect_recog_widen_sum_pattern (vec<gimple *> *stmts, tree *type_in,
   if (!type_conversion_p (oprnd0, last_stmt, true, &half_type, &stmt,
                           &promotion)
       || !promotion)
-     return NULL;
+    return NULL;
 
   oprnd0 = gimple_assign_rhs1 (stmt);
 
   vect_pattern_detected ("vect_recog_widen_sum_pattern", last_stmt);
 
-  *type_in = half_type;
-  *type_out = type;
+  if (!vect_supportable_direct_optab_p (type, WIDEN_SUM_EXPR, half_type,
+                                       type_out))
+    return NULL;
 
   var = vect_recog_temp_ssa_var (type, NULL);
   pattern_stmt = gimple_build_assign (var, WIDEN_SUM_EXPR, oprnd0, oprnd1);
@@ -1473,8 +1446,7 @@ vect_operation_fits_smaller_type (gimple *stmt, tree def, tree *new_type,
    demotion operation.  We also check that S3 and S4 have only one use.  */
 
 static gimple *
-vect_recog_over_widening_pattern (vec<gimple *> *stmts,
-                                  tree *type_in, tree *type_out)
+vect_recog_over_widening_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *stmt = stmts->pop ();
   gimple *pattern_stmt = NULL, *new_def_stmt, *prev_stmt = NULL,
@@ -1562,14 +1534,15 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
       if (TYPE_UNSIGNED (new_type) != TYPE_UNSIGNED (use_type)
           || TYPE_PRECISION (new_type) != TYPE_PRECISION (use_type))
         {
+         *type_out = get_vectype_for_scalar_type (use_type);
+         if (!*type_out)
+           return NULL;
+
           /* Create NEW_TYPE->USE_TYPE conversion.  */
          new_oprnd = make_ssa_name (use_type);
          pattern_stmt = gimple_build_assign (new_oprnd, NOP_EXPR, var);
           STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt;
 
-          *type_in = get_vectype_for_scalar_type (new_type);
-          *type_out = get_vectype_for_scalar_type (use_type);
-
           /* We created a pattern statement for the last statement in the
              sequence, so we don't need to associate it with the pattern
              statement created for PREV_STMT.  Therefore, we add PREV_STMT
@@ -1583,8 +1556,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
            STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (use_stmt))
               = STMT_VINFO_PATTERN_DEF_SEQ (vinfo_for_stmt (prev_stmt));
 
-          *type_in = vectype;
-          *type_out = NULL_TREE;
+         *type_out = vectype;
         }
 
       stmts->safe_push (use_stmt);
@@ -1648,8 +1620,6 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
 
   Output:
 
-  * TYPE_IN: The type of the input arguments to the pattern.
-
   * TYPE_OUT: The type of the output of this pattern.
 
   * Return value: A new stmt that will be used to replace the sequence of
@@ -1657,8 +1627,7 @@ vect_recog_over_widening_pattern (vec<gimple *> *stmts,
     WIDEN_LSHIFT_EXPR <a_t, CONST>.  */
 
 static gimple *
-vect_recog_widen_shift_pattern (vec<gimple *> *stmts,
-                               tree *type_in, tree *type_out)
+vect_recog_widen_shift_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   gimple *def_stmt0;
@@ -1740,7 +1709,6 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts,
                                          &dummy_int, &dummy_vec))
     return NULL;
 
-  *type_in = vectype;
   *type_out = vectype_out;
 
   /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
@@ -1783,15 +1751,13 @@ vect_recog_widen_shift_pattern (vec<gimple *> *stmts,
 
   Output:
 
-  * TYPE_IN: The type of the input arguments to the pattern.
-
   * TYPE_OUT: The type of the output of this pattern.
 
   * Return value: A new stmt that will be used to replace the rotate
     S0 stmt.  */
 
 static gimple *
-vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
+vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   tree oprnd0, oprnd1, lhs, var, var1, var2, vectype, type, stype, def, def2;
@@ -1876,10 +1842,7 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
        return NULL;
     }
 
-  *type_in = vectype;
   *type_out = vectype;
-  if (*type_in == NULL_TREE)
-    return NULL;
 
   if (dt == vect_external_def
       && TREE_CODE (oprnd1) == SSA_NAME
@@ -2034,16 +1997,13 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
 
   Output:
 
-  * TYPE_IN: The type of the input arguments to the pattern.
-
   * TYPE_OUT: The type of the output of this pattern.
 
   * Return value: A new stmt that will be used to replace the shift/rotate
     S3 stmt.  */
 
 static gimple *
-vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts,
-                                       tree *type_in, tree *type_out)
+vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   tree oprnd0, oprnd1, lhs, var;
@@ -2085,9 +2045,8 @@ vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts,
   if (!def_vinfo)
     return NULL;
 
-  *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
-  *type_out = *type_in;
-  if (*type_in == NULL_TREE)
+  *type_out = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
+  if (*type_out == NULL_TREE)
     return NULL;
 
   tree def = NULL_TREE;
@@ -2449,16 +2408,13 @@ vect_synth_mult_by_constant (tree op, tree val,
 
  Output:
 
-  * TYPE_IN: The type of the input arguments to the pattern.
-
   * TYPE_OUT: The type of the output of this pattern.
 
   * Return value: A new stmt that will be used to replace
     the multiplication.  */
 
 static gimple *
-vect_recog_mult_pattern (vec<gimple *> *stmts,
-                        tree *type_in, tree *type_out)
+vect_recog_mult_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   tree oprnd0, oprnd1, vectype, itype;
@@ -2504,7 +2460,6 @@ vect_recog_mult_pattern (vec<gimple *> *stmts,
   vect_pattern_detected ("vect_recog_mult_pattern", last_stmt);
 
   stmts->safe_push (last_stmt);
-  *type_in = vectype;
   *type_out = vectype;
 
   return pattern_stmt;
@@ -2543,16 +2498,13 @@ vect_recog_mult_pattern (vec<gimple *> *stmts,
 
   Output:
 
-  * TYPE_IN: The type of the input arguments to the pattern.
-
   * TYPE_OUT: The type of the output of this pattern.
 
   * Return value: A new stmt that will be used to replace the division
     S1 or modulo S4 stmt.  */
 
 static gimple *
-vect_recog_divmod_pattern (vec<gimple *> *stmts,
-                          tree *type_in, tree *type_out)
+vect_recog_divmod_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   tree oprnd0, oprnd1, vectype, itype, cond;
@@ -2703,7 +2655,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
 
       stmts->safe_push (last_stmt);
 
-      *type_in = vectype;
       *type_out = vectype;
       return pattern_stmt;
     }
@@ -2955,7 +2906,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
 
   stmts->safe_push (last_stmt);
 
-  *type_in = vectype;
   *type_out = vectype;
   return pattern_stmt;
 }
@@ -2980,8 +2930,6 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the pattern.
@@ -2991,8 +2939,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
        a_T = (TYPE) a_it;  */
 
 static gimple *
-vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
-                                   tree *type_out)
+vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = (*stmts)[0];
   tree cond_expr, then_clause, else_clause;
@@ -3108,7 +3055,6 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
   def_stmt_info = new_stmt_vec_info (def_stmt, vinfo);
   set_vinfo_for_stmt (def_stmt, def_stmt_info);
   STMT_VINFO_VECTYPE (def_stmt_info) = vecitype;
-  *type_in = vecitype;
   *type_out = vectype;
 
   vect_pattern_detected ("vect_recog_mixed_size_cond_pattern", last_stmt);
@@ -3581,8 +3527,6 @@ search_type_for_mask (tree var, vec_info *vinfo)
 
    Output:
 
-   * TYPE_IN: The type of the input arguments to the pattern.
-
    * TYPE_OUT: The type of the output of this pattern.
 
    * Return value: A new stmt that will be used to replace the pattern.
@@ -3602,8 +3546,7 @@ search_type_for_mask (tree var, vec_info *vinfo)
        but the above is more efficient.  */
 
 static gimple *
-vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
-                        tree *type_out)
+vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   enum tree_code rhs_code;
@@ -3679,7 +3622,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
        }
 
       *type_out = vectype;
-      *type_in = vectype;
       stmts->safe_push (last_stmt);
       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
 
@@ -3718,7 +3660,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
                                 gimple_assign_rhs2 (last_stmt),
                                 gimple_assign_rhs3 (last_stmt));
       *type_out = vectype;
-      *type_in = vectype;
       stmts->safe_push (last_stmt);
       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
 
@@ -3775,7 +3716,6 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
       STMT_VINFO_DR_WRT_VEC_LOOP (pattern_stmt_info)
        = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
       *type_out = vectype;
-      *type_in = vectype;
       stmts->safe_push (last_stmt);
       vect_pattern_detected ("vect_recog_bool_pattern", last_stmt);
 
@@ -3839,8 +3779,7 @@ build_mask_conversion (tree mask, tree vectype, stmt_vec_info stmt_vinfo,
    S4'  c_1' = m_3'' ? c_2 : c_3;  */
 
 static gimple *
-vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
-                                   tree *type_out)
+vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   enum tree_code rhs_code;
@@ -3911,7 +3850,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
        = STMT_VINFO_DR_WRT_VEC_LOOP (stmt_vinfo);
 
       *type_out = vectype1;
-      *type_in = vectype1;
       stmts->safe_push (last_stmt);
       vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
 
@@ -4035,7 +3973,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
                                          gimple_assign_rhs3 (last_stmt));
 
       *type_out = vectype1;
-      *type_in = vectype1;
       stmts->safe_push (last_stmt);
       vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
 
@@ -4081,7 +4018,6 @@ vect_recog_mask_conversion_pattern (vec<gimple *> *stmts, tree *type_in,
   pattern_stmt = gimple_build_assign (lhs, rhs_code, rhs1, rhs2);
 
   *type_out = vectype1;
-  *type_in = vectype1;
   stmts->safe_push (last_stmt);
   vect_pattern_detected ("vect_recog_mask_conversion_pattern", last_stmt);
 
@@ -4180,14 +4116,14 @@ vect_add_conversion_to_patterm (tree type, tree value,
 
 /* Try to convert STMT into a call to a gather load or scatter store
    internal function.  Return the final statement on success and set
-   *TYPE_IN and *TYPE_OUT to the vector type being loaded or stored.
+   *TYPE_OUT to the vector type being loaded or stored.
 
    This function only handles gathers and scatters that were recognized
    as such from the outset (indicated by STMT_VINFO_GATHER_SCATTER_P).  */
 
 static gimple *
 vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info,
-                                tree *type_in, tree *type_out)
+                                tree *type_out)
 {
   /* Currently we only support this for loop vectorization.  */
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
@@ -4264,7 +4200,6 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info,
 
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   *type_out = vectype;
-  *type_in = vectype;
   vect_pattern_detected ("gather/scatter pattern", stmt);
 
   return pattern_stmt;
@@ -4273,19 +4208,52 @@ vect_try_gather_scatter_pattern (gimple *stmt, stmt_vec_info last_stmt_info,
 /* Pattern wrapper around vect_try_gather_scatter_pattern.  */
 
 static gimple *
-vect_recog_gather_scatter_pattern (vec<gimple *> *stmts, tree *type_in,
-                                  tree *type_out)
+vect_recog_gather_scatter_pattern (vec<gimple *> *stmts, tree *type_out)
 {
   gimple *last_stmt = stmts->pop ();
   stmt_vec_info last_stmt_info = vinfo_for_stmt (last_stmt);
   gimple *pattern_stmt = vect_try_gather_scatter_pattern (last_stmt,
                                                          last_stmt_info,
-                                                         type_in, type_out);
+                                                         type_out);
   if (pattern_stmt)
     stmts->safe_push (last_stmt);
   return pattern_stmt;
 }
 
+typedef gimple *(*vect_recog_func_ptr) (vec<gimple *> *, tree *);
+
+struct vect_recog_func
+{
+  vect_recog_func_ptr fn;
+  const char *name;
+};
+
+/* Note that ordering matters - the first pattern matching on a stmt is
+   taken which means usually the more complex one needs to preceed the
+   less comples onex (widen_sum only after dot_prod or sad for example).  */
+static vect_recog_func vect_vect_recog_func_ptrs[] = {
+  { vect_recog_widen_mult_pattern, "widen_mult" },
+  { vect_recog_dot_prod_pattern, "dot_prod" },
+  { vect_recog_sad_pattern, "sad" },
+  { vect_recog_widen_sum_pattern, "widen_sum" },
+  { vect_recog_pow_pattern, "pow" },
+  { vect_recog_widen_shift_pattern, "widen_shift" },
+  { vect_recog_over_widening_pattern, "over_widening" },
+  { vect_recog_rotate_pattern, "rotate" },
+  { vect_recog_vector_vector_shift_pattern, "vector_vector_shift" },
+  { vect_recog_divmod_pattern, "divmod" },
+  { vect_recog_mult_pattern, "mult" },
+  { vect_recog_mixed_size_cond_pattern, "mixed_size_cond" },
+  { vect_recog_bool_pattern, "bool" },
+  /* This must come before mask conversion, and includes the parts
+     of mask conversion that are needed for gather and scatter
+     internal functions.  */
+  { vect_recog_gather_scatter_pattern, "gather_scatter" },
+  { vect_recog_mask_conversion_pattern, "mask_conversion" }
+};
+
+const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
+
 /* Mark statements that are involved in a pattern.  */
 
 static inline void
@@ -4337,17 +4305,13 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple *pattern_stmt,
         computation pattern.
    STMT: A stmt from which the pattern search should start.
 
-   If PATTERN_RECOG_FUNC successfully detected the pattern, it creates an
-   expression that computes the same functionality and can be used to
-   replace the sequence of stmts that are involved in the pattern.
-
-   Output:
-   This function checks if the expression returned by PATTERN_RECOG_FUNC is
-   supported in vector form by the target.  We use 'TYPE_IN' to obtain the
-   relevant vector type. If 'TYPE_IN' is already a vector type, then this
-   indicates that target support had already been checked by PATTERN_RECOG_FUNC.
-   If 'TYPE_OUT' is also returned by PATTERN_RECOG_FUNC, we check that it fits
-   to the available target pattern.
+   If PATTERN_RECOG_FUNC successfully detected the pattern, it creates
+   a sequence of statements that has the same functionality and can be
+   used to replace STMT.  It returns the last statement in the sequence
+   and adds any earlier statements to STMT's STMT_VINFO_PATTERN_DEF_SEQ.
+   PATTERN_RECOG_FUNC also sets *TYPE_OUT to the vector type of the final
+   statement, having first checked that the target supports the new operation
+   in that type.
 
    This function also does some bookkeeping, as explained in the documentation
    for vect_recog_pattern.  */
@@ -4361,13 +4325,11 @@ vect_pattern_recog_1 (vect_recog_func *recog_func,
   stmt_vec_info stmt_info;
   loop_vec_info loop_vinfo;
   tree pattern_vectype;
-  tree type_in, type_out;
-  enum tree_code code;
   int i;
 
   stmts_to_replace->truncate (0);
   stmts_to_replace->quick_push (stmt);
-  pattern_stmt = recog_func->fn (stmts_to_replace, &type_in, &type_out);
+  pattern_stmt = recog_func->fn (stmts_to_replace, &pattern_vectype);
   if (!pattern_stmt)
     {
       /* Clear related stmt info that analysis might have noted for
@@ -4385,43 +4347,8 @@ vect_pattern_recog_1 (vect_recog_func *recog_func,
   stmt = stmts_to_replace->last ();
   stmt_info = vinfo_for_stmt (stmt);
   loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+  gcc_assert (pattern_vectype);
  
-  if (VECTOR_BOOLEAN_TYPE_P (type_in)
-      || VECTOR_TYPE_P (type_in))
-    {
-      /* No need to check target support (already checked by the pattern
-         recognition function).  */
-      pattern_vectype = type_out ? type_out : type_in;
-    }
-  else
-    {
-      /* Check target support  */
-      type_in = get_vectype_for_scalar_type (type_in);
-      if (!type_in)
-       return false;
-      if (type_out)
-       type_out = get_vectype_for_scalar_type (type_out);
-      else
-       type_out = type_in;
-      if (!type_out)
-       return false;
-      pattern_vectype = type_out;
-
-      if (is_gimple_assign (pattern_stmt))
-       {
-         enum insn_code icode;
-         code = gimple_assign_rhs_code (pattern_stmt);
-         optab optab = optab_for_tree_code (code, type_in, optab_default);
-         machine_mode vec_mode = TYPE_MODE (type_in);
-         if (!optab
-             || (icode = optab_handler (optab, vec_mode)) == CODE_FOR_nothing
-             || (insn_data[icode].operand[0].mode != TYPE_MODE (type_out)))
-           return false;
-       }
-      else
-       gcc_assert (is_gimple_call (pattern_stmt));
-    }
-
   /* Found a vectorizable pattern.  */
   if (dump_enabled_p ())
     {
index fce3238ff64f8a3c438bc348f867ba9285cfa42d..0d4657b1b4209064e728e9551b58f5e0e62d82fa 100644 (file)
@@ -1628,8 +1628,6 @@ extern int vect_get_place_in_interleaving_chain (gimple *, gimple *);
 /* Pattern recognition functions.
    Additional pattern recognition functions can (and will) be added
    in the future.  */
-typedef gimple *(* vect_recog_func_ptr) (vec<gimple *> *, tree *, tree *);
-#define NUM_PATTERNS 15
 void vect_pattern_recog (vec_info *);
 
 /* In tree-vectorizer.c.  */