mcpField
L
llvm-passes

llvm-passes

github.com/mohitmishra786開発269300 回インストール18 週間前に更新
リポジトリ

llvm-passes について

New Pass Manager を使って LLVM の最適化や IR 変換を行う開発者向けのスキルです。プラグイン登録、解析、テスト、デバッグの手順を扱います。

主な機能

  1. 01FunctionPass と ModulePass の作成
  2. 02Pass プラグインの登録と実行
  3. 03制御フローとエイリアス解析の利用
  4. 04IR 変更と解析情報の管理
  5. 05llvm-lit と FileCheck によるテスト
  6. 06Pass の確認、検証、デバッグ

活用シーン

  1. 01LLVM コンパイラーへの独自最適化の追加
  2. 02インライン化、死コード除去、lowering の実装
  3. 03ループと制御フローの解析
  4. 04Pass 順序や IR エラーの調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill llvm-passes

インストール後、Claude Code で/llvm-passesを入力して読み込まれたか確認します。

詳細

LLVM パス

目的

New Pass Manager を使った LLVM 最適化パスの作成方法として、FunctionPass と ModulePass の構成、PassPluginLibraryInfo の登録、opt -load-pass-plugin を使った実行、一般的な解析ユーティリティ(DominatorTree、LoopInfo、AliasAnalysis)、IR の変更パターン、llvm-lit によるテスト、opt -print-after-all を使ったデバッグについて、エージェント向けに説明します。

使用する場面

  • LLVM ベースのコンパイラーにカスタム最適化を追加するとき
  • IR 変換パス(インライン化、DCE、カスタムな低水準化)を作成するとき
  • ドミネーターツリーやループ情報を使って制御フローを解析するとき
  • FileCheck と llvm-lit でパスをテストするとき
  • パスの順序や IR の破損をデバッグするとき
  • プラグインを介して Clang にパスを統合するとき

ワークフロー

1. New Pass Manager のアーキテクチャ
opt / clang
├── ModulePassManager
│   └── FunctionPassManager (per function)
│       └── FunctionPass instances
└── AnalysisManager (cached analyses)

パスは使用する解析を宣言します。IR が変更されると、解析は無効になります。

2. 最小限の FunctionPass(C++ プラグイン)
// MyPass.cpp
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {

struct MyPass : PassInfoMixin<MyPass> {
    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
        bool changed = false;
        for (BasicBlock &BB : F) {
            for (Instruction &I : BB) {
                if (auto *Call = dyn_cast<CallInst>(&I)) {
                    if (Call->getCalledFunction() &&
                        Call->getCalledFunction()->getName() == "dead_func") {
                        Call->eraseFromParent();
                        changed = true;
                    }
                }
            }
        }
        return changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
    }
};

} // namespace

extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() {
    return {
        LLVM_PLUGIN_API_VERSION, "MyPass", "v0.1",
        [](PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](StringRef Name, FunctionPassManager &FPM,
                   ArrayRef<PassBuilder::PipelineElement>) {
                    if (Name == "my-pass") {
                        FPM.addPass(MyPass());
                        return true;
                    }
                    return false;
                });
        }
    };
}
# CMakeLists.txt
find_package(LLVM REQUIRED CONFIG)
add_library(MyPass MODULE MyPass.cpp)
target_include_directories(MyPass SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS})
target_compile_definitions(MyPass PRIVATE ${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(llvm_libs core passes support)
target_link_libraries(MyPass PRIVATE ${llvm_libs})
cmake -B build -DLLVM_DIR=$(llvm-config --cmakedir)
cmake --build build
3. opt を使った実行
# Run pass on IR file
opt -load-pass-plugin ./build/MyPass.so -passes=my-pass -S input.ll -o output.ll

# Print IR after each pass
opt -load-pass-plugin ./build/MyPass.so -passes=my-pass -print-after-all input.ll -o /dev/null

# Pass pipeline string
opt -passes="function(instcombine),my-pass,function(dce)" input.ll -S -o out.ll
4. ModulePass の例
struct MyModulePass : PassInfoMixin<MyModulePass> {
    PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
        for (Function &F : M) {
            if (F.isDeclaration()) continue;
            // module-level transformation
        }
        return PreservedAnalyses::none();
    }
};

プラグインのコールバックで ModulePassManager に登録します。

5. 解析ユーティリティ
#include "llvm/Analysis/DominatorTree.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/AliasAnalysis.h"

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
    auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
    auto &LI = AM.getResult<LoopAnalysis>(F);
    auto &AA = AM.getResult<AAManager>(F);

    for (Loop *L : LI) {
        BasicBlock *Header = L->getHeader();
        // Loop invariant code motion, etc.
    }

    DominatorTreeNode *IDom = DT.getNode(&F.getEntryBlock());
    (void)IDom;
    return PreservedAnalyses::all();
}

使用する解析を宣言します。

AnalysisUsage MyLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired<DominatorTreeWrapperPass>();
    AU.addRequired<LoopInfoWrapperPass>();
    return AU;
}

(New PM では AM.getResult<> を使って解析を要求し、依存関係は自動的に追跡されます。)

6. IR の変更パターン
// Insert instruction before iterator
IRBuilder<> Builder(&*I.getIterator());
Value *NewVal = Builder.CreateAdd(I.getOperand(0), ConstantInt::get(I.getType(), 1));
I.replaceAllUsesWith(NewVal);
I.eraseFromParent();

// Clone basic block
BasicBlock *Clone = CloneBasicBlock(OrigBB, VMap, ".clone", &F);

// Create function
FunctionCallee Fn = M.getOrInsertFunction("my_fn",
    FunctionType::get(Builder.getVoidTy(), false));

構造を変更した後は、必ず SSA を更新し、解析を無効にしてください。

7. llvm-lit によるテスト
test/
├── lit.cfg.py
└── my-pass.test
# my-pass.test
# RUN: opt -load-pass-plugin %shlibdir/MyPass.so -passes=my-pass -S %s | FileCheck %s

define void @test() {
  call void @dead_func()
  ret void
}

; CHECK-NOT: dead_func
llvm-lit test/my-pass.test -v
8. パスのデバッグ
# Verify IR after pass
opt -load-pass-plugin ./MyPass.so -passes=my-pass input.ll -o out.ll
opt -verify-each out.ll

# Time passes
opt -passes=my-pass -time-passes input.ll -o /dev/null

# Debug pass manager
OPT_DEBUG=1 opt -passes=my-pass input.ll -o /dev/null

よくある問題

症状原因対処法
Pass not found: my-passプラグインが読み込まれていない、または名前が一致していないregisterPipelineParsingCallback の名前を確認します
モジュールの検証に失敗する変換後に SSA が壊れている-verify-each を実行し、use-def チェーンを確認します
解析結果が古い無効化せずに IR を変更したPreservedAnalyses::none() を返します
プラグインの読み込みエラーLLVM のバージョンが一致していないopt と同じ LLVM に対してビルドします
opt の出力が空-S を指定していないテキスト形式の IR を出力するには -S を追加します
lit テストが FAIL になるCHECK 行が一致しないopt -S を実行し、手動で比較します

関連スキル

  • skills/compilers/llvm — LLVM IR の調査とユーザーとしての opt パイプラインの利用
  • skills/compiler-internals/compiler-frontend — パスに入力する IR の生成
  • skills/compiler-internals/jit-compilation — 最適化済み IR を実行する ORC JIT
  • skills/compiler-internals/mlir — MLIR パス(類似の概念)
  • skills/compilers/clang — Clang の最適化フラグ
  • skills/build-systems/cmake — パスプラグインのビルド

コメント