As of August 2022, there still does not seem to be a way to write code for which a compiler will generate a PEXT
instruction.
However, at this point (C++20), you can call many functions in <bit>
that wrap assembly code.
In general, you can get a compiler to generate assembly instructions, where supported, for all functions in TBM
/BMI
and for BZHI
from BMI2
, which all can be described with simple expressions.
PDEP
is non-trivial and has the same complexity as PDEP
, with multiple possible implementations. So, neither seem straightforward for an optimizer to recognize.
The ABM
instructions, POPCNT
and LZCNT
are also non-trivial, and implementations could not be recognized. Fortunately, we have std::popcount
and std::countl_zero
, respectively, which can map directly to the corresponding instruction (where the hardware supports it).
It would seem that PEXT
and PDEP
will likely be similarly supported before the time compilers can infer that an instruction can replace the algorithm.
Now that C++ is officially two's compliment, it would be nice to see both arithmetic and logical shift right wrapped so that one could explicitly use them on signed or unsigned, as required.
As far as PEXT implementations go, here's a variation that might compare favorably to TemplateRex's (Matthew Fioravante's) version at https://stackoverflow.com/a/21159523/2963099
template <typename Integral>
constexpr Integral extract_bits(Integral x, Integral mask) {
Integral res=0;
int bb=1;
do {
Integral lsb=mask & -mask;
mask &= ~lsb;
bool isset=x & lsb;
res |= isset ? bb : 0;
bb+=bb;
} while (mask);
return res;
}
You can compare them both on Compiler Explorer at https://godbolt.org/z/3h9WrYqxT
Mostly this breaks out the least significant byte (lsb
) to remove it from mask
, and test against x
It is safe to run through once with mask === 0
. (lsb
will be 0, so isset
is false
). Using a do while
is much more efficient except for that trivial case.
Using the ternary operator is mostly stylist since, to me, it is a stronger hint of the intent to generate a cmove