Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions