如何获得LLVM全局变量常量值?

蘇郁翔*_*蘇郁翔 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().

Ber*_*poh 1

考虑下面的例子

\n\n

hello.cpp

\n\n
 #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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

模块通道将循环浮点全局变量,程序中的任何使用都将被常量 FP 值替换。LLVM pass如下ConstantReplacementPass.cpp:-

\n\n
#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);\n
Run Code Online (Sandbox Code Playgroud)\n\n

关键点:-

\n\n
    \n
  1. 在对指令进行任何修改之前。首先收集在工作清单中。

  2. \n
  3. 对工作清单进行修改。

  4. \n
  5. 使用迭代器时不能进行修改。

  6. \n
\n\n

我在上面的源码上测试成功hello.cpp通过后对应的IR如下:-

\n\n
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\n
Run Code Online (Sandbox Code Playgroud)\n\n

也许使用 -O3 优化标志会消除一切......

\n\n

希望这可以帮助..

\n