Skip to content

Commit e2a20f2

Browse files
[Prototype] Create Dominator Tree
1 parent 29c5ef3 commit e2a20f2

File tree

1 file changed

+134
-60
lines changed

1 file changed

+134
-60
lines changed

tools/swift-module-summary-test/swift-module-summary-test.cpp

Lines changed: 134 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include "swift/Demangling/Demangle.h"
2121
#include "swift/Serialization/ModuleSummary.h"
2222
#include "llvm/Support/CommandLine.h"
23+
#include "llvm/Support/GenericDomTree.h"
24+
#include "llvm/Support/GenericDomTreeConstruction.h"
2325
#include "llvm/Support/GraphWriter.h"
2426
#include "llvm/Support/MemoryBuffer.h"
2527
#include "llvm/Support/YAMLParser.h"
@@ -32,6 +34,7 @@ enum class ActionType : unsigned {
3234
None,
3335
BinaryToYAML,
3436
YAMLToBinary,
37+
BinaryToDominators,
3538
BinaryToDot,
3639
};
3740

@@ -51,16 +54,19 @@ static llvm::cl::opt<bool>
5154
OmitDeadSymbol("omit-dead-symbol", llvm::cl::init(false),
5255
llvm::cl::desc("Omit dead symbols"));
5356

54-
static llvm::cl::opt<ActionType>
55-
Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
56-
llvm::cl::cat(Category),
57-
llvm::cl::values(
58-
clEnumValN(ActionType::BinaryToYAML, "to-yaml",
59-
"Convert new binary .swiftmodule.summary format to YAML"),
60-
clEnumValN(ActionType::YAMLToBinary, "from-yaml",
61-
"Convert YAML to new binary .swiftmodule.summary format"),
62-
clEnumValN(ActionType::BinaryToDot, "binary-to-dot",
63-
"Convert new binary .swiftmodule.summary format to Dot")));
57+
static llvm::cl::opt<ActionType> Action(
58+
llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
59+
llvm::cl::cat(Category),
60+
llvm::cl::values(
61+
clEnumValN(ActionType::BinaryToYAML, "to-yaml",
62+
"Convert new binary .swiftmodule.summary format to YAML"),
63+
clEnumValN(ActionType::YAMLToBinary, "from-yaml",
64+
"Convert YAML to new binary .swiftmodule.summary format"),
65+
clEnumValN(
66+
ActionType::BinaryToDominators, "binary-to-dom",
67+
"Convert new binary .swiftmodule.summary format to dominator tree"),
68+
clEnumValN(ActionType::BinaryToDot, "binary-to-dot",
69+
"Convert new binary .swiftmodule.summary format to Dot")));
6470

6571
} // namespace options
6672

@@ -190,82 +196,83 @@ struct CallGraph {
190196
struct Edge {
191197
FunctionSummary::Call Call;
192198
GUID Target;
193-
Node *Child;
194199
};
195200

196201
struct Node {
197-
FunctionSummary *FS;
198-
SmallVector<Edge, 8> Children;
199-
Node(FunctionSummary *FS) : FS(FS), Children() {}
200-
};
201-
202-
struct child_iterator
203-
: public std::iterator<std::random_access_iterator_tag, Node *,
204-
ptrdiff_t> {
205-
SmallVectorImpl<Edge>::iterator baseIter;
206-
207-
child_iterator(SmallVectorImpl<Edge>::iterator baseIter) :
208-
baseIter(baseIter)
209-
{ }
210-
211-
child_iterator &operator++() { baseIter++; return *this; }
212-
child_iterator operator++(int) {
213-
auto tmp = *this;
214-
++baseIter;
215-
return tmp;
216-
}
217-
Node *operator*() const { return baseIter->Child; }
218-
bool operator==(const child_iterator &RHS) const {
219-
return baseIter == RHS.baseIter;
220-
}
221-
bool operator!=(const child_iterator &RHS) const {
222-
return baseIter != RHS.baseIter;
223-
}
224-
difference_type operator-(const child_iterator &RHS) const {
225-
return baseIter - RHS.baseIter;
202+
GUID Guid;
203+
CallGraph *Parent;
204+
std::vector<Node *> Children;
205+
std::vector<Node *> PredChildren;
206+
std::vector<Edge> Edges;
207+
208+
CallGraph *getParent() const { return Parent; }
209+
210+
void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
211+
FunctionSummary *FS = Parent->Summary.getFunctionSummary(Guid);
212+
if (!FS) {
213+
OS << "Entry node";
214+
return;
215+
}
216+
OS << "Fn#" << FS->getName();
226217
}
227218
};
228219

220+
using child_iterator = std::vector<Node *>::iterator;
221+
229222
std::vector<Node> Nodes;
223+
Node EntryNode;
224+
ModuleSummaryIndex Summary;
230225
using iterator = std::vector<Node>::iterator;
231-
CallGraph(ModuleSummaryIndex *);
226+
CallGraph(ModuleSummaryIndex);
232227
};
233228

