从LLVM IR删除/替换代码

时间:2016-01-11 07:10:46

标签: compiler-construction llvm compiler-optimization llvm-clang llvm-ir

我正在使用LLVM IR代码。我想通过程序从LLVM IR表示中删除指令。 LLVM Official documentation描述了如何删除,但不是那么清楚。由于一些前向引用,当我尝试删除时,它会抛出异常。

例如:

`%add2 = add nsw i32 %4, %5`

`store i32 %add2, i32* %b, align 4 `

在这里,我想删除%add2 = add nsw i32 %4, %5指令,但它会引发异常,因为%add2被第二条指令引用。
 有ReplaceInstWithValueReplaceInstWithInst说明,但官方文档中的用法并不明确。

怎么做?任何人都可以帮我一些例子。

2 个答案:

答案 0 :(得分:1)

如果有两条带有相同llvm的指令,则可以使用ReplaceInstWithInst函数:Type。

例如,如果您的BinaryOperator*导致%add2 = add nsw i32 %4, %5,则可以执行以下操作:

auto& ctx = getGlobalContext();
auto newAdd = BinaryOperator::CreateAdd(
     ConstantInt::get(cast<Type>(Type::getInt32Ty(ctx)), APInt(32, 42)),
     ConstantInt::get(cast<Type>(Type::getInt32Ty(ctx)), APInt(32, -42)));
ReplaceInstWithInst(oldAdd, newAdd);

如果您只是想从IR中删除指令(可能是使用它的所有内容),则替换为UndefValue执行RAUW:

oldAdd->replaceAllUsesWith(UndefValue::get(oldAdd->getType()));
oldAdd->eraseFromParent();

这会产生类似:store i32 undef, i32* %b, align 4的内容,可能会被优化过程删除。

如果你想删除商店,你必须递归所有用户的指示:

void replaceAndErase(Instruction& I) {
    for (auto& U : I.users()) {
          replaceAndErase(*UI);
    }
    I.replaceAllUsesWith(UndefValue::get(I.getType()));
    I.eraseFromParent();
} 

但是你可以认为这个功能不安全。它假定所有用户都是指令。如果您有元数据引用指令,这可能会中断,但您应该明白这一点。

答案 1 :(得分:0)

您可能想要做的是首先使用%add2的RAUW(替换所有用途),然后您可以安全地删除添加指令。

例如,如果你知道上面添加的结果是一个常数(比如说你正在写一个常量传播传递),那么如果你有一个Value * CI和你的指令* I你可以:

I->replaceAllUsesWith(CI)
I->eraseFromParent()

希望有所帮助。