Roslyn 不优化多个增量是否有原因?
Is there a reason why Roslyn does not optimize multiple increments?
我试图了解 Roslyn
如何优化以下代码段:
代码
public int F(int n) {
++n;
++n;
++n;
++n;
return n;
}
asm
C.F(Int32)
L0000: inc edx
L0002: inc edx
L0004: inc edx
L0006: inc edx
L0008: mov eax, edx
L000a: ret
问题
为什么 Roslyn 不像像 MSVC 这样的提前 C 编译器那样对其进行优化? 4 x INC
较慢(4 周期延迟与 1,即使假设移动消除,比吞吐量所需的多 4 微指令;https://agner.org/optimize/)。
C
它的“等价物”:
int
f(void *dummy_this, int n) {
++n;
++n;
++n;
++n;
return n;
}
asm 来自 MSVC,或 GCC __attribute__((ms_abi))
使用与 C# asm 相同的 Windows x64 调用约定:https://godbolt.org/z/sK6h7KKcn
f:
lea eax, [rdx+4]
ret
编译器确实进行了优化。 n
是一个参数,所以不能修改。 JIT 编译器必须修改参数值的 copy。
如果在递增之前将值分配给变量,Roslyn 编译器将消除递增。来自 this Sharplab.io snippet,此 C# 代码:
public int F(int i) {
var n=i;
++n;
++n;
++n;
++n;
return n;
}
将翻译成
public int F(int i)
{
return i + 1 + 1 + 1 + 1;
}
并最终编译成这段汇编代码:
C.F(Int32)
L0000: lea eax, [edx+4]
L0003: ret
我试图了解 Roslyn
如何优化以下代码段:
代码
public int F(int n) {
++n;
++n;
++n;
++n;
return n;
}
asm
C.F(Int32)
L0000: inc edx
L0002: inc edx
L0004: inc edx
L0006: inc edx
L0008: mov eax, edx
L000a: ret
问题
为什么 Roslyn 不像像 MSVC 这样的提前 C 编译器那样对其进行优化? 4 x INC
较慢(4 周期延迟与 1,即使假设移动消除,比吞吐量所需的多 4 微指令;https://agner.org/optimize/)。
C
它的“等价物”:
int
f(void *dummy_this, int n) {
++n;
++n;
++n;
++n;
return n;
}
asm 来自 MSVC,或 GCC __attribute__((ms_abi))
使用与 C# asm 相同的 Windows x64 调用约定:https://godbolt.org/z/sK6h7KKcn
f:
lea eax, [rdx+4]
ret
编译器确实进行了优化。 n
是一个参数,所以不能修改。 JIT 编译器必须修改参数值的 copy。
如果在递增之前将值分配给变量,Roslyn 编译器将消除递增。来自 this Sharplab.io snippet,此 C# 代码:
public int F(int i) {
var n=i;
++n;
++n;
++n;
++n;
return n;
}
将翻译成
public int F(int i)
{
return i + 1 + 1 + 1 + 1;
}
并最终编译成这段汇编代码:
C.F(Int32)
L0000: lea eax, [edx+4]
L0003: ret