clang 和 GCC 之间的 'i % 2 == 0' 的代码生成不同,为什么会这样编译?

Vio*_*ffe 6 c++ assembly x86-64 micro-optimization compiler-optimization

我很好奇编译器是否对像N % <some factor of 2> equals / not equals 0. 确实如此,但有一些有趣的细微差别,所以这里有两个问题:

  1. 为什么 GCC 和 MSVC 对于i % 2( https://godbolt.org/z/KaWrYoz1a ) 的情况产生看似比 clang 更复杂的输出,但对于 4、8、16 因子的输出却相同 - 更简单 - 输出?

铿锵输出(预期):

test    dil, 1
sete    al
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会输出:

mov     rax, rdi
not     rax
and     eax, 1
Run Code Online (Sandbox Code Playgroud)

MSVC 是相同的,但mov/之间的顺序不同not

  1. 为什么 MSVC 为 4 / 8 因子的有符号整数(32 位和 64 位)生成更复杂的代码(https://godbolt.org/z/xP1qcch8q)?Clang 和 GCC 不受签名的影响。
mov     rax, rcx
cdq
and     edx, 3
add     rax, rdx
and     eax, 3
cmp     rax, rdx
sete    al
Run Code Online (Sandbox Code Playgroud)

为什么 MSVC 仍然生成 2 因子的简单代码?

PS 编译器处于最大 O 级别,但我没有指定任何体系结构 ( -march) 标志。