1. ホーム
  2. c

[解決済み] gcc のオプション -fomit-frame-pointer を理解しようとしています。

2023-04-08 01:39:37

質問

の意味を教えてほしいとGoogleに依頼しました。 gcc オプション -fomit-frame-pointer を指定すると、以下の文にリダイレクトされます。

-fomit-frame-pointer

フレームポインタを必要としない関数のために、フレームポインタをレジスタに保持しないようにします。これは、フレームポインタを保存、設定、復元する命令を回避します。また、多くの関数で余分なレジスタを利用できるようにします。また、一部のマシンではデバッグが不可能になります。

各関数の私の知識では、すべてのローカル変数といくつかのより多くの情報を保持するために、プロセス メモリのスタックに活性化レコードが作成されるでしょう。このフレーム ポインターが、関数の起動レコードのアドレスを意味することを願っています。

この場合、フレームポインタをレジスタに保持する必要がない関数はどのようなものでしょうか。フレームポインタをレジスタに保持しない場合、バイナリではいくつかの命令が省略されるからです。これは、多くの関数があるアプリケーションにおいて、本当に顕著にパフォーマンスを向上させるでしょう。

どのように解決するのですか?

ほとんどの小さな関数はフレームポインタを必要としませんが、大きな関数は必要かもしれません。

それは本当に、コンパイラがスタックがどのように使用され、スタックのどこに何があるのか(ローカル変数、現在の関数に渡された引数、呼び出されようとしている関数に準備されている引数)をどれだけうまく追跡できるかによります。フレーム ポインターを必要とする関数と必要としない関数を特徴付けるのは簡単ではないと思います (技術的には、フレーム ポインターを持つ必要のある関数はありません。むしろ、コンパイラが他のコードの複雑さを軽減するために必要だと判断した場合です。)。

コーディングの戦略の一部として、関数にフレーム ポインタを持たせないようにしようとするのはどうかと思います。 -fomit-frame-pointer そうすれば、レジスタ・アロケータが使用できるレジスタが 1 つ増え、関数への入出力のための命令が 1 ~ 3 個節約できます。もし関数にフレームポインタが必要なら、それはコンパイラがフレームポインタを使わないよりその方が良いと判断したためです。フレーム ポインターを使用しない関数を作成することが目標ではなく、正しくかつ高速に動作するコードを作成することが目標なのです。

フレーム ポインターを持たないことは、パフォーマンスを向上させるはずですが、特に x86-64 では、すでに 16 本のレジスタで開始しているため、大きな改善をもたらす魔法の弾丸ではないことに注意してください。32ビットx86では、8本のレジスタしかないので、そのうちの1本をスタックポインタとし、もう1本をフレームポインタとして使用すると、レジスタスペースの25%を占有していることになります。これを12.5%にするのは、かなりの改善といえる。もちろん、64 ビット用にコンパイルすることも大きな助けになります。