Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:23

0001 //===--- FunctionId.h - Sample profile function object ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 ///
0011 /// Defines FunctionId class.
0012 ///
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_PROFILEDATA_FUNCTIONID_H
0016 #define LLVM_PROFILEDATA_FUNCTIONID_H
0017 
0018 #include "llvm/ADT/DenseMapInfo.h"
0019 #include "llvm/ADT/Hashing.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/Support/MD5.h"
0022 #include "llvm/Support/raw_ostream.h"
0023 #include <cstdint>
0024 
0025 namespace llvm {
0026 namespace sampleprof {
0027 
0028 /// This class represents a function that is read from a sample profile. It
0029 /// comes with two forms: a string or a hash code. The latter form is the 64-bit
0030 /// MD5 of the function name for efficient storage supported by ExtBinary
0031 /// profile format, and when reading the profile, this class can represent it
0032 /// without converting it to a string first.
0033 /// When representing a hash code, we utilize the LengthOrHashCode field to
0034 /// store it, and Name is set to null. When representing a string, it is same as
0035 /// StringRef.
0036 class FunctionId {
0037 
0038   const char *Data = nullptr;
0039 
0040   // Use uint64_t instead of size_t so that it can also hold a MD5 value on
0041   // 32-bit system.
0042   uint64_t LengthOrHashCode = 0;
0043 
0044   /// Extension to memcmp to handle hash code representation. If both are hash
0045   /// values, Lhs and Rhs are both null, function returns 0 (and needs an extra
0046   /// comparison using getIntValue). If only one is hash code, it is considered
0047   /// less than the StringRef one. Otherwise perform normal string comparison.
0048   static int compareMemory(const char *Lhs, const char *Rhs, uint64_t Length) {
0049     if (Lhs == Rhs)
0050       return 0;
0051     if (!Lhs)
0052       return -1;
0053     if (!Rhs)
0054       return 1;
0055     return ::memcmp(Lhs, Rhs, (size_t)Length);
0056   }
0057 
0058 public:
0059   FunctionId() = default;
0060 
0061   /// Constructor from a StringRef.
0062   explicit FunctionId(StringRef Str)
0063       : Data(Str.data()), LengthOrHashCode(Str.size()) {
0064   }
0065 
0066   /// Constructor from a hash code.
0067   explicit FunctionId(uint64_t HashCode)
0068       : LengthOrHashCode(HashCode) {
0069     assert(HashCode != 0);
0070   }
0071 
0072   /// Check for equality. Similar to StringRef::equals, but will also cover for
0073   /// the case where one or both are hash codes. Comparing their int values are
0074   /// sufficient. A hash code FunctionId is considered not equal to a StringRef
0075   /// FunctionId regardless of actual contents.
0076   bool equals(const FunctionId &Other) const {
0077     return LengthOrHashCode == Other.LengthOrHashCode &&
0078            compareMemory(Data, Other.Data, LengthOrHashCode) == 0;
0079   }
0080 
0081   /// Total order comparison. If both FunctionId are StringRef, this is the same
0082   /// as StringRef::compare. If one of them is StringRef, it is considered
0083   /// greater than the hash code FunctionId. Otherwise this is the the same
0084   /// as comparing their int values.
0085   int compare(const FunctionId &Other) const {
0086     auto Res = compareMemory(
0087         Data, Other.Data, std::min(LengthOrHashCode, Other.LengthOrHashCode));
0088     if (Res != 0)
0089       return Res;
0090     if (LengthOrHashCode == Other.LengthOrHashCode)
0091       return 0;
0092     return LengthOrHashCode < Other.LengthOrHashCode ? -1 : 1;
0093   }
0094 
0095   /// Convert to a string, usually for output purpose. Use caution on return
0096   /// value's lifetime when converting to StringRef.
0097   std::string str() const {
0098     if (Data)
0099       return std::string(Data, LengthOrHashCode);
0100     if (LengthOrHashCode != 0)
0101       return std::to_string(LengthOrHashCode);
0102     return std::string();
0103   }
0104 
0105   /// Convert to StringRef. This is only allowed when it is known this object is
0106   /// representing a StringRef, not a hash code. Calling this function on a hash
0107   /// code is considered an error.
0108   StringRef stringRef() const {
0109     if (Data)
0110       return StringRef(Data, LengthOrHashCode);
0111     assert(LengthOrHashCode == 0 &&
0112            "Cannot convert MD5 FunctionId to StringRef");
0113     return StringRef();
0114   }
0115 
0116   friend raw_ostream &operator<<(raw_ostream &OS, const FunctionId &Obj);
0117 
0118   /// Get hash code of this object. Returns this object's hash code if it is
0119   /// already representing one, otherwise returns the MD5 of its string content.
0120   /// Note that it is not the same as std::hash because we want to keep the
0121   /// consistency that the same sample profile function in string form or MD5
0122   /// form has the same hash code.
0123   uint64_t getHashCode() const {
0124     if (Data)
0125       return MD5Hash(StringRef(Data, LengthOrHashCode));
0126     return LengthOrHashCode;
0127   }
0128 
0129   bool empty() const { return LengthOrHashCode == 0; }
0130 
0131   /// Check if this object represents a StringRef, or a hash code.
0132   bool isStringRef() const { return Data != nullptr; }
0133 };
0134 
0135 inline bool operator==(const FunctionId &LHS, const FunctionId &RHS) {
0136   return LHS.equals(RHS);
0137 }
0138 
0139 inline bool operator!=(const FunctionId &LHS, const FunctionId &RHS) {
0140   return !LHS.equals(RHS);
0141 }
0142 
0143 inline bool operator<(const FunctionId &LHS, const FunctionId &RHS) {
0144   return LHS.compare(RHS) < 0;
0145 }
0146 
0147 inline bool operator<=(const FunctionId &LHS, const FunctionId &RHS) {
0148   return LHS.compare(RHS) <= 0;
0149 }
0150 
0151 inline bool operator>(const FunctionId &LHS, const FunctionId &RHS) {
0152   return LHS.compare(RHS) > 0;
0153 }
0154 
0155 inline bool operator>=(const FunctionId &LHS, const FunctionId &RHS) {
0156   return LHS.compare(RHS) >= 0;
0157 }
0158 
0159 inline raw_ostream &operator<<(raw_ostream &OS, const FunctionId &Obj) {
0160   if (Obj.Data)
0161     return OS << StringRef(Obj.Data, Obj.LengthOrHashCode);
0162   if (Obj.LengthOrHashCode != 0)
0163     return OS << Obj.LengthOrHashCode;
0164   return OS;
0165 }
0166 
0167 inline uint64_t MD5Hash(const FunctionId &Obj) {
0168   return Obj.getHashCode();
0169 }
0170 
0171 inline uint64_t hash_value(const FunctionId &Obj) {
0172   return Obj.getHashCode();
0173 }
0174 
0175 } // end namespace sampleprof
0176 
0177 /// Template specialization for FunctionId so that it can be used in LLVM map
0178 /// containers.
0179 template <> struct DenseMapInfo<sampleprof::FunctionId, void> {
0180 
0181   static inline sampleprof::FunctionId getEmptyKey() {
0182     return sampleprof::FunctionId(~0ULL);
0183   }
0184 
0185   static inline sampleprof::FunctionId getTombstoneKey() {
0186     return sampleprof::FunctionId(~1ULL);
0187   }
0188 
0189   static unsigned getHashValue(const sampleprof::FunctionId &Val) {
0190     return Val.getHashCode();
0191   }
0192 
0193   static bool isEqual(const sampleprof::FunctionId &LHS,
0194                       const sampleprof::FunctionId &RHS) {
0195     return LHS == RHS;
0196   }
0197 };
0198 
0199 } // end namespace llvm
0200 
0201 namespace std {
0202 
0203 /// Template specialization for FunctionId so that it can be used in STL
0204 /// containers.
0205 template <> struct hash<llvm::sampleprof::FunctionId> {
0206   size_t operator()(const llvm::sampleprof::FunctionId &Val) const {
0207     return Val.getHashCode();
0208   }
0209 };
0210 
0211 } // end namespace std
0212 
0213 #endif // LLVM_PROFILEDATA_FUNCTIONID_H