为什么和生成的指令? [英] Why are AND instructions generated?

查看:102
本文介绍了为什么和生成的指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关code像这样的:

For code such as this:

int res = 0;
for (int i = 0; i < 32; i++)
{
    res += 1 << i;
}

这code产生(释放模式,没有任何附加调试器,64位):

This code is generated (release mode, no debugger attached, 64bit):

 xor edx,edx 
 mov r8d,1 
_loop:
 lea ecx,[r8-1] 
 and ecx,1Fh     ; why?
 mov eax,1 
 shl eax,cl 
 add edx,eax 
 mov ecx,r8d 
 and ecx,1Fh     ; why?
 mov eax,1 
 shl eax,cl 
 add edx,eax 
 lea ecx,[r8+1] 
 and ecx,1Fh     ; why?
 mov eax,1 
 shl eax,cl 
 add edx,eax 
 lea ecx,[r8+2] 
 and ecx,1Fh     ; why?
 mov eax,1 
 shl eax,cl 
 add edx,eax 
 add r8d,4 
 cmp r8d,21h 
 jl  _loop

现在我可以看到大多数指令点那里,但是这是怎么回事与(AND)指令? ECX将的从不的是这个code比0x1F的更多反正,但我原谅它没注意到(而且也没有注意到这个结果是一个常数),它不是一个提前-的 - 时间编译器能够负担得起毕竟花太多的时间分析。但更重要的是,与SHL 32位运算口罩已经通过CL 0x1F的。所以,在我看来,这些与运算是完全无用的。他们为什么产生?他们有某种目的我失踪?

Now I can see the point of most instructions there, but what's up with the AND instructions? ecx will never be more than 0x1F in this code anyway, but I excuse it for not noticing that (and also for not noticing that the result is a constant), it's not an ahead-of-time compiler that can afford to spend much time on analysis after all. But more importantly, SHL with a 32bit operand masks cl by 0x1F already. So it seems to me that these ANDs are entirely useless. Why are they generated? Do they have some purpose I'm missing?

推荐答案

已美元,由C#编译器发出的CIL $ C $中c p $ psent

The and is already present in the CIL code emitted by the C# compiler:

    IL_0009: ldc.i4.s 31
    IL_000b: and
    IL_000c: shl

对于CIL该规范 SHL 说明书上说:

返回值是不确定的,如果的 shiftAmount 的大于或等于大小的

The return value is unspecified if shiftAmount is greater than or equal to the size of value.

C#的规范,但是,定义了32位移取移位计数模32:

The C# spec, however, defines the 32-bit shift to take the shift count mod 32:

当类型的 X 的是 INT UINT,移位次数由低阶数的五比特给出。换句话说,移位计数由计算计数和放大器;为0x1F

When the type of x is int or uint, the shift count is given by the low-order five bits of count. In other words, the shift count is computed from count & 0x1F.

在这种情况下,C#编译器真的不能做的更好比发出一个明确的操作。最好你能希望的是,抖动会注意到这一点,并优化掉多余的,但是这需要时间,JIT的速度是pretty重要。因此,考虑这个支付基于JIT系统的价格。

In this situation, the C# compiler can’t really do much better than emit an explicit and operation. Best you can hope for is that the JITter will notice this and optimize away the redundant and, but that takes time, and the speed of JIT is pretty important. So consider this the price paid for a JIT-based system.

真正的问题,我想,这就是为什么在CIL指定 SHL 指令的方式,在C#和x86两个指定截断行为。我不知道,但我推测,在CIL规范来避免使用可能JIT对一些指令集东西贵行为是很重要的。与此同时,重要的是对C#有少不确定的行为,有可能,因为人们不约而同地结束了使用这种不确定的行为,直到编译/框架/ OS /任何改变它们,突破code的下一个版本。

The real question, I guess, is why the CIL specifies the shl instruction that way, when C# and x86 both specify the truncating behaviour. That I do not know, but I speculate that it’s important for the CIL spec to avoid specifying a behaviour that may JIT to something expensive on some instruction sets. At the same time, it’s important for C# to have as few undefined behaviours as possible, because people invariably end up using such undefined behaviours until the next version of the compiler/framework/OS/whatever changes them, breaking the code.

这篇关于为什么和生成的指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