C++ functional programming optimization on GCC 3.2
AWLaFramboise@aol.com
AWLaFramboise@aol.com
Tue Nov 26 13:01:00 GMT 2002
Hello,
I've made an unfortunate discovery recently regarding GCC's optimization of
functional-style constructs in C++. Apparently, when templated function
objects (in the style of the C++ standard library) are inlined, a bunch of
instructions manipulating the 'this' pointer (that actually have no effect)
remain. In addition, much more stack space is allocated than is actually
needed.
This overhead can have a cost that far exceeds the cost of the actual code.
In some situations, this overhead seems unacceptably high when speed
is important.
$ gcc -v
Reading specs from c:/mingw/bin/../lib/gcc-lib/mingw32/3.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as
--host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads
--disable-nls --enable-languages=f77,c++,objc,ada
--disable-win32-registry --disable-shared
Thread model: win32
gcc version 3.2 (mingw special 20020817-1)
binutils version 2.13
Options used to compile: -O3 -fomit-frame-pointer -maccumulate-outgoing-args
-march=pentium
testcase:
--begin--
int f(void);
void g(int);
template<typename predicate> class noop_t {
public:
inline explicit noop_t(const predicate &p)
: pred(p) {
}
inline noop_t(const noop_t &n)
: pred(n.pred) {
}
inline int operator()() const {
return pred();
}
private:
const predicate &pred;
};
template<typename predicate> inline noop_t<predicate>
noop(const predicate &pred) {
return noop_t<predicate>(pred);
}
void x() {
g(noop(noop(noop(noop(noop(noop(noop(noop(noop(f)))))))))());
}
--eof--
With the above options, the above compiles x() to this:
--begin--
__Z1xv:
LFB1:
sub esp, 172
LCFI0:
lea ecx, [esp+32] # this
lea eax, [esp+48] # this
lea edx, [esp+16] # this
mov DWORD PTR [esp+48], ecx # <variable>.pred, this
mov DWORD PTR [esp+64], eax # <variable>.pred, this
lea ecx, [esp+64] # this
lea eax, [esp+80] # this
mov DWORD PTR [esp+32], edx # <variable>.pred, this
mov DWORD PTR [esp+80], ecx # <variable>.pred, this
mov DWORD PTR [esp+96], eax # <variable>.pred, this
lea ecx, [esp+96] # this
lea edx, [esp+128] # this
lea eax, [esp+112] # this
mov DWORD PTR [esp+112], ecx # <variable>.pred, this
mov DWORD PTR [esp+144], edx # <variable>.pred, this
mov DWORD PTR [esp+128], eax # <variable>.pred, this
mov DWORD PTR [esp+16], OFFSET FLAT:__Z1fv # <variable>.pred
call __Z1fv
mov DWORD PTR [esp], eax # <anonymous>
call __Z1gi
add esp, 172
ret
--eof--
Note all of the instructions between 'sub' and 'call' can be removed without
altering the result of this code.
As an interesting aside, a commercial compiler I tried generated a sequence
of 'this' manipulations that was hundreds of instructions long, even on
full optimization. Apparently this is not a problem unique to GCC.
I am have only vague familiarity with GCC internals, but shouldn't one of the
optimization passes be removing these instructions which have no effect?
Is there some set of compile flags--or perhaps code modifications--that I can
use to cause these extra 'this' manipulations to be emitted?
Thanks,
Aaron W. LaFramboise
awlaframboise@aol.com
More information about the Gcc
mailing list