ハクソク

世界を動かす技術を、日本語で。

LLVM: 悪い部分

概要

  • LLVM IRの設計課題とその進捗状況のまとめ
  • 高レベルな開発課題とコミュニティ運営の問題点
  • ビルド時間やCIの安定性、エンドツーエンドテストの不足
  • バックエンドの分断やパフォーマンス計測基盤の未整備
  • IR設計に関する根本的な問題点の指摘

LLVM IR設計課題と開発運営上の問題点

  • LLVM IRの設計上の課題は、継続的に改善が進められており、過去に指摘した問題のいくつかは既に解決または進行中
  • opaque pointers移行は完全に解決、constant expressionの削除はほぼ完了、ptradd移行も進行中
  • 本稿は、LLVMのリードメンテナー視点での改善機会のリストであり、LLVMを否定するものではなく、今後の発展のための指摘

レビュー体制の課題

  • 貢献者数は多いが、レビュー担当者が不足している現状
  • コードレビューは専門知識が必要で、即時的な価値を感じにくい
  • PR作成者がレビュワーを指定する方式は、新規参加者にとって障壁
  • RustのようなPR自動割当システム導入の検討余地

APIとIRの頻繁な変更(Churn)

  • LLVM C++ APILLVM IRは非安定で頻繁に変更
  • 柔軟性と進化の速さが強みだが、ユーザー側には追従コストが発生
  • C APIは比較的安定だが、すべてをカバーできない
  • LLVMの開発哲学「upstream or GTFO」による、外部コードの取り込み難しさ

ビルド時間の問題

  • LLVM本体は250万行超、モノレポ全体で約900万行
  • C++のビルド時間が長く、特に低スペック環境では厳しい
  • デバッグビルド時のリンク・メモリ・ディスク消費の増大
  • プリコンパイルヘッダーdylibビルドの導入、デーモン化によるテスト高速化などの改善策

CIの安定性

  • 200台以上のビルドボットによる多様な構成でのCI
  • 常に完全なグリーン状態にはならず、flakyなテストやビルドボット固有の問題が混在
  • pre-mergeテスト導入で状況は改善したが、ビルドボット問題は依然残る
  • コミット数・ビルド時間のスケール問題で、bors/merge queueのような手法の適用が困難

エンドツーエンドテストの不足

  • LLVMのテストは最適化パス単位のユニットテストが中心
  • パイプライン全体やミドルエンドとバックエンドの組み合わせのテストはほぼ未整備
  • 実行可能ファイルレベルのテストはllvm-test-suiteに分離されており、開発時には使われにくい
  • 基本操作の網羅的テストが不足しており、型サポートの制約も課題

バックエンドの分断

  • ミドルエンドは統一的だが、バックエンドは実装が分断・重複
  • ターゲット固有最適化やフックの乱用による分岐・重複の増加
  • 他ターゲットへの影響評価の難しさから、対応が限定的になりがち
  • エンドツーエンドテストの不足が問題を助長

コンパイル時間

  • LLVMのコンパイルは遅い。JITやRust/C++の大規模IR生成で特に顕著
  • 近年は改善傾向だが、依然として最適化なし(-O0)時もコストが高い
  • TPDE代替バックエンドは一桁速い実装例を示している

パフォーマンス計測基盤の未整備

  • ランタイム性能追跡の公式インフラが存在しない
  • 各組織が独自に追跡する状況で、貢献者が変更の影響を評価しにくい
  • LNTは存在するが、使い勝手やデータ量、PR単位のテスト依頼不可など多くの課題

IR設計上の根本的課題

  • undef値は未初期化値のモデル化に使われるが、複数回利用時の値の一貫性や最適化困難を招く
  • poison値への移行が進むが、メモリ内poisonの正しい扱いにはIRの追加機能(byte型など)が必要
  • 仕様の不完全性や健全性問題が一部未解決のまま残存

以上がLLVM IR設計および開発運営上の主要な課題と、その現状・背景のまとめ。今後の改善に向けた指針や議論の出発点となる内容。

Hackerたちの意見