234-
CallGraph::CallGraph(ModuleSummaryIndex *Summary) {
235-
llvm::DenseMap<GUID, Node *> NodeMap;
236-
for (auto FI = Summary->functions_begin(), FE = Summary->functions_end();
229+
CallGraph::CallGraph(ModuleSummaryIndex Summary) : Nodes(), EntryNode() {
230+
std::map<GUID, Node *> NodeMap;
231+
Nodes.resize(Summary.functions_size());
232+
int idx = 0;
233+
for (auto FI = Summary.functions_begin(), FE = Summary.functions_end();
237234
FI != FE; ++FI) {
238-
if (options::OmitDeadSymbol && !FI->second->isLive()) continue;
239-
Nodes.emplace_back(FI->second.get());
240-
Node &node = Nodes.back();
241-
NodeMap[FI->first] = &node;
235+
Node *node = &Nodes[idx++];
236+
node->Guid = FI->first;
237+
node->Parent = this;
238+
NodeMap[FI->first] = node;
239+
if (FI->second->isPreserved()) {
240+
EntryNode.Children.push_back(node);
241+
EntryNode.PredChildren.push_back(node);
242+
}
242243
}
244+
EntryNode.Parent = this;
243245

244246
for (Node &node : Nodes) {
245-
for (FunctionSummary::Call call : node.FS->calls()) {
247+
FunctionSummary *FS = Summary.getFunctionSummary(node.Guid);
248+
for (FunctionSummary::Call call : FS->calls()) {
246249
switch (call.getKind()) {
247250
case FunctionSummary::Call::Witness:
248251
case FunctionSummary::Call::VTable: {
249252
VFuncSlot slot = createVFuncSlot(call);
250-
for (auto Impl : Summary->getImplementations(slot)) {
253+
for (auto Impl : Summary.getImplementations(slot)) {
251254
Node *CalleeNode = NodeMap[Impl.Guid];
252-
node.Children.push_back({ call, Impl.Guid, CalleeNode });
255+
node.Children.push_back(CalleeNode);
256+
node.PredChildren.push_back(CalleeNode);
257+
node.Edges.push_back({call, Impl.Guid});
253258
}
254259
break;
255260
}
256261
case FunctionSummary::Call::Direct: {
257262
Node *CalleeNode = NodeMap[call.getCallee()];
258-
node.Children.push_back({ call, call.getCallee(), CalleeNode });
263+
node.Children.push_back(CalleeNode);
264+
node.PredChildren.push_back(CalleeNode);
265+
node.Edges.push_back({call, call.getCallee()});
259266
break;
260267
}
261268
case FunctionSummary::Call::kindCount:
262269
llvm_unreachable("impossible");
263270
}
264271
}
265272
}
273+
this->Summary = std::move(Summary);
266274
}
267275

268-
269276
namespace llvm {
270277

271278
template <> struct GraphTraits<CallGraph::Node *> {
@@ -281,13 +288,28 @@ namespace llvm {
281288
}
282289
};
283290

291+
template <> struct GraphTraits<Inverse<CallGraph::Node *>> {
292+
using ChildIteratorType = CallGraph::child_iterator;
293+
using Node = CallGraph::Node;
294+
using NodeRef = Node *;
295+
static NodeRef getEntryNode(Inverse<CallGraph::Node *> G) {
296+
return G.Graph;
297+
}
298+
static inline ChildIteratorType child_begin(NodeRef N) {
299+
return N->PredChildren.begin();
300+
}
301+
static inline ChildIteratorType child_end(NodeRef N) {
302+
return N->PredChildren.end();
303+
}
304+
};
305+
284306
template <> struct GraphTraits<CallGraph *>
285307
: public GraphTraits<CallGraph::Node *> {
286308
typedef CallGraph *GraphType;
287309
typedef CallGraph::Node *NodeRef;
288-
289-
static NodeRef getEntryNode(GraphType F) { return nullptr; }
290-
310+
311+
static NodeRef getEntryNode(GraphType G) { return &G->EntryNode; }
312+
291313
typedef pointer_iterator<CallGraph::iterator> nodes_iterator;
292314
static nodes_iterator nodes_begin(GraphType CG) {
293315
return nodes_iterator(CG->Nodes.begin());
@@ -307,24 +329,28 @@ namespace llvm {
307329

308330
std::string getNodeLabel(const CallGraph::Node *Node,
309331
const CallGraph *Graph) {
332+
FunctionSummary *FS = Graph->Summary.getFunctionSummary(Node->Guid);
310333
Demangle::Context DCtx;
311-
return DCtx.demangleSymbolAsString(Node->FS->getName());
334+
return DCtx.demangleSymbolAsString(FS->getName());
312335
}
313336

314337
static std::string getNodeAttributes(const CallGraph::Node *Node,
315338
const CallGraph *Graph) {
316-
std::string color = Node->FS->isLive() ? "green" : "red";
339+
FunctionSummary *FS = Graph->Summary.getFunctionSummary(Node->Guid);
340+
std::string color = FS->isLive() ? "green" : "red";
317341
std::string attrs = "color=\"" + color + "\"";
318342
return attrs;
319343
}
320344

321345
static std::string getEdgeAttributes(const CallGraph::Node *Node,
322346
CallGraph::child_iterator I,
323347
const CallGraph *Graph) {
348+
unsigned ChildIdx = I - Node->Children.begin();
324349
std::string Label;
325350
raw_string_ostream O(Label);
326351
Demangle::Context DCtx;
327-
FunctionSummary::Call call = I.baseIter->Call;
352+
CallGraph::Edge edge = Node->Edges[ChildIdx];
353+
FunctionSummary::Call call = edge.Call;
328354
std::string demangled = DCtx.demangleSymbolAsString(call.getName());
329355
O << "label=\"";
330356
switch (call.getKind()) {
@@ -348,6 +374,47 @@ namespace llvm {
348374
}
349375
};
350376
} // namespace llvm
377+
using DomCallTreeBase = llvm::DominatorTreeBase<CallGraph::Node, false>;
378+
using DomCallInfoNode = llvm::DomTreeNodeBase<CallGraph::Node>;
379+
380+
namespace llvm {
381+
382+
template <> struct GraphTraits<DomCallInfoNode *> {
383+
using ChildIteratorType = DomCallInfoNode::iterator;
384+
using NodeRef = DomCallInfoNode *;
385+
386+
static NodeRef getEntryNode(NodeRef N) { return N; }
387+
static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
388+
static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
389+
};
390+
391+
template <> struct GraphTraits<const DomCallInfoNode *> {
392+
using ChildIteratorType = DomCallInfoNode::const_iterator;
393+
using NodeRef = const DomCallInfoNode *;
394+
395+
static NodeRef getEntryNode(NodeRef N) { return N; }
396+
static inline ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
397+
static inline ChildIteratorType child_end(NodeRef N) { return N->end(); }
398+
};
399+
400+
namespace DomTreeBuilder {
401+
extern template void Calculate<DomCallTreeBase>(DomCallTreeBase &DT);
402+
template void Calculate<DomCallTreeBase>(DomCallTreeBase &DT);
403+
} // namespace DomTreeBuilder
404+
} // namespace llvm
405+
406+
class DomCallTree : public DomCallTreeBase {
407+
using super = DominatorTreeBase;
408+
409+
public:
410+
DomCallTree(CallGraph &CG) : DominatorTreeBase() { recalculate(CG); }
411+
};
412+
413+
int dominance_analysis(CallGraph &CG) {
414+
DomCallTree DT(CG);
415+
DT.print(llvm::dbgs());
416+
return 0;
417+
};
351418

352419
int main(int argc, char *argv[]) {
353420
PROGRAM_START(argc, argv);
@@ -408,13 +475,20 @@ int main(int argc, char *argv[]) {
408475
modulesummary::ModuleSummaryIndex summary;
409476
modulesummary::loadModuleSummaryIndex(fileBufOrErr.get()->getMemBufferRef(),
410477
summary);
411-
CallGraph CG(&summary);
478+
CallGraph CG(std::move(summary));
412479
withOutputFile(diags, options::OutputFilename, [&](raw_ostream &out) {
413480
llvm::WriteGraph(out, &CG);
414481
return false;
415482
});
416483
break;
417484
}
485+
case ActionType::BinaryToDominators: {
486+
modulesummary::ModuleSummaryIndex summary;
487+
modulesummary::loadModuleSummaryIndex(fileBufOrErr.get()->getMemBufferRef(),
488+
summary);
489+
CallGraph CG(std::move(summary));
490+
return dominance_analysis(CG);
491+
}
418492
}
419493
return 0;
420494
}

0 commit comments

Comments
 (0)