xref: /llvm-project/bolt/lib/Core/CallGraphWalker.cpp (revision 2430a354bfb9e8c08e0dd5f294012b40afb75ce0)
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 young void 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 young void 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