For memory operands, there's an additional twist: the bit index is a signed offset that can address bits outside the nominal operand. A bit index of 35 on a dword accesses bit 3 of the next dword in memory.
I wonder what is the use case for testing a bit outside of the memory address given.
Don't think the memory operand version would work here. If I understand the x86 architectural manual description, the 32-bit operand form interprets the bit offset as signed. A 64-bit operand could work around that but then run into issues with over-read due to fetching 64 bits of data.
Comments
I wonder what is the use case for testing a bit outside of the memory address given.
So you can have bit arrays of any length in memory, rather than just 32 bits in a register.
That makes sense. LLVM could probably do better here by using the memory operand version:
https://godbolt.org/z/jeqbaPsMz
The memory operand version tends to be as slow or slower than the manual implementation, so LLVM is right to avoid it.
Right, it has much worse throughput:
Memory: https://uica.uops.info/tmp/f022a3c0a70e4ae5ab3588ebe65fd2a5_...
Register: https://uica.uops.info/tmp/e80e60e0c4914955b11dc6590711c1b8_...
Don't think the memory operand version would work here. If I understand the x86 architectural manual description, the 32-bit operand form interprets the bit offset as signed. A 64-bit operand could work around that but then run into issues with over-read due to fetching 64 bits of data.
It was probably easier to just implement it that way, given that the barrel shifter is 64 bits wide.