The length returned by vect_get_loop_len is REALLEN + BIAS, but was
assumed to be REALLEN - BIAS.  If BIAS is -1, this leads to wrong
code.

Bootstrapped and regtested on s390.  Ok for trunk?

gcc/ChangeLog:

        * tree-vect-loop.cc (vectorizable_live_operation_1): Fix
        load/store bias handling.

gcc/testsuite/ChangeLog:

        * gcc.dg/vect/nodump-extractlast-1.c: New test.

Signed-off-by: Juergen Christ <jchr...@linux.ibm.com>
---
 .../gcc.dg/vect/nodump-extractlast-1.c        | 21 ++++++++++++++++++
 gcc/tree-vect-loop.cc                         | 22 ++++++++++---------
 2 files changed, 33 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/nodump-extractlast-1.c

diff --git a/gcc/testsuite/gcc.dg/vect/nodump-extractlast-1.c 
b/gcc/testsuite/gcc.dg/vect/nodump-extractlast-1.c
new file mode 100644
index 000000000000..980ac3e42188
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/nodump-extractlast-1.c
@@ -0,0 +1,21 @@
+/* Check for a bung in the treatment of LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS when
+   using VEC_EXTRACT.  */
+/* { dg-require-effective-target vect_int } */
+
+char c = 4;
+
+__attribute__((noipa))
+int
+foo ()
+{
+  for ( ; c > 3; c -= 3);
+  return c - 1;
+}
+
+int
+main ()
+{
+  if (foo() != 0)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 3b56f865ec7c..78256904dcea 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -10155,10 +10155,12 @@ vectorizable_live_operation_1 (loop_vec_info 
loop_vinfo, basic_block exit_bb,
     {
       /* Emit:
 
-        SCALAR_RES = VEC_EXTRACT <VEC_LHS, LEN + BIAS - 1>
+        SCALAR_RES = VEC_EXTRACT <VEC_LHS, LEN - (BIAS + 1)>
 
-        where VEC_LHS is the vectorized live-out result and MASK is
-        the loop mask for the final iteration.  */
+        where VEC_LHS is the vectorized live-out result, LEN is the length of
+        the vector, BIAS is the load-store bias.  The bias should not be used
+        at all since we are not using load/store operations, but LEN will be
+        REALLEN + BIAS, so subtract it to get to the correct position.  */
       gcc_assert (SLP_TREE_LANES (slp_node) == 1);
       gimple_seq tem = NULL;
       gimple_stmt_iterator gsi = gsi_last (tem);
@@ -10167,18 +10169,18 @@ vectorizable_live_operation_1 (loop_vec_info 
loop_vinfo, basic_block exit_bb,
                                    1, vectype, 0, 1);
       gimple_seq_add_seq (&stmts, tem);
 
-      /* BIAS - 1.  */
+      /* BIAS + 1.  */
       signed char biasval = LOOP_VINFO_PARTIAL_LOAD_STORE_BIAS (loop_vinfo);
-      tree bias_minus_one
-       = int_const_binop (MINUS_EXPR,
+      tree bias_plus_one
+       = int_const_binop (PLUS_EXPR,
                           build_int_cst (TREE_TYPE (len), biasval),
                           build_one_cst (TREE_TYPE (len)));
 
-      /* LAST_INDEX = LEN + (BIAS - 1).  */
-      tree last_index = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (len),
-                                    len, bias_minus_one);
+      /* LAST_INDEX = LEN - (BIAS + 1).  */
+      tree last_index = gimple_build (&stmts, MINUS_EXPR, TREE_TYPE (len),
+                                    len, bias_plus_one);
 
-      /* SCALAR_RES = VEC_EXTRACT <VEC_LHS, LEN + BIAS - 1>.  */
+      /* SCALAR_RES = VEC_EXTRACT <VEC_LHS, LEN - (BIAS + 1)>.  */
       tree scalar_res
        = gimple_build (&stmts, CFN_VEC_EXTRACT, TREE_TYPE (vectype),
                        vec_lhs_phi, last_index);
-- 
2.43.7

Reply via email to