It seems that _BitScanReverse, despite being an intrinsic and not a real function, can't be called in a constexpr function in Visual C++. I'm aware that I can implement this operation myself in a much slower way, which would be fine for the case where it's evaluated at compile-time but it's unfortunate that it wouldn't just be the 1-clock-cycle, single CPU instruction (BSR) for the case where it's evaluated at run-time. I haven't tried __builtin_clz in GCC/Clang yet, but it might or might not have the same sort of issue, and I want this code to work across the major compilers, (with a slow fallback for non-GCC, non-Clang, non-VC compilers).
Ideas/Questions:
Is there an easy way to have a function use one block of code when evaluating at compile-time, so that it can be constexpr-safe, and a different block of code for run-time, so that it can be fast? (If so, this would also be relevant to a few other questions I have.)
Alternatively, is there a way to trick the compiler into being able to evaluate _BitScanReverse for constexpr code?
Side question:
Is there any word of plans to eventually add this to the C++ standard? They've added std::log2 and std::ilogb, but those both go through floating-point numbers, instead of just doing one BSR, (or CLZ and a subtraction on ARM chips).
__builtin_constant_p
. Unfortunately, I don't know whether msvc has a similar construct. – Gottfried_BitScanForward
as the reason, and they had equivalent functions using__builtin_clz
on GCC, so I figured they're probably okay for constexpr. However, it wasn't explicitly stated there, and they removed constexpr from those functions as well, but possibly just for self-consistency across compilers. – Sunkfoo.leading_zeros()
for primitive types likei32
. It's disappointing that C and C++ haven't kept up and still don't have standard bit-scan or popcnt functions. There's POSIXffs()
find first set (man7.org/linux/man-pages/man3/ffs.3.html), but it's just POSIX not ISO C or C++. Some compilers do recognize certain idioms, so you can sometimes write what looks like a dumb loop and have it compile to apopcnt
instruction, but IDK about bit-scan. – Alaniz__builtin_clz
is accepted in aconstexpr
function in gcc, with no warning even with-Wextra -Wpedantic
. godbolt.org/g/6cai3A. – Alaniz__builtin_clz
! I might try out that website you linked to for other things, if it's free to try. Regarding the C/C++ standards, I've been there so many times. I'm particularly disappointed that the Javascript standard is going to add SSE-like support before C or C++, though at least GCC added support for the Intel standard intrinsics for SSE instructions a few years ago, so that Visual C++ and GCC can use the same intrinsics there. – Sunk__restrict__
, which ISO C++ doesn't have, even though C has had it since C99. – Alanizint __attribute__(( vector_size(16) ))
). But there is already OpenMP (#pragma omp simd
before a loop) to ask explicitly for auto-vectorization (without having to use-ffast-math
). – Alanizadc
which has been available since before 1980 for x86. – Consumerism