使用 C++ 进行 LLVM 优化 API
LLVM Optimization Using C++ API
我正在尝试找出如何在 LLVM 模块上执行所有优化(例如,所有 -O3 优化)。我尝试了以下方法,但我不确定是否应用了所有可能的优化(例如,内联)。
//take string "llvm" (LLVM IR) and return "output_llvm" (optimized LLVM IR)
static string optimize(string llvm) {
LLVMContext &ctx = getGlobalContext();
SMDiagnostic err;
Module *ir = ParseIR(MemoryBuffer::getMemBuffer(llvm), err, ctx);
PassManager *pm = new PassManager();
PassManagerBuilder builder;
builder.OptLevel = 3;
builder.populateModulePassManager(*pm);
pm->run(*ir);
delete pm;
string output_llvm;
raw_string_ostream buff(output_llvm);
ir->print(buff, NULL);
return output_llvm;
}
我还能做些什么来提高输出 LLVM IR 的性能吗?
编辑:我尝试在opt.cpp
中添加AddOptimizationPasses()
函数的所有优化,如下所示:
PassManager *pm = new PassManager();
int optLevel = 3;
int sizeLevel = 0;
PassManagerBuilder builder;
builder.OptLevel = optLevel;
builder.SizeLevel = sizeLevel;
builder.Inliner = createFunctionInliningPass(optLevel, sizeLevel);
builder.DisableUnitAtATime = false;
builder.DisableUnrollLoops = false;
builder.LoopVectorize = true;
builder.SLPVectorize = true;
builder.populateModulePassManager(*pm);
pm->run(*module);
此外,我在创建 PassManager
之前创建了一个 FunctionPassManager
并像这样添加了几个通道:
FunctionPassManager *fpm = new FunctionPassManager(module);
// add several passes
fpm->doInitialization();
for (Function &f : *ir)
fpm->run(f);
fpm->doFinalization();
但是,使用 -O1 在命令行上的性能与 运行 相同,而在命令行上使用 -O3 可以获得更好的性能。有什么建议吗?
遵循 opt.cpp
中函数 AddOptimizationPasses
中的逻辑。这就是真相的来源。
在研究 LLVM 优化时,我发现 this information on pass ordering,我认为这可能说明了为什么有人会遇到这种情况。
根据您的语言和您期望的优化,您可能需要针对您的用例专门调整优化过程。特别是,这些通行证的顺序可能很重要。例如,如果您更好的 -O3 代码正在优化完全未优化的代码或已被您的程序部分优化的代码,则可能只是您需要重新排序或复制一些传递以达到预期的最终结果。
考虑到这里的具体措辞以及 Eli 的回答被接受的事实,我不能 100% 确定这是否是 OP 所看到的,但这些知识可能对其他有类似问题的人有帮助,他们像我一样找到这个答案做了。
我正在尝试找出如何在 LLVM 模块上执行所有优化(例如,所有 -O3 优化)。我尝试了以下方法,但我不确定是否应用了所有可能的优化(例如,内联)。
//take string "llvm" (LLVM IR) and return "output_llvm" (optimized LLVM IR)
static string optimize(string llvm) {
LLVMContext &ctx = getGlobalContext();
SMDiagnostic err;
Module *ir = ParseIR(MemoryBuffer::getMemBuffer(llvm), err, ctx);
PassManager *pm = new PassManager();
PassManagerBuilder builder;
builder.OptLevel = 3;
builder.populateModulePassManager(*pm);
pm->run(*ir);
delete pm;
string output_llvm;
raw_string_ostream buff(output_llvm);
ir->print(buff, NULL);
return output_llvm;
}
我还能做些什么来提高输出 LLVM IR 的性能吗?
编辑:我尝试在opt.cpp
中添加AddOptimizationPasses()
函数的所有优化,如下所示:
PassManager *pm = new PassManager();
int optLevel = 3;
int sizeLevel = 0;
PassManagerBuilder builder;
builder.OptLevel = optLevel;
builder.SizeLevel = sizeLevel;
builder.Inliner = createFunctionInliningPass(optLevel, sizeLevel);
builder.DisableUnitAtATime = false;
builder.DisableUnrollLoops = false;
builder.LoopVectorize = true;
builder.SLPVectorize = true;
builder.populateModulePassManager(*pm);
pm->run(*module);
此外,我在创建 PassManager
之前创建了一个 FunctionPassManager
并像这样添加了几个通道:
FunctionPassManager *fpm = new FunctionPassManager(module);
// add several passes
fpm->doInitialization();
for (Function &f : *ir)
fpm->run(f);
fpm->doFinalization();
但是,使用 -O1 在命令行上的性能与 运行 相同,而在命令行上使用 -O3 可以获得更好的性能。有什么建议吗?
遵循 opt.cpp
中函数 AddOptimizationPasses
中的逻辑。这就是真相的来源。
在研究 LLVM 优化时,我发现 this information on pass ordering,我认为这可能说明了为什么有人会遇到这种情况。
根据您的语言和您期望的优化,您可能需要针对您的用例专门调整优化过程。特别是,这些通行证的顺序可能很重要。例如,如果您更好的 -O3 代码正在优化完全未优化的代码或已被您的程序部分优化的代码,则可能只是您需要重新排序或复制一些传递以达到预期的最终结果。
考虑到这里的具体措辞以及 Eli 的回答被接受的事实,我不能 100% 确定这是否是 OP 所看到的,但这些知识可能对其他有类似问题的人有帮助,他们像我一样找到这个答案做了。