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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |segher at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Note, in other cases combine is sucessful.  E.g. consider:
struct S { int a, b, c, d; };
struct T { struct S e[16]; struct S f[1024]; } t;

int
foo (unsigned long x)
{
  return t.f[x + 5].a;
}

int
bar (struct T *x, unsigned long y)
{
  return x->f[y + 5].b;
}

On x86_64-linux with -O2, we have before combine in both cases
(idx + 21) << 4 and in foo combine says:
Trying 7, 8 -> 10:
    7: {r87:DI=r91:DI+0x15;clobber flags:CC;}
      REG_DEAD r91:DI
      REG_UNUSED flags:CC
    8: {r88:DI=r87:DI<<0x4;clobber flags:CC;}
      REG_DEAD r87:DI
      REG_UNUSED flags:CC
   10: r90:SI=[r88:DI+`t']
      REG_DEAD r88:DI
Failed to match this instruction:
(set (reg:SI 90 [ t.f[_1].a ])
    (mem:SI (plus:DI (mult:DI (reg:DI 91)
                (const_int 16 [0x10]))
            (const:DI (plus:DI (symbol_ref:DI ("t") [flags 0x2]  <var_decl
0x7f837b94cab0 t>)
                    (const_int 336 [0x150])))) [1 t.f[_1].a+0 S4 A32]))
Successfully matched this instruction:
(set (reg:DI 88)
    (ashift:DI (reg:DI 91)
        (const_int 4 [0x4])))
Successfully matched this instruction:
(set (reg:SI 90 [ t.f[_1].a ])
    (mem:SI (plus:DI (reg:DI 88)
            (const:DI (plus:DI (symbol_ref:DI ("t") [flags 0x2]  <var_decl
0x7f837b94cab0 t>)
                    (const_int 336 [0x150])))) [1 t.f[_1].a+0 S4 A32]))
and it is merged the way we want:
        salq    $4, %rdi
        movl    t+336(%rdi), %eax
while in bar:
Failed to match this instruction:
(set (reg:SI 91 [ x_4(D)->f[_1].b ])
    (mem:SI (plus:DI (plus:DI (mult:DI (reg:DI 93)
                    (const_int 16 [0x10]))
                (reg:DI 92))
            (const_int 340 [0x154])) [1 x_4(D)->f[_1].b+0 S4 A32]))
Failed to match this instruction:
(set (reg:DI 88)
    (plus:DI (ashift:DI (reg:DI 93)
            (const_int 4 [0x4]))
        (reg:DI 92)))
and it is not merged:
        addq    $21, %rsi
        salq    $4, %rsi
        movl    4(%rsi,%rdi), %eax
when it could be:
        salq    $4, %rsi
        movl    340(%rsi,%rdi), %eax

It isn't x86 specific though, e.g. on powerpc64-linux we end up with:
        addi 4,4,21
        sldi 4,4,4
        add 4,3,4
        lwa 3,4(4)
for bar, where I guess:
        sldi 4,4,4
        add 4,3,4
        lwa 3,340(4)
would work too.

Reply via email to