我试图从全局变量中获取浮点值并将其设置为指令的操作数.
这是我想要做的:
@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("%f\n",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优化标志会消灭一切……
希望这可以帮助..