Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -533,6 +533,9 @@ // FIXME: Add bitcode read/write support for this field. std::map TypeIdMap; + // Maps Oid GUID to the stringified value name (for dissassembly) + std::map OidToValueName; + /// Mapping from original ID to GUID. If original ID can map to multiple /// GUIDs, it will be mapped to 0. std::map OidGuidMap; @@ -599,6 +602,12 @@ std::move(Summary)); } + // Add an OID to ValueName to the map tracking them for disassembly + void addOidToValueName(GlobalValue::GUID OID, std::string ValueName) { + OidToValueName.insert( + std::pair(OID, ValueName)); + } + /// Add a global value summary for the given ValueInfo. void addGlobalValueSummary(ValueInfo VI, std::unique_ptr Summary) { @@ -638,6 +647,14 @@ return Summary->get(); } + std::string findOidToValueName(const GlobalValue::GUID G) const { + auto s = OidToValueName.find(G); + if (s != OidToValueName.end()) { + return s->second; + } + return ""; + } + /// Returns the first GlobalValueSummary for \p GV, asserting that there /// is only one if \p PerModuleIndex. GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV, Index: include/llvm/IR/ModuleSummaryIndexYAML.h =================================================================== --- include/llvm/IR/ModuleSummaryIndexYAML.h +++ include/llvm/IR/ModuleSummaryIndexYAML.h @@ -26,6 +26,25 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, CalleeInfo::HotnessType &value) { + io.enumCase(value, "Unknown", CalleeInfo::HotnessType::Unknown); + io.enumCase(value, "Cold", CalleeInfo::HotnessType::Cold); + io.enumCase(value, "None", CalleeInfo::HotnessType::None); + io.enumCase(value, "Hot", CalleeInfo::HotnessType::Hot); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, GlobalValueSummary::SummaryKind &value) { + io.enumCase(value, "Alias", GlobalValueSummary::SummaryKind::AliasKind); + io.enumCase(value, "Function", + GlobalValueSummary::SummaryKind::FunctionKind); + io.enumCase(value, "GlobalVar", + GlobalValueSummary::SummaryKind::GlobalVarKind); + } +}; + template <> struct MappingTraits { static void mapping(IO &io, TypeTestResolution &res) { io.mapOptional("Kind", res.TheKind); @@ -127,9 +146,20 @@ } }; +struct CalleeInfoYaml { + std::string Name; + GlobalValue::GUID GUID; + CalleeInfo::HotnessType Hotness; +}; + struct FunctionSummaryYaml { - unsigned Linkage; + GlobalValue::GUID GUID; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; bool NotEligibleToImport, Live; + unsigned InstCount; + std::vector Calls; + std::vector TypeTests; std::vector TypeTestAssumeVCalls, TypeCheckedLoadVCalls; @@ -137,6 +167,21 @@ TypeCheckedLoadConstVCalls; }; +struct GlobalVarSummaryYaml { + GlobalValue::GUID GUID; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; + bool NotEligibleToImport, Live; +}; + +struct AliasSummaryYaml { + GlobalValue::GUID GUID; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; + bool NotEligibleToImport, Live; + std::string Aliasee; +}; + } // End yaml namespace } // End llvm namespace @@ -168,11 +213,23 @@ namespace llvm { namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &io, CalleeInfoYaml &summary) { + io.mapOptional("Name", summary.Name); + io.mapOptional("GUID", summary.GUID); + io.mapOptional("Hotness", summary.Hotness); + } +}; + template <> struct MappingTraits { static void mapping(IO &io, FunctionSummaryYaml& summary) { + io.mapOptional("GUID", summary.GUID); + io.mapOptional("Kind", summary.Kind); io.mapOptional("Linkage", summary.Linkage); io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); io.mapOptional("Live", summary.Live); + io.mapOptional("InstCount", summary.InstCount); + io.mapOptional("Calls", summary.Calls); io.mapOptional("TypeTests", summary.TypeTests); io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls); @@ -183,28 +240,86 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &io, GlobalVarSummaryYaml &summary) { + io.mapOptional("GUID", summary.GUID); + io.mapOptional("Kind", summary.Kind); + io.mapOptional("Linkage", summary.Linkage); + io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); + io.mapOptional("Live", summary.Live); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, AliasSummaryYaml &summary) { + io.mapOptional("GUID", summary.GUID); + io.mapOptional("Kind", summary.Kind); + io.mapOptional("Linkage", summary.Linkage); + io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); + io.mapOptional("Live", summary.Live); + io.mapOptional("Aliasee", summary.Aliasee); + } +}; + } // End yaml namespace } // End llvm namespace LLVM_YAML_IS_STRING_MAP(TypeIdSummary) LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(CalleeInfoYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVarSummaryYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(AliasSummaryYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(std::string) namespace llvm { namespace yaml { +struct NGVMValue { + ModuleSummaryIndex *Index; + GlobalValue::GUID GUID; + GlobalValueSummaryInfo *Summary; +}; +using NamedGlobalValueMap = std::map; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, GlobalValue::LinkageTypes &value) { + io.enumCase(value, "ExternalLinkage", + GlobalValue::LinkageTypes::ExternalLinkage); + io.enumCase(value, "AvailableExternallyLinkage", + GlobalValue::LinkageTypes::AvailableExternallyLinkage); + io.enumCase(value, "LinkOnceAnyLinkage", + GlobalValue::LinkageTypes::LinkOnceAnyLinkage); + io.enumCase(value, "LinkOnceODRLinkage", + GlobalValue::LinkageTypes::LinkOnceODRLinkage); + io.enumCase(value, "WeakAnyLinkage", + GlobalValue::LinkageTypes::WeakAnyLinkage); + io.enumCase(value, "WeakODRLinkage", + GlobalValue::LinkageTypes::WeakODRLinkage); + io.enumCase(value, "AppendingLinkage", + GlobalValue::LinkageTypes::AppendingLinkage); + io.enumCase(value, "InternalLinkage", + GlobalValue::LinkageTypes::InternalLinkage); + io.enumCase(value, "PrivateLinkage", + GlobalValue::LinkageTypes::PrivateLinkage); + io.enumCase(value, "ExternalWeakLinkage", + GlobalValue::LinkageTypes::ExternalWeakLinkage); + io.enumCase(value, "CommonLinkage", + GlobalValue::LinkageTypes::CommonLinkage); + } +}; + // FIXME: Add YAML mappings for the rest of the module summary. -template <> struct CustomMappingTraits { - static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) { +template <> struct CustomMappingTraits { + static void inputOne(IO &io, StringRef Key, NamedGlobalValueMap &V) { std::vector FSums; + std::vector GVSums; + std::vector ASums; io.mapRequired(Key.str().c_str(), FSums); - uint64_t KeyInt; - if (Key.getAsInteger(0, KeyInt)) { - io.setError("key not an integer"); - return; - } - auto &Elem = V[KeyInt]; + io.mapRequired(Key.str().c_str(), GVSums); + io.mapRequired(Key.str().c_str(), ASums); + auto &Elem = V[Key].Summary; for (auto &FSum : FSums) { - Elem.SummaryList.push_back(llvm::make_unique( + Elem->SummaryList.push_back(llvm::make_unique( GlobalValueSummary::GVFlags( static_cast(FSum.Linkage), FSum.NotEligibleToImport, FSum.Live), @@ -214,29 +329,87 @@ std::move(FSum.TypeTestAssumeConstVCalls), std::move(FSum.TypeCheckedLoadConstVCalls))); } + + for (auto &GVSum : GVSums) { + Elem->SummaryList.push_back(llvm::make_unique( + GlobalValueSummary::GVFlags( + static_cast(GVSum.Linkage), + GVSum.NotEligibleToImport, GVSum.Live), + ArrayRef{})); + } + + for (auto &ASum : ASums) { + Elem->SummaryList.push_back(llvm::make_unique( + GlobalValueSummary::GVFlags( + static_cast(ASum.Linkage), + ASum.NotEligibleToImport, ASum.Live), + ArrayRef{})); + } } - static void output(IO &io, GlobalValueSummaryMapTy &V) { + + static void output(IO &io, NamedGlobalValueMap &V) { for (auto &P : V) { std::vector FSums; - for (auto &Sum : P.second.SummaryList) { - if (auto *FSum = dyn_cast(Sum.get())) + std::vector GVSums; + std::vector ASums; + for (auto &Sum : P.second.Summary->SummaryList) { + if (auto *FSum = dyn_cast(Sum.get())) { + std::vector Calls; + for (auto edge : FSum->calls()) { + Calls.push_back( + {P.second.Index->findOidToValueName(edge.first.getGUID()), + edge.first.getGUID(), edge.second.Hotness}); + } FSums.push_back(FunctionSummaryYaml{ - FSum->flags().Linkage, + P.second.GUID, FSum->getSummaryKind(), + static_cast(FSum->flags().Linkage), static_cast(FSum->flags().NotEligibleToImport), - static_cast(FSum->flags().Live), FSum->type_tests(), + static_cast(FSum->flags().Live), + + FSum->instCount(), Calls, FSum->type_tests(), FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), FSum->type_checked_load_const_vcalls()}); + } + } + for (auto &Sum : P.second.Summary->SummaryList) { + if (auto *GVSum = dyn_cast(Sum.get())) + GVSums.push_back(GlobalVarSummaryYaml{ + P.second.GUID, GVSum->getSummaryKind(), + static_cast(GVSum->flags().Linkage), + static_cast(GVSum->flags().NotEligibleToImport), + static_cast(GVSum->flags().Live)}); + } + for (auto &Sum : P.second.Summary->SummaryList) { + if (auto *ASum = dyn_cast(Sum.get())) + ASums.push_back(AliasSummaryYaml{ + P.second.GUID, ASum->getSummaryKind(), + static_cast(ASum->flags().Linkage), + static_cast(ASum->flags().NotEligibleToImport), + static_cast(ASum->flags().Live), + P.second.Index->findOidToValueName( + ASum->getAliasee().getOriginalName())}); } if (!FSums.empty()) - io.mapRequired(llvm::utostr(P.first).c_str(), FSums); + io.mapRequired(P.first.c_str(), FSums); + if (!GVSums.empty()) + io.mapRequired(P.first.c_str(), GVSums); + if (!ASums.empty()) + io.mapRequired(P.first.c_str(), ASums); } } }; template <> struct MappingTraits { static void mapping(IO &io, ModuleSummaryIndex& index) { - io.mapOptional("GlobalValueMap", index.GlobalValueMap); + NamedGlobalValueMap M; + for (gvsummary_iterator i = index.GlobalValueMap.begin(); + i != index.GlobalValueMap.end(); i++) { + std::string name = index.findOidToValueName(i->first); + M.insert(std::pair( + name, NGVMValue{&index, i->first, &i->second})); + } + io.mapOptional("NamedGlobalValueMap", M); io.mapOptional("TypeIdMap", index.TypeIdMap); io.mapOptional("WithGlobalValueDeadStripping", index.WithGlobalValueDeadStripping); Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -4712,6 +4712,7 @@ auto OriginalNameID = ValueGUID; if (GlobalValue::isLocalLinkage(Linkage)) OriginalNameID = GlobalValue::getGUID(ValueName); + TheIndex.addOidToValueName(OriginalNameID, GlobalId); if (PrintSummaryGUIDs) dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is " << ValueName << "\n"; Index: test/tools/llvm-lto2/X86/dump-summary.ll =================================================================== --- /dev/null +++ test/tools/llvm-lto2/X86/dump-summary.ll @@ -0,0 +1,17 @@ +; RUN: opt -module-summary %s -o %t.o +; RUN: llvm-lto2 dump-summary %t.o | egrep 'Kind:\s+GlobalVar' +; RUN: llvm-lto2 dump-summary %t.o | egrep 'Kind:\s+Function' +; RUN: llvm-lto2 dump-summary %t.o | egrep 'Kind:\s+Alias' + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +@G = constant i32 2048, align 4 +@a = weak alias i32, i32* @G + +define void @boop() { + tail call void @afun() + ret void +} + +declare void @afun() +declare void @testtest() Index: tools/llvm-dis/llvm-dis.cpp =================================================================== --- tools/llvm-dis/llvm-dis.cpp +++ tools/llvm-dis/llvm-dis.cpp @@ -152,6 +152,43 @@ return M; } +void printModuleSummaryIndex(raw_ostream &Out, const ModuleSummaryIndex *S) { + Out << "; Module summary:\n"; + for (const_gvsummary_iterator i = S->begin(); i != S->end(); i++) { + ValueInfo V = S->getValueInfo(i->first); + auto L = V.getSummaryList(); + for (auto i = L.begin(); i != L.end(); i++) { + Out << "; " << S->findOidToValueName((*i)->getOriginalName()) << ": "; + switch ((*i)->getSummaryKind()) { + case GlobalValueSummary::SummaryKind::AliasKind: { + AliasSummary *a = cast(i->get()); + Out << "Alias (aliasee " + << S->findOidToValueName(a->getAliasee().getOriginalName()) + << ")\n"; + } break; + case GlobalValueSummary::SummaryKind::FunctionKind: { + Out << "Function"; + FunctionSummary *f = cast(i->get()); + Out << " (" << f->instCount() << " instruction" + << (f->instCount() == 1 ? "" : "s") << ")\n"; + for (FunctionSummary::EdgeTy c : f->calls()) { + Out << "; called by: " << S->findOidToValueName(c.first.getGUID()) + << "\n"; + } + } break; + case GlobalValueSummary::SummaryKind::GlobalVarKind: + Out << "Global Variable\n"; + break; + } + const std::string LinkageTypeStr[] = { + "external", "available external", "link once any", "link once odr", + "weak any", "weak odr", "appending", "internal", + "private", "external weak", "common"}; + Out << "; " << LinkageTypeStr[(*i)->flags().Linkage] << " linkage \n"; + } + } +} + int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); @@ -195,9 +232,14 @@ Annotator.reset(new CommentWriter()); // All that llvm-dis does is write the assembly to a file. - if (!DontPrint) + if (!DontPrint) { M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); + std::unique_ptr MSI = + ExitOnErr(getModuleSummaryIndexForFile(InputFilename)); + printModuleSummaryIndex(Out->os(), MSI.get()); + } + // Declare success. Out->keep(); Index: tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- tools/llvm-lto2/llvm-lto2.cpp +++ tools/llvm-lto2/llvm-lto2.cpp @@ -16,9 +16,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/LTO/Caching.h" +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/ModuleSummaryIndexYAML.h" +#include "llvm/LTO/Caching.h" #include "llvm/LTO/LTO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -132,7 +134,7 @@ } static int usage() { - errs() << "Available subcommands: dump-symtab run\n"; + errs() << "Available subcommands: dump-symtab dump-summary run\n"; return 1; } @@ -351,6 +353,19 @@ return 0; } +static int dumpSummary(int argc, char **argv) { + for (StringRef F : make_range(argv + 1, argv + argc)) { + std::unique_ptr MB = check(MemoryBuffer::getFile(F), F); + std::unique_ptr Index = + check(getModuleSummaryIndex(*MB), F); + + yaml::Output Out(outs()); + Out << *Index; + } + + return 0; +} + int main(int argc, char **argv) { InitializeAllTargets(); InitializeAllTargetMCs(); @@ -368,6 +383,8 @@ argv[1] = argv[0]; if (Subcommand == "dump-symtab") return dumpSymtab(argc - 1, argv + 1); + if (Subcommand == "dump-summary") + return dumpSummary(argc - 1, argv + 1); if (Subcommand == "run") return run(argc - 1, argv + 1); return usage();