如何强制 LLVM 生成单个"ret"?



考虑以下LLVM IR:

@yyy = external dso_local global i32
@zzz = external dso_local global i64
define void @exec_xxx() {
entry:
%0 = load i32, i32* @yyy, align 4
%1 = icmp eq i32 %0, 0
br i1 %1, label %bb_true, label %bb_false
bb_true:
store i64 0, i64* @zzz, align 8
br label %bb_false
bb_false:
ret void
}

这里我们看到它只有一个ret。但是,生成的代码有多个ret:

exec_xxx:                               # @exec_xxx
cmp     dword ptr [rip + yyy], 0
je      .LBB0_1
ret
.LBB0_1:                                # %bb_true
mov     qword ptr [rip + zzz], 0
ret

由于某些原因,在生成的代码中需要单个ret

问题:如何强制LLVM生成单个ret?

LLVMish对此的回答是编写一个传递。pass是LLVM修改代码的方式

在这种情况下,这将是非常简单的,你需要一个类声明继承PassInfoMixin<>和重新实现run(Function &, FunctionAnalysisManager &)。我认为你的重新实现应该是15-20行代码。

如果你以前没有写过一篇文章,我将概述一下。它需要遍历基本块,查看每个块的结束符是否存在ReturnInst>),并将存在的结束符添加到列表中。迭代后,如果列表中返回值少于两个,则提前返回。

否则创建一个新的基本块。如果返回类型不是void,则需要创建一个phi节点并用来自返回的传入值填充它,然后创建返回phi节点的返回。如果它是空的,你就返回一个新的空值。最后,用新块的分支替换所有旧的返回。做。

最新更新