Скажем, у меня есть действующий модуль LLVM:
std::unique_ptr<llvm::Module> module;
Я хочу запустить на этом традиционные этапы оптимизации LLVM:
llvm::PassBuilder passBuilder;
llvm::ModulePassManager modulePassManager = passBuilder.buildPerModuleDefaultPipeline(llvm::PassBuilder::OptimizationLevel::O3);
llvm::ModuleAnalysisManager moduleAnalysisManager;
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
modulePassManager.run(*module, moduleAnalysisManager);
К сожалению, сбой вызова и отладка показывают, что moduleAnalysisManager
имеет только модуль проходит, но
не те функции, которые заключены в прокси-класс.
Как мне настроить modulePassManager
обрабатывать все (модульные) проходы определенного уровня? У меня нет отдельных функций, поэтому я не могу запустить передачи функций только на них.
Правильный способ LLVM состоит в том, чтобы создать все analysisManager
и затем связать их всех вместе. Давайте начнем с их создания:
llvm::PassBuilder passBuilder;
llvm::LoopAnalysisManager loopAnalysisManager(true); // true is just to output debug info
llvm::FunctionAnalysisManager functionAnalysisManager(true);
llvm::CGSCCAnalysisManager cGSCCAnalysisManager(true);
llvm::ModuleAnalysisManager moduleAnalysisManager(true);
Затем мы регистрируем каждого менеджера индивидуально, а затем перекрестно регистрируем их. Это означает, что количество менеджеров здесь фиксировано, и если LLVM (7 в настоящее время) меняет количество менеджеров, это необходимо будет адаптировать:
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
passBuilder.registerFunctionAnalyses(functionAnalysisManager);
passBuilder.registerLoopAnalyses(loopAnalysisManager);
// This is the important line:
passBuilder.crossRegisterProxies(
loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager);
Однажды passBuilder
наконец, мы можем выполнить этапы оптимизации для модуля с вызовом moduleAnalysisManager
,
llvm::ModulePassManager modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(llvm::PassBuilder::OptimizationLevel::O3);
modulePassManager.run(*module, moduleAnalysisManager);
Это запустит проходы уровня модуля, а также все внутренние проходы, которые LLVM может выполнить на частях модуля (уровень функции, уровень цикла …).
Других решений пока нет …