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