Replacing instruction in LLVM IR by an intrinsics

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.

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

You have to include the operands in the call to CallInst::Create.

-Eli

Hi, 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;
}