3 ms·
I have come across a related compiler issue with popcnt before. I was trying to prototype a "population count" routine in C before rewriting it in 64-bit ARM as
by Findecanor 2y ago
I have come across a related compiler issue with popcnt before. I was trying to prototype a "population count" routine in C before rewriting it in 64-bit ARM assembly.
ARMv8.0 64-bit doesn't have a "popcnt" instruction in its scalar set.
I was curious to how well Clang would map my C statements into the ARM assembly I had been thinking of using, so I tested it on Compiler Explorer.
I noticed that in the output my routine was oh so slightly different, using an inverted constant. I then rewrote my routine with another algorithm ... but got the same compiler output.
Apparently Clang can recognise that "Oh, this is a population count routine" and replace it with a `llvm.ctpop.i32` intrinsic.
I have found no way to use compiler flags to suppress specifically this optimisation without turning off optimisations completely.
- matthews2 2y agoYou can use -mno-popcnt for this. Godbolt: https://godbolt.org/z/raszoEedr https://godbolt.org/z/raszoEedr Reference: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mpopcnt https://clang.llvm.org/docs/ClangCommandLineReference.html#c...
- tialaramex 2y agoThis is called Idiom Recognition, and it was already needed in some compilers in the 1960s. So, unless you're now writing C from a retirement home probably all the non-toy compilers you've used had this feature.
- trealira 2y agoYes, but even though there were some advanced compilers back then, particularly for Fortran, there were also really dumb compilers for C and Pascal in the 1980s that didn't do any of that, and just did local register allocation statement by statement (storing to the stack after every statement), which is probably more like what they were used to.
- dzaima 2y agoClosest you can realistically get in current compilers is adding some no-op asm statement "modifying" some subexpression as an "optimization barrier". e.g. __asm__("" : "=r"(x) : "0"(x)); to make the optimizer unable to preserve known properties of "x" from before to after this line. Though this requires knowing the assembly register constraint to use ("r" here for a GPR), and can inhibit some other optimizations. (do note that this still allows dead code elimination and common subexpression elimination; "asm volatile" prevents these too)