いいまとめだね、ほとんど全部に同意するよ。二つコメントがあるんだけど: - LLVM IRは最近かなり安定してるよ。llvm 17から20にFil-Cを一日でリベースできたし。他のプロジェクトでも、複数のllvmバージョンで動くLLVMパスを維持してたけど、簡単にできたよ。 - LICMのレジスタプレッシャーは大きな問題だね、特にソースがCやC++じゃないときは。ここでの問題は必ずしもlicmじゃないと思う。regallocが再マテリアライズするように教えられる必要があるかもしれない。
> "regallocが再マテリアライズするように教えられる必要があるかもしれない" それは再マテリアライズの方法を知ってるし、かなり前からそうだったんだけど、バックエンドは一般的にもっとローカルで、オプティマイザよりも視認性が低いんだ。これが原因で、LICMが下した悪い決定を一貫して元に戻すのが難しくなってる。
再マテリアライズパスはあるし、レジスタ割り当てと結びつける理由は特にないよ。LLVMのregallocはすでにちょっと劣ってるし、フロントエンドの開発者がいくつかの可能性をベンチマークして適切な値を選べるように、すべての適切なノブやレバーを公開するのが面白いと思う。もちろん、これは言うは易し行うは難しだよね。
「LLVM IRは最近、驚くほど安定している。」って言うけど、俺はLLVMの専門家じゃないから、数年前に触ったときの感想だけど、LLVMは色んな言語の集合体みたいな感じだった。LLVMの世界の各ツールやコンポーネントは、それぞれ理解するためのルールや要件があったからね。IRは共通の言語というより、共通の語彙みたいなものだと思う。バージョン間でLLVM IRが安定していないことに戸惑ってたけど、その自由さが必要なんだって理解できたよ。俺、勘違いしてたかな?
最近数週間の議論を見てきて、LLVMに特に欲しいのは、CからではなくLLVM IRから始まる包括的な実行可能テストスイートだね。自分のバックエンドに取り組んだことがあるなら、SelectionDAGやGlobalISelに関するドキュメントがあまりないことに気づくと思うし、「X操作がサポートされていない場合はY操作の上にX操作をサポートする」という半分一般的なものが多いんだ。XやYの正確なセマンティクスが明確に文書化されていないから、間違ったものを作るのが簡単なんだよね。
コンパイル時間は問題だよ、LLVM自体だけじゃなくて、ユーザーにとってもね。Rustがその典型的な例だ。Rustは大きなものに対してコンパイル時間がひどくて、使うのが本当に面倒なんだよ。
> "コンパイル時間" LLVMの初期段階での売りの一つは、GCCよりもコンパイル時間がずっと速いことだったのを覚えてる。LLVMはGCCの約15年後に始まったから、LLVMはもう23年も経ってるし、また新しい何かが出てくるのかな。
数ヶ月前に、LLVMのためのもっと速い-O0バックエンドが書かれたみたいだけど、上流ではあまり注目されてないみたいだね。 https://discourse.llvm.org/t/tpde-llvm-10-20x-faster-llvm-o0... それに、LLVM IRを使わないコード生成プロジェクトもあって、Craneliftみたいに速いのもあるよ。 https://github.com/bytecodealliance/wasmtime/tree/main/crane...
> "これはやや驚くべきことではない。コードレビューは…レビューしている人(またはその雇用主)に即座の価値を提供しないかもしれない。" レビューで貢献したと「クレジット」をもらえるなら、もしかしたら人々(そして雇用主も、これはあまり可能性が低いかもしれないけど)がレビューをすることをもっと価値あるものと感じるかもしれないね。どんな形になるのかはわからないけど、GitHubに出てくるもので十分かもしれない。
正直、同じ現象が企業内でも問題になってるよ。私の雇用主はレビューの質と量を比較的よく評価してるけど(つまり、年次のパフォーマンスレビューで)、それでも満足できるレベルまで率を上げるには十分なモチベーションにはなってないんだよね。
参考までに、記事には「フロントエンドは、主に安定したC APIを使えるので、これからある程度隔離されている。」って書いてあるけど、俺たちの経験とはちょっと違うな。APIの中にはある程度安定している部分もあるけど、他の部分(例えばOrc)はめちゃくちゃ変わるからね。
そうそう、OrcのC APIは他のC APIとは違うルールに従ってるよ。 (https://github.com/llvm/llvm-project/blob/501416a755d1b85ca1...)
ねえニキータ、これ読んでたらありがとう!PHPへの貢献、感謝してるよ!君がいなくて寂しいよ!
6年前、8GBのDell 9360ノートパソコンでLLVMを結構定期的にビルドしてたんだ。コンパイラ関連の契約の時にね。(実際、今でも持ってるけど、あれは安いウルトラブックにしては妙に壊れないんだよね。)ビルド時間はそんなに良くなかったけど、許容範囲だったよ。リンクの並列性を減らせば、メモリ制約内に収まったからね。今でもそんなマシンでLLVMをコンパイルするのは可能なのかな?それとも8GBじゃもう無理なのかな?