あかりラボ

七森中赤座あかり研究室の活動日記

C++ LLVM passでループを扱いたい人に送る記事

タイトルのとおりです.もう誰もLLVM IRで泣かないような世界を作るのが夢です.

LLVM IRには古いやつ(Legacy Pass Manager)と新しいやつ(New Pass Manager)がありますが,本記事は新しいやつ向けです.

関数内のループを抽出する

まずLoopInfoを取ってからイテレータを使ってループ(Loopクラス)を取り出します.一番外側のループのみ抽出できます.

ModulePass::run(Module& M, ModuleAnalysisManager& MAM)  {
  FunctionAnalysisManager &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();

  for (auto &F : M) {
    if (!F.isDeclaration()) {
      LoopInfo &li = FAM.getResult<LoopAnalysis>(F);
      for (LoopInfo::iterator i = li.begin(), e = li.end(); i != e; i++) {
        // *i で Loop* が取れる
      }
    }
  }
}

ループ内ループを取る

  // Loop *loop;
  const std::vector<Loop*> &subloops = loop->getSubLoops();

ループの親ループを取る

一番外のループだった場合nullptrが返ります.

// Loop *loop;
Loop *parent = loop->getParentLoop();

ループ内の命令列を取る

// Loop *loop;
for (Loop::block_iterator bb = loop->block_begin(); bb != loop->block_end(); bb++) {
  BasicBlock *BB = *bb;
  for (auto &I: *BB) {
    // I は Instruction&
  }
}

そのループ内に属する全てのBasicBlockを取る

// Loop *loop;
for (Loop::block_iterator bb = loop->block_begin(); bb != loop->block_end(); bb++) {
  BasicBlock *BB = *bb;
  if (loop->contains(BB)) {
    // BB は loop に属する 
  }
}

ループにプリヘッダを付ける

hoistingなどに有用です.

// Loop *loop;
BasicBlock *newBB = InsertPreheaderForLoop(loop, nullptr, nullptr, nullptr, false);

付けたプリヘッダに命令を挿入する際は,IRBuilderを利用します

IRBuilder<> IRB(&newBB->back());