是否存在“&”产生的性能低于“%”的情况?

Is there a case where '&' yields a lower performance than '%'?

以下两个代码序列产生相同的结果:

uint mod = val % 4;

uint mod1 = val & 0x3;

我可以同时使用两者来计算相同的结果。我知道在硬件中 & 运算符比 % 运算符更容易实现。因此我希望它比 % 运算符具有更好的性能。

我能否始终假设 & 具有更好或相等的性能? 编译器会自动优化吗?

(现代)编译器应该根据您的示例生成相同的代码,这种优化的原因是 rhs 是一个编译常量。

据我所知,& 运算符是用一条处理器指令完成的 and;模运算符不是这种情况,它通常意味着更多的操作(计算整数除法的余数)。 AFAIK,它通常比乘法长;我认为只要一个整数除法。

您不能对这些操作中的任何一个进行任何假设,编译可以将两者优化为相同的指令。

而且,事实上,clanggcc 都会将它们翻译成一条 and 指令。

不幸的是,由于 % 的性质自 ISO C99 起具有指定的 return 负值,signed 整数需要一些额外的工作。与 ISO C90 相反,负模是实现定义的。

两个操作的结果集,在 signedunsigned 值上:

modulo 有符号整数:

mov     eax, DWORD PTR [esp+4]       ; grab `val`
cdq                                  ; convert 32-bit EAX to 64-bit
                                     ; and fill EDX with the sign bit
shr     edx, 30                      ; shift EDX by 30 positions to the right
                                     ; leaving only the two left-most bits
add     eax, edx                     ; add EDX to EAX
and     eax, 3                       ; do the AND
sub     eax, edx                     ; subtract EDX from EAX
mov     DWORD PTR [esp+8], eax       ; move result on stack

这是一个巧妙的技巧,可以正确定义负值的行为。它对负值执行 ((val + 3) & 3) - 3,对正值执行 val & 3

and with signed/unsigned and modulo with unsigned:

mov     eax, DWORD PTR [esp+4]
and     eax, 3
mov     DWORD PTR [esp+12], eax