optimization/5738: GCSE missed optimization

Dan Nicolaescu dann@godzilla.ICS.UCI.EDU
Wed Apr 3 10:01:00 GMT 2002


Daniel Berlin <dan@dberlin.org> writes:

  > On 3 Apr 2002 rth@gcc.gnu.org wrote:
  > 
  > > Synopsis: GCSE missed optimization
  > > 
  > > State-Changed-From-To: open->closed
  > > State-Changed-By: rth
  > > State-Changed-When: Wed Apr  3 02:25:09 2002
  > > State-Changed-Why:
  > >     That's not how partial redundancy elimination (PRE) works.
  > >     The object with PRE is to minimize the number of evaluations
  > >     of an expression *along a path*. 
  > 
  > Please don't close this PR, it's correct.

I want to add one more data point to this: the cfg-branch does a
little better on this testcase, it finds some of the common code on
the 2 branches of the if, but not all of it. 

struct foo { unsigned short * p;};

unsigned short
foo (struct foo *s, unsigned long *coord, _Bool delta)
{
  unsigned short change;
  if (delta) {
    change = *((s->p)++);
    coord +=  change;
    return change;
  } else {
    change = *((s->p)++);
    coord +=  change; 
    coord += *((s)->p++) <<  8;
    return change;
  }
}

the generated SPARC assembly for "foo" is: 

CVS HEAD gcc -O2                   cfg-branch gcc -O2
foo:                               foo:
        !#PROLOGUE# 0                      !#PROLOGUE# 0
        !#PROLOGUE# 1                      save    %sp, -112, %sp  
        andcc   %o2, 0xff, %g0             !#PROLOGUE# 1
        be      .LL2                       andcc   %i2, 0xff, %g0
        mov     %o0, %o3                   be      .LL2
        ld      [%o0], %o0                 mov     %i0, %i3
        lduh    [%o0], %o2                 ld      [%i0], %i0
        add     %o0, 2, %o0                b       .LL4
        sll     %o2, 16, %o1               add     %i0, 2, %i2
        st      %o0, [%o3]         .LL2:
        b       .LL1                       ld      [%i0], %i0
        srl     %o1, 16, %o0               add     %i0, 4, %i2
.LL2:                              .LL4:
        ld      [%o0], %o0                 lduh    [%i0], %i1
        lduh    [%o0], %o2                 st      %i2, [%i3]
        add     %o0, 4, %o1                sll     %i1, 16, %i1
        st      %o1, [%o3]                 srl     %i1, 16, %i0
        mov     %o2, %o0                   ret
.LL1:                                      restore
        retl                       
        nop                        


the function "foo" above should be roughly simplified to:

unsigned short
bar (struct foo *s, unsigned long *coord, _Bool delta)
{
  unsigned short change;
  change = *((s->p)++);
  coord +=  change;
  if (delta)
    ;
  else 
    coord += *((s)->p++) <<  8;
  return change;
}

bar:
        !#PROLOGUE# 0
        !#PROLOGUE# 1
        ld      [%o0], %o1
        mov     %o0, %o3
        lduh    [%o1], %o0
        andcc   %o2, 0xff, %g0
        add     %o1, 2, %o1
        sll     %o0, 16, %o0
        st      %o1, [%o3]
        srl     %o0, 16, %o0
        bne     .LL6
        add     %o1, 2, %o2
        st      %o2, [%o3]
.LL6:
        retl
        nop



More information about the Gcc-bugs mailing list