
2026/06/03 2:37
QBE コンパイラバックエンド 1.3
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
改良された要約:
QBE バージョン 1.3 は、バージョン 1.0(大まかには 7k 行の追加と 1.5k 行の削除)に対する飛躍的な進歩を意味し、リンケージとアーキテクチャ互換性の改良—特に Scott Graham が Upstream で導入した
-t amd64_win フラグを介した Windows 向けのサポート—を通じて、コンパイラを実運用向けに近づけることを目指している。このリリースは、位置不依存コードのサポートを追加し、多くのターゲットで共有オブジェクトのシームレスなリンケージを可能にし、またランタイムではなくリンケージ時に割り当てられるアドレスではなく、実行時において割り当てられるアドレスを表す新しい IL extern「動的定数」(DYNCONST)を通じた間接的全局アクセスを追加する。
パフォーマンス最適化は主に coremark 分析に基づいており、標準ベンチマークソースコードを改変せずに GCC の
-O2 パフォーマンスからのギャップを 40% から 63% 以上まで縮めた;対象となった改良(例:ee_isdigit のインライン化、crcu8 の簡素化)により、QBE はその約 70% の目標に達する。主要な最適化には GVN/GCM、ループ最適化、if-elimination、CFG 簡素化が含まれる一方、QBE の関数単位ストリーミングモデルとの互換性を維持するため、インライン化は除外されている。新しい OCaml ツール mgen は、算術の結合法や交換法則など複雑なコードパターンを扱い、DAG ナンバーと BitSet を用いたパターンマッチングにより IL パターンに一致する慣用的 C コードを生成する。
ベンチマーク結果では、QBE 1.3 と 1.2 の比較において Hare テストスイートにおける実行時間は 33% 減少した(2.6s から 1.7s に)。出力は AT&T 表記であり、mingw ツールで組み立てるのが最も適している。全体として、QBE 1.3 は Windows とクロスプラットフォーム環境をサポートしつつ、業界標準のコンパイラと現実世界のアプリケーションにおいて競合できる高性能な代替手段としての位置づけを獲得している。
本文
QBE 1.3 リリースノート
QBE 1.3 は、開発に時間を要したにもかかわらず 1.0 以降最も意義深いリリースです。約 7,000 行の新規コードを追加し、約 1,500 行のコードを削除するリファクタリングを実施しました。主な更新点は以下の通りです。
- 独自のパターニング IL マッチングアルゴリズムを採用
- Roland Paterson-Jones と Scott Grahamによる新しい最適化機能を追加
- Michael Forneyの提言に基づき、位置不依存コード(共有オブジェクト動作)の実装を追加
- チームワークによる成果であり、すべての貢献者に感謝します
より高速化
QBE は常に速度向上への挑戦を続けます。今回は
Coremark ベンチマークにおいて具体的な最適化課題が浮上し、特に以下の 2 つの関数処理がボトルネックとなっていました:
ee_isdigitcrcu8
これらは従来の C の慣習(例:論理積演算子として
&& を用いるなど)に従っておらず、性能に支障をきたしていましたが、QBE のインライン化機能の欠如だけが原因ではないことが分かりました。CPU 依存型コードの大部分はコンパクトなセクションで処理されるという想定通りでした。
実装された最適化
以下の最適化パスを実装し、パフォーマンスを向上させました:
- GVN/GCM(共有値ノード・グローバル共通部分除去)
- ループ最適化
- if-消去
- CFG の簡素化
達成した成果
- インライン化を一時的に最適化セットから排除し、他社商用コンパイラに対するスコアを 63% 超えることに成功しました。
- ベンチマーク自体の修正(
のインライン化、ee_isdigit
の分岐不使用実装への置換)により、**目標の 70%**を達成しました。crcu8
Hare テストスイートでの改善
Hare ユーザー向けにも有益な改善が見られました:
- qbe-1.2 から 33% の速度向上(1.7 秒 → 2.6 秒へ)を実測
より賢く
QBE は Ken Thompson の Plan9 C コンパイラに触発され、長年「bottom-up 型ツリー番号付けアルゴリズム」を使用してきましたが、算術演算子の結合律と交換律の扱いに微妙な課題がありました。
新しい OCaml ツール「mgen」の導入
QBE 1.3 でこの課題をメタプログラミングにより解決。新ツール
mgen が以下の機能を提供します:
- lispy 形式の IL パターンを C コードへコンパイル
- IL パターンを含む特別コメントブロックを検出し、該当箇所にマッチする C コードを自動インライン化
- 生成されたコードは QBE 内の慣習的な記述に準拠し、1.3 以前のロジックと同等の動作を保証
命令 DAG と番号付け
- 命令 DAG(Directed Acyclic Graph)を Ken Thompson コンパイラと同様の手法で番号付け
が各ノードに対し、トップレベルユーザーパターンとの一致度をビットセットで関連付けmgen- 最適なパターンは手書きロジックにより選択され、変数を含む場合はマッチプログラム実行を通じて収集
将来の展開
mgen は以下への拡張が予定されています:
- 多様なバックエンドにおける命令選択の簡素化
- IL パターン(例:ビット回転)の認識による最適化パス強化
より使いやすく
Windows ABI の対応
Scott Graham が貢献してくれたWindows ABI のアップストリーム実装が採用されました。
- 生成されるアセンブリは引き続き AT&T スキプトを使用
- mingw アンセーブラとの相性が最適ですが、Windows 環境でのテストは行われていません
- Windows 向けコンパイルには以下のオプションを使用します:
qbe -t amd64_win <input.c>
位置不依存コード(PIC)の大幅強化
共有オブジェクト生成が今やほぼ全てのターゲットで問題なくリンク可能になりました。
- 主な障害物だったグローバル変数の間接アクセス(例:ELF のグロバルオフセットテーブル)をサポート
- 新しい IL の外部フラグ
(動的定数)を導入し、IL レベルからサポートDYNCONST
動的リンクライブラリでの変数アクセスの例
動的リンカーが割り当てる実行時アドレスシンボルにアクセスするには:
function w $load() { @start %v =w load extern $dlvar ret %v }
用語解説:「動的定数」
このオキシモロンな用語は以下の理由で使用されています:
- コンパイル時の静的リンクフェーズではなく、ランタイムまたはダイナミックリンカーで割り当てられる
- アドレスシンボルが実行時においてのみ既知であるため(=動的)