C/C++:"mod 2" 不会产生与 "and 1" 相同的指令 (gcc -O3)

C/C++: "mod 2" not resulting in the same instructions as "and 1" (gcc -O3)

在使用 gcc 和最大优化(GCC 11.1.0,gcc -std=c11 -O3)编译这两个片段时,我希望获得完全相同的相同的可执行文件,因为 %2&1 运算 等价 。但是,在使用 objdump 进行反汇编后,这两个目标文件有所不同。输出如下所示。

int main(int argc, char **argv){
   return argc & 1;
}
0000000000001020 <main>:
    1020:       89 f8                   mov    %edi,%eax
    1022:       83 e0 01                and    [=14=]x1,%eax
    1025:       c3                      ret    
    1026:       66 2e 0f 1f 84 00 00    cs nopw 0x0(%rax,%rax,1) 

模数

int main(int argc, char **argv){
   return argc % 2;
}
0000000000001020 <main>:
    1020:       89 fa                   mov    %edi,%edx
    1022:       c1 ea 1f                shr    [=16=]x1f,%edx
    1025:       8d 04 17                lea    (%rdi,%rdx,1),%eax
    1028:       83 e0 01                and    [=16=]x1,%eax
    102b:       29 d0                   sub    %edx,%eax
    102d:       c3                      ret    
    102e:       66 90                   xchg   %ax,%ax

我理解第一个程序中的指令,但我不太明白第二个程序中某些行的目的。

为什么这两个程序不同?为什么编译器不将 %2 优化为 &1,这应该更快并且使用更少的指令?

如果 val 为负,

val % 2 可能有负值。 val & 1 将只有一个正值(或零)。所以这些操作不相同 - 因此编译代码不同。