https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70782
Bug ID: 70782
Summary: zero-initialized union returned by value generates
useless stores/loads to the stack
Product: gcc
Version: 5.2.1
Status: UNCONFIRMED
Severity: enhancement
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: jhaberman at gmail dot com
Target Milestone: ---
Test case:
--
#include <string.h>
typedef union {
char ch;
float fl;
double dbl;
} u;
u f(const void *p, int type) {
u v;
memset(&v, 0, 8);
if (type == 1) {
memcpy(&v, p, 1);
} else if (type <= 5) {
memcpy(&v, p, 4);
} else if (type <= 8) {
memcpy(&v, p, 8);
}
return v;
}
--
With gcc 5.2.1 on Ubuntu, compiled with -O3 -fno-stack-protect I get:
--
0000000000000000 <f>:
0: 83 fe 01 cmp esi,0x1
3: 48 c7 44 24 e8 00 00 mov QWORD PTR [rsp-0x18],0x0
a: 00 00
c: 74 32 je 40 <f+0x40>
e: 83 fe 05 cmp esi,0x5
11: 7e 1d jle 30 <f+0x30>
13: 83 fe 08 cmp esi,0x8
16: 7f 08 jg 20 <f+0x20>
18: 48 8b 07 mov rax,QWORD PTR [rdi]
1b: 48 89 44 24 e8 mov QWORD PTR [rsp-0x18],rax
20: 48 8b 44 24 e8 mov rax,QWORD PTR [rsp-0x18]
25: c3 ret
26: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
2d: 00 00 00
30: 8b 07 mov eax,DWORD PTR [rdi]
32: 89 44 24 e8 mov DWORD PTR [rsp-0x18],eax
36: 48 8b 44 24 e8 mov rax,QWORD PTR [rsp-0x18]
3b: c3 ret
3c: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
40: 0f b6 07 movzx eax,BYTE PTR [rdi]
43: 88 44 24 e8 mov BYTE PTR [rsp-0x18],al
47: 48 8b 44 24 e8 mov rax,QWORD PTR [rsp-0x18]
4c: c3 ret
--
In every code path it saves the read value to the stack, only to read it back.
None of these operations are actually necessary, since the code is already
zeroing the other parts of rax. This function shouldn't need to use any stack
space at all.