diff options
Diffstat (limited to 'contrib/llvm/lib/ProfileData')
-rw-r--r-- | contrib/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 55 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | 74 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp | 35 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/InstrProf.cpp | 174 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/InstrProfReader.cpp | 49 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/InstrProfWriter.cpp | 42 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/SampleProf.cpp | 34 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/SampleProfReader.cpp | 31 | ||||
-rw-r--r-- | contrib/llvm/lib/ProfileData/SampleProfWriter.cpp | 70 |
9 files changed, 416 insertions, 148 deletions
diff --git a/contrib/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/contrib/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 6d907c7098e0..23999a5312c7 100644 --- a/contrib/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/contrib/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -1,4 +1,4 @@ -//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=// +//===- CoverageMapping.cpp - Code coverage mapping support ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,18 +12,32 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/Coverage/CoverageMapping.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <iterator> +#include <memory> +#include <string> +#include <system_error> +#include <utility> +#include <vector> using namespace llvm; using namespace coverage; @@ -59,7 +73,7 @@ void CounterExpressionBuilder::extractTerms( Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { // Gather constant terms. - llvm::SmallVector<std::pair<unsigned, int>, 32> Terms; + SmallVector<std::pair<unsigned, int>, 32> Terms; extractTerms(ExpressionTree, +1, Terms); // If there are no terms, this is just a zero. The algorithm below assumes at @@ -120,8 +134,7 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); } -void CounterMappingContext::dump(const Counter &C, - llvm::raw_ostream &OS) const { +void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const { switch (C.getKind()) { case Counter::Zero: OS << '0'; @@ -145,7 +158,7 @@ void CounterMappingContext::dump(const Counter &C, return; Expected<int64_t> Value = evaluate(C); if (auto E = Value.takeError()) { - llvm::consumeError(std::move(E)); + consumeError(std::move(E)); return; } OS << '[' << *Value << ']'; @@ -217,7 +230,7 @@ Error CoverageMapping::loadFunctionRecord( for (const auto &Region : Record.MappingRegions) { Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); if (auto E = ExecutionCount.takeError()) { - llvm::consumeError(std::move(E)); + consumeError(std::move(E)); return Error::success(); } Function.pushRegion(Region, *ExecutionCount); @@ -281,6 +294,7 @@ CoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, } namespace { + /// \brief Distributes functions into instantiation sets. /// /// An instantiation set is a collection of functions that have the same source @@ -326,7 +340,7 @@ class SegmentBuilder { Segments.pop_back(); DEBUG(dbgs() << "Segment at " << Line << ":" << Col); // Set this region's count. - if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { + if (Region.Kind != CounterMappingRegion::SkippedRegion) { DEBUG(dbgs() << " with count " << Region.ExecutionCount); Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry); } else @@ -380,10 +394,10 @@ class SegmentBuilder { // in combineRegions(). Because we accumulate counter values only from // regions of the same kind as the first region of the area, prefer // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. - static_assert(coverage::CounterMappingRegion::CodeRegion < - coverage::CounterMappingRegion::ExpansionRegion && - coverage::CounterMappingRegion::ExpansionRegion < - coverage::CounterMappingRegion::SkippedRegion, + static_assert(CounterMappingRegion::CodeRegion < + CounterMappingRegion::ExpansionRegion && + CounterMappingRegion::ExpansionRegion < + CounterMappingRegion::SkippedRegion, "Unexpected order of region kind values"); return LHS.Kind < RHS.Kind; }); @@ -437,7 +451,8 @@ public: return Segments; } }; -} + +} // end anonymous namespace std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { std::vector<StringRef> Filenames; @@ -487,7 +502,7 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) { CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { CoverageData FileCoverage(Filename); - std::vector<coverage::CountedRegion> Regions; + std::vector<CountedRegion> Regions; for (const auto &Function : Functions) { auto MainFileID = findMainViewFileID(Filename, Function); @@ -533,7 +548,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const { return CoverageData(); CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); - std::vector<coverage::CountedRegion> Regions; + std::vector<CountedRegion> Regions; for (const auto &CR : Function.CountedRegions) if (CR.FileID == *MainFileID) { Regions.push_back(CR); @@ -551,7 +566,7 @@ CoverageData CoverageMapping::getCoverageForExpansion( const ExpansionRecord &Expansion) const { CoverageData ExpansionCoverage( Expansion.Function.Filenames[Expansion.FileID]); - std::vector<coverage::CountedRegion> Regions; + std::vector<CountedRegion> Regions; for (const auto &CR : Expansion.Function.CountedRegions) if (CR.FileID == Expansion.FileID) { Regions.push_back(CR); @@ -566,8 +581,7 @@ CoverageData CoverageMapping::getCoverageForExpansion( return ExpansionCoverage; } -namespace { -std::string getCoverageMapErrString(coveragemap_error Err) { +static std::string getCoverageMapErrString(coveragemap_error Err) { switch (Err) { case coveragemap_error::success: return "Success"; @@ -585,6 +599,8 @@ std::string getCoverageMapErrString(coveragemap_error Err) { llvm_unreachable("A value of coveragemap_error has no message."); } +namespace { + // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. @@ -594,6 +610,7 @@ class CoverageMappingErrorCategoryType : public std::error_category { return getCoverageMapErrString(static_cast<coveragemap_error>(IE)); } }; + } // end anonymous namespace std::string CoverageMapError::message() const { diff --git a/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index a6c7031ccd3d..a34f359cd542 100644 --- a/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -1,4 +1,4 @@ -//=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// +//===- CoverageMappingReader.cpp - Code coverage mapping reader -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,14 +13,34 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/Error.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <memory> +#include <utility> +#include <vector> using namespace llvm; using namespace coverage; @@ -226,9 +246,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( } Error RawCoverageMappingReader::read() { - // Read the virtual file mapping. - llvm::SmallVector<unsigned, 8> VirtualFileMapping; + SmallVector<unsigned, 8> VirtualFileMapping; uint64_t NumFileMappings; if (auto Err = readSize(NumFileMappings)) return Err; @@ -349,7 +368,10 @@ static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { } namespace { + struct CovMapFuncRecordReader { + virtual ~CovMapFuncRecordReader() = default; + // The interface to read coverage mapping function records for a module. // // \p Buf points to the buffer containing the \c CovHeader of the coverage @@ -359,26 +381,24 @@ struct CovMapFuncRecordReader { // greater than \p End if not. virtual Expected<const char *> readFunctionRecords(const char *Buf, const char *End) = 0; - virtual ~CovMapFuncRecordReader() {} + template <class IntPtrT, support::endianness Endian> static Expected<std::unique_ptr<CovMapFuncRecordReader>> - get(coverage::CovMapVersion Version, InstrProfSymtab &P, + get(CovMapVersion Version, InstrProfSymtab &P, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<StringRef> &F); }; // A class for reading coverage mapping function records for a module. -template <coverage::CovMapVersion Version, class IntPtrT, - support::endianness Endian> +template <CovMapVersion Version, class IntPtrT, support::endianness Endian> class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { - typedef typename coverage::CovMapTraits< + typedef typename CovMapTraits< Version, IntPtrT>::CovMapFuncRecordType FuncRecordType; - typedef typename coverage::CovMapTraits<Version, IntPtrT>::NameRefType - NameRefType; + typedef typename CovMapTraits<Version, IntPtrT>::NameRefType NameRefType; // Maps function's name references to the indexes of their records // in \c Records. - llvm::DenseMap<NameRefType, size_t> FunctionRecords; + DenseMap<NameRefType, size_t> FunctionRecords; InstrProfSymtab &ProfileNames; std::vector<StringRef> &Filenames; std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; @@ -432,14 +452,16 @@ public: std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<StringRef> &F) : ProfileNames(P), Filenames(F), Records(R) {} - ~VersionedCovMapFuncRecordReader() override {} + + ~VersionedCovMapFuncRecordReader() override = default; Expected<const char *> readFunctionRecords(const char *Buf, const char *End) override { using namespace support; + if (Buf + sizeof(CovMapHeader) > End) return make_error<CoverageMapError>(coveragemap_error::malformed); - auto CovHeader = reinterpret_cast<const coverage::CovMapHeader *>(Buf); + auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf); uint32_t NRecords = CovHeader->getNRecords<Endian>(); uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); @@ -490,14 +512,16 @@ public: return Buf; } }; + } // end anonymous namespace template <class IntPtrT, support::endianness Endian> Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( - coverage::CovMapVersion Version, InstrProfSymtab &P, + CovMapVersion Version, InstrProfSymtab &P, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, std::vector<StringRef> &F) { using namespace coverage; + switch (Version) { case CovMapVersion::Version1: return llvm::make_unique<VersionedCovMapFuncRecordReader< @@ -518,11 +542,12 @@ static Error readCoverageMappingData( std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, std::vector<StringRef> &Filenames) { using namespace coverage; + // Read the records in the coverage data section. auto CovHeader = - reinterpret_cast<const coverage::CovMapHeader *>(Data.data()); + reinterpret_cast<const CovMapHeader *>(Data.data()); CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); - if (Version > coverage::CovMapVersion::CurrentVersion) + if (Version > CovMapVersion::CurrentVersion) return make_error<CoverageMapError>(coveragemap_error::unsupported_version); Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, @@ -538,6 +563,7 @@ static Error readCoverageMappingData( } return Error::success(); } + static const char *TestingFormatMagic = "llvmcovmtestdata"; static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, @@ -595,21 +621,21 @@ static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian, StringRef Arch) { - auto BinOrErr = object::createBinary(ObjectBuffer); + auto BinOrErr = createBinary(ObjectBuffer); if (!BinOrErr) return BinOrErr.takeError(); auto Bin = std::move(BinOrErr.get()); std::unique_ptr<ObjectFile> OF; - if (auto *Universal = dyn_cast<object::MachOUniversalBinary>(Bin.get())) { + if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { // If we have a universal binary, try to look up the object for the // appropriate architecture. auto ObjectFileOrErr = Universal->getObjectForArch(Arch); if (!ObjectFileOrErr) return ObjectFileOrErr.takeError(); OF = std::move(ObjectFileOrErr.get()); - } else if (isa<object::ObjectFile>(Bin.get())) { + } else if (isa<ObjectFile>(Bin.get())) { // For any other object file, upcast and take ownership. - OF.reset(cast<object::ObjectFile>(Bin.release())); + OF.reset(cast<ObjectFile>(Bin.release())); // If we've asked for a particular arch, make sure they match. if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) return errorCodeToError(object_error::arch_not_found); @@ -623,11 +649,15 @@ static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, : support::endianness::big; // Look for the sections that we are interested in. - auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName(false)); + auto ObjFormat = OF->getTripleObjectFormat(); + auto NamesSection = + lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, + /*AddSegmentInfo=*/false)); if (auto E = NamesSection.takeError()) return E; auto CoverageSection = - lookupSection(*OF, getInstrProfCoverageSectionName(false)); + lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, + /*AddSegmentInfo=*/false)); if (auto E = CoverageSection.takeError()) return E; diff --git a/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp index 82356333b937..f131be2cba49 100644 --- a/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp +++ b/contrib/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp @@ -1,4 +1,4 @@ -//=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=// +//===- CoverageMappingWriter.cpp - Code coverage mapping writer -----------===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <limits> +#include <vector> using namespace llvm; using namespace coverage; @@ -27,14 +34,25 @@ void CoverageFilenamesSectionWriter::write(raw_ostream &OS) { } namespace { + /// \brief Gather only the expressions that are used by the mapping /// regions in this function. class CounterExpressionsMinimizer { ArrayRef<CounterExpression> Expressions; - llvm::SmallVector<CounterExpression, 16> UsedExpressions; + SmallVector<CounterExpression, 16> UsedExpressions; std::vector<unsigned> AdjustedExpressionIDs; public: + CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions, + ArrayRef<CounterMappingRegion> MappingRegions) + : Expressions(Expressions) { + AdjustedExpressionIDs.resize(Expressions.size(), 0); + for (const auto &I : MappingRegions) + mark(I.Count); + for (const auto &I : MappingRegions) + gatherUsed(I.Count); + } + void mark(Counter C) { if (!C.isExpression()) return; @@ -54,16 +72,6 @@ public: gatherUsed(E.RHS); } - CounterExpressionsMinimizer(ArrayRef<CounterExpression> Expressions, - ArrayRef<CounterMappingRegion> MappingRegions) - : Expressions(Expressions) { - AdjustedExpressionIDs.resize(Expressions.size(), 0); - for (const auto &I : MappingRegions) - mark(I.Count); - for (const auto &I : MappingRegions) - gatherUsed(I.Count); - } - ArrayRef<CounterExpression> getExpressions() const { return UsedExpressions; } /// \brief Adjust the given counter to correctly transition from the old @@ -74,7 +82,8 @@ public: return C; } }; -} + +} // end anonymous namespace /// \brief Encode the counter. /// diff --git a/contrib/llvm/lib/ProfileData/InstrProf.cpp b/contrib/llvm/lib/ProfileData/InstrProf.cpp index 74acd9e5e207..64a65ccc11a1 100644 --- a/contrib/llvm/lib/ProfileData/InstrProf.cpp +++ b/contrib/llvm/lib/ProfileData/InstrProf.cpp @@ -1,4 +1,4 @@ -//=-- InstrProf.cpp - Instrumented profiling format support -----------------=// +//===- InstrProf.cpp - Instrumented profiling format support --------------===// // // The LLVM Compiler Infrastructure // @@ -12,29 +12,68 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SwapByteOrder.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <cstdint> +#include <memory> +#include <string> +#include <system_error> +#include <utility> +#include <vector> using namespace llvm; static cl::opt<bool> StaticFuncFullModulePrefix( - "static-func-full-module-prefix", cl::init(false), + "static-func-full-module-prefix", cl::init(true), cl::desc("Use full module build paths in the profile counter names for " "static functions.")); -namespace { -std::string getInstrProfErrString(instrprof_error Err) { +// This option is tailored to users that have different top-level directory in +// profile-gen and profile-use compilation. Users need to specific the number +// of levels to strip. A value larger than the number of directories in the +// source file will strip all the directory names and only leave the basename. +// +// Note current ThinLTO module importing for the indirect-calls assumes +// the source directory name not being stripped. A non-zero option value here +// can potentially prevent some inter-module indirect-call-promotions. +static cl::opt<unsigned> StaticFuncStripDirNamePrefix( + "static-func-strip-dirname-prefix", cl::init(0), + cl::desc("Strip specified level of directory name from source path in " + "the profile counter name for static functions.")); + +static std::string getInstrProfErrString(instrprof_error Err) { switch (Err) { case instrprof_error::success: return "Success"; @@ -76,15 +115,19 @@ std::string getInstrProfErrString(instrprof_error Err) { llvm_unreachable("A value of instrprof_error has no message."); } +namespace { + // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class InstrProfErrorCategoryType : public std::error_category { const char *name() const noexcept override { return "llvm.instrprof"; } + std::string message(int IE) const override { return getInstrProfErrString(static_cast<instrprof_error>(IE)); } }; + } // end anonymous namespace static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory; @@ -93,8 +136,49 @@ const std::error_category &llvm::instrprof_category() { return *ErrorCategory; } +namespace { + +const char *InstrProfSectNameCommon[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ + SectNameCommon, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectNameCoff[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ + SectNameCoff, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +const char *InstrProfSectNamePrefix[] = { +#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ + Prefix, +#include "llvm/ProfileData/InstrProfData.inc" +}; + +} // namespace + namespace llvm { +std::string getInstrProfSectionName(InstrProfSectKind IPSK, + Triple::ObjectFormatType OF, + bool AddSegmentInfo) { + std::string SectName; + + if (OF == Triple::MachO && AddSegmentInfo) + SectName = InstrProfSectNamePrefix[IPSK]; + + if (OF == Triple::COFF) + SectName += InstrProfSectNameCoff[IPSK]; + else + SectName += InstrProfSectNameCommon[IPSK]; + + if (OF == Triple::MachO && IPSK == IPSK_data && AddSegmentInfo) + SectName += ",regular,live_support"; + + return SectName; +} + void SoftInstrProfErrors::addError(instrprof_error IE) { if (IE == instrprof_error::success) return; @@ -133,6 +217,24 @@ std::string getPGOFuncName(StringRef RawFuncName, return GlobalValue::getGlobalIdentifier(RawFuncName, Linkage, FileName); } +// Strip NumPrefix level of directory name from PathNameStr. If the number of +// directory separators is less than NumPrefix, strip all the directories and +// leave base file name only. +static StringRef stripDirPrefix(StringRef PathNameStr, uint32_t NumPrefix) { + uint32_t Count = NumPrefix; + uint32_t Pos = 0, LastPos = 0; + for (auto & CI : PathNameStr) { + ++Pos; + if (llvm::sys::path::is_separator(CI)) { + LastPos = Pos; + --Count; + } + if (Count == 0) + break; + } + return PathNameStr.substr(LastPos); +} + // Return the PGOFuncName. This function has some special handling when called // in LTO optimization. The following only applies when calling in LTO passes // (when \c InLTO is true): LTO's internalization privatizes many global linkage @@ -151,6 +253,8 @@ std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) { StringRef FileName = (StaticFuncFullModulePrefix ? F.getParent()->getName() : sys::path::filename(F.getParent()->getName())); + if (StaticFuncFullModulePrefix && StaticFuncStripDirNamePrefix != 0) + FileName = stripDirPrefix(FileName, StaticFuncStripDirNamePrefix); return getPGOFuncName(F.getName(), F.getLinkage(), FileName, Version); } @@ -198,7 +302,6 @@ std::string getPGOFuncNameVarName(StringRef FuncName, GlobalVariable *createPGOFuncNameVar(Module &M, GlobalValue::LinkageTypes Linkage, StringRef PGOFuncName) { - // We generally want to match the function's linkage, but available_externally // and extern_weak both have the wrong semantics, and anything that doesn't // need to link across compilation units doesn't need to be visible at all. @@ -236,6 +339,17 @@ void InstrProfSymtab::create(Module &M, bool InLTO) { const std::string &PGOFuncName = getPGOFuncName(F, InLTO); addFuncName(PGOFuncName); MD5FuncMap.emplace_back(Function::getGUID(PGOFuncName), &F); + // In ThinLTO, local function may have been promoted to global and have + // suffix added to the function name. We need to add the stripped function + // name to the symbol table so that we can find a match from profile. + if (InLTO) { + auto pos = PGOFuncName.find('.'); + if (pos != std::string::npos) { + const std::string &OtherFuncName = PGOFuncName.substr(0, pos); + addFuncName(OtherFuncName); + MD5FuncMap.emplace_back(Function::getGUID(OtherFuncName), &F); + } + } } finalizeSymtab(); @@ -243,7 +357,7 @@ void InstrProfSymtab::create(Module &M, bool InLTO) { Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs, bool doCompression, std::string &Result) { - assert(NameStrs.size() && "No name data to emit"); + assert(!NameStrs.empty() && "No name data to emit"); uint8_t Header[16], *P = Header; std::string UncompressedNameStrings = @@ -271,12 +385,12 @@ Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs, } SmallString<128> CompressedNameStrings; - zlib::Status Success = - zlib::compress(StringRef(UncompressedNameStrings), CompressedNameStrings, - zlib::BestSizeCompression); - - if (Success != zlib::StatusOK) + Error E = zlib::compress(StringRef(UncompressedNameStrings), + CompressedNameStrings, zlib::BestSizeCompression); + if (E) { + consumeError(std::move(E)); return make_error<InstrProfError>(instrprof_error::compress_failed); + } return WriteStringToResult(CompressedNameStrings.size(), CompressedNameStrings); @@ -315,9 +429,12 @@ Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) { if (isCompressed) { StringRef CompressedNameStrings(reinterpret_cast<const char *>(P), CompressedSize); - if (zlib::uncompress(CompressedNameStrings, UncompressedNameStrings, - UncompressedSize) != zlib::StatusOK) + if (Error E = + zlib::uncompress(CompressedNameStrings, UncompressedNameStrings, + UncompressedSize)) { + consumeError(std::move(E)); return make_error<InstrProfError>(instrprof_error::uncompress_failed); + } P += CompressedSize; NameStrings = StringRef(UncompressedNameStrings.data(), UncompressedNameStrings.size()); @@ -553,6 +670,7 @@ void ValueProfRecord::deserializeTo(InstrProfRecord &Record, void ValueProfRecord::swapBytes(support::endianness Old, support::endianness New) { using namespace support; + if (Old == New) return; @@ -589,6 +707,7 @@ void ValueProfData::deserializeTo(InstrProfRecord &Record, template <class T> static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) { using namespace support; + if (Orig == little) return endian::readNext<T, little, unaligned>(D); else @@ -623,6 +742,7 @@ ValueProfData::getValueProfData(const unsigned char *D, const unsigned char *const BufferEnd, support::endianness Endianness) { using namespace support; + if (D + sizeof(ValueProfData) > BufferEnd) return make_error<InstrProfError>(instrprof_error::truncated); @@ -645,6 +765,7 @@ ValueProfData::getValueProfData(const unsigned char *D, void ValueProfData::swapBytesToHost(support::endianness Endianness) { using namespace support; + if (Endianness == getHostEndianness()) return; @@ -660,6 +781,7 @@ void ValueProfData::swapBytesToHost(support::endianness Endianness) { void ValueProfData::swapBytesFromHost(support::endianness Endianness) { using namespace support; + if (Endianness == getHostEndianness()) return; @@ -791,7 +913,7 @@ bool needsComdatForCounter(const Function &F, const Module &M) { return true; Triple TT(M.getTargetTriple()); - if (!TT.isOSBinFormatELF()) + if (!TT.isOSBinFormatELF() && !TT.isOSBinFormatWasm()) return false; // See createPGOFuncNameVar for more details. To avoid link errors, profile @@ -854,4 +976,26 @@ bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken) { } return true; } + +// Parse the value profile options. +void getMemOPSizeRangeFromOption(std::string MemOPSizeRange, + int64_t &RangeStart, int64_t &RangeLast) { + static const int64_t DefaultMemOPSizeRangeStart = 0; + static const int64_t DefaultMemOPSizeRangeLast = 8; + RangeStart = DefaultMemOPSizeRangeStart; + RangeLast = DefaultMemOPSizeRangeLast; + + if (!MemOPSizeRange.empty()) { + auto Pos = MemOPSizeRange.find(":"); + if (Pos != std::string::npos) { + if (Pos > 0) + RangeStart = atoi(MemOPSizeRange.substr(0, Pos).c_str()); + if (Pos < MemOPSizeRange.size() - 1) + RangeLast = atoi(MemOPSizeRange.substr(Pos + 1).c_str()); + } else + RangeLast = atoi(MemOPSizeRange.c_str()); + } + assert(RangeLast >= RangeStart); +} + } // end namespace llvm diff --git a/contrib/llvm/lib/ProfileData/InstrProfReader.cpp b/contrib/llvm/lib/ProfileData/InstrProfReader.cpp index ad407f07957f..856f793363f7 100644 --- a/contrib/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/contrib/llvm/lib/ProfileData/InstrProfReader.cpp @@ -1,4 +1,4 @@ -//=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=// +//===- InstrProfReader.cpp - Instrumented profiling reader ----------------===// // // The LLVM Compiler Infrastructure // @@ -12,9 +12,27 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include <cassert> +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/ProfileSummary.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SwapByteOrder.h" +#include <algorithm> +#include <cctype> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <memory> +#include <system_error> +#include <utility> +#include <vector> using namespace llvm; @@ -78,7 +96,6 @@ IndexedInstrProfReader::create(const Twine &Path) { return IndexedInstrProfReader::create(std::move(BufferOrError.get())); } - Expected<std::unique_ptr<IndexedInstrProfReader>> IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { // Sanity check the buffer. @@ -182,7 +199,7 @@ TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { CHECK_LINE_END(Line); std::pair<StringRef, StringRef> VD = Line->rsplit(':'); uint64_t TakenCount, Value; - if (VK == IPVK_IndirectCallTarget) { + if (ValueKind == IPVK_IndirectCallTarget) { Symtab->addFuncName(VD.first); Value = IndexedInstrProf::ComputeHash(VD.first); } else { @@ -192,7 +209,8 @@ TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { CurrentValues.push_back({Value, TakenCount}); Line++; } - Record.addValueData(VK, S, CurrentValues.data(), NumValueData, nullptr); + Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData, + nullptr); } } return success(); @@ -232,7 +250,7 @@ Error TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { return error(instrprof_error::malformed); // Read each counter and fill our internal storage with the values. - Record.Counts.clear(); + Record.Clear(); Record.Counts.reserve(NumCounters); for (uint64_t I = 0; I < NumCounters; ++I) { if (Line.is_at_end()) @@ -398,7 +416,6 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts( template <class IntPtrT> Error RawInstrProfReader<IntPtrT>::readValueProfilingData( InstrProfRecord &Record) { - Record.clearValueData(); CurValueDataSize = 0; // Need to match the logic in value profile dumper code in compiler-rt: @@ -454,9 +471,11 @@ Error RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) { } namespace llvm { + template class RawInstrProfReader<uint32_t>; template class RawInstrProfReader<uint64_t>; -} + +} // end namespace llvm InstrProfLookupTrait::hash_value_type InstrProfLookupTrait::ComputeHash(StringRef K) { @@ -482,6 +501,8 @@ bool InstrProfLookupTrait::readValueProfilingData( data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, offset_type N) { + using namespace support; + // Check if the data is corrupt. If so, don't try to read it. if (N % sizeof(uint64_t)) return data_type(); @@ -489,7 +510,6 @@ data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, DataBuffer.clear(); std::vector<uint64_t> CounterBuffer; - using namespace support; const unsigned char *End = D + N; while (D < End) { // Read hash. @@ -567,9 +587,10 @@ InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( } bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { + using namespace support; + if (DataBuffer.getBufferSize() < 8) return false; - using namespace support; uint64_t Magic = endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); // Verify that it's magical. @@ -581,6 +602,7 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, const unsigned char *Cur) { using namespace IndexedInstrProf; using namespace support; + if (Version >= IndexedInstrProf::Version4) { const IndexedInstrProf::Summary *SummaryInLE = reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); @@ -617,6 +639,7 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, } else { // For older version of profile data, we need to compute on the fly: using namespace IndexedInstrProf; + InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); // FIXME: This only computes an empty summary. Need to call addRecord for // all InstrProfRecords to get the correct summary. @@ -626,14 +649,14 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, } Error IndexedInstrProfReader::readHeader() { + using namespace support; + const unsigned char *Start = (const unsigned char *)DataBuffer->getBufferStart(); const unsigned char *Cur = Start; if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) return error(instrprof_error::truncated); - using namespace support; - auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); Cur += sizeof(IndexedInstrProf::Header); diff --git a/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp b/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp index 029d75660a73..6b7bd3b2fc0a 100644 --- a/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/contrib/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -1,4 +1,4 @@ -//=-- InstrProfWriter.cpp - Instrumented profiling writer -------------------=// +//===- InstrProfWriter.cpp - Instrumented profiling writer ----------------===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/InstrProfWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/ProfileSummary.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/InstrProfWriter.h" #include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cstdint> +#include <memory> #include <string> #include <tuple> #include <utility> @@ -41,10 +47,9 @@ namespace llvm { // A wrapper class to abstract writer stream with support of bytes // back patching. class ProfOStream { - public: - ProfOStream(llvm::raw_fd_ostream &FD) : IsFDOStream(true), OS(FD), LE(FD) {} - ProfOStream(llvm::raw_string_ostream &STR) + ProfOStream(raw_fd_ostream &FD) : IsFDOStream(true), OS(FD), LE(FD) {} + ProfOStream(raw_string_ostream &STR) : IsFDOStream(false), OS(STR), LE(STR) {} uint64_t tell() { return OS.tell(); } @@ -55,15 +60,16 @@ public: // directly and it won't be reflected in the stream's internal buffer. void patch(PatchItem *P, int NItems) { using namespace support; + if (IsFDOStream) { - llvm::raw_fd_ostream &FDOStream = static_cast<llvm::raw_fd_ostream &>(OS); + raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS); for (int K = 0; K < NItems; K++) { FDOStream.seek(P[K].Pos); for (int I = 0; I < P[K].N; I++) write(P[K].D[I]); } } else { - llvm::raw_string_ostream &SOStream = + raw_string_ostream &SOStream = static_cast<llvm::raw_string_ostream &>(OS); std::string &Data = SOStream.str(); // with flush for (int K = 0; K < NItems; K++) { @@ -94,17 +100,19 @@ public: typedef uint64_t hash_value_type; typedef uint64_t offset_type; - support::endianness ValueProfDataEndianness; + support::endianness ValueProfDataEndianness = support::little; InstrProfSummaryBuilder *SummaryBuilder; - InstrProfRecordWriterTrait() : ValueProfDataEndianness(support::little) {} + InstrProfRecordWriterTrait() = default; + static hash_value_type ComputeHash(key_type_ref K) { return IndexedInstrProf::ComputeHash(K); } static std::pair<offset_type, offset_type> EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V) { - using namespace llvm::support; + using namespace support; + endian::Writer<little> LE(Out); offset_type N = K.size(); @@ -130,7 +138,8 @@ public: } void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type) { - using namespace llvm::support; + using namespace support; + endian::Writer<little> LE(Out); for (const auto &ProfileData : *V) { const InstrProfRecord &ProfRecord = ProfileData.second; @@ -154,8 +163,7 @@ public: } // end namespace llvm InstrProfWriter::InstrProfWriter(bool Sparse) - : Sparse(Sparse), FunctionData(), ProfileKind(PF_Unknown), - InfoObj(new InstrProfRecordWriterTrait()) {} + : Sparse(Sparse), InfoObj(new InstrProfRecordWriterTrait()) {} InstrProfWriter::~InstrProfWriter() { delete InfoObj; } @@ -208,7 +216,7 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) { return true; for (const auto &Func : PD) { const InstrProfRecord &IPR = Func.second; - if (any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; })) + if (llvm::any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; })) return true; } return false; @@ -217,6 +225,7 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) { static void setSummary(IndexedInstrProf::Summary *TheSummary, ProfileSummary &PS) { using namespace IndexedInstrProf; + std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary(); TheSummary->NumSummaryFields = Summary::NumKinds; TheSummary->NumCutoffEntries = Res.size(); @@ -231,9 +240,10 @@ static void setSummary(IndexedInstrProf::Summary *TheSummary, } void InstrProfWriter::writeImpl(ProfOStream &OS) { + using namespace IndexedInstrProf; + OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator; - using namespace IndexedInstrProf; InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs); InfoObj->SummaryBuilder = &ISB; @@ -301,7 +311,7 @@ void InstrProfWriter::write(raw_fd_ostream &OS) { std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() { std::string Data; - llvm::raw_string_ostream OS(Data); + raw_string_ostream OS(Data); ProfOStream POS(OS); // Write the hash table. writeImpl(POS); diff --git a/contrib/llvm/lib/ProfileData/SampleProf.cpp b/contrib/llvm/lib/ProfileData/SampleProf.cpp index 5bcfff0801d5..eafdd2154b7b 100644 --- a/contrib/llvm/lib/ProfileData/SampleProf.cpp +++ b/contrib/llvm/lib/ProfileData/SampleProf.cpp @@ -13,18 +13,25 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +#include <system_error> -using namespace llvm::sampleprof; using namespace llvm; +using namespace sampleprof; namespace { + // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class SampleProfErrorCategoryType : public std::error_category { const char *name() const noexcept override { return "llvm.sampleprof"; } + std::string message(int IE) const override { sampleprof_error E = static_cast<sampleprof_error>(IE); switch (E) { @@ -54,7 +61,8 @@ class SampleProfErrorCategoryType : public std::error_category { llvm_unreachable("A value of sampleprof_error has no message."); } }; -} + +} // end anonymous namespace static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory; @@ -74,7 +82,9 @@ raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, return OS; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); } +#endif /// \brief Print the sample record to the stream \p OS indented by \p Indent. void SampleRecord::print(raw_ostream &OS, unsigned Indent) const { @@ -87,7 +97,9 @@ void SampleRecord::print(raw_ostream &OS, unsigned Indent) const { OS << "\n"; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void SampleRecord::dump() const { print(dbgs(), 0); } +#endif raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, const SampleRecord &Sample) { @@ -101,7 +113,7 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const { << " sampled lines\n"; OS.indent(Indent); - if (BodySamples.size() > 0) { + if (!BodySamples.empty()) { OS << "Samples collected in the function's body {\n"; SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples); for (const auto &SI : SortedBodySamples.get()) { @@ -115,14 +127,16 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const { } OS.indent(Indent); - if (CallsiteSamples.size() > 0) { + if (!CallsiteSamples.empty()) { OS << "Samples collected in inlined callsites {\n"; - SampleSorter<LineLocation, FunctionSamples> SortedCallsiteSamples( + SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples( CallsiteSamples); for (const auto &CS : SortedCallsiteSamples.get()) { - OS.indent(Indent + 2); - OS << CS->first << ": inlined callee: " << CS->second.getName() << ": "; - CS->second.print(OS, Indent + 4); + for (const auto &FS : CS->second) { + OS.indent(Indent + 2); + OS << CS->first << ": inlined callee: " << FS.second.getName() << ": "; + FS.second.print(OS, Indent + 4); + } } OS << "}\n"; } else { @@ -136,4 +150,6 @@ raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS, return OS; } -void FunctionSamples::dump(void) const { print(dbgs(), 0); } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); } +#endif diff --git a/contrib/llvm/lib/ProfileData/SampleProfReader.cpp b/contrib/llvm/lib/ProfileData/SampleProfReader.cpp index af80b036a5bb..234fe02ac8a8 100644 --- a/contrib/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/contrib/llvm/lib/ProfileData/SampleProfReader.cpp @@ -23,14 +23,25 @@ #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/ProfileSummary.h" +#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <memory> +#include <system_error> +#include <vector> -using namespace llvm::sampleprof; using namespace llvm; +using namespace sampleprof; /// \brief Dump the function profile for \p FName. /// @@ -200,7 +211,7 @@ std::error_code SampleProfileReaderText::read() { InlineStack.pop_back(); } FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt( - LineLocation(LineOffset, Discriminator)); + LineLocation(LineOffset, Discriminator))[FName]; FSamples.setName(FName); MergeResult(Result, FSamples.addTotalSamples(NumSamples)); InlineStack.push_back(&FSamples); @@ -352,8 +363,8 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { if (std::error_code EC = FName.getError()) return EC; - FunctionSamples &CalleeProfile = - FProfile.functionSamplesAt(LineLocation(*LineOffset, *Discriminator)); + FunctionSamples &CalleeProfile = FProfile.functionSamplesAt( + LineLocation(*LineOffset, *Discriminator))[*FName]; CalleeProfile.setName(*FName); if (std::error_code EC = readProfile(CalleeProfile)) return EC; @@ -625,7 +636,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile( uint32_t LineOffset = Offset >> 16; uint32_t Discriminator = Offset & 0xffff; FProfile = &CallerProfile->functionSamplesAt( - LineLocation(LineOffset, Discriminator)); + LineLocation(LineOffset, Discriminator))[Name]; } FProfile->setName(Name); @@ -681,11 +692,9 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile( if (!GcovBuffer.readInt64(TargetCount)) return sampleprof_error::truncated; - if (Update) { - FunctionSamples &TargetProfile = Profiles[TargetName]; - TargetProfile.addCalledTargetSamples(LineOffset, Discriminator, - TargetName, TargetCount); - } + if (Update) + FProfile->addCalledTargetSamples(LineOffset, Discriminator, + TargetName, TargetCount); } } diff --git a/contrib/llvm/lib/ProfileData/SampleProfWriter.cpp b/contrib/llvm/lib/ProfileData/SampleProfWriter.cpp index 4fa71288f8d9..b91b6fb7c7ad 100644 --- a/contrib/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/contrib/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -18,16 +18,23 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringRef.h" +#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/ProfileData/SampleProfWriter.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/LineIterator.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Regex.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstdint> +#include <memory> +#include <system_error> +#include <utility> +#include <vector> -using namespace llvm::sampleprof; using namespace llvm; +using namespace sampleprof; /// \brief Write samples to a text file. /// @@ -61,20 +68,21 @@ std::error_code SampleProfileWriterText::write(const FunctionSamples &S) { OS << "\n"; } - SampleSorter<LineLocation, FunctionSamples> SortedCallsiteSamples( + SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples( S.getCallsiteSamples()); Indent += 1; - for (const auto &I : SortedCallsiteSamples.get()) { - LineLocation Loc = I->first; - const FunctionSamples &CalleeSamples = I->second; - OS.indent(Indent); - if (Loc.Discriminator == 0) - OS << Loc.LineOffset << ": "; - else - OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; - if (std::error_code EC = write(CalleeSamples)) - return EC; - } + for (const auto &I : SortedCallsiteSamples.get()) + for (const auto &FS : I->second) { + LineLocation Loc = I->first; + const FunctionSamples &CalleeSamples = FS.second; + OS.indent(Indent); + if (Loc.Discriminator == 0) + OS << Loc.LineOffset << ": "; + else + OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; + if (std::error_code EC = write(CalleeSamples)) + return EC; + } Indent -= 1; return sampleprof_error::success; @@ -102,11 +110,12 @@ void SampleProfileWriterBinary::addNames(const FunctionSamples &S) { } // Recursively add all the names for inlined callsites. - for (const auto &J : S.getCallsiteSamples()) { - const FunctionSamples &CalleeSamples = J.second; - addName(CalleeSamples.getName()); - addNames(CalleeSamples); - } + for (const auto &J : S.getCallsiteSamples()) + for (const auto &FS : J.second) { + const FunctionSamples &CalleeSamples = FS.second; + addName(CalleeSamples.getName()); + addNames(CalleeSamples); + } } std::error_code SampleProfileWriterBinary::writeHeader( @@ -180,14 +189,15 @@ std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) { // Recursively emit all the callsite samples. encodeULEB128(S.getCallsiteSamples().size(), OS); - for (const auto &J : S.getCallsiteSamples()) { - LineLocation Loc = J.first; - const FunctionSamples &CalleeSamples = J.second; - encodeULEB128(Loc.LineOffset, OS); - encodeULEB128(Loc.Discriminator, OS); - if (std::error_code EC = writeBody(CalleeSamples)) - return EC; - } + for (const auto &J : S.getCallsiteSamples()) + for (const auto &FS : J.second) { + LineLocation Loc = J.first; + const FunctionSamples &CalleeSamples = FS.second; + encodeULEB128(Loc.LineOffset, OS); + encodeULEB128(Loc.Discriminator, OS); + if (std::error_code EC = writeBody(CalleeSamples)) + return EC; + } return sampleprof_error::success; } |