#c 11 #llvm #llvm-ir
Вопрос:
Я пытаюсь написать пропуск llvm и хочу заменить все инструкции, имеющие двоичный оператор сложения, теми же инструкциями, но с умножением вместо сложения. Я запускаю проход по нижеприведенному test.cpp код:
int add( int x, int y) {
x = x y;
// x = x x;
y = x y;
return x;
}
Я могу заменить все добавления умножением в приведенном выше коде, но когда я раскомментирую строку x = x x
, она запускается и переходит в бесконечный цикл, и я понял, что бесконечный цикл находится for (auto amp;U : bop->uses())
в приведенном ниже коде llvm pass.
Итак, может ли кто-нибудь, пожалуйста, помочь мне изменить приведенный ниже код, чтобы он также заменил сложение умножением в инструкции для строки x = x x
.
bool runOnFunction(llvm::Function amp;Func) {
std::string func_name = Func.getName();
for(llvm::BasicBlockamp; b : Func ) {
// llvm::errs() << "nBasic block '" << b.getName() << "' has " << b.size() << " instructions.n";
for (llvm::BasicBlock::iterator DI = b.begin(); DI != b.end(); ) {
llvm::Instruction *I = amp;*DI ;
// llvm::errs() << "Instruction : " << *I << "n";
if(auto bop = llvm::dyn_cast<llvm::BinaryOperator>(I) ) {
llvm::IRBuilder<> Builder(bop);
auto op0 = bop->getOperand( 0 );
auto op1 = bop->getOperand( 1 );
unsigned op = bop->getOpcode();
if( op == llvm::Instruction::Add ) {
llvm::Value *mul = Builder.CreateMul(op0, op1);
for (auto amp;U : bop->uses()) {
// llvm::errs() << "Instruction inside uses: " << *I << "n";
llvm::User *user = U.getUser(); // A User is anything with operands.
user->setOperand(U.getOperandNo(), mul);
}
I->eraseFromParent();
}
}
}
}
return false;
}
Комментарии:
1. Я не присматривался внимательно… но такого рода ошибка часто возникает из-за того, что изменение списка во время его повторения приводит к удивительным результатам. Я уверен, что это работает, но то, как это работает, обычно удивляет людей. Попробуйте изменить свой код, чтобы сначала найти инструкции для изменения и добавить их в отдельную коллекцию. Затем повторите эту коллекцию.