LLVM IR: вставить новую инструкцию сразу после двух аргументов - PullRequest
0 голосов
/ 07 февраля 2019

Давайте рассмотрим пример функции IR LLVM @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() выглядит относительно сложным по сравнению с проблемой, которую он решает.Есть ли более простые решения для этого?

...