如何获取LLVM指针指向内存的数据及Armv7m转LLVM IR lifter相关问题
核心现象原因
LLVM 的 IRBuilder 仅负责按 API 调用顺序生成原始未优化 IR,不会自动执行常量传播、内存到寄存器提升、指令简化这类优化逻辑。你代码中先存0再加载的操作会完整保留在未优化 IR 中,load 指令返回的结果不会被自动折叠为立即数0,因此 icmp eq 的结果也不会被计算为常量 i1 true。
如果要得到你期望的常量结果,只需要在生成完完整 IR 后运行 instcombine、sroa、early-cse 这类基础优化 Pass 即可。
具体问题解答
1、如何获取LLVM变量%18内部存储的值?
你提到的 %18 是 CreateLoad 生成的加载指令,属于 llvm::Instruction 类型,在未优化 IR 阶段没有固定的静态常量值,有两种方式可以推导它的取值:
- 自行实现局部def-use分析:遍历当前基本块中该
load指令之前的所有同内存地址的store指令,若该地址在最近一次store之后到本次load之前没有被其他操作修改,即可直接取store的源操作数作为本次加载的实际值 - 运行常量传播、全局值编号类优化Pass后再遍历IR,此时确定为常量的加载操作会被直接替换为
ConstantInt类型,调用dyn_cast<llvm::ConstantInt>(loaded_V)即可拿到对应的常量值。
2、有没有办法无需load操作,直接获取指针V指向的内存地址中存储的数据?
在你完全掌控内存访问语义的场景下(比如模拟寄存器的私有栈内存,无指针别名、无volatile访问),可以自行维护一个内存地址到当前值的映射表:
- 每次调用
CreateStore写入内存时,同步更新该指针在映射表中对应的最新值 - 需要读取该地址的值时,先查询映射表,若存在确定的最新值,直接使用该值即可,不需要生成
load指令
如果存在指针别名、外部修改内存的可能性,则不能跳过load操作。
3、有没有更好的操作数表示方式(比如用虚拟寄存器替代指向内存的指针)?
你当前用alloca模拟寄存器的方案是LLVM前端的通用实现,本身是合规的,后续运行SROA(标量聚合替换)优化Pass时,会自动把这类无逃逸、单用途的alloca提升为虚拟寄存器,消除多余的load/store操作。
如果想要直接生成更高质量的SSA形式IR,更推荐的方案是自行维护寄存器编号到llvm::Value的映射表:
- 每次给寄存器赋值时,直接把运算结果(比如
CreateAdd的返回值)更新到映射表对应条目中 - 读取寄存器值时,直接从映射表取对应的
llvm::Value即可,完全不需要生成alloca、store、load相关指令
这种方案生成的IR直接符合SSA规范,没有多余内存操作,代码质量更高,也可以减少后续优化的开销,更适合指令lifter的开发场景。
内容的提问来源于stack exchange,提问作者hany erfan
相关产品推荐
相关产品推荐

