- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在 MSVC 2013 中编译以下代码,64 位发行版,/O2
优化:
while (*s == ' ' || *s == ',' || *s == '\r' || *s == '\n') {
++s;
}
我得到了以下代码——它使用 64 位寄存器作为查找表进行了非常酷的优化,带有 bt
(位测试)指令。
mov rcx, 17596481020928 ; 0000100100002400H
npad 5
$LL82@myFunc:
movzx eax, BYTE PTR [rsi]
cmp al, 44 ; 0000002cH
ja SHORT $LN81@myFunc
movsx rax, al
bt rcx, rax
jae SHORT $LN81@myFunc
inc rsi
jmp SHORT $LL82@myFunc
$LN81@myFunc:
; code after loop...
但我的问题是:movsx rax, al
的目的是什么?在第一个分支之后?
首先我们从字符串中加载一个字节到rax
并对其进行零扩展:
movzx eax, BYTE PTR [rsi]
然后是 cmp
/ja
pair 在 al
之间执行 无符号 比较和 44
, 如果 al
则向前分支更大。
所以现在,我们知道 0 <= al <= 44
在无符号数中。因此,al
的最高位无法设置!
不过,下一条指令是 movsx rax, al
.这是一个符号扩展的举动。但是因为:
al
是 rax
的最低字节rax
的其他 7 个字节归零al
的最高位不可能被设置这个 movsx
必须是空操作。
为什么 MSVC 会这样做?我假设它不是用于填充,因为在这种情况下另一个 npad
会使意思更清楚。是刷新数据依赖还是什么?
(顺便说一句,这个 bt
优化真的让我很高兴。一些有趣的事实:它的运行时间是你可能期望的 4 个 cmp
/je
对的 0.6 倍,这是 方式 比 strspn
或 std::string::find_first_not_of
快,并且它只发生在 64 位构建中,即使感兴趣的字符的值低于 32。)
最佳答案
您肯定认识到,这种优化是由优化器中用于查找该模式的非常具体的代码产生的。只是位掩码的生成就泄露了它。是的,不错的技巧。
这里有两个基本的代码生成案例。第一个是更通用的,其中 (charmax - charmin <= 64) 但charmax >= 64。优化器需要生成与您看到的不同的代码,它需要减去charmin。该版本没有有 MOVSX 指令。您可以通过将 *s == ' '
替换为 *s == 'A'
来查看它。
然后是您测试的特殊情况,所有要测试的字符代码恰好 < 64。Microsoft 程序员确实在他的代码中处理了这个问题,他确保不会生成愚蠢的 SUB EAX,0 指令。但忽略了生成 MOVSX 是不必要的。在一般情况下仅检查最佳代码肯定会错过。代码中还有一个通用的函数调用,很容易被忽略,注意当你用/J 编译时指令是如何变成 MOVZX 的。否则很容易被认为是必要的,没有 BT 指令将 8 位寄存器作为第二个操作数,因此 AL 寄存器加载本身是不够的。
可能存在一个假设的优化器后优化器,用于优化优化器生成的优化代码。并决定保留 MOVSX 以改进超标量执行。我严重怀疑它的存在。
关于c++ - 为什么 MSVC 在执行此位测试之前会发出无用的 MOVSX?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26124620/
在 MSVC 2013 中编译以下代码,64 位发行版,/O2优化: while (*s == ' ' || *s == ',' || *s == '\r' || *s == '\n') {
我正在尝试使用 yasm 汇编下面的代码。我在 yasm 报告错误“错误:操作数 2 的大小无效”的地方添加了“此处”注释。为什么会发生这个错误? segment .data a db 25
我对以下代码段感到困惑: movsx ecx, [ebp+var_8] ; signed move cmp ecx, [ebp+arg_0] jnb short loc_40102
对于 asm 模拟器,我正在尝试编写将 ASM 代码转换为等效工作代码的工作代码。最好的代码是可以在一行或最多两到三行中完成的代码,不在乎关于速度。 根据我的理解。如果用 C++ 完成,MOVZX 将
我是一名优秀的程序员,十分优秀!