为什么g ++ x64 / i86没有优化编译模式这种方式

时间:2016-12-05 23:43:41

标签: assembly g++ 64-bit x86-64

以下代码是由g ++ 5.4.0编译的x64。左边是编译输出。右边的东西就是我所期望的样子。当然,右边的stuf可能在语法上不正确。这段代码应该基本上做:

if(i%3 == 0)  do_stuff

400512将把你带到if块后面的空格

mov    -0x4(%rbp),%ecx              mov -0x4(%rbp), %eax
mov    $0x55555556,%edx             idvq $0x3
mov    %ecx,%eax                    cmp %edx, 0x0
imul   %edx                         jnz 400512 <main+0x3c>
mov    %ecx,%eax
sar    $0x1f,%eax
sub    %eax,%edx
mov    %edx,%eax
mov    %eax,%edx
add    %edx,%edx
add    %eax,%edx
mov    %ecx,%eax
sub    %edx,%eax
test   %eax,%eax
jne    400512 <main+0x3c>

我的问题是那些比我更聪明的人:为什么g ++有更多来计算模数,有人可以向我解释它在做什么。

1 个答案:

答案 0 :(得分:0)

出于我的好奇心,Ross Ridge对unsigned int修改的评论产生了更短的代码:

bar(unsigned int):
    mov     eax, edi
    mov     edx, -1431655765
    mul     edx
    shr     edx
    lea     eax, [rdx+rdx*2]
    cmp     edi, eax
    je      .L4
    rep ret
.L4:
    jmp     foo()

但是回到int版本......对于编译器来说它很整洁......但它仍然感觉有些......

等等,它是否正确划分为3然后再将其相乘,然后检查是否计算了相等的数字?嗯......但是我们只想要mod 3 == 0测试,对吧?

那么这也应该这样做:

bar(int):
    mov     eax, edi
    mov     edx, 1431655766
    imul    edx
; don't +1 of div result for negative edi
;    mov     eax, edi  
;    sar     eax, 31
;    sub     edx, eax
; instead do +3 for all results
    lea     eax, [rdx+rdx*2+3]
    sub     eax, edi   ; eax = 0, 1, 2 or 3 (!)
    jpe     .L4        ; so parity-even condition will resolve it (!)
    rep ret
.L4:
    jmp     foo()

不幸的是,这是特殊情况&#34; mod 3&#34;仅限优化(而且我不确定这真的是否会改善任何东西)...... :)但我无法抗拒&#34;高尔夫&#34;它有点。