蘇郁翔*_*蘇郁翔 5 c++ compiler-construction llvm
我试图从全局变量中获取浮点值并将其设置为指令的操作数。
这是我想要做的:
@a = private constant float 0x3FB99999A0000000
...
%1 = load float, float* @a ---> removed
%3 = fmul fast %1, %2 ---> %3 = fmul fast float 0x3FB99999A0000000, %2
Run Code Online (Sandbox Code Playgroud)
以下是我迄今为止尝试过的:
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();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试运行我的代码时,它会导致分段错误。
我确定我已经通过打印的值访问了我想要的全局变量和指令
gv_fpval这是0.1因为 0x3FB99999A0000000 等于 0.10000000149011612
精确。程序似乎在setOperand().
考虑下面的例子
\n\nhello.cpp
#include <stdio.h>\n// Global Constant value\nfloat a=1.4f;\n\nfloat Multiply(){\n float b=2.2f;\n float c=4.32f;\n float d= a*c;\n return d;\n}\n\nint main(int argc, char const *argv[])\n{\n\n printf("%f\\n",Multiply());\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n模块通道将循环浮点全局变量,程序中的任何使用都将被常量 FP 值替换。LLVM pass如下ConstantReplacementPass.cpp:-
#include "llvm/Pass.h"\n#include "llvm/IR/Function.h"\n#include "llvm/Support/raw_ostream.h"\n#include "llvm/IR/LegacyPassManager.h"\n#include "llvm/IR/InstrTypes.h"\n#include "llvm/Transforms/IPO/PassManagerBuilder.h"\n#include "llvm/IR/IRBuilder.h"\n#include "llvm/IR/Module.h"\n#include "llvm/Transforms/Utils/BasicBlockUtils.h"\n#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"\n#include "llvm/IR/DebugLoc.h"\n#include "llvm/IR/DebugInfo.h"\nusing namespace llvm;\n\n/* StackOverflow : /sf/ask/3374864601/* /\n/**Bernard Nongpoh */\n\nnamespace {\n class ConstantReplacementPass : public ModulePass {\n\n\n public:\n static char ID;\n\n\n ConstantReplacementPass() : ModulePass(ID) {\n srand (time(NULL));\n }\n\n virtual bool runOnModule(Module &M) {\n\n // list to collect instruction\n /*\n * You cannot change an iterator while iterating over it\n \xe2\x80\xa2 To remove instructions or modify, first collect the instructions to remove/modify\n \xe2\x80\xa2\n *\n * **/\n // This are the list of load to delete\n SmallVector<Instruction*,128> *WorkListLoad=new SmallVector<Instruction*,128>();\n // This is the list of instruction to modify the source operand\n SmallVector<Instruction*,128> *WorkListUserOfLoad=new SmallVector<Instruction*,128>();\n\n\n for (auto gv_iter = M.global_begin();gv_iter != M.global_end(); gv_iter++) {\n /* GLOBAL DATA INFO*/\n GlobalVariable *gv = &*gv_iter;\n Constant *const_gv = gv->getInitializer();\n ConstantFP *Fvalue;\n if(!const_gv->isNullValue()) {\n\n if (ConstantFP *constfp_gv = llvm::dyn_cast<llvm::ConstantFP>(const_gv)) {\n float gv_fpval = (constfp_gv->getValueAPF()).convertToFloat();\n Fvalue = constfp_gv;\n errs() << gv_fpval; // Value retrieved here\n // Collect Instruction to modify\n\n\n }\n\n for (auto user_of_gv: gv->users()) {\n // Collect in a worklist\n if (llvm::Instruction *instr_ld_gv = llvm::dyn_cast<Instruction>(user_of_gv)) {\n\n if (LoadInst *loadInst = dyn_cast<LoadInst>(instr_ld_gv)) {\n\n WorkListLoad->push_back(loadInst);\n for (auto user_of_load:loadInst->users()) {\n user_of_load->dump();\n Instruction *instruction1 = dyn_cast<Instruction>(user_of_load);\n instruction1->dump();\n //instruction1->setOperand(0, Fvalue);\n //instruction1->dump();\n // if(Instruction *instruction1 = dyn_cast<Instruction>(user_of_load))\n WorkListUserOfLoad->push_back(instruction1);\n //instruction1->setOperand(0, Fvalue);\n //instruction1->dump();\n }\n\n }\n }\n }\n\n\n // Modify Here\n while (!WorkListUserOfLoad->empty()) {\n Instruction *instruction = WorkListUserOfLoad->pop_back_val();\n instruction->setOperand(0, Fvalue);\n instruction->dump();\n }\n\n // Removing all loads that are used by the global variable\n while (!WorkListLoad->empty()) {\n Instruction *instruction = WorkListLoad->pop_back_val();\n instruction->eraseFromParent();\n }\n\n\n\n }\n }\n\n\n\n\n\n\n\n\n return true;\n }\n };\n}\n\nchar ConstantReplacementPass::ID = 0;\n\n\nstatic RegisterPass<ConstantReplacementPass> F0("constantREP", "Constant Replacement Pass "\n , false,true);\nRun Code Online (Sandbox Code Playgroud)\n\n关键点:-
\n\n在对指令进行任何修改之前。首先收集在工作清单中。
对工作清单进行修改。
使用迭代器时不能进行修改。
我在上面的源码上测试成功hello.cpp通过后对应的IR如下:-
entry:\n%b = alloca float, align 4\n%c = alloca float, align 4\n%d = alloca float, align 4\ncall void @llvm.dbg.declare(metadata float* %b, metadata !14, metadata !15),\n... !dbg !16\nstore float 0x40019999A0000000, float* %b, align 4, !dbg !16\ncall void @llvm.dbg.declare(metadata float* %c, metadata !17, metadata !15),\n... !dbg !18\nstore float 0x401147AE20000000, float* %c, align 4, !dbg !18\ncall void @llvm.dbg.declare(metadata float* %d, metadata !19, metadata !15),\n... !dbg !20\n%0 = load float, float* %c, align 4, !dbg !21\n%mul = fmul float 0x3FF6666660000000, %0, !dbg !22\nstore float %mul, float* %d, align 4, !dbg !20\n%1 = load float, float* %d, align 4, !dbg !23\nret float %1, !dbg !24\nRun Code Online (Sandbox Code Playgroud)\n\n也许使用 -O3 优化标志会消除一切......
\n\n希望这可以帮助..
\n