2025/12/03 21:14
You can't fool the optimizer
RSS: https://news.ycombinator.com/rss
要約▶
要約(300文字以内)
ARM用にコンパイルされた疑わしい符号なし加算関数群は、実際にはすべて単一の
add w0, w1, w0 命令へ最適化される。
- コンパイラは中間表現(IR)でコードを標準化し、数学的等価性を認識できる。
- 難読化や再帰呼び出しでも同一の最適化対象として扱われ、意図した計算結果を保持する。
- こうしたパターン認識は「超能力」のように頑健で、不要な複雑さを自動的に削除する。
重要ポイント
- IRによる正規化が鍵
- 単一命令への最適化例
- コンパイラの頑健なパターン認識能力
本文
私自身が執筆し、LLM が校正した記事です。
詳細は最後に記載しています。
デバッガでコードをステップ実行しているとき、複雑に見えるループが実際には 1 つの命令として実行されることがあります。コンパイラは難読化を透過的に 解釈し、結局は「明らかな」コードを生成します。
以下は ARM 用にコンパイルされた、極めて疑わしい符号なし加算ルーチンの集まりです(昨日の加算例とは異なります)。
いずれも
x + y を返すという点では大きく異なる実装ですが、
コンパイラはそれらをすべて見抜き、最終的には単一の
add w0, w1, w0 命令に置き換えます。再帰呼び出しを行う
add_v4 でさえも同じ命令へと最適化されます。
パターンを認識して効率的な代替案に差し替えるこの能力は、 コードが非常に難読化されていても、コンパイラが正しく動作するという 「超能力」です。プログラマは意図を明示した形でコードを書き、 生成はコンパイラに任せることで、多くの場合適切な最適化が行われます。
では、コンパイラはどのようにしてこれらのパターンを検出するのでしょうか?
「数値を加算するおふざけ的手段」のデータベースを保持しているわけではありません。
内部では、あなたのコードを中間表現(IR)へ変換します。これは解析しやすい
抽象化された簡略化版です。たとえば
add_v3 の while ループは、
「y を x だけ増やしてから y を返せ」という形に変換され、これを
「x + y を返せ」と数学的に同等であることが認識されます。このように
さまざまなコードパターンを標準化・正規化した形式へ変換するプロセスこそ、
コンパイラがそれらを同一視できる理由です。コード生成時には、4 つの関数すべてが同じ最適化対象として扱われます。
このパターン認識は驚くほど頑健であり、実際に書きたくないような
コードも快く最適化してしまいます。シリーズを通して、この正規化がどこまで
有効かを探ります。
この記事に付随する動画もご覧ください。
この投稿は Advent of Compiler Optimisations 2025 の第3日目で、25 日間にわたる コンパイラがコードを変換していく過程を追うシリーズです。 執筆者は Matt Godbolt(人間)で、LLM と人間によってレビュー・校正されています。
Compiler Explorer を Patreon や GitHub でサポートするか、CE 製品を Compiler Explorer Shop から購入してください。
2025 年 12 月 3 日 CST 午前 6 時に投稿しました。