2017-01-09 11 views
6

ブール値bと、iがある場合、どちらの方が良いでしょうか?両方の例でブール値に基づいて値を決定する最速の方法+ +

int x = i-1; 
if(!b)x--; 

または

int x; 
if(b)x = i-1;else x = i-2; 

bがtrueの場合xxi-2ある他、i-1です。 xi-1と宣言し、bが偽の場合、または2番目の例を使用する必要がある場合は、減らしてください。

+9

ブランチレス版は 'x = i - 2 + b; –

+4

です。リリースでコンパイルした場合、コンパイラは同じコードを出力します – user

+1

なぜ尋ねるのですか?マイクロ最適化は無関係です。 –

答えて

10

コンパイラが両方のバージョンを同じ最適なアセンブリに最適化しなかった場合、私は驚くでしょう。プロファイラを使用して重要であることを証明できない限り、このマイクロ最適化で時間を無駄にしないでください。

あなたの質問に答えるには:それは無関係です。ここではgcc.godbolt.orgの "生成されたアセンブリ"の比較は-Ofastです。コンパイルさ


volatile int state0; 
volatile void f0(volatile int i, volatile bool b) 
{ 
    int x; 
    if(b)x = i-1;else x = i-2; 
    state0 = x; 
} 

... ... ...に


volatile int state1; 
volatile void f1(volatile int i, volatile bool b) 
{ 
    int x = i-1; 
    if(!b)x--; 
    state1 = x; 
} 

...

f0(int, bool):        # @f0(int, bool) 
     mov  dword ptr [rsp - 4], edi 
     mov  byte ptr [rsp - 5], sil 
     movzx eax, byte ptr [rsp - 5] 
     or  eax, -2 
     add  eax, dword ptr [rsp - 4] 
     mov  dword ptr [rip + state0], eax 
     ret 
をコンパイルさ

f1(int, bool):        # @f1(int, bool) 
     mov  dword ptr [rsp - 4], edi 
     mov  byte ptr [rsp - 5], sil 
     mov  eax, dword ptr [rsp - 4] 
     movzx ecx, byte ptr [rsp - 5] 
     or  ecx, -2 
     add  ecx, eax 
     mov  dword ptr [rip + state1], ecx 
     ret 

あなたが見ることができるように、差が少なく、コンパイラはvolatileを除去することによって、より積極的に最適化することが許可されているときに消えることは極めて可能性があります。


ここ-Ofast -march=native -ffast-mathを使用して、画像の形で同様の比較です:

Godbolt comparison

+0

はあなたが使用しているフラグを明記してください(-03?) –

+0

@IvanRubinson:それはgodboltリンク上で、私は '-Ofast'を使用します。 –

+0

ありがとう!私が好奇心が強いからと言って、私は尋ねていた。 – theo2003

5

オプティマイザは同じソリューションに両方のあなたのソリューションおそらく、最適化するために、アセンブリコードを確認してください。

私はおそらくとしてそれを実装します:そうオプティマイザはあなたの第二の溶液として、それは同じようになります読みやすさと高いため

int x = (b) ? i - 1 : i - 2; 

+3

私は 'int x = i - b? 1:2; 'i'は2回は言及しないでください – Slava

+1

私は' const int x = i - 2 + !! b'と書くことで、全く分岐しないようにしています。 –

+0

'int x = i - 2 + b'はうまくいくでしょうか? – theo2003

関連する問題