
2026/08/10 20:34
C言語における尾再帰最適化は比較的新しく(2025年)です
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
現代の C コンパイラ(GCC、Clang など)は、歴史的な制約を克服し、堅牢なテールコール最適化を実現しました。これにより、現在の関数の呼び出し元がスタックをクリーンアップでき、次のコールのために残さず済むようになりました。この画期的な進歩により、以前なら厳格なコール規約(呼び出し元が返却する前に引数を除去することを強制されていた)の下では不可能だった高度なコンパイル技術が可能になりました。最新のテストでは、主要なコンパイラの双方が複雑な使用パターンを効果的に処理することが確認され、別個の間接呼び出し制限を必要としないことが判明しました。これは、膨大なコードベースを処理するに関する研究からの発見を裏付けています。「Copy-and-Patch Compilation」という Xu および Kjolstad による論文はこの最適化を利用しており、その実装は 10 万ものコードスニペットを使用してテストされました。歴史的には、C の標準がコール側でのクリーンアップを許容しなかったのは 1994 年までであり、2001 年の初期の最適化ですら間接呼び出しでは失敗しました。この制限のため、Gforth などのレガシシステムは 2,000 スニペット未満しかサポートできませんでした。現在、ツールは 10 万という異なるコードスニペットを処理する準備が整っており、goto*ベースのシステムにおいて多数のスニペットを必要とする技術を実行可能にしていますが、Gforth にこれらの特定の最適化を組み込む作業はまだ完了していません。この進歩により、Python の開発者や広く業界全体は、自らのコミュニティによって以前から導入された強力な機能を採用することができ、かつて堅固なスタック管理のルールによってブロックされていた新たな戦略への扉が開かれています。この機能を実装した最初の Python コミュニティには賞賛を送りたいと思います。
本文
C 言語における尾部呼び出し最適化の経緯と現状
はじめに
C 言語における**尾部呼び出し最適化(Tail Call Optimization: TCO)**は比較的新しい技術です。Python コミュニティが最先端を走り、そのパフォーマンス向上において重要な進展となっています。
C 言語での TCO の歴史的経緯
当初から TCO が実装されていたわけではなく、呼出規約の限界が存在しました。
- スタック削除の前提
- 従来の呼出規約では、コールされた関数(callee)が、呼出し側(caller)によってスタック上に置かれたデータを削除しないことを前提としていました。
- コール先が引数を処理しようとしても機能せず、結果として呼び出しは非尾部呼び出しとみなされました。
- 実装の進展
- 1994 年:当時の C コンパイラでは TCO がサポートされていませんでした。
- 2001 年:Mark Probst が GCC で専用の呼出規約を導入し、TCO を実装しました。
- ただし、当时的な制限事項があり、**「間接呼び出しに対応できない」**という欠点を持っていました(インタプリタディスパッチにおいて重要)。
GCC と Clang の現在の状況
著者は以前から GCC 内部の
goto * メカニズムには満足していたものの、近年の研究論文により TCO が活用されていることを確認しました。
- 技術的背景
- Xu と Kjolstad による論文「Copy-and-Patch Compilation」において TCO の活用事例が示されました。
- 検証結果
- GCC や Clang を実際に検証したところ、記事で示されている種類の尾部呼び出しに対して最適化を実行し、正常動作することを確認できました。
- 規模の比較
- 論文: 10 万個以上のコード断片を検討対象としています。
- Gforth: VM 命令やスタックキャッシュなど、静的なスーパー指令に限定され、2,000 未満の断片にとどまります。
今後の展望
TCO の活用が巨大規模のコードに対応できるようになれば、
goto * ベースでは実用不可能だった多数の異なるコード断片を処理する技術も利用可能になります。
- 現状: まだ Gforth への正式導入段階ではありません。
- 祝福: Python コミュニティがこの領域を先取りしたことを祝意を表します。