LLVM Pass之间的依赖关系是由PassManager进行管理控制的。由它来控制并管理pass之间的交互与操作。如果pass之间存在依赖关系,例如在执行本pass之前必须先执行哪些pass,这个是必须要先在本pass中声明的。要声明pass的依赖,需要实现getAnalusisUsage
方法。
getAnalysisUsage
方法
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
在此方法中,要声明依赖的pass是填充在AnalysisUsage这个对象中的,具体方法如下:
AnalysisUsage::addRequired<>
AnalysisUsage::addRequiredTransitive<>
如果本pass执行之前需要依赖其它pass的执行,那么可以使用这两种方法中的一种来添加需要执行的pass。对于单个pass使用AnalysisUsage::addRequired<>
添加。
若所需要先执行的pass过多形成Analysis链,则使用第二种方法:addRequiredTransitive<>
添加所有的pass。
考虑另外一种情况,当某一个pass经常会被用到时,我们希望它的结果可以暂时保存避免经常重复进行计算,那么就需要使用下面的方法:
AnalysisUsage::addPreserved<>
它用来暂时保存某个pass的结果。
getAnalysisUsage
代码示例
//保留了CFG,但是改变了程序代码,即必须等LoopInfoWrapperPass执行后才会执行本pass
void LICM::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
}
getAnalysis<> and getAnalysisIfAvailable<>
方法
Pass::getAnalysis<>
方法提供了一种访问依赖pass的方式,它使用一些简单的模板参数来标志对应的pass里的class,它返回了访问这些class的接口:
bool LICM::runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
//...
}
这个方法返回的是LoopInfoWrapperPass
对应的getLoopInfo
方法的接口,不过在这之前,你需要将LoopInfoWrapperPass
声明为一个addRequired Pass。
module级的pass可以返回一个函数级的接口:
bool ModuleLevelPass::runOnModule(Module &M) {
//...
DominatorTree &DT = getAnalysis<DominatorTree>(Func);
//...
}
在上面的例子中,runOnFunction
和DominatorTree
由passmanager调用并返回接口给当前的pass。
详细参考