如何获取 LLVM 全局变量常量值
How to get LLVM global variable constant value?
我正在尝试从全局变量中获取浮点值并将其设置为指令的操作数。
这是我想做的:
@a = private constant float 0x3FB99999A0000000
...
%1 = load float, float* @a ---> removed
%3 = fmul fast %1, %2 ---> %3 = fmul fast float 0x3FB99999A0000000, %2
以下是我到目前为止尝试过的方法:
for (auto gv_iter = llvm_module.global_begin();gv_iter != llvm_module.global_end(); gv_iter++){
llvm::GlobalVariable* gv = &*gv_iter;
for(auto user_of_gv : gv->users()){
llvm::Instruction *instr_ld_gv = llvm::dyn_cast<llvm::Instruction>(user_of_gv);
llvm::Value *val_gv = llvm::cast<llvm::Value>(instr_ld_gv);
llvm::Constant *const_gv = gv->getInitializer();
llvm::ConstantFP *constfp_gv = llvm::dyn_cast<llvm::ConstantFP>(const_gv);
float gv_fpval = (constfp_gv->getValueAPF()).convertToFloat();
llvm::Constant *const_gv_opd = llvm::ConstantFP::get(llvm::Type::getFloatTy(llvm_context),gv_fpval);
for(auto user_of_load : val_gv->users()){
llvm::Instruction *instr_exe_gv = llvm::dyn_cast<llvm::Instruction>(user_of_load);
//P
for(int operand_num = 0;operand_num < instr_exe_gv->getNumOperands();operand_num++){
llvm::Value *val_instr_op = instr_exe_gv->getOperand(operand_num);
if(val_instr_op == val_gv){
instr_exe_gv->setOperand(operand_num,const_gv_opd);
instr_ld_gv->removeFromParent();
}
}
}
}
}
但是,当我尝试运行代码时,它会导致分段错误。
我确定我已经访问了我想要的全局变量和指令通过打印值
gv_fpval
0.1
,因为0x3FB99999A0000000等于 0.10000000149011612
精度。似乎程序在setOperand()
崩溃了。
考虑以下示例
hello.cpp
#include <stdio.h>
// Global Constant value
float a=1.4f;
float Multiply(){
float b=2.2f;
float c=4.32f;
float d= a*c;
return d;
}
int main(int argc, char const *argv[])
{
printf("%fn",Multiply());
return 0;
}
模块通道将循环浮点全局变量,程序中的任何使用都将替换为常量 FP 值。LLVM通行证如下ConstantReplacementPass.cpp
:-
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugInfo.h"
using namespace llvm;
/* StackOverflow : https://stackoverflow.com/questions/48212351/how-to-get-llvm-global-variable-constant-value* /
/**Bernard Nongpoh */
namespace {
class ConstantReplacementPass : public ModulePass {
public:
static char ID;
ConstantReplacementPass() : ModulePass(ID) {
srand (time(NULL));
}
virtual bool runOnModule(Module &M) {
// list to collect instruction
/*
* You cannot change an iterator while iterating over it
• To remove instructions or modify, first collect the instructions to remove/modify
•
*
* **/
// This are the list of load to delete
SmallVector<Instruction*,128> *WorkListLoad=new SmallVector<Instruction*,128>();
// This is the list of instruction to modify the source operand
SmallVector<Instruction*,128> *WorkListUserOfLoad=new SmallVector<Instruction*,128>();
for (auto gv_iter = M.global_begin();gv_iter != M.global_end(); gv_iter++) {
/* GLOBAL DATA INFO*/
GlobalVariable *gv = &*gv_iter;
Constant *const_gv = gv->getInitializer();
ConstantFP *Fvalue;
if(!const_gv->isNullValue()) {
if (ConstantFP *constfp_gv = llvm::dyn_cast<llvm::ConstantFP>(const_gv)) {
float gv_fpval = (constfp_gv->getValueAPF()).convertToFloat();
Fvalue = constfp_gv;
errs() << gv_fpval; // Value retrieved here
// Collect Instruction to modify
}
for (auto user_of_gv: gv->users()) {
// Collect in a worklist
if (llvm::Instruction *instr_ld_gv = llvm::dyn_cast<Instruction>(user_of_gv)) {
if (LoadInst *loadInst = dyn_cast<LoadInst>(instr_ld_gv)) {
WorkListLoad->push_back(loadInst);
for (auto user_of_load:loadInst->users()) {
user_of_load->dump();
Instruction *instruction1 = dyn_cast<Instruction>(user_of_load);
instruction1->dump();
//instruction1->setOperand(0, Fvalue);
//instruction1->dump();
// if(Instruction *instruction1 = dyn_cast<Instruction>(user_of_load))
WorkListUserOfLoad->push_back(instruction1);
//instruction1->setOperand(0, Fvalue);
//instruction1->dump();
}
}
}
}
// Modify Here
while (!WorkListUserOfLoad->empty()) {
Instruction *instruction = WorkListUserOfLoad->pop_back_val();
instruction->setOperand(0, Fvalue);
instruction->dump();
}
// Removing all loads that are used by the global variable
while (!WorkListLoad->empty()) {
Instruction *instruction = WorkListLoad->pop_back_val();
instruction->eraseFromParent();
}
}
}
return true;
}
};
}
char ConstantReplacementPass::ID = 0;
static RegisterPass<ConstantReplacementPass> F0("constantREP", "Constant Replacement Pass "
, false,true);
要点:-
在对指令进行任何修改之前。在工作清单中首先收集。
对工作清单执行修改。
使用迭代器时无法进行修改。
通过后,我在上述源代码hello.cpp
相应的IR上成功测试如下:-
entry:
%b = alloca float, align 4
%c = alloca float, align 4
%d = alloca float, align 4
call void @llvm.dbg.declare(metadata float* %b, metadata !14, metadata !15),
... !dbg !16
store float 0x40019999A0000000, float* %b, align 4, !dbg !16
call void @llvm.dbg.declare(metadata float* %c, metadata !17, metadata !15),
... !dbg !18
store float 0x401147AE20000000, float* %c, align 4, !dbg !18
call void @llvm.dbg.declare(metadata float* %d, metadata !19, metadata !15),
... !dbg !20
%0 = load float, float* %c, align 4, !dbg !21
%mul = fmul float 0x3FF6666660000000, %0, !dbg !22
store float %mul, float* %d, align 4, !dbg !20
%1 = load float, float* %d, align 4, !dbg !23
ret float %1, !dbg !24
也许使用 -O3 优化标志会抹去一切......
希望这有帮助..
相关文章:
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 当vector是tje全局变量时,c++中vector的内存管理
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 内联函数中具有内部链接的全局变量
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 全局变量 多读取器 一个写入器多线程安全?
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 不同作用域中的静态变量和全局变量
- 如何使用 llvm-10 库在C++定义 LLVM 全局值变量?
- C++ 在编译时具有函数计算全局变量
- 修改程序的入口点时未调用全局变量的构造函数
- 使用 std::ios_base::Init 正确初始化全局变量
- 为什么我的全局变量似乎没有变化?
- 如何获取 LLVM 全局变量常量值
- LLVM-如何将ConstantExpr转换为ConstantDataArray,以便打印全局变量char*的值
- 如何获取LLVM中指令引用的所有全局变量
- 如何在LLVM模块中增加全局变量
- 在 llvm 中创建全局变量时出错
- LLVM中的非指针全局变量
- 如何使用LLVM API获取全局变量的初始化器