【LLVM】Pass之间的依赖

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);
  //...
}

在上面的例子中,runOnFunctionDominatorTree由passmanager调用并返回接口给当前的pass。
详细参考

推荐阅读更多精彩内容