べき等関数への追加の呼び出しを削除するにはどうすればよいですか?

ヴァンジョー

後続の2つの呼び出しに同じ引数がある場合、副作用のある関数は1回だけ呼び出す必要があることをgccに伝える方法はありますか?次の動作が必要です。

foo(6);//run this function
foo(6);//optimize this away
foo(6);//optimize this away
foo(5);//run this function
foo(6);//run this function again

foo作業を行う前にグローバル変数チェックすることはできますが、それは最適ではありません。

void inline foo(int i){
   static int last_i=i+1;
   if(last_i != i){
        last_i==i;
        //do_work...
    }
}

以来foo、インライン関数があるコンパイラがのinvokations見ていくことができるはずですfoo()、それはそれを実行する必要がないことを参照してください。問題は、コンパイラーがグローバル変数に対してそのように最適化できないことです。コンパイラーにそれが安全であることを知らせる方法はありますか?

ヴァンジョー

したがって、最後に使用した引数をチェックすることを躊躇した理由は、関数呼び出しが非常にタイトな内部ループ内にあったため、特に分岐予測のある(または非常に貧弱な)プラットフォームでは、余分な比較と分岐命令が煩わしいためです。 。

私はそれを試したときにgccが何をするかを見ることにしました。次のコードを使用しました。

#include <stdio.h>
int check;

void myfun(int num){
        printf("changing to %d\n",num);
}
static inline __attribute__((always_inline)) void idem(int num){
    if(num!=check){
        myfun(num);
        check=num;
    }
}

int main(){
    idem(5);
    idem(5);
    idem(4);
    idem(4);
    return 0;
}

これgcc -O2 main.cは、x86(私の最終ターゲットではない)で)を次のようにコンパイルします

0000000000400440 <main>:
  400440:       48 83 ec 08             sub    $0x8,%rsp
  400444:       83 3d e5 0b 20 00 05    cmpl   $0x5,0x200be5(%rip)        # 601030 <check>
  40044b:       74 14                   je     400461 <main+0x21>
  40044d:       bf 05 00 00 00          mov    $0x5,%edi
  400452:       e8 09 01 00 00          callq  400560 <myfun>
  400457:       c7 05 cf 0b 20 00 05    movl   $0x5,0x200bcf(%rip)        # 601030 <check>
  40045e:       00 00 00 
  400461:       bf 04 00 00 00          mov    $0x4,%edi
  400466:       e8 f5 00 00 00          callq  400560 <myfun>
  40046b:       c7 05 bb 0b 20 00 04    movl   $0x4,0x200bbb(%rip)        # 601030 <check>
  400472:       00 00 00 
  400475:       31 c0                   xor    %eax,%eax
  400477:       5a                      pop    %rdx
  400478:       c3                      retq   
  400479:       90                      nop
  40047a:       90                      nop
  40047b:       90                      nop

ご覧のとおり、myfunは私が望むように2回しか呼び出されません。したがって、gccがこれを正しく行うことが可能であるように見えます。誰かがここでの最適化の制限についてチャイムを鳴らしたいのなら、私は非常に興味があります

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

関数への再帰呼び出しを返すにはどうすればよいですか?

分類Dev

特定の関数が呼び出されたときに関数を呼び出す関数を作成するにはどうすればよいですか?

分類Dev

`into()`への複数の呼び出しをチェーンするにはどうすればよいですか?

分類Dev

LLVMで関数呼び出しの引数を取得するにはどうすればよいですか?

分類Dev

関数呼び出しの後で変数を変更するにはどうすればよいですか?

分類Dev

この関数の呼び出しを単純化するにはどうすればよいですか?

分類Dev

関数が呼び出されるたびに、関数を別の関数に追加するにはどうすればよいですか?

分類Dev

特定の関数からのすべてのAJAX呼び出しがいつ終了したかを知るにはどうすればよいですか?

分類Dev

関数呼び出しのselectで行全体を使用するにはどうすればよいですか?

分類Dev

関数を呼び出してその結果を使用するにはどうすればよいですか?

分類Dev

関数が再度呼び出された場合、関数の最初の呼び出しの実行を停止するにはどうすればよいですか?

分類Dev

C ++の外部関数から削除演算子を呼び出すにはどうすればよいですか?

分類Dev

dplyrのRmutate関数から関数を呼び出して、計算列を追加するにはどうすればよいですか?

分類Dev

関数の外部でipc呼び出しから結果を利用できるようにするにはどうすればよいですか?

分類Dev

間隔内で関数への複数の呼び出しを停止するにはどうすればよいですか?

分類Dev

