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++/70171] New: Poor code generated when return struct using ternary operator


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.

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