2016-11-14 118 views
4

这是我的C#代码:如何强制编译器使用ldc.i8 IL指令而不是ldc.i4加conv.i8?

const long pSize = 20; 

不管,如果我使用的x64或任何CPU建立它在发行模式下,我得到如下MSIL指令:

IL_0010: ldc.i4.s 20 
    IL_0012: conv.i8 

然而,MSIL有最不发达国家。 i8指令。如何让编译器使用它?

+2

为什么你想要做什么编译器通常负责? – Sinatr

+0

所以你想强制编译器生成比必要的更长的代码? – hvd

+2

您正在询问如何使MSIL *效率更低,ldc.i8需要4个字节。毫无意义。 –

回答

24

MSIL有ldc.i8指令。如何让编译器使用它?

你不知道。那会是更糟糕的代码。

ldc.i4.s 20 
conv.i8 

是三个字节的代码:两个用于指令,一个用于常量。而

ldc.i8 20 

是九个字节:一个用于指令,八个用于常量。

编译器足够聪明,可以避免六个不必要的字节。请记住,代码速度可能会受到加载到内存中所需的页面错误数量的不利影响;生成的代码比它需要的大三倍大。有违这个目标。

但是等等,还有更多,而且都很糟糕。

代码的基本块越大,围绕它的分支越可能长于紧凑分支指令格式的长度。这意味着这种去优化可以使分支指令变大,这又使得它们的基本块更大,并且现在可能分支约它们不紧凑,并且整个事情可以滚雪球。

它不只是六个额外的字节;这是所有这六个额外字节的后果,使其他代码更大;你也必须考虑到这个成本。

编译器做得很好。让它做它的工作。

如果您的心脏设置为使编译器生成较差的代码,则编译器的源代码可用。如果您出于某种原因真的需要编译器,请随时编写一个去优化编译器。

+0

指令“conv.i8”的实际效果是什么?我的C#代码想把20看作'long',然后再乘以另一个很长的数字。我认为conv.i8将20个字节转换为long。 – Sheen

+1

@Sheen:操作码语义清楚地记录在案;做一些研究。另外,我觉得有些不安,你问如何强制编译器生成一个替代的指令序列*而不知道当前的实际指令序列指令做了什么*。 C#的设计使您可以了解C#的语义,从而推导出您的代码;不要担心IL。生成的IL是正确的。 –

+0

埃里克,谢谢你的建议。我阅读MSDN页面。它说3个步骤: 1.值被推入堆栈。 2.从堆栈弹出值并尝试转换操作。 3.如果转换成功,则将结果值压入堆栈。 所以在运行时,将int64直接放在堆栈上更好吗? – Sheen

相关问题