为什么不能(!A&&!B)优化单个TEST指令?

时间:2016-09-01 08:31:10

标签: c# c++ assembly x86 compiler-optimization

if( !A && !B )似乎应该编译为

mov    eax, dword ptr[esp + A_offset]
test   eax, dword ptr[esp + B_offset]
jne    ~~~~~~~~~~

编译器实际生成

mov    eax, dword ptr[esp + A_offset]
test   eax, eax
jne    ~~~~~~~~~~
mov    eax, dword ptr[esp + B_offset]
test   eax, eax
jne    ~~~~~~~~~~

请参阅此处转储

8B 45 F8             mov         eax,dword ptr [b]  
83 7D FC 00          cmp         dword ptr [a],0  
75 04                jne         main+32h (0A71072h)  
85 C0                test        eax,eax  
75 00                jne         main+32h (0A71072h)   

为什么不使用单个TEST指令来保存分支和指令?

2 个答案:

答案 0 :(得分:2)

没有。 test指令对操作数执行按位AND并根据结果设置标志,请参阅https://en.wikipedia.org/wiki/TEST_(x86_instruction)

因此编译器生成的代码是正确的。

答案 1 :(得分:2)

由于short-circuit evaluation

if(!A && !B)

让我们注意上面的代码。

如果A是真实的(不是0), !A && !B变为0(FALSE)。 是的,你不必检查B的值。 它应该跳过(跳转)if语句的代码块。

mov eax, dword ptr[esp + A_offset]
test eax, eax   ; If `A & A`
jne ~~~~~~~~~~  ; is not 0(If A is not 0), skip this if-codeblock.
mov eax, dword ptr[esp + B_offset] ; Otherwise,
test eax, eax   ; If `B & B`
jne ~~~~~~~~~~  ; is not 0(If B is not 0), skip this if-codeblock.
......          ; Both A and B are 0, and `!A && !B` is `1(TRUE)`! Run the if-codeblock.

加:

看来你的代码错了..?

mov eax, dword ptr[esp + A_offset]
mov ebx, dword ptr[esp + B_offset]
test eax, ebx  ; `A & B`
jne ~~~~~~~~~~ ; If `A & B != 0`, skip this code-block for the if statement.
...... ; In other words, this code-block will be run when `A & B == 0`,
       ; which will be `TRUE` when A is 1(0b00000001) and B is 2(0b00000010).