diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index f92b993bded59..26fd38660a135 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -318,6 +318,14 @@ struct LineLocationHash { raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc); +static inline hash_code hashFuncName(StringRef F) { + // If function name is already MD5 string, do not hash again. + uint64_t Hash; + if (F.getAsInteger(10, Hash)) + Hash = MD5Hash(F); + return Hash; +} + /// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which @@ -630,9 +638,13 @@ class SampleContext { return getContextString(FullContext, false); } - uint64_t getHashCode() const { - return hasContext() ? hash_value(getContextFrames()) - : hash_value(getName()); + hash_code getHashCode() const { + if (hasContext()) + return hash_value(getContextFrames()); + + // For non-context function name, use its MD5 as hash value, so that it is + // consistent with the profile map's key. + return hashFuncName(getName()); } /// Set the name of the function and clear the current context. @@ -710,9 +722,12 @@ class SampleContext { uint32_t Attributes; }; -static inline hash_code hash_value(const SampleContext &arg) { - return arg.hasContext() ? hash_value(arg.getContextFrames()) - : hash_value(arg.getName()); +static inline hash_code hash_value(const SampleContext &Context) { + return Context.getHashCode(); +} + +inline raw_ostream &operator<<(raw_ostream &OS, const SampleContext &Context) { + return OS << Context.toString(); } class FunctionSamples; @@ -1202,6 +1217,9 @@ class FunctionSamples { return !(*this == Other); } + template + const T &getKey() const; + private: /// CFG hash value for the function. uint64_t FunctionHash = 0; @@ -1265,12 +1283,173 @@ class FunctionSamples { const LocToLocMap *IRToProfileLocationMap = nullptr; }; +template <> +inline const SampleContext &FunctionSamples::getKey() const { + return getContext(); +} + raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS); -using SampleProfileMap = - std::unordered_map; +/// This class is a wrapper to associative container MapT using +/// the hash value of the original key as the new key. This greatly improves the +/// performance of insert and query operations especially when hash values of +/// keys are available a priori, and reduces memory usage if KeyT has a large +/// size. +/// When performing any action, if an existing entry with a given key is found, +/// and the interface "KeyT ValueT::getKey() const" to retrieve a value's +/// original key exists, this class checks if the given key actually matches +/// the existing entry's original key. If they do not match, this class behaves +/// as if the entry did not exist (for insertion, this means the new value will +/// replace the existing entry's value, as if it is newly inserted). If +/// ValueT::getKey() is not available, all keys with the same hash value +/// are considered equivalent (i.e. hash collision is silently ignored). Given +/// such feature this class should only be used where it does not affect +/// compilation correctness, for example, when loading a sample profile. +/// Assuming the hashing algorithm is uniform, the probability of hash collision +/// with 1,000,000 entries is +/// (2^64)!/((2^64-1000000)!*(2^64)^1000000) ~= 3*10^-8. +template