X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FProfileData%2FInstrProf.h;h=365656bb9d2ca1eb32b47beba6cb36a8f2577076;hp=4cd4ef9ee8f1d807967ba00497ff5f55dceef925;hb=5c542537c1330e18cce3744b519849e2c0c11fff;hpb=77b5e3816106051a5c83ffcf482bff19a17cb852 diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 4cd4ef9ee8f..365656bb9d2 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -16,6 +16,7 @@ #ifndef LLVM_PROFILEDATA_INSTRPROF_H_ #define LLVM_PROFILEDATA_INSTRPROF_H_ +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/IR/GlobalValue.h" @@ -29,6 +30,7 @@ #include #include +#define INSTR_PROF_INDEX_VERSION 3 namespace llvm { class Function; @@ -37,19 +39,28 @@ class Module; /// Return the name of data section containing profile counter variables. inline StringRef getInstrProfCountersSectionName(bool AddSegment) { - return AddSegment ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts"; + return AddSegment ? "__DATA," INSTR_PROF_CNTS_SECT_NAME_STR + : INSTR_PROF_CNTS_SECT_NAME_STR; } /// Return the name of data section containing names of instrumented /// functions. inline StringRef getInstrProfNameSectionName(bool AddSegment) { - return AddSegment ? "__DATA,__llvm_prf_names" : "__llvm_prf_names"; + return AddSegment ? "__DATA," INSTR_PROF_NAME_SECT_NAME_STR + : INSTR_PROF_NAME_SECT_NAME_STR; } /// Return the name of the data section containing per-function control /// data. inline StringRef getInstrProfDataSectionName(bool AddSegment) { - return AddSegment ? "__DATA,__llvm_prf_data" : "__llvm_prf_data"; + return AddSegment ? "__DATA," INSTR_PROF_DATA_SECT_NAME_STR + : INSTR_PROF_DATA_SECT_NAME_STR; +} + +/// Return the name profile runtime entry point to do value profiling +/// for a given site. +inline StringRef getInstrProfValueProfFuncName() { + return INSTR_PROF_VALUE_PROF_FUNC_STR; } /// Return the name of the section containing function coverage mapping @@ -59,21 +70,19 @@ inline StringRef getInstrProfCoverageSectionName(bool AddSegment) { } /// Return the name prefix of variables containing instrumented function names. -inline StringRef getInstrProfNameVarPrefix() { return "__llvm_profile_name_"; } +inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; } /// Return the name prefix of variables containing per-function control data. -inline StringRef getInstrProfDataVarPrefix() { return "__llvm_profile_data_"; } +inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; } /// Return the name prefix of profile counter variables. -inline StringRef getInstrProfCountersVarPrefix() { - return "__llvm_profile_counters_"; -} +inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; } /// Return the name prefix of the COMDAT group for instrumentation variables /// associated with a COMDAT function. -inline StringRef getInstrProfComdatPrefix() { return "__llvm_profile_vars_"; } +inline StringRef getInstrProfComdatPrefix() { return "__profv_"; } -/// Return the name of a covarage mapping variable (internal linkage) +/// Return the name of a covarage mapping variable (internal linkage) /// for each instrumented source module. Such variables are allocated /// in the __llvm_covmap section. inline StringRef getCoverageMappingVarName() { @@ -122,7 +131,8 @@ inline StringRef getInstrProfFileOverriderFuncName() { /// Return the modified name for function \c F suitable to be /// used the key for profile lookup. -std::string getPGOFuncName(const Function &F); +std::string getPGOFuncName(const Function &F, + uint64_t Version = INSTR_PROF_INDEX_VERSION); /// Return the modified name for a function suitable to be /// used the key for profile lookup. The function's original @@ -130,7 +140,8 @@ std::string getPGOFuncName(const Function &F); /// The function is defined in module \c FileName. std::string getPGOFuncName(StringRef RawFuncName, GlobalValue::LinkageTypes Linkage, - StringRef FileName); + StringRef FileName, + uint64_t Version = INSTR_PROF_INDEX_VERSION); /// Create and return the global variable for function name used in PGO /// instrumentation. \c FuncName is the name of the function returned @@ -145,6 +156,10 @@ GlobalVariable *createPGOFuncNameVar(Module &M, GlobalValue::LinkageTypes Linkage, StringRef FuncName); +/// Given a PGO function name, remove the filename prefix and return +/// the original (static) function name. +StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName); + const std::error_category &instrprof_category(); enum class instrprof_error { @@ -169,11 +184,52 @@ inline std::error_code make_error_code(instrprof_error E) { return std::error_code(static_cast(E), instrprof_category()); } +inline instrprof_error MergeResult(instrprof_error &Accumulator, + instrprof_error Result) { + // Prefer first error encountered as later errors may be secondary effects of + // the initial problem. + if (Accumulator == instrprof_error::success && + Result != instrprof_error::success) + Accumulator = Result; + return Accumulator; +} + enum InstrProfValueKind : uint32_t { #define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value, #include "llvm/ProfileData/InstrProfData.inc" }; +namespace object { +class SectionRef; +} +/// A symbol table used for function PGO name look-up with keys +/// (such as pointers, md5hash values) to the function. A function's +/// PGO name or name's md5hash are used in retrieving the profile +/// data of the function. See \c getPGOFuncName() method for details +/// on how PGO name is formed. +class InstrProfSymtab { +private: + StringRef Data; + uint64_t Address; + +public: + InstrProfSymtab() : Data(), Address(0) {} + + /// Create InstrProfSymtab from a object file section which + /// contains function PGO names that are uncompressed. + std::error_code create(object::SectionRef &Section); + std::error_code create(StringRef D, uint64_t BaseAddr) { + Data = D; + Address = BaseAddr; + return std::error_code(); + } + + /// Return function's PGO name from the function name's symabol + /// address in the object file. If an error occurs, Return + /// an empty string. + StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); +}; + struct InstrProfStringTable { // Set of string values in profiling data. StringSet<> StringValueSet; @@ -190,13 +246,6 @@ struct InstrProfStringTable { } }; -struct InstrProfValueData { - // Profiled value. - uint64_t Value; - // Number of times the value appears in the training run. - uint64_t Count; -}; - struct InstrProfValueSiteRecord { /// Value profiling data pairs at a given value site. std::list ValueData; @@ -215,22 +264,35 @@ struct InstrProfValueSiteRecord { } /// Merge data from another InstrProfValueSiteRecord - void mergeValueData(InstrProfValueSiteRecord &Input) { + /// Optionally scale merged counts by \p Weight. + instrprof_error mergeValueData(InstrProfValueSiteRecord &Input, + uint64_t Weight = 1) { this->sortByTargetValues(); Input.sortByTargetValues(); auto I = ValueData.begin(); auto IE = ValueData.end(); + instrprof_error Result = instrprof_error::success; for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE; ++J) { while (I != IE && I->Value < J->Value) ++I; if (I != IE && I->Value == J->Value) { - I->Count = SaturatingAdd(I->Count, J->Count); + uint64_t JCount = J->Count; + bool Overflowed; + if (Weight > 1) { + JCount = SaturatingMultiply(JCount, Weight, &Overflowed); + if (Overflowed) + Result = instrprof_error::counter_overflow; + } + I->Count = SaturatingAdd(I->Count, JCount, &Overflowed); + if (Overflowed) + Result = instrprof_error::counter_overflow; ++I; continue; } ValueData.insert(I, *J); } + return Result; } }; @@ -256,8 +318,13 @@ struct InstrProfRecord { /// site: Site. inline uint32_t getNumValueDataForSite(uint32_t ValueKind, uint32_t Site) const; + /// Return the array of profiled values at \p Site. inline std::unique_ptr - getValueForSite(uint32_t ValueKind, uint32_t Site) const; + getValueForSite(uint32_t ValueKind, uint32_t Site, + uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const; + inline void + getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind, uint32_t Site, + uint64_t (*ValueMapper)(uint32_t, uint64_t) = 0) const; /// Reserve space for NumValueSites sites. inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites); /// Add ValueData for ValueKind at value Site. @@ -266,7 +333,8 @@ struct InstrProfRecord { ValueMapType *HashKeys); /// Merge the counts in \p Other into this one. - inline instrprof_error merge(InstrProfRecord &Other); + /// Optionally scale merged counts by \p Weight. + inline instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1); /// Used by InstrProfWriter: update the value strings to commoned strings in /// the writer instance. @@ -318,7 +386,9 @@ private: } // Merge Value Profile data from Src record to this record for ValueKind. - instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src) { + // Scale merged value counts by \p Weight. + instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, + uint64_t Weight) { uint32_t ThisNumValueSites = getNumValueSites(ValueKind); uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind); if (ThisNumValueSites != OtherNumValueSites) @@ -327,9 +397,11 @@ private: getValueSitesForKind(ValueKind); std::vector &OtherSiteRecords = Src.getValueSitesForKind(ValueKind); + instrprof_error Result = instrprof_error::success; for (uint32_t I = 0; I < ThisNumValueSites; I++) - ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I]); - return instrprof_error::success; + MergeResult(Result, ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], + Weight)); + return Result; } }; @@ -359,21 +431,29 @@ uint32_t InstrProfRecord::getNumValueDataForSite(uint32_t ValueKind, return getValueSitesForKind(ValueKind)[Site].ValueData.size(); } -std::unique_ptr -InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site) const { +std::unique_ptr InstrProfRecord::getValueForSite( + uint32_t ValueKind, uint32_t Site, + uint64_t (*ValueMapper)(uint32_t, uint64_t)) const { uint32_t N = getNumValueDataForSite(ValueKind, Site); if (N == 0) return std::unique_ptr(nullptr); - std::unique_ptr VD(new InstrProfValueData[N]); + auto VD = llvm::make_unique(N); + getValueForSite(VD.get(), ValueKind, Site, ValueMapper); + + return VD; +} + +void InstrProfRecord::getValueForSite(InstrProfValueData Dest[], + uint32_t ValueKind, uint32_t Site, + uint64_t (*ValueMapper)(uint32_t, + uint64_t)) const { uint32_t I = 0; for (auto V : getValueSitesForKind(ValueKind)[Site].ValueData) { - VD[I] = V; + Dest[I].Value = ValueMapper ? ValueMapper(ValueKind, V.Value) : V.Value; + Dest[I].Count = V.Count; I++; } - assert(I == N); - - return VD; } void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site, @@ -406,125 +486,63 @@ void InstrProfRecord::updateStrings(InstrProfStringTable *StrTab) { VData.Value = (uint64_t)StrTab->insertString((const char *)VData.Value); } -instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) { +instrprof_error InstrProfRecord::merge(InstrProfRecord &Other, + uint64_t Weight) { // If the number of counters doesn't match we either have bad data // or a hash collision. if (Counts.size() != Other.Counts.size()) return instrprof_error::count_mismatch; + instrprof_error Result = instrprof_error::success; + for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) { - if (Counts[I] + Other.Counts[I] < Counts[I]) - return instrprof_error::counter_overflow; - Counts[I] += Other.Counts[I]; + bool Overflowed; + uint64_t OtherCount = Other.Counts[I]; + if (Weight > 1) { + OtherCount = SaturatingMultiply(OtherCount, Weight, &Overflowed); + if (Overflowed) + Result = instrprof_error::counter_overflow; + } + Counts[I] = SaturatingAdd(Counts[I], OtherCount, &Overflowed); + if (Overflowed) + Result = instrprof_error::counter_overflow; } - for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) { - instrprof_error result = mergeValueProfData(Kind, Other); - if (result != instrprof_error::success) - return result; - } + for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) + MergeResult(Result, mergeValueProfData(Kind, Other, Weight)); - return instrprof_error::success; + return Result; } inline support::endianness getHostEndianness() { return sys::IsLittleEndianHost ? support::little : support::big; } -/// This is the header of the data structure that defines the on-disk -/// layout of the value profile data of a particular kind for one function. -struct ValueProfRecord { - // The kind of the value profile record. - uint32_t Kind; - // The number of value profile sites. It is guaranteed to be non-zero; - // otherwise the record for this kind won't be emitted. - uint32_t NumValueSites; - // The first element of the array that stores the number of profiled - // values for each value site. The size of the array is NumValueSites. - // Since NumValueSites is greater than zero, there is at least one - // element in the array. - uint8_t SiteCountArray[1]; - - // The fake declaration is for documentation purpose only. - // Align the start of next field to be on 8 byte boundaries. - // uint8_t Padding[X]; - - // The array of value profile data. The size of the array is the sum - // of all elements in SiteCountArray[]. - // InstrProfValueData ValueData[]; - - /// Return the \c ValueProfRecord header size including the padding bytes. - static uint32_t getHeaderSize(uint32_t NumValueSites); - /// Return the total size of the value profile record including the - /// header and the value data. - static uint32_t getSize(uint32_t NumValueSites, uint32_t NumValueData); - /// Return the total size of the value profile record including the - /// header and the value data. - uint32_t getSize() const { return getSize(NumValueSites, getNumValueData()); } - /// Use this method to advance to the next \c ValueProfRecord. - ValueProfRecord *getNext(); - /// Return the pointer to the first value profile data. - InstrProfValueData *getValueData(); - /// Return the number of value sites. - uint32_t getNumValueSites() const { return NumValueSites; } - /// Return the number of value data. - uint32_t getNumValueData() const; - /// Read data from this record and save it to Record. - void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); - /// Extract data from \c Record and serialize into this instance. - void serializeFrom(const InstrProfRecord &Record, uint32_t ValueKind, - uint32_t NumValueSites); - /// In-place byte swap: - /// Do byte swap for this instance. \c Old is the original order before - /// the swap, and \c New is the New byte order. - void swapBytes(support::endianness Old, support::endianness New); -}; -/// Per-function header/control data structure for value profiling -/// data in indexed format. -struct ValueProfData { - // Total size in bytes including this field. It must be a multiple - // of sizeof(uint64_t). - uint32_t TotalSize; - // The number of value profile kinds that has value profile data. - // In this implementation, a value profile kind is considered to - // have profile data if the number of value profile sites for the - // kind is not zero. More aggressively, the implementation can - // choose to check the actual data value: if none of the value sites - // has any profiled values, the kind can be skipped. - uint32_t NumValueKinds; - - // Following are a sequence of variable length records. The prefix/header - // of each record is defined by ValueProfRecord type. The number of - // records is NumValueKinds. - // ValueProfRecord Record_1; - // ValueProfRecord Record_N; - - /// Return the total size in bytes of the on-disk value profile data - /// given the data stored in Record. - static uint32_t getSize(const InstrProfRecord &Record); - /// Return a pointer to \c ValueProfData instance ready to be streamed. - static std::unique_ptr - serializeFrom(const InstrProfRecord &Record); - /// Return a pointer to \c ValueProfileData instance ready to be read. - /// All data in the instance are properly byte swapped. The input - /// data is assumed to be in little endian order. - static ErrorOr> - getValueProfData(const unsigned char *D, const unsigned char *const BufferEnd, - support::endianness SrcDataEndianness); - /// Swap byte order from \c Endianness order to host byte order. - void swapBytesToHost(support::endianness Endianness); - /// Swap byte order from host byte order to \c Endianness order. - void swapBytesFromHost(support::endianness Endianness); - /// Return the total size of \c ValueProfileData. - uint32_t getSize() const { return TotalSize; } - /// Read data from this data and save it to \c Record. - void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); - /// Return the first \c ValueProfRecord instance. - ValueProfRecord *getFirstValueProfRecord(); -}; +// Include definitions for value profile data +#define INSTR_PROF_VALUE_PROF_DATA +#include "llvm/ProfileData/InstrProfData.inc" + + /* + * Initialize the record for runtime value profile data. + * Return 0 if the initialization is successful, otherwise + * return 1. + */ +int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, + const uint16_t *NumValueSites, + ValueProfNode **Nodes); + +/* Release memory allocated for the runtime record. */ +void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord); + +/* Return the size of ValueProfData structure that can be used to store + the value profile data collected at runtime. */ +uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record); + +/* Return a ValueProfData instance that stores the data collected at runtime. */ +ValueProfData * +serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, + ValueProfData *Dst); namespace IndexedInstrProf { @@ -554,9 +572,13 @@ static inline uint64_t ComputeHash(HashT Type, StringRef K) { } const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81" -const uint64_t Version = 3; +const uint64_t Version = INSTR_PROF_INDEX_VERSION; const HashT HashType = HashT::MD5; +static inline uint64_t ComputeHash(StringRef K) { + return ComputeHash(HashType, K); +} + // This structure defines the file header of the LLVM profile // data file in indexed-format. struct Header { @@ -597,7 +619,7 @@ template struct LLVM_ALIGNAS(8) ProfileData { // compiler-rt/lib/profile/InstrProfilingFile.c and // InstrProfilingBuffer.c. struct Header { -#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Type Name; +#define INSTR_PROF_RAW_HEADER(Type, Name, Init) const Type Name; #include "llvm/ProfileData/InstrProfData.inc" };