2つの異なる関数から2つの変数を呼び出して追加するにはどうすればよいですか?(Python3)

分類Dev

Cのループで関数として呼び出されているchar画像を削除するにはどうすればよいですか?

分類Dev

Pythonソースコードで使用されるすべての関数とAPI呼び出しを抽出するにはどうすればよいですか?

分類Dev

関数を使用して別の関数を呼び出すにはどうすればよいですか?

分類Dev

実行時に関数のすべての呼び出しを一覧表示するにはどうすればよいですか?

分類Dev

非同期関数を同時に呼び出してすべてのコールバックを待機するにはどうすればよいですか?

分類Dev

別のファイルからGitの関数への呼び出しを見つけるにはどうすればよいですか?

分類Dev

別のクラスから静的関数を呼び出すときに「存在しない」を修正するにはどうすればよいですか?

分類Dev

LLVM APIを使用して関数mallocへの呼び出しを作成するにはどうすればよいですか?

分類Dev

WebJobのJobHost.CallAsyncを介して呼び出すことができるF#で関数を宣言するにはどうすればよいですか?

分類Dev

input関数を使用して変数の値を呼び出すにはどうすればよいですか?

分類Dev

関数が呼び出されるたびに、関数の呼び出し場所にアクセスするにはどうすればよいですか?

分類Dev

cppcheckを使用して未使用の関数からのみ呼び出される関数を検出するにはどうすればよいですか?

分類Dev

promiseから呼び出し元の関数に値を返すにはどうすればよいですか?

Related 関連記事

  1. 1

    関数への再帰呼び出しを返すにはどうすればよいですか?

  2. 2

    特定の関数が呼び出されたときに関数を呼び出す関数を作成するにはどうすればよいですか?

  3. 3

    `into()`への複数の呼び出しをチェーンするにはどうすればよいですか?

  4. 4

    LLVMで関数呼び出しの引数を取得するにはどうすればよいですか?

  5. 5

    関数呼び出しの後で変数を変更するにはどうすればよいですか?

  6. 6

    この関数の呼び出しを単純化するにはどうすればよいですか?

  7. 7

    関数が呼び出されるたびに、関数を別の関数に追加するにはどうすればよいですか?

  8. 8

    特定の関数からのすべてのAJAX呼び出しがいつ終了したかを知るにはどうすればよいですか?

  9. 9

    関数呼び出しのselectで行全体を使用するにはどうすればよいですか?

  10. 10

    関数を呼び出してその結果を使用するにはどうすればよいですか?

  11. 11

    関数が再度呼び出された場合、関数の最初の呼び出しの実行を停止するにはどうすればよいですか?

  12. 12

    C ++の外部関数から削除演算子を呼び出すにはどうすればよいですか?

  13. 13

    dplyrのRmutate関数から関数を呼び出して、計算列を追加するにはどうすればよいですか?

  14. 14

    関数の外部でipc呼び出しから結果を利用できるようにするにはどうすればよいですか?

  15. 15

    間隔内で関数への複数の呼び出しを停止するにはどうすればよいですか?

  16. 16

    2つの異なる関数から2つの変数を呼び出して追加するにはどうすればよいですか?(Python3)

  17. 17

    Cのループで関数として呼び出されているchar画像を削除するにはどうすればよいですか?

  18. 18

    Pythonソースコードで使用されるすべての関数とAPI呼び出しを抽出するにはどうすればよいですか?

  19. 19

    関数を使用して別の関数を呼び出すにはどうすればよいですか?

  20. 20

    実行時に関数のすべての呼び出しを一覧表示するにはどうすればよいですか?

  21. 21

    非同期関数を同時に呼び出してすべてのコールバックを待機するにはどうすればよいですか?

  22. 22

    別のファイルからGitの関数への呼び出しを見つけるにはどうすればよいですか?

  23. 23

    別のクラスから静的関数を呼び出すときに「存在しない」を修正するにはどうすればよいですか?

  24. 24

    LLVM APIを使用して関数mallocへの呼び出しを作成するにはどうすればよいですか?

  25. 25

    WebJobのJobHost.CallAsyncを介して呼び出すことができるF#で関数を宣言するにはどうすればよいですか?

  26. 26

    input関数を使用して変数の値を呼び出すにはどうすればよいですか?

  27. 27

    関数が呼び出されるたびに、関数の呼び出し場所にアクセスするにはどうすればよいですか?

  28. 28

    cppcheckを使用して未使用の関数からのみ呼び出される関数を検出するにはどうすればよいですか?

  29. 29

    promiseから呼び出し元の関数に値を返すにはどうすればよいですか?

ホットタグ

アーカイブ