https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126200

--- Comment #3 from WANG Xuerui <xen0n at gentoo dot org> ---
Dumped pr126200.c.280r.fwprop1:

(insn 7 3 11 2 (set (reg:V16QI 81 [ <retval> ])
        (vec_select:V16QI (reg/v:V16QI 82 [ in ])
            (parallel [
                    (const_int 1 [0x1])
                    (const_int 3 [0x3])
                    (const_int 5 [0x5])
                    (const_int 7 [0x7])
                    (const_int 9 [0x9])
                    (const_int 11 [0xb])
                    (const_int 13 [0xd])
                    (const_int 15 [0xf])
                    (const_int 1 [0x1])
                    (const_int 3 [0x3])
                    (const_int 5 [0x5])
                    (const_int 7 [0x7])
                    (const_int 9 [0x9])
                    (const_int 11 [0xb])
                    (const_int 13 [0xd])
                    (const_int 15 [0xf])
                ])))
"../../gcc/testsuite/gcc.target/loongarch/vector/lsx/pr126200.c":10:10 1322
{lsx_vshuf4i_b}
     (nil))

This is wrong -- this shuffle pattern cannot be realized by a single vshuf4i.b
insn. Looking at loongarch_const_vector_shuffle_set_p in loongarch.cc:

  /* Check if we have the same 4-element sets.  */
  for (j = 0; j < nsets; j++, set = 4 * j)
    for (i = 0; i < 4; i++)
      if ((INTVAL (XVECEXP (op, 0, i))
          != (INTVAL (XVECEXP (op, 0, set + i)) - set))
         || !IN_RANGE (INTVAL (XVECEXP (op, 0, set + i)), 0, set + 3))
        return false;

The code was copied from mips/mips.cc and the IN_RANGE check is buggy: should
check if the value falls between *set* and (set + 3). Weird thing is I tried
this change but the bug didn't disappear; I had to rewrite the function to
derive the expected vshuf4i control word from the first group of 4, and then
compare the remaining groups with it.

Reply via email to