[Bug target/126550] New: RISC-V: auto-vectorization miscompiles duplicated deinterleave store via vcompress/vrgather (rv64gcv_zvl256b)

mail--- via Gcc-bugs <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126550

            Bug ID: 126550
           Summary: RISC-V: auto-vectorization miscompiles duplicated
                    deinterleave store via vcompress/vrgather
                    (rv64gcv_zvl256b)
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: [email protected]
  Target Milestone: ---

Created attachment 65195
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65195&action=edit
preprocessed file triggering the bug

At `-O3` for a RISC-V target with `zvl256b` GCC miscompiles a loop that stores
each source pair into two adjacent 2-element `uint16_t` fields of a 12-byte
struct (a duplicate deinterleave, `dst[k] = {first, second, first, second}`).

The loop is compiled to a `vcompress.vm` / `vrgather.vv` combination that
reads only every 4th source pair and broadcasts it across four destinations.
Element 1 of the result wrongly receives `src[0]` instead of `src[1]`.

The source is well-defined C (no UB: `-fsanitize=address,undefined` is clean,
`-fno-strict-aliasing -fwrapv` makes no difference).

wrong code:
  riscv64-unknown-elf-gcc -O3 -march=rv64gcv_zvl256b -mabi=lp64d bug.c -o bug

correct:
  riscv64-unknown-elf-gcc -O3 -fno-tree-vectorize -march=rv64gcv_zvl256b
-mabi=lp64d bug.c -o bug
  riscv64-unknown-elf-gcc -O3 -march=rv64gcv -mabi=lp64d bug.c -o bug # VLEN
not fixed


```
$ riscv64-unknown-elf-gcc -O3 -march=rv64gcv_zvl256b -mabi=lp64d bug.c -o bug
$ qemu-riscv64 -cpu rv64,v=true,vlen=256 ./bug
FAIL at 1: got {7,123,7,123} want {2661,40626,2661,40626}
$ spike --isa=rv64gcbv_zvl256b pk ./bug
FAIL at 1: got {7,123,7,123} want {2661,40626,2661,40626}
```

Tested with qemu-riscv64 8.2.2 and spike (riscv-isa-sim) commit
`3d8eb089bd289c59dcb506f197a172e02beb7b5b` (1.1.1-dev).

Compiled with the gcc from riscv-collab/riscv-gnu-toolchain most current
nightly July 15, 2026:
$ riscv64-unknown-elf-gcc -v
Target: riscv64-unknown-elf
Configured with:
/home/runner/work/riscv-gnu-toolchain/riscv-gnu-toolchain/gcc/configure
--target=riscv64-unknown-elf --prefix=/mnt/riscv --disable-shared
--disable-threads --enable-languages=c,c++ --with-pkgversion=g6afcc4f6d
--with-system-zlib --enable-tls --with-newlib
--with-sysroot=/mnt/riscv/riscv64-unknown-elf
--with-native-system-header-dir=/include --disable-libmudflap --disable-libssp
--disable-libquadmath --disable-libgomp --disable-nls
--disable-tm-clone-registry --src=.././gcc --disable-multilib --with-abi=lp64d
--with-arch=rv64gc --with-isa-spec=20191213
--with-specs='%{!mcmodel*:-mcmodel=medlow}' 'CFLAGS_FOR_TARGET=-Os   
-mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os    -mcmodel=medlow'
gcc version 16.1.0 (g6afcc4f6d)


$ cat bug.c#include <stdint.h>
#include <stdio.h>

struct Pair { uint16_t first, second; };
struct S { uint16_t a[2], b[2]; uint32_t r; };

__attribute__((noipa))
void load(struct S *dst, const struct Pair *src, unsigned long n)
{
  for (unsigned long k = 0; k < n; k++) {
    dst[k].a[0] = src[k].first;
    dst[k].a[1] = src[k].second;
    dst[k].b[0] = src[k].first;
    dst[k].b[1] = src[k].second;
  }
}

#define N 40
static struct Pair src[N];
static struct S    out[N];

int main(void)
{
  for (unsigned i = 0; i < N; i++) {
    src[i].first = (uint16_t)(i * 2u + 1);
    src[i].second = (uint16_t)(i * 3u + 2);
  }
  load(out, src, N);

  for (unsigned i = 0; i < N; i++) {
    uint16_t f = src[i].first, s = src[i].second;
    if (out[i].a[0] != f || out[i].a[1] != s ||
      out[i].b[0] != f || out[i].b[1] != s) {
      printf("FAIL at %u: got {%u,%u,%u,%u} want {%u,%u,%u,%u}\n",
        i, out[i].a[0], out[i].a[1], out[i].b[0], out[i].b[1], f, s, f, s);
      return 1;
    }
  }
  printf("OK\n");
  return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.