简体   繁体   English

如何强制 LLVM 生成单个“ret”?

[英]How to force LLVM to generate a single 'ret'?

Consider the following LLVM IR:考虑以下 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
}

Here we see that it has a single ret .在这里我们看到它有一个ret However, the generated code has multiple 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

By some reason one need a single ret in the generated code.由于某种原因,在生成的代码中需要一个ret

Question: how to force LLVM to generate a single 'ret'?问题:如何强制 LLVM 生成单个“ret”?

The LLVMish answer to that is to write a pass. LLVMish 对此的回答是写一个通行证。 Passes is how LLVM modifies code. Passes 是 LLVM 修改代码的方式。

In this case that'll be really simple, you'll need a class declaration that inherits PassInfoMixin<> and reimplements run(Function &, FunctionAnalysisManager &) .在这种情况下,这将非常简单,您需要一个继承PassInfoMixin<>并重新实现run(Function &, FunctionAnalysisManager &)的类声明。 Your reimplementation should be 15-20 lines of code, I think.我认为您的重新实现应该是 15-20 行代码。

I'll outline it in case you haven't written a pass before.如果您之前没有写过通行证,我会概述一下。 It needs to iterate over the basic blocks and see whether the terminator of each isa<ReturnInst>(), and add the ones that are to a list.它需要遍历基本块并查看每个块的终止符是否为 <ReturnInst>(),并将那些添加到列表中。 After iterating you return early if there are fewer than two returns in the list.迭代后,如果列表中的返回少于两个,则提前返回。

Otherwise you make a new basic block .否则你会创建一个新的基本块 If the return type isn't void you need to create a phi node and populate it with incoming values from the returns, then create a return that returns the phi node.如果返回类型不是 void,则需要创建一个phi 节点并使用返回的传入值填充它,然后创建一个返回 phi 节点的返回。 If it's void you make a new void return.如果它无效,您将返回一个新的无效返回值。 Finally you replace all the old returns with branches to your new block.最后,您将所有旧返回替换为新块的分支。 Done.完毕。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM