次のようなアプリを作成する場合:
- シングルスレッド
- コール グラフにサイクルがない
- alloca またはVLAを使用しない
最新のプログラム全体を最適化するコンパイラは、すべてのスタック割り当て (GCC、MSVC、ICC など) を最適化できますか? そのような状況では、可能なすべてのスタックスペースを静的に割り当てることができるはずです。「プログラム全体」とは、コンパイラが /all/ ソースコードにアクセスできることを意味します (実行時に dlopen することはできません)。
次のようなアプリを作成する場合:
最新のプログラム全体を最適化するコンパイラは、すべてのスタック割り当て (GCC、MSVC、ICC など) を最適化できますか? そのような状況では、可能なすべてのスタックスペースを静的に割り当てることができるはずです。「プログラム全体」とは、コンパイラが /all/ ソースコードにアクセスできることを意味します (実行時に dlopen することはできません)。
コンパイラがこれを行うことは可能ですが、それはおそらくそうしないような特定の最適化です。
完全にインライン化されたプログラムがある場合は、関数呼び出し用にスタック フレームを設定するオーバーヘッドを処理します。
ただし、ローカル変数のスタック割り当ても削除したい場合、コンパイラはそれらのローカル変数をグローバル変数に変換する必要があります。私が知っているコンパイラはそれを行いません。一部のプラットフォームでは、ローカル変数と比較してグローバル変数を参照するために追加の命令が必要です (アドレスは 1 つではなく 2 つの命令でロードする必要があるため)。さらに、スタック変数の参照は非常に一般的な操作であるため、通常はより小さな命令にエンコードされます。
これは、コメントとしては長すぎるコメントです。
理論的にはすべてのスタック割り当てが最適化されている可能性がありますが、必要以上に割り当てられる可能性があることに注意してください。これはOPが求めていたものではありませんが、検討するのは興味深いかもしれません. 必要な最小サイズの割り当てを見つけることは、停止問題を解決することと同じです。次のような構造のプログラムを想像してください。
<do 'something'>
<call last thing which happens to require more
stack space than everything else in 'something'>
<do 'something'>
「停止」した場合にのみ、追加のスタック スペースが必要になります。
最適化が恣意的に難しくなる他のバリエーションも想像できます。たとえば、プログラムはユーザー入力で 3SAT 式を単純に評価し、それに応じて何かを実行できますが、その 3SAT 式には、結果が true になる値がある場合とない場合があります。
おそらく、もっと些細なケースがあります: ユーザーは、処理のために多くのスタック スペースを必要とする入力を決して入力しないかもしれません。
リストに「外部ライブラリを使用しない」を追加しない限り、外部関数の呼び出しにはスタックのセットアップが必要になります。これは、呼び出しコードが特定の方法でパラメーターを渡すことを期待してコンパイルされているためです。さらに、そのようなライブラリは、ほぼ確実に、独自のローカル用にスタック自体を調整する必要があります。
さらに、正確なアプリケーションによっては、スタックが静的に割り当てられることがわかっている場合でも、スタックが必要になるコードなどへのコールバックがないことをコンパイラが認識するのは非常に難しい場合があります。割り当て。
スタックスペースの割り当てはすでに簡単に高速であるため、コンパイルがこの最適化を試みるケースはわかりません(私が信じているいくつかのレジスタ操作)