xref: /freebsd-src/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- InstrProf.cpp - Instrumented profiling format support --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for clang's instrumentation based PGO and
100b57cec5SDimitry Andric // coverage.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
19fe6060f1SDimitry Andric #include "llvm/Config/config.h"
200b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
210b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
220b57cec5SDimitry Andric #include "llvm/IR/Function.h"
230b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
240b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
250b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
260b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
270b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
280b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
290b57cec5SDimitry Andric #include "llvm/IR/Module.h"
300b57cec5SDimitry Andric #include "llvm/IR/Type.h"
310b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
320b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
330b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
340b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
350b57cec5SDimitry Andric #include "llvm/Support/Compression.h"
36*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h"
370b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
380b57cec5SDimitry Andric #include "llvm/Support/Error.h"
390b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
400b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
410b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
420b57cec5SDimitry Andric #include "llvm/Support/Path.h"
430b57cec5SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
4406c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
4506c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
460b57cec5SDimitry Andric #include <algorithm>
470b57cec5SDimitry Andric #include <cassert>
480b57cec5SDimitry Andric #include <cstddef>
490b57cec5SDimitry Andric #include <cstdint>
500b57cec5SDimitry Andric #include <cstring>
510b57cec5SDimitry Andric #include <memory>
520b57cec5SDimitry Andric #include <string>
530b57cec5SDimitry Andric #include <system_error>
5481ad6265SDimitry Andric #include <type_traits>
550b57cec5SDimitry Andric #include <utility>
560b57cec5SDimitry Andric #include <vector>
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric using namespace llvm;
590b57cec5SDimitry Andric 
60*0fca6ea1SDimitry Andric #define DEBUG_TYPE "instrprof"
61*0fca6ea1SDimitry Andric 
620b57cec5SDimitry Andric static cl::opt<bool> StaticFuncFullModulePrefix(
630b57cec5SDimitry Andric     "static-func-full-module-prefix", cl::init(true), cl::Hidden,
640b57cec5SDimitry Andric     cl::desc("Use full module build paths in the profile counter names for "
650b57cec5SDimitry Andric              "static functions."));
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric // This option is tailored to users that have different top-level directory in
680b57cec5SDimitry Andric // profile-gen and profile-use compilation. Users need to specific the number
690b57cec5SDimitry Andric // of levels to strip. A value larger than the number of directories in the
700b57cec5SDimitry Andric // source file will strip all the directory names and only leave the basename.
710b57cec5SDimitry Andric //
720b57cec5SDimitry Andric // Note current ThinLTO module importing for the indirect-calls assumes
730b57cec5SDimitry Andric // the source directory name not being stripped. A non-zero option value here
740b57cec5SDimitry Andric // can potentially prevent some inter-module indirect-call-promotions.
750b57cec5SDimitry Andric static cl::opt<unsigned> StaticFuncStripDirNamePrefix(
760b57cec5SDimitry Andric     "static-func-strip-dirname-prefix", cl::init(0), cl::Hidden,
770b57cec5SDimitry Andric     cl::desc("Strip specified level of directory name from source path in "
780b57cec5SDimitry Andric              "the profile counter name for static functions."));
790b57cec5SDimitry Andric 
80349cc55cSDimitry Andric static std::string getInstrProfErrString(instrprof_error Err,
81349cc55cSDimitry Andric                                          const std::string &ErrMsg = "") {
82349cc55cSDimitry Andric   std::string Msg;
83349cc55cSDimitry Andric   raw_string_ostream OS(Msg);
84349cc55cSDimitry Andric 
850b57cec5SDimitry Andric   switch (Err) {
860b57cec5SDimitry Andric   case instrprof_error::success:
87349cc55cSDimitry Andric     OS << "success";
88349cc55cSDimitry Andric     break;
890b57cec5SDimitry Andric   case instrprof_error::eof:
90349cc55cSDimitry Andric     OS << "end of File";
91349cc55cSDimitry Andric     break;
920b57cec5SDimitry Andric   case instrprof_error::unrecognized_format:
93349cc55cSDimitry Andric     OS << "unrecognized instrumentation profile encoding format";
94349cc55cSDimitry Andric     break;
950b57cec5SDimitry Andric   case instrprof_error::bad_magic:
96349cc55cSDimitry Andric     OS << "invalid instrumentation profile data (bad magic)";
97349cc55cSDimitry Andric     break;
980b57cec5SDimitry Andric   case instrprof_error::bad_header:
99349cc55cSDimitry Andric     OS << "invalid instrumentation profile data (file header is corrupt)";
100349cc55cSDimitry Andric     break;
1010b57cec5SDimitry Andric   case instrprof_error::unsupported_version:
102349cc55cSDimitry Andric     OS << "unsupported instrumentation profile format version";
103349cc55cSDimitry Andric     break;
1040b57cec5SDimitry Andric   case instrprof_error::unsupported_hash_type:
105349cc55cSDimitry Andric     OS << "unsupported instrumentation profile hash type";
106349cc55cSDimitry Andric     break;
1070b57cec5SDimitry Andric   case instrprof_error::too_large:
108349cc55cSDimitry Andric     OS << "too much profile data";
109349cc55cSDimitry Andric     break;
1100b57cec5SDimitry Andric   case instrprof_error::truncated:
111349cc55cSDimitry Andric     OS << "truncated profile data";
112349cc55cSDimitry Andric     break;
1130b57cec5SDimitry Andric   case instrprof_error::malformed:
114349cc55cSDimitry Andric     OS << "malformed instrumentation profile data";
115349cc55cSDimitry Andric     break;
1165f757f3fSDimitry Andric   case instrprof_error::missing_correlation_info:
1175f757f3fSDimitry Andric     OS << "debug info/binary for correlation is required";
1180eae32dcSDimitry Andric     break;
1195f757f3fSDimitry Andric   case instrprof_error::unexpected_correlation_info:
1205f757f3fSDimitry Andric     OS << "debug info/binary for correlation is not necessary";
1210eae32dcSDimitry Andric     break;
1220eae32dcSDimitry Andric   case instrprof_error::unable_to_correlate_profile:
1230eae32dcSDimitry Andric     OS << "unable to correlate profile";
1240eae32dcSDimitry Andric     break;
125fe6060f1SDimitry Andric   case instrprof_error::invalid_prof:
126349cc55cSDimitry Andric     OS << "invalid profile created. Please file a bug "
127fe6060f1SDimitry Andric           "at: " BUG_REPORT_URL
128fe6060f1SDimitry Andric           " and include the profraw files that caused this error.";
129349cc55cSDimitry Andric     break;
1300b57cec5SDimitry Andric   case instrprof_error::unknown_function:
131349cc55cSDimitry Andric     OS << "no profile data available for function";
132349cc55cSDimitry Andric     break;
1330b57cec5SDimitry Andric   case instrprof_error::hash_mismatch:
134349cc55cSDimitry Andric     OS << "function control flow change detected (hash mismatch)";
135349cc55cSDimitry Andric     break;
1360b57cec5SDimitry Andric   case instrprof_error::count_mismatch:
137349cc55cSDimitry Andric     OS << "function basic block count change detected (counter mismatch)";
138349cc55cSDimitry Andric     break;
1395f757f3fSDimitry Andric   case instrprof_error::bitmap_mismatch:
1405f757f3fSDimitry Andric     OS << "function bitmap size change detected (bitmap size mismatch)";
1415f757f3fSDimitry Andric     break;
1420b57cec5SDimitry Andric   case instrprof_error::counter_overflow:
143349cc55cSDimitry Andric     OS << "counter overflow";
144349cc55cSDimitry Andric     break;
1450b57cec5SDimitry Andric   case instrprof_error::value_site_count_mismatch:
146349cc55cSDimitry Andric     OS << "function value site count change detected (counter mismatch)";
147349cc55cSDimitry Andric     break;
1480b57cec5SDimitry Andric   case instrprof_error::compress_failed:
149349cc55cSDimitry Andric     OS << "failed to compress data (zlib)";
150349cc55cSDimitry Andric     break;
1510b57cec5SDimitry Andric   case instrprof_error::uncompress_failed:
152349cc55cSDimitry Andric     OS << "failed to uncompress data (zlib)";
153349cc55cSDimitry Andric     break;
1540b57cec5SDimitry Andric   case instrprof_error::empty_raw_profile:
155349cc55cSDimitry Andric     OS << "empty raw profile file";
156349cc55cSDimitry Andric     break;
1570b57cec5SDimitry Andric   case instrprof_error::zlib_unavailable:
158349cc55cSDimitry Andric     OS << "profile uses zlib compression but the profile reader was built "
159fe6060f1SDimitry Andric           "without zlib support";
160349cc55cSDimitry Andric     break;
16106c3fb27SDimitry Andric   case instrprof_error::raw_profile_version_mismatch:
16206c3fb27SDimitry Andric     OS << "raw profile version mismatch";
16306c3fb27SDimitry Andric     break;
1645f757f3fSDimitry Andric   case instrprof_error::counter_value_too_large:
1655f757f3fSDimitry Andric     OS << "excessively large counter value suggests corrupted profile data";
1665f757f3fSDimitry Andric     break;
1670b57cec5SDimitry Andric   }
168349cc55cSDimitry Andric 
169349cc55cSDimitry Andric   // If optional error message is not empty, append it to the message.
170349cc55cSDimitry Andric   if (!ErrMsg.empty())
171349cc55cSDimitry Andric     OS << ": " << ErrMsg;
172349cc55cSDimitry Andric 
173349cc55cSDimitry Andric   return OS.str();
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric namespace {
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
1790b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
1800b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
1810b57cec5SDimitry Andric class InstrProfErrorCategoryType : public std::error_category {
1820b57cec5SDimitry Andric   const char *name() const noexcept override { return "llvm.instrprof"; }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   std::string message(int IE) const override {
1850b57cec5SDimitry Andric     return getInstrProfErrString(static_cast<instrprof_error>(IE));
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric };
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric } // end anonymous namespace
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric const std::error_category &llvm::instrprof_category() {
192753f127fSDimitry Andric   static InstrProfErrorCategoryType ErrorCategory;
193753f127fSDimitry Andric   return ErrorCategory;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric namespace {
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric const char *InstrProfSectNameCommon[] = {
1990b57cec5SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
2000b57cec5SDimitry Andric   SectNameCommon,
2010b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
2020b57cec5SDimitry Andric };
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric const char *InstrProfSectNameCoff[] = {
2050b57cec5SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
2060b57cec5SDimitry Andric   SectNameCoff,
2070b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
2080b57cec5SDimitry Andric };
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric const char *InstrProfSectNamePrefix[] = {
2110b57cec5SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
2120b57cec5SDimitry Andric   Prefix,
2130b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
2140b57cec5SDimitry Andric };
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric } // namespace
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric namespace llvm {
2190b57cec5SDimitry Andric 
2205ffd83dbSDimitry Andric cl::opt<bool> DoInstrProfNameCompression(
2215ffd83dbSDimitry Andric     "enable-name-compression",
2225ffd83dbSDimitry Andric     cl::desc("Enable name/filename string compression"), cl::init(true));
2235ffd83dbSDimitry Andric 
224*0fca6ea1SDimitry Andric cl::opt<bool> EnableVTableValueProfiling(
225*0fca6ea1SDimitry Andric     "enable-vtable-value-profiling", cl::init(false),
226*0fca6ea1SDimitry Andric     cl::desc("If true, the virtual table address will be instrumented to know "
227*0fca6ea1SDimitry Andric              "the types of a C++ pointer. The information is used in indirect "
228*0fca6ea1SDimitry Andric              "call promotion to do selective vtable-based comparison."));
229*0fca6ea1SDimitry Andric 
230*0fca6ea1SDimitry Andric cl::opt<bool> EnableVTableProfileUse(
231*0fca6ea1SDimitry Andric     "enable-vtable-profile-use", cl::init(false),
232*0fca6ea1SDimitry Andric     cl::desc("If ThinLTO and WPD is enabled and this option is true, vtable "
233*0fca6ea1SDimitry Andric              "profiles will be used by ICP pass for more efficient indirect "
234*0fca6ea1SDimitry Andric              "call sequence. If false, type profiles won't be used."));
235*0fca6ea1SDimitry Andric 
2360b57cec5SDimitry Andric std::string getInstrProfSectionName(InstrProfSectKind IPSK,
2370b57cec5SDimitry Andric                                     Triple::ObjectFormatType OF,
2380b57cec5SDimitry Andric                                     bool AddSegmentInfo) {
2390b57cec5SDimitry Andric   std::string SectName;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   if (OF == Triple::MachO && AddSegmentInfo)
2420b57cec5SDimitry Andric     SectName = InstrProfSectNamePrefix[IPSK];
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (OF == Triple::COFF)
2450b57cec5SDimitry Andric     SectName += InstrProfSectNameCoff[IPSK];
2460b57cec5SDimitry Andric   else
2470b57cec5SDimitry Andric     SectName += InstrProfSectNameCommon[IPSK];
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   if (OF == Triple::MachO && IPSK == IPSK_data && AddSegmentInfo)
2500b57cec5SDimitry Andric     SectName += ",regular,live_support";
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   return SectName;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric std::string InstrProfError::message() const {
256349cc55cSDimitry Andric   return getInstrProfErrString(Err, Msg);
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric char InstrProfError::ID = 0;
2600b57cec5SDimitry Andric 
261cb14a3feSDimitry Andric std::string getPGOFuncName(StringRef Name, GlobalValue::LinkageTypes Linkage,
2620b57cec5SDimitry Andric                            StringRef FileName,
2630b57cec5SDimitry Andric                            uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
264cb14a3feSDimitry Andric   // Value names may be prefixed with a binary '1' to indicate
265cb14a3feSDimitry Andric   // that the backend should not modify the symbols due to any platform
266cb14a3feSDimitry Andric   // naming convention. Do not include that '1' in the PGO profile name.
267cb14a3feSDimitry Andric   if (Name[0] == '\1')
268cb14a3feSDimitry Andric     Name = Name.substr(1);
269cb14a3feSDimitry Andric 
270cb14a3feSDimitry Andric   std::string NewName = std::string(Name);
271cb14a3feSDimitry Andric   if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
272cb14a3feSDimitry Andric     // For local symbols, prepend the main file name to distinguish them.
273cb14a3feSDimitry Andric     // Do not include the full path in the file name since there's no guarantee
274cb14a3feSDimitry Andric     // that it will stay the same, e.g., if the files are checked out from
275cb14a3feSDimitry Andric     // version control in different locations.
276cb14a3feSDimitry Andric     if (FileName.empty())
277cb14a3feSDimitry Andric       NewName = NewName.insert(0, "<unknown>:");
278cb14a3feSDimitry Andric     else
279cb14a3feSDimitry Andric       NewName = NewName.insert(0, FileName.str() + ":");
280cb14a3feSDimitry Andric   }
281cb14a3feSDimitry Andric   return NewName;
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric // Strip NumPrefix level of directory name from PathNameStr. If the number of
2850b57cec5SDimitry Andric // directory separators is less than NumPrefix, strip all the directories and
2860b57cec5SDimitry Andric // leave base file name only.
2870b57cec5SDimitry Andric static StringRef stripDirPrefix(StringRef PathNameStr, uint32_t NumPrefix) {
2880b57cec5SDimitry Andric   uint32_t Count = NumPrefix;
2890b57cec5SDimitry Andric   uint32_t Pos = 0, LastPos = 0;
290*0fca6ea1SDimitry Andric   for (const auto &CI : PathNameStr) {
2910b57cec5SDimitry Andric     ++Pos;
2920b57cec5SDimitry Andric     if (llvm::sys::path::is_separator(CI)) {
2930b57cec5SDimitry Andric       LastPos = Pos;
2940b57cec5SDimitry Andric       --Count;
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric     if (Count == 0)
2970b57cec5SDimitry Andric       break;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric   return PathNameStr.substr(LastPos);
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
3025f757f3fSDimitry Andric static StringRef getStrippedSourceFileName(const GlobalObject &GO) {
3035f757f3fSDimitry Andric   StringRef FileName(GO.getParent()->getSourceFileName());
3045f757f3fSDimitry Andric   uint32_t StripLevel = StaticFuncFullModulePrefix ? 0 : (uint32_t)-1;
3055f757f3fSDimitry Andric   if (StripLevel < StaticFuncStripDirNamePrefix)
3065f757f3fSDimitry Andric     StripLevel = StaticFuncStripDirNamePrefix;
3075f757f3fSDimitry Andric   if (StripLevel)
3085f757f3fSDimitry Andric     FileName = stripDirPrefix(FileName, StripLevel);
3095f757f3fSDimitry Andric   return FileName;
3105f757f3fSDimitry Andric }
3115f757f3fSDimitry Andric 
3121db9f3b2SDimitry Andric // The PGO name has the format [<filepath>;]<mangled-name> where <filepath>; is
3131db9f3b2SDimitry Andric // provided if linkage is local and is used to discriminate possibly identical
3141db9f3b2SDimitry Andric // mangled names. ";" is used because it is unlikely to be found in either
3151db9f3b2SDimitry Andric // <filepath> or <mangled-name>.
3165f757f3fSDimitry Andric //
3175f757f3fSDimitry Andric // Older compilers used getPGOFuncName() which has the format
3181db9f3b2SDimitry Andric // [<filepath>:]<mangled-name>. This caused trouble for Objective-C functions
3191db9f3b2SDimitry Andric // which commonly have :'s in their names. We still need to compute this name to
3201db9f3b2SDimitry Andric // lookup functions from profiles built by older compilers.
3215f757f3fSDimitry Andric static std::string
3225f757f3fSDimitry Andric getIRPGONameForGlobalObject(const GlobalObject &GO,
3235f757f3fSDimitry Andric                             GlobalValue::LinkageTypes Linkage,
3245f757f3fSDimitry Andric                             StringRef FileName) {
3251db9f3b2SDimitry Andric   return GlobalValue::getGlobalIdentifier(GO.getName(), Linkage, FileName);
3265f757f3fSDimitry Andric }
3275f757f3fSDimitry Andric 
3285f757f3fSDimitry Andric static std::optional<std::string> lookupPGONameFromMetadata(MDNode *MD) {
3295f757f3fSDimitry Andric   if (MD != nullptr) {
3305f757f3fSDimitry Andric     StringRef S = cast<MDString>(MD->getOperand(0))->getString();
3315f757f3fSDimitry Andric     return S.str();
3325f757f3fSDimitry Andric   }
3335f757f3fSDimitry Andric   return {};
3345f757f3fSDimitry Andric }
3355f757f3fSDimitry Andric 
3365f757f3fSDimitry Andric // Returns the PGO object name. This function has some special handling
3375f757f3fSDimitry Andric // when called in LTO optimization. The following only applies when calling in
3385f757f3fSDimitry Andric // LTO passes (when \c InLTO is true): LTO's internalization privatizes many
3395f757f3fSDimitry Andric // global linkage symbols. This happens after value profile annotation, but
3405f757f3fSDimitry Andric // those internal linkage functions should not have a source prefix.
3410b57cec5SDimitry Andric // Additionally, for ThinLTO mode, exported internal functions are promoted
3420b57cec5SDimitry Andric // and renamed. We need to ensure that the original internal PGO name is
3430b57cec5SDimitry Andric // used when computing the GUID that is compared against the profiled GUIDs.
3440b57cec5SDimitry Andric // To differentiate compiler generated internal symbols from original ones,
3450b57cec5SDimitry Andric // PGOFuncName meta data are created and attached to the original internal
3460b57cec5SDimitry Andric // symbols in the value profile annotation step
3470b57cec5SDimitry Andric // (PGOUseFunc::annotateIndirectCallSites). If a symbol does not have the meta
3480b57cec5SDimitry Andric // data, its original linkage must be non-internal.
3495f757f3fSDimitry Andric static std::string getIRPGOObjectName(const GlobalObject &GO, bool InLTO,
3505f757f3fSDimitry Andric                                       MDNode *PGONameMetadata) {
3515f757f3fSDimitry Andric   if (!InLTO) {
3525f757f3fSDimitry Andric     auto FileName = getStrippedSourceFileName(GO);
3535f757f3fSDimitry Andric     return getIRPGONameForGlobalObject(GO, GO.getLinkage(), FileName);
3545f757f3fSDimitry Andric   }
3555f757f3fSDimitry Andric 
3565f757f3fSDimitry Andric   // In LTO mode (when InLTO is true), first check if there is a meta data.
3575f757f3fSDimitry Andric   if (auto IRPGOFuncName = lookupPGONameFromMetadata(PGONameMetadata))
3585f757f3fSDimitry Andric     return *IRPGOFuncName;
3595f757f3fSDimitry Andric 
3605f757f3fSDimitry Andric   // If there is no meta data, the function must be a global before the value
3615f757f3fSDimitry Andric   // profile annotation pass. Its current linkage may be internal if it is
3625f757f3fSDimitry Andric   // internalized in LTO mode.
3635f757f3fSDimitry Andric   return getIRPGONameForGlobalObject(GO, GlobalValue::ExternalLinkage, "");
3645f757f3fSDimitry Andric }
3655f757f3fSDimitry Andric 
3665f757f3fSDimitry Andric // Returns the IRPGO function name and does special handling when called
3675f757f3fSDimitry Andric // in LTO optimization. See the comments of `getIRPGOObjectName` for details.
3685f757f3fSDimitry Andric std::string getIRPGOFuncName(const Function &F, bool InLTO) {
3695f757f3fSDimitry Andric   return getIRPGOObjectName(F, InLTO, getPGOFuncNameMetadata(F));
3705f757f3fSDimitry Andric }
3715f757f3fSDimitry Andric 
372cb14a3feSDimitry Andric // Please use getIRPGOFuncName for LLVM IR instrumentation. This function is
373cb14a3feSDimitry Andric // for front-end (Clang, etc) instrumentation.
374cb14a3feSDimitry Andric // The implementation is kept for profile matching from older profiles.
3755f757f3fSDimitry Andric // This is similar to `getIRPGOFuncName` except that this function calls
3765f757f3fSDimitry Andric // 'getPGOFuncName' to get a name and `getIRPGOFuncName` calls
3775f757f3fSDimitry Andric // 'getIRPGONameForGlobalObject'. See the difference between two callees in the
3785f757f3fSDimitry Andric // comments of `getIRPGONameForGlobalObject`.
3790b57cec5SDimitry Andric std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) {
3800b57cec5SDimitry Andric   if (!InLTO) {
3815f757f3fSDimitry Andric     auto FileName = getStrippedSourceFileName(F);
3820b57cec5SDimitry Andric     return getPGOFuncName(F.getName(), F.getLinkage(), FileName, Version);
3830b57cec5SDimitry Andric   }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   // In LTO mode (when InLTO is true), first check if there is a meta data.
3865f757f3fSDimitry Andric   if (auto PGOFuncName = lookupPGONameFromMetadata(getPGOFuncNameMetadata(F)))
3875f757f3fSDimitry Andric     return *PGOFuncName;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   // If there is no meta data, the function must be a global before the value
3900b57cec5SDimitry Andric   // profile annotation pass. Its current linkage may be internal if it is
3910b57cec5SDimitry Andric   // internalized in LTO mode.
3920b57cec5SDimitry Andric   return getPGOFuncName(F.getName(), GlobalValue::ExternalLinkage, "");
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
395*0fca6ea1SDimitry Andric std::string getPGOName(const GlobalVariable &V, bool InLTO) {
396*0fca6ea1SDimitry Andric   // PGONameMetadata should be set by compiler at profile use time
397*0fca6ea1SDimitry Andric   // and read by symtab creation to look up symbols corresponding to
398*0fca6ea1SDimitry Andric   // a MD5 hash.
399*0fca6ea1SDimitry Andric   return getIRPGOObjectName(V, InLTO, V.getMetadata(getPGONameMetadataName()));
400*0fca6ea1SDimitry Andric }
401*0fca6ea1SDimitry Andric 
402*0fca6ea1SDimitry Andric // See getIRPGOObjectName() for a discription of the format.
403*0fca6ea1SDimitry Andric std::pair<StringRef, StringRef> getParsedIRPGOName(StringRef IRPGOName) {
404*0fca6ea1SDimitry Andric   auto [FileName, MangledName] = IRPGOName.split(GlobalIdentifierDelimiter);
405*0fca6ea1SDimitry Andric   if (MangledName.empty())
406*0fca6ea1SDimitry Andric     return std::make_pair(StringRef(), IRPGOName);
407*0fca6ea1SDimitry Andric   return std::make_pair(FileName, MangledName);
4085f757f3fSDimitry Andric }
4095f757f3fSDimitry Andric 
4100b57cec5SDimitry Andric StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) {
4110b57cec5SDimitry Andric   if (FileName.empty())
4120b57cec5SDimitry Andric     return PGOFuncName;
413cb14a3feSDimitry Andric   // Drop the file name including ':' or ';'. See getIRPGONameForGlobalObject as
414cb14a3feSDimitry Andric   // well.
4155f757f3fSDimitry Andric   if (PGOFuncName.starts_with(FileName))
4160b57cec5SDimitry Andric     PGOFuncName = PGOFuncName.drop_front(FileName.size() + 1);
4170b57cec5SDimitry Andric   return PGOFuncName;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric // \p FuncName is the string used as profile lookup key for the function. A
4210b57cec5SDimitry Andric // symbol is created to hold the name. Return the legalized symbol name.
4220b57cec5SDimitry Andric std::string getPGOFuncNameVarName(StringRef FuncName,
4230b57cec5SDimitry Andric                                   GlobalValue::LinkageTypes Linkage) {
4245ffd83dbSDimitry Andric   std::string VarName = std::string(getInstrProfNameVarPrefix());
4250b57cec5SDimitry Andric   VarName += FuncName;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   if (!GlobalValue::isLocalLinkage(Linkage))
4280b57cec5SDimitry Andric     return VarName;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   // Now fix up illegal chars in local VarName that may upset the assembler.
4315f757f3fSDimitry Andric   const char InvalidChars[] = "-:;<>/\"'";
432*0fca6ea1SDimitry Andric   size_t FoundPos = VarName.find_first_of(InvalidChars);
433*0fca6ea1SDimitry Andric   while (FoundPos != std::string::npos) {
434*0fca6ea1SDimitry Andric     VarName[FoundPos] = '_';
435*0fca6ea1SDimitry Andric     FoundPos = VarName.find_first_of(InvalidChars, FoundPos + 1);
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric   return VarName;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric GlobalVariable *createPGOFuncNameVar(Module &M,
4410b57cec5SDimitry Andric                                      GlobalValue::LinkageTypes Linkage,
4420b57cec5SDimitry Andric                                      StringRef PGOFuncName) {
4430b57cec5SDimitry Andric   // We generally want to match the function's linkage, but available_externally
4440b57cec5SDimitry Andric   // and extern_weak both have the wrong semantics, and anything that doesn't
4450b57cec5SDimitry Andric   // need to link across compilation units doesn't need to be visible at all.
4460b57cec5SDimitry Andric   if (Linkage == GlobalValue::ExternalWeakLinkage)
4470b57cec5SDimitry Andric     Linkage = GlobalValue::LinkOnceAnyLinkage;
4480b57cec5SDimitry Andric   else if (Linkage == GlobalValue::AvailableExternallyLinkage)
4490b57cec5SDimitry Andric     Linkage = GlobalValue::LinkOnceODRLinkage;
4500b57cec5SDimitry Andric   else if (Linkage == GlobalValue::InternalLinkage ||
4510b57cec5SDimitry Andric            Linkage == GlobalValue::ExternalLinkage)
4520b57cec5SDimitry Andric     Linkage = GlobalValue::PrivateLinkage;
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   auto *Value =
4550b57cec5SDimitry Andric       ConstantDataArray::getString(M.getContext(), PGOFuncName, false);
456*0fca6ea1SDimitry Andric   auto *FuncNameVar =
4570b57cec5SDimitry Andric       new GlobalVariable(M, Value->getType(), true, Linkage, Value,
4580b57cec5SDimitry Andric                          getPGOFuncNameVarName(PGOFuncName, Linkage));
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   // Hide the symbol so that we correctly get a copy for each executable.
4610b57cec5SDimitry Andric   if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
4620b57cec5SDimitry Andric     FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   return FuncNameVar;
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) {
4680b57cec5SDimitry Andric   return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric Error InstrProfSymtab::create(Module &M, bool InLTO) {
4720b57cec5SDimitry Andric   for (Function &F : M) {
4730b57cec5SDimitry Andric     // Function may not have a name: like using asm("") to overwrite the name.
4740b57cec5SDimitry Andric     // Ignore in this case.
4750b57cec5SDimitry Andric     if (!F.hasName())
4760b57cec5SDimitry Andric       continue;
4775f757f3fSDimitry Andric     if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO)))
4785f757f3fSDimitry Andric       return E;
4795f757f3fSDimitry Andric     // Also use getPGOFuncName() so that we can find records from older profiles
4805f757f3fSDimitry Andric     if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO)))
4815f757f3fSDimitry Andric       return E;
4825f757f3fSDimitry Andric   }
483*0fca6ea1SDimitry Andric 
484*0fca6ea1SDimitry Andric   SmallVector<MDNode *, 2> Types;
485*0fca6ea1SDimitry Andric   for (GlobalVariable &G : M.globals()) {
486*0fca6ea1SDimitry Andric     if (!G.hasName() || !G.hasMetadata(LLVMContext::MD_type))
487*0fca6ea1SDimitry Andric       continue;
488*0fca6ea1SDimitry Andric     if (Error E = addVTableWithName(G, getPGOName(G, InLTO)))
489*0fca6ea1SDimitry Andric       return E;
490*0fca6ea1SDimitry Andric   }
491*0fca6ea1SDimitry Andric 
4925f757f3fSDimitry Andric   Sorted = false;
4935f757f3fSDimitry Andric   finalizeSymtab();
4945f757f3fSDimitry Andric   return Error::success();
4955f757f3fSDimitry Andric }
4965f757f3fSDimitry Andric 
497*0fca6ea1SDimitry Andric Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
498*0fca6ea1SDimitry Andric                                          StringRef VTablePGOName) {
499*0fca6ea1SDimitry Andric   auto NameToGUIDMap = [&](StringRef Name) -> Error {
500*0fca6ea1SDimitry Andric     if (Error E = addSymbolName(Name))
501*0fca6ea1SDimitry Andric       return E;
502*0fca6ea1SDimitry Andric 
503*0fca6ea1SDimitry Andric     bool Inserted = true;
504*0fca6ea1SDimitry Andric     std::tie(std::ignore, Inserted) =
505*0fca6ea1SDimitry Andric         MD5VTableMap.try_emplace(GlobalValue::getGUID(Name), &VTable);
506*0fca6ea1SDimitry Andric     if (!Inserted)
507*0fca6ea1SDimitry Andric       LLVM_DEBUG(dbgs() << "GUID conflict within one module");
508*0fca6ea1SDimitry Andric     return Error::success();
509*0fca6ea1SDimitry Andric   };
510*0fca6ea1SDimitry Andric   if (Error E = NameToGUIDMap(VTablePGOName))
511*0fca6ea1SDimitry Andric     return E;
512*0fca6ea1SDimitry Andric 
513*0fca6ea1SDimitry Andric   StringRef CanonicalName = getCanonicalName(VTablePGOName);
514*0fca6ea1SDimitry Andric   if (CanonicalName != VTablePGOName)
515*0fca6ea1SDimitry Andric     return NameToGUIDMap(CanonicalName);
516*0fca6ea1SDimitry Andric 
517*0fca6ea1SDimitry Andric   return Error::success();
518*0fca6ea1SDimitry Andric }
519*0fca6ea1SDimitry Andric 
5205f757f3fSDimitry Andric /// \c NameStrings is a string composed of one of more possibly encoded
5215f757f3fSDimitry Andric /// sub-strings. The substrings are separated by 0 or more zero bytes. This
5225f757f3fSDimitry Andric /// method decodes the string and calls `NameCallback` for each substring.
5235f757f3fSDimitry Andric static Error
5245f757f3fSDimitry Andric readAndDecodeStrings(StringRef NameStrings,
5255f757f3fSDimitry Andric                      std::function<Error(StringRef)> NameCallback) {
5265f757f3fSDimitry Andric   const uint8_t *P = NameStrings.bytes_begin();
5275f757f3fSDimitry Andric   const uint8_t *EndP = NameStrings.bytes_end();
5285f757f3fSDimitry Andric   while (P < EndP) {
5295f757f3fSDimitry Andric     uint32_t N;
5305f757f3fSDimitry Andric     uint64_t UncompressedSize = decodeULEB128(P, &N);
5315f757f3fSDimitry Andric     P += N;
5325f757f3fSDimitry Andric     uint64_t CompressedSize = decodeULEB128(P, &N);
5335f757f3fSDimitry Andric     P += N;
534*0fca6ea1SDimitry Andric     const bool IsCompressed = (CompressedSize != 0);
5355f757f3fSDimitry Andric     SmallVector<uint8_t, 128> UncompressedNameStrings;
5365f757f3fSDimitry Andric     StringRef NameStrings;
537*0fca6ea1SDimitry Andric     if (IsCompressed) {
5385f757f3fSDimitry Andric       if (!llvm::compression::zlib::isAvailable())
5395f757f3fSDimitry Andric         return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
5405f757f3fSDimitry Andric 
5415f757f3fSDimitry Andric       if (Error E = compression::zlib::decompress(ArrayRef(P, CompressedSize),
5425f757f3fSDimitry Andric                                                   UncompressedNameStrings,
5435f757f3fSDimitry Andric                                                   UncompressedSize)) {
5445f757f3fSDimitry Andric         consumeError(std::move(E));
5455f757f3fSDimitry Andric         return make_error<InstrProfError>(instrprof_error::uncompress_failed);
5465f757f3fSDimitry Andric       }
5475f757f3fSDimitry Andric       P += CompressedSize;
5485f757f3fSDimitry Andric       NameStrings = toStringRef(UncompressedNameStrings);
5495f757f3fSDimitry Andric     } else {
5505f757f3fSDimitry Andric       NameStrings =
5515f757f3fSDimitry Andric           StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
5525f757f3fSDimitry Andric       P += UncompressedSize;
5535f757f3fSDimitry Andric     }
5545f757f3fSDimitry Andric     // Now parse the name strings.
5555f757f3fSDimitry Andric     SmallVector<StringRef, 0> Names;
5565f757f3fSDimitry Andric     NameStrings.split(Names, getInstrProfNameSeparator());
5575f757f3fSDimitry Andric     for (StringRef &Name : Names)
5585f757f3fSDimitry Andric       if (Error E = NameCallback(Name))
5595f757f3fSDimitry Andric         return E;
5605f757f3fSDimitry Andric 
5615f757f3fSDimitry Andric     while (P < EndP && *P == 0)
5625f757f3fSDimitry Andric       P++;
5635f757f3fSDimitry Andric   }
5645f757f3fSDimitry Andric   return Error::success();
5655f757f3fSDimitry Andric }
5665f757f3fSDimitry Andric 
5675f757f3fSDimitry Andric Error InstrProfSymtab::create(StringRef NameStrings) {
5685f757f3fSDimitry Andric   return readAndDecodeStrings(
5695f757f3fSDimitry Andric       NameStrings,
5705f757f3fSDimitry Andric       std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1));
5715f757f3fSDimitry Andric }
5725f757f3fSDimitry Andric 
573*0fca6ea1SDimitry Andric Error InstrProfSymtab::create(StringRef FuncNameStrings,
574*0fca6ea1SDimitry Andric                               StringRef VTableNameStrings) {
575*0fca6ea1SDimitry Andric   if (Error E = readAndDecodeStrings(FuncNameStrings,
576*0fca6ea1SDimitry Andric                                      std::bind(&InstrProfSymtab::addFuncName,
577*0fca6ea1SDimitry Andric                                                this, std::placeholders::_1)))
5780b57cec5SDimitry Andric     return E;
579*0fca6ea1SDimitry Andric 
580*0fca6ea1SDimitry Andric   return readAndDecodeStrings(
581*0fca6ea1SDimitry Andric       VTableNameStrings,
582*0fca6ea1SDimitry Andric       std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1));
583*0fca6ea1SDimitry Andric }
584*0fca6ea1SDimitry Andric 
585*0fca6ea1SDimitry Andric Error InstrProfSymtab::initVTableNamesFromCompressedStrings(
586*0fca6ea1SDimitry Andric     StringRef CompressedVTableStrings) {
587*0fca6ea1SDimitry Andric   return readAndDecodeStrings(
588*0fca6ea1SDimitry Andric       CompressedVTableStrings,
589*0fca6ea1SDimitry Andric       std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1));
590*0fca6ea1SDimitry Andric }
591*0fca6ea1SDimitry Andric 
592*0fca6ea1SDimitry Andric StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) {
5930b57cec5SDimitry Andric   // In ThinLTO, local function may have been promoted to global and have
594fe6060f1SDimitry Andric   // suffix ".llvm." added to the function name. We need to add the
595fe6060f1SDimitry Andric   // stripped function name to the symbol table so that we can find a match
596fe6060f1SDimitry Andric   // from profile.
597fe6060f1SDimitry Andric   //
598*0fca6ea1SDimitry Andric   // ".__uniq." suffix is used to differentiate internal linkage functions in
599*0fca6ea1SDimitry Andric   // different modules and should be kept. This is the only suffix with the
600*0fca6ea1SDimitry Andric   // pattern ".xxx" which is kept before matching, other suffixes similar as
601*0fca6ea1SDimitry Andric   // ".llvm." will be stripped.
602fe6060f1SDimitry Andric   const std::string UniqSuffix = ".__uniq.";
603*0fca6ea1SDimitry Andric   size_t Pos = PGOName.find(UniqSuffix);
604*0fca6ea1SDimitry Andric   if (Pos != StringRef::npos)
605*0fca6ea1SDimitry Andric     Pos += UniqSuffix.length();
606fe6060f1SDimitry Andric   else
607*0fca6ea1SDimitry Andric     Pos = 0;
608*0fca6ea1SDimitry Andric 
609*0fca6ea1SDimitry Andric   // Search '.' after ".__uniq." if ".__uniq." exists, otherwise search '.' from
610*0fca6ea1SDimitry Andric   // the beginning.
611*0fca6ea1SDimitry Andric   Pos = PGOName.find('.', Pos);
612*0fca6ea1SDimitry Andric   if (Pos != StringRef::npos && Pos != 0)
613*0fca6ea1SDimitry Andric     return PGOName.substr(0, Pos);
614*0fca6ea1SDimitry Andric 
615*0fca6ea1SDimitry Andric   return PGOName;
6160b57cec5SDimitry Andric }
617*0fca6ea1SDimitry Andric 
618*0fca6ea1SDimitry Andric Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName) {
619*0fca6ea1SDimitry Andric   auto NameToGUIDMap = [&](StringRef Name) -> Error {
620*0fca6ea1SDimitry Andric     if (Error E = addFuncName(Name))
621*0fca6ea1SDimitry Andric       return E;
622*0fca6ea1SDimitry Andric     MD5FuncMap.emplace_back(Function::getGUID(Name), &F);
6230b57cec5SDimitry Andric     return Error::success();
624*0fca6ea1SDimitry Andric   };
625*0fca6ea1SDimitry Andric   if (Error E = NameToGUIDMap(PGOFuncName))
626*0fca6ea1SDimitry Andric     return E;
627*0fca6ea1SDimitry Andric 
628*0fca6ea1SDimitry Andric   StringRef CanonicalFuncName = getCanonicalName(PGOFuncName);
629*0fca6ea1SDimitry Andric   if (CanonicalFuncName != PGOFuncName)
630*0fca6ea1SDimitry Andric     return NameToGUIDMap(CanonicalFuncName);
631*0fca6ea1SDimitry Andric 
632*0fca6ea1SDimitry Andric   return Error::success();
633*0fca6ea1SDimitry Andric }
634*0fca6ea1SDimitry Andric 
635*0fca6ea1SDimitry Andric uint64_t InstrProfSymtab::getVTableHashFromAddress(uint64_t Address) {
636*0fca6ea1SDimitry Andric   // Given a runtime address, look up the hash value in the interval map, and
637*0fca6ea1SDimitry Andric   // fallback to value 0 if a hash value is not found.
638*0fca6ea1SDimitry Andric   return VTableAddrMap.lookup(Address, 0);
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric uint64_t InstrProfSymtab::getFunctionHashFromAddress(uint64_t Address) {
6420b57cec5SDimitry Andric   finalizeSymtab();
6430b57cec5SDimitry Andric   auto It = partition_point(AddrToMD5Map, [=](std::pair<uint64_t, uint64_t> A) {
6440b57cec5SDimitry Andric     return A.first < Address;
6450b57cec5SDimitry Andric   });
6460b57cec5SDimitry Andric   // Raw function pointer collected by value profiler may be from
6470b57cec5SDimitry Andric   // external functions that are not instrumented. They won't have
6480b57cec5SDimitry Andric   // mapping data to be used by the deserializer. Force the value to
6490b57cec5SDimitry Andric   // be 0 in this case.
6500b57cec5SDimitry Andric   if (It != AddrToMD5Map.end() && It->first == Address)
6510b57cec5SDimitry Andric     return (uint64_t)It->second;
6520b57cec5SDimitry Andric   return 0;
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
65506c3fb27SDimitry Andric void InstrProfSymtab::dumpNames(raw_ostream &OS) const {
65606c3fb27SDimitry Andric   SmallVector<StringRef, 0> Sorted(NameTab.keys());
65706c3fb27SDimitry Andric   llvm::sort(Sorted);
65806c3fb27SDimitry Andric   for (StringRef S : Sorted)
65906c3fb27SDimitry Andric     OS << S << '\n';
66006c3fb27SDimitry Andric }
66106c3fb27SDimitry Andric 
6625f757f3fSDimitry Andric Error collectGlobalObjectNameStrings(ArrayRef<std::string> NameStrs,
663*0fca6ea1SDimitry Andric                                      bool DoCompression, std::string &Result) {
6640b57cec5SDimitry Andric   assert(!NameStrs.empty() && "No name data to emit");
6650b57cec5SDimitry Andric 
6665f757f3fSDimitry Andric   uint8_t Header[20], *P = Header;
6670b57cec5SDimitry Andric   std::string UncompressedNameStrings =
6680b57cec5SDimitry Andric       join(NameStrs.begin(), NameStrs.end(), getInstrProfNameSeparator());
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   assert(StringRef(UncompressedNameStrings)
6710b57cec5SDimitry Andric                  .count(getInstrProfNameSeparator()) == (NameStrs.size() - 1) &&
6720b57cec5SDimitry Andric          "PGO name is invalid (contains separator token)");
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   unsigned EncLen = encodeULEB128(UncompressedNameStrings.length(), P);
6750b57cec5SDimitry Andric   P += EncLen;
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   auto WriteStringToResult = [&](size_t CompressedLen, StringRef InputStr) {
6780b57cec5SDimitry Andric     EncLen = encodeULEB128(CompressedLen, P);
6790b57cec5SDimitry Andric     P += EncLen;
6800b57cec5SDimitry Andric     char *HeaderStr = reinterpret_cast<char *>(&Header[0]);
6810b57cec5SDimitry Andric     unsigned HeaderLen = P - &Header[0];
6820b57cec5SDimitry Andric     Result.append(HeaderStr, HeaderLen);
6830b57cec5SDimitry Andric     Result += InputStr;
6840b57cec5SDimitry Andric     return Error::success();
6850b57cec5SDimitry Andric   };
6860b57cec5SDimitry Andric 
687*0fca6ea1SDimitry Andric   if (!DoCompression) {
6880b57cec5SDimitry Andric     return WriteStringToResult(0, UncompressedNameStrings);
6890b57cec5SDimitry Andric   }
6900b57cec5SDimitry Andric 
691753f127fSDimitry Andric   SmallVector<uint8_t, 128> CompressedNameStrings;
692753f127fSDimitry Andric   compression::zlib::compress(arrayRefFromStringRef(UncompressedNameStrings),
693753f127fSDimitry Andric                               CompressedNameStrings,
694753f127fSDimitry Andric                               compression::zlib::BestSizeCompression);
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   return WriteStringToResult(CompressedNameStrings.size(),
697753f127fSDimitry Andric                              toStringRef(CompressedNameStrings));
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar) {
7010b57cec5SDimitry Andric   auto *Arr = cast<ConstantDataArray>(NameVar->getInitializer());
7020b57cec5SDimitry Andric   StringRef NameStr =
7030b57cec5SDimitry Andric       Arr->isCString() ? Arr->getAsCString() : Arr->getAsString();
7040b57cec5SDimitry Andric   return NameStr;
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
708*0fca6ea1SDimitry Andric                                 std::string &Result, bool DoCompression) {
7090b57cec5SDimitry Andric   std::vector<std::string> NameStrs;
7100b57cec5SDimitry Andric   for (auto *NameVar : NameVars) {
7115ffd83dbSDimitry Andric     NameStrs.push_back(std::string(getPGOFuncNameVarInitializer(NameVar)));
7120b57cec5SDimitry Andric   }
7135f757f3fSDimitry Andric   return collectGlobalObjectNameStrings(
714*0fca6ea1SDimitry Andric       NameStrs, compression::zlib::isAvailable() && DoCompression, Result);
715*0fca6ea1SDimitry Andric }
716*0fca6ea1SDimitry Andric 
717*0fca6ea1SDimitry Andric Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables,
718*0fca6ea1SDimitry Andric                            std::string &Result, bool DoCompression) {
719*0fca6ea1SDimitry Andric   std::vector<std::string> VTableNameStrs;
720*0fca6ea1SDimitry Andric   for (auto *VTable : VTables)
721*0fca6ea1SDimitry Andric     VTableNameStrs.push_back(getPGOName(*VTable));
722*0fca6ea1SDimitry Andric   return collectGlobalObjectNameStrings(
723*0fca6ea1SDimitry Andric       VTableNameStrs, compression::zlib::isAvailable() && DoCompression,
724*0fca6ea1SDimitry Andric       Result);
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7278bcb0991SDimitry Andric void InstrProfRecord::accumulateCounts(CountSumOrPercent &Sum) const {
7280b57cec5SDimitry Andric   uint64_t FuncSum = 0;
7290b57cec5SDimitry Andric   Sum.NumEntries += Counts.size();
7300eae32dcSDimitry Andric   for (uint64_t Count : Counts)
7310eae32dcSDimitry Andric     FuncSum += Count;
7320b57cec5SDimitry Andric   Sum.CountSum += FuncSum;
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric   for (uint32_t VK = IPVK_First; VK <= IPVK_Last; ++VK) {
7350b57cec5SDimitry Andric     uint64_t KindSum = 0;
7360b57cec5SDimitry Andric     uint32_t NumValueSites = getNumValueSites(VK);
7370b57cec5SDimitry Andric     for (size_t I = 0; I < NumValueSites; ++I) {
738*0fca6ea1SDimitry Andric       for (const auto &V : getValueArrayForSite(VK, I))
739*0fca6ea1SDimitry Andric         KindSum += V.Count;
7400b57cec5SDimitry Andric     }
7410b57cec5SDimitry Andric     Sum.ValueCounts[VK] += KindSum;
7420b57cec5SDimitry Andric   }
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric void InstrProfValueSiteRecord::overlap(InstrProfValueSiteRecord &Input,
7460b57cec5SDimitry Andric                                        uint32_t ValueKind,
7470b57cec5SDimitry Andric                                        OverlapStats &Overlap,
7480b57cec5SDimitry Andric                                        OverlapStats &FuncLevelOverlap) {
7490b57cec5SDimitry Andric   this->sortByTargetValues();
7500b57cec5SDimitry Andric   Input.sortByTargetValues();
7510b57cec5SDimitry Andric   double Score = 0.0f, FuncLevelScore = 0.0f;
7520b57cec5SDimitry Andric   auto I = ValueData.begin();
7530b57cec5SDimitry Andric   auto IE = ValueData.end();
7540b57cec5SDimitry Andric   auto J = Input.ValueData.begin();
7550b57cec5SDimitry Andric   auto JE = Input.ValueData.end();
7560b57cec5SDimitry Andric   while (I != IE && J != JE) {
7570b57cec5SDimitry Andric     if (I->Value == J->Value) {
7580b57cec5SDimitry Andric       Score += OverlapStats::score(I->Count, J->Count,
7590b57cec5SDimitry Andric                                    Overlap.Base.ValueCounts[ValueKind],
7600b57cec5SDimitry Andric                                    Overlap.Test.ValueCounts[ValueKind]);
7610b57cec5SDimitry Andric       FuncLevelScore += OverlapStats::score(
7620b57cec5SDimitry Andric           I->Count, J->Count, FuncLevelOverlap.Base.ValueCounts[ValueKind],
7630b57cec5SDimitry Andric           FuncLevelOverlap.Test.ValueCounts[ValueKind]);
7640b57cec5SDimitry Andric       ++I;
7650b57cec5SDimitry Andric     } else if (I->Value < J->Value) {
7660b57cec5SDimitry Andric       ++I;
7670b57cec5SDimitry Andric       continue;
7680b57cec5SDimitry Andric     }
7690b57cec5SDimitry Andric     ++J;
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric   Overlap.Overlap.ValueCounts[ValueKind] += Score;
7720b57cec5SDimitry Andric   FuncLevelOverlap.Overlap.ValueCounts[ValueKind] += FuncLevelScore;
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric // Return false on mismatch.
7760b57cec5SDimitry Andric void InstrProfRecord::overlapValueProfData(uint32_t ValueKind,
7770b57cec5SDimitry Andric                                            InstrProfRecord &Other,
7780b57cec5SDimitry Andric                                            OverlapStats &Overlap,
7790b57cec5SDimitry Andric                                            OverlapStats &FuncLevelOverlap) {
7800b57cec5SDimitry Andric   uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
7810b57cec5SDimitry Andric   assert(ThisNumValueSites == Other.getNumValueSites(ValueKind));
7820b57cec5SDimitry Andric   if (!ThisNumValueSites)
7830b57cec5SDimitry Andric     return;
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
7860b57cec5SDimitry Andric       getOrCreateValueSitesForKind(ValueKind);
7870b57cec5SDimitry Andric   MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
7880b57cec5SDimitry Andric       Other.getValueSitesForKind(ValueKind);
7890b57cec5SDimitry Andric   for (uint32_t I = 0; I < ThisNumValueSites; I++)
7900b57cec5SDimitry Andric     ThisSiteRecords[I].overlap(OtherSiteRecords[I], ValueKind, Overlap,
7910b57cec5SDimitry Andric                                FuncLevelOverlap);
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric void InstrProfRecord::overlap(InstrProfRecord &Other, OverlapStats &Overlap,
7950b57cec5SDimitry Andric                               OverlapStats &FuncLevelOverlap,
7960b57cec5SDimitry Andric                               uint64_t ValueCutoff) {
7970b57cec5SDimitry Andric   // FuncLevel CountSum for other should already computed and nonzero.
7980b57cec5SDimitry Andric   assert(FuncLevelOverlap.Test.CountSum >= 1.0f);
7998bcb0991SDimitry Andric   accumulateCounts(FuncLevelOverlap.Base);
8000b57cec5SDimitry Andric   bool Mismatch = (Counts.size() != Other.Counts.size());
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   // Check if the value profiles mismatch.
8030b57cec5SDimitry Andric   if (!Mismatch) {
8040b57cec5SDimitry Andric     for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
8050b57cec5SDimitry Andric       uint32_t ThisNumValueSites = getNumValueSites(Kind);
8060b57cec5SDimitry Andric       uint32_t OtherNumValueSites = Other.getNumValueSites(Kind);
8070b57cec5SDimitry Andric       if (ThisNumValueSites != OtherNumValueSites) {
8080b57cec5SDimitry Andric         Mismatch = true;
8090b57cec5SDimitry Andric         break;
8100b57cec5SDimitry Andric       }
8110b57cec5SDimitry Andric     }
8120b57cec5SDimitry Andric   }
8130b57cec5SDimitry Andric   if (Mismatch) {
8140b57cec5SDimitry Andric     Overlap.addOneMismatch(FuncLevelOverlap.Test);
8150b57cec5SDimitry Andric     return;
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   // Compute overlap for value counts.
8190b57cec5SDimitry Andric   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
8200b57cec5SDimitry Andric     overlapValueProfData(Kind, Other, Overlap, FuncLevelOverlap);
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric   double Score = 0.0;
8230b57cec5SDimitry Andric   uint64_t MaxCount = 0;
8240b57cec5SDimitry Andric   // Compute overlap for edge counts.
8250b57cec5SDimitry Andric   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
8260b57cec5SDimitry Andric     Score += OverlapStats::score(Counts[I], Other.Counts[I],
8270b57cec5SDimitry Andric                                  Overlap.Base.CountSum, Overlap.Test.CountSum);
8280b57cec5SDimitry Andric     MaxCount = std::max(Other.Counts[I], MaxCount);
8290b57cec5SDimitry Andric   }
8300b57cec5SDimitry Andric   Overlap.Overlap.CountSum += Score;
8310b57cec5SDimitry Andric   Overlap.Overlap.NumEntries += 1;
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric   if (MaxCount >= ValueCutoff) {
8340b57cec5SDimitry Andric     double FuncScore = 0.0;
8350b57cec5SDimitry Andric     for (size_t I = 0, E = Other.Counts.size(); I < E; ++I)
8360b57cec5SDimitry Andric       FuncScore += OverlapStats::score(Counts[I], Other.Counts[I],
8370b57cec5SDimitry Andric                                        FuncLevelOverlap.Base.CountSum,
8380b57cec5SDimitry Andric                                        FuncLevelOverlap.Test.CountSum);
8390b57cec5SDimitry Andric     FuncLevelOverlap.Overlap.CountSum = FuncScore;
8400b57cec5SDimitry Andric     FuncLevelOverlap.Overlap.NumEntries = Other.Counts.size();
8410b57cec5SDimitry Andric     FuncLevelOverlap.Valid = true;
8420b57cec5SDimitry Andric   }
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
8460b57cec5SDimitry Andric                                      uint64_t Weight,
8470b57cec5SDimitry Andric                                      function_ref<void(instrprof_error)> Warn) {
8480b57cec5SDimitry Andric   this->sortByTargetValues();
8490b57cec5SDimitry Andric   Input.sortByTargetValues();
8500b57cec5SDimitry Andric   auto I = ValueData.begin();
8510b57cec5SDimitry Andric   auto IE = ValueData.end();
852*0fca6ea1SDimitry Andric   std::vector<InstrProfValueData> Merged;
853*0fca6ea1SDimitry Andric   Merged.reserve(std::max(ValueData.size(), Input.ValueData.size()));
8544824e7fdSDimitry Andric   for (const InstrProfValueData &J : Input.ValueData) {
855*0fca6ea1SDimitry Andric     while (I != IE && I->Value < J.Value) {
856*0fca6ea1SDimitry Andric       Merged.push_back(*I);
8570b57cec5SDimitry Andric       ++I;
858*0fca6ea1SDimitry Andric     }
8594824e7fdSDimitry Andric     if (I != IE && I->Value == J.Value) {
8600b57cec5SDimitry Andric       bool Overflowed;
8614824e7fdSDimitry Andric       I->Count = SaturatingMultiplyAdd(J.Count, Weight, I->Count, &Overflowed);
8620b57cec5SDimitry Andric       if (Overflowed)
8630b57cec5SDimitry Andric         Warn(instrprof_error::counter_overflow);
864*0fca6ea1SDimitry Andric       Merged.push_back(*I);
8650b57cec5SDimitry Andric       ++I;
8660b57cec5SDimitry Andric       continue;
8670b57cec5SDimitry Andric     }
868*0fca6ea1SDimitry Andric     Merged.push_back(J);
8690b57cec5SDimitry Andric   }
870*0fca6ea1SDimitry Andric   Merged.insert(Merged.end(), I, IE);
871*0fca6ea1SDimitry Andric   ValueData = std::move(Merged);
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric 
874e8d8bef9SDimitry Andric void InstrProfValueSiteRecord::scale(uint64_t N, uint64_t D,
8750b57cec5SDimitry Andric                                      function_ref<void(instrprof_error)> Warn) {
8760eae32dcSDimitry Andric   for (InstrProfValueData &I : ValueData) {
8770b57cec5SDimitry Andric     bool Overflowed;
8780eae32dcSDimitry Andric     I.Count = SaturatingMultiply(I.Count, N, &Overflowed) / D;
8790b57cec5SDimitry Andric     if (Overflowed)
8800b57cec5SDimitry Andric       Warn(instrprof_error::counter_overflow);
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric // Merge Value Profile data from Src record to this record for ValueKind.
8850b57cec5SDimitry Andric // Scale merged value counts by \p Weight.
8860b57cec5SDimitry Andric void InstrProfRecord::mergeValueProfData(
8870b57cec5SDimitry Andric     uint32_t ValueKind, InstrProfRecord &Src, uint64_t Weight,
8880b57cec5SDimitry Andric     function_ref<void(instrprof_error)> Warn) {
8890b57cec5SDimitry Andric   uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
8900b57cec5SDimitry Andric   uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
8910b57cec5SDimitry Andric   if (ThisNumValueSites != OtherNumValueSites) {
8920b57cec5SDimitry Andric     Warn(instrprof_error::value_site_count_mismatch);
8930b57cec5SDimitry Andric     return;
8940b57cec5SDimitry Andric   }
8950b57cec5SDimitry Andric   if (!ThisNumValueSites)
8960b57cec5SDimitry Andric     return;
8970b57cec5SDimitry Andric   std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
8980b57cec5SDimitry Andric       getOrCreateValueSitesForKind(ValueKind);
8990b57cec5SDimitry Andric   MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
9000b57cec5SDimitry Andric       Src.getValueSitesForKind(ValueKind);
9010b57cec5SDimitry Andric   for (uint32_t I = 0; I < ThisNumValueSites; I++)
9020b57cec5SDimitry Andric     ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight, Warn);
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
9060b57cec5SDimitry Andric                             function_ref<void(instrprof_error)> Warn) {
9070b57cec5SDimitry Andric   // If the number of counters doesn't match we either have bad data
9080b57cec5SDimitry Andric   // or a hash collision.
9090b57cec5SDimitry Andric   if (Counts.size() != Other.Counts.size()) {
9100b57cec5SDimitry Andric     Warn(instrprof_error::count_mismatch);
9110b57cec5SDimitry Andric     return;
9120b57cec5SDimitry Andric   }
9130b57cec5SDimitry Andric 
914bdd1243dSDimitry Andric   // Special handling of the first count as the PseudoCount.
915bdd1243dSDimitry Andric   CountPseudoKind OtherKind = Other.getCountPseudoKind();
916bdd1243dSDimitry Andric   CountPseudoKind ThisKind = getCountPseudoKind();
917bdd1243dSDimitry Andric   if (OtherKind != NotPseudo || ThisKind != NotPseudo) {
918bdd1243dSDimitry Andric     // We don't allow the merge of a profile with pseudo counts and
919bdd1243dSDimitry Andric     // a normal profile (i.e. without pesudo counts).
920bdd1243dSDimitry Andric     // Profile supplimenation should be done after the profile merge.
921bdd1243dSDimitry Andric     if (OtherKind == NotPseudo || ThisKind == NotPseudo) {
922bdd1243dSDimitry Andric       Warn(instrprof_error::count_mismatch);
923bdd1243dSDimitry Andric       return;
924bdd1243dSDimitry Andric     }
925bdd1243dSDimitry Andric     if (OtherKind == PseudoHot || ThisKind == PseudoHot)
926bdd1243dSDimitry Andric       setPseudoCount(PseudoHot);
927bdd1243dSDimitry Andric     else
928bdd1243dSDimitry Andric       setPseudoCount(PseudoWarm);
929bdd1243dSDimitry Andric     return;
930bdd1243dSDimitry Andric   }
931bdd1243dSDimitry Andric 
9320b57cec5SDimitry Andric   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
9330b57cec5SDimitry Andric     bool Overflowed;
934bdd1243dSDimitry Andric     uint64_t Value =
9350b57cec5SDimitry Andric         SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
936bdd1243dSDimitry Andric     if (Value > getInstrMaxCountValue()) {
937bdd1243dSDimitry Andric       Value = getInstrMaxCountValue();
938bdd1243dSDimitry Andric       Overflowed = true;
939bdd1243dSDimitry Andric     }
940bdd1243dSDimitry Andric     Counts[I] = Value;
9410b57cec5SDimitry Andric     if (Overflowed)
9420b57cec5SDimitry Andric       Warn(instrprof_error::counter_overflow);
9430b57cec5SDimitry Andric   }
9440b57cec5SDimitry Andric 
9455f757f3fSDimitry Andric   // If the number of bitmap bytes doesn't match we either have bad data
9465f757f3fSDimitry Andric   // or a hash collision.
9475f757f3fSDimitry Andric   if (BitmapBytes.size() != Other.BitmapBytes.size()) {
9485f757f3fSDimitry Andric     Warn(instrprof_error::bitmap_mismatch);
9495f757f3fSDimitry Andric     return;
9505f757f3fSDimitry Andric   }
9515f757f3fSDimitry Andric 
9525f757f3fSDimitry Andric   // Bitmap bytes are merged by simply ORing them together.
9535f757f3fSDimitry Andric   for (size_t I = 0, E = Other.BitmapBytes.size(); I < E; ++I) {
9545f757f3fSDimitry Andric     BitmapBytes[I] = Other.BitmapBytes[I] | BitmapBytes[I];
9555f757f3fSDimitry Andric   }
9565f757f3fSDimitry Andric 
9570b57cec5SDimitry Andric   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
9580b57cec5SDimitry Andric     mergeValueProfData(Kind, Other, Weight, Warn);
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric void InstrProfRecord::scaleValueProfData(
962e8d8bef9SDimitry Andric     uint32_t ValueKind, uint64_t N, uint64_t D,
9630b57cec5SDimitry Andric     function_ref<void(instrprof_error)> Warn) {
9640b57cec5SDimitry Andric   for (auto &R : getValueSitesForKind(ValueKind))
965e8d8bef9SDimitry Andric     R.scale(N, D, Warn);
9660b57cec5SDimitry Andric }
9670b57cec5SDimitry Andric 
968e8d8bef9SDimitry Andric void InstrProfRecord::scale(uint64_t N, uint64_t D,
9690b57cec5SDimitry Andric                             function_ref<void(instrprof_error)> Warn) {
970e8d8bef9SDimitry Andric   assert(D != 0 && "D cannot be 0");
9710b57cec5SDimitry Andric   for (auto &Count : this->Counts) {
9720b57cec5SDimitry Andric     bool Overflowed;
973e8d8bef9SDimitry Andric     Count = SaturatingMultiply(Count, N, &Overflowed) / D;
974bdd1243dSDimitry Andric     if (Count > getInstrMaxCountValue()) {
975bdd1243dSDimitry Andric       Count = getInstrMaxCountValue();
976bdd1243dSDimitry Andric       Overflowed = true;
977bdd1243dSDimitry Andric     }
9780b57cec5SDimitry Andric     if (Overflowed)
9790b57cec5SDimitry Andric       Warn(instrprof_error::counter_overflow);
9800b57cec5SDimitry Andric   }
9810b57cec5SDimitry Andric   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
982e8d8bef9SDimitry Andric     scaleValueProfData(Kind, N, D, Warn);
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric // Map indirect call target name hash to name string.
9860b57cec5SDimitry Andric uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind,
9870b57cec5SDimitry Andric                                      InstrProfSymtab *SymTab) {
9880b57cec5SDimitry Andric   if (!SymTab)
9890b57cec5SDimitry Andric     return Value;
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric   if (ValueKind == IPVK_IndirectCallTarget)
9920b57cec5SDimitry Andric     return SymTab->getFunctionHashFromAddress(Value);
9930b57cec5SDimitry Andric 
994*0fca6ea1SDimitry Andric   if (ValueKind == IPVK_VTableTarget)
995*0fca6ea1SDimitry Andric     return SymTab->getVTableHashFromAddress(Value);
996*0fca6ea1SDimitry Andric 
9970b57cec5SDimitry Andric   return Value;
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site,
1001*0fca6ea1SDimitry Andric                                    ArrayRef<InstrProfValueData> VData,
10020b57cec5SDimitry Andric                                    InstrProfSymtab *ValueMap) {
1003*0fca6ea1SDimitry Andric   // Remap values.
1004*0fca6ea1SDimitry Andric   std::vector<InstrProfValueData> RemappedVD;
1005*0fca6ea1SDimitry Andric   RemappedVD.reserve(VData.size());
1006*0fca6ea1SDimitry Andric   for (const auto &V : VData) {
1007*0fca6ea1SDimitry Andric     uint64_t NewValue = remapValue(V.Value, ValueKind, ValueMap);
1008*0fca6ea1SDimitry Andric     RemappedVD.push_back({NewValue, V.Count});
10090b57cec5SDimitry Andric   }
1010*0fca6ea1SDimitry Andric 
10110b57cec5SDimitry Andric   std::vector<InstrProfValueSiteRecord> &ValueSites =
10120b57cec5SDimitry Andric       getOrCreateValueSitesForKind(ValueKind);
1013*0fca6ea1SDimitry Andric   assert(ValueSites.size() == Site);
1014*0fca6ea1SDimitry Andric 
1015*0fca6ea1SDimitry Andric   // Add a new value site with remapped value profiling data.
1016*0fca6ea1SDimitry Andric   ValueSites.emplace_back(std::move(RemappedVD));
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric 
1019*0fca6ea1SDimitry Andric void TemporalProfTraceTy::createBPFunctionNodes(
1020*0fca6ea1SDimitry Andric     ArrayRef<TemporalProfTraceTy> Traces, std::vector<BPFunctionNode> &Nodes,
1021*0fca6ea1SDimitry Andric     bool RemoveOutlierUNs) {
102206c3fb27SDimitry Andric   using IDT = BPFunctionNode::IDT;
102306c3fb27SDimitry Andric   using UtilityNodeT = BPFunctionNode::UtilityNodeT;
1024*0fca6ea1SDimitry Andric   UtilityNodeT MaxUN = 0;
1025*0fca6ea1SDimitry Andric   DenseMap<IDT, size_t> IdToFirstTimestamp;
1026*0fca6ea1SDimitry Andric   DenseMap<IDT, UtilityNodeT> IdToFirstUN;
1027*0fca6ea1SDimitry Andric   DenseMap<IDT, SmallVector<UtilityNodeT>> IdToUNs;
102806c3fb27SDimitry Andric   // TODO: We need to use the Trace.Weight field to give more weight to more
102906c3fb27SDimitry Andric   // important utilities
1030*0fca6ea1SDimitry Andric   for (auto &Trace : Traces) {
1031*0fca6ea1SDimitry Andric     size_t CutoffTimestamp = 1;
1032*0fca6ea1SDimitry Andric     for (size_t Timestamp = 0; Timestamp < Trace.FunctionNameRefs.size();
1033*0fca6ea1SDimitry Andric          Timestamp++) {
1034*0fca6ea1SDimitry Andric       IDT Id = Trace.FunctionNameRefs[Timestamp];
1035*0fca6ea1SDimitry Andric       auto [It, WasInserted] = IdToFirstTimestamp.try_emplace(Id, Timestamp);
1036*0fca6ea1SDimitry Andric       if (!WasInserted)
1037*0fca6ea1SDimitry Andric         It->getSecond() = std::min<size_t>(It->getSecond(), Timestamp);
1038*0fca6ea1SDimitry Andric       if (Timestamp >= CutoffTimestamp) {
1039*0fca6ea1SDimitry Andric         ++MaxUN;
1040*0fca6ea1SDimitry Andric         CutoffTimestamp = 2 * Timestamp;
104106c3fb27SDimitry Andric       }
1042*0fca6ea1SDimitry Andric       IdToFirstUN.try_emplace(Id, MaxUN);
104306c3fb27SDimitry Andric     }
1044*0fca6ea1SDimitry Andric     for (auto &[Id, FirstUN] : IdToFirstUN)
1045*0fca6ea1SDimitry Andric       for (auto UN = FirstUN; UN <= MaxUN; ++UN)
1046*0fca6ea1SDimitry Andric         IdToUNs[Id].push_back(UN);
1047*0fca6ea1SDimitry Andric     ++MaxUN;
1048*0fca6ea1SDimitry Andric     IdToFirstUN.clear();
104906c3fb27SDimitry Andric   }
105006c3fb27SDimitry Andric 
1051*0fca6ea1SDimitry Andric   if (RemoveOutlierUNs) {
1052*0fca6ea1SDimitry Andric     DenseMap<UtilityNodeT, unsigned> UNFrequency;
1053*0fca6ea1SDimitry Andric     for (auto &[Id, UNs] : IdToUNs)
1054*0fca6ea1SDimitry Andric       for (auto &UN : UNs)
1055*0fca6ea1SDimitry Andric         ++UNFrequency[UN];
1056*0fca6ea1SDimitry Andric     // Filter out utility nodes that are too infrequent or too prevalent to make
1057*0fca6ea1SDimitry Andric     // BalancedPartitioning more effective.
1058*0fca6ea1SDimitry Andric     for (auto &[Id, UNs] : IdToUNs)
1059*0fca6ea1SDimitry Andric       llvm::erase_if(UNs, [&](auto &UN) {
1060*0fca6ea1SDimitry Andric         return UNFrequency[UN] <= 1 || 2 * UNFrequency[UN] > IdToUNs.size();
1061*0fca6ea1SDimitry Andric       });
106206c3fb27SDimitry Andric   }
1063*0fca6ea1SDimitry Andric 
1064*0fca6ea1SDimitry Andric   for (auto &[Id, UNs] : IdToUNs)
1065*0fca6ea1SDimitry Andric     Nodes.emplace_back(Id, UNs);
1066*0fca6ea1SDimitry Andric 
1067*0fca6ea1SDimitry Andric   // Since BalancedPartitioning is sensitive to the initial order, we explicitly
1068*0fca6ea1SDimitry Andric   // order nodes by their earliest timestamp.
1069*0fca6ea1SDimitry Andric   llvm::sort(Nodes, [&](auto &L, auto &R) {
1070*0fca6ea1SDimitry Andric     return std::make_pair(IdToFirstTimestamp[L.Id], L.Id) <
1071*0fca6ea1SDimitry Andric            std::make_pair(IdToFirstTimestamp[R.Id], R.Id);
1072*0fca6ea1SDimitry Andric   });
107306c3fb27SDimitry Andric }
107406c3fb27SDimitry Andric 
10750b57cec5SDimitry Andric #define INSTR_PROF_COMMON_API_IMPL
10760b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric /*!
10790b57cec5SDimitry Andric  * ValueProfRecordClosure Interface implementation for  InstrProfRecord
10800b57cec5SDimitry Andric  *  class. These C wrappers are used as adaptors so that C++ code can be
10810b57cec5SDimitry Andric  *  invoked as callbacks.
10820b57cec5SDimitry Andric  */
10830b57cec5SDimitry Andric uint32_t getNumValueKindsInstrProf(const void *Record) {
10840b57cec5SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
10850b57cec5SDimitry Andric }
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
10880b57cec5SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)
10890b57cec5SDimitry Andric       ->getNumValueSites(VKind);
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
10930b57cec5SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)
10940b57cec5SDimitry Andric       ->getNumValueData(VKind);
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
10980b57cec5SDimitry Andric                                          uint32_t S) {
1099*0fca6ea1SDimitry Andric   const auto *IPR = reinterpret_cast<const InstrProfRecord *>(R);
1100*0fca6ea1SDimitry Andric   return IPR->getValueArrayForSite(VK, S).size();
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
11040b57cec5SDimitry Andric                               uint32_t K, uint32_t S) {
1105*0fca6ea1SDimitry Andric   const auto *IPR = reinterpret_cast<const InstrProfRecord *>(R);
1106*0fca6ea1SDimitry Andric   llvm::copy(IPR->getValueArrayForSite(K, S), Dst);
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
11100b57cec5SDimitry Andric   ValueProfData *VD =
11110b57cec5SDimitry Andric       (ValueProfData *)(new (::operator new(TotalSizeInBytes)) ValueProfData());
11120b57cec5SDimitry Andric   memset(VD, 0, TotalSizeInBytes);
11130b57cec5SDimitry Andric   return VD;
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric static ValueProfRecordClosure InstrProfRecordClosure = {
11170b57cec5SDimitry Andric     nullptr,
11180b57cec5SDimitry Andric     getNumValueKindsInstrProf,
11190b57cec5SDimitry Andric     getNumValueSitesInstrProf,
11200b57cec5SDimitry Andric     getNumValueDataInstrProf,
11210b57cec5SDimitry Andric     getNumValueDataForSiteInstrProf,
11220b57cec5SDimitry Andric     nullptr,
11230b57cec5SDimitry Andric     getValueForSiteInstrProf,
11240b57cec5SDimitry Andric     allocValueProfDataInstrProf};
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric // Wrapper implementation using the closure mechanism.
11270b57cec5SDimitry Andric uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
11280b57cec5SDimitry Andric   auto Closure = InstrProfRecordClosure;
11290b57cec5SDimitry Andric   Closure.Record = &Record;
11300b57cec5SDimitry Andric   return getValueProfDataSize(&Closure);
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric // Wrapper implementation using the closure mechanism.
11340b57cec5SDimitry Andric std::unique_ptr<ValueProfData>
11350b57cec5SDimitry Andric ValueProfData::serializeFrom(const InstrProfRecord &Record) {
11360b57cec5SDimitry Andric   InstrProfRecordClosure.Record = &Record;
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   std::unique_ptr<ValueProfData> VPD(
11390b57cec5SDimitry Andric       serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr));
11400b57cec5SDimitry Andric   return VPD;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
11440b57cec5SDimitry Andric                                     InstrProfSymtab *SymTab) {
11450b57cec5SDimitry Andric   Record.reserveSites(Kind, NumValueSites);
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric   InstrProfValueData *ValueData = getValueProfRecordValueData(this);
11480b57cec5SDimitry Andric   for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
11490b57cec5SDimitry Andric     uint8_t ValueDataCount = this->SiteCountArray[VSite];
1150*0fca6ea1SDimitry Andric     ArrayRef<InstrProfValueData> VDs(ValueData, ValueDataCount);
1151*0fca6ea1SDimitry Andric     Record.addValueData(Kind, VSite, VDs, SymTab);
11520b57cec5SDimitry Andric     ValueData += ValueDataCount;
11530b57cec5SDimitry Andric   }
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric // For writing/serializing,  Old is the host endianness, and  New is
11570b57cec5SDimitry Andric // byte order intended on disk. For Reading/deserialization, Old
11580b57cec5SDimitry Andric // is the on-disk source endianness, and New is the host endianness.
11595f757f3fSDimitry Andric void ValueProfRecord::swapBytes(llvm::endianness Old, llvm::endianness New) {
11600b57cec5SDimitry Andric   using namespace support;
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   if (Old == New)
11630b57cec5SDimitry Andric     return;
11640b57cec5SDimitry Andric 
11655f757f3fSDimitry Andric   if (llvm::endianness::native != Old) {
11660b57cec5SDimitry Andric     sys::swapByteOrder<uint32_t>(NumValueSites);
11670b57cec5SDimitry Andric     sys::swapByteOrder<uint32_t>(Kind);
11680b57cec5SDimitry Andric   }
11690b57cec5SDimitry Andric   uint32_t ND = getValueProfRecordNumValueData(this);
11700b57cec5SDimitry Andric   InstrProfValueData *VD = getValueProfRecordValueData(this);
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   // No need to swap byte array: SiteCountArrray.
11730b57cec5SDimitry Andric   for (uint32_t I = 0; I < ND; I++) {
11740b57cec5SDimitry Andric     sys::swapByteOrder<uint64_t>(VD[I].Value);
11750b57cec5SDimitry Andric     sys::swapByteOrder<uint64_t>(VD[I].Count);
11760b57cec5SDimitry Andric   }
11775f757f3fSDimitry Andric   if (llvm::endianness::native == Old) {
11780b57cec5SDimitry Andric     sys::swapByteOrder<uint32_t>(NumValueSites);
11790b57cec5SDimitry Andric     sys::swapByteOrder<uint32_t>(Kind);
11800b57cec5SDimitry Andric   }
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric void ValueProfData::deserializeTo(InstrProfRecord &Record,
11840b57cec5SDimitry Andric                                   InstrProfSymtab *SymTab) {
11850b57cec5SDimitry Andric   if (NumValueKinds == 0)
11860b57cec5SDimitry Andric     return;
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
11890b57cec5SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
11900b57cec5SDimitry Andric     VR->deserializeTo(Record, SymTab);
11910b57cec5SDimitry Andric     VR = getValueProfRecordNext(VR);
11920b57cec5SDimitry Andric   }
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
11960b57cec5SDimitry Andric   return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
11970b57cec5SDimitry Andric                                             ValueProfData());
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric Error ValueProfData::checkIntegrity() {
12010b57cec5SDimitry Andric   if (NumValueKinds > IPVK_Last + 1)
1202349cc55cSDimitry Andric     return make_error<InstrProfError>(
1203349cc55cSDimitry Andric         instrprof_error::malformed, "number of value profile kinds is invalid");
1204349cc55cSDimitry Andric   // Total size needs to be multiple of quadword size.
12050b57cec5SDimitry Andric   if (TotalSize % sizeof(uint64_t))
1206349cc55cSDimitry Andric     return make_error<InstrProfError>(
1207349cc55cSDimitry Andric         instrprof_error::malformed, "total size is not multiples of quardword");
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
12100b57cec5SDimitry Andric   for (uint32_t K = 0; K < this->NumValueKinds; K++) {
12110b57cec5SDimitry Andric     if (VR->Kind > IPVK_Last)
1212349cc55cSDimitry Andric       return make_error<InstrProfError>(instrprof_error::malformed,
1213349cc55cSDimitry Andric                                         "value kind is invalid");
12140b57cec5SDimitry Andric     VR = getValueProfRecordNext(VR);
12150b57cec5SDimitry Andric     if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
1216349cc55cSDimitry Andric       return make_error<InstrProfError>(
1217349cc55cSDimitry Andric           instrprof_error::malformed,
1218349cc55cSDimitry Andric           "value profile address is greater than total size");
12190b57cec5SDimitry Andric   }
12200b57cec5SDimitry Andric   return Error::success();
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric Expected<std::unique_ptr<ValueProfData>>
12240b57cec5SDimitry Andric ValueProfData::getValueProfData(const unsigned char *D,
12250b57cec5SDimitry Andric                                 const unsigned char *const BufferEnd,
12265f757f3fSDimitry Andric                                 llvm::endianness Endianness) {
12270b57cec5SDimitry Andric   using namespace support;
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   if (D + sizeof(ValueProfData) > BufferEnd)
12300b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::truncated);
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   const unsigned char *Header = D;
1233*0fca6ea1SDimitry Andric   uint32_t TotalSize = endian::readNext<uint32_t>(Header, Endianness);
1234*0fca6ea1SDimitry Andric 
12350b57cec5SDimitry Andric   if (D + TotalSize > BufferEnd)
12360b57cec5SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric   std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
12390b57cec5SDimitry Andric   memcpy(VPD.get(), D, TotalSize);
12400b57cec5SDimitry Andric   // Byte swap.
12410b57cec5SDimitry Andric   VPD->swapBytesToHost(Endianness);
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric   Error E = VPD->checkIntegrity();
12440b57cec5SDimitry Andric   if (E)
12450b57cec5SDimitry Andric     return std::move(E);
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   return std::move(VPD);
12480b57cec5SDimitry Andric }
12490b57cec5SDimitry Andric 
12505f757f3fSDimitry Andric void ValueProfData::swapBytesToHost(llvm::endianness Endianness) {
12510b57cec5SDimitry Andric   using namespace support;
12520b57cec5SDimitry Andric 
12535f757f3fSDimitry Andric   if (Endianness == llvm::endianness::native)
12540b57cec5SDimitry Andric     return;
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric   sys::swapByteOrder<uint32_t>(TotalSize);
12570b57cec5SDimitry Andric   sys::swapByteOrder<uint32_t>(NumValueKinds);
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
12600b57cec5SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
12615f757f3fSDimitry Andric     VR->swapBytes(Endianness, llvm::endianness::native);
12620b57cec5SDimitry Andric     VR = getValueProfRecordNext(VR);
12630b57cec5SDimitry Andric   }
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric 
12665f757f3fSDimitry Andric void ValueProfData::swapBytesFromHost(llvm::endianness Endianness) {
12670b57cec5SDimitry Andric   using namespace support;
12680b57cec5SDimitry Andric 
12695f757f3fSDimitry Andric   if (Endianness == llvm::endianness::native)
12700b57cec5SDimitry Andric     return;
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
12730b57cec5SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
12740b57cec5SDimitry Andric     ValueProfRecord *NVR = getValueProfRecordNext(VR);
12755f757f3fSDimitry Andric     VR->swapBytes(llvm::endianness::native, Endianness);
12760b57cec5SDimitry Andric     VR = NVR;
12770b57cec5SDimitry Andric   }
12780b57cec5SDimitry Andric   sys::swapByteOrder<uint32_t>(TotalSize);
12790b57cec5SDimitry Andric   sys::swapByteOrder<uint32_t>(NumValueKinds);
12800b57cec5SDimitry Andric }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric void annotateValueSite(Module &M, Instruction &Inst,
12830b57cec5SDimitry Andric                        const InstrProfRecord &InstrProfR,
12840b57cec5SDimitry Andric                        InstrProfValueKind ValueKind, uint32_t SiteIdx,
12850b57cec5SDimitry Andric                        uint32_t MaxMDCount) {
1286*0fca6ea1SDimitry Andric   auto VDs = InstrProfR.getValueArrayForSite(ValueKind, SiteIdx);
1287*0fca6ea1SDimitry Andric   if (VDs.empty())
12880b57cec5SDimitry Andric     return;
12890b57cec5SDimitry Andric   uint64_t Sum = 0;
1290*0fca6ea1SDimitry Andric   for (const InstrProfValueData &V : VDs)
1291*0fca6ea1SDimitry Andric     Sum = SaturatingAdd(Sum, V.Count);
12920b57cec5SDimitry Andric   annotateValueSite(M, Inst, VDs, Sum, ValueKind, MaxMDCount);
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric void annotateValueSite(Module &M, Instruction &Inst,
12960b57cec5SDimitry Andric                        ArrayRef<InstrProfValueData> VDs,
12970b57cec5SDimitry Andric                        uint64_t Sum, InstrProfValueKind ValueKind,
12980b57cec5SDimitry Andric                        uint32_t MaxMDCount) {
1299*0fca6ea1SDimitry Andric   if (VDs.empty())
1300*0fca6ea1SDimitry Andric     return;
13010b57cec5SDimitry Andric   LLVMContext &Ctx = M.getContext();
13020b57cec5SDimitry Andric   MDBuilder MDHelper(Ctx);
13030b57cec5SDimitry Andric   SmallVector<Metadata *, 3> Vals;
13040b57cec5SDimitry Andric   // Tag
13050b57cec5SDimitry Andric   Vals.push_back(MDHelper.createString("VP"));
13060b57cec5SDimitry Andric   // Value Kind
13070b57cec5SDimitry Andric   Vals.push_back(MDHelper.createConstant(
13080b57cec5SDimitry Andric       ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind)));
13090b57cec5SDimitry Andric   // Total Count
13100b57cec5SDimitry Andric   Vals.push_back(
13110b57cec5SDimitry Andric       MDHelper.createConstant(ConstantInt::get(Type::getInt64Ty(Ctx), Sum)));
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   // Value Profile Data
13140b57cec5SDimitry Andric   uint32_t MDCount = MaxMDCount;
1315*0fca6ea1SDimitry Andric   for (const auto &VD : VDs) {
13160b57cec5SDimitry Andric     Vals.push_back(MDHelper.createConstant(
13170b57cec5SDimitry Andric         ConstantInt::get(Type::getInt64Ty(Ctx), VD.Value)));
13180b57cec5SDimitry Andric     Vals.push_back(MDHelper.createConstant(
13190b57cec5SDimitry Andric         ConstantInt::get(Type::getInt64Ty(Ctx), VD.Count)));
13200b57cec5SDimitry Andric     if (--MDCount == 0)
13210b57cec5SDimitry Andric       break;
13220b57cec5SDimitry Andric   }
13230b57cec5SDimitry Andric   Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals));
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric 
1326*0fca6ea1SDimitry Andric MDNode *mayHaveValueProfileOfKind(const Instruction &Inst,
1327*0fca6ea1SDimitry Andric                                   InstrProfValueKind ValueKind) {
13280b57cec5SDimitry Andric   MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof);
13290b57cec5SDimitry Andric   if (!MD)
1330*0fca6ea1SDimitry Andric     return nullptr;
13310b57cec5SDimitry Andric 
1332*0fca6ea1SDimitry Andric   if (MD->getNumOperands() < 5)
1333*0fca6ea1SDimitry Andric     return nullptr;
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   MDString *Tag = cast<MDString>(MD->getOperand(0));
1336*0fca6ea1SDimitry Andric   if (!Tag || Tag->getString() != "VP")
1337*0fca6ea1SDimitry Andric     return nullptr;
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric   // Now check kind:
13400b57cec5SDimitry Andric   ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
13410b57cec5SDimitry Andric   if (!KindInt)
1342*0fca6ea1SDimitry Andric     return nullptr;
13430b57cec5SDimitry Andric   if (KindInt->getZExtValue() != ValueKind)
1344*0fca6ea1SDimitry Andric     return nullptr;
13450b57cec5SDimitry Andric 
1346*0fca6ea1SDimitry Andric   return MD;
1347*0fca6ea1SDimitry Andric }
1348*0fca6ea1SDimitry Andric 
1349*0fca6ea1SDimitry Andric SmallVector<InstrProfValueData, 4>
1350*0fca6ea1SDimitry Andric getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind,
1351*0fca6ea1SDimitry Andric                          uint32_t MaxNumValueData, uint64_t &TotalC,
1352*0fca6ea1SDimitry Andric                          bool GetNoICPValue) {
1353*0fca6ea1SDimitry Andric   // Four inline elements seem to work well in practice.  With MaxNumValueData,
1354*0fca6ea1SDimitry Andric   // this array won't grow very big anyway.
1355*0fca6ea1SDimitry Andric   SmallVector<InstrProfValueData, 4> ValueData;
1356*0fca6ea1SDimitry Andric   MDNode *MD = mayHaveValueProfileOfKind(Inst, ValueKind);
1357*0fca6ea1SDimitry Andric   if (!MD)
1358*0fca6ea1SDimitry Andric     return ValueData;
1359*0fca6ea1SDimitry Andric   const unsigned NOps = MD->getNumOperands();
13600b57cec5SDimitry Andric   // Get total count
13610b57cec5SDimitry Andric   ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
13620b57cec5SDimitry Andric   if (!TotalCInt)
1363*0fca6ea1SDimitry Andric     return ValueData;
13640b57cec5SDimitry Andric   TotalC = TotalCInt->getZExtValue();
13650b57cec5SDimitry Andric 
1366*0fca6ea1SDimitry Andric   ValueData.reserve((NOps - 3) / 2);
13670b57cec5SDimitry Andric   for (unsigned I = 3; I < NOps; I += 2) {
1368*0fca6ea1SDimitry Andric     if (ValueData.size() >= MaxNumValueData)
13690b57cec5SDimitry Andric       break;
13700b57cec5SDimitry Andric     ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
13710b57cec5SDimitry Andric     ConstantInt *Count =
13720b57cec5SDimitry Andric         mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1));
1373*0fca6ea1SDimitry Andric     if (!Value || !Count) {
1374*0fca6ea1SDimitry Andric       ValueData.clear();
1375*0fca6ea1SDimitry Andric       return ValueData;
1376*0fca6ea1SDimitry Andric     }
1377fe6060f1SDimitry Andric     uint64_t CntValue = Count->getZExtValue();
1378fe6060f1SDimitry Andric     if (!GetNoICPValue && (CntValue == NOMORE_ICP_MAGICNUM))
1379fe6060f1SDimitry Andric       continue;
1380*0fca6ea1SDimitry Andric     InstrProfValueData V;
1381*0fca6ea1SDimitry Andric     V.Value = Value->getZExtValue();
1382*0fca6ea1SDimitry Andric     V.Count = CntValue;
1383*0fca6ea1SDimitry Andric     ValueData.push_back(V);
13840b57cec5SDimitry Andric   }
1385*0fca6ea1SDimitry Andric   return ValueData;
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric MDNode *getPGOFuncNameMetadata(const Function &F) {
13890b57cec5SDimitry Andric   return F.getMetadata(getPGOFuncNameMetadataName());
13900b57cec5SDimitry Andric }
13910b57cec5SDimitry Andric 
1392*0fca6ea1SDimitry Andric static void createPGONameMetadata(GlobalObject &GO, StringRef MetadataName,
1393*0fca6ea1SDimitry Andric                                   StringRef PGOName) {
1394*0fca6ea1SDimitry Andric   // Only for internal linkage functions or global variables. The name is not
1395*0fca6ea1SDimitry Andric   // the same as PGO name for these global objects.
1396*0fca6ea1SDimitry Andric   if (GO.getName() == PGOName)
13970b57cec5SDimitry Andric     return;
1398*0fca6ea1SDimitry Andric 
1399*0fca6ea1SDimitry Andric   // Don't create duplicated metadata.
1400*0fca6ea1SDimitry Andric   if (GO.getMetadata(MetadataName))
14010b57cec5SDimitry Andric     return;
1402*0fca6ea1SDimitry Andric 
1403*0fca6ea1SDimitry Andric   LLVMContext &C = GO.getContext();
1404*0fca6ea1SDimitry Andric   MDNode *N = MDNode::get(C, MDString::get(C, PGOName));
1405*0fca6ea1SDimitry Andric   GO.setMetadata(MetadataName, N);
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric 
1408*0fca6ea1SDimitry Andric void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName) {
1409*0fca6ea1SDimitry Andric   return createPGONameMetadata(F, getPGOFuncNameMetadataName(), PGOFuncName);
1410*0fca6ea1SDimitry Andric }
1411*0fca6ea1SDimitry Andric 
1412*0fca6ea1SDimitry Andric void createPGONameMetadata(GlobalObject &GO, StringRef PGOName) {
1413*0fca6ea1SDimitry Andric   return createPGONameMetadata(GO, getPGONameMetadataName(), PGOName);
1414*0fca6ea1SDimitry Andric }
1415*0fca6ea1SDimitry Andric 
1416*0fca6ea1SDimitry Andric bool needsComdatForCounter(const GlobalObject &GO, const Module &M) {
1417*0fca6ea1SDimitry Andric   if (GO.hasComdat())
14180b57cec5SDimitry Andric     return true;
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric   if (!Triple(M.getTargetTriple()).supportsCOMDAT())
14210b57cec5SDimitry Andric     return false;
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   // See createPGOFuncNameVar for more details. To avoid link errors, profile
14240b57cec5SDimitry Andric   // counters for function with available_externally linkage needs to be changed
14250b57cec5SDimitry Andric   // to linkonce linkage. On ELF based systems, this leads to weak symbols to be
14260b57cec5SDimitry Andric   // created. Without using comdat, duplicate entries won't be removed by the
14270b57cec5SDimitry Andric   // linker leading to increased data segement size and raw profile size. Even
14280b57cec5SDimitry Andric   // worse, since the referenced counter from profile per-function data object
14290b57cec5SDimitry Andric   // will be resolved to the common strong definition, the profile counts for
14300b57cec5SDimitry Andric   // available_externally functions will end up being duplicated in raw profile
14310b57cec5SDimitry Andric   // data. This can result in distorted profile as the counts of those dups
14320b57cec5SDimitry Andric   // will be accumulated by the profile merger.
1433*0fca6ea1SDimitry Andric   GlobalValue::LinkageTypes Linkage = GO.getLinkage();
14340b57cec5SDimitry Andric   if (Linkage != GlobalValue::ExternalWeakLinkage &&
14350b57cec5SDimitry Andric       Linkage != GlobalValue::AvailableExternallyLinkage)
14360b57cec5SDimitry Andric     return false;
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   return true;
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric // Check if INSTR_PROF_RAW_VERSION_VAR is defined.
14420b57cec5SDimitry Andric bool isIRPGOFlagSet(const Module *M) {
1443*0fca6ea1SDimitry Andric   const GlobalVariable *IRInstrVar =
14440b57cec5SDimitry Andric       M->getNamedGlobal(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1445349cc55cSDimitry Andric   if (!IRInstrVar || IRInstrVar->hasLocalLinkage())
14460b57cec5SDimitry Andric     return false;
14470b57cec5SDimitry Andric 
1448349cc55cSDimitry Andric   // For CSPGO+LTO, this variable might be marked as non-prevailing and we only
1449349cc55cSDimitry Andric   // have the decl.
1450349cc55cSDimitry Andric   if (IRInstrVar->isDeclaration())
1451349cc55cSDimitry Andric     return true;
1452349cc55cSDimitry Andric 
14530b57cec5SDimitry Andric   // Check if the flag is set.
14540b57cec5SDimitry Andric   if (!IRInstrVar->hasInitializer())
14550b57cec5SDimitry Andric     return false;
14560b57cec5SDimitry Andric 
14578bcb0991SDimitry Andric   auto *InitVal = dyn_cast_or_null<ConstantInt>(IRInstrVar->getInitializer());
14580b57cec5SDimitry Andric   if (!InitVal)
14590b57cec5SDimitry Andric     return false;
14608bcb0991SDimitry Andric   return (InitVal->getZExtValue() & VARIANT_MASK_IR_PROF) != 0;
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric // Check if we can safely rename this Comdat function.
14640b57cec5SDimitry Andric bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken) {
14650b57cec5SDimitry Andric   if (F.getName().empty())
14660b57cec5SDimitry Andric     return false;
14670b57cec5SDimitry Andric   if (!needsComdatForCounter(F, *(F.getParent())))
14680b57cec5SDimitry Andric     return false;
14690b57cec5SDimitry Andric   // Unsafe to rename the address-taken function (which can be used in
14700b57cec5SDimitry Andric   // function comparison).
14710b57cec5SDimitry Andric   if (CheckAddressTaken && F.hasAddressTaken())
14720b57cec5SDimitry Andric     return false;
14730b57cec5SDimitry Andric   // Only safe to do if this function may be discarded if it is not used
14740b57cec5SDimitry Andric   // in the compilation unit.
14750b57cec5SDimitry Andric   if (!GlobalValue::isDiscardableIfUnused(F.getLinkage()))
14760b57cec5SDimitry Andric     return false;
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric   // For AvailableExternallyLinkage functions.
14790b57cec5SDimitry Andric   if (!F.hasComdat()) {
14800b57cec5SDimitry Andric     assert(F.getLinkage() == GlobalValue::AvailableExternallyLinkage);
14810b57cec5SDimitry Andric     return true;
14820b57cec5SDimitry Andric   }
14830b57cec5SDimitry Andric   return true;
14840b57cec5SDimitry Andric }
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric // Create the variable for the profile file name.
14870b57cec5SDimitry Andric void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput) {
14880b57cec5SDimitry Andric   if (InstrProfileOutput.empty())
14890b57cec5SDimitry Andric     return;
14900b57cec5SDimitry Andric   Constant *ProfileNameConst =
14910b57cec5SDimitry Andric       ConstantDataArray::getString(M.getContext(), InstrProfileOutput, true);
14920b57cec5SDimitry Andric   GlobalVariable *ProfileNameVar = new GlobalVariable(
14930b57cec5SDimitry Andric       M, ProfileNameConst->getType(), true, GlobalValue::WeakAnyLinkage,
14940b57cec5SDimitry Andric       ProfileNameConst, INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR));
1495bdd1243dSDimitry Andric   ProfileNameVar->setVisibility(GlobalValue::HiddenVisibility);
14960b57cec5SDimitry Andric   Triple TT(M.getTargetTriple());
14970b57cec5SDimitry Andric   if (TT.supportsCOMDAT()) {
14980b57cec5SDimitry Andric     ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
14990b57cec5SDimitry Andric     ProfileNameVar->setComdat(M.getOrInsertComdat(
15000b57cec5SDimitry Andric         StringRef(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR))));
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric }
15030b57cec5SDimitry Andric 
15048bcb0991SDimitry Andric Error OverlapStats::accumulateCounts(const std::string &BaseFilename,
15050b57cec5SDimitry Andric                                      const std::string &TestFilename,
15060b57cec5SDimitry Andric                                      bool IsCS) {
1507*0fca6ea1SDimitry Andric   auto GetProfileSum = [IsCS](const std::string &Filename,
15080b57cec5SDimitry Andric                               CountSumOrPercent &Sum) -> Error {
150906c3fb27SDimitry Andric     // This function is only used from llvm-profdata that doesn't use any kind
151006c3fb27SDimitry Andric     // of VFS. Just create a default RealFileSystem to read profiles.
151106c3fb27SDimitry Andric     auto FS = vfs::getRealFileSystem();
151206c3fb27SDimitry Andric     auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
15130b57cec5SDimitry Andric     if (Error E = ReaderOrErr.takeError()) {
15140b57cec5SDimitry Andric       return E;
15150b57cec5SDimitry Andric     }
15160b57cec5SDimitry Andric     auto Reader = std::move(ReaderOrErr.get());
15178bcb0991SDimitry Andric     Reader->accumulateCounts(Sum, IsCS);
15180b57cec5SDimitry Andric     return Error::success();
15190b57cec5SDimitry Andric   };
1520*0fca6ea1SDimitry Andric   auto Ret = GetProfileSum(BaseFilename, Base);
15210b57cec5SDimitry Andric   if (Ret)
15220b57cec5SDimitry Andric     return Ret;
1523*0fca6ea1SDimitry Andric   Ret = GetProfileSum(TestFilename, Test);
15240b57cec5SDimitry Andric   if (Ret)
15250b57cec5SDimitry Andric     return Ret;
15260b57cec5SDimitry Andric   this->BaseFilename = &BaseFilename;
15270b57cec5SDimitry Andric   this->TestFilename = &TestFilename;
15280b57cec5SDimitry Andric   Valid = true;
15290b57cec5SDimitry Andric   return Error::success();
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric void OverlapStats::addOneMismatch(const CountSumOrPercent &MismatchFunc) {
15330b57cec5SDimitry Andric   Mismatch.NumEntries += 1;
15340b57cec5SDimitry Andric   Mismatch.CountSum += MismatchFunc.CountSum / Test.CountSum;
15350b57cec5SDimitry Andric   for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
15360b57cec5SDimitry Andric     if (Test.ValueCounts[I] >= 1.0f)
15370b57cec5SDimitry Andric       Mismatch.ValueCounts[I] +=
15380b57cec5SDimitry Andric           MismatchFunc.ValueCounts[I] / Test.ValueCounts[I];
15390b57cec5SDimitry Andric   }
15400b57cec5SDimitry Andric }
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric void OverlapStats::addOneUnique(const CountSumOrPercent &UniqueFunc) {
15430b57cec5SDimitry Andric   Unique.NumEntries += 1;
15440b57cec5SDimitry Andric   Unique.CountSum += UniqueFunc.CountSum / Test.CountSum;
15450b57cec5SDimitry Andric   for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
15460b57cec5SDimitry Andric     if (Test.ValueCounts[I] >= 1.0f)
15470b57cec5SDimitry Andric       Unique.ValueCounts[I] += UniqueFunc.ValueCounts[I] / Test.ValueCounts[I];
15480b57cec5SDimitry Andric   }
15490b57cec5SDimitry Andric }
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric void OverlapStats::dump(raw_fd_ostream &OS) const {
15520b57cec5SDimitry Andric   if (!Valid)
15530b57cec5SDimitry Andric     return;
15540b57cec5SDimitry Andric 
15550b57cec5SDimitry Andric   const char *EntryName =
15560b57cec5SDimitry Andric       (Level == ProgramLevel ? "functions" : "edge counters");
15570b57cec5SDimitry Andric   if (Level == ProgramLevel) {
15580b57cec5SDimitry Andric     OS << "Profile overlap infomation for base_profile: " << *BaseFilename
15590b57cec5SDimitry Andric        << " and test_profile: " << *TestFilename << "\nProgram level:\n";
15600b57cec5SDimitry Andric   } else {
15610b57cec5SDimitry Andric     OS << "Function level:\n"
15620b57cec5SDimitry Andric        << "  Function: " << FuncName << " (Hash=" << FuncHash << ")\n";
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   OS << "  # of " << EntryName << " overlap: " << Overlap.NumEntries << "\n";
15660b57cec5SDimitry Andric   if (Mismatch.NumEntries)
15670b57cec5SDimitry Andric     OS << "  # of " << EntryName << " mismatch: " << Mismatch.NumEntries
15680b57cec5SDimitry Andric        << "\n";
15690b57cec5SDimitry Andric   if (Unique.NumEntries)
15700b57cec5SDimitry Andric     OS << "  # of " << EntryName
15710b57cec5SDimitry Andric        << " only in test_profile: " << Unique.NumEntries << "\n";
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric   OS << "  Edge profile overlap: " << format("%.3f%%", Overlap.CountSum * 100)
15740b57cec5SDimitry Andric      << "\n";
15750b57cec5SDimitry Andric   if (Mismatch.NumEntries)
15760b57cec5SDimitry Andric     OS << "  Mismatched count percentage (Edge): "
15770b57cec5SDimitry Andric        << format("%.3f%%", Mismatch.CountSum * 100) << "\n";
15780b57cec5SDimitry Andric   if (Unique.NumEntries)
15790b57cec5SDimitry Andric     OS << "  Percentage of Edge profile only in test_profile: "
15800b57cec5SDimitry Andric        << format("%.3f%%", Unique.CountSum * 100) << "\n";
15810b57cec5SDimitry Andric   OS << "  Edge profile base count sum: " << format("%.0f", Base.CountSum)
15820b57cec5SDimitry Andric      << "\n"
15830b57cec5SDimitry Andric      << "  Edge profile test count sum: " << format("%.0f", Test.CountSum)
15840b57cec5SDimitry Andric      << "\n";
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric   for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
15870b57cec5SDimitry Andric     if (Base.ValueCounts[I] < 1.0f && Test.ValueCounts[I] < 1.0f)
15880b57cec5SDimitry Andric       continue;
1589*0fca6ea1SDimitry Andric     char ProfileKindName[20] = {0};
15900b57cec5SDimitry Andric     switch (I) {
15910b57cec5SDimitry Andric     case IPVK_IndirectCallTarget:
15920b57cec5SDimitry Andric       strncpy(ProfileKindName, "IndirectCall", 19);
15930b57cec5SDimitry Andric       break;
15940b57cec5SDimitry Andric     case IPVK_MemOPSize:
15950b57cec5SDimitry Andric       strncpy(ProfileKindName, "MemOP", 19);
15960b57cec5SDimitry Andric       break;
1597*0fca6ea1SDimitry Andric     case IPVK_VTableTarget:
1598*0fca6ea1SDimitry Andric       strncpy(ProfileKindName, "VTable", 19);
1599*0fca6ea1SDimitry Andric       break;
16000b57cec5SDimitry Andric     default:
16010b57cec5SDimitry Andric       snprintf(ProfileKindName, 19, "VP[%d]", I);
16020b57cec5SDimitry Andric       break;
16030b57cec5SDimitry Andric     }
16040b57cec5SDimitry Andric     OS << "  " << ProfileKindName
16050b57cec5SDimitry Andric        << " profile overlap: " << format("%.3f%%", Overlap.ValueCounts[I] * 100)
16060b57cec5SDimitry Andric        << "\n";
16070b57cec5SDimitry Andric     if (Mismatch.NumEntries)
16080b57cec5SDimitry Andric       OS << "  Mismatched count percentage (" << ProfileKindName
16090b57cec5SDimitry Andric          << "): " << format("%.3f%%", Mismatch.ValueCounts[I] * 100) << "\n";
16100b57cec5SDimitry Andric     if (Unique.NumEntries)
16110b57cec5SDimitry Andric       OS << "  Percentage of " << ProfileKindName
16120b57cec5SDimitry Andric          << " profile only in test_profile: "
16130b57cec5SDimitry Andric          << format("%.3f%%", Unique.ValueCounts[I] * 100) << "\n";
16140b57cec5SDimitry Andric     OS << "  " << ProfileKindName
16150b57cec5SDimitry Andric        << " profile base count sum: " << format("%.0f", Base.ValueCounts[I])
16160b57cec5SDimitry Andric        << "\n"
16170b57cec5SDimitry Andric        << "  " << ProfileKindName
16180b57cec5SDimitry Andric        << " profile test count sum: " << format("%.0f", Test.ValueCounts[I])
16190b57cec5SDimitry Andric        << "\n";
16200b57cec5SDimitry Andric   }
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric 
162381ad6265SDimitry Andric namespace IndexedInstrProf {
162481ad6265SDimitry Andric Expected<Header> Header::readFromBuffer(const unsigned char *Buffer) {
162581ad6265SDimitry Andric   using namespace support;
1626bdd1243dSDimitry Andric   static_assert(std::is_standard_layout_v<Header>,
1627*0fca6ea1SDimitry Andric                 "Use standard layout for Header for simplicity");
162881ad6265SDimitry Andric   Header H;
162981ad6265SDimitry Andric 
1630*0fca6ea1SDimitry Andric   H.Magic = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
163181ad6265SDimitry Andric   // Check the magic number.
1632*0fca6ea1SDimitry Andric   if (H.Magic != IndexedInstrProf::Magic)
163381ad6265SDimitry Andric     return make_error<InstrProfError>(instrprof_error::bad_magic);
163481ad6265SDimitry Andric 
163581ad6265SDimitry Andric   // Read the version.
1636*0fca6ea1SDimitry Andric   H.Version = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1637*0fca6ea1SDimitry Andric   if (H.getIndexedProfileVersion() >
163881ad6265SDimitry Andric       IndexedInstrProf::ProfVersion::CurrentVersion)
163981ad6265SDimitry Andric     return make_error<InstrProfError>(instrprof_error::unsupported_version);
164081ad6265SDimitry Andric 
1641*0fca6ea1SDimitry Andric   static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
1642*0fca6ea1SDimitry Andric                 "Please update the reader as needed when a new field is added "
1643*0fca6ea1SDimitry Andric                 "or when indexed profile version gets bumped.");
164481ad6265SDimitry Andric 
1645*0fca6ea1SDimitry Andric   Buffer += sizeof(uint64_t); // Skip Header.Unused field.
1646*0fca6ea1SDimitry Andric   H.HashType = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1647*0fca6ea1SDimitry Andric   H.HashOffset = endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1648*0fca6ea1SDimitry Andric   if (H.getIndexedProfileVersion() >= 8)
1649*0fca6ea1SDimitry Andric     H.MemProfOffset =
1650*0fca6ea1SDimitry Andric         endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1651*0fca6ea1SDimitry Andric   if (H.getIndexedProfileVersion() >= 9)
1652*0fca6ea1SDimitry Andric     H.BinaryIdOffset =
1653*0fca6ea1SDimitry Andric         endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1654*0fca6ea1SDimitry Andric   // Version 11 is handled by this condition.
1655*0fca6ea1SDimitry Andric   if (H.getIndexedProfileVersion() >= 10)
1656*0fca6ea1SDimitry Andric     H.TemporalProfTracesOffset =
1657*0fca6ea1SDimitry Andric         endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
1658*0fca6ea1SDimitry Andric   if (H.getIndexedProfileVersion() >= 12)
1659*0fca6ea1SDimitry Andric     H.VTableNamesOffset =
1660*0fca6ea1SDimitry Andric         endian::readNext<uint64_t, llvm::endianness::little>(Buffer);
166181ad6265SDimitry Andric   return H;
166281ad6265SDimitry Andric }
166381ad6265SDimitry Andric 
1664*0fca6ea1SDimitry Andric uint64_t Header::getIndexedProfileVersion() const {
1665*0fca6ea1SDimitry Andric   return GET_VERSION(Version);
1666*0fca6ea1SDimitry Andric }
1667*0fca6ea1SDimitry Andric 
166881ad6265SDimitry Andric size_t Header::size() const {
1669*0fca6ea1SDimitry Andric   switch (getIndexedProfileVersion()) {
1670*0fca6ea1SDimitry Andric     // To retain backward compatibility, new fields must be appended to the end
1671*0fca6ea1SDimitry Andric     // of the header, and byte offset of existing fields shouldn't change when
1672*0fca6ea1SDimitry Andric     // indexed profile version gets incremented.
1673*0fca6ea1SDimitry Andric     static_assert(
1674*0fca6ea1SDimitry Andric         IndexedInstrProf::ProfVersion::CurrentVersion == Version12,
167581ad6265SDimitry Andric         "Please update the size computation below if a new field has "
1676*0fca6ea1SDimitry Andric         "been added to the header; for a version bump without new "
1677*0fca6ea1SDimitry Andric         "fields, add a case statement to fall through to the latest version.");
1678*0fca6ea1SDimitry Andric   case 12ull:
1679*0fca6ea1SDimitry Andric     return 72;
16805f757f3fSDimitry Andric   case 11ull:
16815f757f3fSDimitry Andric     [[fallthrough]];
168206c3fb27SDimitry Andric   case 10ull:
1683*0fca6ea1SDimitry Andric     return 64;
1684bdd1243dSDimitry Andric   case 9ull:
1685*0fca6ea1SDimitry Andric     return 56;
168681ad6265SDimitry Andric   case 8ull:
1687*0fca6ea1SDimitry Andric     return 48;
168881ad6265SDimitry Andric   default: // Version7 (when the backwards compatible header was introduced).
1689*0fca6ea1SDimitry Andric     return 40;
169081ad6265SDimitry Andric   }
169181ad6265SDimitry Andric }
169281ad6265SDimitry Andric 
169381ad6265SDimitry Andric } // namespace IndexedInstrProf
169481ad6265SDimitry Andric 
16950b57cec5SDimitry Andric } // end namespace llvm
1696