4 ms·
GCC can't optimize out the mask (which is required to avoid UB if n may be equal or greater than 64): #include <stdint.h> uint64_t rol(uint64_t n, uin
by clarry 9y ago
GCC can't optimize out the mask (which is required to avoid UB if n may be equal or greater than 64):
#include <stdint.h>
uint64_t rol(uint64_t n, uint64_t val)
{
n &= 63;
return (val << n) | (val >> 64-n);
}
Compiles to
rol(unsigned long, unsigned long):
mov rcx, rdi
mov rax, rsi
and ecx, 63
rol rax, cl
ret
Clang and ICC do get it right.
- waterhouse 9y agoInteresting... My AMD64 Programmer's Manual says, about "Rotate Left": "The processor masks the upper three bits of the count operand, thus restricting the count to a number between 0 and 31. When the destination is 64 bits wide, it masks the upper two bits of the count, providing a count in the range of 0 to 63." Are there x86 platforms that don't do that? (I don't know if there's a more official document than the AMD64 manual. Technically Intel's stuff is made to be compatible with a standard that AMD first created.) If not, yeah, that's a nice, clear case of a missed optimization.
- userbinator 9y agoIntel's official reference says the count is masked too, with an interesting note that the 8086 (and presumably '186) doesn't.
- dom0 9y agoWith a fixed n, GCC does get it right as well (kinda has to, because that's the only portable way to do fixed rotations in C). I'd sort it under range analysis.