如何从LLVM Pass中获取O0、O1、O2等编译优化等级
解决方案
LLVM 没有直接在 Function Pass 上下文内置查询优化等级的单步API,你可以根据你使用的 PassManager 版本选择以下实现方式:
新PassManager(LLVM 13+ 官方推荐)
优化等级可以在注册Pass时从PassBuilder实例中获取,作为构造参数传入你的Function Pass即可:
#include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { class MyFunctionPass : public PassInfoMixin<MyFunctionPass> { OptimizationLevel CurrentOL; public: // 构造函数接收优化等级参数 MyFunctionPass(OptimizationLevel OL) : CurrentOL(OL) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { // 检测到O0/O1直接返回,跳过当前Pass逻辑 if (CurrentOL == OptimizationLevel::O0 || CurrentOL == OptimizationLevel::O1) { return PreservedAnalyses::all(); } // 此处放置O2/O3下需要执行的Pass逻辑 errs() << "Running pass on function: " << F.getName() << "\n"; return PreservedAnalyses::all(); } static bool isRequired() { return true; } }; } // 匿名命名空间 // Pass 注册逻辑 extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() { return { LLVM_PLUGIN_API_VERSION, "MyFunctionPass", "v0.1", [](PassBuilder &PB) { // 手动指定-pass参数调用时的注册逻辑 PB.registerPipelineParsingCallback( [&](StringRef Name, FunctionPassManager &FPM, ArrayRef<PassBuilder::PipelineElement>) { if (Name == "my-custom-pass") { FPM.addPass(MyFunctionPass(PB.getOptLevel())); return true; } return false; } ); // 自动插入到优化流水线末尾的注册逻辑 PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL, ThinLTOPhase, PassBuilder::DebugLogging) { FunctionPassManager FPM; FPM.addPass(MyFunctionPass(OL)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } ); } }; }
旧版Legacy PassManager
直接引用LLVM全局定义的OptLevel命令行参数即可读取当前优化等级:
#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; // 引用LLVM全局定义的优化等级参数,无需自己重新定义 extern cl::opt<int> OptLevel; namespace { struct LegacyMyFunctionPass : public FunctionPass { static char ID; LegacyMyFunctionPass() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { // OptLevel取值0对应O0、1对应O1、2对应O2、3对应O3 if (OptLevel <= 1) { return false; } // 此处放置O2/O3下需要执行的Pass逻辑 errs() << "Running legacy pass on function: " << F.getName() << "\n"; return false; } }; } // 匿名命名空间 char LegacyMyFunctionPass::ID = 0; static RegisterPass<LegacyMyFunctionPass> X("legacy-my-pass", "My Legacy Custom Function Pass");
注意事项
- 仅需要跳过当前Pass执行时,直接返回空修改的结果即可,不会影响其他Pass的正常运行
- 如果你需要直接终止整个编译流程,可以调用
report_fatal_error("MyPass requires O2/O3 optimization level"),该方法会直接中断编译并输出错误信息,非必要不建议使用 - LLVM 12及更早版本的新PassManager没有
PassBuilder::getOptLevel()接口,你可以在注册Pass时手动把优化等级作为参数传入即可正常使用
内容的提问来源于stack exchange,提问作者Darshan Bhat
相关产品推荐
相关产品推荐

