This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
I'm currently trying to track down why gcc is generating this poor code when optimising memset with constant params. A helping hand would be greatly appreciated.
Consider the following code: char a[8]
int main (void)
{
__builtin_memset (a, 0, 8);
}This will result in two simple stores of the value 0 into two adjacent 32bit values in memory on at least darwin-powerpc and linux-i686. Great!
Next try: char a[8]
int main (void)
{
__builtin_memset (a, 1, 8);
}will result in:
pushl %ebp
movl $16843009, %eax
movl %esp, %ebp
subl $8, %esp
movl $16843009, %edx
andl $-16, %esp
movl %eax, a+4
subl $16, %esp
movl %edx, a
leave
reton linux-i686 compiled with gcc-3.4 -c -march=i686 -mtune=i686 -O2. Let's call that in interesting result.
_main:
lis r3,ha16(L_a$non_lazy_ptr)
li r4,1
li r5,8
lwz r3,lo16(L_a$non_lazy_ptr)(r3)
b L_memset$stub
.comm _a,8
.data
.section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16
.align 4
L_memset$stub:
.indirect_symbol _memset
lis r11,ha16(L_memset$lazy_ptr)
lwzu r12,lo16(L_memset$lazy_ptr)(r11)
mtctr r12
bctr
.data
.lazy_symbol_pointer
L_memset$lazy_ptr:
.indirect_symbol _memset
.long dyld_stub_binding_helper
.data
.non_lazy_symbol_pointer
L_a$non_lazy_ptr:
.indirect_symbol _a
.long 0
.subsections_via_symbols
And it keeps getting worse: char a[12]
int main (void)
{
__builtin_memset (a, 0, 12);
}aforementioned gcc call on i686 will result in:
main:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
pushl %edi
cld
subl $4, %esp
movl $a, %edi
movl $3, %ecx
andl $-16, %esp
subl $16, %esp
rep
stosl
movl -4(%ebp), %edi
leave
retThe rep;stosl sequence seems somewhat okay to me for a simply inline sequence to clear a larger or only at runtime known amount of memory, however for under 16 bytes this seems like a clear loss in performance and code size to me.
On darwin-powerpc we get the same sequence as above except for the to-be-written value and the amount which is a clear lose no matter what in this case.
There are several facts known in this case which should help to generate much better code: - The allocated memory is local and not volatile - The destination of the store is unused - The alignment and size of the storage - The destination memory is a (possibly large) block instead of scattered locations - The parameters to the memset call are all constant
In addition to the poor code on i686 the results on darwin-powerpc are really abysmal because we there seems to be no way to force the inlining of memset which always means a *very* costly rountrip into the linkage even for obvious uses.
I'm very certain that this pessimizes quite a lot of common applications (including gcc) where a memset is chosen in favor of a loop to clear a block of memory.
I'm currently digging into builtins.c but a helping hand would be more than appreciated.
Servus,
Daniel
Attachment:
PGP.sig
Description: This is a digitally signed message part
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |