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