Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -415,6 +415,43 @@ TIdInfo = llvm::make_unique(); TIdInfo->TypeTests.push_back(Guid); } + + friend struct GraphTraits; +}; + +/// GraphTraits definition to build SCC for the index +template <> struct GraphTraits { + typedef FunctionSummary *NodeRef; + + static NodeRef fsumFromEdge(FunctionSummary::EdgeTy &P) { + if (P.first.Ref && P.first.getSummaryList().size()) + return cast(P.first.getSummaryList().front().get()); + static auto ExternalCallee = llvm::make_unique( + FunctionSummary::GVFlags( + GlobalValue::LinkageTypes::AvailableExternallyLinkage, true, false), + 0, FunctionSummary::FFlags{}, std::vector(), + std::vector(), + std::vector(), + std::vector(), + std::vector(), + std::vector(), + std::vector()); + return ExternalCallee.get(); + } + using ChildIteratorType = + mapped_iterator::iterator, + decltype(&fsumFromEdge)>; + + // Use the first callee as the entry node + static NodeRef getEntryNode(FunctionSummary *F) { return F; } + + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->CallGraphEdgeList.begin(), &fsumFromEdge); + } + + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->CallGraphEdgeList.end(), &fsumFromEdge); + } }; template <> struct DenseMapInfo { @@ -566,6 +603,8 @@ /// considered live. bool WithGlobalValueDeadStripping = false; + std::unique_ptr CallGraphRoot; + std::set CfiFunctionDefs; std::set CfiFunctionDecls; @@ -584,6 +623,61 @@ const_gvsummary_iterator end() const { return GlobalValueMap.end(); } size_t size() const { return GlobalValueMap.size(); } + // Lazily get callgraph root + FunctionSummary *getCallGraphRoot() { + // Return already calculated root + if (CallGraphRoot) + return CallGraphRoot.get(); + + // Find callgraph root + std::map FunctionHasParent; + auto isDiscovered = [&FunctionHasParent](FunctionSummary *F) { + return FunctionHasParent.count(F) == 1; + }; + + std::function discoverNodes = + [&](FunctionSummary *F) { + if (!isDiscovered(F)) + // If it's not in the map yet, we've discovered a new node + FunctionHasParent[F] = false; + for (auto I = GraphTraits::child_begin(F); + I != GraphTraits::child_end(F); I++) { + FunctionHasParent[*I] = true; + if (!isDiscovered(*I)) + discoverNodes(*I); + } + }; + + for (auto &S : *this) { + FunctionSummary *FS; + if (!S.second.SummaryList.size() || + !(FS = dyn_cast(S.second.SummaryList.front().get()))) + continue; + discoverNodes(FS); + } + + std::vector Edges; + // create edges to all roots in the Index + for (auto &P : FunctionHasParent) { + if (!P.second) { + ValueInfo V = getOrInsertValueInfo(P.first->getOriginalName()); + assert(V.Ref && V.getSummaryList().size()); + Edges.push_back(std::make_pair(V, CalleeInfo{})); + } + } + assert(Edges.size() && "Couldn't find any roots in index callgraph!"); + CallGraphRoot = llvm::make_unique( + FunctionSummary::GVFlags( + GlobalValue::LinkageTypes::AvailableExternallyLinkage, true, false), + 0, FunctionSummary::FFlags{}, std::vector(), + std::move(Edges), std::vector(), + std::vector(), + std::vector(), + std::vector(), + std::vector()); + return CallGraphRoot.get(); + } + bool withGlobalValueDeadStripping() const { return WithGlobalValueDeadStripping; } @@ -771,6 +865,14 @@ StringMap &ModuleToDefinedGVSummaries) const; }; +template <> +struct GraphTraits + : public GraphTraits { + static NodeRef getEntryNode(ModuleSummaryIndex *I) { + return I->getCallGraphRoot(); + } +}; + } // end namespace llvm #endif // LLVM_IR_MODULESUMMARYINDEX_H