restrict leaving byte copies unoptimized

Dan Dickerman dan09@trueindiemedia.com
Wed Mar 17 23:48:00 GMT 2010


I'm trying to clean-up some code which does not currently take advantage of 
the possible optimizations of the __restrict__ qualifier. Using gcc with the 
Xcode-bundled tools on OSX for PPC, gcc versions 4.0.1 and 4.2.1, I can see 
the differences of strict-aliasing if I use (4-byte) words to copy from one 
place to another, but not when using byte pointers.

I've attached the over-simplified test-case demonstrate this issue. I can't 
help but think I'm missing something obvious, but it basically boils-down to 
this: the setup starts with a pair of (unsigned char*) and declares restricted 
pointers of the right type, which for words is:

#define SRC w_src
#define DST w_dst
         uint32       * __restrict__ w_dst = d;
         uint32 const * __restrict__ w_src = s;

It then copies through these pointers with a series of:
#define COPY_WORD(dst,src,i)    \
         *(dst+((i)/4)) = *(src+((i)/4));

=== This macro is called in an unrolled loop with i=0, 4, 8, 12...

With general optimizations on (-O3 -fgcse-sm) this produces code which gets 
flagged (by Shark) as producing stalls, as the register loads need to wait for 
memory before proceeding with the corresponding stores:
	...
         lwz r0,4(r2)
         stw r0,4(r9)
         lwz r11,8(r2)
         stw r11,8(r9)
         lwz r0,12(r2)
         stw r0,12(r9)
         lwz r11,16(r2)
         stw r11,16(r9)
	...


If the option -fstrict-aliasing is added to the list to take advantage of the 
__restrict__ qualifier, it re-orders the instructions as I expect, so the 
loads fill the registers before proceeding with the stores...
	...
         lwz r3,32(r2)
         lwz r29,36(r2)
         lwz r28,40(r2)
         lwz r27,44(r2)
         lwz r26,48(r2)
         lwz r25,52(r2)
         lwz r24,56(r2)
         lwz r23,60(r2)
         lwz r22,64(r2)
         stwx r11,r12,r21
         stw r10,4(r9)
         add r12,r12,r19
         stw r0,8(r9)
         stw r8,12(r9)
         stw r7,16(r9)
         stw r6,20(r9)
	...

When the code is changed to use byte pointers (which would seem the simpler 
case, avoiding the incompatible pointer type warnings, for starters), the 
loads/stores get padded with nops and -fstrict-aliasing appears to have no 
effect. The C level changes look like:

#define SRC b_src
#define DST b_dst
         uchar       * __restrict__ b_dst = d;
         uchar const * __restrict__ b_src = s;

#define COPY_WORD(dst,src,i)    \
         *(dst+(i  )) = *(src+(i  )); \
         *(dst+(i+1)) = *(src+(i+1)); \
         *(dst+(i+2)) = *(src+(i+2)); \
         *(dst+(i+3)) = *(src+(i+3));


The compiled code, optimized as above is:
	...
         lbz r0,1(r2)
         stb r0,1(r9)
         nop
         nop
         lbz r11,2(r2)
         stb r11,2(r9)
         nop
         nop
         lbz r0,3(r2)
         stb r0,3(r9)
         nop
         nop
         lbz r11,4(r2)
         stb r11,4(r9)
         nop
         nop
	...

Can someone suggest where the nops are coming from and how I can encourage gcc 
to re-order the loads/stores as is done for words to streamline this code a 
bit? As a related note, is Shark making a valid complaint about the stalls 
this code produces, or can I sleep comfortably knowing that the cache will 
simply make all these memory references into single-cycle instructions anyway?
--
   Dan Dickerman
-------------- next part --------------
A non-text attachment was scrubbed...
Name: restrictMe.tgz
Type: application/x-gzip
Size: 1225 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-help/attachments/20100317/bffdc60c/attachment.bin>


More information about the Gcc-help mailing list