SUBREG givs - no success yet, sigh.

Toon Moene toon@moene.indiv.nluug.nl
Sat Sep 20 07:02:00 GMT 1997


Do you want to speed up serious Fortran code as compiled with g77  
by a factor of two on Alpha's ?

I knew you would ;-)

OK, now that I have your attention, let me explain the way to get there:

Consider the following simple Fortran subroutine:

      subroutine daxpy(n,da,dx,dy)
      double precision dx(n),dy(n),da
      integer  i,n
      do i = 1, n
        dy(i) = dy(i) + da*dx(i)
      enddo
      end

Compiling with -O2 will lead to no strength reduction at all on an  
Alpha.  On my m68k, strength reduction will remove all index  
calculations, leaving only post-incremented address registers, as  
expected.

The reason is the following difference in generated code before  
loop optimisation (I'm just showing a single address computation):

===== On Alpha:

(insn 36 33 37 (set (subreg:DI (reg:SI 79) 0)
        (plus:DI (reg/v:DI 72)
            (const_int -1))) -1 (nil)
    (nil))

(insn 37 36 40 (set (reg:DI 80)
        (sign_extend:DI (reg:SI 79))) -1 (nil)
    (nil))

(insn 40 37 41 (set (reg:DI 82)
        (ashift:DI (reg:DI 80)
            (const_int 3))) -1 (nil)
    (expr_list:REG_EQUAL (mult:DI (reg:DI 80)
            (const_int 8))
        (nil)))

(insn 41 40 43 (set (reg:DI 83)
        (plus:DI (reg/v/u:DI 71)
            (reg:DI 82))) -1 (nil)
    (nil))

===== On m68k:

(insn 43 41 46 (set (reg:SI 42)
        (plus:SI (reg/v:SI 40)
            (const_int -1))) -1 (nil)
    (nil))

(insn 46 43 47 (set (reg:SI 44)
        (ashift:SI (reg:SI 42)
            (const_int 3))) -1 (nil)
    (expr_list:REG_EQUAL (mult:SI (reg:SI 42)
            (const_int 8))
        (nil)))

(insn 47 46 57 (set (reg:SI 45)
        (plus:SI (reg/v/u:SI 31)
            (reg:SI 44))) -1 (nil)
    (nil))

On the Alpha it is register 72 that's a BIV, on the m68k it is  
register 40.  On the Alpha, strength reduction is ineffective,  
because either simplify_giv_expr or general_induction_var cannot  
detect that (set (reg) (plus (reg) (const)), and (set (subreg) (plus  
(reg) (const)) followed by (set (reg) (sign_extend (subreg)) are  
basically equivalent.

I set out to solve this myself, but after a couple of hours looking  
into this problem and re-re-re-compiling loop.c with different  
trial code [on a machine six time zones away from me], I give up -  
apparently, it's too hard for me. (What I basically did was  
"generalising" the code in basic_induction_var for recognising  
promoted_mode subregs into simplify_giv_expr and  
geneal_induction_var - without any observable effect).

However, if anyone on this list has a good idea that I can try out  
I'm certainly willing to give it another shot.

Thanks in advance,
Toon.



More information about the Gcc mailing list