blob: ea213f27acbb413462eba9b3cbf24fef72180436 [file] [log] [blame]
Chandler Carruthbf71a342014-02-06 04:37:03 +00001//===- LazyCallGraph.cpp - Analysis of a Module's call graph --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Analysis/LazyCallGraph.h"
11#include "llvm/ADT/SCCIterator.h"
Chandler Carruth219b89b2014-03-04 11:01:28 +000012#include "llvm/IR/CallSite.h"
Chandler Carruth7da14f12014-03-06 03:23:41 +000013#include "llvm/IR/InstVisitor.h"
Chandler Carruthbf71a342014-02-06 04:37:03 +000014#include "llvm/IR/Instructions.h"
15#include "llvm/IR/PassManager.h"
Chandler Carruthbf71a342014-02-06 04:37:03 +000016#include "llvm/Support/raw_ostream.h"
Chandler Carruthbf71a342014-02-06 04:37:03 +000017
18using namespace llvm;
19
20static void findCallees(
21 SmallVectorImpl<Constant *> &Worklist, SmallPtrSetImpl<Constant *> &Visited,
Chandler Carruthe9b50612014-03-10 02:14:14 +000022 SmallVectorImpl<PointerUnion<Function *, LazyCallGraph::Node *>> &Callees,
Chandler Carruthbf71a342014-02-06 04:37:03 +000023 SmallPtrSetImpl<Function *> &CalleeSet) {
24 while (!Worklist.empty()) {
25 Constant *C = Worklist.pop_back_val();
26
27 if (Function *F = dyn_cast<Function>(C)) {
28 // Note that we consider *any* function with a definition to be a viable
29 // edge. Even if the function's definition is subject to replacement by
30 // some other module (say, a weak definition) there may still be
31 // optimizations which essentially speculate based on the definition and
32 // a way to check that the specific definition is in fact the one being
33 // used. For example, this could be done by moving the weak definition to
34 // a strong (internal) definition and making the weak definition be an
35 // alias. Then a test of the address of the weak function against the new
36 // strong definition's address would be an effective way to determine the
37 // safety of optimizing a direct call edge.
38 if (!F->isDeclaration() && CalleeSet.insert(F))
Chandler Carruthe9b50612014-03-10 02:14:14 +000039 Callees.push_back(F);
Chandler Carruthbf71a342014-02-06 04:37:03 +000040 continue;
41 }
42
Chandler Carruth1583e992014-03-03 10:42:58 +000043 for (Value *Op : C->operand_values())
44 if (Visited.insert(cast<Constant>(Op)))
45 Worklist.push_back(cast<Constant>(Op));
Chandler Carruthbf71a342014-02-06 04:37:03 +000046 }
47}
48
49LazyCallGraph::Node::Node(LazyCallGraph &G, Function &F) : G(G), F(F) {
50 SmallVector<Constant *, 16> Worklist;
51 SmallPtrSet<Constant *, 16> Visited;
52 // Find all the potential callees in this function. First walk the
53 // instructions and add every operand which is a constant to the worklist.
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000054 for (BasicBlock &BB : F)
55 for (Instruction &I : BB)
56 for (Value *Op : I.operand_values())
Chandler Carruth1583e992014-03-03 10:42:58 +000057 if (Constant *C = dyn_cast<Constant>(Op))
Chandler Carruthbf71a342014-02-06 04:37:03 +000058 if (Visited.insert(C))
59 Worklist.push_back(C);
60
61 // We've collected all the constant (and thus potentially function or
62 // function containing) operands to all of the instructions in the function.
63 // Process them (recursively) collecting every function found.
64 findCallees(Worklist, Visited, Callees, CalleeSet);
65}
66
67LazyCallGraph::Node::Node(LazyCallGraph &G, const Node &OtherN)
68 : G(G), F(OtherN.F), CalleeSet(OtherN.CalleeSet) {
69 // Loop over the other node's callees, adding the Function*s to our list
70 // directly, and recursing to add the Node*s.
71 Callees.reserve(OtherN.Callees.size());
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000072 for (const auto &OtherCallee : OtherN.Callees)
73 if (Function *Callee = OtherCallee.dyn_cast<Function *>())
Chandler Carruthbf71a342014-02-06 04:37:03 +000074 Callees.push_back(Callee);
75 else
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000076 Callees.push_back(G.copyInto(*OtherCallee.get<Node *>()));
Chandler Carruthbf71a342014-02-06 04:37:03 +000077}
78
Chandler Carruthbf71a342014-02-06 04:37:03 +000079LazyCallGraph::Node::Node(LazyCallGraph &G, Node &&OtherN)
80 : G(G), F(OtherN.F), Callees(std::move(OtherN.Callees)),
81 CalleeSet(std::move(OtherN.CalleeSet)) {
82 // Loop over our Callees. They've been moved from another node, but we need
83 // to move the Node*s to live under our bump ptr allocator.
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000084 for (auto &Callee : Callees)
85 if (Node *ChildN = Callee.dyn_cast<Node *>())
86 Callee = G.moveInto(std::move(*ChildN));
Chandler Carruthbf71a342014-02-06 04:37:03 +000087}
Chandler Carruthbf71a342014-02-06 04:37:03 +000088
89LazyCallGraph::LazyCallGraph(Module &M) : M(M) {
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000090 for (Function &F : M)
91 if (!F.isDeclaration() && !F.hasLocalLinkage())
92 if (EntryNodeSet.insert(&F))
93 EntryNodes.push_back(&F);
Chandler Carruthbf71a342014-02-06 04:37:03 +000094
95 // Now add entry nodes for functions reachable via initializers to globals.
96 SmallVector<Constant *, 16> Worklist;
97 SmallPtrSet<Constant *, 16> Visited;
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +000098 for (GlobalVariable &GV : M.globals())
99 if (GV.hasInitializer())
100 if (Visited.insert(GV.getInitializer()))
101 Worklist.push_back(GV.getInitializer());
Chandler Carruthbf71a342014-02-06 04:37:03 +0000102
103 findCallees(Worklist, Visited, EntryNodes, EntryNodeSet);
104}
105
106LazyCallGraph::LazyCallGraph(const LazyCallGraph &G)
107 : M(G.M), EntryNodeSet(G.EntryNodeSet) {
Chandler Carruthd1ba2ef2014-02-06 05:17:02 +0000108 EntryNodes.reserve(G.EntryNodes.size());
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +0000109 for (const auto &EntryNode : G.EntryNodes)
110 if (Function *Callee = EntryNode.dyn_cast<Function *>())
Chandler Carruthbf71a342014-02-06 04:37:03 +0000111 EntryNodes.push_back(Callee);
112 else
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +0000113 EntryNodes.push_back(copyInto(*EntryNode.get<Node *>()));
Chandler Carruthbf71a342014-02-06 04:37:03 +0000114}
115
Chandler Carruthbf71a342014-02-06 04:37:03 +0000116// FIXME: This would be crazy simpler if BumpPtrAllocator were movable without
117// invalidating any of the allocated memory. We should make that be the case at
118// some point and delete this.
119LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)
120 : M(G.M), EntryNodes(std::move(G.EntryNodes)),
121 EntryNodeSet(std::move(G.EntryNodeSet)) {
Chandler Carruthd1ba2ef2014-02-06 05:17:02 +0000122 // Loop over our EntryNodes. They've been moved from another graph, so we
123 // need to move the Node*s to live under our bump ptr allocator. We can just
124 // do this in-place.
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +0000125 for (auto &Entry : EntryNodes)
126 if (Node *EntryN = Entry.dyn_cast<Node *>())
127 Entry = moveInto(std::move(*EntryN));
Chandler Carruthbf71a342014-02-06 04:37:03 +0000128}
Chandler Carruthbf71a342014-02-06 04:37:03 +0000129
130LazyCallGraph::Node *LazyCallGraph::insertInto(Function &F, Node *&MappedN) {
131 return new (MappedN = BPA.Allocate()) Node(*this, F);
132}
133
134LazyCallGraph::Node *LazyCallGraph::copyInto(const Node &OtherN) {
135 Node *&N = NodeMap[&OtherN.F];
136 if (N)
137 return N;
138
139 return new (N = BPA.Allocate()) Node(*this, OtherN);
140}
141
Chandler Carruthbf71a342014-02-06 04:37:03 +0000142LazyCallGraph::Node *LazyCallGraph::moveInto(Node &&OtherN) {
143 Node *&N = NodeMap[&OtherN.F];
144 if (N)
145 return N;
146
147 return new (N = BPA.Allocate()) Node(*this, std::move(OtherN));
148}
Chandler Carruthbf71a342014-02-06 04:37:03 +0000149
150char LazyCallGraphAnalysis::PassID;
151
152LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
153
154static void printNodes(raw_ostream &OS, LazyCallGraph::Node &N,
155 SmallPtrSetImpl<LazyCallGraph::Node *> &Printed) {
156 // Recurse depth first through the nodes.
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +0000157 for (LazyCallGraph::Node *ChildN : N)
158 if (Printed.insert(ChildN))
159 printNodes(OS, *ChildN, Printed);
Chandler Carruthbf71a342014-02-06 04:37:03 +0000160
161 OS << " Call edges in function: " << N.getFunction().getName() << "\n";
162 for (LazyCallGraph::iterator I = N.begin(), E = N.end(); I != E; ++I)
163 OS << " -> " << I->getFunction().getName() << "\n";
164
165 OS << "\n";
166}
167
Chandler Carruthe9b50612014-03-10 02:14:14 +0000168PreservedAnalyses LazyCallGraphPrinterPass::run(Module *M,
169 ModuleAnalysisManager *AM) {
Chandler Carruthbf71a342014-02-06 04:37:03 +0000170 LazyCallGraph &G = AM->getResult<LazyCallGraphAnalysis>(M);
171
Chandler Carruthe9b50612014-03-10 02:14:14 +0000172 OS << "Printing the call graph for module: " << M->getModuleIdentifier()
173 << "\n\n";
Chandler Carruthbf71a342014-02-06 04:37:03 +0000174
175 SmallPtrSet<LazyCallGraph::Node *, 16> Printed;
Chandler Carruthb9e2f8c2014-03-09 12:20:34 +0000176 for (LazyCallGraph::Node *N : G)
177 if (Printed.insert(N))
178 printNodes(OS, *N, Printed);
Chandler Carruthbf71a342014-02-06 04:37:03 +0000179
180 return PreservedAnalyses::all();
181}