This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/17481] New: Dead temporaries saved across function calls
- From: "benoitsevigny at hotmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 14 Sep 2004 17:14:22 -0000
- Subject: [Bug c++/17481] New: Dead temporaries saved across function calls
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
When optimizing, GCC needlessly saves dead temporary aggregates on the stack
across function calls.
The following code illustrates the case:
typedef float pod;
struct aggregate {
pod p;
inline aggregate()
{
}
inline aggregate(pod q) : p(q)
{
}
inline aggregate(const aggregate &a) : p(a.p)
{
}
inline aggregate &operator=(const aggregate &a)
{
p = a.p;
return *this;
}
};
inline aggregate operator+(const aggregate &a, const aggregate &b)
{
return aggregate(a.p + b.p);
}
inline aggregate operator*(const aggregate &a, const aggregate &b)
{
return aggregate(a.p * b.p);
}
#ifdef INLINE_FCALL
inline aggregate fcall(const aggregate &a)
{
return a;
}
#else
__attribute__((noinline)) aggregate fcall(const aggregate &a)
{
return a;
}
#endif
aggregate test(const aggregate &a, const aggregate &b, const aggregate &c)
{
aggregate d;
{
// expression generating temporaries
d = a*(b + c) + b*(c + a) + c*(a + b);
}
// dead temporaries are saved on the stack when fcall is not inlined
return fcall(d);
}
int main(int argc, const char *argv[])
{
aggregate a(1), b(2), c(3);
aggregate d = test(a, b, c);
return 0;
}
In the test() function, several temporaries are created in order to evaluate
the expression. When compiled with: gcc -O3 -DINLINE_FCALL -S, the fcall
function is integrated in its caller (resulting in no function call) and the
optimizer does a very good job at assigning temporaries to machine registers:
__Z4testRK9aggregateS1_S1_:
pushl %ebp
movl %esp, %ebp
subl $152, %esp # unused stack space
movl %ebx, -4(%ebp)
movl 20(%ebp), %ecx
movl 12(%ebp), %ebx
movl 16(%ebp), %edx
movl 8(%ebp), %eax
flds (%ebx)
flds (%ecx)
fadds (%edx)
fxch %st(1)
fadds (%ecx)
fxch %st(1)
fmuls (%ebx)
fxch %st(1)
fmuls (%edx)
faddp %st, %st(1)
flds (%edx)
fadds (%ebx)
fmuls (%ecx)
faddp %st, %st(1)
fstps (%eax)
movl -4(%ebp), %ebx
movl %ebp, %esp
popl %ebp
ret $4
However, when fcall is not inlined, (gcc -O3 -S), all temporaries are saved on
the stack even though they are no longer used (their scope is not even visible
to the call site), resulting in lots of dead stores:
__Z4testRK9aggregateS1_S1_:
pushl %ebp
movl %esp, %ebp
pushl %esi
leal -24(%ebp), %esi
pushl %ebx
subl $160, %esp
movl 20(%ebp), %ecx
movl 16(%ebp), %eax
movl 12(%ebp), %edx
movl 8(%ebp), %ebx
flds (%ecx)
fadds (%eax)
-> fsts -88(%ebp)
flds (%edx)
fmulp %st, %st(1)
-> fsts -72(%ebp)
flds (%edx)
fadds (%ecx)
-> fsts -120(%ebp)
fmuls (%eax)
fadd %st, %st(1)
-> fstps -104(%ebp)
-> fsts -56(%ebp)
flds (%eax)
fadds (%edx)
-> fsts -152(%ebp)
fmuls (%ecx)
movl %esi, 4(%esp)
movl %ebx, (%esp)
fadd %st, %st(1)
-> fstps -136(%ebp)
-> fsts -40(%ebp)
fstps -24(%ebp)
call __Z5fcallRK9aggregate
subl $4, %esp
movl %ebx, %eax
leal -8(%ebp), %esp
popl %ebx
popl %esi
popl %ebp
ret $4
I have seen the same problem with other basic types (including simd builtin
types) on several other targets (notably Apple's ppc port and Sony's mips5900
port). So when encapsulating a basic type into a structure, the optimizer
misses lots of optimization opportunities anytime a function call happens in a
function using temporaries, even when they are no longer used. Not only this
results in lots of dead stores, but it also consumes the equivalent amount of
stack space (each temporary is assigned a distinct stack slot).
Interesting note: even when there are no function calls, stack space is still
allocated for temporaries even though they never transit to memory (as we can
see in the first assembly output).
--
Summary: Dead temporaries saved across function calls
Product: gcc
Version: 3.3.1
Status: UNCONFIRMED
Severity: enhancement
Priority: P2
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: benoitsevigny at hotmail dot com
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: i686-pc-cygwin
GCC host triplet: i686-pc-cygwin
GCC target triplet: i686-pc-cygwin
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17481