This is the mail archive of the gcc-bugs@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]

[Bug c++/17481] New: Dead temporaries saved across function calls


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]