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

            Bug ID: 127161
           Summary: [MIPS] cc1 hangs in LRA on indexed loads with a
                    frame-pointer base (-march=octeon2 -O2)
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: orgads at gmail dot com
  Target Milestone: ---

cc1 never terminates compiling this at -O2 for any MIPS target with
the indexed loads enabled (octeon2/octeon3; DSP presumably too).
Reproduces on the 16.2.0 release and on today's trunk. First hit
cross-building xz and strace for an Octeon II board; presumably latent
since the MIPS port switched to LRA — -march=octeon is fine.

```c
int a, b;
char c;
char *d;
void e(int, int, int, int, int, int);
void h() {
  int f;
  unsigned *g = &f;
  for (int j;; ++j) {
    char *i = d - g[j];
    if (i)
      b = 0;
    e(0, a, 1, 1, c, a);
  }
}
```

```
mips64octeon-linux-gnu-gcc -mabi=64 -march=octeon2 -O2 -w -c final.c
```

The essential ingredient is an indexed load from a stack object:
combine forms

```
(insn 16 ... (zero_extend:DI (mem:SI (plus:DI (reg/f:DI 78 $frame)
                                              (reg:DI 212))))
 {*mips_lwux_di_ext})
```

with the soft frame pointer as base. The reg+reg address embedded in
these patterns is not legitimate on MIPS; old reload coped, LRA does
not converge: each iteration spills the index pseudo and reloads it
from a stack slot, growing the frame 16 bytes, which changes the
elimination offsets and forces another pass. The reload dump reaches
assignment sub-pass 9500+ and 30000+ pseudos before being killed; no
LRA iteration guard fires (arguably a second, generic bug — this
should be an ICE, not a hang).

-march=octeon2 -O1/-O0 and -march=octeon/mips64r2 -O2 are ok
(a larger original file hangs at -O1 as well). -mtune is irrelevant
in both directions.

## Proposed patch

Reject FRAME_POINTER_REGNUM/ARG_POINTER_REGNUM in the address
operands of the four indexed-load patterns (mips-dsp.md:
mips_l<size><u>x_ext, mips_l<size>x, *mips_lw<u>x_ext; mips.md:
*lwxs) via a new predicate — see mips-indexed-load-lra.patch.

Verified on trunk: the test case and the original xz/strace files
compile at octeon2/octeon3 -O0..-O3; `p[i]` from a pointer argument
still emits lwux/lbux, and the stack case still becomes
`lwux $2,$2($sp)` via post-RA late_combine, where the base is the
real, non-eliminable $sp. Full DejaGnu testsuite not run (no MIPS
execution environment here).

## gcc -v (release toolchain where first seen)

```
Target: mips64octeon-linux-gnu
Configured with: ../gcc-16.2.0/configure --target=mips64octeon-linux-gnu
  --with-arch=octeon --with-abi=64 --enable-languages=c,c++
  --disable-nls --enable-__cxa_atexit --with-mips-plt
  --disable-libsanitizer --with-static-standard-libraries
gcc version 16.2.0 (GCC)
```

Host: x86_64-pc-linux-gnu, binutils 2.47. Trunk repro: fresh
--disable-bootstrap C-only cross build of master (20260831).

Reply via email to