Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -41,6 +41,7 @@ namespace yaml { template struct MappingTraits; +struct ModuleSummaryIndexWithModule; } // end namespace yaml @@ -544,6 +545,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,14 @@ namespace llvm { namespace yaml { +using NameMapTy = std::map; + +template +struct NameMapWrapper { + T *Val; + NameMapTy *NameMap; +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &io, TypeTestResolution::Kind &value) { io.enumCase(value, "Unsat", TypeTestResolution::Unsat); @@ -26,6 +34,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 +154,20 @@ } }; +struct CalleeInfoYaml { + StringRef Name; + GlobalValue::GUID GUID; + CalleeInfo::HotnessType Hotness; +}; + struct FunctionSummaryYaml { - unsigned Linkage; + StringRef Name; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; bool NotEligibleToImport, Live; + unsigned InstCount; + std::vector Calls; + std::vector TypeTests; std::vector TypeTestAssumeVCalls, TypeCheckedLoadVCalls; @@ -137,6 +175,20 @@ TypeCheckedLoadConstVCalls; }; +struct GlobalVarSummaryYaml { + StringRef Name; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; + bool NotEligibleToImport, Live; +}; + +struct AliasSummaryYaml { + StringRef Name; + GlobalValueSummary::SummaryKind Kind; + GlobalValue::LinkageTypes Linkage; + bool NotEligibleToImport, Live; +}; + } // End yaml namespace } // End llvm namespace @@ -168,11 +220,23 @@ namespace llvm { namespace yaml { +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); + } +}; + template <> struct MappingTraits { static void mapping(IO &io, FunctionSummaryYaml& 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("InstCount", summary.InstCount); + io.mapOptional("Calls", summary.Calls); io.mapOptional("TypeTests", summary.TypeTests); io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls); @@ -183,26 +247,76 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &io, GlobalVarSummaryYaml &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); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, AliasSummaryYaml &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); + } +}; + } // 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 { +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( @@ -214,29 +328,108 @@ 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) { - 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())) + if (auto *FSum = dyn_cast(Sum.get())) { + std::vector Calls; + for (auto edge : FSum->calls()) { + Calls.push_back(CalleeInfoYaml{ + (*V.NameMap)[edge.first.getGUID()], + edge.first.getGUID(), edge.second.Hotness}); + } FSums.push_back(FunctionSummaryYaml{ - FSum->flags().Linkage, + (*V.NameMap)[P.first], + 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()}); + } + if (auto *GVSum = dyn_cast(Sum.get())) + GVSums.push_back(GlobalVarSummaryYaml{ + (*V.NameMap)[P.first], + GVSum->getSummaryKind(), + static_cast(GVSum->flags().Linkage), + static_cast(GVSum->flags().NotEligibleToImport), + static_cast(GVSum->flags().Live)}); + if (auto *ASum = dyn_cast(Sum.get())) + ASums.push_back(AliasSummaryYaml{ + (*V.NameMap)[P.first], + ASum->getSummaryKind(), + static_cast(ASum->flags().Linkage), + static_cast(ASum->flags().NotEligibleToImport), + static_cast(ASum->flags().Live)}); } 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 CustomMappingTraits { + static void inputOne(IO &io, StringRef Key, NameMapTy &V) { + // do nothing - this map is only used for output + } + + static void output(IO &io, NameMapTy &V) { + for (auto &P : V) { + io.mapRequired(llvm::utostr(P.first).c_str(), P.second); + } + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, ModuleSummaryIndexWithModule& M) { + NameMapTy NameMap; + if(M.Mod) { + for(Module::global_object_iterator i = M.Mod->global_object_begin(); i != M.Mod->global_object_end(); i++) { + NameMap.insert(std::make_pair(i->getGUID(), i->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.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()) {