为什么.NET Native编译顺序相反? [英] Why does .NET Native compile loop in reverse order?
问题描述
我正在研究.NET Native编译器执行的优化技术. 我创建了一个示例循环:
I'm working on optimization techniques performed by the .NET Native compiler. I've created a sample loop:
for (int i = 0; i < 100; i++)
{
Function();
}
我已经用Native编译了它.然后,我在IDA中反汇编了带有机器代码的结果.dll
文件.结果,我得到了:
And I've compiled it with Native. Then I disassembled the result .dll
file with machine code inside in IDA. As the result, I have:
(我已经删除了一些不必要的行,所以不用担心地址行不一致)
(I've removed a few unnecessary lines, so don't worry that address lines are inconsistent)
我知道add esi, 0FFFFFFFFh
的意思是真正的subtract one from esi and alter Zero Flag if needed
,因此如果尚未达到零,我们可以跳到开头.
I understand that add esi, 0FFFFFFFFh
means really subtract one from esi and alter Zero Flag if needed
, so we can jump to the beginning if zero hasn't been reached yet.
我不明白的是为什么编译器会反转循环?
What I don't understand is why did the compiler reverse the loop?
我得出的结论
LOOP:
add esi, 0FFFFFFFFh
jnz LOOP
比例如更快
LOOP:
inc esi
cmp esi, 064h
jl LOOP
但这是真的吗,并且速度差异真的很明显吗?
But is it really because of that and is the speed difference really significant?
推荐答案
inc
可能比add
慢,因为部分标志更新.此外,add
影响零标志,因此您无需使用其他cmp
指令.只是直接跳.
inc
might be slower than add
because of the partial flag update. Moreover add
affects the zero flag so you don't need to use another cmp
instruction. Just jump directly.
这是循环优化的一种著名类型
This is one famous type of loop optimization
反转:循环反转反转了将值分配给索引变量的顺序.这是一个微妙的优化,可以帮助消除依赖关系,从而启用其他优化.此外,某些架构会利用汇编语言级别的循环构造,这些循环构造仅在单个方向上计数(例如,减量-跳跃-如果非零(DJNZ)).
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)).