2016-09-01 7 views
4

if(!A && !B)それは(!A &&!B)が単一のTEST命令に最適化されないのはなぜですか?

mov eax, dword ptr[esp + A_offset] 
test eax, dword ptr[esp + B_offset] 
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命令を使用していないダンプコンパイラが実際に

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

参照を生成しそうです支店や指示を保存するには?

+2

A = 1かつB = 2の場合はどうなりますか?そうすれば、テストは間違った答えを与えるでしょう。 –

+1

@Yuvalこれは重複していません(少なくともその特定の質問ではありません)。 –

+0

@MarcGlisse質問には、&& 'ではなく、'& 'と書かれています。 – molbdnilo

答えて

2

if(!A && !B) 

上記のコードに注意してください。

Aが真実(0でない)である場合、!A && !B0(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). 
+0

同時に両​​方をテストする効率的な方法があった場合、コンパイラはそうするでしょう。 OPのコードはすでに 'a'をテストする前にレジスタに' b'をロードしているので、コンパイラの意思決定は回避策や短絡の評価とは何の関係もなく、 'bool( A&B) '!=' A && B 'AとBが非ゼロであり、非交差ビットパターンの場合。また、gccが '!a &&!b 'を'!(a | b) 'に変えるというgccの開発者Marc Glisseのコメントに注意してください。 –

+0

@PeterCordesまあ、公正であるならば、 'b'が読みにくいときにGCCが最適化をしないのは、短絡評価が' a'が真であれば決してアクセスしないということです。 –

+0

@RossRidge:明らかに、Cソースのセマンティクスを維持するための前提条件です。しかし、私の指摘は、最初のテストの前に両方のロードを行い、それらがアクセスするのが安全であることと、それを避けようとしていないことを証明していたので、この答えの最初の仮説は違う。 –

2

No. test命令は、結果に応じてオペランドとセットフラグのビット単位の論理積を実行します。https://en.wikipedia.org/wiki/TEST_(x86_instruction)を参照してください。

ので、コンパイラによって生成されたコードは正しいです。そのためshort-circuit evaluation

+0

ありがとうございます。私はちょうど混乱していた –

関連する問題