Skip to content

Compare against signed minimum/signed maximum by checking for overflow #159578

@Kmeakin

Description

@Kmeakin

Instead of comparing against the constant, which may take more instructions (AArch64) or more bytes to encode (x86_64), add/subtract 1 and check for overflow:

https://godbolt.org/z/1scGEndG1

#include <limits>

template <typename T, typename V>
auto add_with_overflow(T x, V y) -> bool {
    T sum;
    return __builtin_add_overflow(x, y, &sum);
}

auto src1(int x) { return x == std::numeric_limits<int>::max(); }
auto tgt1(int x) { return add_with_overflow(x, 1); }

auto src2(int x) { return x == std::numeric_limits<int>::min(); }
auto tgt2(int x) { return add_with_overflow(x, -1); }

auto src3(long x) { return x == std::numeric_limits<long>::max(); }
auto tgt3(long x) { return add_with_overflow(x, 1); }

auto src4(long x) { return x == std::numeric_limits<long>::min(); }
auto tgt4(long x) { return add_with_overflow(x, -1); }

Assembly (AArch64)

src1(int):
        mov     w1, 2147483647
        cmp     w0, w1
        cset    w0, eq
        ret
tgt1(int):
        cmn     w0, 1
        cset    w0, vs
        ret
src2(int):
        mov     w1, -2147483648
        cmp     w0, w1
        cset    w0, eq
        ret
tgt2(int):
        cmp     w0, #1
        cset    w0, vs
        ret
src3(long):
        mov     x1, 9223372036854775807
        cmp     x0, x1
        cset    w0, eq
        ret
tgt3(long):
        cmn     x0, 1
        cset    w0, vs
        ret
src4(long):
        mov     x1, -9223372036854775808
        cmp     x0, x1
        cset    w0, eq
        ret
tgt4(long):
        cmp     x0, #1
        cset    w0, vs
        ret

Assembly (x86_64)

"src1(int)":
        cmp     edi, 2147483647
        sete    al
        ret
"tgt1(int)":
        add     edi, 1
        seto    al
        ret
"src2(int)":
        cmp     edi, -2147483648
        sete    al
        ret
"tgt2(int)":
        add     edi, -1
        seto    al
        ret
"src3(long)":
        movabs  rax, 9223372036854775807
        cmp     rdi, rax
        sete    al
        ret
"tgt3(long)":
        add     rdi, 1
        seto    al
        ret
"src4(long)":
        movabs  rax, -9223372036854775808
        cmp     rdi, rax
        sete    al
        ret
"tgt4(long)":
        add     rdi, -1
        seto    al
        ret

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