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

            Bug ID: 89195
           Summary: [7/8/9 regression] Corrupted stack offset after
                    combine
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wilco at gcc dot gnu.org
  Target Milestone: ---

The following testcase generates incorrect stack offsets on AArch64 since GCC7
when compiled with -O1 -mbig-endian:

struct S {
   unsigned i : 24;
};

volatile unsigned char x;

int f (struct S d) 
{
  return d.i & x;
}

This produces:

        sub     sp, sp, #16
        str     x0, [sp, 8]
        adrp    x0, x
        ldrb    w0, [x0, #:lo12:x]
        and     w0, w0, 255
        mov     x1, 2305843009213693952
        add     x1, sp, x1
        ldr     w1, [x1, 7]
        and     w0, w1, w0
        add     sp, sp, 16
        ret

The combine output is as follows:

Trying 10, 11 -> 12:
   10: r100:SI=[sfp:DI-0x8]
   11: r101:SI#0=zero_extract(r100:SI#0,0x18,0x8)
      REG_DEAD r100:SI
   12: r98:SI=r101:SI&r92:SI
      REG_DEAD r101:SI
      REG_DEAD r92:SI
Failed to match this instruction:
(set (reg:SI 98)
    (and:SI (mem/c:SI (plus:DI (reg/f:DI 64 sfp)
                (const_int 2305843009213693943 [0x1ffffffffffffff7])) [1
dD.3407+2305843009213693951 S4 A8])
        (reg:SI 92 [ x.0_3+-3 ])))
Successfully matched this instruction:
(set (reg:SI 101)
    (mem/c:SI (plus:DI (reg/f:DI 64 sfp)
            (const_int 2305843009213693943 [0x1ffffffffffffff7])) [1
dD.3407+2305843009213693951 S4 A8]))
Successfully matched this instruction:
(set (reg:SI 98)
    (and:SI (reg:SI 101)
        (reg:SI 92 [ x.0_3+-3 ])))
allowing combination of insns 10, 11 and 12
original costs 16 + 4 + 4 = 24
replacement costs 16 + 4 = 20
deferring deletion of insn with uid = 10.
modifying insn i2    11: r101:SI=[sfp:DI+0x1ffffffffffffff7]
deferring rescan insn with uid = 11.
modifying insn i3    12: r98:SI=r101:SI&r92:SI
      REG_DEAD r92:SI
      REG_DEAD r101:SI
deferring rescan insn with uid = 12.


So it appears to want to change the offset -8 to -7 to optimize the zero-extend
away (this is an out-of-bound access, but maybe OK for locals?). It must be
converting a bit offset to a byte offset using an unsigned shift, losing the
top 3 bits, which results in a wildly out of range offset...

Reply via email to