llvm-ir-and-passes について
LLVM IRと最適化パイプラインを調べ、考察する方法を学ぶためのスキルです。SSAの概念やLLVMツールによる変換の確認を扱い、ツールチェーンやパス作成の資料を補完します。
主な機能
- 01LLVM IRとSSAの概念
- 02ClangによるIR生成
- 03標準最適化パイプライン
- 04解析パスの確認
- 05最適化前後のIR比較
活用シーン
- 01-O2による変更の理解
- 02Clangバージョン間の誤コンパイル調査
- 03SSAと支配関係の学習
- 04カスタムパス作成の準備
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill llvm-ir-and-passesインストール後、Claude Code で/llvm-ir-and-passesを入力して読み込まれたか確認します。
詳細
LLVM IR とパス
目的
LLVM IR(SSA、型、ターミネーター)を読み解く方法、標準パスパイプラインのたどり方、調査に opt/llvm-dis を使用する方法をエージェントに教えます。skills/compilers/llvm(ツールチェーン)および skills/compiler-internals/llvm-passes(プラグインの作成)を補完するものであり、統合はしません。
使用する場面
- 生成された IR で
-O2によって何が変更されたかを把握するとき - Clang のバージョン間で発生する誤コンパイルを切り分けるとき
- カスタムパスの作成に取りかかるとき
- まだ C++ パスを書かずに、SSA と支配関係を教えるとき
ワークフロー
1. LLVM IR の構造
; Function in SSA form
define i32 @add(i32 %a, i32 %b) {
entry:
%sum = add i32 %a, %b
ret i32 %sum
}
主な概念:基本ブロック、合流点の PHI ノード、型付きの値(i32、ptr、ベクトル)。
2. Clang から IR を出力する
clang -S -emit-llvm -O0 -o foo.ll foo.c
clang -c -emit-llvm -O2 -o foo.bc foo.c
llvm-dis foo.bc -o foo.ll
3. 標準の最適化パイプライン(New PM)
Clang の -O2 では、おおむね次の処理が実行されます。
SimplifyCFG → InstCombine → GVN → LICM → LoopVectorize → ...
次のコマンドで調査できます。
opt -passes='default<O2>' -S foo.ll -o foo-opt.ll
opt -passes='default<O2>' -print-passes foo.ll 2>&1 | head
4. 便利な解析パス
| パス | 表示内容 |
|---|---|
-passes=print<domtree> | 支配木 |
-passes=print<loops> | ループのネスト |
-passes=print-alias-sets | エイリアスセット |
opt -passes='print<domtree>' -disable-output foo.ll
5. PHI と UB を読み解く
merge:
%v = phi i32 [ %a, %then ], [ %b, %else ]
IR の undef と poison は LLVM の poison セマンティクスをモデル化したもので、C の UB とは異なりますが、関連しています。
6. 最適化前後を比較する
opt -passes='instcombine,simplifycfg' -S foo.ll -o - | diff -u foo.ll -
7. エージェントでの使用
/llvm-ir-and-passes Explain this PHI node and which pass likely created it
よくある問題
| 症状 | 原因 | 修正 |
|---|---|---|
| パスが見つからない | LLVM のバージョン変更による名称変更 | 使用するビルドで opt --print-passes を実行する |
| IR が一致しない | LLVM のメジャーバージョンが異なる | clang/opt のバージョンをそろえる |
| 「optnone」によって最適化がブロックされる | -O0 属性 | -O1+ でコンパイルする |
| IR が巨大になる | インライン化されたヘッダー | -fno-discard-value-names をオフにし、関数で絞り込む |
| パイプラインが誤っている | Legacy と NPM の違い | -passes= 構文を使う |
関連スキル
skills/compilers/llvm— ツールチェーンの概要skills/compiler-internals/llvm-passes— PassPlugins の作成skills/compiler-internals/compiler-optimizations-deep— RA と ISelskills/compiler-internals/compiler-frontend— IR の生成skills/rust/rustc-basics—rustc --emit=llvm-ir
コメント
Markdown 対応