Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Roslyn为什么不优化多个增量?_C#_Assembly_X86 64_Compiler Optimization_Roslyn - Fatal编程技术网

C# Roslyn为什么不优化多个增量?

C# Roslyn为什么不优化多个增量?,c#,assembly,x86-64,compiler-optimization,roslyn,C#,Assembly,X86 64,Compiler Optimization,Roslyn,我试图了解Roslyn如何优化以下代码段: 代码 public int F(int n){ ++n; ++n; ++n; ++n; 返回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

我试图了解
Roslyn
如何优化以下代码段:

代码

public int F(int n){
++n;
++n;
++n;
++n;
返回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个周期的延迟相比,即使假设消除mov,也比吞吐量所需的多4个UOP;)

C
它的“等效物”:

int
f(无效*伪值,整数n){
++n;
++n;
++n;
++n;
返回n;
}
asm来自MSVC,或带有
\uuuuu属性((ms\u abi))
的GCC使用与C\asm相同的Windows x64调用约定:


编译器确实进行了优化<代码>n是一个参数,因此无法修改。JIT编译器必须修改参数值的副本

如果该值在递增之前分配给变量,则Roslyn编译器将消除递增。从中,此C#代码:

将被翻译为

public int F(int i)
{
    return i + 1 + 1 + 1 + 1;
}
并最终编译成以下汇编代码:

C.F(Int32)
    L0000: lea eax, [edx+4]
    L0003: ret

n
是一个参数,因此不能修改”-但是
n
Int32
,一种值类型。它不是通过-
ref
-传递的,CLR抽象堆栈中的参数和局部变量的行为都是相同的,所以我不明白你为什么说“它不能修改”。@Dai是对的。“n是一个参数,所以它不能被修改”没有意义,并且也被OP的反汇编彻底失效(包含参数的寄存器明显递增,只是效率不高)。把它赋给另一个变量不会有什么区别。@Peter,我想你是对的。这就是为什么我称这个版本为“变通方法”。不过,知道至少有一些方法可以做到这一点是很好的。@Hrant:正如在对这个问题的评论中所讨论的(现在不幸地转到聊天),这个答案并不能解释它(所以你应该不接受它)。这不是C#或Windowsx64调用约定的工作方式。(如果
int i
是由ref获取的(它不是),那么它的值不会在EDX中传递/返回;它将由指针传递。因此
inc-EDX
纯粹是函数的私有部分,比mov+add或LEA更糟糕。)@PeterCordes您完全正确,但我认为这个答案总比没有好。而且我也不明白,当有非常有价值的信息可供阅读时,为什么要改为聊天;这段对话已经结束。
public int F(int i)
{
    return i + 1 + 1 + 1 + 1;
}
C.F(Int32)
    L0000: lea eax, [edx+4]
    L0003: ret