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=3a1226662007fce351f5ec55de80384127fcf408;hb=5c542537c1330e18cce3744b519849e2c0c11fff;hpb=170357c9b7506ed3947702816012214fb1cd93a6 diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 3a122666200..365656bb9d2 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" @@ -30,6 +30,7 @@ #include #include +#define INSTR_PROF_INDEX_VERSION 3 namespace llvm { class Function; @@ -69,19 +70,17 @@ 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) /// for each instrumented source module. Such variables are allocated @@ -132,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 @@ -140,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 @@ -155,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 { @@ -179,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; @@ -218,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; } }; @@ -274,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. @@ -326,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) @@ -335,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; } }; @@ -422,170 +486,51 @@ 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. -typedef 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 number of value sites. - uint32_t getNumValueSites() const { return NumValueSites; } - /// Read data from this record and save it to Record. - void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); - /// 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); -} ValueProfRecord; - -/// Per-function header/control data structure for value profiling -/// data in indexed format. -typedef 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); - /// Check the integrity of the record. Return the error code when - /// an error is detected, otherwise return instrprof_error::success. - instrprof_error checkIntegrity(); - /// 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); -} ValueProfData; - -/* The closure is designed to abstact away two types of value profile data: - * - InstrProfRecord which is the primary data structure used to - * represent profile data in host tools (reader, writer, and profile-use) - * - value profile runtime data structure suitable to be used by C - * runtime library. - * - * Both sources of data need to serialize to disk/memory-buffer in common - * format: ValueProfData. The abstraction allows compiler-rt's raw profiler - * writer to share * the same code with indexed profile writer. - * - * For documentation of the member methods below, refer to corresponding methods - * in class InstrProfRecord. - */ -typedef struct ValueProfRecordClosure { - const void *Record; - uint32_t (*GetNumValueKinds)(const void *Record); - uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); - uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); - uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); - - /* After extracting the value profile data from the value profile record, - * this method is used to map the in-memory value to on-disk value. If - * the method is null, value will be written out untranslated. - */ - uint64_t (*RemapValueData)(uint32_t, uint64_t Value); - void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, - uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)); - ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); -} ValueProfRecordClosure; - -/* A wrapper struct that represents value profile runtime data. - * Like InstrProfRecord class which is used by profiling host tools, - * ValueProfRuntimeRecord also implements the abstract intefaces defined in - * ValueProfRecordClosure so that the runtime data can be serialized using - * shared C implementation. In this structure, NumValueSites and Nodes - * members are the primary fields while other fields hold the derived - * information for fast implementation of closure interfaces. + +// 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. */ -typedef struct ValueProfRuntimeRecord { - /* Number of sites for each value profile kind. */ - uint16_t *NumValueSites; - /* An array of linked-list headers. The size of of the array is the - * total number of value profile sites : sum(NumValueSites[*])). Each - * linked-list stores the values profiled for a value profile site. */ - ValueProfNode **Nodes; - - /* Total number of value profile kinds which have at least one - * value profile sites. */ - uint32_t NumValueKinds; - /* An array recording the number of values tracked at each site. - * The size of the array is TotalNumValueSites. - */ - uint8_t *SiteCountArray[IPVK_Last + 1]; - ValueProfNode **NodesKind[IPVK_Last + 1]; -} ValueProfRuntimeRecord; - -/* Initialize the record for runtime value profile data. */ -void initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, - uint16_t *NumValueSites, - ValueProfNode **Nodes); +int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, + const uint16_t *NumValueSites, + ValueProfNode **Nodes); /* Release memory allocated for the runtime record. */ void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord); @@ -596,62 +541,8 @@ uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record); /* Return a ValueProfData instance that stores the data collected at runtime. */ ValueProfData * -serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record); - - -/*! \brief Return the \c ValueProfRecord header size including the - * padding bytes. - */ -inline uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { - uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) + - sizeof(uint8_t) * NumValueSites; - // Round the size to multiple of 8 bytes. - Size = (Size + 7) & ~7; - return Size; -} - -/*! \brief Return the total size of the value profile record including the - * header and the value data. - */ -inline uint32_t getValueProfRecordSize(uint32_t NumValueSites, - uint32_t NumValueData) { - return getValueProfRecordHeaderSize(NumValueSites) + - sizeof(InstrProfValueData) * NumValueData; -} - -/*! \brief Return the pointer to the start of value data array. - */ -inline InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { - return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize( - This->NumValueSites)); -} - -/*! \brief Return the total number of value data for \c This record. - */ -inline uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { - uint32_t NumValueData = 0; - uint32_t I; - for (I = 0; I < This->NumValueSites; I++) - NumValueData += This->SiteCountArray[I]; - return NumValueData; -} - -/* \brief Use this method to advance to the next \c This \c ValueProfRecord. - */ -inline ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { - uint32_t NumValueData = getValueProfRecordNumValueData(This); - return (ValueProfRecord *)((char *)This + - getValueProfRecordSize(This->NumValueSites, - NumValueData)); -} - -/*! \brief Return the first \c ValueProfRecord instance. - */ -inline ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { - return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); -} - - +serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, + ValueProfData *Dst); namespace IndexedInstrProf { @@ -681,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 {