我正在写几个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,似乎也不会发生错误。
任何人都可以告诉我为什么会发生这种断言错误,并且(或许)如何解决这个问题?