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]

Question regarding struct return optimization in plain old C with gcc


Hi folks!

Using gcc (tested version 4.9.2-10 from Debian official repo, on x86-64 architecture), the following function, taking an hypothetical structure and returning it after modifying a member, is correctly inlined, but the stack use somehow grows when using it:

static __inline__ struct foo add_flag_0(struct foo foo, int flag) {
	foo.flags |= flag;
	return foo;
}

If you call twice the function or more (ie. add_flag_0(add_flag_0(...))), then the stack usage continues to grow linearly.

Here's a complete demonstration of the issue:

#define INLINE __inline__
// Note: using __attribute__((const)) does not help

struct foo {
	int flags;
	/* Let it be enough NOT to be packed in registers */
	void *opaque[2];
};

static INLINE struct foo new_foo() {
	struct foo foo = { 0 };
	return foo;
}

static INLINE struct foo add_flag_0(struct foo foo, int flag) {
	foo.flags |= flag;
	return foo;
}

extern void some_unknown_function(struct foo foo);

void demo_1(void) {
	some_unknown_function(new_foo());
}

void demo_2(void) {
	some_unknown_function(add_flag_0(new_foo(), 1));
}

void demo_3(void) {
	some_unknown_function(add_flag_0(add_flag_0(new_foo(), 1), 2));
}

void demo_4(void) {
	some_unknown_function(add_flag_0(add_flag_0(add_flag_0(new_foo(), 1), 2), 3));
}

$ gcc -S -W -Wall -O3 demo.c -o demo.S

You can see the differences in size of the used stack for the four functions:

$ grep -E "addq.*rsp" /tmp/demo.S
	addq    $104, %rsp
	addq    $136, %rsp
	addq    $200, %rsp
	addq    $264, %rsp

And for example the difference between the demo_1 and demo_2 functions:

demo_1:
	subq    $80, %rsp
	pushq   $0
	pushq   $0
	pushq   $0
	call    some_unknown_function
	addq    $104, %rsp
	ret

demo_2:
	subq    $112, %rsp
	movq    $0, 72(%rsp)
	movl    $1, 72(%rsp)
	pushq   $0
	pushq   $0
	pushq   88(%rsp)
	call    some_unknown_function
	addq    $136, %rsp
	ret

My understanding is that the four functions should ideally have the same stack usage. Is this expectation absurd for some kind of conformance/calling convention/temporary struct issue somewhere ? (please forgive my total lack of expertise on the optimization internals)

Thanks in advance for any clues!

Regards,

Xavier


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