gpt4 book ai didi

c# - 为什么会产生AND指令?

转载 作者:IT王子 更新时间:2023-10-29 04:05:03 24 4
gpt4 key购买 nike

对于这样的代码:

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

此代码已生成( Release模式,未附加调试器,64 位):

 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 永远不会在此代码中超过 0x1F,但我原谅它没有注意到这一点(也没有注意到结果是一个常量),它不是提前编译器毕竟可以花很多时间进行分析。但更重要的是,具有 32 位操作数的 SHL 已经通过 0x1F 屏蔽了 cl。所以在我看来,这些 AND 完全没有用。它们为什么会产生?他们有什么我想念的目的吗?

最佳答案

and 已经存在于 C# 编译器生成的 CIL 代码中:

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

CIL shl 指令的规范说:

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

然而,C# 规范定义了 32 位移位以采用移位计数模 32:

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# 编译器除了发出显式 操作之外,真的做的再好不过了。最好的希望是 JITter 会注意到这一点并优化掉冗余的 ,但这需要时间,而且 JIT 的速度非常重要。因此,请考虑为基于 JIT 的系统支付的价格。

我想,真正的问题是为什么 CIL 以这种方式指定 shl 指令,而 C# 和 x86 都指定了截断行为。我不知道,但我推测对于 CIL 规范来说,避免指定可能对某些指令集上昂贵的东西进行 JIT 的行为很重要。同时,对于 C# 来说,尽可能少的未定义行为很重要,因为人们总是会使用这些未定义的行为,直到下一个版本的编译器/框架/操作系统/无论什么改变它们,破坏代码。

关于c# - 为什么会产生AND指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9905668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com