下から(LSBから)nビットが1のビットマスクを作りたいとき。もしくは上から(MSBから)について同様のものがほしい場合について。
ビット演算としては基本的だけど、定期的に自信がなくなってしまうのでまとめた。
下からnビットを立てたビットマスク
全部のビットが立ったものを左シフトしてからビット反転すればよい。
定数のロード、シフト、NOTで合計3命令。
uint32_t f(int n)
{
return ~(0xffffffffu << n);
}
x86かつHaswell世代以降のCPUに特化していいのであれば、BMI2にbzhiという命令がある。
演算が1命令で済むようになる。
# include <immintrin.h>
uint32_t g(int n)
{
return _bzhi_u32(0xffffffffu, n);
}
上からnビットを立てたビットマスク
ほぼ同様のやり方ができる。全部のビットが立ったものを右シフトしてからビット反転すればよい。
uint32_t h(int n)
{
return ~(0xffffffffu >> n);
}
下からnビットには特化した命令としてbzhiがあったが、bzloというものは存在しない様子。
アセンブリの確認
出力の確認はCompiler Explorerを使った。とても便利。
https://godbolt.org/z/mtStCk
f(int): # @f(int)
mov eax, -1
shlx eax, eax, edi
not eax
ret
g(int): # @g(int)
mov eax, -1
bzhi eax, eax, edi
ret
h(int): # @h(int)
mov eax, -1
shrx eax, eax, edi
not eax
ret