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

            Bug ID: 127862
           Summary: VEC_PERM_EXPR merge patterns mishandle permutes whose
                    inputs and result differ in length (ICE with svld1rq +
                    svrev, wrong code)
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code, wrong-code
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: igor at tachyum dot com
                CC: rguenth at gcc dot gnu.org
  Target Milestone: ---
            Target: aarch64-*-*, x86_64-*-*

Created attachment 65818
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65818&action=edit
vec-perm-merge-sve.c

This is in the same family as PR123175 and PR123573: a VEC_PERM_EXPR with a
constant selector may have inputs and a result with different numbers of
elements, but the match.pd patterns that merge two consecutive
VEC_PERM_EXPRs, and is_combined_permutation_identity in forwprop, still
assume that both permutes and all their inputs have the same number of
elements.

Seen on trunk r17 at e1cf6f306d9 (20261012), on aarch64 (cross compiler)
and x86_64-pc-linux-gnu; 16.2.1 on x86_64 fails the same way.

A) aarch64, plain C (vec-perm-merge-sve.c).  svld1rq folds to a permute
   from a 128-bit vector to the SVE vector, and a following permute of that
   gets merged into it:

   svint32_t
   f1 (int32_t *p)
   {
     svint32_t c = svld1rq_s32 (svptrue_b8 (), p);
     return svrev_s32 (c);
   }

   $ gcc -O2 -march=armv8.2-a+sve -msve-vector-bits=256 vec-perm-merge-sve.c
   error: vectors with different element number found in 'vec_perm_expr'
   vector(4) int
   vector(4) int
   vector(4) int
   vector(8) ssizetype
   _1 = VEC_PERM_EXPR <_6, _6, { 3, 2, 1, 0, 3, 2, 1, 0 }>;
   error: conversion of register to a different size in 'view_convert_expr'
   VIEW_CONVERT_EXPR<svint32_t>(_1);
   _5 = VIEW_CONVERT_EXPR<svint32_t>(_1);
   during GIMPLE pass: forwprop
   internal compiler error: verify_gimple failed

   Same with -msve-vector-bits=512, and with svzip1/svuzp1/svuzp2/svtrn2 in
   place of svrev, with c as one or both operands.  With -fno-checking (so
   presumably with a release compiler):
     f1: compiles; the 128-bit permute result is stored to the stack and
         reloaded as a 256-bit vector, so the upper half is garbage.
     f2 (svzip1 (x, c)): internal compiler error: in expand_vec_perm_const,
         at optabs.cc:6896 (during RTL pass: expand)
   vec-perm-merge-sve-run.c is a runtime test (svrev (c) and
   svtrn2 (c, x)); built with -O2 -msve-vector-bits=256 -fno-checking it
   aborts under qemu-aarch64 with a 256-bit vector length, for each of its
   two functions on its own.  It passes at -O0.

B) Target independent, GIMPLE FE (vec-perm-merge-{1,2,3}.c, tested on
   x86_64).  These cover the other direction, inputs wider than the result,
   which I could not get from plain C on x86_64 since
   ix86_vectorize_vec_perm_const rejects vmode != op_mode.  All three pass
   at -O0.

1) vec-perm-merge-1.c: d = VEC_PERM <c, c>, c = VEC_PERM <a, b>, d narrower
   than c.

     c_ = __VEC_PERM (a_, b_, _Literal (v8si) { 8, 0, 9, 1, 10, 2, 11, 3 });
     d_ = __VEC_PERM (c_, c_, _Literal (v4si) { 1, 2, 3, 4 });

   The pattern builds the merged selector with d's element count as the
   number of elements per input and gives the new permute a's type:

   $ gcc -O1 -fgimple vec-perm-merge-1.c
   vec-perm-merge-1.c:20:1: error: vectors with different element number found
in 'vec_perm_expr'
   vector(8) int
   v8si
   v8si
   v4si
   _7 = VEC_PERM_EXPR <b__3, b__3, { 0, 1, 1, 2 }>;
   vec-perm-merge-1.c:20:1: error: conversion of register to a different size
in 'view_convert_expr'
   VIEW_CONVERT_EXPR<v4si>(_7);
   d__5 = VIEW_CONVERT_EXPR<v4si>(_7);
   during GIMPLE pass: forwprop
   vec-perm-merge-1.c:20:1: internal compiler error: verify_gimple failed

   The selector is wrong as well ({ a0, b1, a1, b2 } is expected, the result
   uses only b).  With -fno-checking, or a release compiler:
     -O1:         wrong code, the test aborts
     -O2 -mavx2:  internal compiler error: in ix86_vectorize_vec_perm_const,
                  at config/i386/i386-expand.cc:27393 (during RTL pass: expand)

2) vec-perm-merge-2.c: d = VEC_PERM <x, c>, c = VEC_PERM <a, b>, d narrower
   than c.  Silent wrong code at -O1 and above, also with checking enabled.

     c_ = __VEC_PERM (a_, b_, _Literal (v8si) { 7, 6, 5, 4, 8, 9, 10, 11 });
     d_ = __VEC_PERM (x_, c_, _Literal (v4si) { 0, 9, 7, 11 });

   forwprop1 turns this into

     d__6 = VEC_PERM_EXPR <x__4, x__4, { 0, 6, 7, 4 }>;

   so the lanes that should come from c (a6 and a4) are taken from x.  The
   <c, x> variant of the pattern has the same problem.

3) vec-perm-merge-3.c: d = VEC_PERM <c, c>, c = VEC_PERM <a, b>, c narrower
   than a and b.

     c_ = __VEC_PERM (a_, b_, _Literal (v2hi) { 7, 6 });
     d_ = __VEC_PERM (c_, c_, _Literal (v2hi) { 1, 2 });

   $ gcc -O1 -fgimple vec-perm-merge-3.c
   vec-perm-merge-3.c:20:1: error: vectors with different element number found
in 'vec_perm_expr'
   vector(4) short int
   v4hi
   v4hi
   v2hi
   _7 = VEC_PERM_EXPR <b__3, b__3, { 2, 3 }>;
   ...
   vec-perm-merge-3.c:20:1: internal compiler error: verify_gimple failed

   With -fno-checking: internal compiler error: in
   ix86_vectorize_vec_perm_const, at config/i386/i386-expand.cc:27393
   (during GIMPLE pass: veclower2).

   This one also has a second bug behind the first.  With the match.pd
   pattern fixed, simplify_permutation in forwprop sees the pair first;
   is_combined_permutation_identity reduces the composed selector by the
   length of c instead of the length of b, takes { 7, 6 } o { 1, 2 } for an
   identity on b, and replaces the V2HI result by the V4HI input
   ("error: non-trivial conversion in 'ssa_name'").  With other selectors
   the same path ICEs in fold_vec_perm, at fold-const.cc:10668.

I have a patch for the three match.pd patterns and for forwprop and will
post it to gcc-patches.

Reply via email to