Hi everyone, I am trying to write a pass, that finds some instructions and replaces them with my intrinsics, but I am having problem understanding, how this should be done. Let's say I have this instruction: %tmp14 = load i32* getelementptr ([32 x i32]* @gpregs, i32 0, i64 28) and i need to read the load's operands and replace it by let's say: %tmp14 = call i32 @llvm.regread_i32.i32(i32 0, i32 1) Here is what I have: //for each instruction of a function for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { Instruction* i = &(*I); //if this is a load if (isa<LoadInst>(i)) { //now i need to create an instruction that represents a call to a intrinsic Function* FIntr = Intrinsic::getDeclaration(&M, Intrinsic::regread_i32); // here it fails: void llvm::CallInst::init(llvm::Value*): //Assertion `FTy->getNumParams() == 0 && "Calling a function with bad signature"' failed. Instruction* Instr = CallInst::Create(FIntr); //do some stuff with the operands //and replace it ReplaceInstWithInst(i, Instr); } } Intrinsic regread_i32 is defined in Intrinsics.td as follows: //represents register value read, as arguments takes 1) register class number (determined from the acessed variable, here 'regs') and 2) register operand index (not important now) def int_regread_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; The problem is, that I have not found yet, how to correctly create an intrinsic instruction and how do I access and set operands. Is there some documentation, how is the LLVM IR API designed? Or, has someone already tried to solve similar problem? (I am already trying to learn from the source code how it works, but I thought that asking you would be faster:) Thank you Adam btw.: Is there a way how to search archived messages from this mailing list? Google with site:lists.cs.uiuc.edu does not work very much.
Samuel Crow
2009-Jun-24 18:16 UTC
[LLVMdev] searching mailing list (was Re:Replacing instruction in LLVM IR by an intrinsics)
> > btw.: Is there a way how to search archived messages from this mailing list? > Google with site:lists.cs.uiuc.edu > does not work very much.Try http://www.nabble.com/LLVM---Dev-f692.html --Sam
Eli Friedman
2009-Jun-25 00:18 UTC
[LLVMdev] Replacing instruction in LLVM IR by an intrinsics
On Thu, Jun 25, 2009 at 12:32 AM, ihusar<ihusar at fit.vutbr.cz> wrote:> //now i need to create an instruction that represents a call to a intrinsic > Function* FIntr = Intrinsic::getDeclaration(&M, Intrinsic::regread_i32); > > // here it fails: void llvm::CallInst::init(llvm::Value*): > //Assertion `FTy->getNumParams() == 0 && "Calling a function with bad signature"' failed. > Instruction* Instr = CallInst::Create(FIntr);You have to include the operands in the call to CallInst::Create. -Eli
On Thu, 25 Jun 2009 02:18:23 +0200, Eli Friedman <eli.friedman at gmail.com> wrote:> On Thu, Jun 25, 2009 at 12:32 AM, ihusar<ihusar at fit.vutbr.cz> wrote: >> //now i need to create an instruction that represents a call to a intrinsic >> Function* FIntr = Intrinsic::getDeclaration(&M, Intrinsic::regread_i32); >> >> // here it fails: void llvm::CallInst::init(llvm::Value*): >> //Assertion `FTy->getNumParams() == 0 && "Calling a function with bad signature"' failed. >> Instruction* Instr = CallInst::Create(FIntr); > > You have to include the operands in the call to CallInst::Create. > > -EliHi, I created arguments as you told and now everything works fine. If someone would be interested, I am putting the code here. Adam void CGInstrOpRewriter::replaceByIntrinsic(Module& M, Instruction* instrToReplace, const Intrinsic::ID intrId, const int arg1, const int arg2) { //create function and its arguments Function* FIntr = Intrinsic::getDeclaration(&M, intrId); SmallVector<Value*, 2> Args(2); Args[0] = ConstantInt::get(Type::Int32Ty, arg1); Args[1] = ConstantInt::get(Type::Int32Ty, arg2); //now create and replace original instruction Instruction* IntrI = CallInst::Create(FIntr, Args.begin(), Args.end()); ReplaceInstWithInst(instrToReplace, IntrI); } bool CGInstrOpRewriter::runOnModule(Module &M) { if (!bLoaded) { llvm::cerr << "CG: Error: Ignoring module\n"; //should not happen return false; } //for each function in module for(Module::iterator FuncIt = M.getFunctionList().begin(); FuncIt != M.getFunctionList().end(); FuncIt++) { Function* F = FuncIt; llvm::cerr << "Original ---- \n" << *F << "\n"; //and for each instruction of a function for (inst_iterator It = inst_begin(F), E = inst_end(F); It != E; ++It) { //previous iterator inst_iterator PrevIt; bool bFirst = false; if (It == inst_begin(F)) { bFirst = true; } else { PrevIt = It; --PrevIt; } Instruction* CurrI = &(*It); llvm::cerr << "Processing " << *CurrI << "\n"; if (isa<LoadInst>(CurrI)) { //replace - intrinsics ID (from Intrinsics.def) and some int arguments replaceByIntrinsic(M, CurrI, Intrinsic::regread_i32, 1, 2); //renew iterator because we removed previous instruction to which it was pointing if (!bFirst) { It = ++PrevIt; } else { It = ++inst_begin(F); } } } llvm::cerr << "Modified ---- \n" << *F << "\n"; } return true; }