Using a LLVM pass, I wish to iterate through all conditional branches of the form if(a==b)
and change these statements to if(func(a)==func(b))
thereby replacing the original operands a
and b
with the result of function calls func(a)
and func(b)
. This should occur wherever an if
statement of the form if(a==b)
is found.
Here a
is the operand. I can access this operand in my LLVM pass but I can't change it to be the result of a function. What approach should I use to achieve this.
It can be assumed that a
and b
are always of the same type and func
takes in parameters of any type and returns the same type of the parameter. For simplicity it can also be assumed that a
and b
are integers and func
returns an integer as well.
Elaborating on my comment (although there are aspects that are still unclear)
Adopting the following simplifications:
we could do something like this in a llvm::Function
pass:
bool runOnFunction(llvm::Function &CurFunc) override {
bool hasChanged = false;
// the llvm::Function to be called could be specified here
auto *toCallFunc = [...];
for (auto &bb : CurFunc) {
auto *ti = bb.getTerminator();
auto *bri = llvm::dyn_cast<llvm::BranchInst>(ti);
if (!bri)
continue;
if (!bri->isConditional())
continue;
auto *cond = bri->getCondition();
// please note that this cast is for integer comparisons
// adjust according to your needs
auto cmpi = llvm::dyn_cast<llvm::ICmpInst>(cond);
if (!cmpi)
continue;
auto *opA = cmpi->getOperand(0);
auto *opB = cmpi->getOperand(1);
auto argsA = llvm::ArrayRef<llvm::Value *>(&opA, 1);
auto argsB = llvm::ArrayRef<llvm::Value *>(&opB, 1);
// note the insertion before the comparison operation
auto *ciA = llvm::CallInst(toCallFunc, argsA, "funcA", cmpi);
auto *ciB = llvm::CallInst(toCallFunc, argsB, "funcB", cmpi);
cmpi->setOperand(1, opA);
cmpi->setOperand(1, opB);
hasChanged |= true;
}
return hasChanged;
}
From then on, you can expand and deal with other argument types, depending on the required handling.