------- Comment #5 from rguenth at gcc dot gnu dot org  2007-07-09 15:00 -------
Note that we don't hoist the i*4 or the addition to p to help addressing mode
selection which likes to see the "whole" address.

Of course it shouldn't matter in which form we see the addresses and the same
code should be generated for all, still canonicalization to the same form
makes a difference.

In fact, canonicalizing to

  unsigned int D.1656;

<bb 2>:
  D.1656 = i * 4;
  return (*(p + (D.1656 + 8)) + *(p + (D.1656 + 4))) + *(p + (D.1656 + 12));

as you suggest creates worse assembly (look at the extra shift)

foo:
        pushl   %ebp
        movl    %esp, %ebp
        movl    12(%ebp), %ecx
        movl    8(%ebp), %edx
        popl    %ebp
        sall    $2, %ecx
        movl    8(%ecx,%edx), %eax
        addl    4(%ecx,%edx), %eax
        addl    12(%ecx,%edx), %eax
        ret

in fact the above shows that the proper fix would be in the backend (if
there is anything to fix) and making sure we consistently canonicalize
is good enough.  Consider the related testcase

int foo(int *p, short *q, char *r, unsigned int i)
{
  return p[i + 1] + q[i + 1] + r[i + 1];
}

which in one case is canonicalized to

  unsigned int D.1658;

<bb 2>:
  D.1658 = i + 1;
  return ((int) *(r + D.1658) + *(p + D.1658 * 4)) + (int) *(q + D.1658 * 2);

in the other to

  return ((int) *(r + (i + 1)) + *(p + (i * 4 + 4))) + (int) *(q + (i * 2 +
2));

so there is no form that is clearly better to canonicalize to.  But the
correct "form" depends on the context (whether it is profitable to either
CSE i * 4 or i + 1).


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32698

Reply via email to