https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127989
Bug ID: 127989
Summary: [16/17 Regression] volatile 32-bit load folded into a
compare is narrowed to lhu on MIPS
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: [email protected]
Target Milestone: ---
Target: mipsel-none-elf
Same class as PR125180, on MIPS: with -ffuse-ops-with-volatile-access (now on
by
default) a volatile 32-bit load whose low half feeds a compare is emitted as a
16-bit lhu. On a memory-mapped register the access width is part of the
semantics: this one is a PlayStation GPU readback FIFO port, and a halfword
read
does not return the pixel. The PR125180 fix only touches the i386 splitters, so
16.2.0 still does it here. -fno-fuse-ops-with-volatile-access restores lw.
typedef unsigned int u32; typedef unsigned short u16;
int pass;
#define R (*(volatile u32 *)0x1f801810)
static inline __attribute__((always_inline)) u16 rp(void) { u32 w = R; return w
& 0xffff; }
void A(int want) { if (rp() == (want ? 0x001f : 0x7c00)) pass++; }
void C(void) { if (rp() == 0x7c00) pass++; }
$ mipsel-none-elf-gcc -Os -march=mips1 -S -o - repro.c
gcc 16.2.0, function A: lhu $3,6160($2)
gcc 16.2.0, function C: lw $2,6160($2)
gcc 16.2.0 -fno-fuse-ops-with-volatile-access, A and C: lw
gcc 15.2.0: lw in both
Compiler Explorer (mips gcc 16.1 vs 15.2): https://godbolt.org/z/nzfPe89qG
Only the select of two constants (A) narrows; a single constant compare (C)
keeps the full load.