[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,
BinaryOperator.
However, I have some trouble when implementing the transformation of
CallInst:
1.
Change the type of the arguments of function calls
2. Construct the body of called function with new type
3.
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 {
entry:
%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 {
entry:
%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:
1.
Construct the new FunctionType
x86_fp80(x86_fp80, x86_fp80)
using
std::vector<Type*> ParamTys;
ParamTys.push_back(Type::getX86_FP80Ty(context));
ParamTys.push_back(Type::getX86_FP80Ty(context));
FunctionType *new_fun_type =
FunctionType::get(Type::getX86_FP80Ty(context), ParamTys, true);
2.
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",
fun->getParent());
3.
Construct a new CallInst with the new function obtained from step 2.
CallInst *new_call = CallInst::Create(new_fun, *arrayRefOperands,
"newCall", call);
new_call->takeName(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 :)
Sincerely,
Suhua
-------------- 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