Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -42,6 +42,7 @@ namespace yaml { template struct MappingTraits; +struct ModuleSummaryIndexWithModule; } // end namespace yaml @@ -548,6 +549,7 @@ // YAML I/O support. friend yaml::MappingTraits; + friend yaml::MappingTraits; GlobalValueSummaryMapTy::value_type * getOrInsertValuePtr(GlobalValue::GUID GUID) { Index: include/llvm/IR/ModuleSummaryIndexYAML.h =================================================================== --- include/llvm/IR/ModuleSummaryIndexYAML.h +++ include/llvm/IR/ModuleSummaryIndexYAML.h @@ -16,6 +16,19 @@ namespace llvm { namespace yaml { +using NameMapTy = std::map; + +template struct NameMapWrapper { + T *Val; + NameMapTy *NameMap; + + StringRef getNameOrEmpty(GlobalValue::GUID G) { + if (NameMap) + return (*NameMap)[G]; + return StringRef(""); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &io, TypeTestResolution::Kind &value) { io.enumCase(value, "Unsat", TypeTestResolution::Unsat); @@ -26,6 +39,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 +159,30 @@ } }; -struct FunctionSummaryYaml { - unsigned Linkage; +struct RefYaml { + StringRef Name; + GlobalValue::GUID GUID; +}; + +struct CalleeInfoYaml { + StringRef Name; + GlobalValue::GUID GUID; + CalleeInfo::HotnessType Hotness; +}; + +struct GlobalValueSummaryYaml { + StringRef Name; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; bool NotEligibleToImport, Live; + std::vector Refs; +}; + +struct FunctionSummaryYaml { + GlobalValueSummaryYaml GVSum; + unsigned InstCount; + std::vector Calls; + std::vector TypeTests; std::vector TypeTestAssumeVCalls, TypeCheckedLoadVCalls; @@ -137,6 +190,16 @@ TypeCheckedLoadConstVCalls; }; +struct GlobalVarSummaryYaml { + GlobalValueSummaryYaml GVSum; +}; + +struct AliasSummaryYaml { + GlobalValueSummaryYaml GVSum; + GlobalValue::GUID Aliasee; + StringRef AliaseeName; +}; + } // End yaml namespace } // End llvm namespace @@ -168,11 +231,35 @@ namespace llvm { namespace yaml { +template <> struct MappingTraits { + static void mapping(IO &io, RefYaml &summary) { + io.mapOptional("GUID", summary.GUID); + io.addComment(Comment(summary.Name, false)); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, CalleeInfoYaml &summary) { + io.mapOptional("GUID", summary.GUID); + io.addComment(Comment(summary.Name, false)); + io.mapOptional("Hotness", summary.Hotness); + } +}; + +static void mapGlobalValueSummary(IO &io, GlobalValueSummaryYaml &summary) { + io.addComment(Comment(summary.Name)); + io.mapOptional("Kind", summary.Kind); + io.mapOptional("Linkage", summary.Linkage); + io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); + io.mapOptional("Live", summary.Live); + io.mapOptional("Refs", summary.Refs); +} + template <> struct MappingTraits { static void mapping(IO &io, FunctionSummaryYaml& summary) { - io.mapOptional("Linkage", summary.Linkage); - io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); - io.mapOptional("Live", summary.Live); + mapGlobalValueSummary(io, summary.GVSum); + 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,61 +270,175 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &io, GlobalVarSummaryYaml &summary) { + mapGlobalValueSummary(io, summary.GVSum); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, AliasSummaryYaml &summary) { + mapGlobalValueSummary(io, summary.GVSum); + io.mapOptional("Aliasee", summary.Aliasee); + io.addComment(Comment{summary.AliaseeName, false}); + } +}; + } // 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(RefYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVarSummaryYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(AliasSummaryYaml) LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string) namespace llvm { namespace yaml { +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, + NameMapWrapper &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.Val)[std::stoi(Key)]; for (auto &FSum : FSums) { Elem.SummaryList.push_back(llvm::make_unique( GlobalValueSummary::GVFlags( - static_cast(FSum.Linkage), - FSum.NotEligibleToImport, FSum.Live), + static_cast(FSum.GVSum.Linkage), + FSum.GVSum.NotEligibleToImport, FSum.GVSum.Live), 0, ArrayRef{}, ArrayRef{}, std::move(FSum.TypeTests), std::move(FSum.TypeTestAssumeVCalls), std::move(FSum.TypeCheckedLoadVCalls), std::move(FSum.TypeTestAssumeConstVCalls), std::move(FSum.TypeCheckedLoadConstVCalls))); } + + for (auto &GVSum : GVSums) { + Elem.SummaryList.push_back(llvm::make_unique( + GlobalValueSummary::GVFlags( + static_cast(GVSum.GVSum.Linkage), + GVSum.GVSum.NotEligibleToImport, GVSum.GVSum.Live), + ArrayRef{})); + } + + for (auto &ASum : ASums) { + Elem.SummaryList.push_back(llvm::make_unique( + GlobalValueSummary::GVFlags( + static_cast(ASum.GVSum.Linkage), + ASum.GVSum.NotEligibleToImport, ASum.GVSum.Live), + ArrayRef{})); + } } - static void output(IO &io, GlobalValueSummaryMapTy &V) { - for (auto &P : V) { + + static void output(IO &io, NameMapWrapper &V) { + for (auto &P : *V.Val) { std::vector FSums; + std::vector GVSums; + std::vector ASums; for (auto &Sum : P.second.SummaryList) { - if (auto *FSum = dyn_cast(Sum.get())) + std::vector Refs; + for (auto i : Sum->refs()) { + Refs.push_back({V.getNameOrEmpty(i.getGUID()), i.getGUID()}); + } + GlobalValueSummaryYaml GVSumY = { + V.getNameOrEmpty(P.first), + Sum->getSummaryKind(), + static_cast(Sum->flags().Linkage), + static_cast(Sum->flags().NotEligibleToImport), + static_cast(Sum->flags().Live), + Refs}; + + if (auto *FSum = dyn_cast(Sum.get())) { + std::vector Calls; + for (auto edge : FSum->calls()) { + Calls.push_back( + CalleeInfoYaml{V.getNameOrEmpty(edge.first.getGUID()), + edge.first.getGUID(), edge.second.Hotness}); + } FSums.push_back(FunctionSummaryYaml{ - FSum->flags().Linkage, - static_cast(FSum->flags().NotEligibleToImport), - static_cast(FSum->flags().Live), FSum->type_tests(), + GVSumY, 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()}); + } + if (auto *GVSum = dyn_cast(Sum.get())) + GVSums.push_back(GlobalVarSummaryYaml{GVSumY}); + if (auto *ASum = dyn_cast(Sum.get())) + ASums.push_back(AliasSummaryYaml{ + GVSumY, ASum->getAliasee().getOriginalName(), + V.getNameOrEmpty(ASum->getAliasee().getOriginalName())}); } if (!FSums.empty()) - io.mapRequired(llvm::utostr(P.first).c_str(), FSums); + io.mapRequired(utostr(P.first).c_str(), FSums); + if (!GVSums.empty()) + io.mapRequired(utostr(P.first).c_str(), GVSums); + if (!ASums.empty()) + io.mapRequired(utostr(P.first).c_str(), ASums); + } + } +}; + +struct ModuleSummaryIndexWithModule { + ModuleSummaryIndex *Index; + Module *Mod; +}; + +template <> struct MappingTraits { + static void mapping(IO &io, ModuleSummaryIndexWithModule &M) { + NameMapTy NameMap; + if (M.Mod) { + for (GlobalValue &V : M.Mod->global_values()) { + NameMap.insert(std::make_pair(V.getGUID(), V.getName())); + } } + NameMapWrapper N = {&M.Index->GlobalValueMap, + &NameMap}; + io.mapRequired("ModuleSummaryIndex", N); } }; template <> struct MappingTraits { static void mapping(IO &io, ModuleSummaryIndex& index) { - io.mapOptional("GlobalValueMap", index.GlobalValueMap); + NameMapWrapper M = {&index.GlobalValueMap, + nullptr}; + io.addComment(Comment{"Use output for debugging/testing purposes only"}); + io.mapOptional("GlobalValueMap", M); io.mapOptional("TypeIdMap", index.TypeIdMap); io.mapOptional("WithGlobalValueDeadStripping", index.WithGlobalValueDeadStripping); Index: include/llvm/Support/YAMLTraits.h =================================================================== --- include/llvm/Support/YAMLTraits.h +++ include/llvm/Support/YAMLTraits.h @@ -534,6 +534,14 @@ bool, has_MappingTraits::value && !has_MappingValidateTraits::value> {}; +struct Comment { + StringRef Str; + bool NewLine = true; + + Comment(StringRef S) : Str(S){}; + Comment(StringRef S, bool N) : Str(S), NewLine(N){}; +}; + // Base class for Input and Output. class IO { public: @@ -572,6 +580,8 @@ virtual bool bitSetMatch(const char*, bool) = 0; virtual void endBitSetScalar() = 0; + virtual void comment(StringRef &S, bool) = 0; + virtual void scalarString(StringRef &, bool) = 0; virtual void blockScalarString(StringRef &) = 0; @@ -643,6 +653,12 @@ this->processKey(Key, Val, true, Ctx); } + void addComment(Comment C) { + if (outputting() && !C.Str.empty()) { + comment(C.Str, C.NewLine); + } + } + template void mapOptional(const char *Key, T &Val) { EmptyContext Ctx; mapOptionalWithContext(Key, Val, Ctx); @@ -1136,6 +1152,7 @@ bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; + void comment(StringRef &S, bool) override; void scalarString(StringRef &, bool) override; void blockScalarString(StringRef &) override; void setError(const Twine &message) override; @@ -1283,6 +1300,7 @@ bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; + void comment(StringRef &S, bool) override; void scalarString(StringRef &, bool) override; void blockScalarString(StringRef &) override; void setError(const Twine &message) override; Index: lib/Support/YAMLTraits.cpp =================================================================== --- lib/Support/YAMLTraits.cpp +++ lib/Support/YAMLTraits.cpp @@ -315,6 +315,9 @@ } } +// ignore comments +void Input::comment(StringRef &S, bool) {} + void Input::scalarString(StringRef &S, bool) { if (ScalarHNode *SN = dyn_cast(CurrentNode)) { S = SN->value(); @@ -602,6 +605,23 @@ this->outputUpToEndOfLine(" ]"); } +void Output::comment(StringRef &S, bool NewLine) { + if (NewLine) { + this->outputNewLine(); + unsigned Indent = StateStack.size(); + for (unsigned i = 0; i < Indent; i++) + output(" "); + } else + this->output(" "); + + if (S.empty()) { + this->outputUpToEndOfLine("#"); + } else { + this->output("# "); + this->outputUpToEndOfLine(S); + } +} + void Output::scalarString(StringRef &S, bool MustQuote) { this->newLineCheck(); if (S.empty()) { Index: test/tools/llvm-lto2/X86/dump-summary-yaml.ll =================================================================== --- /dev/null +++ test/tools/llvm-lto2/X86/dump-summary-yaml.ll @@ -0,0 +1,46 @@ +; RUN: opt -module-summary %s -o %s.o +; RUN: llvm-lto2 dump-summary %s.o | FileCheck %s +; CHECK: ModuleSummaryIndex: +; CHECK: - Kind: GlobalVar +; CHECK: Linkage: ExternalLinkage +; CHECK: NotEligibleToImport: false +; CHECK: Live: false +; CHECK: - Kind: Function +; CHECK: Linkage: ExternalLinkage +; CHECK: NotEligibleToImport: false +; CHECK: Live: false +; CHECK: InstCount: 2 +; CHECK: Calls: +; CHECK: - GUID: +; CHECK: Hotness: Unknown +; CHECK: - Kind: Alias +; CHECK: Linkage: WeakAnyLinkage +; CHECK: NotEligibleToImport: false +; CHECK: Live: false +; CHECK: Aliasee: +; CHECK: - Kind: Function +; CHECK: Linkage: ExternalLinkage +; CHECK: NotEligibleToImport: false +; CHECK: Live: false +; CHECK: Refs: +; CHECK: - GUID: +; CHECK: InstCount: 2 + + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@X = constant i32 42, section "foo", align 4 +@a = weak alias i32, i32* @X + +define void @f() { + %1 = load i32, i32* @a + ret void +} + +define void @t() { + tail call void @b() + ret void +} + +declare void @b()