Tzcntを使用して計算されたビット位置(ゼロではない)があり、その位置から開始して上位ビットをゼロにしたいと考えています。これはC++と逆アセンブリのコードです(私はMSVCを使用しています)。
auto position = _tzcnt_u64(xxx);
auto masked =_bzhi_u64(yyy, static_cast<uint32_t>(position));
tzcnt rcx,rdx
mov ecx,ecx
bzhi rax,rbx,rcx
BZHIは2番目のパラメーターとしてunsigned intを受け入れますが、rcxからのビット[7..0]のみを使用するため、この 'mov'命令は私の意見では不要です。
これを後でポップカウントを計算するために使用するので、代わりに<<(64-position)のようなものを使用することもできます。
問題は-これらの2つのコードの実行時間は同じですが、bzhiはsub + shlxよりも高速に実行する必要があるため、movがおそらく違いを生みます。
それを回避する方法はありますか、それともこのコンパイラのものですか?
これはコンパイラーのものです(Visual C++ 2019 00435-60000-00000-AA388現在)。
MSVCのimmintrin.hは、
__int64 _bzhi_u64(unsigned __int64, unsigned int);
intelの次善の 固有の定義コマンドドキュメント と矛盾します(すべてのbzhi
パラメータは同じサイズです)。
clangはbmi2intrin.hにあります
unsigned long long _bzhi_u64(unsigned long long __X, unsigned long long __Y)
なので、_tzcnt_u64
結果はコードになります。
私はMSVCのimmintrin.hにパッチを適用しました。悲しい!ピーターの洗練された回避策は私の場合には適用されないためです(lzcnt/bzhi、popcntは不可)。