LLVM IR:在两个指令之后插入新指令

时间:2019-02-07 11:10:14

标签: c++ llvm llvm-ir

让我们以LLVM IR函数@example_before()为例。

define void @example_before(i32 %x, i32 %y) {
  %a = and i32 %x, 65535
  %b = lshr i32 %x, 16
  %c = and i32 %y, 65535
  %d = lshr i32 %y, 16
  ret void
}

使用LLVM C ++ API,目标是在其两个参数之后插入新的二进制指令。即在函数中出现的参数之后,比其他参数晚。

在示例中,我们考虑寄存器%a%c。我们要插入%z = mul i32 %a, %c。最终结果应类似于以下@example_after()

define void @example_after(i32 %x, i32 %y) {
  %a = and i32 %x, 65535
  %b = lshr i32 %x, 16
  %c = and i32 %y, 65535
  %z = mul i32 %a, %c
  %d = lshr i32 %y, 16
  ret void
}

为解决该问题,我最终得到了一个辅助函数,该函数在提供的两个参数之后找到该指令。 该函数还需要DominatorTree

/// Finds the first instruction after both A and B.
/// A and B are assumed to be either Instruction or Argument.
Instruction *getInstructionAfter(Value *A, Value *B, DominatorTree &DT) {
  Instruction *I = nullptr;

  if (auto AI = dyn_cast<Instruction>(A))
    I = AI->getNextNode();
  else // If Argument use the first instruction in the entry block.
    I = &cast<Argument>(A)->getParent()->front().front();

  auto BI = dyn_cast<Instruction>(B);
  if (BI && DT.dominates(I, BI))
    I = BI->getNextNode(); // After B.

  return I;
}

getInstructionAfter()的输出可以很容易地用作新指令的插入点。

  IRBuilder<> Builder{getInstructionAfter(X, Y, DT)};
  return Builder.CreateMul(X, Y);

但是,getInstructionAfter()与其解决的问题相比,显得相对复杂。有没有更简单的解决方案?

0 个答案:

没有答案