diff --git a/llvm/include/llvm/ProfileData/DataAccessProf.h b/llvm/include/llvm/ProfileData/DataAccessProf.h index f410096d83f5e..7065689d544d4 100644 --- a/llvm/include/llvm/ProfileData/DataAccessProf.h +++ b/llvm/include/llvm/ProfileData/DataAccessProf.h @@ -185,6 +185,10 @@ class DataAccessProfData { ArrayRef getKnownColdHashes() const { return KnownColdHashes.getArrayRef(); } + [[nodiscard]] bool empty() const { + return Records.empty() && KnownColdSymbols.empty() && + KnownColdHashes.empty(); + } private: /// Serialize the symbol strings into the output stream. diff --git a/llvm/include/llvm/ProfileData/MemProfYAML.h b/llvm/include/llvm/ProfileData/MemProfYAML.h index ad5d7c0e22751..87e2f0ea14487 100644 --- a/llvm/include/llvm/ProfileData/MemProfYAML.h +++ b/llvm/include/llvm/ProfileData/MemProfYAML.h @@ -263,7 +263,8 @@ template <> struct MappingTraits { template <> struct MappingTraits { static void mapping(IO &Io, memprof::AllMemProfData &Data) { - Io.mapRequired("HeapProfileRecords", Data.HeapProfileRecords); + if (!Io.outputting() || !Data.HeapProfileRecords.empty()) + Io.mapOptional("HeapProfileRecords", Data.HeapProfileRecords); // Map data access profiles if reading input, or if writing output && // the struct is populated. if (!Io.outputting() || !Data.YamlifiedDataAccessProfiles.isEmpty()) diff --git a/llvm/test/tools/llvm-profdata/memprof-yaml.test b/llvm/test/tools/llvm-profdata/memprof-yaml.test index 2e52b796ceedc..18b073c44531b 100644 --- a/llvm/test/tools/llvm-profdata/memprof-yaml.test +++ b/llvm/test/tools/llvm-profdata/memprof-yaml.test @@ -18,6 +18,11 @@ ; RUN: llvm-profdata show --memory %t/memprof-out.indexed > %t/memprof-out-no-dap.yaml ; RUN: diff -b %t/memprof-in-no-dap.yaml %t/memprof-out-no-dap.yaml +; memprof-in-no-heap.yaml has empty heap access profiles. +; RUN: llvm-profdata merge --memprof-version=4 %t/memprof-in-no-heap.yaml -o %t/memprof-out-no-heap.indexed +; RUN: llvm-profdata show --memory %t/memprof-out-no-heap.indexed > %t/memprof-out-no-heap.yaml +; RUN: diff -b %t/memprof-in-no-heap.yaml %t/memprof-out-no-heap.yaml + ;--- memprof-in.yaml --- # MemProfSummary: @@ -151,3 +156,32 @@ HeapProfileRecords: - { Function: 0x8888888888888888, LineOffset: 88, Column: 80, IsInlineFrame: false } CalleeGuids: [ 0x300 ] ... +;--- memprof-in-no-heap.yaml +--- +# MemProfSummary: +# Total contexts: 0 +# Total cold contexts: 0 +# Total hot contexts: 0 +# Maximum cold context total size: 0 +# Maximum warm context total size: 0 +# Maximum hot context total size: 0 +--- +DataAccessProfiles: + SampledRecords: + - Symbol: abcde + AccessCount: 100 + Locations: + - FileName: file2.h + Line: 123 + - FileName: file3.cpp + Line: 456 + - Hash: 101010 + AccessCount: 200 + Locations: + - FileName: file.cpp + Line: 233 + KnownColdSymbols: + - foo + - bar + KnownColdStrHashes: [ 999, 1001 ] +... diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 8fe0887c59774..d658ea99ab1b9 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -760,7 +760,8 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, auto DataAccessProfData = Reader->takeDataAccessProfData(); // Check for the empty input in case the YAML file is invalid. - if (MemProfData.Records.empty()) { + if (MemProfData.Records.empty() && + (!DataAccessProfData || DataAccessProfData->empty())) { WC->Errors.emplace_back( make_error("The profile is empty.", std::error_code()), Filename);