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).