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.

Reply via email to