[9b/n] PR85694: Make vect_is_simple_use look through pattern statements
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 30 Jun 2018 12:47:25 +0000 (12:47 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 30 Jun 2018 12:47:25 +0000 (12:47 +0000)
As suggested by Richard B., this patch makes vect_is_simple_use check
whether a defining statement has been replaced by a pattern statement,
and if so returns the pattern statement instead.

The reason for doing this is that the main patch for PR85694
makes over_widening handle more general cases.  These over-widened
patterns can still be useful when matching later statements;
e.g. an overwidened MULT_EXPR could be the input to a DOT_PROD_EXPR.

The patch doesn't do anything with the STMT_VINFO_IN_PATTERN_P checks
in vect_recog_over_widening_pattern or vect_recog_widen_shift_pattern
since later patches rewrite them anyway.

Doing this fixed an XFAIL in vect-reduc-dot-u16b.c.

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

gcc/
* tree-vect-loop.c (vectorizable_reduction): Assert that the
phi is not a pattern statement and has not been replaced by
a pattern statement.
* tree-vect-patterns.c (type_conversion_p): Don't check
STMT_VINFO_IN_PATTERN_P.
(vect_recog_vector_vector_shift_pattern): Likewise.
(vect_recog_dot_prod_pattern): Expect vect_is_simple_use to return
the pattern statement rather than the original statement; check
directly for a WIDEN_MULT_EXPR here.
* tree-vect-slp.c (vect_get_and_check_slp_defs): Expect
vect_is_simple_use to return the pattern statement rather
than the original statement; use is_pattern_stmt_p to check
for such a pattern statement.
* tree-vect-stmts.c (process_use): Expect vect_is_simple_use
to return the pattern statement rather than the original statement;
don't do the same transformation here.
(vect_is_simple_use): If the defining statement has been replaced
by a pattern statement, return the pattern statement instead.
Remove the corresponding (local) transformation from the vectype
overload.

gcc/testsuite/
* gcc.dg/vect/vect-reduc-dot-u16b.c: Remove xfail and update the
test for vectorization along the lines described in the comment.

From-SVN: r262273

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c
gcc/tree-vect-loop.c
gcc/tree-vect-patterns.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c

index 528bc4bde5c8b749990fc8e0d3ffc759ebdb6c30..366bbc073fa50532313ad173e5c70a54b2cfd672 100644 (file)
@@ -1,3 +1,26 @@
+2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * tree-vect-loop.c (vectorizable_reduction): Assert that the
+       phi is not a pattern statement and has not been replaced by
+       a pattern statement.
+       * tree-vect-patterns.c (type_conversion_p): Don't check
+       STMT_VINFO_IN_PATTERN_P.
+       (vect_recog_vector_vector_shift_pattern): Likewise.
+       (vect_recog_dot_prod_pattern): Expect vect_is_simple_use to return
+       the pattern statement rather than the original statement; check
+       directly for a WIDEN_MULT_EXPR here.
+       * tree-vect-slp.c (vect_get_and_check_slp_defs): Expect
+       vect_is_simple_use to return the pattern statement rather
+       than the original statement; use is_pattern_stmt_p to check
+       for such a pattern statement.
+       * tree-vect-stmts.c (process_use): Expect vect_is_simple_use
+       to return the pattern statement rather than the original statement;
+       don't do the same transformation here.
+       (vect_is_simple_use): If the defining statement has been replaced
+       by a pattern statement, return the pattern statement instead.
+       Remove the corresponding (local) transformation from the vectype
+       overload.
+
 2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vectorizer.h (vect_is_simple_use): Move the gimple ** to the
index aa05ce747127e6ae7e26df4ed7453b2c3c028c73..db2ca7353a98b5991e1ff013c1d1324cce9e3333 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gcc.dg/vect/vect-reduc-dot-u16b.c: Remove xfail and update the
+       test for vectorization along the lines described in the comment.
+
 2018-06-30  Tom de Vries  <tdevries@suse.de>
 
        * gcc.dg/guality/guality.exp (guality_transform_options): New proc.
index b2e6ab8861d64622f0593fb0065b7a75de430d27..57e18040cf24b71cf77788716078f6c1f08fa3a0 100644 (file)
 unsigned short X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
 unsigned short Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
 
-/* short->int->int dot product. 
-   Currently not detected as a dot-product pattern: the multiplication 
-   promotes the ushorts to int, and then the product is promoted to unsigned 
-   int for the addition.  Which results in an int->unsigned int cast, which 
-   since no bits are modified in the cast should be trivially vectorizable.  */
+/* ushort->int->uint dot product: the multiplication promotes the ushorts
+   to int, and then the product is converted to uint for the addition.  */
 __attribute__ ((noinline)) unsigned int
 foo2(int len) {
   int i;
@@ -47,12 +44,6 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected" 1 "vect" { xfail *-*-* } } } */
-
-/* Once the dot-product pattern is detected, we expect
-   that loop to be vectorized on vect_udot_hi targets (targets that support 
-   dot-product of unsigned shorts) and targets that support widening multiplication.  */
-/* The induction loop in main is vectorized.  */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail *-*-* } } } */ 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_pack_trunc } } } */ 
+/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected" 1 "vect" } } */
 
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_pack_trunc || vect_udot_hi } } } } */ 
index 73a1a8f027c2ec2bbcdc919d86a34bb23e62ee8a..67e8efe2fa98bb744e4de699ef856d206eb21c4d 100644 (file)
@@ -6487,6 +6487,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
     }
 
   stmt_vec_info reduc_def_info = vinfo_for_stmt (reduc_def_stmt);
