re PR tree-optimization/65930 (Reduction with sign-change not handled)
authorRichard Biener <rguenther@suse.de>
Wed, 30 Oct 2019 09:21:09 +0000 (09:21 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 30 Oct 2019 09:21:09 +0000 (09:21 +0000)
2019-10-30  Richard Biener  <rguenther@suse.de>

PR tree-optimization/65930
* tree-vect-loop.c (vect_is_simple_reduction): For reduction
chains also allow a leading and trailing conversion.
* tree-vect-slp.c (vect_get_and_check_slp_defs): Handle
intermediate reduction chains.
(vect_analyze_slp_instance): Likewise.  Build a SLP
node for a trailing conversion manually.

* gcc.dg/vect/pr65930-2.c: New testcase.

From-SVN: r277603

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr65930-2.c [new file with mode: 0644]
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c

index 72d6ec76e9e3ca31062c3a73e644478909430582..618197d1fbe9f34e45012bc754744a85ed0834c8 100644 (file)
@@ -1,3 +1,13 @@
+2019-10-30  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/65930
+       * tree-vect-loop.c (vect_is_simple_reduction): For reduction
+       chains also allow a leading and trailing conversion.
+       * tree-vect-slp.c (vect_get_and_check_slp_defs): Handle
+       intermediate reduction chains.
+       (vect_analyze_slp_instance): Likewise.  Build a SLP
+       node for a trailing conversion manually.
+
 2019-10-30  Martin Liska  <mliska@suse.cz>
 
        * cgraph.c (cgraph_node::local_info): Transform to ...
index 519952fef24ed3d39f425ba2e2d8965045da30ea..23caef029631340729770f3946c82fa7b685cd00 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-30  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/65930
+       * gcc.dg/vect/pr65930-2.c: New testcase.
+
 2019-10-30  Mark Eggleston <mark.eggleston@codethink.com>
 
        * gfortran.dg/no_overwrite_recursive_1.f90: New test.
diff --git a/gcc/testsuite/gcc.dg/vect/pr65930-2.c b/gcc/testsuite/gcc.dg/vect/pr65930-2.c
new file mode 100644 (file)
index 0000000..9cfb9b1
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+int __attribute__((noipa))
+bar (unsigned int *x, int n)
+{
+  int sum = 4;
+  x = __builtin_assume_aligned (x, __BIGGEST_ALIGNMENT__);
+  for (int i = 0; i < n; ++i)
+    sum += x[i*4+0]+ x[i*4 + 1] + x[i*4 + 2] + x[i*4 + 3];
+  return sum;
+}
+
+int
+main ()
+{
+  static int a[16] __attribute__((aligned(__BIGGEST_ALIGNMENT__)))
+    = { 1, 3, 5, 8, 9, 10, 17, 18, 23, 29, 30, 55, 42, 2, 3, 1 };
+  check_vect ();
+  if (bar (a, 4) != 260)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+/* { dg-final { scan-tree-dump "Loop contains only SLP stmts" "vect" } } */
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */
index 9b7d2485b7cae81578c6a7d33304dc48134cc850..fa873e9b435037e5a81dda6615cab809d2d4de48 100644 (file)
@@ -3005,14 +3005,21 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
       for (i = path.length () - 1; i >= 1; --i)
        {
          gimple *stmt = USE_STMT (path[i].second);
-         if (gimple_assign_rhs_code (stmt) != code
+         stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt);
+         STMT_VINFO_REDUC_IDX (stmt_info)
+           = path[i].second->use - gimple_assign_rhs1_ptr (stmt);
+         enum tree_code stmt_code = gimple_assign_rhs_code (stmt);
+         bool leading_conversion = (CONVERT_EXPR_CODE_P (stmt_code)
+                                    && (i == 1 || i == path.length () - 1));
+         if ((stmt_code != code && !leading_conversion)
              /* We can only handle the final value in epilogue
                 generation for reduction chains.  */
              || (i != 1 && !has_single_use (gimple_assign_lhs (stmt))))
            is_slp_reduc = false;
-         stmt_vec_info stmt_info = loop_info->lookup_stmt (stmt);
-         STMT_VINFO_REDUC_IDX (stmt_info)
-           = path[i].second->use - gimple_assign_rhs1_ptr (stmt);
+         /* For reduction chains we support a trailing/leading
+            conversions.  We do not store those in the actual chain.  */
+         if (leading_conversion)
+           continue;
          reduc_chain.safe_push (stmt_info);
        }
       if (is_slp_reduc && reduc_chain.length () > 1)
index 9d65471ae70fe5d7db5e5d9ee20b89303af13be3..4b1a231bb6ddf60b4e943fe9066fb87f97a4993a 100644 (file)
@@ -419,6 +419,13 @@ again:
 
       if (first)
        {
+         /* For the swapping logic below force vect_reduction_def
+            for the reduction op in a SLP reduction group.  */
+         if (!STMT_VINFO_DATA_REF (stmt_info)
+             && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
+             && (int)i == STMT_VINFO_REDUC_IDX (stmt_info)
+             && def_stmt_info)
+           dt = vect_reduction_def;
          oprnd_info->first_dt = dt;
          oprnd_info->first_op_type = TREE_TYPE (oprnd);
        }
@@ -2041,7 +2048,8 @@ vect_analyze_slp_instance (vec_info *vinfo,
       /* Mark the first element of the reduction chain as reduction to properly
         transform the node.  In the reduction analysis phase only the last
         element of the chain is marked as reduction.  */
-      STMT_VINFO_DEF_TYPE (stmt_info) = vect_reduction_def;
+      STMT_VINFO_DEF_TYPE (stmt_info)
+       = STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
       STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
        = STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
     }
@@ -2071,6 +2079,34 @@ vect_analyze_slp_instance (vec_info *vinfo,
   delete bst_map;
   if (node != NULL)
     {
+      /* If this is a reduction chain with a conversion in front
+         amend the SLP tree with a node for that.  */
+      if (!dr
+         && REDUC_GROUP_FIRST_ELEMENT (stmt_info)
+         && STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def)
+       {
+         /* Get at the conversion stmt - we know it's the single use
+            of the last stmt of the reduction chain.  */
+         gimple *tem = vect_orig_stmt (scalar_stmts[group_size - 1])->stmt;
+         use_operand_p use_p;
+         gimple *use_stmt;
+         bool r = single_imm_use (gimple_assign_lhs (tem), &use_p, &use_stmt);
+         gcc_assert (r);
+         next_info = vinfo->lookup_stmt (use_stmt);
+         next_info = vect_stmt_to_vectorize (next_info);
+         scalar_stmts = vNULL;
+         scalar_stmts.create (group_size);
+         for (unsigned i = 0; i < group_size; ++i)
+           scalar_stmts.quick_push (next_info);
+         slp_tree conv = vect_create_new_slp_node (scalar_stmts);
+         SLP_TREE_CHILDREN (conv).quick_push (node);
+         node = conv;
+         /* We also have to fake this conversion stmt as SLP reduction group
+            so we don't have to mess with too much code elsewhere.  */
+         REDUC_GROUP_FIRST_ELEMENT (next_info) = next_info;
+         REDUC_GROUP_NEXT_ELEMENT (next_info) = NULL;
+       }
+
       /* Calculate the unrolling factor based on the smallest type.  */
       poly_uint64 unrolling_factor
        = calculate_unrolling_factor (max_nunits, group_size);