在 x86 上的 64 位模式下,大多数 32 位算术运算会清除目标寄存器的前 32 位。如果算术运算是“cmov”指令,并且条件为假怎么办?(我看过的参考手册中似乎没有涵盖这种情况)。
我有__mask64一些 AVX512 操作的结果:
__mmask64 mboth = _kand_mask64(lres, hres);
我想计算其中所有位均已设置的半字节数 ( 0xF)。
简单的解决方案是这样做:
uint64 imask = (uint64)mboth;
while (imask) {
if (imask & 0xf == 0xf)
ret++;
imask = imask >> 4;
}
Run Code Online (Sandbox Code Playgroud)
我想要更好的东西,但我想出的东西并不优雅:
//outside the loop
__m512i b512_1s = _mm512_set1_epi32(0xffffffff);
__m512i b512_0s = _mm512_set1_epi32(0x00000000);
//then...
__m512i vboth = _mm512_mask_set1_epi8(b512_0s, mboth, 0xff);
__mmask16 bits = _mm512_cmpeq_epi32_mask(b512_1s, vboth);
ret += __builtin_popcount((unsigned int)fres);
Run Code Online (Sandbox Code Playgroud)
上面将一个0xff字节放入一个向量中,其中掩码中存在 1 位,然后当现在发现bits放大的半字节为' 时,在掩码中获取一个 1 位。0xf0xffffffff int32
我觉得当原始数据存在于 64 位数字中时,两个 512 …
我需要得到一个32位数字中的1位数字,其中只有一个1位(总是)。最快的方式是C++或者asm。
例如
input: 0x00000001, 0x10000000
output: 0, 28
Run Code Online (Sandbox Code Playgroud) C++20 引入了许多新函数,例如std::popcount,我使用Intel Intrinsic使用相同的功能。
我编译了这两个选项 - 可以在编译器资源管理器代码中看到:
除了 std 模板中使用的类型检查之外,生成的汇编代码看起来是相同的。
就操作系统不可知代码并具有相同的优化而言 - 假设使用std::popcount和 apt 编译器向量优化标志比直接使用内在函数更好是否正确?
谢谢。
如果我想将 2 个无符号字节从内存移动到 32 位寄存器中,我可以用MOV指令而不用模式切换来做到这一点吗?
我注意到您可以使用MOVSE和MOVZE说明来做到这一点。例如,通过MOVSE编码0F B7将 16 位移动到 32 位寄存器。不过,它是一个 3 周期指令。
或者,我想我可以将 4 个字节移动到寄存器中,然后以某种方式仅 CMP 中的两个。
在 32 位 x86 上检索和比较 16 位数据的最快策略是什么?请注意,我主要进行 32 位操作,因此我无法切换到 16 位模式并留在那里。
仅供初学者参考:这里的问题是 32 位 Intel x86 处理器可以处理MOV8 位数据和 16 位 OR 32 位数据,具体取决于它们所处的模式。这种模式称为“D 位”设置。您可以使用特殊前缀 0x66 和 0x67 来使用非默认模式。例如,如果您处于 32 位模式,并且您使用 0x66 作为指令前缀,这将导致操作数被视为 16 位。唯一的问题是这样做会导致性能下降。
可以安全地假设 x64 构建可以使用TZCNT而无需通过 cpu 标志检查其支持吗?
我正在用 c 语言编写一个国际象棋引擎,速度至关重要。国际象棋引擎基于 unsigned long long,我将其表示为 u64,并且它严重依赖于最低有效位扫描。到目前为止,我一直在使用 gcc 函数 __builtin_ctzll ,它做得很好。然而,我使用 gcc -S -O2 为这个独立函数生成了汇编代码。它给了我以下内容:
xorl %eax, %eax
rep bsfq %rdi, %rax
cltq
ret
Run Code Online (Sandbox Code Playgroud)
然而经过一番调查似乎代码
rep bsfq %rdi, %rax
ret
Run Code Online (Sandbox Code Playgroud)
在我的国际象棋程序中做了完全相同的事情。然而现在速度慢了约 20%。它应该更快,因为它的指令更少。然而,原始的 __builtin_ctzll 内联在我的 C 代码中。这是我的自定义汇编代码运行速度比原始代码慢的原因吗?因为当我声明函数 ctzll 时,我当然不能在 c 中内联声明它,除非我有定义(不在汇编代码中)。
是否有另一种方法来优化汇编指令,或者我应该尝试直接在 c 中内联 asm 的新汇编代码?