https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94006

            Bug ID: 94006
           Summary: Poor codegen for cond ? lval1 : lval2
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

I noticed that this (compiled with -std=c++2a and any optimization level except
-O0):

#include <compare>

std::strong_ordering f1(int a, int b)
{
  return a == b ? std::strong_ordering::equal
   : std::strong_ordering::less;
}

compiles to:

_Z2f1ii:
        cmp     edi, esi
        jne     .L3
        mov     al, BYTE PTR _ZNSt15strong_ordering5equalE[rip]
        ret
.L3:
        mov     al, BYTE PTR _ZNSt15strong_ordering4lessE[rip]
        ret
_ZNSt15strong_ordering5equalE:
        .zero   1
_ZNSt15strong_ordering4lessE:
        .byte   -1


Whereas this less readable form:

#include <compare>

std::strong_ordering f2(int a, int b)
{
  return (a == b) <=> true;
}

produces much smaller code:

_Z2f2ii:
        cmp     edi, esi
        setne   al
        neg     eax
        ret


Jason observed that it seems to be because the result of <=> is a prvalue,
whereas the ?: version is returning from lvalues.

We get similar codegen (but with a less extreme difference in size) for this:

struct A { int i; };
constexpr A a1 { 1 };
constexpr A a2 { 0 };

A f1 (int a, int b)
{
  return a == b ? a1 : a2;
}

A f2 (int a, int b)
{
  return A{a == b ? a1.i : a2.i};
}

The first function is obviously easier to read, but the second produces smaller
code because the two global variables are not emitted.

Reply via email to