Xref: utzoo comp.lang.c:12328 comp.arch:6236 Path: utzoo!utgpu!water!watmath!clyde!att!alberta!ubc-cs!van-bc!sl From: sl@van-bc.UUCP (pri=-10 Stuart Lynne) Newsgroups: comp.lang.c,comp.arch Subject: Re: Loop unfolding Message-ID: <1867@van-bc.UUCP> Date: 2 Sep 88 09:30:04 GMT References: <5612@june.cs.washington.edu> Reply-To: sl@van-bc.UUCP (pri=-10 Stuart Lynne) Organization: Wimsey Associates, Vancouver, BC. Lines: 51 In article <5612@june.cs.washington.edu> rik@june.cs.washington.edu (Rik Littlefield) writes: >All of the examples of loop unfolding recently discussed on the net have >implemented just copying. Several authors have suggested improving on >the loop unfolding method by using a (pseudo-) standard routine like >'memcpy', or by declaring large structures that the compiler can generate >good code for moving. > >I have seen at least three cases where loop unfolding was very productive >but neither of the above suggestions seems to apply. All were in time- >critical production applications. In the original Macintosh SCSI driver I was able to go from 3:1 interleave on the SCSI disks to 2:1 simply by replacing Apple's SCSI manager with a block copy with an unrolled loop, similiar to the Duff Device (only in 68000 asm). A recent example from a device driver. By unrolling the loop to check which device had produced the interrupt we achieved the following: - could use absolute memory addresses instead of a variable - saved time not having to save a register to store the address - saved time not having to load the address into the var - no loop control variables required - no need to allocate a register, init or test it - loop overhead eliminated The compiled code actually turned out to be almost the same size as the orignal looped implementation, but significantly faster. int (*cdsvint[4])() = { XXXXINT, XXXMINT, XXXFRINT, XXXEINT }; cdsintr( achan ) { register int intvec; intvec = RMSPC( SUNBASE2+4, RWR2 ); /* required, grab intvec here */ if ( (RMSPC( SUNBASE2, RWR0 ) & INTPEND ) ) { /* check pending */ (*cdsvint[(intvec >> 2)&0x3])( intvec&CHANA?2:3 ); WMSPC( SUNBASE2, RWR0, EOIRST ); /* End of Interrupt Service */ return( 1 ); } intvec = RMSPC( SUNBASE+4, RWR2 ); /* required, grab intvec here */ if ( (RMSPC( SUNBASE, RWR0 ) & INTPEND ) ) { /* check pending */ (*cdsvint[(intvec >> 2)&0x3])( intvec&CHANA?0:1 ); WMSPC( SUNBASE, RWR0, EOIRST ); /* End of Interrupt Service */ return( 1 ); } return( 0 ); } -- Stuart.Lynne@wimsey.bc.ca {ubc-cs,uunet}!van-bc!sl Vancouver,BC,604-937-7532