使用模块传递内部循环传递

时间:2016-04-22 20:06:36

标签: llvm llvm-c++-api

我正在写几个LLVM通行证。其中一个是ModulePass,它执行一些分析,但不会改变任何东西(没有函数,没有元数据,没有变量......)。它只查看一些元数据节点,就是这样。

MyModuleChecker.cpp:

INITIALIZE_PASS_BEGIN(MyModuleChecker, "mmc", "Check module",  false, true)
INITIALIZE_PASS_END(MyModuleChecker, "mmc", "Check module",  false, true)

char MyModuleChecker::ID = 0;

namespace llvm {
  Pass* createMyModuleCheckerPass() {
    return new MyModuleChecker();
  }
}

MyModuleChecker::MyModuleChecker(void) : ModulePass(ID) {
  initializeMyModuleCheckerPass(*PassRegistry::getPassRegistry());
}

void MyModuleChecker::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
}

bool MyModuleChecker::runOnModule(Module &M) {
  // ...
  return false; // <-- Under all circumstances
}

然后有第二遍。该传递是一个LoopPass,并根据某些标准基本执行一些循环展开任务。为了计算展开计数,通行证需要MyModuleChecker通过的结果。所以我把它放在依赖项中。

MyLoopUnroll.cpp:

INITIALIZE_PASS_BEGIN(MyLoopUnroll, "myloopunroll", "Unroll loops",  false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
INITIALIZE_PASS_DEPENDENCY(MyModuleChecker)
INITIALIZE_PASS_DEPENDENCY(DataLayoutPass)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_END(MyLoopUnroll, "myloopunroll", "Unroll loops",  false, false)

char MyLoopUnroll::ID = 0;

namespace llvm {
  Pass* createMyLoopUnrollPass() {
    return new MyLoopUnroll();
  }
}

MyLoopUnroll::MyLoopUnroll()
 : LoopPass(ID), MDK(nullptr), LI(nullptr), SE(nullptr), AC(nullptr),
   DL(nullptr) {
  initializeMyLoopUnrollPass(*PassRegistry::getPassRegistry());
}

void HDLLoopUnroll::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<LoopInfo>();
  AU.addRequired<ScalarEvolution>();
  AU.addRequired<MyModuleChecker>();
  AU.addPreserved<MyModuleChecker>();
  AU.addRequired<DataLayoutPass>();
  AU.addPreserved<DataLayoutPass>();
  AU.addRequired<AssumptionCacheTracker>();
}

bool MyLoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
  LI = &getAnalysis<LoopInfo>();
  SE = &getAnalysis<ScalarEvolution>();
  MDK = &getAnalysis<MyModuleChecker>();    // <-- Seems not to work
  DL = &getAnalysis<DataLayoutPass>().getDataLayout();
  AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*L->getHeader()->getParent());

  if ((LI == nullptr) || (SE == nullptr) || (DL == nullptr) || (MDK == nullptr) || (AC == nullptr)) {
    return false;
  }

  bool Changed = handleLoop(L, LPM);
  return Changed;
}

循环展开本身并不是由我自己实现的,而是我使用LLVM提供的现有函数,并且也是由LLVM提供的循环展开使用。

目前这些传递是Scalar库的一部分,因此我采用了相应的文件(包括/llvm/Transforms/Scalar.h,LinkAllPasses.h,...)。所以我的通行证没有动态联系到选择。

现在我想使用opt运行传递(我正在使用LLVM 3.6):

opt -stats -debug -debug-pass=Structure -mem2reg -loop-rotate -myloopunroll -simplifycfg

我现在得到一个断言错误:

LoopRotation: rotating Loop at depth 1 containing: %for.cond<header><exiting>,%for.body,%for.inc<latch>
  Inserted PHI:   %i.01 = phi i32 [ 0, %entry ], [ %i.0, %for.cond ]
  LoopRotation: into Loop at depth 1 containing: %for.body<header>,%for.inc<latch><exiting>
opt: ~/llvm-clang/source/include/llvm/PassAnalysisSupport.h:214: AnalysisType& llvm::Pass::getAnalysisID(llvm::AnalysisID) const [with AnalysisType = MyModuleChecker; llvm::AnalysisID = const void*]: Assertion `ResultPass && "getAnalysis*() called on an analysis that was not " "'required' by pass!"' failed.
// ...
#8 0x1685a99 MyModuleChecker& llvm::Pass::getAnalysisID<MyModuleChecker>(void const*) const ()
#9 0x16857f0 MyModuleChecker& llvm::Pass::getAnalysis<MyModuleChecker>() const ()
#10 0x16853cd MyLoopUnroll::runOnLoop(llvm::Loop*, llvm::LPPassManager&) ()
#11 0xd34aaa llvm::LPPassManager::runOnFunction(llvm::Function&) ()
// ...

而且我不知道该错误发生在哪里以及它发生的原因(任何是的,所有内容都会编译而没有错误和警告)。看起来循环旋转传递正常执行,然后传递管理器在调用getAnalysis<MyModuleChecker>;分析结果时卡在循环展开传递中。

如果我省略-simplifycfg并且在我自己的loopunrolling传递之后没有运行simplifycfg传递,那么在同一个程序中一切正常并且没有断言错误。然后展开循环。 如果将ModuleChecker传递转换为FunctionPass,似乎也不会发生错误。 任何人都可以告诉我为什么会发生这种断言错误,并且(或许)如何解决这个问题?

0 个答案:

没有答案