我正在尝试实施活动分析以删除死命令。我知道isInstructionTriviallyDead()
存在,但是,我想学习如何使用def-use(或use-def)链删除代码。
我目前正在这样做的方式是迭代一个块中的所有指令(使用inst_iterator
),并为每个指令循环遍历其所有用途。最终,如果一条指令没用,那么我认为它已经死了,因此可以使用eraseFromParent()
删除它
这看起来像:
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
bool deadInst = true;
Instruction *inst = &*I;
for (User* pUser : inst->users()) {
// If we enter this loop, we have at least one use, so instruction isn't dead
deadInst = false;
}
// deadInst is true if we didn't enter the loop, so has no uses
if (deadInst) {
inst->eraseFromParent();
}
}
问题是,返回指令没有与它相关的用途(我确信还有其他定义没有用)。但是,不应删除返回指令,因为它会导致语义错误的代码。
我通过活体分析删除说明的一般方法好吗?我该怎样做才能确保不会删除返回等指示?
非常感谢任何指针:)
答案 0 :(得分:0)
还检查指令是否是终止符指令(inst->isTerminator()
)
答案 1 :(得分:0)
您提到了llvm::isInstructionTriviallyDead
,这是一个很好的开始,可以获得有关可以删除的内容和不可删除内容的一些见解。
您已经注意到您无法删除终结符指令。
此外,您不想删除没有使用但有副作用的说明。考虑一下:
define void @bar()() {
call void @foo()()
ret void
}
您不想删除call
指令,即使它没有用处,因为它可以,例如,写入stdout或更改某些全局变量。同样适用于store
。检查Instruction::mayHaveSideEffects
以获取完整列表。
您的活跃度分析过于激进:没有必要必要,但不足以条件使指令被视为死亡。
如果您不想将isInstructionTriviallyDead
用于学习目的,我建议您从另一个方面开始:考虑指令何时失效(例如,alloca
在没有时已经死亡使用,add
指令......)然后概括。
此外,只需循环遍历所有指令并删除死指令是不够的。例如:
%2 = add i32 3, %1
%3 = add i32 3, %2
当您第一次遇到%2
时,它在%3
中有用,所以没有死。但是,在你将%3
消灭后,%2
也会死亡。你可以通过迭代来解决这个问题,直到找不到新的死命令(无效,但很简单),或者通过一些递归过程。