如何在LLVM FunctionPass中获取自定义RegionPass的分析结果?
在FunctionPass中获取自定义RegionPass的分析结果
要实现这个需求,你需要让你的RPass保存分析结果并提供公共访问接口,同时在FPass中声明对RPass的依赖,这样LLVM的Pass管理器会确保RPass先完成所有Region的分析,再运行你的FPass。下面是具体的实现步骤和代码示例:
步骤1:修改RPass,保存并暴露分析结果
首先,你的RPass需要存储每个Region的分析数据,并提供一个方法让外部Pass获取指定Region的结果。同时要确保它被标记为分析Pass(不修改IR):
#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionPass.h" #include "llvm/Pass.h" #include <map> #include <cassert> class RPass : public RegionPass { public: static char ID; RPass() : RegionPass(ID) {} // 用map存储每个Region对应的分析结果,这里假设结果是int,你可以替换成自己的类型 std::map<Region*, int> RegionAnalysisResults; bool runOnRegion(Region *R, RGPassManager &RGM, PassManagerBuilder &PMB) override { // 这里写你的Region分析逻辑,示例计算Region包含的基本块数量 int exampleResult = R->getBlocks().size(); RegionAnalysisResults[R] = exampleResult; return false; // 分析Pass不修改IR,返回false } // 公共方法:获取指定Region的分析结果 int getResultForRegion(Region *R) { auto resultIter = RegionAnalysisResults.find(R); // 断言确保Region已经被分析过,避免运行时错误 assert(resultIter != RegionAnalysisResults.end() && "Region未被RPass分析!"); return resultIter->second; } // 声明这是一个分析Pass,不修改任何IR void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; // 注册RPass,最后两个参数:false表示不修改IR,true表示这是一个分析Pass char RPass::ID = 0; static RegisterPass<RPass> X("r-pass", "自定义Region分析Pass", false, true);
步骤2:修改FPass,声明依赖并获取结果
接下来,在你的FPass中,需要声明对RPass的依赖,这样LLVM会先执行RPass处理函数内的所有Region,然后你就可以通过RPass的实例获取每个Region的结果:
#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include <deque> class FPass : public FunctionPass { public: static char ID; FPass() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { // 获取当前函数的RegionInfo auto ®ionInfo = getAnalysis<RegionInfoPass>().getRegionInfo(); std::deque<Region *> regionQueue = getRegionList(regionInfo->getTopLevelRegion()); // 获取RPass的实例,因为已经声明依赖,这里可以安全获取 auto &rPassInstance = getAnalysis<RPass>(); // 遍历每个Region,获取分析结果 for(Region *R : regionQueue){ int regionResult = rPassInstance.getResultForRegion(R); // 这里写你使用分析结果的逻辑,比如打印结果 llvm::errs() << "函数" << F.getName() << "中的Region,包含" << regionResult << "个基本块\n"; } return false; } // 声明Pass依赖:必须先运行RegionInfoPass和RPass void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<RegionInfoPass>(); AU.addRequired<RPass>(); // 关键:添加对RPass的依赖 AU.setPreservesAll(); } }; // 注册FPass char FPass::ID = 0; static RegisterPass<FPass> Y("f-pass", "使用Region分析结果的FunctionPass", false, false);
关键注意事项
- Pass注册类型:确保
RPass注册时最后一个参数为true,标记为分析Pass,LLVM会正确保留它的分析数据。 - 依赖声明:
FPass的getAnalysisUsage必须添加AU.addRequired<RPass>(),否则Pass管理器不会先运行RPass,会导致获取分析结果时出错。 - 结果存储:如果你的分析结果是复杂类型,建议使用智能指针或者确保Region的生命周期长于
RPass实例(LLVM中Region和函数生命周期一致,Pass实例由PassManager管理,只要PassManager存在,结果就会保留)。 - Legacy vs New Pass Manager:上面的代码基于传统的Legacy Pass Manager,如果使用LLVM 13+的新Pass Manager,需要使用
AnalysisInfoMixin等新的API,但核心逻辑(保存结果+依赖声明)是一致的。
内容的提问来源于stack exchange,提问作者TSG
相关产品推荐
相关产品推荐

