- ベストアンサー
インライン展開でコンパイラが何をやっているのか知りたいです
インライン展開すると、関数の呼び出しオーバーヘッドが小さくなることはわかるのですが、インライン展開した場合としていない場合と、なぜ関数呼び出しのオーバーヘッドがなくなるのかアセンブルレベルでの違いがよくわからないです。 関数をインライン展開した場合、コンパイラはどのようにコンパイルするのか、そしてその関数実行時の振る舞いがインライン展開なしの場合とどう違うのか、わからないので教えていただけませんか? 以上、よろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
簡単に言うと 1.引数のコピー処理 2.CALL命令 3.戻り値のセット処理 4.RET命令 の分が多くなります。 変な例えですが、冷蔵庫を家の外に置いておくと、上着を着て履物を履いて出て行き、戻ると履物を脱いで、上着を脱ぐといったようなものです。 上の1の引数のコピー処理はCall by value(値渡し)の場合におこります。
その他の回答 (3)
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
#2: loopのun-rollとinlineは別物じゃないですか?
- jacta
- ベストアンサー率26% (845/3158)
引数や返却値のコピーとサブルーチンの往復に関しては既に別の方が回答されていますが、それ以外にも違いが現れます。 インライン関数を呼び出す部分をコンパイルする際、コンパイラは呼び出そうとする関数の中身のことまで全て分かることになります。これによって関数の枠組みを超えた最適化が可能になります。 関数の枠組みを超えた最適化は、引数に定数式を渡した場合等に最も顕著になり、場合によっては関数の呼び出しが単なる定数として展開される可能性もあります。 他に、例外処理に関しても大きな影響が現れます。例外指定によって明示的に例外が発生しないことを宣言しない限り、通常の関数であればあらゆる例外が発生するものとして、それに対応するために処理を展開する必要がありますが、インライン関数であれば、関数の中身が分かっていますから、可能であれば例外が発生しないものとして扱うことが可能になります。これによって(多くの場合)速度もサイズも大幅な改善が可能になります。
- 春原 なの(@ymda)
- ベストアンサー率37% (668/1777)
単純な例でいいますと、こうなります。 for(i=0;i<10;i++) { func(); } は funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身; のようになります。 上記の例ですと、i変数を使ってループしていますが、i変数を加算したり評価したりする部分、 そして、関数のcall、引数のセット等、ret がなくなり、その分だけ速度が向上します。 しかし、funcの中身が大きかったりループ数が多ければ 命令がL1キャッシュに入りきらず、かえって速度が低下することがあるので コンパイラはそのあたりも自動的に判断します。