17a7e6055SDimitry Andric //===- InstrProf.cpp - Instrumented profiling format support --------------===//
291bc56edSDimitry Andric //
391bc56edSDimitry Andric //                     The LLVM Compiler Infrastructure
491bc56edSDimitry Andric //
591bc56edSDimitry Andric // This file is distributed under the University of Illinois Open Source
691bc56edSDimitry Andric // License. See LICENSE.TXT for details.
791bc56edSDimitry Andric //
891bc56edSDimitry Andric //===----------------------------------------------------------------------===//
991bc56edSDimitry Andric //
1091bc56edSDimitry Andric // This file contains support for clang's instrumentation based PGO and
1191bc56edSDimitry Andric // coverage.
1291bc56edSDimitry Andric //
1391bc56edSDimitry Andric //===----------------------------------------------------------------------===//
1491bc56edSDimitry Andric 
15db17bf38SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
167a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
177a7e6055SDimitry Andric #include "llvm/ADT/SmallString.h"
187a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
194d0b32cdSDimitry Andric #include "llvm/ADT/StringExtras.h"
207a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
21d88c1a5aSDimitry Andric #include "llvm/ADT/Triple.h"
227a7e6055SDimitry Andric #include "llvm/IR/Constant.h"
237d523365SDimitry Andric #include "llvm/IR/Constants.h"
247d523365SDimitry Andric #include "llvm/IR/Function.h"
257a7e6055SDimitry Andric #include "llvm/IR/GlobalValue.h"
267d523365SDimitry Andric #include "llvm/IR/GlobalVariable.h"
277a7e6055SDimitry Andric #include "llvm/IR/Instruction.h"
287a7e6055SDimitry Andric #include "llvm/IR/LLVMContext.h"
293ca95b02SDimitry Andric #include "llvm/IR/MDBuilder.h"
307a7e6055SDimitry Andric #include "llvm/IR/Metadata.h"
314d0b32cdSDimitry Andric #include "llvm/IR/Module.h"
327a7e6055SDimitry Andric #include "llvm/IR/Type.h"
337a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
347a7e6055SDimitry Andric #include "llvm/Support/CommandLine.h"
357a7e6055SDimitry Andric #include "llvm/Support/Compiler.h"
364d0b32cdSDimitry Andric #include "llvm/Support/Compression.h"
377a7e6055SDimitry Andric #include "llvm/Support/Endian.h"
387a7e6055SDimitry Andric #include "llvm/Support/Error.h"
3991bc56edSDimitry Andric #include "llvm/Support/ErrorHandling.h"
404d0b32cdSDimitry Andric #include "llvm/Support/LEB128.h"
4139d628a0SDimitry Andric #include "llvm/Support/ManagedStatic.h"
427a7e6055SDimitry Andric #include "llvm/Support/MathExtras.h"
433ca95b02SDimitry Andric #include "llvm/Support/Path.h"
447a7e6055SDimitry Andric #include "llvm/Support/SwapByteOrder.h"
457a7e6055SDimitry Andric #include <algorithm>
467a7e6055SDimitry Andric #include <cassert>
477a7e6055SDimitry Andric #include <cstddef>
487a7e6055SDimitry Andric #include <cstdint>
49db17bf38SDimitry Andric #include <cstring>
507a7e6055SDimitry Andric #include <memory>
517a7e6055SDimitry Andric #include <string>
527a7e6055SDimitry Andric #include <system_error>
537a7e6055SDimitry Andric #include <utility>
547a7e6055SDimitry Andric #include <vector>
5591bc56edSDimitry Andric 
5691bc56edSDimitry Andric using namespace llvm;
5791bc56edSDimitry Andric 
583ca95b02SDimitry Andric static cl::opt<bool> StaticFuncFullModulePrefix(
592cab237bSDimitry Andric     "static-func-full-module-prefix", cl::init(true), cl::Hidden,
603ca95b02SDimitry Andric     cl::desc("Use full module build paths in the profile counter names for "
613ca95b02SDimitry Andric              "static functions."));
623ca95b02SDimitry Andric 
637a7e6055SDimitry Andric // This option is tailored to users that have different top-level directory in
647a7e6055SDimitry Andric // profile-gen and profile-use compilation. Users need to specific the number
657a7e6055SDimitry Andric // of levels to strip. A value larger than the number of directories in the
667a7e6055SDimitry Andric // source file will strip all the directory names and only leave the basename.
677a7e6055SDimitry Andric //
687a7e6055SDimitry Andric // Note current ThinLTO module importing for the indirect-calls assumes
697a7e6055SDimitry Andric // the source directory name not being stripped. A non-zero option value here
707a7e6055SDimitry Andric // can potentially prevent some inter-module indirect-call-promotions.
717a7e6055SDimitry Andric static cl::opt<unsigned> StaticFuncStripDirNamePrefix(
722cab237bSDimitry Andric     "static-func-strip-dirname-prefix", cl::init(0), cl::Hidden,
737a7e6055SDimitry Andric     cl::desc("Strip specified level of directory name from source path in "
747a7e6055SDimitry Andric              "the profile counter name for static functions."));
757a7e6055SDimitry Andric 
getInstrProfErrString(instrprof_error Err)767a7e6055SDimitry Andric static std::string getInstrProfErrString(instrprof_error Err) {
773ca95b02SDimitry Andric   switch (Err) {
7891bc56edSDimitry Andric   case instrprof_error::success:
7991bc56edSDimitry Andric     return "Success";
8091bc56edSDimitry Andric   case instrprof_error::eof:
8191bc56edSDimitry Andric     return "End of File";
827d523365SDimitry Andric   case instrprof_error::unrecognized_format:
837d523365SDimitry Andric     return "Unrecognized instrumentation profile encoding format";
8491bc56edSDimitry Andric   case instrprof_error::bad_magic:
857d523365SDimitry Andric     return "Invalid instrumentation profile data (bad magic)";
8691bc56edSDimitry Andric   case instrprof_error::bad_header:
877d523365SDimitry Andric     return "Invalid instrumentation profile data (file header is corrupt)";
8891bc56edSDimitry Andric   case instrprof_error::unsupported_version:
897d523365SDimitry Andric     return "Unsupported instrumentation profile format version";
9091bc56edSDimitry Andric   case instrprof_error::unsupported_hash_type:
917d523365SDimitry Andric     return "Unsupported instrumentation profile hash type";
9291bc56edSDimitry Andric   case instrprof_error::too_large:
9391bc56edSDimitry Andric     return "Too much profile data";
9491bc56edSDimitry Andric   case instrprof_error::truncated:
9591bc56edSDimitry Andric     return "Truncated profile data";
9691bc56edSDimitry Andric   case instrprof_error::malformed:
977d523365SDimitry Andric     return "Malformed instrumentation profile data";
9891bc56edSDimitry Andric   case instrprof_error::unknown_function:
9991bc56edSDimitry Andric     return "No profile data available for function";
10091bc56edSDimitry Andric   case instrprof_error::hash_mismatch:
1017d523365SDimitry Andric     return "Function control flow change detected (hash mismatch)";
10291bc56edSDimitry Andric   case instrprof_error::count_mismatch:
1037d523365SDimitry Andric     return "Function basic block count change detected (counter mismatch)";
10491bc56edSDimitry Andric   case instrprof_error::counter_overflow:
10591bc56edSDimitry Andric     return "Counter overflow";
1067d523365SDimitry Andric   case instrprof_error::value_site_count_mismatch:
1077d523365SDimitry Andric     return "Function value site count change detected (counter mismatch)";
1083ca95b02SDimitry Andric   case instrprof_error::compress_failed:
1093ca95b02SDimitry Andric     return "Failed to compress data (zlib)";
1103ca95b02SDimitry Andric   case instrprof_error::uncompress_failed:
1113ca95b02SDimitry Andric     return "Failed to uncompress data (zlib)";
112d88c1a5aSDimitry Andric   case instrprof_error::empty_raw_profile:
113d88c1a5aSDimitry Andric     return "Empty raw profile file";
1142cab237bSDimitry Andric   case instrprof_error::zlib_unavailable:
1152cab237bSDimitry Andric     return "Profile uses zlib compression but the profile reader was built without zlib support";
11691bc56edSDimitry Andric   }
11791bc56edSDimitry Andric   llvm_unreachable("A value of instrprof_error has no message.");
11891bc56edSDimitry Andric }
1193ca95b02SDimitry Andric 
1207a7e6055SDimitry Andric namespace {
1217a7e6055SDimitry Andric 
1223ca95b02SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
1233ca95b02SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
1243ca95b02SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
1253ca95b02SDimitry Andric class InstrProfErrorCategoryType : public std::error_category {
name() const126d88c1a5aSDimitry Andric   const char *name() const noexcept override { return "llvm.instrprof"; }
1277a7e6055SDimitry Andric 
message(int IE) const1283ca95b02SDimitry Andric   std::string message(int IE) const override {
1293ca95b02SDimitry Andric     return getInstrProfErrString(static_cast<instrprof_error>(IE));
1303dac3a9bSDimitry Andric   }
1313ca95b02SDimitry Andric };
1327a7e6055SDimitry Andric 
1333ca95b02SDimitry Andric } // end anonymous namespace
13491bc56edSDimitry Andric 
13539d628a0SDimitry Andric static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;
13639d628a0SDimitry Andric 
instrprof_category()13791bc56edSDimitry Andric const std::error_category &llvm::instrprof_category() {
13839d628a0SDimitry Andric   return *ErrorCategory;
13991bc56edSDimitry Andric }
1407d523365SDimitry Andric 
1417a7e6055SDimitry Andric namespace {
1427a7e6055SDimitry Andric 
1437a7e6055SDimitry Andric const char *InstrProfSectNameCommon[] = {
1447a7e6055SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
1457a7e6055SDimitry Andric   SectNameCommon,
1467a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1477a7e6055SDimitry Andric };
1487a7e6055SDimitry Andric 
1497a7e6055SDimitry Andric const char *InstrProfSectNameCoff[] = {
1507a7e6055SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
1517a7e6055SDimitry Andric   SectNameCoff,
1527a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1537a7e6055SDimitry Andric };
1547a7e6055SDimitry Andric 
1557a7e6055SDimitry Andric const char *InstrProfSectNamePrefix[] = {
1567a7e6055SDimitry Andric #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix)      \
1577a7e6055SDimitry Andric   Prefix,
1587a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1597a7e6055SDimitry Andric };
1607a7e6055SDimitry Andric 
1617a7e6055SDimitry Andric } // namespace
1627a7e6055SDimitry Andric 
1637d523365SDimitry Andric namespace llvm {
1647d523365SDimitry Andric 
getInstrProfSectionName(InstrProfSectKind IPSK,Triple::ObjectFormatType OF,bool AddSegmentInfo)1657a7e6055SDimitry Andric std::string getInstrProfSectionName(InstrProfSectKind IPSK,
1667a7e6055SDimitry Andric                                     Triple::ObjectFormatType OF,
1677a7e6055SDimitry Andric                                     bool AddSegmentInfo) {
1687a7e6055SDimitry Andric   std::string SectName;
1697a7e6055SDimitry Andric 
1707a7e6055SDimitry Andric   if (OF == Triple::MachO && AddSegmentInfo)
1717a7e6055SDimitry Andric     SectName = InstrProfSectNamePrefix[IPSK];
1727a7e6055SDimitry Andric 
1737a7e6055SDimitry Andric   if (OF == Triple::COFF)
1747a7e6055SDimitry Andric     SectName += InstrProfSectNameCoff[IPSK];
1757a7e6055SDimitry Andric   else
1767a7e6055SDimitry Andric     SectName += InstrProfSectNameCommon[IPSK];
1777a7e6055SDimitry Andric 
1787a7e6055SDimitry Andric   if (OF == Triple::MachO && IPSK == IPSK_data && AddSegmentInfo)
1797a7e6055SDimitry Andric     SectName += ",regular,live_support";
1807a7e6055SDimitry Andric 
1817a7e6055SDimitry Andric   return SectName;
1827a7e6055SDimitry Andric }
1837a7e6055SDimitry Andric 
addError(instrprof_error IE)1843ca95b02SDimitry Andric void SoftInstrProfErrors::addError(instrprof_error IE) {
1853ca95b02SDimitry Andric   if (IE == instrprof_error::success)
1863ca95b02SDimitry Andric     return;
1873ca95b02SDimitry Andric 
1883ca95b02SDimitry Andric   if (FirstError == instrprof_error::success)
1893ca95b02SDimitry Andric     FirstError = IE;
1903ca95b02SDimitry Andric 
1913ca95b02SDimitry Andric   switch (IE) {
1923ca95b02SDimitry Andric   case instrprof_error::hash_mismatch:
1933ca95b02SDimitry Andric     ++NumHashMismatches;
1943ca95b02SDimitry Andric     break;
1953ca95b02SDimitry Andric   case instrprof_error::count_mismatch:
1963ca95b02SDimitry Andric     ++NumCountMismatches;
1973ca95b02SDimitry Andric     break;
1983ca95b02SDimitry Andric   case instrprof_error::counter_overflow:
1993ca95b02SDimitry Andric     ++NumCounterOverflows;
2003ca95b02SDimitry Andric     break;
2013ca95b02SDimitry Andric   case instrprof_error::value_site_count_mismatch:
2023ca95b02SDimitry Andric     ++NumValueSiteCountMismatches;
2033ca95b02SDimitry Andric     break;
2043ca95b02SDimitry Andric   default:
2053ca95b02SDimitry Andric     llvm_unreachable("Not a soft error");
2063ca95b02SDimitry Andric   }
2073ca95b02SDimitry Andric }
2083ca95b02SDimitry Andric 
message() const2093ca95b02SDimitry Andric std::string InstrProfError::message() const {
2103ca95b02SDimitry Andric   return getInstrProfErrString(Err);
2113ca95b02SDimitry Andric }
2123ca95b02SDimitry Andric 
2133ca95b02SDimitry Andric char InstrProfError::ID = 0;
2143ca95b02SDimitry Andric 
getPGOFuncName(StringRef RawFuncName,GlobalValue::LinkageTypes Linkage,StringRef FileName,uint64_t Version LLVM_ATTRIBUTE_UNUSED)2157d523365SDimitry Andric std::string getPGOFuncName(StringRef RawFuncName,
2167d523365SDimitry Andric                            GlobalValue::LinkageTypes Linkage,
2177d523365SDimitry Andric                            StringRef FileName,
2187d523365SDimitry Andric                            uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
2193ca95b02SDimitry Andric   return GlobalValue::getGlobalIdentifier(RawFuncName, Linkage, FileName);
2207d523365SDimitry Andric }
2217d523365SDimitry Andric 
2227a7e6055SDimitry Andric // Strip NumPrefix level of directory name from PathNameStr. If the number of
2237a7e6055SDimitry Andric // directory separators is less than NumPrefix, strip all the directories and
2247a7e6055SDimitry Andric // leave base file name only.
stripDirPrefix(StringRef PathNameStr,uint32_t NumPrefix)2257a7e6055SDimitry Andric static StringRef stripDirPrefix(StringRef PathNameStr, uint32_t NumPrefix) {
2267a7e6055SDimitry Andric   uint32_t Count = NumPrefix;
2277a7e6055SDimitry Andric   uint32_t Pos = 0, LastPos = 0;
2287a7e6055SDimitry Andric   for (auto & CI : PathNameStr) {
2297a7e6055SDimitry Andric     ++Pos;
2307a7e6055SDimitry Andric     if (llvm::sys::path::is_separator(CI)) {
2317a7e6055SDimitry Andric       LastPos = Pos;
2327a7e6055SDimitry Andric       --Count;
2337a7e6055SDimitry Andric     }
2347a7e6055SDimitry Andric     if (Count == 0)
2357a7e6055SDimitry Andric       break;
2367a7e6055SDimitry Andric   }
2377a7e6055SDimitry Andric   return PathNameStr.substr(LastPos);
2387a7e6055SDimitry Andric }
2397a7e6055SDimitry Andric 
2403ca95b02SDimitry Andric // Return the PGOFuncName. This function has some special handling when called
2413ca95b02SDimitry Andric // in LTO optimization. The following only applies when calling in LTO passes
2423ca95b02SDimitry Andric // (when \c InLTO is true): LTO's internalization privatizes many global linkage
2433ca95b02SDimitry Andric // symbols. This happens after value profile annotation, but those internal
2443ca95b02SDimitry Andric // linkage functions should not have a source prefix.
245d88c1a5aSDimitry Andric // Additionally, for ThinLTO mode, exported internal functions are promoted
246d88c1a5aSDimitry Andric // and renamed. We need to ensure that the original internal PGO name is
247d88c1a5aSDimitry Andric // used when computing the GUID that is compared against the profiled GUIDs.
2483ca95b02SDimitry Andric // To differentiate compiler generated internal symbols from original ones,
2493ca95b02SDimitry Andric // PGOFuncName meta data are created and attached to the original internal
2503ca95b02SDimitry Andric // symbols in the value profile annotation step
2513ca95b02SDimitry Andric // (PGOUseFunc::annotateIndirectCallSites). If a symbol does not have the meta
2523ca95b02SDimitry Andric // data, its original linkage must be non-internal.
getPGOFuncName(const Function & F,bool InLTO,uint64_t Version)2533ca95b02SDimitry Andric std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) {
2543ca95b02SDimitry Andric   if (!InLTO) {
255*b5893f02SDimitry Andric     StringRef FileName(F.getParent()->getSourceFileName());
256*b5893f02SDimitry Andric     uint32_t StripLevel = StaticFuncFullModulePrefix ? 0 : (uint32_t)-1;
257*b5893f02SDimitry Andric     if (StripLevel < StaticFuncStripDirNamePrefix)
258*b5893f02SDimitry Andric       StripLevel = StaticFuncStripDirNamePrefix;
259*b5893f02SDimitry Andric     if (StripLevel)
260*b5893f02SDimitry Andric       FileName = stripDirPrefix(FileName, StripLevel);
2613ca95b02SDimitry Andric     return getPGOFuncName(F.getName(), F.getLinkage(), FileName, Version);
2623ca95b02SDimitry Andric   }
2633ca95b02SDimitry Andric 
2643ca95b02SDimitry Andric   // In LTO mode (when InLTO is true), first check if there is a meta data.
2653ca95b02SDimitry Andric   if (MDNode *MD = getPGOFuncNameMetadata(F)) {
2663ca95b02SDimitry Andric     StringRef S = cast<MDString>(MD->getOperand(0))->getString();
2673ca95b02SDimitry Andric     return S.str();
2683ca95b02SDimitry Andric   }
2693ca95b02SDimitry Andric 
2703ca95b02SDimitry Andric   // If there is no meta data, the function must be a global before the value
2713ca95b02SDimitry Andric   // profile annotation pass. Its current linkage may be internal if it is
2723ca95b02SDimitry Andric   // internalized in LTO mode.
2733ca95b02SDimitry Andric   return getPGOFuncName(F.getName(), GlobalValue::ExternalLinkage, "");
2747d523365SDimitry Andric }
2757d523365SDimitry Andric 
getFuncNameWithoutPrefix(StringRef PGOFuncName,StringRef FileName)2767d523365SDimitry Andric StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) {
2777d523365SDimitry Andric   if (FileName.empty())
2787d523365SDimitry Andric     return PGOFuncName;
2797d523365SDimitry Andric   // Drop the file name including ':'. See also getPGOFuncName.
2807d523365SDimitry Andric   if (PGOFuncName.startswith(FileName))
2817d523365SDimitry Andric     PGOFuncName = PGOFuncName.drop_front(FileName.size() + 1);
2827d523365SDimitry Andric   return PGOFuncName;
2837d523365SDimitry Andric }
2847d523365SDimitry Andric 
2857d523365SDimitry Andric // \p FuncName is the string used as profile lookup key for the function. A
2867d523365SDimitry Andric // symbol is created to hold the name. Return the legalized symbol name.
getPGOFuncNameVarName(StringRef FuncName,GlobalValue::LinkageTypes Linkage)2873ca95b02SDimitry Andric std::string getPGOFuncNameVarName(StringRef FuncName,
2887d523365SDimitry Andric                                   GlobalValue::LinkageTypes Linkage) {
2897d523365SDimitry Andric   std::string VarName = getInstrProfNameVarPrefix();
2907d523365SDimitry Andric   VarName += FuncName;
2917d523365SDimitry Andric 
2927d523365SDimitry Andric   if (!GlobalValue::isLocalLinkage(Linkage))
2937d523365SDimitry Andric     return VarName;
2947d523365SDimitry Andric 
2957d523365SDimitry Andric   // Now fix up illegal chars in local VarName that may upset the assembler.
2963ca95b02SDimitry Andric   const char *InvalidChars = "-:<>/\"'";
2977d523365SDimitry Andric   size_t found = VarName.find_first_of(InvalidChars);
2987d523365SDimitry Andric   while (found != std::string::npos) {
2997d523365SDimitry Andric     VarName[found] = '_';
3007d523365SDimitry Andric     found = VarName.find_first_of(InvalidChars, found + 1);
3017d523365SDimitry Andric   }
3027d523365SDimitry Andric   return VarName;
3037d523365SDimitry Andric }
3047d523365SDimitry Andric 
createPGOFuncNameVar(Module & M,GlobalValue::LinkageTypes Linkage,StringRef PGOFuncName)3057d523365SDimitry Andric GlobalVariable *createPGOFuncNameVar(Module &M,
3067d523365SDimitry Andric                                      GlobalValue::LinkageTypes Linkage,
3073ca95b02SDimitry Andric                                      StringRef PGOFuncName) {
3087d523365SDimitry Andric   // We generally want to match the function's linkage, but available_externally
3097d523365SDimitry Andric   // and extern_weak both have the wrong semantics, and anything that doesn't
3107d523365SDimitry Andric   // need to link across compilation units doesn't need to be visible at all.
3117d523365SDimitry Andric   if (Linkage == GlobalValue::ExternalWeakLinkage)
3127d523365SDimitry Andric     Linkage = GlobalValue::LinkOnceAnyLinkage;
3137d523365SDimitry Andric   else if (Linkage == GlobalValue::AvailableExternallyLinkage)
3147d523365SDimitry Andric     Linkage = GlobalValue::LinkOnceODRLinkage;
3157d523365SDimitry Andric   else if (Linkage == GlobalValue::InternalLinkage ||
3167d523365SDimitry Andric            Linkage == GlobalValue::ExternalLinkage)
3177d523365SDimitry Andric     Linkage = GlobalValue::PrivateLinkage;
3187d523365SDimitry Andric 
3193ca95b02SDimitry Andric   auto *Value =
3203ca95b02SDimitry Andric       ConstantDataArray::getString(M.getContext(), PGOFuncName, false);
3217d523365SDimitry Andric   auto FuncNameVar =
3227d523365SDimitry Andric       new GlobalVariable(M, Value->getType(), true, Linkage, Value,
3233ca95b02SDimitry Andric                          getPGOFuncNameVarName(PGOFuncName, Linkage));
3247d523365SDimitry Andric 
3257d523365SDimitry Andric   // Hide the symbol so that we correctly get a copy for each executable.
3267d523365SDimitry Andric   if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
3277d523365SDimitry Andric     FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);
3287d523365SDimitry Andric 
3297d523365SDimitry Andric   return FuncNameVar;
3307d523365SDimitry Andric }
3317d523365SDimitry Andric 
createPGOFuncNameVar(Function & F,StringRef PGOFuncName)3323ca95b02SDimitry Andric GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) {
3333ca95b02SDimitry Andric   return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
3347d523365SDimitry Andric }
3357d523365SDimitry Andric 
create(Module & M,bool InLTO)336edd7eaddSDimitry Andric Error InstrProfSymtab::create(Module &M, bool InLTO) {
3373ca95b02SDimitry Andric   for (Function &F : M) {
3383ca95b02SDimitry Andric     // Function may not have a name: like using asm("") to overwrite the name.
3393ca95b02SDimitry Andric     // Ignore in this case.
3403ca95b02SDimitry Andric     if (!F.hasName())
3413ca95b02SDimitry Andric       continue;
3423ca95b02SDimitry Andric     const std::string &PGOFuncName = getPGOFuncName(F, InLTO);
343edd7eaddSDimitry Andric     if (Error E = addFuncName(PGOFuncName))
344edd7eaddSDimitry Andric       return E;
3453ca95b02SDimitry Andric     MD5FuncMap.emplace_back(Function::getGUID(PGOFuncName), &F);
3467a7e6055SDimitry Andric     // In ThinLTO, local function may have been promoted to global and have
3477a7e6055SDimitry Andric     // suffix added to the function name. We need to add the stripped function
3487a7e6055SDimitry Andric     // name to the symbol table so that we can find a match from profile.
3497a7e6055SDimitry Andric     if (InLTO) {
3507a7e6055SDimitry Andric       auto pos = PGOFuncName.find('.');
3517a7e6055SDimitry Andric       if (pos != std::string::npos) {
3527a7e6055SDimitry Andric         const std::string &OtherFuncName = PGOFuncName.substr(0, pos);
353edd7eaddSDimitry Andric         if (Error E = addFuncName(OtherFuncName))
354edd7eaddSDimitry Andric           return E;
3557a7e6055SDimitry Andric         MD5FuncMap.emplace_back(Function::getGUID(OtherFuncName), &F);
3567a7e6055SDimitry Andric       }
3577a7e6055SDimitry Andric     }
3583ca95b02SDimitry Andric   }
3594ba319b5SDimitry Andric   Sorted = false;
3603ca95b02SDimitry Andric   finalizeSymtab();
361edd7eaddSDimitry Andric   return Error::success();
3623ca95b02SDimitry Andric }
3633ca95b02SDimitry Andric 
getFunctionHashFromAddress(uint64_t Address)3644ba319b5SDimitry Andric uint64_t InstrProfSymtab::getFunctionHashFromAddress(uint64_t Address) {
3654ba319b5SDimitry Andric   finalizeSymtab();
3664ba319b5SDimitry Andric   auto Result =
3674ba319b5SDimitry Andric       std::lower_bound(AddrToMD5Map.begin(), AddrToMD5Map.end(), Address,
3684ba319b5SDimitry Andric                        [](const std::pair<uint64_t, uint64_t> &LHS,
3694ba319b5SDimitry Andric                           uint64_t RHS) { return LHS.first < RHS; });
3704ba319b5SDimitry Andric   // Raw function pointer collected by value profiler may be from
3714ba319b5SDimitry Andric   // external functions that are not instrumented. They won't have
3724ba319b5SDimitry Andric   // mapping data to be used by the deserializer. Force the value to
3734ba319b5SDimitry Andric   // be 0 in this case.
3744ba319b5SDimitry Andric   if (Result != AddrToMD5Map.end() && Result->first == Address)
3754ba319b5SDimitry Andric     return (uint64_t)Result->second;
3764ba319b5SDimitry Andric   return 0;
3774ba319b5SDimitry Andric }
3784ba319b5SDimitry Andric 
collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,bool doCompression,std::string & Result)379302affcbSDimitry Andric Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,
3804d0b32cdSDimitry Andric                                 bool doCompression, std::string &Result) {
3817a7e6055SDimitry Andric   assert(!NameStrs.empty() && "No name data to emit");
3823ca95b02SDimitry Andric 
3834d0b32cdSDimitry Andric   uint8_t Header[16], *P = Header;
3844d0b32cdSDimitry Andric   std::string UncompressedNameStrings =
3853ca95b02SDimitry Andric       join(NameStrs.begin(), NameStrs.end(), getInstrProfNameSeparator());
3863ca95b02SDimitry Andric 
3873ca95b02SDimitry Andric   assert(StringRef(UncompressedNameStrings)
3883ca95b02SDimitry Andric                  .count(getInstrProfNameSeparator()) == (NameStrs.size() - 1) &&
3893ca95b02SDimitry Andric          "PGO name is invalid (contains separator token)");
3904d0b32cdSDimitry Andric 
3914d0b32cdSDimitry Andric   unsigned EncLen = encodeULEB128(UncompressedNameStrings.length(), P);
3924d0b32cdSDimitry Andric   P += EncLen;
3934d0b32cdSDimitry Andric 
3943ca95b02SDimitry Andric   auto WriteStringToResult = [&](size_t CompressedLen, StringRef InputStr) {
3954d0b32cdSDimitry Andric     EncLen = encodeULEB128(CompressedLen, P);
3964d0b32cdSDimitry Andric     P += EncLen;
3974d0b32cdSDimitry Andric     char *HeaderStr = reinterpret_cast<char *>(&Header[0]);
3984d0b32cdSDimitry Andric     unsigned HeaderLen = P - &Header[0];
3994d0b32cdSDimitry Andric     Result.append(HeaderStr, HeaderLen);
4004d0b32cdSDimitry Andric     Result += InputStr;
4013ca95b02SDimitry Andric     return Error::success();
4024d0b32cdSDimitry Andric   };
4034d0b32cdSDimitry Andric 
4043ca95b02SDimitry Andric   if (!doCompression) {
4054d0b32cdSDimitry Andric     return WriteStringToResult(0, UncompressedNameStrings);
4063ca95b02SDimitry Andric   }
4074d0b32cdSDimitry Andric 
4083ca95b02SDimitry Andric   SmallString<128> CompressedNameStrings;
4097a7e6055SDimitry Andric   Error E = zlib::compress(StringRef(UncompressedNameStrings),
4107a7e6055SDimitry Andric                            CompressedNameStrings, zlib::BestSizeCompression);
4117a7e6055SDimitry Andric   if (E) {
4127a7e6055SDimitry Andric     consumeError(std::move(E));
4133ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::compress_failed);
4147a7e6055SDimitry Andric   }
4154d0b32cdSDimitry Andric 
4163ca95b02SDimitry Andric   return WriteStringToResult(CompressedNameStrings.size(),
4173ca95b02SDimitry Andric                              CompressedNameStrings);
4184d0b32cdSDimitry Andric }
4194d0b32cdSDimitry Andric 
getPGOFuncNameVarInitializer(GlobalVariable * NameVar)4203ca95b02SDimitry Andric StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar) {
4214d0b32cdSDimitry Andric   auto *Arr = cast<ConstantDataArray>(NameVar->getInitializer());
4224d0b32cdSDimitry Andric   StringRef NameStr =
4234d0b32cdSDimitry Andric       Arr->isCString() ? Arr->getAsCString() : Arr->getAsString();
4244d0b32cdSDimitry Andric   return NameStr;
4254d0b32cdSDimitry Andric }
4264d0b32cdSDimitry Andric 
collectPGOFuncNameStrings(ArrayRef<GlobalVariable * > NameVars,std::string & Result,bool doCompression)427302affcbSDimitry Andric Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
4283ca95b02SDimitry Andric                                 std::string &Result, bool doCompression) {
4294d0b32cdSDimitry Andric   std::vector<std::string> NameStrs;
4304d0b32cdSDimitry Andric   for (auto *NameVar : NameVars) {
4313ca95b02SDimitry Andric     NameStrs.push_back(getPGOFuncNameVarInitializer(NameVar));
4324d0b32cdSDimitry Andric   }
4333ca95b02SDimitry Andric   return collectPGOFuncNameStrings(
4343ca95b02SDimitry Andric       NameStrs, zlib::isAvailable() && doCompression, Result);
4354d0b32cdSDimitry Andric }
4364d0b32cdSDimitry Andric 
readPGOFuncNameStrings(StringRef NameStrings,InstrProfSymtab & Symtab)4373ca95b02SDimitry Andric Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) {
4384d0b32cdSDimitry Andric   const uint8_t *P = reinterpret_cast<const uint8_t *>(NameStrings.data());
4394d0b32cdSDimitry Andric   const uint8_t *EndP = reinterpret_cast<const uint8_t *>(NameStrings.data() +
4404d0b32cdSDimitry Andric                                                           NameStrings.size());
4414d0b32cdSDimitry Andric   while (P < EndP) {
4424d0b32cdSDimitry Andric     uint32_t N;
4434d0b32cdSDimitry Andric     uint64_t UncompressedSize = decodeULEB128(P, &N);
4444d0b32cdSDimitry Andric     P += N;
4454d0b32cdSDimitry Andric     uint64_t CompressedSize = decodeULEB128(P, &N);
4464d0b32cdSDimitry Andric     P += N;
4474d0b32cdSDimitry Andric     bool isCompressed = (CompressedSize != 0);
4484d0b32cdSDimitry Andric     SmallString<128> UncompressedNameStrings;
4494d0b32cdSDimitry Andric     StringRef NameStrings;
4504d0b32cdSDimitry Andric     if (isCompressed) {
4512cab237bSDimitry Andric       if (!llvm::zlib::isAvailable())
4522cab237bSDimitry Andric         return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
4532cab237bSDimitry Andric 
4544d0b32cdSDimitry Andric       StringRef CompressedNameStrings(reinterpret_cast<const char *>(P),
4554d0b32cdSDimitry Andric                                       CompressedSize);
4567a7e6055SDimitry Andric       if (Error E =
4577a7e6055SDimitry Andric               zlib::uncompress(CompressedNameStrings, UncompressedNameStrings,
4587a7e6055SDimitry Andric                                UncompressedSize)) {
4597a7e6055SDimitry Andric         consumeError(std::move(E));
4603ca95b02SDimitry Andric         return make_error<InstrProfError>(instrprof_error::uncompress_failed);
4617a7e6055SDimitry Andric       }
4624d0b32cdSDimitry Andric       P += CompressedSize;
4634d0b32cdSDimitry Andric       NameStrings = StringRef(UncompressedNameStrings.data(),
4644d0b32cdSDimitry Andric                               UncompressedNameStrings.size());
4654d0b32cdSDimitry Andric     } else {
4664d0b32cdSDimitry Andric       NameStrings =
4674d0b32cdSDimitry Andric           StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
4684d0b32cdSDimitry Andric       P += UncompressedSize;
4694d0b32cdSDimitry Andric     }
4704d0b32cdSDimitry Andric     // Now parse the name strings.
4714d0b32cdSDimitry Andric     SmallVector<StringRef, 0> Names;
4723ca95b02SDimitry Andric     NameStrings.split(Names, getInstrProfNameSeparator());
4734d0b32cdSDimitry Andric     for (StringRef &Name : Names)
474edd7eaddSDimitry Andric       if (Error E = Symtab.addFuncName(Name))
475edd7eaddSDimitry Andric         return E;
4764d0b32cdSDimitry Andric 
4774d0b32cdSDimitry Andric     while (P < EndP && *P == 0)
4784d0b32cdSDimitry Andric       P++;
4794d0b32cdSDimitry Andric   }
4803ca95b02SDimitry Andric   return Error::success();
4814d0b32cdSDimitry Andric }
4824d0b32cdSDimitry Andric 
merge(InstrProfValueSiteRecord & Input,uint64_t Weight,function_ref<void (instrprof_error)> Warn)483c4394386SDimitry Andric void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
484c4394386SDimitry Andric                                      uint64_t Weight,
485c4394386SDimitry Andric                                      function_ref<void(instrprof_error)> Warn) {
4867d523365SDimitry Andric   this->sortByTargetValues();
4877d523365SDimitry Andric   Input.sortByTargetValues();
4887d523365SDimitry Andric   auto I = ValueData.begin();
4897d523365SDimitry Andric   auto IE = ValueData.end();
4907d523365SDimitry Andric   for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
4917d523365SDimitry Andric        ++J) {
4927d523365SDimitry Andric     while (I != IE && I->Value < J->Value)
4937d523365SDimitry Andric       ++I;
4947d523365SDimitry Andric     if (I != IE && I->Value == J->Value) {
4957d523365SDimitry Andric       bool Overflowed;
496444ed5c5SDimitry Andric       I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);
4977d523365SDimitry Andric       if (Overflowed)
498c4394386SDimitry Andric         Warn(instrprof_error::counter_overflow);
4997d523365SDimitry Andric       ++I;
5007d523365SDimitry Andric       continue;
5017d523365SDimitry Andric     }
5027d523365SDimitry Andric     ValueData.insert(I, *J);
5037d523365SDimitry Andric   }
5047d523365SDimitry Andric }
5057d523365SDimitry Andric 
scale(uint64_t Weight,function_ref<void (instrprof_error)> Warn)506c4394386SDimitry Andric void InstrProfValueSiteRecord::scale(uint64_t Weight,
507c4394386SDimitry Andric                                      function_ref<void(instrprof_error)> Warn) {
508444ed5c5SDimitry Andric   for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) {
509444ed5c5SDimitry Andric     bool Overflowed;
510444ed5c5SDimitry Andric     I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed);
511444ed5c5SDimitry Andric     if (Overflowed)
512c4394386SDimitry Andric       Warn(instrprof_error::counter_overflow);
513444ed5c5SDimitry Andric   }
514444ed5c5SDimitry Andric }
515444ed5c5SDimitry Andric 
5167d523365SDimitry Andric // Merge Value Profile data from Src record to this record for ValueKind.
5177d523365SDimitry Andric // Scale merged value counts by \p Weight.
mergeValueProfData(uint32_t ValueKind,InstrProfRecord & Src,uint64_t Weight,function_ref<void (instrprof_error)> Warn)518c4394386SDimitry Andric void InstrProfRecord::mergeValueProfData(
519c4394386SDimitry Andric     uint32_t ValueKind, InstrProfRecord &Src, uint64_t Weight,
520c4394386SDimitry Andric     function_ref<void(instrprof_error)> Warn) {
5217d523365SDimitry Andric   uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
5227d523365SDimitry Andric   uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
5233ca95b02SDimitry Andric   if (ThisNumValueSites != OtherNumValueSites) {
524c4394386SDimitry Andric     Warn(instrprof_error::value_site_count_mismatch);
5253ca95b02SDimitry Andric     return;
5263ca95b02SDimitry Andric   }
527a580b014SDimitry Andric   if (!ThisNumValueSites)
528a580b014SDimitry Andric     return;
5297d523365SDimitry Andric   std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
530a580b014SDimitry Andric       getOrCreateValueSitesForKind(ValueKind);
531a580b014SDimitry Andric   MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
5327d523365SDimitry Andric       Src.getValueSitesForKind(ValueKind);
5337d523365SDimitry Andric   for (uint32_t I = 0; I < ThisNumValueSites; I++)
534c4394386SDimitry Andric     ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight, Warn);
5357d523365SDimitry Andric }
5367d523365SDimitry Andric 
merge(InstrProfRecord & Other,uint64_t Weight,function_ref<void (instrprof_error)> Warn)537c4394386SDimitry Andric void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
538c4394386SDimitry Andric                             function_ref<void(instrprof_error)> Warn) {
5397d523365SDimitry Andric   // If the number of counters doesn't match we either have bad data
5407d523365SDimitry Andric   // or a hash collision.
5413ca95b02SDimitry Andric   if (Counts.size() != Other.Counts.size()) {
542c4394386SDimitry Andric     Warn(instrprof_error::count_mismatch);
5433ca95b02SDimitry Andric     return;
5443ca95b02SDimitry Andric   }
5457d523365SDimitry Andric 
5467d523365SDimitry Andric   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
5477d523365SDimitry Andric     bool Overflowed;
548444ed5c5SDimitry Andric     Counts[I] =
549444ed5c5SDimitry Andric         SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
5507d523365SDimitry Andric     if (Overflowed)
551c4394386SDimitry Andric       Warn(instrprof_error::counter_overflow);
5527d523365SDimitry Andric   }
5537d523365SDimitry Andric 
5547d523365SDimitry Andric   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
555c4394386SDimitry Andric     mergeValueProfData(Kind, Other, Weight, Warn);
5567d523365SDimitry Andric }
5577d523365SDimitry Andric 
scaleValueProfData(uint32_t ValueKind,uint64_t Weight,function_ref<void (instrprof_error)> Warn)558c4394386SDimitry Andric void InstrProfRecord::scaleValueProfData(
559c4394386SDimitry Andric     uint32_t ValueKind, uint64_t Weight,
560c4394386SDimitry Andric     function_ref<void(instrprof_error)> Warn) {
561a580b014SDimitry Andric   for (auto &R : getValueSitesForKind(ValueKind))
562c4394386SDimitry Andric     R.scale(Weight, Warn);
563444ed5c5SDimitry Andric }
564444ed5c5SDimitry Andric 
scale(uint64_t Weight,function_ref<void (instrprof_error)> Warn)565c4394386SDimitry Andric void InstrProfRecord::scale(uint64_t Weight,
566c4394386SDimitry Andric                             function_ref<void(instrprof_error)> Warn) {
567444ed5c5SDimitry Andric   for (auto &Count : this->Counts) {
568444ed5c5SDimitry Andric     bool Overflowed;
569444ed5c5SDimitry Andric     Count = SaturatingMultiply(Count, Weight, &Overflowed);
5703ca95b02SDimitry Andric     if (Overflowed)
571c4394386SDimitry Andric       Warn(instrprof_error::counter_overflow);
572444ed5c5SDimitry Andric   }
573444ed5c5SDimitry Andric   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
574c4394386SDimitry Andric     scaleValueProfData(Kind, Weight, Warn);
575444ed5c5SDimitry Andric }
576444ed5c5SDimitry Andric 
5777d523365SDimitry Andric // Map indirect call target name hash to name string.
remapValue(uint64_t Value,uint32_t ValueKind,InstrProfSymtab * SymTab)5787d523365SDimitry Andric uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind,
5794ba319b5SDimitry Andric                                      InstrProfSymtab *SymTab) {
5804ba319b5SDimitry Andric   if (!SymTab)
5817d523365SDimitry Andric     return Value;
5824ba319b5SDimitry Andric 
5834ba319b5SDimitry Andric   if (ValueKind == IPVK_IndirectCallTarget)
5844ba319b5SDimitry Andric     return SymTab->getFunctionHashFromAddress(Value);
5854ba319b5SDimitry Andric 
5867d523365SDimitry Andric   return Value;
5877d523365SDimitry Andric }
5887d523365SDimitry Andric 
addValueData(uint32_t ValueKind,uint32_t Site,InstrProfValueData * VData,uint32_t N,InstrProfSymtab * ValueMap)5897d523365SDimitry Andric void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site,
5907d523365SDimitry Andric                                    InstrProfValueData *VData, uint32_t N,
5914ba319b5SDimitry Andric                                    InstrProfSymtab *ValueMap) {
5927d523365SDimitry Andric   for (uint32_t I = 0; I < N; I++) {
5937d523365SDimitry Andric     VData[I].Value = remapValue(VData[I].Value, ValueKind, ValueMap);
5947d523365SDimitry Andric   }
5957d523365SDimitry Andric   std::vector<InstrProfValueSiteRecord> &ValueSites =
596a580b014SDimitry Andric       getOrCreateValueSitesForKind(ValueKind);
5977d523365SDimitry Andric   if (N == 0)
5983ca95b02SDimitry Andric     ValueSites.emplace_back();
5997d523365SDimitry Andric   else
6007d523365SDimitry Andric     ValueSites.emplace_back(VData, VData + N);
6017d523365SDimitry Andric }
6027d523365SDimitry Andric 
6037d523365SDimitry Andric #define INSTR_PROF_COMMON_API_IMPL
6047d523365SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
6057d523365SDimitry Andric 
6067d523365SDimitry Andric /*!
6074ba319b5SDimitry Andric  * ValueProfRecordClosure Interface implementation for  InstrProfRecord
6087d523365SDimitry Andric  *  class. These C wrappers are used as adaptors so that C++ code can be
6097d523365SDimitry Andric  *  invoked as callbacks.
6107d523365SDimitry Andric  */
getNumValueKindsInstrProf(const void * Record)6117d523365SDimitry Andric uint32_t getNumValueKindsInstrProf(const void *Record) {
6127d523365SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
6137d523365SDimitry Andric }
6147d523365SDimitry Andric 
getNumValueSitesInstrProf(const void * Record,uint32_t VKind)6157d523365SDimitry Andric uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
6167d523365SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)
6177d523365SDimitry Andric       ->getNumValueSites(VKind);
6187d523365SDimitry Andric }
6197d523365SDimitry Andric 
getNumValueDataInstrProf(const void * Record,uint32_t VKind)6207d523365SDimitry Andric uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
6217d523365SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(Record)
6227d523365SDimitry Andric       ->getNumValueData(VKind);
6237d523365SDimitry Andric }
6247d523365SDimitry Andric 
getNumValueDataForSiteInstrProf(const void * R,uint32_t VK,uint32_t S)6257d523365SDimitry Andric uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
6267d523365SDimitry Andric                                          uint32_t S) {
6277d523365SDimitry Andric   return reinterpret_cast<const InstrProfRecord *>(R)
6287d523365SDimitry Andric       ->getNumValueDataForSite(VK, S);
6297d523365SDimitry Andric }
6307d523365SDimitry Andric 
getValueForSiteInstrProf(const void * R,InstrProfValueData * Dst,uint32_t K,uint32_t S)6317d523365SDimitry Andric void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
6323ca95b02SDimitry Andric                               uint32_t K, uint32_t S) {
6333ca95b02SDimitry Andric   reinterpret_cast<const InstrProfRecord *>(R)->getValueForSite(Dst, K, S);
6347d523365SDimitry Andric }
6357d523365SDimitry Andric 
allocValueProfDataInstrProf(size_t TotalSizeInBytes)6367d523365SDimitry Andric ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
6377d523365SDimitry Andric   ValueProfData *VD =
6387d523365SDimitry Andric       (ValueProfData *)(new (::operator new(TotalSizeInBytes)) ValueProfData());
6397d523365SDimitry Andric   memset(VD, 0, TotalSizeInBytes);
6407d523365SDimitry Andric   return VD;
6417d523365SDimitry Andric }
6427d523365SDimitry Andric 
6437d523365SDimitry Andric static ValueProfRecordClosure InstrProfRecordClosure = {
6443ca95b02SDimitry Andric     nullptr,
6457d523365SDimitry Andric     getNumValueKindsInstrProf,
6467d523365SDimitry Andric     getNumValueSitesInstrProf,
6477d523365SDimitry Andric     getNumValueDataInstrProf,
6487d523365SDimitry Andric     getNumValueDataForSiteInstrProf,
6493ca95b02SDimitry Andric     nullptr,
6507d523365SDimitry Andric     getValueForSiteInstrProf,
6517d523365SDimitry Andric     allocValueProfDataInstrProf};
6527d523365SDimitry Andric 
6537d523365SDimitry Andric // Wrapper implementation using the closure mechanism.
getSize(const InstrProfRecord & Record)6547d523365SDimitry Andric uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
655a580b014SDimitry Andric   auto Closure = InstrProfRecordClosure;
656a580b014SDimitry Andric   Closure.Record = &Record;
657a580b014SDimitry Andric   return getValueProfDataSize(&Closure);
6587d523365SDimitry Andric }
6597d523365SDimitry Andric 
6607d523365SDimitry Andric // Wrapper implementation using the closure mechanism.
6617d523365SDimitry Andric std::unique_ptr<ValueProfData>
serializeFrom(const InstrProfRecord & Record)6627d523365SDimitry Andric ValueProfData::serializeFrom(const InstrProfRecord &Record) {
6637d523365SDimitry Andric   InstrProfRecordClosure.Record = &Record;
6647d523365SDimitry Andric 
6657d523365SDimitry Andric   std::unique_ptr<ValueProfData> VPD(
6667d523365SDimitry Andric       serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr));
6677d523365SDimitry Andric   return VPD;
6687d523365SDimitry Andric }
6697d523365SDimitry Andric 
deserializeTo(InstrProfRecord & Record,InstrProfSymtab * SymTab)6707d523365SDimitry Andric void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
6714ba319b5SDimitry Andric                                     InstrProfSymtab *SymTab) {
6727d523365SDimitry Andric   Record.reserveSites(Kind, NumValueSites);
6737d523365SDimitry Andric 
6747d523365SDimitry Andric   InstrProfValueData *ValueData = getValueProfRecordValueData(this);
6757d523365SDimitry Andric   for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
6767d523365SDimitry Andric     uint8_t ValueDataCount = this->SiteCountArray[VSite];
6774ba319b5SDimitry Andric     Record.addValueData(Kind, VSite, ValueData, ValueDataCount, SymTab);
6787d523365SDimitry Andric     ValueData += ValueDataCount;
6797d523365SDimitry Andric   }
6807d523365SDimitry Andric }
6817d523365SDimitry Andric 
6827d523365SDimitry Andric // For writing/serializing,  Old is the host endianness, and  New is
6837d523365SDimitry Andric // byte order intended on disk. For Reading/deserialization, Old
6847d523365SDimitry Andric // is the on-disk source endianness, and New is the host endianness.
swapBytes(support::endianness Old,support::endianness New)6857d523365SDimitry Andric void ValueProfRecord::swapBytes(support::endianness Old,
6867d523365SDimitry Andric                                 support::endianness New) {
6877d523365SDimitry Andric   using namespace support;
6887a7e6055SDimitry Andric 
6897d523365SDimitry Andric   if (Old == New)
6907d523365SDimitry Andric     return;
6917d523365SDimitry Andric 
6927d523365SDimitry Andric   if (getHostEndianness() != Old) {
6937d523365SDimitry Andric     sys::swapByteOrder<uint32_t>(NumValueSites);
6947d523365SDimitry Andric     sys::swapByteOrder<uint32_t>(Kind);
6957d523365SDimitry Andric   }
6967d523365SDimitry Andric   uint32_t ND = getValueProfRecordNumValueData(this);
6977d523365SDimitry Andric   InstrProfValueData *VD = getValueProfRecordValueData(this);
6987d523365SDimitry Andric 
6997d523365SDimitry Andric   // No need to swap byte array: SiteCountArrray.
7007d523365SDimitry Andric   for (uint32_t I = 0; I < ND; I++) {
7017d523365SDimitry Andric     sys::swapByteOrder<uint64_t>(VD[I].Value);
7027d523365SDimitry Andric     sys::swapByteOrder<uint64_t>(VD[I].Count);
7037d523365SDimitry Andric   }
7047d523365SDimitry Andric   if (getHostEndianness() == Old) {
7057d523365SDimitry Andric     sys::swapByteOrder<uint32_t>(NumValueSites);
7067d523365SDimitry Andric     sys::swapByteOrder<uint32_t>(Kind);
7077d523365SDimitry Andric   }
7087d523365SDimitry Andric }
7097d523365SDimitry Andric 
deserializeTo(InstrProfRecord & Record,InstrProfSymtab * SymTab)7107d523365SDimitry Andric void ValueProfData::deserializeTo(InstrProfRecord &Record,
7114ba319b5SDimitry Andric                                   InstrProfSymtab *SymTab) {
7127d523365SDimitry Andric   if (NumValueKinds == 0)
7137d523365SDimitry Andric     return;
7147d523365SDimitry Andric 
7157d523365SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
7167d523365SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
7174ba319b5SDimitry Andric     VR->deserializeTo(Record, SymTab);
7187d523365SDimitry Andric     VR = getValueProfRecordNext(VR);
7197d523365SDimitry Andric   }
7207d523365SDimitry Andric }
7217d523365SDimitry Andric 
7227d523365SDimitry Andric template <class T>
swapToHostOrder(const unsigned char * & D,support::endianness Orig)7237d523365SDimitry Andric static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
7247d523365SDimitry Andric   using namespace support;
7257a7e6055SDimitry Andric 
7267d523365SDimitry Andric   if (Orig == little)
7277d523365SDimitry Andric     return endian::readNext<T, little, unaligned>(D);
7287d523365SDimitry Andric   else
7297d523365SDimitry Andric     return endian::readNext<T, big, unaligned>(D);
7307d523365SDimitry Andric }
7317d523365SDimitry Andric 
allocValueProfData(uint32_t TotalSize)7327d523365SDimitry Andric static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
7337d523365SDimitry Andric   return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
7347d523365SDimitry Andric                                             ValueProfData());
7357d523365SDimitry Andric }
7367d523365SDimitry Andric 
checkIntegrity()7373ca95b02SDimitry Andric Error ValueProfData::checkIntegrity() {
7387d523365SDimitry Andric   if (NumValueKinds > IPVK_Last + 1)
7393ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
7407d523365SDimitry Andric   // Total size needs to be mulltiple of quadword size.
7417d523365SDimitry Andric   if (TotalSize % sizeof(uint64_t))
7423ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::malformed);
7437d523365SDimitry Andric 
7447d523365SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
7457d523365SDimitry Andric   for (uint32_t K = 0; K < this->NumValueKinds; K++) {
7467d523365SDimitry Andric     if (VR->Kind > IPVK_Last)
7473ca95b02SDimitry Andric       return make_error<InstrProfError>(instrprof_error::malformed);
7487d523365SDimitry Andric     VR = getValueProfRecordNext(VR);
7497d523365SDimitry Andric     if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
7503ca95b02SDimitry Andric       return make_error<InstrProfError>(instrprof_error::malformed);
7517d523365SDimitry Andric   }
7523ca95b02SDimitry Andric   return Error::success();
7537d523365SDimitry Andric }
7547d523365SDimitry Andric 
7553ca95b02SDimitry Andric Expected<std::unique_ptr<ValueProfData>>
getValueProfData(const unsigned char * D,const unsigned char * const BufferEnd,support::endianness Endianness)7567d523365SDimitry Andric ValueProfData::getValueProfData(const unsigned char *D,
7577d523365SDimitry Andric                                 const unsigned char *const BufferEnd,
7587d523365SDimitry Andric                                 support::endianness Endianness) {
7597d523365SDimitry Andric   using namespace support;
7607a7e6055SDimitry Andric 
7617d523365SDimitry Andric   if (D + sizeof(ValueProfData) > BufferEnd)
7623ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::truncated);
7637d523365SDimitry Andric 
7647d523365SDimitry Andric   const unsigned char *Header = D;
7657d523365SDimitry Andric   uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
7667d523365SDimitry Andric   if (D + TotalSize > BufferEnd)
7673ca95b02SDimitry Andric     return make_error<InstrProfError>(instrprof_error::too_large);
7687d523365SDimitry Andric 
7697d523365SDimitry Andric   std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
7707d523365SDimitry Andric   memcpy(VPD.get(), D, TotalSize);
7717d523365SDimitry Andric   // Byte swap.
7727d523365SDimitry Andric   VPD->swapBytesToHost(Endianness);
7737d523365SDimitry Andric 
7743ca95b02SDimitry Andric   Error E = VPD->checkIntegrity();
7753ca95b02SDimitry Andric   if (E)
7763ca95b02SDimitry Andric     return std::move(E);
7777d523365SDimitry Andric 
7787d523365SDimitry Andric   return std::move(VPD);
7797d523365SDimitry Andric }
7807d523365SDimitry Andric 
swapBytesToHost(support::endianness Endianness)7817d523365SDimitry Andric void ValueProfData::swapBytesToHost(support::endianness Endianness) {
7827d523365SDimitry Andric   using namespace support;
7837a7e6055SDimitry Andric 
7847d523365SDimitry Andric   if (Endianness == getHostEndianness())
7857d523365SDimitry Andric     return;
7867d523365SDimitry Andric 
7877d523365SDimitry Andric   sys::swapByteOrder<uint32_t>(TotalSize);
7887d523365SDimitry Andric   sys::swapByteOrder<uint32_t>(NumValueKinds);
7897d523365SDimitry Andric 
7907d523365SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
7917d523365SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
7927d523365SDimitry Andric     VR->swapBytes(Endianness, getHostEndianness());
7937d523365SDimitry Andric     VR = getValueProfRecordNext(VR);
7947d523365SDimitry Andric   }
7957d523365SDimitry Andric }
7967d523365SDimitry Andric 
swapBytesFromHost(support::endianness Endianness)7977d523365SDimitry Andric void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
7987d523365SDimitry Andric   using namespace support;
7997a7e6055SDimitry Andric 
8007d523365SDimitry Andric   if (Endianness == getHostEndianness())
8017d523365SDimitry Andric     return;
8027d523365SDimitry Andric 
8037d523365SDimitry Andric   ValueProfRecord *VR = getFirstValueProfRecord(this);
8047d523365SDimitry Andric   for (uint32_t K = 0; K < NumValueKinds; K++) {
8057d523365SDimitry Andric     ValueProfRecord *NVR = getValueProfRecordNext(VR);
8067d523365SDimitry Andric     VR->swapBytes(getHostEndianness(), Endianness);
8077d523365SDimitry Andric     VR = NVR;
8087d523365SDimitry Andric   }
8097d523365SDimitry Andric   sys::swapByteOrder<uint32_t>(TotalSize);
8107d523365SDimitry Andric   sys::swapByteOrder<uint32_t>(NumValueKinds);
8117d523365SDimitry Andric }
8127d523365SDimitry Andric 
annotateValueSite(Module & M,Instruction & Inst,const InstrProfRecord & InstrProfR,InstrProfValueKind ValueKind,uint32_t SiteIdx,uint32_t MaxMDCount)8133ca95b02SDimitry Andric void annotateValueSite(Module &M, Instruction &Inst,
8143ca95b02SDimitry Andric                        const InstrProfRecord &InstrProfR,
8153ca95b02SDimitry Andric                        InstrProfValueKind ValueKind, uint32_t SiteIdx,
8163ca95b02SDimitry Andric                        uint32_t MaxMDCount) {
8173ca95b02SDimitry Andric   uint32_t NV = InstrProfR.getNumValueDataForSite(ValueKind, SiteIdx);
8183ca95b02SDimitry Andric   if (!NV)
8193ca95b02SDimitry Andric     return;
8203ca95b02SDimitry Andric 
8213ca95b02SDimitry Andric   uint64_t Sum = 0;
8223ca95b02SDimitry Andric   std::unique_ptr<InstrProfValueData[]> VD =
8233ca95b02SDimitry Andric       InstrProfR.getValueForSite(ValueKind, SiteIdx, &Sum);
8243ca95b02SDimitry Andric 
8253ca95b02SDimitry Andric   ArrayRef<InstrProfValueData> VDs(VD.get(), NV);
8263ca95b02SDimitry Andric   annotateValueSite(M, Inst, VDs, Sum, ValueKind, MaxMDCount);
8277d523365SDimitry Andric }
8283ca95b02SDimitry Andric 
annotateValueSite(Module & M,Instruction & Inst,ArrayRef<InstrProfValueData> VDs,uint64_t Sum,InstrProfValueKind ValueKind,uint32_t MaxMDCount)8293ca95b02SDimitry Andric void annotateValueSite(Module &M, Instruction &Inst,
8303ca95b02SDimitry Andric                        ArrayRef<InstrProfValueData> VDs,
8313ca95b02SDimitry Andric                        uint64_t Sum, InstrProfValueKind ValueKind,
8323ca95b02SDimitry Andric                        uint32_t MaxMDCount) {
8333ca95b02SDimitry Andric   LLVMContext &Ctx = M.getContext();
8343ca95b02SDimitry Andric   MDBuilder MDHelper(Ctx);
8353ca95b02SDimitry Andric   SmallVector<Metadata *, 3> Vals;
8363ca95b02SDimitry Andric   // Tag
8373ca95b02SDimitry Andric   Vals.push_back(MDHelper.createString("VP"));
8383ca95b02SDimitry Andric   // Value Kind
8393ca95b02SDimitry Andric   Vals.push_back(MDHelper.createConstant(
8403ca95b02SDimitry Andric       ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind)));
8413ca95b02SDimitry Andric   // Total Count
8423ca95b02SDimitry Andric   Vals.push_back(
8433ca95b02SDimitry Andric       MDHelper.createConstant(ConstantInt::get(Type::getInt64Ty(Ctx), Sum)));
8443ca95b02SDimitry Andric 
8453ca95b02SDimitry Andric   // Value Profile Data
8463ca95b02SDimitry Andric   uint32_t MDCount = MaxMDCount;
8473ca95b02SDimitry Andric   for (auto &VD : VDs) {
8483ca95b02SDimitry Andric     Vals.push_back(MDHelper.createConstant(
8493ca95b02SDimitry Andric         ConstantInt::get(Type::getInt64Ty(Ctx), VD.Value)));
8503ca95b02SDimitry Andric     Vals.push_back(MDHelper.createConstant(
8513ca95b02SDimitry Andric         ConstantInt::get(Type::getInt64Ty(Ctx), VD.Count)));
8523ca95b02SDimitry Andric     if (--MDCount == 0)
8533ca95b02SDimitry Andric       break;
8543ca95b02SDimitry Andric   }
8553ca95b02SDimitry Andric   Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals));
8563ca95b02SDimitry Andric }
8573ca95b02SDimitry Andric 
getValueProfDataFromInst(const Instruction & Inst,InstrProfValueKind ValueKind,uint32_t MaxNumValueData,InstrProfValueData ValueData[],uint32_t & ActualNumValueData,uint64_t & TotalC)8583ca95b02SDimitry Andric bool getValueProfDataFromInst(const Instruction &Inst,
8593ca95b02SDimitry Andric                               InstrProfValueKind ValueKind,
8603ca95b02SDimitry Andric                               uint32_t MaxNumValueData,
8613ca95b02SDimitry Andric                               InstrProfValueData ValueData[],
8623ca95b02SDimitry Andric                               uint32_t &ActualNumValueData, uint64_t &TotalC) {
8633ca95b02SDimitry Andric   MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof);
8643ca95b02SDimitry Andric   if (!MD)
8653ca95b02SDimitry Andric     return false;
8663ca95b02SDimitry Andric 
8673ca95b02SDimitry Andric   unsigned NOps = MD->getNumOperands();
8683ca95b02SDimitry Andric 
8693ca95b02SDimitry Andric   if (NOps < 5)
8703ca95b02SDimitry Andric     return false;
8713ca95b02SDimitry Andric 
8723ca95b02SDimitry Andric   // Operand 0 is a string tag "VP":
8733ca95b02SDimitry Andric   MDString *Tag = cast<MDString>(MD->getOperand(0));
8743ca95b02SDimitry Andric   if (!Tag)
8753ca95b02SDimitry Andric     return false;
8763ca95b02SDimitry Andric 
8773ca95b02SDimitry Andric   if (!Tag->getString().equals("VP"))
8783ca95b02SDimitry Andric     return false;
8793ca95b02SDimitry Andric 
8803ca95b02SDimitry Andric   // Now check kind:
8813ca95b02SDimitry Andric   ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
8823ca95b02SDimitry Andric   if (!KindInt)
8833ca95b02SDimitry Andric     return false;
8843ca95b02SDimitry Andric   if (KindInt->getZExtValue() != ValueKind)
8853ca95b02SDimitry Andric     return false;
8863ca95b02SDimitry Andric 
8873ca95b02SDimitry Andric   // Get total count
8883ca95b02SDimitry Andric   ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
8893ca95b02SDimitry Andric   if (!TotalCInt)
8903ca95b02SDimitry Andric     return false;
8913ca95b02SDimitry Andric   TotalC = TotalCInt->getZExtValue();
8923ca95b02SDimitry Andric 
8933ca95b02SDimitry Andric   ActualNumValueData = 0;
8943ca95b02SDimitry Andric 
8953ca95b02SDimitry Andric   for (unsigned I = 3; I < NOps; I += 2) {
8963ca95b02SDimitry Andric     if (ActualNumValueData >= MaxNumValueData)
8973ca95b02SDimitry Andric       break;
8983ca95b02SDimitry Andric     ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
8993ca95b02SDimitry Andric     ConstantInt *Count =
9003ca95b02SDimitry Andric         mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1));
9013ca95b02SDimitry Andric     if (!Value || !Count)
9023ca95b02SDimitry Andric       return false;
9033ca95b02SDimitry Andric     ValueData[ActualNumValueData].Value = Value->getZExtValue();
9043ca95b02SDimitry Andric     ValueData[ActualNumValueData].Count = Count->getZExtValue();
9053ca95b02SDimitry Andric     ActualNumValueData++;
9063ca95b02SDimitry Andric   }
9073ca95b02SDimitry Andric   return true;
9083ca95b02SDimitry Andric }
9093ca95b02SDimitry Andric 
getPGOFuncNameMetadata(const Function & F)9103ca95b02SDimitry Andric MDNode *getPGOFuncNameMetadata(const Function &F) {
9113ca95b02SDimitry Andric   return F.getMetadata(getPGOFuncNameMetadataName());
9123ca95b02SDimitry Andric }
9133ca95b02SDimitry Andric 
createPGOFuncNameMetadata(Function & F,StringRef PGOFuncName)9143ca95b02SDimitry Andric void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName) {
9153ca95b02SDimitry Andric   // Only for internal linkage functions.
9163ca95b02SDimitry Andric   if (PGOFuncName == F.getName())
9173ca95b02SDimitry Andric       return;
9183ca95b02SDimitry Andric   // Don't create duplicated meta-data.
9193ca95b02SDimitry Andric   if (getPGOFuncNameMetadata(F))
9203ca95b02SDimitry Andric     return;
9213ca95b02SDimitry Andric   LLVMContext &C = F.getContext();
9223ca95b02SDimitry Andric   MDNode *N = MDNode::get(C, MDString::get(C, PGOFuncName));
9233ca95b02SDimitry Andric   F.setMetadata(getPGOFuncNameMetadataName(), N);
9243ca95b02SDimitry Andric }
9253ca95b02SDimitry Andric 
needsComdatForCounter(const Function & F,const Module & M)926d88c1a5aSDimitry Andric bool needsComdatForCounter(const Function &F, const Module &M) {
927d88c1a5aSDimitry Andric   if (F.hasComdat())
928d88c1a5aSDimitry Andric     return true;
929d88c1a5aSDimitry Andric 
9304ba319b5SDimitry Andric   if (!Triple(M.getTargetTriple()).supportsCOMDAT())
931d88c1a5aSDimitry Andric     return false;
932d88c1a5aSDimitry Andric 
933d88c1a5aSDimitry Andric   // See createPGOFuncNameVar for more details. To avoid link errors, profile
934d88c1a5aSDimitry Andric   // counters for function with available_externally linkage needs to be changed
935d88c1a5aSDimitry Andric   // to linkonce linkage. On ELF based systems, this leads to weak symbols to be
936d88c1a5aSDimitry Andric   // created. Without using comdat, duplicate entries won't be removed by the
937d88c1a5aSDimitry Andric   // linker leading to increased data segement size and raw profile size. Even
938d88c1a5aSDimitry Andric   // worse, since the referenced counter from profile per-function data object
939d88c1a5aSDimitry Andric   // will be resolved to the common strong definition, the profile counts for
940d88c1a5aSDimitry Andric   // available_externally functions will end up being duplicated in raw profile
941d88c1a5aSDimitry Andric   // data. This can result in distorted profile as the counts of those dups
942d88c1a5aSDimitry Andric   // will be accumulated by the profile merger.
943d88c1a5aSDimitry Andric   GlobalValue::LinkageTypes Linkage = F.getLinkage();
944d88c1a5aSDimitry Andric   if (Linkage != GlobalValue::ExternalWeakLinkage &&
945d88c1a5aSDimitry Andric       Linkage != GlobalValue::AvailableExternallyLinkage)
946d88c1a5aSDimitry Andric     return false;
947d88c1a5aSDimitry Andric 
948d88c1a5aSDimitry Andric   return true;
949d88c1a5aSDimitry Andric }
950f1a29dd3SDimitry Andric 
951f1a29dd3SDimitry Andric // Check if INSTR_PROF_RAW_VERSION_VAR is defined.
isIRPGOFlagSet(const Module * M)952f1a29dd3SDimitry Andric bool isIRPGOFlagSet(const Module *M) {
953f1a29dd3SDimitry Andric   auto IRInstrVar =
954f1a29dd3SDimitry Andric       M->getNamedGlobal(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
955f1a29dd3SDimitry Andric   if (!IRInstrVar || IRInstrVar->isDeclaration() ||
956f1a29dd3SDimitry Andric       IRInstrVar->hasLocalLinkage())
957f1a29dd3SDimitry Andric     return false;
958f1a29dd3SDimitry Andric 
959f1a29dd3SDimitry Andric   // Check if the flag is set.
960f1a29dd3SDimitry Andric   if (!IRInstrVar->hasInitializer())
961f1a29dd3SDimitry Andric     return false;
962f1a29dd3SDimitry Andric 
963f1a29dd3SDimitry Andric   const Constant *InitVal = IRInstrVar->getInitializer();
964f1a29dd3SDimitry Andric   if (!InitVal)
965f1a29dd3SDimitry Andric     return false;
966f1a29dd3SDimitry Andric 
967f1a29dd3SDimitry Andric   return (dyn_cast<ConstantInt>(InitVal)->getZExtValue() &
968f1a29dd3SDimitry Andric           VARIANT_MASK_IR_PROF) != 0;
969f1a29dd3SDimitry Andric }
970f1a29dd3SDimitry Andric 
971f1a29dd3SDimitry Andric // Check if we can safely rename this Comdat function.
canRenameComdatFunc(const Function & F,bool CheckAddressTaken)972f1a29dd3SDimitry Andric bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken) {
973f1a29dd3SDimitry Andric   if (F.getName().empty())
974f1a29dd3SDimitry Andric     return false;
975f1a29dd3SDimitry Andric   if (!needsComdatForCounter(F, *(F.getParent())))
976f1a29dd3SDimitry Andric     return false;
977f1a29dd3SDimitry Andric   // Unsafe to rename the address-taken function (which can be used in
978f1a29dd3SDimitry Andric   // function comparison).
979f1a29dd3SDimitry Andric   if (CheckAddressTaken && F.hasAddressTaken())
980f1a29dd3SDimitry Andric     return false;
981f1a29dd3SDimitry Andric   // Only safe to do if this function may be discarded if it is not used
982f1a29dd3SDimitry Andric   // in the compilation unit.
983f1a29dd3SDimitry Andric   if (!GlobalValue::isDiscardableIfUnused(F.getLinkage()))
984f1a29dd3SDimitry Andric     return false;
985f1a29dd3SDimitry Andric 
986f1a29dd3SDimitry Andric   // For AvailableExternallyLinkage functions.
987f1a29dd3SDimitry Andric   if (!F.hasComdat()) {
988f1a29dd3SDimitry Andric     assert(F.getLinkage() == GlobalValue::AvailableExternallyLinkage);
989f1a29dd3SDimitry Andric     return true;
990f1a29dd3SDimitry Andric   }
991f1a29dd3SDimitry Andric   return true;
992f1a29dd3SDimitry Andric }
9937a7e6055SDimitry Andric 
9947a7e6055SDimitry Andric // Parse the value profile options.
getMemOPSizeRangeFromOption(StringRef MemOPSizeRange,int64_t & RangeStart,int64_t & RangeLast)995302affcbSDimitry Andric void getMemOPSizeRangeFromOption(StringRef MemOPSizeRange, int64_t &RangeStart,
996302affcbSDimitry Andric                                  int64_t &RangeLast) {
9977a7e6055SDimitry Andric   static const int64_t DefaultMemOPSizeRangeStart = 0;
9987a7e6055SDimitry Andric   static const int64_t DefaultMemOPSizeRangeLast = 8;
9997a7e6055SDimitry Andric   RangeStart = DefaultMemOPSizeRangeStart;
10007a7e6055SDimitry Andric   RangeLast = DefaultMemOPSizeRangeLast;
10017a7e6055SDimitry Andric 
10027a7e6055SDimitry Andric   if (!MemOPSizeRange.empty()) {
1003302affcbSDimitry Andric     auto Pos = MemOPSizeRange.find(':');
10047a7e6055SDimitry Andric     if (Pos != std::string::npos) {
10057a7e6055SDimitry Andric       if (Pos > 0)
1006302affcbSDimitry Andric         MemOPSizeRange.substr(0, Pos).getAsInteger(10, RangeStart);
10077a7e6055SDimitry Andric       if (Pos < MemOPSizeRange.size() - 1)
1008302affcbSDimitry Andric         MemOPSizeRange.substr(Pos + 1).getAsInteger(10, RangeLast);
10097a7e6055SDimitry Andric     } else
1010302affcbSDimitry Andric       MemOPSizeRange.getAsInteger(10, RangeLast);
10117a7e6055SDimitry Andric   }
10127a7e6055SDimitry Andric   assert(RangeLast >= RangeStart);
10137a7e6055SDimitry Andric }
10147a7e6055SDimitry Andric 
10153ca95b02SDimitry Andric } // end namespace llvm
1016