Description
The definition for Base.:>>>
, Base.:>>
and Base.:<<
do not compile to native shift instructions, because they need to handle the case where the integer is shifted by more than the integer bitwidth:
julia> @code_native debuginfo=:none dump_module=false 1 >> 1
.text
pushq %rbp
movq %rsp, %rbp
cmpq $63, %rsi
movl $63, %ecx
cmovbl %esi, %ecx
movq %rdi, %rdx
sarq %cl, %rdx
movq %rsi, %rcx
negq %rcx
shlq %cl, %rdi
xorl %eax, %eax
cmpq $64, %rcx
cmovbq %rdi, %rax
testq %rsi, %rsi
cmovnsq %rdx, %rax
popq %rbp
retq
nopw %cs:(%rax,%rax)
Often, this extra complication is not necessary, and it is possible to create a more effective bitshift operation by allowing overflow. This is completely analogous to how Base.:+
is more efficient than a saturating add, because it allows overflow:
julia> f(x, i) = x >> (i & (8*sizeof(i)-1));
julia> @code_native debuginfo=:none dump_module=false f(1, 1)
.text
pushq %rbp
movq %rsp, %rbp
sarxq %rsi, %rdi, %rax
popq %rbp
retq
nopl (%rax,%rax)
I find myself using that pattern relatively often, but this bit-twiddling trick is a little obscure, so readers may not understand what the function is doing, and may not know that this trick is available.
It would be nice if Base provided these very basic operations for users interested in high performance bit-twiddling.