diff options
Diffstat (limited to 'lib/ProfileData/InstrProfWriter.cpp')
-rw-r--r-- | lib/ProfileData/InstrProfWriter.cpp | 107 |
1 files changed, 94 insertions, 13 deletions
diff --git a/lib/ProfileData/InstrProfWriter.cpp b/lib/ProfileData/InstrProfWriter.cpp index 18b9deec158f..4ca2defd26da 100644 --- a/lib/ProfileData/InstrProfWriter.cpp +++ b/lib/ProfileData/InstrProfWriter.cpp @@ -1,9 +1,8 @@ //===- InstrProfWriter.cpp - Instrumented profiling writer ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -102,6 +101,7 @@ public: support::endianness ValueProfDataEndianness = support::little; InstrProfSummaryBuilder *SummaryBuilder; + InstrProfSummaryBuilder *CSSummaryBuilder; InstrProfRecordWriterTrait() = default; @@ -143,7 +143,10 @@ public: endian::Writer LE(Out, little); for (const auto &ProfileData : *V) { const InstrProfRecord &ProfRecord = ProfileData.second; - SummaryBuilder->addRecord(ProfRecord); + if (NamedInstrProfRecord::hasCSFlagInHash(ProfileData.first)) + CSSummaryBuilder->addRecord(ProfRecord); + else + SummaryBuilder->addRecord(ProfRecord); LE.write<uint64_t>(ProfileData.first); // Function hash LE.write<uint64_t>(ProfRecord.Counts.size()); @@ -184,6 +187,40 @@ void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight, addRecord(Name, Hash, std::move(I), Weight, Warn); } +void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other, + OverlapStats &Overlap, + OverlapStats &FuncLevelOverlap, + const OverlapFuncFilters &FuncFilter) { + auto Name = Other.Name; + auto Hash = Other.Hash; + Other.accumuateCounts(FuncLevelOverlap.Test); + if (FunctionData.find(Name) == FunctionData.end()) { + Overlap.addOneUnique(FuncLevelOverlap.Test); + return; + } + if (FuncLevelOverlap.Test.CountSum < 1.0f) { + Overlap.Overlap.NumEntries += 1; + return; + } + auto &ProfileDataMap = FunctionData[Name]; + bool NewFunc; + ProfilingData::iterator Where; + std::tie(Where, NewFunc) = + ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord())); + if (NewFunc) { + Overlap.addOneMismatch(FuncLevelOverlap.Test); + return; + } + InstrProfRecord &Dest = Where->second; + + uint64_t ValueCutoff = FuncFilter.ValueCutoff; + if (!FuncFilter.NameFilter.empty() && + Name.find(FuncFilter.NameFilter) != Name.npos) + ValueCutoff = 0; + + Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff); +} + void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I, uint64_t Weight, function_ref<void(Error)> Warn) { @@ -254,6 +291,8 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs); InfoObj->SummaryBuilder = &ISB; + InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs); + InfoObj->CSSummaryBuilder = &CSISB; // Populate the hash table generator. for (const auto &I : FunctionData) @@ -265,6 +304,10 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion; if (ProfileKind == PF_IRLevel) Header.Version |= VARIANT_MASK_IR_PROF; + if (ProfileKind == PF_IRLevelWithCS) { + Header.Version |= VARIANT_MASK_IR_PROF; + Header.Version |= VARIANT_MASK_CSIR_PROF; + } Header.Unused = 0; Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType); Header.HashOffset = 0; @@ -288,6 +331,14 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { uint64_t SummaryOffset = OS.tell(); for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) OS.write(0); + uint64_t CSSummaryOffset = 0; + uint64_t CSSummarySize = 0; + if (ProfileKind == PF_IRLevelWithCS) { + CSSummaryOffset = OS.tell(); + CSSummarySize = SummarySize / sizeof(uint64_t); + for (unsigned I = 0; I < CSSummarySize; I++) + OS.write(0); + } // Write the hash table. uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj); @@ -301,13 +352,25 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { setSummary(TheSummary.get(), *PS); InfoObj->SummaryBuilder = nullptr; + // For Context Sensitive summary. + std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr; + if (ProfileKind == PF_IRLevelWithCS) { + TheCSSummary = IndexedInstrProf::allocSummary(SummarySize); + std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary(); + setSummary(TheCSSummary.get(), *CSPS); + } + InfoObj->CSSummaryBuilder = nullptr; + // Now do the final patch: PatchItem PatchItems[] = { // Patch the Header.HashOffset field. {HashTableStartFieldOffset, &HashTableStart, 1}, // Patch the summary data. {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()), - (int)(SummarySize / sizeof(uint64_t))}}; + (int)(SummarySize / sizeof(uint64_t))}, + {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()), + (int)CSSummarySize}}; + OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems)); } @@ -328,7 +391,7 @@ std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() { } static const char *ValueProfKindStr[] = { -#define VALUE_PROF_KIND(Enumerator, Value) #Enumerator, +#define VALUE_PROF_KIND(Enumerator, Value, Descr) #Enumerator, #include "llvm/ProfileData/InstrProfData.inc" }; @@ -376,15 +439,33 @@ void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash, Error InstrProfWriter::writeText(raw_fd_ostream &OS) { if (ProfileKind == PF_IRLevel) OS << "# IR level Instrumentation Flag\n:ir\n"; + else if (ProfileKind == PF_IRLevelWithCS) + OS << "# CSIR level Instrumentation Flag\n:csir\n"; InstrProfSymtab Symtab; - for (const auto &I : FunctionData) - if (shouldEncodeData(I.getValue())) + + using FuncPair = detail::DenseMapPair<uint64_t, InstrProfRecord>; + using RecordType = std::pair<StringRef, FuncPair>; + SmallVector<RecordType, 4> OrderedFuncData; + + for (const auto &I : FunctionData) { + if (shouldEncodeData(I.getValue())) { if (Error E = Symtab.addFuncName(I.getKey())) return E; - - for (const auto &I : FunctionData) - if (shouldEncodeData(I.getValue())) for (const auto &Func : I.getValue()) - writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS); + OrderedFuncData.push_back(std::make_pair(I.getKey(), Func)); + } + } + + llvm::sort(OrderedFuncData, [](const RecordType &A, const RecordType &B) { + return std::tie(A.first, A.second.first) < + std::tie(B.first, B.second.first); + }); + + for (const auto &record : OrderedFuncData) { + const StringRef &Name = record.first; + const FuncPair &Func = record.second; + writeRecordInText(Name, Func.first, Func.second, Symtab, OS); + } + return Error::success(); } |