考虑以下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节点的返回。如果它是空的,你就返回一个新的空值。最后,用新块的分支替换所有旧的返回。做。