Skip to content

[X86] Recognize Clang's <=> code pattern #60012

Closed
@scottmcm

Description

@scottmcm

Today, this code https://cpp.godbolt.org/z/e8q15zzK1

#include <compare>
std::strong_ordering cmp(int a, int b) {
    return a <=> b;
}

gives this select chain

define dso_local i8 @_Z3cmpii(i32 noundef %0, i32 noundef %1) local_unnamed_addr #0 {
  %3 = icmp slt i32 %0, %1
  %4 = select i1 %3, i8 -1, i8 1
  %5 = icmp eq i32 %0, %1
  %6 = select i1 %5, i8 0, i8 %4
  ret i8 %6
}

which compiles to some pretty verbose assembly:

cmp(int, int):                               # @cmp(int, int)
        cmp     edi, esi
        setl    al
        neg     al
        or      al, 1
        xor     ecx, ecx
        cmp     edi, esi
        movzx   eax, al
        cmove   eax, ecx
        ret

There are other ways of doing this that are definitely better for size, and plausibly better for speed too https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign

For example, it could be

cmp(int, int):                               # @cmp(int, int)
        cmp     edi, esi
        setg    al
        setl    cl
        sub     al, cl
        ret

(I've filed this as x86-specific because the selects in LLVM-IR might be better for optimizations to use, as more obvious than the subtraction. The specific pattern that Clang emits for <=> is most important, but it would be nice if it also recognized -- or canonicalized in IR -- the bunch of equivalent select chains.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions