Compiling the following code with MSVC
#include <mmintrin.h>
#include <utility>
static auto bit_width(unsigned long x) {
unsigned long i;
_BitScanReverse(&i, x);
++i;
if (x == 0) { i = 0; }
return i;
}
auto foo(unsigned long x) {
__assume(x > 0);
return bit_width(x);
}
auto bar(unsigned long x) {
if (x > 0) {
return bit_width(x);
} else {
std::unreachable(); // implemented as __assume(0) in MSVC
}
}
generates the following, where foo
got optimized and bar
didn't (compiling to the same asm as the general-case function that checks for zero).
bit_width(unsigned long)
bsr eax, ecx
xor edx, edx
inc eax
test ecx, ecx
cmovne edx, eax
mov eax, edx
ret 0
foo(unsigned long) PROC
bsr eax, ecx
inc eax
ret 0
bar(unsigned long) PROC
bsr eax, ecx
xor edx, edx
inc eax
test ecx, ecx
cmovne edx, eax
mov eax, edx
ret 0
MSVC's documentation suggests that __assume(0)
as an "unreachable" assertion should help with optimization, but I can't actually make it do this.
Is it possible to use std::unexpected()
to optimize code such as the above on MSVC? If so, how?
__assume(x>0)
works but isn't portable; Clang has an equivalent __builtin_assume
. These are different from GNU C __builtin_expect(x>0, 1)
which would only hint the compiler that's usually the case, like [[likely]]
, not a promise which can affect correctness.