X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FProfileData%2FInstrProf.h;h=299763429006566cf2c651c4ae121146fa915a2c;hb=b195813e9eff4af71efaf6948ea3dc953260d628;hp=95648511910298c5e73e27cc04d05f6babd6703c;hpb=1c2b998913d05c83a781da1a15738ac4c9379f6f;p=oota-llvm.git diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 95648511910..29976342900 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -16,9 +16,9 @@ #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/ADT/STLExtras.h" #include "llvm/IR/GlobalValue.h" #include "llvm/ProfileData/InstrProfData.inc" #include "llvm/Support/Endian.h" @@ -65,23 +65,22 @@ inline StringRef getInstrProfValueProfFuncName() { /// Return the name of the section containing function coverage mapping /// data. inline StringRef getInstrProfCoverageSectionName(bool AddSegment) { - return AddSegment ? "__DATA,__llvm_covmap" : "__llvm_covmap"; + return AddSegment ? "__DATA," INSTR_PROF_COVMAP_SECT_NAME_STR + : INSTR_PROF_COVMAP_SECT_NAME_STR; } /// 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) /// for each instrumented source module. Such variables are allocated @@ -90,6 +89,12 @@ inline StringRef getCoverageMappingVarName() { return "__llvm_coverage_mapping"; } +/// Return the name of the internal variable recording the array +/// of PGO name vars referenced by the coverage mapping, The owning +/// functions of those names are not emitted by FE (e.g, unused inline +/// functions.) +inline StringRef getCoverageNamesVarName() { return "__llvm_coverage_names"; } + /// Return the name of function that registers all the per-function control /// data at program startup time by calling __llvm_register_function. This /// function has internal linkage and is called by __llvm_profile_init @@ -132,7 +137,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 @@ -140,7 +146,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 @@ -154,6 +161,35 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName); GlobalVariable *createPGOFuncNameVar(Module &M, GlobalValue::LinkageTypes Linkage, StringRef FuncName); +/// Return the initializer in string of the PGO name var \c NameVar. +StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar); + +/// Given a PGO function name, remove the filename prefix and return +/// the original (static) function name. +StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName); + +/// Given a vector of strings (function PGO names) \c NameStrs, the +/// method generates a combined string \c Result thatis ready to be +/// serialized. The \c Result string is comprised of three fields: +/// The first field is the legnth of the uncompressed strings, and the +/// the second field is the length of the zlib-compressed string. +/// Both fields are encoded in ULEB128. If \c doCompress is false, the +/// third field is the uncompressed strings; otherwise it is the +/// compressed string. When the string compression is off, the +/// second field will have value zero. +int collectPGOFuncNameStrings(const std::vector &NameStrs, + bool doCompression, std::string &Result); +/// Produce \c Result string with the same format described above. The input +/// is vector of PGO function name variables that are referenced. +int collectPGOFuncNameStrings(const std::vector &NameVars, + std::string &Result); +class InstrProfSymtab; +/// \c NameStrings is a string composed of one of more sub-strings encoded in +/// the +/// format described above. The substrings are seperated by 0 or more zero +/// bytes. +/// This method decodes the string and populates the \c Symtab. +int readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab); const std::error_category &instrprof_category(); @@ -179,27 +215,130 @@ 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" }; -struct InstrProfStringTable { - // Set of string values in profiling data. - StringSet<> StringValueSet; - InstrProfStringTable() { StringValueSet.clear(); } - // Get a pointer to internal storage of a string in set - const char *getStringData(StringRef Str) { - auto Result = StringValueSet.find(Str); - return (Result == StringValueSet.end()) ? nullptr : Result->first().data(); +namespace object { +class SectionRef; +} + +namespace IndexedInstrProf { +uint64_t ComputeHash(StringRef K); +} + +/// 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 { +public: + typedef std::vector> AddrHashMap; + +private: + StringRef Data; + uint64_t Address; + // A map from MD5 hash keys to function name strings. + std::vector> HashNameMap; + // A map from function runtime address to function name MD5 hash. + // This map is only populated and used by raw instr profile reader. + AddrHashMap AddrToMD5Map; + +public: + InstrProfSymtab() : Data(), Address(0), HashNameMap(), AddrToMD5Map() {} + + /// Create InstrProfSymtab from an object file section which + /// contains function PGO names that are uncompressed. + /// This interface is used by CoverageMappingReader. + std::error_code create(object::SectionRef &Section); + /// This interface is used by reader of CoverageMapping test + /// format. + inline std::error_code create(StringRef D, uint64_t BaseAddr); + /// \c NameStrings is a string composed of one of more sub-strings + /// encoded in the format described above. The substrings are + /// seperated by 0 or more zero bytes. This method decodes the + /// string and populates the \c Symtab. + inline std::error_code create(StringRef NameStrings); + /// Create InstrProfSymtab from a set of names iteratable from + /// \p IterRange. This interface is used by IndexedProfReader. + template void create(const NameIterRange &IterRange); + // If the symtab is created by a series of calls to \c addFuncName, \c + // finalizeSymtab needs to be called before looking up function names. + // This is required because the underlying map is a vector (for space + // efficiency) which needs to be sorted. + inline void finalizeSymtab(); + /// Update the symtab by adding \p FuncName to the table. This interface + /// is used by the raw and text profile readers. + void addFuncName(StringRef FuncName) { + HashNameMap.push_back(std::make_pair( + IndexedInstrProf::ComputeHash(FuncName), FuncName.str())); } - // Insert a string to StringTable - const char *insertString(StringRef Str) { - auto Result = StringValueSet.insert(Str); - return Result.first->first().data(); + /// Map a function address to its name's MD5 hash. This interface + /// is only used by the raw profiler reader. + void mapAddress(uint64_t Addr, uint64_t MD5Val) { + AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); } + AddrHashMap &getAddrHashMap() { return AddrToMD5Map; } + /// Return function's PGO name from the function name's symbol + /// address in the object file. If an error occurs, return + /// an empty string. + StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); + /// Return function's PGO name from the name's md5 hash value. + /// If not found, return an empty string. + inline StringRef getFuncName(uint64_t FuncMD5Hash); }; +std::error_code InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) { + Data = D; + Address = BaseAddr; + return std::error_code(); +} + +std::error_code InstrProfSymtab::create(StringRef NameStrings) { + if (readPGOFuncNameStrings(NameStrings, *this)) + return make_error_code(instrprof_error::malformed); + return std::error_code(); +} + +template +void InstrProfSymtab::create(const NameIterRange &IterRange) { + for (auto Name : IterRange) + HashNameMap.push_back( + std::make_pair(IndexedInstrProf::ComputeHash(Name), Name.str())); + finalizeSymtab(); +} + +void InstrProfSymtab::finalizeSymtab() { + std::sort(HashNameMap.begin(), HashNameMap.end(), less_first()); + HashNameMap.erase(std::unique(HashNameMap.begin(), HashNameMap.end()), + HashNameMap.end()); + std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first()); + AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()), + AddrToMD5Map.end()); +} + +StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) { + auto Result = + std::lower_bound(HashNameMap.begin(), HashNameMap.end(), FuncMD5Hash, + [](const std::pair &LHS, + uint64_t RHS) { return LHS.first < RHS; }); + if (Result != HashNameMap.end()) + return Result->second; + return StringRef(); +} + struct InstrProfValueSiteRecord { /// Value profiling data pairs at a given value site. std::list ValueData; @@ -216,25 +355,14 @@ struct InstrProfValueSiteRecord { return left.Value < right.Value; }); } + /// Sort ValueData Descending by Count + inline void sortByCount(); /// Merge data from another InstrProfValueSiteRecord - void mergeValueData(InstrProfValueSiteRecord &Input) { - this->sortByTargetValues(); - Input.sortByTargetValues(); - auto I = ValueData.begin(); - auto IE = ValueData.end(); - 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); - ++I; - continue; - } - ValueData.insert(I, *J); - } - } + /// Optionally scale merged counts by \p Weight. + instrprof_error merge(InstrProfValueSiteRecord &Input, uint64_t Weight = 1); + /// Scale up value profile data counts. + instrprof_error scale(uint64_t Weight); }; /// Profiling information for a single function. @@ -246,7 +374,7 @@ struct InstrProfRecord { uint64_t Hash; std::vector Counts; - typedef std::vector> ValueMapType; + typedef std::vector> ValueMapType; /// Return the number of value profile kinds with non-zero number /// of profile sites. @@ -269,19 +397,29 @@ struct InstrProfRecord { /// Reserve space for NumValueSites sites. inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites); /// Add ValueData for ValueKind at value Site. - inline void addValueData(uint32_t ValueKind, uint32_t Site, - InstrProfValueData *VData, uint32_t N, - ValueMapType *HashKeys); + void addValueData(uint32_t ValueKind, uint32_t Site, + InstrProfValueData *VData, uint32_t N, + ValueMapType *ValueMap); /// Merge the counts in \p Other into this one. - inline instrprof_error merge(InstrProfRecord &Other); - - /// Used by InstrProfWriter: update the value strings to commoned strings in - /// the writer instance. - inline void updateStrings(InstrProfStringTable *StrTab); - + /// Optionally scale merged counts by \p Weight. + instrprof_error merge(InstrProfRecord &Other, uint64_t Weight = 1); + + /// Scale up profile counts (including value profile data) by + /// \p Weight. + instrprof_error scale(uint64_t Weight); + + /// Sort value profile data (per site) by count. + void sortValueData() { + for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) { + std::vector &SiteRecords = + getValueSitesForKind(Kind); + for (auto &SR : SiteRecords) + SR.sortByCount(); + } + } /// Clear value data entries - inline void clearValueData() { + void clearValueData() { for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) getValueSitesForKind(Kind).clear(); } @@ -308,37 +446,14 @@ private: // Map indirect call target name hash to name string. uint64_t remapValue(uint64_t Value, uint32_t ValueKind, - ValueMapType *HashKeys) { - if (!HashKeys) - return Value; - switch (ValueKind) { - case IPVK_IndirectCallTarget: { - auto Result = - std::lower_bound(HashKeys->begin(), HashKeys->end(), Value, - [](const std::pair &LHS, - uint64_t RHS) { return LHS.first < RHS; }); - if (Result != HashKeys->end()) - Value = (uint64_t)Result->second; - break; - } - } - return Value; - } + ValueMapType *HashKeys); // Merge Value Profile data from Src record to this record for ValueKind. - instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src) { - uint32_t ThisNumValueSites = getNumValueSites(ValueKind); - uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind); - if (ThisNumValueSites != OtherNumValueSites) - return instrprof_error::value_site_count_mismatch; - std::vector &ThisSiteRecords = - getValueSitesForKind(ValueKind); - std::vector &OtherSiteRecords = - Src.getValueSitesForKind(ValueKind); - for (uint32_t I = 0; I < ThisNumValueSites; I++) - ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I]); - return instrprof_error::success; - } + // Scale merged value counts by \p Weight. + instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src, + uint64_t Weight); + // Scale up value profile data count. + instrprof_error scaleValueProfData(uint32_t ValueKind, uint64_t Weight); }; uint32_t InstrProfRecord::getNumValueKinds() const { @@ -392,74 +507,36 @@ void InstrProfRecord::getValueForSite(InstrProfValueData Dest[], } } -void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site, - InstrProfValueData *VData, uint32_t N, - ValueMapType *HashKeys) { - for (uint32_t I = 0; I < N; I++) { - VData[I].Value = remapValue(VData[I].Value, ValueKind, HashKeys); - } - std::vector &ValueSites = - getValueSitesForKind(ValueKind); - if (N == 0) - ValueSites.push_back(InstrProfValueSiteRecord()); - else - ValueSites.emplace_back(VData, VData + N); -} - void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) { std::vector &ValueSites = getValueSitesForKind(ValueKind); ValueSites.reserve(NumValueSites); } -void InstrProfRecord::updateStrings(InstrProfStringTable *StrTab) { - if (!StrTab) - return; - - Name = StrTab->insertString(Name); - for (auto &VSite : IndirectCallSites) - for (auto &VData : VSite.ValueData) - VData.Value = (uint64_t)StrTab->insertString((const char *)VData.Value); -} - -instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) { - // 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) { - bool ResultOverflowed; - Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], ResultOverflowed); - if (ResultOverflowed) - Result = instrprof_error::counter_overflow; - } - - for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) { - instrprof_error MergeValueResult = mergeValueProfData(Kind, Other); - if (MergeValueResult != instrprof_error::success) - Result = MergeValueResult; - } - - return Result; -} - inline support::endianness getHostEndianness() { return sys::IsLittleEndianHost ? support::little : support::big; } - // 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. - */ +void InstrProfValueSiteRecord::sortByCount() { + ValueData.sort( + [](const InstrProfValueData &left, const InstrProfValueData &right) { + return left.Count > right.Count; + }); + // Now truncate + size_t max_s = INSTR_PROF_MAX_NUM_VAL_PER_SITE; + if (ValueData.size() > max_s) + ValueData.resize(max_s); +} + +/* +* 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); @@ -495,7 +572,7 @@ static inline uint64_t MD5Hash(StringRef Str) { return endian::read(Result); } -static inline uint64_t ComputeHash(HashT Type, StringRef K) { +inline uint64_t ComputeHash(HashT Type, StringRef K) { switch (Type) { case HashT::MD5: return IndexedInstrProf::MD5Hash(K); @@ -504,9 +581,11 @@ 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; +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 { @@ -568,8 +647,20 @@ template struct CovMapFunctionRecord { #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; #include "llvm/ProfileData/InstrProfData.inc" }; +// Per module coverage mapping data header, i.e. CoverageMapFileHeader +// documented above. +struct CovMapHeader { +#define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; +#include "llvm/ProfileData/InstrProfData.inc" +}; + LLVM_PACKED_END +enum CoverageMappingVersion { + CoverageMappingVersion1 = 0, + // The current versin is Version1 + CoverageMappingCurrentVersion = INSTR_PROF_COVMAP_VERSION +}; } } // end namespace llvm