This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
GCC 3.0.3 produces large code
- From: Nicholas Adrian Vinen <hb at x256 dot org>
- To: <gcc at gcc dot gnu dot org>
- Date: Thu, 31 Jan 2002 05:49:53 -0800 (PST)
- Subject: GCC 3.0.3 produces large code
Hi, I'm the author of a fairly large project which builds in GCC and
Visual C. I noticed that GCC was producing very large files and with a
series of hacks I managed to get the size down, but it's still
considerably larger than Visual C. Here's an example of a function that
doesn't get optimised very well:
#include <stdio.h>
#include <stdlib.h>
class RWL
{
public:
int a;
};
class AutoRWL
{
public:
AutoRWL(RWL* pRWL, int foo)
{
printf("Lock");
m_pRWL = pRWL;
m_foo = foo;
}
~AutoRWL()
{
printf("Unlock");
}
RWL* m_pRWL;
int m_foo;
};
class a
{
public:
int DoOtherThing()
{
return rand();
}
};
class b
{
public:
b() { m_pa = new a; }
~b() { delete m_pa; }
virtual int DoThing()
{
AutoRWL Lock(&m_RWL, 1);
if( m_pa )
return m_pa->DoOtherThing();
else
return 0;
}
virtual int DoThing2()
{
AutoRWL Lock(&m_RWL, 1);
return m_pa ? m_pa->DoOtherThing() : 0;
}
virtual int DoThing3()
{
AutoRWL Lock(&m_RWL, 1);
int ret = 0;
if( m_pa ) ret = m_pa->DoOtherThing();
return ret;
}
a* m_pa;
RWL m_RWL;
};
int main(void)
{
b bb;
return bb.DoThing();
}
This is a disassembly of the three DoThing routines:
08048870 <b::DoThing()>:
8048870: 56 push %esi
8048871: 53 push %ebx
8048872: 83 ec 20 sub $0x20,%esp
8048875: 8b 74 24 2c mov 0x2c(%esp,1),%esi
8048879: 68 a4 89 04 08 push $0x80489a4
804887e: e8 91 fd ff ff call 8048614 <_init+0x98>
8048883: 83 c4 10 add $0x10,%esp
8048886: c7 44 24 0c 01 00 00 movl $0x1,0xc(%esp,1)
804888d: 00
804888e: 8d 5e 08 lea 0x8(%esi),%ebx
8048891: 89 5c 24 08 mov %ebx,0x8(%esp,1)
8048895: 83 7e 04 00 cmpl $0x0,0x4(%esi)
8048899: 74 25 je 80488c0 <b::DoThing()+0x50>
804889b: e8 a4 fd ff ff call 8048644 <_init+0xc8>
80488a0: 83 ec 0c sub $0xc,%esp
80488a3: 89 c3 mov %eax,%ebx
80488a5: 68 a9 89 04 08 push $0x80489a9
80488aa: e8 65 fd ff ff call 8048614 <_init+0x98>
80488af: 83 c4 10 add $0x10,%esp
80488b2: 89 d8 mov %ebx,%eax
80488b4: 83 c4 14 add $0x14,%esp
80488b7: 5b pop %ebx
80488b8: 5e pop %esi
80488b9: c3 ret
80488ba: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
80488c0: 83 ec 0c sub $0xc,%esp
80488c3: 68 a9 89 04 08 push $0x80489a9
80488c8: e8 47 fd ff ff call 8048614 <_init+0x98>
80488cd: 83 c4 10 add $0x10,%esp
80488d0: 31 c0 xor %eax,%eax
80488d2: eb e0 jmp 80488b4 <b::DoThing()+0x44>
80488d4: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
80488da: 8d bf 00 00 00 00 lea 0x0(%edi),%edi
080488e0 <b::DoThing2()>:
80488e0: 56 push %esi
80488e1: 53 push %ebx
80488e2: 83 ec 20 sub $0x20,%esp
80488e5: 8b 74 24 2c mov 0x2c(%esp,1),%esi
80488e9: 68 a4 89 04 08 push $0x80489a4
80488ee: e8 21 fd ff ff call 8048614 <_init+0x98>
80488f3: 83 c4 10 add $0x10,%esp
80488f6: c7 44 24 0c 01 00 00 movl $0x1,0xc(%esp,1)
80488fd: 00
80488fe: 8d 5e 08 lea 0x8(%esi),%ebx
8048901: 89 5c 24 08 mov %ebx,0x8(%esp,1)
8048905: 83 7e 04 00 cmpl $0x0,0x4(%esi)
8048909: 74 1c je 8048927 <b::DoThing2()+0x47>
804890b: e8 34 fd ff ff call 8048644 <_init+0xc8>
8048910: 89 c3 mov %eax,%ebx
8048912: 83 ec 0c sub $0xc,%esp
8048915: 68 a9 89 04 08 push $0x80489a9
804891a: e8 f5 fc ff ff call 8048614 <_init+0x98>
804891f: 83 c4 24 add $0x24,%esp
8048922: 89 d8 mov %ebx,%eax
8048924: 5b pop %ebx
8048925: 5e pop %esi
8048926: c3 ret
8048927: 31 db xor %ebx,%ebx
8048929: eb e7 jmp 8048912 <b::DoThing2()+0x32>
804892b: 90 nop
804892c: 8d 74 26 00 lea 0x0(%esi,1),%esi
08048930 <b::DoThing3()>:
8048930: 56 push %esi
8048931: 53 push %ebx
8048932: 83 ec 20 sub $0x20,%esp
8048935: 8b 74 24 2c mov 0x2c(%esp,1),%esi
8048939: 68 a4 89 04 08 push $0x80489a4
804893e: e8 d1 fc ff ff call 8048614 <_init+0x98>
8048943: 83 c4 10 add $0x10,%esp
8048946: c7 44 24 0c 01 00 00 movl $0x1,0xc(%esp,1)
804894d: 00
804894e: 8d 5e 08 lea 0x8(%esi),%ebx
8048951: 89 5c 24 08 mov %ebx,0x8(%esp,1)
8048955: 31 db xor %ebx,%ebx
8048957: 83 7e 04 00 cmpl $0x0,0x4(%esi)
804895b: 74 07 je 8048964 <b::DoThing3()+0x34>
804895d: e8 e2 fc ff ff call 8048644 <_init+0xc8>
8048962: 89 c3 mov %eax,%ebx
8048964: 83 ec 0c sub $0xc,%esp
8048967: 68 a9 89 04 08 push $0x80489a9
804896c: e8 a3 fc ff ff call 8048614 <_init+0x98>
8048971: 83 c4 24 add $0x24,%esp
8048974: 89 d8 mov %ebx,%eax
8048976: 5b pop %ebx
8048977: 5e pop %esi
8048978: c3 ret
8048979: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
Here are the sizes:
08048930 w F .text 00000049 b::DoThing3()
080488e0 w F .text 0000004b b::DoThing2()
08048870 w F .text 00000064 b::DoThing()
What vexes me is that all three routines do very similar things; in
fact, I have really just done a trivial optimisation by hand in each
case.. but each time this has reduced the code size, in fact quite a lot.
I don't understand why GCC isn't able to do this itself, and I'm still not
sure that the smallest code that I can get it to produce couldn't be made
quite a bit smaller. Here's the commandline by the way:
g++ -Os -fomit-frame-pointer-falign-labels=1 -falign-jumps=1
-fno-exceptions -o test test.cpp
I chose -Os for obvious reasons... the others are also in an attempt to
get file size down. The version, as mentioned in the subject, is 3.0.3.
Can anyone suggest how to make it compile the code any smaller? And
perhaps the people responsible for optimisations might take note of this.
I can understand maybe why the code needs to be so big with -O3, but with
-Os, it seems to me it could be a lot smaller, and really routines like
this benefit most from being small rather than fast (they'll never really
be all that fast). Maybe the compiler can be super-smart about it, and
automatically optimise small functions for size and large functions for
speed?
Anyway, I hope someone can improve the situation a bit.
Thanks,
Nicholas
P.S. Other than code size, GCC 3.0.3 seems great.