//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // This file contains common definitions used in the reading and writing of // sample profile data. // //===----------------------------------------------------------------------===// #ifndef LLVM_PROFILEDATA_SAMPLEPROF_H #define LLVM_PROFILEDATA_SAMPLEPROF_H #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/ProfileData/FunctionId.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MathExtras.h" #include "llvm/ProfileData/HashKeyMap.h" #include <algorithm> #include <cstdint> #include <list> #include <map> #include <set> #include <sstream> #include <string> #include <system_error> #include <unordered_map> #include <utility> namespace llvm { class DILocation; class raw_ostream; const std::error_category &sampleprof_category(); enum class sampleprof_error { … }; inline std::error_code make_error_code(sampleprof_error E) { … } inline sampleprof_error mergeSampleProfErrors(sampleprof_error &Accumulator, sampleprof_error Result) { … } } // end namespace llvm namespace std { template <> struct is_error_code_enum<llvm::sampleprof_error> : std::true_type { … }; } // end namespace std namespace llvm { namespace sampleprof { enum SampleProfileFormat { … }; enum SampleProfileLayout { … }; static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) { … } static inline uint64_t SPVersion() { … } // Section Type used by SampleProfileExtBinaryBaseReader and // SampleProfileExtBinaryBaseWriter. Never change the existing // value of enum. Only append new ones. enum SecType { … }; static inline std::string getSecName(SecType Type) { … } // Entry type of section header table used by SampleProfileExtBinaryBaseReader // and SampleProfileExtBinaryBaseWriter. struct SecHdrTableEntry { … }; // Flags common for all sections are defined here. In SecHdrTableEntry::Flags, // common flags will be saved in the lower 32bits and section specific flags // will be saved in the higher 32 bits. enum class SecCommonFlags : uint32_t { … }; // Section specific flags are defined here. // !!!Note: Everytime a new enum class is created here, please add // a new check in verifySecFlag. enum class SecNameTableFlags : uint32_t { … }; enum class SecProfSummaryFlags : uint32_t { … }; enum class SecFuncMetadataFlags : uint32_t { … }; enum class SecFuncOffsetFlags : uint32_t { … }; // Verify section specific flag is used for the correct section. template <class SecFlagType> static inline void verifySecFlag(SecType Type, SecFlagType Flag) { … } template <class SecFlagType> static inline void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) { … } template <class SecFlagType> static inline void removeSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag) { … } template <class SecFlagType> static inline bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag) { … } /// Represents the relative location of an instruction. /// /// Instruction locations are specified by the line offset from the /// beginning of the function (marked by the line where the function /// header is) and the discriminator value within that line. /// /// The discriminator value is useful to distinguish instructions /// that are on the same line but belong to different basic blocks /// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). struct LineLocation { … }; struct LineLocationHash { … }; raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc); /// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which /// indicates how frequently was the associated line location executed. /// /// Additionally, if the associated location contains a function call, /// the record will hold a list of all the possible called targets. For /// direct calls, this will be the exact function being invoked. For /// indirect calls (function pointers, virtual table dispatch), this /// will be a list of one or more functions. class SampleRecord { … }; raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample); // State of context associated with FunctionSamples enum ContextStateMask { … }; // Attribute of context associated with FunctionSamples enum ContextAttributeMask { … }; // Represents a context frame with profile function and line location struct SampleContextFrame { … }; static inline hash_code hash_value(const SampleContextFrame &arg) { … } SampleContextFrameVector; SampleContextFrames; struct SampleContextFrameHash { … }; // Sample context for FunctionSamples. It consists of the calling context, // the function name and context state. Internally sample context is represented // using ArrayRef, which is also the input for constructing a `SampleContext`. // It can accept and represent both full context string as well as context-less // function name. // For a CS profile, a full context vector can look like: // `main:3 _Z5funcAi:1 _Z8funcLeafi` // For a base CS profile without calling context, the context vector should only // contain the leaf frame name. // For a non-CS profile, the context vector should be empty. class SampleContext { … }; static inline hash_code hash_value(const SampleContext &Context) { … } inline raw_ostream &operator<<(raw_ostream &OS, const SampleContext &Context) { … } class FunctionSamples; class SampleProfileReaderItaniumRemapper; BodySampleMap; // NOTE: Using a StringMap here makes parsed profiles consume around 17% more // memory, which is *very* significant for large profiles. FunctionSamplesMap; CallsiteSampleMap; LocToLocMap; /// Representation of the samples collected for a function. /// /// This data structure contains all the collected samples for the body /// of a function. Each sample corresponds to a LineLocation instance /// within the body of the function. class FunctionSamples { … }; /// Get the proper representation of a string according to whether the /// current Format uses MD5 to represent the string. static inline FunctionId getRepInFormat(StringRef Name) { … } raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS); /// This class provides operator overloads to the map container using MD5 as the /// key type, so that existing code can still work in most cases using /// SampleContext as key. /// Note: when populating container, make sure to assign the SampleContext to /// the mapped value immediately because the key no longer holds it. class SampleProfileMap : public HashKeyMap<std::unordered_map, SampleContext, FunctionSamples> { … }; NameFunctionSamples; void sortFuncProfiles(const SampleProfileMap &ProfileMap, std::vector<NameFunctionSamples> &SortedProfiles); /// Sort a LocationT->SampleT map by LocationT. /// /// It produces a sorted list of <LocationT, SampleT> records by ascending /// order of LocationT. template <class LocationT, class SampleT> class SampleSorter { … }; /// SampleContextTrimmer impelements helper functions to trim, merge cold /// context profiles. It also supports context profile canonicalization to make /// sure ProfileMap's key is consistent with FunctionSample's name/context. class SampleContextTrimmer { … }; /// Helper class for profile conversion. /// /// It supports full context-sensitive profile to nested profile conversion, /// nested profile to flatten profile conversion, etc. class ProfileConverter { … }; /// ProfileSymbolList records the list of function symbols shown up /// in the binary used to generate the profile. It is useful to /// to discriminate a function being so cold as not to shown up /// in the profile and a function newly added. class ProfileSymbolList { … }; } // end namespace sampleprof usingnamespacesampleprof; // Provide DenseMapInfo for SampleContext. template <> struct DenseMapInfo<SampleContext> { … }; // Prepend "__uniq" before the hash for tools like profilers to understand // that this symbol is of internal linkage type. The "__uniq" is the // pre-determined prefix that is used to tell tools that this symbol was // created with -funique-internal-linkage-symbols and the tools can strip or // keep the prefix as needed. inline std::string getUniqueInternalLinkagePostfix(const StringRef &FName) { … } } // end namespace llvm #endif // LLVM_PROFILEDATA_SAMPLEPROF_H