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