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).

Reply via email to