https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94524
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Both the tree-vect-patterns.c and tree-vect-generic.c code contains the same. Except that the latter which handles modulo with a VECTOR_CST divisor, where we properly divide by the absolute value, but when computing the modulo, we actually use the original VECTOR_CST to multiply again. So, --- gcc/tree-vect-generic.c.jj 2020-01-12 11:54:38.518381650 +0100 +++ gcc/tree-vect-generic.c 2020-04-08 09:02:56.465316469 +0200 @@ -478,6 +478,7 @@ expand_vector_divmod (gimple_stmt_iterat { bool use_pow2 = true; bool has_vector_shift = true; + bool use_abs_op1 = false; int mode = -1, this_mode; int pre_shift = -1, post_shift; unsigned int nunits = nunits_for_known_piecewise_op (type); @@ -618,7 +619,10 @@ expand_vector_divmod (gimple_stmt_iterat /* n rem d = n rem -d */ if (code == TRUNC_MOD_EXPR && d < 0) - d = abs_d; + { + d = abs_d; + use_abs_op1 = true; + } else if (abs_d == HOST_WIDE_INT_1U << (prec - 1)) { /* This case is not handled correctly below. */ @@ -899,6 +903,23 @@ expand_vector_divmod (gimple_stmt_iterat if (op == unknown_optab || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) return NULL_TREE; + if (use_abs_op1) + { + tree_vector_builder elts; + if (!elts.new_unary_operation (type, op1, false)) + return NULL_TREE; + unsigned int count = elts.encoded_nelts (); + for (unsigned int i = 0; i < count; ++i) + { + tree elem1 = VECTOR_CST_ELT (op1, i); + + tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1); + if (elt == NULL_TREE) + return NULL_TREE; + elts.quick_push (elt); + } + op1 = elts.build (); + } tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1); op = optab_for_tree_code (MINUS_EXPR, type, optab_default); if (op == unknown_optab should fix this (the last hunk because const_binop apparently doesn't handle ABS_EXPR on VECTOR_CST :(, and it is probably not appropriate time to add it now). That said, I'll need to verify also what we do for modulo with the signed minimum divisor (either all elts or just one).