4
votes

I am trying to use llvm::PassBuilder and FunctionPassManager to optimize a function in a module, what I have done is:

mod = ...load module from LLVM IR bitcode file...

auto lift_func = mod->getFunction("go_back");
if (not lift_func) {
    llvm::errs() << "Error: cannot get function\n";
    return 0;
}

auto pass_builder = llvm::PassBuilder{};
auto fa_manager = llvm::FunctionAnalysisManager{};

pass_builder.registerFunctionAnalyses(fa_manager);
auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2);

fp_manager.run(*lift_func, fa_manager);

but the program crashes always at fp_manager.run. I tried several ways with pass_builder, fa_manager, fp_manager but nothing works.

Strange enough, the LLVM's opt tool (which uses legacy optimization interface) works without any problem, i.e. if I run

opt -O2 go_back.bc -o go_back_o2.bc

then I get a new module where the (single) function go_back is optimized.

Many thanks for any response.

NB. The (disassembled) LLVM bitcode file is given here if anyone wants to take a look.

Update: I've somehow managed to pass the fp_manager.run with:

auto loop_manager = llvm::LoopAnalysisManager{};
auto cgscc_manager = llvm::CGSCCAnalysisManager{};
auto mod_manager = llvm::ModuleAnalysisManager{};

pass_builder.registerModuleAnalyses(mod_manager);
pass_builder.registerCGSCCAnalyses(cgscc_manager);
pass_builder.registerFunctionAnalyses(fa_manager);
pass_builder.registerLoopAnalyses(loop_manager);

pass_builder.crossRegisterProxies(loop_manager, fa_manager, cgscc_manager, mod_manager);

auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2, llvm::PassBuilder::ThinLTOPhase::None, true);

fp_manager.run(*lift_func, fa_manager);

...print mod...

But the program crashes when the fa_manager object is destroyed, still do not understand why!!!

1

1 Answers

0
votes

Well, after debugging and reading LLVM source code, I've managed to make it works, as following

mod = ...load module from LLVM IR bitcode file...

auto lift_func = mod->getFunction("go_back");
if (not lift_func) {
    llvm::errs() << "Error: cannot get function\n";
    return 0;
}

auto pass_builder = llvm::PassBuilder{};

auto loop_manager = llvm::LoopAnalysisManager{};
auto cgscc_manager = llvm::CGSCCAnalysisManager{};
auto mod_manager = llvm::ModuleAnalysisManager{};
auto fa_manager = llvm::FunctionAnalysisManager{}; // magic: it's must be here

pass_builder.registerModuleAnalyses(mod_manager);
pass_builder.registerCGSCCAnalyses(cgscc_manager);
pass_builder.registerFunctionAnalyses(fa_manager);
pass_builder.registerLoopAnalyses(loop_manager);

pass_builder.crossRegisterProxies(loop_manager, fa_manager, cgscc_manager, mod_manager);

auto fp_manager = pass_builder.buildFunctionSimplificationPipeline(llvm::PassBuilder::OptimizationLevel::O2, llvm::PassBuilder::ThinLTOPhase::None, true);

fp_manager.run(*lift_func, fa_manager);

...anything...

The fa_manager should be initialized as late as possible, I still don't know why!!!