继续学习LLVM笔记。
LLVM的新版本好像将phi替换成了select,有必要研究一下二者的区别。
查询一下control dependence 和Terminator分别是什么意思。
DenseMap
SmallPtrSet,定义该类使用了模板,其中第一个参数表示Set中的元素类型,第二个参数表示Set的大小,使用下述代码创建了一个类型为BasicBlock,大小为16的集合:
/// Set of blocks with not known to have live terminators.
SmallSetVector<BasicBlock *, 16> BlocksWithDeadTerminators;
执行removeDeadInstructions()时,我注意到返回值是ADCEChanged,该struct定义在同一个文件中,定义代码如下:
struct ADCEChanged {
bool ChangedAnything = false;
bool ChangedNonDebugInstr = false;
bool ChangedControlFlow = false;
};
其中ChangedNonDebugInstr比较费解,带入到源代码中(下面的是简化版):
if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) {
} else {
Changed.ChangedNonDebugInstr = true;
}
其实就是判断是否有非DebugInfoInstrinsic指令的修改,也即是否有用户编写的指令修改,如果LLVM生成的Debug信息造成的死代码消除,说明用户编写的源程序不存在分析出的死代码。
后续使用也可以看到
if (!Changed.ChangedNonDebugInstr) {
// Only removing debug instructions does not affect MemorySSA.
//
// Therefore we preserve MemorySSA when only removing debug instructions
// since otherwise later passes may behave differently which then makes
// the presence of debug info affect code generation.
PA.preserve<MemorySSAAnalysis>();
}
目前有一个疑问,为什么两个判断结构的封装是嵌套的,也即是否存在修改了ControlFlow但没有修改NonDebugInstr。这样的话判断结构就不存在了:
PreservedAnalyses PA;
if (!Changed.ChangedControlFlow) {
PA.preserveSet<CFGAnalyses>();
if (!Changed.ChangedNonDebugInstr) {
// Only removing debug instructions does not affect MemorySSA.
//
// Therefore we preserve MemorySSA when only removing debug instructions
// since otherwise later passes may behave differently which then makes
// the presence of debug info affect code generation.
PA.preserve<MemorySSAAnalysis>();
}
}
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<PostDominatorTreeAnalysis>();
return PA;
留待以后思考吧。
static bool isUnconditionalBranch(Instruction *Term) {
auto *BR = dyn_cast<BranchInst>(Term);
return BR && BR->isUnconditional();
}
这个函数也有意思,LLVM把dyn_cast用活了,奇技淫巧get。
LLVM在上述程序中为什么不适用isa<BranchInst>(Term),想必是因为该函数不仅要求是BranchInst还要求是UnConditionalBranch。
为什么UnconditionalBranch在该例子中是特殊的,在下述代码中也有所透露:
// Mark unconditional branches at the end of live
// blocks as live since there is no work to do for them later
if (BBInfo.UnconditionalBranch)
markLive(BBInfo.Terminator);