analysis pass 必须继承 analysisinfomixin 或显式定义 analysiskey,否则 getresult 编译失败或运行时 panic;run() 必须返回可移动的分析结果类型,并实现 isinvalidated;transform pass 需通过 am.getresult 安全获取结果;插件必须导出 llvmgetpassplugininfo 符号。

Analysis Pass 必须继承 AnalysisInfoMixin 或显式提供 ID
LLVM New PM(2021 年后主流)下,Analysis Pass 不再靠 static char ID 和 RegisterPass 注册,而是必须继承 AnalysisInfoMixin 或手动定义 AnalysisKey。否则 FunctionAnalysisManager::getResult<myanalysis>()</myanalysis> 会编译失败或运行时 panic。
常见错误现象:error: no member named 'getAnalysisResult' in 'llvm::FunctionAnalysisManager' 或 Assertion failed: Result.isValid()
- 正确写法:用
struct MyAnalysis : public AnalysisInfoMixin<myanalysis></myanalysis>,并声明static inline AnalysisKey Key; - 不推荐 Legacy 方式(
FunctionPass+getAnalysis())混用 New PM,会导致分析结果未缓存或重复计算 - 若需兼容旧框架(如某些插件仍用 opt -load),需额外提供 Legacy 包装器,但不建议新开发走这条路
run() 返回值决定分析是否被缓存
New PM 中,Analysis Pass 的 run() 方法返回类型必须是具体分析结果(如 MyAnalysisResult),且该类型需满足可移动、可拷贝(或显式禁用拷贝)。LLVM 用返回值的生命周期管理缓存——返回栈对象会被 move 构造进分析管理器;返回引用或指针直接崩溃。
典型错误:写成 void run(...) 或 MyAnalysisResult& run(...),导致编译不过或运行时 segfault
- 正确模式:
MyAnalysisResult run(Function &F, FunctionAnalysisManager &AM) - 结果类需定义
isInvalidated(const PreservedAnalyses &PA)方法,告知哪些修改会使缓存失效 - 若分析结果只读且不依赖任何其他分析,可直接返回
PreservedAnalyses::all(),但这是 Transform Pass 的逻辑,Analysis Pass 不适用
如何在 Transform Pass 中安全获取 Analysis 结果
Transform Pass(如 FunctionPass)不能直接调用 getAnalysis(),而必须通过 FunctionAnalysisManager & 参数获取。New PM 强制依赖注入,不提供全局或隐式访问路径。
常见错误现象:在 run() 内部硬编码 AM.getResult<dominatortreeanalysis>(F)</dominatortreeanalysis> 却没在 registerAnalyses() 或 pass pipeline 配置中提前注册该 analysis,导致运行时报 Analysis not registered
- 确保 pipeline 构建时已注册所需 analysis,例如:
FAM.registerPass([&] { return DominatorTreeAnalysis(); }); - 在 Transform Pass 的
run()中,用AM.getResult<myanalysis>(F)</myanalysis>获取,不是AM.getResult<myanalysis>(*F.getParent())</myanalysis>(Module 级 analysis 要用 ModuleAnalysisManager) - 避免在循环中反复调用
getResult——它本身是 O(1) 缓存查找,但滥用会掩盖设计问题;应一次获取、多次使用
registerPassPluginInfo 是插件唯一入口,漏掉就加载失败
以 shared library 形式分发的 Analysis Pass(如用 opt -load=libMyAnalysis.so -my-transform),必须导出 C 符号 llvmGetPassPluginInfo。没有它,opt 根本不会扫描该 so 文件里的任何 pass。
错误现象:opt: Unknown argument: -my-transform,即使 .so 已用 -load 指定
- 函数签名严格为:
extern "C" PassPluginLibraryInfo llvmGetPassPluginInfo() { ... } - 其中
PassRegistry.def风格的注册必须包含 analysis 类型标识,例如PassBuilder.registerAnalysisRegistrationCallback([](PassBuilder &PB) { PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &FAM) { FAM.registerPass([] { return MyAnalysis(); }); }); }); - 插件里不能混用 Legacy 和 New PM 的注册逻辑;一个 so 只应面向一种 PM 架构
最易被忽略的是分析结果的失效策略:isInvalidated() 里漏判某类 transform(比如没检查 PA.get<cfganalyses>().areCFGOnlyPreserved()</cfganalyses>),会导致后续 pass 读到脏数据。这不是编译错误,而是静默优化退化——IR 看似没变,实际行为已偏移。











