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

--- Comment #9 from Konstantinos Eleftheriou <konstantinos.eleftheriou at vrull 
dot eu> ---
Hi David, thanks for reporting. I reproduced this and there seems to
be an issue with our cancellation logic.

Several globals are reached off one anchor base:
  r0 = r7 + 976.

r0 feeds three memory access roots: g_13+4 at [r0,#4], g_253 at [r0,#32],
and g_590 through a second add r3 = r0 + 32, at [r3,#-8] / [r3,#-4].

g_590 folds fine to [r7,#1000] / [r7,#1004], and doing so zeroes the
constants in both r3 = r0 + 32 and the shared r0 = r7 + 976, leaving
r0 == r7. g_253 is the one that can't be folded: it would need
ldrsb [r0,#1008], and 1008 is outside LDRSB's +/-255 range, so recog
rejects it and its group is cancelled.

Dump:

  INSN 376: Memory offset changed from -4 to 1004.
  INSN 631: Constant set to zero.         (r3 = r0 + 32  -> r3 = r0)
  INSN 648: Constant set to zero.         (r0 = r7 + 976 -> r0 = r7)
  INSN 375: Memory offset changed from -8 to 1000. 
  failed to match this instruction:
  (set (reg:SI 0 r0 [orig:114 g_253_lsm.49 ])
      (sign_extend:SI (mem/c:QI (plus:SI (reg:SI 0 r0)
                  (const_int 1008)) [0 g_253+0 S1 A8])))
  Recog/verify: Cannot update INSN 114.

The problem is that the cancellation doesn't undo the zeroing of
r0 = r7 + 976. Changes are grouped by the destination register of the
last fold insn, so g_590 lands under r3 while g_253 and g_13+4 land under
r0; the r0 group is cancelled, but r0 = r7 + 976 was already committed as
part of the r3 group and stays zeroed. The g_13+4 update is dropped along
with the group too, even though [r0,#4] -> [r7,#980] would have been fine.

So r0 ends up as r7 while those two roots keep their old offsets:

  g_13+4   [r0,#4]  -> [r7,#4]      (should be [r7,#980])
  g_253    [r0,#32] -> [r7,#32]     (should be [r7,#1008])

g_13 is the value being checked, so the result comes out wrong.

Reply via email to