运行 使用现代 LLVM 的默认优化管道

Run default optimization pipeline using modern LLVM

我正在使用 LLVM 7,我有一个 llvm::Module 我想使用标准优化管道进行优化。不幸的是,没有我可以调用的 llvm::runDefaultOptimizations 函数。似乎有无数种方法可以优化 LLVM 中的模块。我对这个主题的搜索发现了许多 old/depreciated API 和一些在我的系统上不起作用的示例。

我想 运行 在 -O3 处以尽可能少的麻烦进行所有标准优化。我不想手动列出所有通过,甚至不想编写 for 循环。我认为 llvm::PassBuilder::buildModuleOptimizationPipeline 可能是解决方案,但当我尝试使用我认为非常奇怪的函数时出现链接器错误。

要查看 LLVM 的标准传递是什么,您可以尝试 检查 Pass 接口的子类。据我所知,没有通过 运行 clang 特定通过 LLVM API 本身。为此,您必须查看 clang。

要准确了解您想要添加的通行证,请查看

llvm-as < /dev/null | opt -O3 -disable-output -debug-pass=Arguments  

Where to find the optimization sequence for clang -OX?

不过还是有点麻烦,找你用的API等等。同样可以应用于 Clang -O3。

如果你的项目可能的话,你可以做的是生成 LLVM IR 到磁盘上的文件,然后用 clang 和 O3 标志分别编译未优化的 LLVM IR。

这就是您可以使用旧版通行证管理器 运行 一些通行证的方法。假设您有一个 LLVM 上下文。

 module = llvm::make_unique<llvm::Module>("module",context); //Context is your LLVM context.
 functionPassMngr = llvm::make_unique<llvm::legacy::FunctionPassManager>(module.get());
 functionPassMngr->add(llvm::createPromoteMemoryToRegisterPass()); //SSA conversion
 functionPassMngr->add(llvm::createCFGSimplificationPass()); //Dead code elimination
 functionPassMngr->add(llvm::createSROAPass());
 functionPassMngr->add(llvm::createLoopSimplifyCFGPass());
 functionPassMngr->add(llvm::createConstantPropagationPass());
 functionPassMngr->add(llvm::createNewGVNPass());//Global value numbering
 functionPassMngr->add(llvm::createReassociatePass());
 functionPassMngr->add(llvm::createPartiallyInlineLibCallsPass()); //Inline standard calls
 functionPassMngr->add(llvm::createDeadCodeEliminationPass());
 functionPassMngr->add(llvm::createCFGSimplificationPass()); //Cleanup
 functionPassMngr->add(llvm::createInstructionCombiningPass());
 functionPassMngr->add(llvm::createFlattenCFGPass()); //Flatten the control flow graph.

然后这些可以通过 运行 通过

functionPassMngr->run(getLLVMFunc());

如果 getLLVMFunc 会 return 您当前正在生成的 llvm::Function*。请注意,我在这里使用旧版通行证管理器,原因是 clang 在内部使用旧版通行证管理器。

我最终获取了 opt 工具 (found here) 的源代码并删除了我不需要的所有内容。我最终得到了这个:

#include <llvm/IR/Verifier.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Analysis/TargetLibraryInfo.h>
#include <llvm/Analysis/TargetTransformInfo.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>

namespace {

void addOptPasses(
  llvm::legacy::PassManagerBase &passes,
  llvm::legacy::FunctionPassManager &fnPasses,
  llvm::TargetMachine *machine
) {
  llvm::PassManagerBuilder builder;
  builder.OptLevel = 3;
  builder.SizeLevel = 0;
  builder.Inliner = llvm::createFunctionInliningPass(3, 0, false);
  builder.LoopVectorize = true;
  builder.SLPVectorize = true;
  machine->adjustPassManager(builder);

  builder.populateFunctionPassManager(fnPasses);
  builder.populateModulePassManager(passes);
}

void addLinkPasses(llvm::legacy::PassManagerBase &passes) {
  llvm::PassManagerBuilder builder;
  builder.VerifyInput = true;
  builder.Inliner = llvm::createFunctionInliningPass(3, 0, false);
  builder.populateLTOPassManager(passes);
}

}

void optimizeModule(llvm::TargetMachine *machine, llvm::Module *module) {
  module->setTargetTriple(machine->getTargetTriple().str());
  module->setDataLayout(machine->createDataLayout());

  llvm::legacy::PassManager passes;
  passes.add(new llvm::TargetLibraryInfoWrapperPass(machine->getTargetTriple()));
  passes.add(llvm::createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis()));

  llvm::legacy::FunctionPassManager fnPasses(module);
  fnPasses.add(llvm::createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis()));

  addOptPasses(passes, fnPasses, machine);
  addLinkPasses(passes);

  fnPasses.doInitialization();
  for (llvm::Function &func : *module) {
    fnPasses.run(func);
  }
  fnPasses.doFinalization();

  passes.add(llvm::createVerifierPass());
  passes.run(*module);
}

这大致相当于将-O3传递给opt。它使用了一些 legacy 东西,但我真的不介意。