使用LLVM C++ API生成的简单函数未被优化问题咨询
为什么LLVM没有消除我生成的IR中多余的存储/加载操作?
我来帮你分析这个问题——你遇到的情况其实是优化级别设置导致的预期偏差。
先把你的场景整理清楚:
你用LLVM C++ API生成的IR代码如下:
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define i64 @"foo"(i64) { %2 = alloca i64 store i64 %0, i64* %2 %3 = load i64, i64* %2 ret i64 %3 }
当你使用llvm::CodeGenOpt::None优化级别编译后,反汇编结果保留了冗余的栈存储和加载操作:
$ objdump -M intel -d out.o | grep -A 10 foo 0000000000000000 <foo>: 0: 48 89 7c 24 f8 mov ...
问题根源
llvm::CodeGenOpt::None是LLVM里完全禁用所有优化的级别,这个模式下LLVM会严格按照你生成的IR结构生成机器码,不会执行任何优化逻辑——包括你期望的「冗余存储/加载消除」。这类消除操作属于Mem2Reg(内存转寄存器)优化Pass的范畴,而这类Pass在CodeGenOpt::None级别下是完全不运行的。
解决方法
方法1:提升优化级别
如果你希望LLVM自动消除这类冗余操作,只需要把优化级别调高到至少llvm::CodeGenOpt::Default(对应命令行的-O1),或者更高的CodeGenOpt::Aggressive(对应-O2/-O3)。
当你用-O1及以上级别编译时,LLVM会自动运行Mem2Reg、死代码消除等优化Pass,最终生成的foo函数反汇编会非常简洁——直接返回输入参数,完全没有栈操作:
0000000000000000 <foo>: 0: mov rax, rdi 1: ret
方法2:手动添加优化Pass(适用于必须低优化级别的场景)
如果你因为某些原因必须保持CodeGenOpt::None,但又想消除这个冗余操作,可以在代码生成前手动添加Mem2Reg优化Pass。比如在你的LLVM代码里添加类似逻辑:
#include "llvm/Transforms/Scalar/PromoteMemoryToRegister.h" // ... 你的IR生成代码 ... // 创建Pass管理器并添加Mem2Reg Pass llvm::FunctionPassManager FPM(Module); FPM.add(llvm::createPromoteMemoryToRegisterPass()); FPM.run(*FooFunction); // FooFunction是你生成的foo函数
这样即使在无优化级别下,也能把栈上的临时变量提升到寄存器,消除多余的存载操作。
内容的提问来源于stack exchange,提问作者llvm newbie
相关产品推荐
相关产品推荐

