LLVM Pass 简介(4)
这里介绍LLVM或者所有编译器中非常重要的一种结构,def-use链,或者叫DU-chain。说是DU,实际上除了def-use,还有use-def的存在。
通常,我们可能有Value类的一个实例,并且我们想确定哪些使用者使用了该Value。我们将具有特定值的所有用户的列表称为def-use链。
另外,通常有一个User Class实例,需要知道它使用了哪些值。用户使用的所有值的列表称为use-def链。 Instruction类的实例是常见的User,
因此我们可能要遍历特定指令使用的所有值另外,通常有一个User Class实例,需要知道它使用了哪些值。用户使用的所有值的列表称use-def链。
Instruction类的实例是常见的User,因此我们可能要遍历特定指令使用的所有值。
source from:https://llvm.org/docs/ProgrammersManual.html#iterating-over-def-use-use-def-chains
def是定值,use是使用点。DU是查找该点的使用点,UD是确定该点用了哪些其他点,其实就是得到它的操作数,如果这个是一个函数调用的话,就是找到函数调用的参数列表。
编程手册中给的一个例子,介绍如何使用函数F的使用点:
Function *F = ...; for (User *U : F->users()) { if (Instruction *Inst = dyn_cast<Instruction>(U)) { errs() << "F is used in instruction:\n"; errs() << *Inst << "\n"; }
而对于UD,是这样的case:
Instruction *pi = ...; for (Use &U : pi->operands()) { Value *v = U.get(); // ... }
下边是一个DCE的代码,进行死代码删除的功能,来源于《LLVM CodeBook》一书,代码虽然有bug,但是作为DU的阅读代码非常不错:
1 // Hello4 - Dead code Elimination 2 // 3 //source code :https://ch4r1l4.github.io/2019/05/04/LLVM-%E5%88%9D%E6%8E%A2-2-Optimization-Pass-%E7%BC%96%E5%86%99/ 4 namespace { 5 struct Hello4 : public FunctionPass { 6 static char ID; // Pass identification, replacement for typeid 7 Hello4() : FunctionPass(ID) {} 8 using BasicBlockListType = SymbolTableList<BasicBlock>; 9 10 bool runOnFunction(Function &F) override { 11 errs()<<"in runOnFunction\n"; 12 SmallPtrSet<Instruction*, 32> Alive; 13 SmallVector<Instruction*, 32> Worklist; 14 for(Instruction & I:instructions(F)){ 15 if(isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) 16 || isa<LandingPadInst>(I) || I.mayHaveSideEffects()){ 17 Alive.insert(&I); 18 Worklist.push_back(&I); 19 } 20 } 21 while(!Worklist.empty()){ 22 Instruction* Curr = Worklist.pop_back_val(); 23 for( Use &OI : Curr->operands()) { 24 if (Instruction* Inst = dyn_cast<Instruction>(OI)) 25 if(Alive.insert(Inst).second) 26 Worklist.push_back(Inst); 27 } 28 } 29 for(Instruction &I : instructions(F)){ 30 if(!Alive.count(&I)){ 31 Worklist.push_back(&I); 32 I.dropAllReferences(); 33 } 34 } 35 for(Instruction* I : Worklist){ 36 I->dump(); 37 I->eraseFromParent(); 38 } 39 return !Worklist.empty(); 40 41 return false; 42 } 43 44 45 // We don't modify the program, so we preserve all analyses. 46 void getAnalysisUsage(AnalysisUsage &AU) const override { 47 AU.setPreservesAll(); 48 } 49 std::map<std::string, uint> opCodeMap; 50 }; 51 } 52 53 char Hello4::ID = 0; 54 static RegisterPass<Hello4> Ms("hello4", "remove dead code", false, false);