https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70171
Bug ID: 70171 Summary: Poor code generated when return struct using ternary operator Product: gcc Version: 5.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: sethml at ofb dot net Target Milestone: --- Created attachment 37926 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37926&action=edit Example C++ code. Consider the following code: int int_ternary(int a, int b, bool select) { return select ? a : b; } int int_if(int a, int b, bool select) { if (select) return a; else return b; } struct S { int i; }; S struct_ternary(S a, S b, bool select) { return select ? a : b; } S struct_if(S a, S b, bool select) { if (select) return a; else return b; } G++ 5.3.0 -O2 generates identical code for int_ternary(), int_if(), and struct_if() - for x86-64: testb %dl, %dl movl %esi, %eax cmovne %edi, %eax ret However, for struct_ternary() it generates terrible code which stores a and b into memory locations and then loads one by address: struct_ternary(S, S, bool): leaq -40(%rsp), %rcx testb %dl, %dl movl %edi, -24(%rsp) leaq -24(%rsp), %rax movl %esi, -40(%rsp) cmove %rcx, %rax movl (%rax), %eax ret Compile command: % g++-5 -O2 -S ternary_reference_pessimization.cc % g++-5 --version g++-5 (Homebrew gcc 5.3.0) 5.3.0 This can have a major performance impact when using wrappers around built-in types. For example, I discovered it experimenting with John McFarlane's fixed_point library, which is a candidate for C++ standardization. In particular, calling std::max() on two fixed_point<uint32_t,...> values results in the kind of terrible code demonstrated above. https://github.com/johnmcfarlane/fixed_point/blob/master/doc/p0037r1.md As wrappers around basic types become more common in C++, the performance impact of this problem will get worse.