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

            Bug ID: 128514
           Summary: wrong code at -O2: vectorizer bit-field lowering
                    ignores reverse storage order since r13-3219
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jeffchen006 at gmail dot com
  Target Milestone: ---
            Target: x86_64-pc-linux-gnu

int printf(const char *, ...);

#pragma scalar_storage_order big-endian
struct S {
  unsigned b : 5;
};
#pragma scalar_storage_order default

struct S a[16];
unsigned char c[16][3];

int main(void)
{
  for (int i = 0; i < 16; i++)
    c[i][0] = i + 1;
  for (int i = 0; i < 16; i++) {
    c[i][1] = c[i][2] = 0;
    a[i ^ 1].b = c[i ^ 1][0];
  }
  printf("%u\n", a[15].b);
  return 0;
}

$ gcc -O0 t.c && ./a.out
16
$ gcc -O2 t.c && ./a.out
2

Expected 16: a[15].b gets c[15][0] = 16, which fits in 5 bits.

Cause: to vectorize the loop, if-conversion changes the bit-field store into a
read-modify-write of the whole word (bitfields_to_lower_p and get_bitfield_rep
in tree-if-conv.cc). The bit position is correct only for the native byte
order, not for a big-endian struct. Loop vectorization then fails, but
basic-block SLP vectorizes the if-converted copy, so the wrong code stays.

First bad commit: r13-3219-g25413fdb2ac (vectorization of bit-field accesses).
Correct on 12.5. Wrong on 13.4, 14.3, 15.2, 16.2 and trunk.
Avoided by: -fno-tree-loop-vectorize.

UBSan and ASan are clean at -O0.
gcc version 17.0.0 20261029 (experimental), r17-5747-g85867b0c935,
x86_64-pc-linux-gnu

Reply via email to