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 Auler void 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 Auler void CallGraphWalker::walk() {
62a34c753fSRafael Auler   TopologicalCGOrder = CG.buildTraversalOrder();
63a34c753fSRafael Auler   traverseCG();
64a34c753fSRafael Auler }
65a34c753fSRafael Auler 
6640c2e0faSMaksim Panchenko } // namespace bolt
6740c2e0faSMaksim Panchenko } // namespace llvm
68