5 ms·
My favorite thing about these is how they come full circle - programmers find convoluted ways to outsmart the compiler in some primitive operation, but then CPU
by jsheard 6y ago
My favorite thing about these is how they come full circle - programmers find convoluted ways to outsmart the compiler in some primitive operation, but then CPU manufacturers add dedicated instructions for those operations, and eventually the compilers outsmart the programmer by deleting their smartass method and emitting a single instruction instead
https://godbolt.org/z/nPdrcz https://godbolt.org/z/nPdrcz
- ncmncm 6y agoThis of course refers to the POPCNT instruction, that is still quite tricky to get compilers to generate reliably, and which RISC-V specifications and all implementations to date mysteriously lack. Compilers failing to generate POPCNT cause sometimes 10x slowdowns in key operations.
- jsheard 6y agoIndeed it's better to use intrinsics in new code rather than rely on compiler magic https://godbolt.org/z/n3z8nz https://godbolt.org/z/n3z8nz Portability is an issue though, that works on GCC/Clang but you need a different intrinsic for MSVC
- csense 6y agoAny idea why this hasn't been addressed in the C standard? Like C21 could say "math.h shall have a popcnt() function with these semantics", and then the compiler treats that like the intrinsic?
- jsheard 6y agoI don't know why C doesn't have it yet, but TIL they did already standardize it in C++20 https://en.cppreference.com/w/cpp/numeric/popcount https://en.cppreference.com/w/cpp/numeric/popcount
- ncmncm 6y agoThe difficult part is not expressing it. Rather, it is persuading the compiler that the target implements the instruction. gcc and clang have to be convinced they are generating code for an amd64 chip manufactured since 2002 (for which "-mpopcnt" usually works). Common Linux distributions don't turn on any such flags. MSVC offers no way to persuade it, but it will issue the instruction anyway if you use its intrinsic, _popcntN(x), where N is 16, 32, or 64. Shipping Microsoft code doesn't; it is all supposed to work on the oldest amd64 chips ever made. C++98 gave us std::bitset<N>(x).count(). With C++20 we have std::popcount(x). But getting the compiler to produce the instruction reliably and portably is no easier than before.
- mmastrac 6y agoOdd that GCC is emitting an xor eax, eax before popcount (in both the intrinsic and pattern cases!): popcnt(unsigned int): xor eax, eax popcnt eax, edi ret
- umenthum 6y agoPCNT instruction is in the proposed bit manipulation extension of RISC-V. https://github.com/riscv/riscv-bitmanip/blob/master/bitmanip-0.92.pdf https://github.com/riscv/riscv-bitmanip/blob/master/bitmanip...