[llvm-dev] How to change the type of operands in the Callinst in llvm?

Suhua Lei via llvm-dev llvm-dev at lists.llvm.org
Mon Aug 29 18:18:57 PDT 2016

 Hi all,

I am Sue. I am writing a LLVM pass to change the type of float-point
variables in the original program to long double. My framework is like this:

for (auto B : F) {
//for every basic block B in the funtion F
for (auto I : B){
//for every instruction I in the basic block B
    if (I is a AllocaInst){
       If the type of I is float or double,
       then change the type to long double, construct new I';
         for (auto U: I->users()){
              //propogate the new type to I's users
              transform(U, I, I');

transform(U, I, I'){
    if (U is StoreInst)
        Construct new storeinst;
    if(U is LoadInst){
        Construct new_load;
        for(auto W: U->users())
           transform(W, U, new_load);
    ... ....

I have finished changing the type of AllocaInst, StoreInst, LoadInst,

However, I have some trouble when implementing the transformation of


   Change the type of the arguments of function calls
   2. Construct the body of called function with new type

   Change the type of the return value

For example, I want to change the following IR:

    %call = call double @add(double %0, double %1)

    define double @add(double %x, double %y) #0 {
      %x.addr = alloca double, align 8
      %y.addr = alloca double, align 8
      store double %x, double* %x.addr, align 8
      store double %y, double* %y.addr, align 8
      %0 = load double, double* %x.addr, align 8
      %1 = load double, double* %x.addr, align 8
      %add = fadd double %0, %1
      ret double %add

To IR_New:

    %call = call x86_fp80 @new_add(x86_fp80 %0, x86_fp80 %1)

    define x86_fp80 @new_add(x86_fp80 %x, x86_fp80 %y) #0 {
      %x.addr = alloca x86_fp80, align 16
      %y.addr = alloca x86_fp80, align 16
      store x86_fp80 %x, x86_fp80* %x.addr, align 16
      store x86_fp80 %y, x86_fp80* %y.addr, align 16
      %0 = load x86_fp80, x86_fp80* %x.addr, align 16
      %1 = load x86_fp80, x86_fp80* %x.addr, align 16
      %add = fadd x86_fp80 %0, %1
      ret x86_fp80 %add

My original idea is when I find a CallInst,

   if (CallInst *call = dyn_cast<CallInst>(it)){

do the following three steps:


   Construct the new FunctionType

   x86_fp80(x86_fp80, x86_fp80)


   std::vector<Type*> ParamTys;
   FunctionType *new_fun_type =
FunctionType::get(Type::getX86_FP80Ty(context), ParamTys, true);


   Construct function with new type in Step 1, i.e. construct new_add in
   the example

   Function *fun = call->getCalledFunction();
   Function *new_fun =
Function::Create(new_fun_type,fun->getLinkage(), "new_add",


   Construct a new CallInst with the new function obtained from step 2.

   CallInst *new_call = CallInst::Create(new_fun, *arrayRefOperands,
"newCall", call);

However, in this way, I got the following:

   %call = call x86_fp80 (x86_fp80, x86_fp80, ...) @0(x86_fp80 %5, x86_fp80 %7)

   declare x86_fp80 @new_add(x86_fp80, x86_fp80, ...)

A new definition of called function is constructed(declare x86_fp80
@new_add(x86_fp80, x86_fp80, ...)), but the body of this new function is
empty. I am very confused how to add the body and get the IR_New I want. My
naive idea is:
for (Instruction i : called function(add in the example)){
    create new_i with type x86_fp80;
    insert new_i in the new function constructed(new_add in the example);

Is this a good way to achieve my goal please?

Any advice will be greatly appreciated :)


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160829/82229430/attachment.html>

More information about the llvm-dev mailing list