+  /* PHIs should not participate in patterns.  */
+  gcc_assert (!STMT_VINFO_RELATED_STMT (reduc_def_info));
   enum vect_reduction_type v_reduc_type
     = STMT_VINFO_REDUC_TYPE (reduc_def_info);
   gimple *tmp = STMT_VINFO_REDUC_DEF (reduc_def_info);
index 6fb07fd1265784f71869e22c29ada73c8261baad..6926c849f13e4e4cc006203126991a4a703344f4 100644 (file)
@@ -193,13 +193,6 @@ type_conversion_p (tree name, gimple *use_stmt, bool check_sign,
   if (!*def_stmt)
     return false;
 
-  if (dt == vect_internal_def)
-    {
-      stmt_vec_info def_vinfo = vinfo_for_stmt (*def_stmt);
-      if (STMT_VINFO_IN_PATTERN_P (def_vinfo))
-       return false;
-    }
-
   if (!is_gimple_assign (*def_stmt))
     return false;
 
@@ -383,20 +376,11 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_out)
   /* FORNOW.  Can continue analyzing the def-use chain when this stmt in a phi
      inside the loop (in case we are analyzing an outer-loop).  */
   gassign *mult = dyn_cast <gassign *> (mult_vinfo->stmt);
-  if (!mult || gimple_assign_rhs_code (mult) != MULT_EXPR)
+  if (!mult)
     return NULL;
-  if (STMT_VINFO_IN_PATTERN_P (mult_vinfo))
+  if (gimple_assign_rhs_code (mult) == WIDEN_MULT_EXPR)
     {
       /* Has been detected as a widening multiplication?  */
-
-      mult = dyn_cast <gassign *> (STMT_VINFO_RELATED_STMT (mult_vinfo));
-      if (!mult || gimple_assign_rhs_code (mult) != WIDEN_MULT_EXPR)
-        return NULL;
-      STMT_VINFO_PATTERN_DEF_SEQ (stmt_vinfo)
-       = STMT_VINFO_PATTERN_DEF_SEQ (mult_vinfo);
-      mult_vinfo = vinfo_for_stmt (mult);
-      gcc_assert (mult_vinfo);
-      gcc_assert (STMT_VINFO_DEF_TYPE (mult_vinfo) == vect_internal_def);
       oprnd00 = gimple_assign_rhs1 (mult);
       oprnd01 = gimple_assign_rhs2 (mult);
     }
@@ -406,6 +390,9 @@ vect_recog_dot_prod_pattern (vec<gimple *> *stmts, tree *type_out)
       gimple *def_stmt;
       tree oprnd0, oprnd1;
 
