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

--- Comment #17 from ptomsich at gcc dot gnu.org ---
In my view, we are compounding multiple discussions here:

1. A frontend "defect" (or: "Why the match.pd Change Is Correct")

The C frontend's pointer_int_sum  applies a premature distributive-law
optimization when computing array subscripts. For a[j - 1] where the index
expression is j + (-1), it
  distributes the sizeof(int) multiplication through the addition:

  a[j - 1]  →  *(a + (ulong)j * 4 + (-4))        // distributed form
  a[k]      →  *(a + (ulong)(j - 1) * 4)          // factored form  (k = j - 1)

Richard identified this in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109393#c3: the premature
distribution in pointer_int_sum produces two structurally different GIMPLE
representations for the same address, and "this kind of stuff shouldn't be done
by the frontends these days."

The factored form (cast(X + C)) * S is the canonical GIMPLE form for
array-index arithmetic. The match.pd pattern added by the PR109393 fix
correctly re-factors the distributed form back to canonical:

  (A * B) + (-C)  →  (B - C/A) * A    when C is a multiple of A

This transforms (ulong)j * 4 + (-4) into ((ulong)j + (-1)) * 4, restoring the
factored form. The patch is correct and should not be reverted — it compensates
for a frontend deficiency that Richard explicitly called out.

2. The Residual Asymmetry (or: Why func1 and func2 differ..)

The problem is that FRE can prove this equivalence in only one direction,
depending on which form it encounters first.

func2 fails because the statements appear in the opposite order of func1.

3. The x86 backend might not be entirely innocent?

x86-64 has "[base + index*scale + displacement]" (SIB ... I had to look the
term up!) encoding that handles all three components in a single instruction.
The distributed form "a + j*4 + (-4)" maps directly. The factored form "a + (j
- 1)*4" requires computing "j - 1" first.


AArch64 does not have a "[base + index*scale + displacement]" addressing mode.
This is the same cost as any alternative — the factored form is natural for
AArch64. No regression.

Looking at "ix86_legitimize_address" (I didn't expect that I'd ever have to
poke around there), has logic for "PLUS(MULT, PLUS)", but not for
"MULT(PLUS(reg, const), scale)".

My guess is that adding some distrubution logic to "ix86_legitimize_address"
(to handle "PLUS(base, MULT(PLUS(reg, const), scale))") 


So no, don't revert the fix. It is correct.

Reply via email to