llvm-删除死亡代码的实用分析

LLVM - Liveness Analysis to remove dead code

本文关键字:删除 死亡代码 llvm-      更新时间:2023-10-16

我正在尝试实施LIVISE分析以删除死亡指令。我知道isInstructionTriviallyDead()存在,但是,我想学习如何使用Def-use(或使用)链删除代码。

我目前正在这样做的方式是,我在块中的所有指令(使用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();
    }
}

问题是,返回指令没有对其进行调查的用途(而且我敢肯定还有其他无用的定义)。但是,不应删除返回指令,因为它会导致语义上不正确的代码。

我的一般方法是通过Livices分析删除说明吗?我该怎么做才能确保不删除返回之类的说明?

任何指针都非常感谢:)

还检查指令是否是终结者指令(inst->isTerminator()

您提到了llvm::isInstructionTriviallyDead,这是一个很好的开始,可以从可以删除的内容以及无法删除的内容中进行一些见解。

您已经注意到您无法删除终结器指令。

另外,您不想删除没有任何用途的说明,但是有副作用。考虑一下:

define void @bar()() {
  call void @foo()()
  ret void
}

您不想删除call指令,即使没有用途,因为它可以写入stdout或更改某些全局变量。store的同样事情也是如此。检查Instruction::mayHaveSideEffects中的完整列表。

您的livesice分析太激进了:没有任何用途是必要的,但是不足以被视为死亡。

如果您不想将isInstructionTriviallyDead用于学习目的,我建议您启动其他方式:请考虑肯定指令何时死亡(例如,alloca在没有用途时死亡,add指令也可以。。)然后概括。

此外,只需循环遍历所有指示并删除死亡的指示就不够。例如:

%2 = add i32 3, %1
%3 = add i32 3, %2

第一次遇到%2时,它在%3中使用,因此没有死。但是在消除%3死亡之后,%2也会死亡。您可以通过迭代来克服此问题,直到找不到新的死指令(无效,但简单)或通过某些递归过程。

我认为在删除instruciton之前,您应该首先判断其功能。用isa<>()通过

做到这一点
if (isa<ReturnInst>(instruction) || isa<BranchInst>(instruction) || ...) {
  deadInst = false;
}