関数のインライン化基準
C++/C99言語では、"inline"キーワードが正式にサポートされており、コンパイラに対して関数を「インライン化してほしい」と要求することができます。しかし、良く知られていることですがこれはあくまでヒントなので、コンパイラの気分次第でインライン化が起きたり起きなかったり曖昧な点があります。
そこで、g++で、ある関数(フリー関数およびメンバ関数)がどういう時にインライン展開されるのかをまとめてみました。g++ 3.3.2 で -S したアセンブリ言語のリストを目視で確認しました。なお、「ある関数」の処理内容は "整数値123をリターンするだけ" と、充分に単純なものしておきました。
結果、おおよそ次のような基準でインライン展開の有無を決定していると思われます。
ただしワタクシ、横着してGCCのソースは一切読んでいませんのでその点ご注意ください(笑)。
if (関数に__attribute__((always_inline)) が指定されている?) { インライン化する; } else if (最適化(-O1以上)あるいは-finlineが指定されている?) { if (関数がinline修飾されている?) { if (充分に単純な関数?) { // (1) インライン化する; } else { インライン化しない; } } else if (-finline-functionsが指定されている?) { if (充分に単純な関数?) { // (2) インライン化する; } else { インライン化しない; } } else { インライン化しない; } } else { インライン化しない; } ※ (1)と(2)は微妙に判断基準が異なるようだ。(1)のほうがtrueになりやすいように思う。 ※ -O3以上では-finline-functionsが自動設定される。
なお、「inline修飾」については、C++のヘッダファイル中に直接
class Foo { public: int foo(void) { return 123; } };
のようにして実装を記述した場合も「inline修飾」ありと同等の結果になりました。ただし、
class Foo { public: int foo(void); }; inline int Foo::foo(void) { return 123; }
のようにしてヘッダファイル内だがクラス定義部分の外に実装を記述した場合には、明示的にinlineと書かなければ「inline修飾」なしと同等の結果になりました。
最後に、inline修飾が効かなかった場合を検出するため、時間性能を気にしなければならない場所では-Winline(下記のヘルプ参照)を使いましょう。
$ LANG=C g++ -v --help 2>&1 | grep inline | sort --param max-inline-insns=<value> The maximum number of instructions in a function that is eligible for inlining -Wextern-inline Warn when a function is declared extern, then inline -Winline Warn when an inlined function cannot be inlined -finline Pay attention to the 'inline' keyword -finline-functions Integrate simple functions into their callers -finline-limit=<number> Limits the size of inlined functions to <number> -fkeep-inline-functions Generate code for funcs even if they are fully inlined -fno-default-inline Do not inline member functions by default -fno-implement-inlines Export functions even if they can be inlined -fno-implicit-inline-te Only emit explicit instatiations of inline templates -minline-all-stringops Inline all known string operations -mno-inline-all-stringops Do not inline all known string operations
余談ですが、gcc --help すると、infoにも載っていないようなオプションが出てきたりしてびっくりです(w