为什么.NET Native 以相反的顺序编译循环?
Why does .NET Native compile loop in reverse order?
我正在研究由 .NET Native 编译器执行的优化技术。
我创建了一个示例循环:
for (int i = 0; i < 100; i++)
{
Function();
}
而且我已经用 Native 编译了它。然后我在 IDA 中用机器代码反汇编结果 .dll
文件。结果,我有:
(我去掉了一些不需要的行,所以不用担心地址行不一致)
我理解 add esi, 0FFFFFFFFh
的真正意思是 subtract one from esi and alter Zero Flag if needed
,所以如果还没有达到零,我们可以跳到开头。
我不明白的是编译器为什么要反转循环?
我得出的结论是
LOOP:
add esi, 0FFFFFFFFh
jnz LOOP
只是比例如
快
LOOP:
inc esi
cmp esi, 064h
jl LOOP
但这真的是因为这个吗?速度差异真的很大吗?
inc
might be slower than add
because of the partial flag update。此外 add
影响零标志,因此您不需要使用另一个 cmp
指令。直接跳转就好了
这是一种著名的类型 loop optimization
reversal: Loop reversal reverses the order in which values are assigned to the index variable. This is a subtle optimization which can help eliminate dependencies and thus enable other optimizations. Also, certain architectures utilize looping constructs at Assembly language level that count in a single direction only (e.g. decrement-jump-if-not-zero (DJNZ)).
- Is it faster to count down than it is to count up?
- GCC Loop optimization
您可以看到其他编译器的结果here。
你的结论是正确的:反转循环将以0
为目标(当寄存器值达到0
时循环结束),因此Add
将设置条件分支中使用的零标志。
这样您就不需要专用的 Cmp
,这导致:1) 大小优化 2) 它也更快(来自编译器程序员的决定和另一个 的结论)。
这是编写循环目标的非常常见的汇编程序技巧 0
。我很惊讶你了解汇编程序,但不知道(询问)它。
我正在研究由 .NET Native 编译器执行的优化技术。 我创建了一个示例循环:
for (int i = 0; i < 100; i++)
{
Function();
}
而且我已经用 Native 编译了它。然后我在 IDA 中用机器代码反汇编结果 .dll
文件。结果,我有:
(我去掉了一些不需要的行,所以不用担心地址行不一致)
我理解 add esi, 0FFFFFFFFh
的真正意思是 subtract one from esi and alter Zero Flag if needed
,所以如果还没有达到零,我们可以跳到开头。
我不明白的是编译器为什么要反转循环?
我得出的结论是
LOOP:
add esi, 0FFFFFFFFh
jnz LOOP
只是比例如
快LOOP:
inc esi
cmp esi, 064h
jl LOOP
但这真的是因为这个吗?速度差异真的很大吗?
inc
might be slower than add
because of the partial flag update。此外 add
影响零标志,因此您不需要使用另一个 cmp
指令。直接跳转就好了
这是一种著名的类型 loop optimization
reversal: Loop reversal reverses the order in which values are assigned to the index variable. This is a subtle optimization which can help eliminate dependencies and thus enable other optimizations. Also, certain architectures utilize looping constructs at Assembly language level that count in a single direction only (e.g. decrement-jump-if-not-zero (DJNZ)).
- Is it faster to count down than it is to count up?
- GCC Loop optimization
您可以看到其他编译器的结果here。
你的结论是正确的:反转循环将以0
为目标(当寄存器值达到0
时循环结束),因此Add
将设置条件分支中使用的零标志。
这样您就不需要专用的 Cmp
,这导致:1) 大小优化 2) 它也更快(来自编译器程序员的决定和另一个
这是编写循环目标的非常常见的汇编程序技巧 0
。我很惊讶你了解汇编程序,但不知道(询问)它。