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