rust-lang/rust

Make `wrapping_neg` and `overflowing_neg` functions into `const`

Lokathor opened this issue · 3 comments

With the merge of #57234, we can now make wrapping_neg and overflowing_neg into const as well. They are currently branching, but with a small amount of bit math you can make it branchless instead.

Basic formulas given here, along with some tests: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6a800d9c97885c1aba464ea3103c86e6

(Issue filed per the general request of @Centril to seek and const all possible const targets)

cc @SimonSapin

(I have no opinions on whether this is feasible to do branchless and w/o control flow, seems like something that needs to be perf tested to not regress non-CTFE...)

There appears to be the same performance once you go through optimization (with 1.31, and on x86_64, I didn't check every single target). The overflowing versions are slightly different, but the wrapping versions are the exact same.

https://godbolt.org/z/IWJ2ev

example::CORE_wrapping_neg_u8:
        neg     dil
        mov     eax, edi
        ret

example::NEW_wrapping_neg_u8:
        neg     dil
        mov     eax, edi
        ret

example::CORE_wrapping_neg_i8:
        neg     dil
        mov     eax, edi
        ret

example::NEW_wrapping_neg_i8:
        neg     dil
        mov     eax, edi
        ret

This was done in #58044.