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

--- Comment #9 from ptomsich at gcc dot gnu.org ---
(In reply to Andreas Schwab from comment #7)
> This is no longer reproducible since r17-4001-gbbc2517fe41307, but I think
> it just went dormant.

This is the same defect as PR126412, and the patch posted there fixes it:
https://gcc.gnu.org/pipermail/gcc-patches/2026-September/730012.html

Reduced testcase, no LTO, fails at -O2 on powerpc64le-linux-gnu:

  __attribute__ ((noipa)) void
  f (char *base, char *base2, long t, long long k)
  {
    long t2 = t + 28;
    char *p = base + t2;
    char *q = base2 + t2;
    *(long long *) (p + 2) = k;
    q[1] = (char) k;
    p[3] = (char) k;
  }

fold-mem-offsets groups its changes by the register defined by the last fold
insn of each root's def-chain, and zeroes a fold insn's constant once the group
that reached it commits.  Here the two byte stores reach the "t + 28" add
directly while the long long store reaches it through a further add, so they
land in different groups.  The byte stores commit and zero the constant; the
long long store is refused, because its folded displacement would be 30 and std
is DS-form, and the rollback leaves it addressing without the 28:

  trunk -O2:                        with the PR126412 patch:
      add 3,3,5                         addi 5,5,28
      add 4,4,5                         add 3,3,5
      addi 9,3,2                        add 4,4,5
      std 6,0(9)    <- base+t+2         addi 9,3,2
      stb 6,29(4)                       std 6,0(9)   <- base+t+30
      stb 6,31(3)                       stb 6,1(4)
                                        stb 6,3(3)

Verified under qemu, on a cross built from trunk 826a52902ec: FAIL at -O2, -O3
and -Os, PASS with -fno-fold-mem-offsets, PASS at -O2 and -O3 with the patch
applied to the same tree. 

Note that it always passes on aarch64 (the unscaled form admits the
displacement) so it doesn't reproduce there.

Reply via email to