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

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Marc Glisse from comment #0)
> For most comparisons @ we do optimize (i<=>0)@0 to just i@0, but not for >
> and <=. Spaceship operator<=> is very painful to use, but I expect we will
> end up seeing a lot of it with C++20, and comparing its result with 0 is
> almost the only way to use its output, so it seems important to optimize
> this common case.

Maybe even common enough to transform it in the FE.


(In reply to Victor Khimenko from comment #2)
> Note that gcc looks bad even on the example from Microsoft's blog post:
> 
> https://godbolt.org/z/Jc7TcN


Right, this doesn't only affect (i<=>0)@0 but also (i<=>j)@0 which is very
common, because it's what the FE synthesizes for operator@ when the type only
defines operator<=>


https://godbolt.org/z/19dM8PdaM

#include <compare> 

struct X
{
    int i = 0;
    auto operator<=>(const X&) const = default;
};

bool lt(X l, X r) { return l<r; }

struct Y
{
    int i = 0;
    bool operator<(Y rhs) const { return i < rhs.i; }
};

bool lt(Y l, Y r) { return l<r; }

Defining <=> once is easier than defining all of < > <= >= but the code is bad:

lt(X, X):
        xor     eax, eax
        cmp     edi, esi
        je      .L2
        setge   al
        lea     eax, [rax-1+rax]
.L2:
        shr     al, 7
        ret
lt(Y, Y):
        cmp     edi, esi
        setl    al
        ret

It seems like it should be possible for the FE to recognize that in this
trivial case the defaulted <=> is just comparing integers, and therefore the
synthesized op< could be transformed from (l.i <=> r.i) < 0 to simply l.i < r.i

The FE is not required to synthesize exactly (l.i<=>r.i) @ 0 as long as the
result is correct, so l.i @ r.i would be OK (and avoids the poor codegen until
the missed-optimization gets done).

Reply via email to