| //===- bolt/Passes/CallGraphWalker.cpp ------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the CallGraphWalker class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "bolt/Passes/CallGraphWalker.h" |
| #include "bolt/Passes/BinaryFunctionCallGraph.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Timer.h" |
| #include <queue> |
| #include <set> |
| |
| namespace opts { |
| extern llvm::cl::opt<bool> TimeOpts; |
| } |
| |
| namespace llvm { |
| namespace bolt { |
| |
| void CallGraphWalker::traverseCG() { |
| NamedRegionTimer T1("CG Traversal", "CG Traversal", "CG breakdown", |
| "CG breakdown", opts::TimeOpts); |
| std::queue<BinaryFunction *> Queue; |
| std::set<BinaryFunction *> InQueue; |
| |
| for (BinaryFunction *Func : TopologicalCGOrder) { |
| Queue.push(Func); |
| InQueue.insert(Func); |
| } |
| |
| while (!Queue.empty()) { |
| BinaryFunction *Func = Queue.front(); |
| Queue.pop(); |
| InQueue.erase(Func); |
| |
| bool Changed = false; |
| for (CallbackTy Visitor : Visitors) { |
| bool CurVisit = Visitor(Func); |
| Changed = Changed || CurVisit; |
| } |
| |
| if (Changed) { |
| for (CallGraph::NodeId CallerID : CG.predecessors(CG.getNodeId(Func))) { |
| BinaryFunction *CallerFunc = CG.nodeIdToFunc(CallerID); |
| if (InQueue.count(CallerFunc)) |
| continue; |
| Queue.push(CallerFunc); |
| InQueue.insert(CallerFunc); |
| } |
| } |
| } |
| } |
| |
| void CallGraphWalker::walk() { |
| TopologicalCGOrder = CG.buildTraversalOrder(); |
| traverseCG(); |
| } |
| |
| } // namespace bolt |
| } // namespace llvm |