LLVM 将 if/else 插入现有的基本块

LLVM insert if/else into existing basic block

我想在运行时检查一些指令的值。因此,我创建了一个比较指令和一个分支到 "then" 基本块或 "else" 基本块的分支指令。但是,我不确定如何在条件分支之后插入创建的基本块以及现有基本块的拆分如何工作。

Instruction* someInst;
IRBuilder<> B(someInst);

Value* condition = B.CreateICmp(CmpInst::ICMP_UGT, someInst, someValue);

BasicBlock* thenBB = BasicBlock::Create(*ctx, "then");
BasicBlock* elseBB = BasicBlock::Create(*ctx, "else");

B.CreateCondBr(condition, thenBB, elseBB);

B.SetInsertPoint(thenBB);
//insert stuff

B.SetInsertPoint(elseBB);
//insert stuff

如何在现有基本块的中间插入 if/else?

您可以使用一个名为 llvm::SplitBlockAndInsertIfThenElse 的辅助函数。您需要 #include "llvm/Transforms/Utils/BasicBlockUtils.h".

简答:您或许可以使用 llvm::SplitBlockAndInsertIfThenElse。不要忘记你的 PHI 节点。

根据维基百科,basic block:

is a straight-line code sequence with no branches in except to the entry and no branches out except at the exit.

因此,if-then-else 涉及多个块:

  1. 包含条件的块,
  2. 然后块
  3. else 块
  4. 可选地,then 和 else 块之后的块(如果 then 和 else 不 return 或在其他地方分支)。

要插入 if-then-else,必须将原始基本块拆分为 (1) 和 (4)。条件检查和条件分支进入 (1),并且 (2) 和 (3) 以 (4) 的分支结束。 SplitBlockAndInsertIfThenElse function (docs) 会在简单的情况下为你做这件事。如果您有更复杂的要求 - 例如 then 或 else 包含他们自己的控制流 - 您可能需要自己进行拆分。

如果您的 then 或 else 块修改变量,您将需要一个 PHI 节点。 Kaleidoscope tutorial explains why PHI nodes are needed and how to use them. The tutorial references the Single Static Assignment 维基百科文章,这是有用的背景。