+      if (gimple_assign_rhs_code (mult) != MULT_EXPR)
+       return NULL;
+
       oprnd0 = gimple_assign_rhs1 (mult);
       oprnd1 = gimple_assign_rhs2 (mult);
       if (!type_conversion_p (oprnd0, mult, true, &half_type0, &def_stmt,
@@ -2050,9 +2037,7 @@ vect_recog_vector_vector_shift_pattern (vec<gimple *> *stmts, tree *type_out)
 
   tree def = NULL_TREE;
   gassign *def_stmt = dyn_cast <gassign *> (def_vinfo->stmt);
-  if (!STMT_VINFO_IN_PATTERN_P (def_vinfo)
-      && def_stmt
-      && gimple_assign_cast_p (def_stmt))
+  if (def_stmt && gimple_assign_cast_p (def_stmt))
     {
       tree rhs1 = gimple_assign_rhs1 (def_stmt);
       if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
index 573ed76f6546f1ff1b066e73e4ead4ad1e377118..528e1d55892d3b7c8a162fe804bec036989c46cf 100644 (file)
@@ -365,11 +365,9 @@ again:
          from the pattern.  Check that all the stmts of the node are in the
          pattern.  */
       if (def_stmt && gimple_bb (def_stmt)
-          && vect_stmt_in_region_p (vinfo, def_stmt)
-          && vinfo_for_stmt (def_stmt)
-          && STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (def_stmt))
-         && !STMT_VINFO_RELEVANT (vinfo_for_stmt (def_stmt))
-         && !STMT_VINFO_LIVE_P (vinfo_for_stmt (def_stmt)))
+         && vect_stmt_in_region_p (vinfo, def_stmt)
+         && vinfo_for_stmt (def_stmt)
+         && is_pattern_stmt_p (vinfo_for_stmt (def_stmt)))
         {
           pattern = true;
           if (!first && !oprnd_info->first_pattern
@@ -398,7 +396,6 @@ again:
              return 1;
             }
 
-          def_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
           dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt));
 
           if (dt == vect_unknown_def_type)
index c1c5410d46bb55d847cea1a60334794c150b2f2b..ab8cc8049a427b74bc862fdaf95ce5d4ca90d4de 100644 (file)
@@ -506,8 +506,6 @@ process_use (gimple *stmt, tree use, loop_vec_info loop_vinfo,
       if (dump_enabled_p ())
        dump_printf_loc (MSG_NOTE, vect_location,
                          "reduc-stmt defining reduc-phi in the same nest.\n");
-      if (STMT_VINFO_IN_PATTERN_P (dstmt_vinfo))
-       dstmt_vinfo = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (dstmt_vinfo));
       gcc_assert (STMT_VINFO_RELEVANT (dstmt_vinfo) < vect_used_by_reduction);
       gcc_assert (STMT_VINFO_LIVE_P (dstmt_vinfo)
                  || STMT_VINFO_RELEVANT (dstmt_vinfo) > vect_unused_in_scope);
@@ -10069,8 +10067,6 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
     }
 
   gimple *def_stmt = SSA_NAME_DEF_STMT (operand);
-  if (def_stmt_out)
-    *def_stmt_out = def_stmt;
   if (dump_enabled_p ())
     {
       dump_printf_loc (MSG_NOTE, vect_location, "def_stmt: ");
@@ -10082,8 +10078,15 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
   else
     {
       stmt_vec_info stmt_vinfo = vinfo_for_stmt (def_stmt);
+      if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
+       {
+         def_stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
+         stmt_vinfo = vinfo_for_stmt (def_stmt);
+       }
       *dt = STMT_VINFO_DEF_TYPE (stmt_vinfo);
     }
+  if (def_stmt_out)
+    *def_stmt_out = def_stmt;
 
   if (dump_enabled_p ())
     {
@@ -10174,12 +10177,6 @@ vect_is_simple_use (tree operand, vec_info *vinfo, enum vect_def_type *dt,
       || *dt == vect_nested_cycle)
     {
       stmt_vec_info stmt_info = vinfo_for_stmt (def_stmt);
-
-      if (STMT_VINFO_IN_PATTERN_P (stmt_info)
-          && !STMT_VINFO_RELEVANT (stmt_info)
-          && !STMT_VINFO_LIVE_P (stmt_info))
-       stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
-
       *vectype = STMT_VINFO_VECTYPE (stmt_info);
       gcc_assert (*vectype != NULL_TREE);
     }