1*2f09f445SMaksim Panchenko //===- bolt/Passes/CallGraphWalker.cpp ------------------------------------===// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler // 9*2f09f445SMaksim Panchenko // This file implements the CallGraphWalker class. 10*2f09f445SMaksim Panchenko // 11a34c753fSRafael Auler //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/Passes/CallGraphWalker.h" 14a34c753fSRafael Auler #include "bolt/Passes/BinaryFunctionCallGraph.h" 15a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 16a34c753fSRafael Auler #include "llvm/Support/Timer.h" 17a34c753fSRafael Auler #include <queue> 18a34c753fSRafael Auler #include <set> 19a34c753fSRafael Auler 20a34c753fSRafael Auler namespace opts { 21a34c753fSRafael Auler extern llvm::cl::opt<bool> TimeOpts; 22a34c753fSRafael Auler } 23a34c753fSRafael Auler 24a34c753fSRafael Auler namespace llvm { 25a34c753fSRafael Auler namespace bolt { 26a34c753fSRafael Auler traverseCG()27a34c753fSRafael Aulervoid CallGraphWalker::traverseCG() { 28a34c753fSRafael Auler NamedRegionTimer T1("CG Traversal", "CG Traversal", "CG breakdown", 29a34c753fSRafael Auler "CG breakdown", opts::TimeOpts); 30a34c753fSRafael Auler std::queue<BinaryFunction *> Queue; 31a34c753fSRafael Auler std::set<BinaryFunction *> InQueue; 32a34c753fSRafael Auler 33a34c753fSRafael Auler for (BinaryFunction *Func : TopologicalCGOrder) { 34a34c753fSRafael Auler Queue.push(Func); 35a34c753fSRafael Auler InQueue.insert(Func); 36a34c753fSRafael Auler } 37a34c753fSRafael Auler 38a34c753fSRafael Auler while (!Queue.empty()) { 39a34c753fSRafael Auler BinaryFunction *Func = Queue.front(); 40a34c753fSRafael Auler Queue.pop(); 41a34c753fSRafael Auler InQueue.erase(Func); 42a34c753fSRafael Auler 43a34c753fSRafael Auler bool Changed = false; 44a34c753fSRafael Auler for (CallbackTy Visitor : Visitors) { 45a34c753fSRafael Auler bool CurVisit = Visitor(Func); 46a34c753fSRafael Auler Changed = Changed || CurVisit; 47a34c753fSRafael Auler } 48a34c753fSRafael Auler 49a34c753fSRafael Auler if (Changed) { 50a34c753fSRafael Auler for (CallGraph::NodeId CallerID : CG.predecessors(CG.getNodeId(Func))) { 51a34c753fSRafael Auler BinaryFunction *CallerFunc = CG.nodeIdToFunc(CallerID); 52a34c753fSRafael Auler if (InQueue.count(CallerFunc)) 53a34c753fSRafael Auler continue; 54a34c753fSRafael Auler Queue.push(CallerFunc); 55a34c753fSRafael Auler InQueue.insert(CallerFunc); 56a34c753fSRafael Auler } 57a34c753fSRafael Auler } 58a34c753fSRafael Auler } 59a34c753fSRafael Auler } 60a34c753fSRafael Auler walk()61a34c753fSRafael Aulervoid CallGraphWalker::walk() { 62a34c753fSRafael Auler TopologicalCGOrder = CG.buildTraversalOrder(); 63a34c753fSRafael Auler traverseCG(); 64a34c753fSRafael Auler } 65a34c753fSRafael Auler 6640c2e0faSMaksim Panchenko } // namespace bolt 6740c2e0faSMaksim Panchenko } // namespace llvm 68