gpt4 book ai didi

c++ - 如何获取LLVM全局变量常量值?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:14:36 25 4
gpt4 key购买 nike

我正在尝试从全局变量中获取浮点值并将其设置为指令的操作数。

这是我想做的:

@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_fpval0.1 因为 0x3FB99999A0000000 等于 0.10000000149011612 的双数

精度。程序似乎在 setOperand() 处崩溃。

最佳答案

考虑下面的例子

你好.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("%f\n",Multiply());

return 0;
}

模块 pass 将循环查找浮点全局变量,程序中的任何使用都将替换为常量 FP 值。 LLVM pass 如下所示 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);

要点:-

  1. 在对指令进行任何修改之前。在工作列表中首先收集。

  2. 对工作列表进行修改。

  3. 您不能在使用迭代器时进行修改。

我在上面的源码hello.cpp上测试成功,pass后对应的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 优化标志会清除一切...

希望这有帮助..

关于c++ - 如何获取LLVM全局变量常量值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48212351/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com