1e78d131aSEugene Zelenko //===- InstrProf.cpp - Instrumented profiling format support --------------===//
2f8d79198SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8d79198SJustin Bogner //
7f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
8f8d79198SJustin Bogner //
9f8d79198SJustin Bogner // This file contains support for clang's instrumentation based PGO and
10f8d79198SJustin Bogner // coverage.
11f8d79198SJustin Bogner //
12f8d79198SJustin Bogner //===----------------------------------------------------------------------===//
13f8d79198SJustin Bogner
146bda14b3SChandler Carruth #include "llvm/ProfileData/InstrProf.h"
15e78d131aSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
16e78d131aSEugene Zelenko #include "llvm/ADT/SmallString.h"
17e78d131aSEugene Zelenko #include "llvm/ADT/SmallVector.h"
180c677878SXinliang David Li #include "llvm/ADT/StringExtras.h"
19e78d131aSEugene Zelenko #include "llvm/ADT/StringRef.h"
2097b68c5eSRong Xu #include "llvm/ADT/Triple.h"
216da7d314SMatthew Voss #include "llvm/Config/config.h"
22e78d131aSEugene Zelenko #include "llvm/IR/Constant.h"
23441959d2SXinliang David Li #include "llvm/IR/Constants.h"
24441959d2SXinliang David Li #include "llvm/IR/Function.h"
25e78d131aSEugene Zelenko #include "llvm/IR/GlobalValue.h"
26441959d2SXinliang David Li #include "llvm/IR/GlobalVariable.h"
27e78d131aSEugene Zelenko #include "llvm/IR/Instruction.h"
28e78d131aSEugene Zelenko #include "llvm/IR/LLVMContext.h"
29402477d2SXinliang David Li #include "llvm/IR/MDBuilder.h"
30e78d131aSEugene Zelenko #include "llvm/IR/Metadata.h"
31e413f1a0SXinliang David Li #include "llvm/IR/Module.h"
32e78d131aSEugene Zelenko #include "llvm/IR/Type.h"
33998b97f6SRong Xu #include "llvm/ProfileData/InstrProfReader.h"
34e78d131aSEugene Zelenko #include "llvm/Support/Casting.h"
35e78d131aSEugene Zelenko #include "llvm/Support/CommandLine.h"
36e78d131aSEugene Zelenko #include "llvm/Support/Compiler.h"
37e413f1a0SXinliang David Li #include "llvm/Support/Compression.h"
38e78d131aSEugene Zelenko #include "llvm/Support/Endian.h"
39e78d131aSEugene Zelenko #include "llvm/Support/Error.h"
40f8d79198SJustin Bogner #include "llvm/Support/ErrorHandling.h"
41e413f1a0SXinliang David Li #include "llvm/Support/LEB128.h"
42e78d131aSEugene Zelenko #include "llvm/Support/MathExtras.h"
439eb472baSXinliang David Li #include "llvm/Support/Path.h"
44e78d131aSEugene Zelenko #include "llvm/Support/SwapByteOrder.h"
45e78d131aSEugene Zelenko #include <algorithm>
46e78d131aSEugene Zelenko #include <cassert>
47e78d131aSEugene Zelenko #include <cstddef>
48e78d131aSEugene Zelenko #include <cstdint>
496bda14b3SChandler Carruth #include <cstring>
50e78d131aSEugene Zelenko #include <memory>
51e78d131aSEugene Zelenko #include <string>
52e78d131aSEugene Zelenko #include <system_error>
53a3beb340SSnehasish Kumar #include <type_traits>
54e78d131aSEugene Zelenko #include <utility>
55e78d131aSEugene Zelenko #include <vector>
56f8d79198SJustin Bogner
57f8d79198SJustin Bogner using namespace llvm;
58f8d79198SJustin Bogner
599eb472baSXinliang David Li static cl::opt<bool> StaticFuncFullModulePrefix(
608065f0b9SZachary Turner "static-func-full-module-prefix", cl::init(true), cl::Hidden,
619eb472baSXinliang David Li cl::desc("Use full module build paths in the profile counter names for "
629eb472baSXinliang David Li "static functions."));
639eb472baSXinliang David Li
64a1a9f705SRong Xu // This option is tailored to users that have different top-level directory in
65a1a9f705SRong Xu // profile-gen and profile-use compilation. Users need to specific the number
66a1a9f705SRong Xu // of levels to strip. A value larger than the number of directories in the
67a1a9f705SRong Xu // source file will strip all the directory names and only leave the basename.
68a1a9f705SRong Xu //
6908d08402SRong Xu // Note current ThinLTO module importing for the indirect-calls assumes
70a1a9f705SRong Xu // the source directory name not being stripped. A non-zero option value here
71a1a9f705SRong Xu // can potentially prevent some inter-module indirect-call-promotions.
72a1a9f705SRong Xu static cl::opt<unsigned> StaticFuncStripDirNamePrefix(
738065f0b9SZachary Turner "static-func-strip-dirname-prefix", cl::init(0), cl::Hidden,
74a1a9f705SRong Xu cl::desc("Strip specified level of directory name from source path in "
75a1a9f705SRong Xu "the profile counter name for static functions."));
76a1a9f705SRong Xu
getInstrProfErrString(instrprof_error Err,const std::string & ErrMsg="")77ee88b8d6SGulfem Savrun Yeniceri static std::string getInstrProfErrString(instrprof_error Err,
78ee88b8d6SGulfem Savrun Yeniceri const std::string &ErrMsg = "") {
79ee88b8d6SGulfem Savrun Yeniceri std::string Msg;
80ee88b8d6SGulfem Savrun Yeniceri raw_string_ostream OS(Msg);
81ee88b8d6SGulfem Savrun Yeniceri
829152fd17SVedant Kumar switch (Err) {
83f8d79198SJustin Bogner case instrprof_error::success:
84ee88b8d6SGulfem Savrun Yeniceri OS << "success";
85ee88b8d6SGulfem Savrun Yeniceri break;
86f8d79198SJustin Bogner case instrprof_error::eof:
87ee88b8d6SGulfem Savrun Yeniceri OS << "end of File";
88ee88b8d6SGulfem Savrun Yeniceri break;
894f823667SNathan Slingerland case instrprof_error::unrecognized_format:
90ee88b8d6SGulfem Savrun Yeniceri OS << "unrecognized instrumentation profile encoding format";
91ee88b8d6SGulfem Savrun Yeniceri break;
92f8d79198SJustin Bogner case instrprof_error::bad_magic:
93ee88b8d6SGulfem Savrun Yeniceri OS << "invalid instrumentation profile data (bad magic)";
94ee88b8d6SGulfem Savrun Yeniceri break;
95531bb481SDuncan P. N. Exon Smith case instrprof_error::bad_header:
96ee88b8d6SGulfem Savrun Yeniceri OS << "invalid instrumentation profile data (file header is corrupt)";
97ee88b8d6SGulfem Savrun Yeniceri break;
98f8d79198SJustin Bogner case instrprof_error::unsupported_version:
99ee88b8d6SGulfem Savrun Yeniceri OS << "unsupported instrumentation profile format version";
100ee88b8d6SGulfem Savrun Yeniceri break;
101b7aa2630SJustin Bogner case instrprof_error::unsupported_hash_type:
102ee88b8d6SGulfem Savrun Yeniceri OS << "unsupported instrumentation profile hash type";
103ee88b8d6SGulfem Savrun Yeniceri break;
104f8d79198SJustin Bogner case instrprof_error::too_large:
105ee88b8d6SGulfem Savrun Yeniceri OS << "too much profile data";
106ee88b8d6SGulfem Savrun Yeniceri break;
107f8d79198SJustin Bogner case instrprof_error::truncated:
108ee88b8d6SGulfem Savrun Yeniceri OS << "truncated profile data";
109ee88b8d6SGulfem Savrun Yeniceri break;
110f8d79198SJustin Bogner case instrprof_error::malformed:
111ee88b8d6SGulfem Savrun Yeniceri OS << "malformed instrumentation profile data";
112ee88b8d6SGulfem Savrun Yeniceri break;
11365d7fd02SEllis Hoag case instrprof_error::missing_debug_info_for_correlation:
11465d7fd02SEllis Hoag OS << "debug info for correlation is required";
11565d7fd02SEllis Hoag break;
11665d7fd02SEllis Hoag case instrprof_error::unexpected_debug_info_for_correlation:
11765d7fd02SEllis Hoag OS << "debug info for correlation is not necessary";
11865d7fd02SEllis Hoag break;
11965d7fd02SEllis Hoag case instrprof_error::unable_to_correlate_profile:
12065d7fd02SEllis Hoag OS << "unable to correlate profile";
12165d7fd02SEllis Hoag break;
1226da7d314SMatthew Voss case instrprof_error::invalid_prof:
123ee88b8d6SGulfem Savrun Yeniceri OS << "invalid profile created. Please file a bug "
1246da7d314SMatthew Voss "at: " BUG_REPORT_URL
1256da7d314SMatthew Voss " and include the profraw files that caused this error.";
126ee88b8d6SGulfem Savrun Yeniceri break;
127f8d79198SJustin Bogner case instrprof_error::unknown_function:
128ee88b8d6SGulfem Savrun Yeniceri OS << "no profile data available for function";
129ee88b8d6SGulfem Savrun Yeniceri break;
130b9bd7f85SJustin Bogner case instrprof_error::hash_mismatch:
131ee88b8d6SGulfem Savrun Yeniceri OS << "function control flow change detected (hash mismatch)";
132ee88b8d6SGulfem Savrun Yeniceri break;
133b9bd7f85SJustin Bogner case instrprof_error::count_mismatch:
134ee88b8d6SGulfem Savrun Yeniceri OS << "function basic block count change detected (counter mismatch)";
135ee88b8d6SGulfem Savrun Yeniceri break;
136b9bd7f85SJustin Bogner case instrprof_error::counter_overflow:
137ee88b8d6SGulfem Savrun Yeniceri OS << "counter overflow";
138ee88b8d6SGulfem Savrun Yeniceri break;
1399e9a057aSJustin Bogner case instrprof_error::value_site_count_mismatch:
140ee88b8d6SGulfem Savrun Yeniceri OS << "function value site count change detected (counter mismatch)";
141ee88b8d6SGulfem Savrun Yeniceri break;
14243cba733SVedant Kumar case instrprof_error::compress_failed:
143ee88b8d6SGulfem Savrun Yeniceri OS << "failed to compress data (zlib)";
144ee88b8d6SGulfem Savrun Yeniceri break;
14543cba733SVedant Kumar case instrprof_error::uncompress_failed:
146ee88b8d6SGulfem Savrun Yeniceri OS << "failed to uncompress data (zlib)";
147ee88b8d6SGulfem Savrun Yeniceri break;
1482c684cfdSRong Xu case instrprof_error::empty_raw_profile:
149ee88b8d6SGulfem Savrun Yeniceri OS << "empty raw profile file";
150ee88b8d6SGulfem Savrun Yeniceri break;
151b8cc0544SDavid Blaikie case instrprof_error::zlib_unavailable:
152ee88b8d6SGulfem Savrun Yeniceri OS << "profile uses zlib compression but the profile reader was built "
1538ea2a58aSFangrui Song "without zlib support";
154ee88b8d6SGulfem Savrun Yeniceri break;
155ee88b8d6SGulfem Savrun Yeniceri }
156ee88b8d6SGulfem Savrun Yeniceri
157ee88b8d6SGulfem Savrun Yeniceri // If optional error message is not empty, append it to the message.
158ee88b8d6SGulfem Savrun Yeniceri if (!ErrMsg.empty())
159126e7611SGulfem Savrun Yeniceri OS << ": " << ErrMsg;
160ee88b8d6SGulfem Savrun Yeniceri
161ee88b8d6SGulfem Savrun Yeniceri return OS.str();
162f8d79198SJustin Bogner }
1639152fd17SVedant Kumar
164e78d131aSEugene Zelenko namespace {
165e78d131aSEugene Zelenko
1664718f8b5SPeter Collingbourne // FIXME: This class is only here to support the transition to llvm::Error. It
1674718f8b5SPeter Collingbourne // will be removed once this transition is complete. Clients should prefer to
1684718f8b5SPeter Collingbourne // deal with the Error value directly, rather than converting to error_code.
1699152fd17SVedant Kumar class InstrProfErrorCategoryType : public std::error_category {
name() const170990504e6SReid Kleckner const char *name() const noexcept override { return "llvm.instrprof"; }
171e78d131aSEugene Zelenko
message(int IE) const1729152fd17SVedant Kumar std::string message(int IE) const override {
1739152fd17SVedant Kumar return getInstrProfErrString(static_cast<instrprof_error>(IE));
1749152fd17SVedant Kumar }
175f8d79198SJustin Bogner };
176e78d131aSEugene Zelenko
1776ac3f739SEugene Zelenko } // end anonymous namespace
178f8d79198SJustin Bogner
instrprof_category()17925188c95SRafael Espindola const std::error_category &llvm::instrprof_category() {
180ede60037SNicolai Hähnle static InstrProfErrorCategoryType ErrorCategory;
181ede60037SNicolai Hähnle return ErrorCategory;
182f8d79198SJustin Bogner }
183441959d2SXinliang David Li
18457dea2d3SXinliang David Li namespace {
18557dea2d3SXinliang David Li
18657dea2d3SXinliang David Li const char *InstrProfSectNameCommon[] = {
1871a6a2b64SVedant Kumar #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \
18857dea2d3SXinliang David Li SectNameCommon,
18957dea2d3SXinliang David Li #include "llvm/ProfileData/InstrProfData.inc"
19057dea2d3SXinliang David Li };
19157dea2d3SXinliang David Li
19257dea2d3SXinliang David Li const char *InstrProfSectNameCoff[] = {
1931a6a2b64SVedant Kumar #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \
19457dea2d3SXinliang David Li SectNameCoff,
19557dea2d3SXinliang David Li #include "llvm/ProfileData/InstrProfData.inc"
19657dea2d3SXinliang David Li };
19757dea2d3SXinliang David Li
19857dea2d3SXinliang David Li const char *InstrProfSectNamePrefix[] = {
1991a6a2b64SVedant Kumar #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \
20057dea2d3SXinliang David Li Prefix,
20157dea2d3SXinliang David Li #include "llvm/ProfileData/InstrProfData.inc"
20257dea2d3SXinliang David Li };
20357dea2d3SXinliang David Li
20457dea2d3SXinliang David Li } // namespace
20557dea2d3SXinliang David Li
206441959d2SXinliang David Li namespace llvm {
207441959d2SXinliang David Li
208dd1ea9deSVedant Kumar cl::opt<bool> DoInstrProfNameCompression(
209dd1ea9deSVedant Kumar "enable-name-compression",
210dd1ea9deSVedant Kumar cl::desc("Enable name/filename string compression"), cl::init(true));
211dd1ea9deSVedant Kumar
getInstrProfSectionName(InstrProfSectKind IPSK,Triple::ObjectFormatType OF,bool AddSegmentInfo)2121a6a2b64SVedant Kumar std::string getInstrProfSectionName(InstrProfSectKind IPSK,
2131a6a2b64SVedant Kumar Triple::ObjectFormatType OF,
2141a6a2b64SVedant Kumar bool AddSegmentInfo) {
2151a6a2b64SVedant Kumar std::string SectName;
21657dea2d3SXinliang David Li
2171a6a2b64SVedant Kumar if (OF == Triple::MachO && AddSegmentInfo)
2181a6a2b64SVedant Kumar SectName = InstrProfSectNamePrefix[IPSK];
21957dea2d3SXinliang David Li
2201a6a2b64SVedant Kumar if (OF == Triple::COFF)
2211a6a2b64SVedant Kumar SectName += InstrProfSectNameCoff[IPSK];
2221a6a2b64SVedant Kumar else
2231a6a2b64SVedant Kumar SectName += InstrProfSectNameCommon[IPSK];
2244a5ddf80SXinliang David Li
2251a6a2b64SVedant Kumar if (OF == Triple::MachO && IPSK == IPSK_data && AddSegmentInfo)
2261a6a2b64SVedant Kumar SectName += ",regular,live_support";
22757dea2d3SXinliang David Li
2281a6a2b64SVedant Kumar return SectName;
2294a5ddf80SXinliang David Li }
2304a5ddf80SXinliang David Li
addError(instrprof_error IE)23142369dbcSVedant Kumar void SoftInstrProfErrors::addError(instrprof_error IE) {
23242369dbcSVedant Kumar if (IE == instrprof_error::success)
23342369dbcSVedant Kumar return;
23442369dbcSVedant Kumar
23542369dbcSVedant Kumar if (FirstError == instrprof_error::success)
23642369dbcSVedant Kumar FirstError = IE;
23742369dbcSVedant Kumar
23842369dbcSVedant Kumar switch (IE) {
23942369dbcSVedant Kumar case instrprof_error::hash_mismatch:
24042369dbcSVedant Kumar ++NumHashMismatches;
24142369dbcSVedant Kumar break;
24242369dbcSVedant Kumar case instrprof_error::count_mismatch:
24342369dbcSVedant Kumar ++NumCountMismatches;
24442369dbcSVedant Kumar break;
24542369dbcSVedant Kumar case instrprof_error::counter_overflow:
24642369dbcSVedant Kumar ++NumCounterOverflows;
24742369dbcSVedant Kumar break;
24842369dbcSVedant Kumar case instrprof_error::value_site_count_mismatch:
24942369dbcSVedant Kumar ++NumValueSiteCountMismatches;
25042369dbcSVedant Kumar break;
25142369dbcSVedant Kumar default:
25242369dbcSVedant Kumar llvm_unreachable("Not a soft error");
25342369dbcSVedant Kumar }
25442369dbcSVedant Kumar }
25542369dbcSVedant Kumar
message() const2569152fd17SVedant Kumar std::string InstrProfError::message() const {
257ee88b8d6SGulfem Savrun Yeniceri return getInstrProfErrString(Err, Msg);
2589152fd17SVedant Kumar }
2599152fd17SVedant Kumar
2609152fd17SVedant Kumar char InstrProfError::ID = 0;
2619152fd17SVedant Kumar
getPGOFuncName(StringRef RawFuncName,GlobalValue::LinkageTypes Linkage,StringRef FileName,uint64_t Version LLVM_ATTRIBUTE_UNUSED)262441959d2SXinliang David Li std::string getPGOFuncName(StringRef RawFuncName,
263441959d2SXinliang David Li GlobalValue::LinkageTypes Linkage,
264a86545b0SXinliang David Li StringRef FileName,
265a86545b0SXinliang David Li uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
266b43027d1STeresa Johnson return GlobalValue::getGlobalIdentifier(RawFuncName, Linkage, FileName);
267441959d2SXinliang David Li }
268441959d2SXinliang David Li
269a1a9f705SRong Xu // Strip NumPrefix level of directory name from PathNameStr. If the number of
270a1a9f705SRong Xu // directory separators is less than NumPrefix, strip all the directories and
271a1a9f705SRong Xu // leave base file name only.
stripDirPrefix(StringRef PathNameStr,uint32_t NumPrefix)272a1a9f705SRong Xu static StringRef stripDirPrefix(StringRef PathNameStr, uint32_t NumPrefix) {
273a1a9f705SRong Xu uint32_t Count = NumPrefix;
274a1a9f705SRong Xu uint32_t Pos = 0, LastPos = 0;
275a1a9f705SRong Xu for (auto & CI : PathNameStr) {
276a1a9f705SRong Xu ++Pos;
277a1a9f705SRong Xu if (llvm::sys::path::is_separator(CI)) {
278a1a9f705SRong Xu LastPos = Pos;
279a1a9f705SRong Xu --Count;
280a1a9f705SRong Xu }
281a1a9f705SRong Xu if (Count == 0)
282a1a9f705SRong Xu break;
283a1a9f705SRong Xu }
284a1a9f705SRong Xu return PathNameStr.substr(LastPos);
285a1a9f705SRong Xu }
286a1a9f705SRong Xu
287b534166fSRong Xu // Return the PGOFuncName. This function has some special handling when called
288b534166fSRong Xu // in LTO optimization. The following only applies when calling in LTO passes
289b534166fSRong Xu // (when \c InLTO is true): LTO's internalization privatizes many global linkage
290b534166fSRong Xu // symbols. This happens after value profile annotation, but those internal
291b534166fSRong Xu // linkage functions should not have a source prefix.
2928c1bc986STeresa Johnson // Additionally, for ThinLTO mode, exported internal functions are promoted
2938c1bc986STeresa Johnson // and renamed. We need to ensure that the original internal PGO name is
2948c1bc986STeresa Johnson // used when computing the GUID that is compared against the profiled GUIDs.
295b534166fSRong Xu // To differentiate compiler generated internal symbols from original ones,
296b534166fSRong Xu // PGOFuncName meta data are created and attached to the original internal
297b534166fSRong Xu // symbols in the value profile annotation step
298b534166fSRong Xu // (PGOUseFunc::annotateIndirectCallSites). If a symbol does not have the meta
299b534166fSRong Xu // data, its original linkage must be non-internal.
getPGOFuncName(const Function & F,bool InLTO,uint64_t Version)300b534166fSRong Xu std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) {
3019eb472baSXinliang David Li if (!InLTO) {
30201622054SRong Xu StringRef FileName(F.getParent()->getSourceFileName());
30301622054SRong Xu uint32_t StripLevel = StaticFuncFullModulePrefix ? 0 : (uint32_t)-1;
30401622054SRong Xu if (StripLevel < StaticFuncStripDirNamePrefix)
30501622054SRong Xu StripLevel = StaticFuncStripDirNamePrefix;
30601622054SRong Xu if (StripLevel)
30701622054SRong Xu FileName = stripDirPrefix(FileName, StripLevel);
3089eb472baSXinliang David Li return getPGOFuncName(F.getName(), F.getLinkage(), FileName, Version);
3099eb472baSXinliang David Li }
310b534166fSRong Xu
3118e8fe859SRong Xu // In LTO mode (when InLTO is true), first check if there is a meta data.
3128e8fe859SRong Xu if (MDNode *MD = getPGOFuncNameMetadata(F)) {
313b534166fSRong Xu StringRef S = cast<MDString>(MD->getOperand(0))->getString();
314b534166fSRong Xu return S.str();
315b534166fSRong Xu }
316b534166fSRong Xu
317b534166fSRong Xu // If there is no meta data, the function must be a global before the value
318b534166fSRong Xu // profile annotation pass. Its current linkage may be internal if it is
319b534166fSRong Xu // internalized in LTO mode.
320b534166fSRong Xu return getPGOFuncName(F.getName(), GlobalValue::ExternalLinkage, "");
321441959d2SXinliang David Li }
322441959d2SXinliang David Li
getFuncNameWithoutPrefix(StringRef PGOFuncName,StringRef FileName)3234ec40140SXinliang David Li StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) {
3244ec40140SXinliang David Li if (FileName.empty())
32543a8565bSVedant Kumar return PGOFuncName;
3264ec40140SXinliang David Li // Drop the file name including ':'. See also getPGOFuncName.
3274ec40140SXinliang David Li if (PGOFuncName.startswith(FileName))
3284ec40140SXinliang David Li PGOFuncName = PGOFuncName.drop_front(FileName.size() + 1);
3294ec40140SXinliang David Li return PGOFuncName;
3304ec40140SXinliang David Li }
3314ec40140SXinliang David Li
332d1bab960SXinliang David Li // \p FuncName is the string used as profile lookup key for the function. A
333d1bab960SXinliang David Li // symbol is created to hold the name. Return the legalized symbol name.
getPGOFuncNameVarName(StringRef FuncName,GlobalValue::LinkageTypes Linkage)334aa0cae62SVedant Kumar std::string getPGOFuncNameVarName(StringRef FuncName,
335d1bab960SXinliang David Li GlobalValue::LinkageTypes Linkage) {
336adcd0268SBenjamin Kramer std::string VarName = std::string(getInstrProfNameVarPrefix());
337d1bab960SXinliang David Li VarName += FuncName;
338d1bab960SXinliang David Li
339d1bab960SXinliang David Li if (!GlobalValue::isLocalLinkage(Linkage))
340d1bab960SXinliang David Li return VarName;
341d1bab960SXinliang David Li
342d1bab960SXinliang David Li // Now fix up illegal chars in local VarName that may upset the assembler.
343eeaf0bcfSXinliang David Li const char *InvalidChars = "-:<>/\"'";
344d1bab960SXinliang David Li size_t found = VarName.find_first_of(InvalidChars);
345d1bab960SXinliang David Li while (found != std::string::npos) {
346d1bab960SXinliang David Li VarName[found] = '_';
347d1bab960SXinliang David Li found = VarName.find_first_of(InvalidChars, found + 1);
348d1bab960SXinliang David Li }
349d1bab960SXinliang David Li return VarName;
350d1bab960SXinliang David Li }
351d1bab960SXinliang David Li
createPGOFuncNameVar(Module & M,GlobalValue::LinkageTypes Linkage,StringRef PGOFuncName)352441959d2SXinliang David Li GlobalVariable *createPGOFuncNameVar(Module &M,
353441959d2SXinliang David Li GlobalValue::LinkageTypes Linkage,
354897d2923SXinliang David Li StringRef PGOFuncName) {
355441959d2SXinliang David Li // We generally want to match the function's linkage, but available_externally
356441959d2SXinliang David Li // and extern_weak both have the wrong semantics, and anything that doesn't
357441959d2SXinliang David Li // need to link across compilation units doesn't need to be visible at all.
358441959d2SXinliang David Li if (Linkage == GlobalValue::ExternalWeakLinkage)
359441959d2SXinliang David Li Linkage = GlobalValue::LinkOnceAnyLinkage;
360441959d2SXinliang David Li else if (Linkage == GlobalValue::AvailableExternallyLinkage)
361441959d2SXinliang David Li Linkage = GlobalValue::LinkOnceODRLinkage;
362441959d2SXinliang David Li else if (Linkage == GlobalValue::InternalLinkage ||
363441959d2SXinliang David Li Linkage == GlobalValue::ExternalLinkage)
364441959d2SXinliang David Li Linkage = GlobalValue::PrivateLinkage;
365441959d2SXinliang David Li
366897d2923SXinliang David Li auto *Value =
367897d2923SXinliang David Li ConstantDataArray::getString(M.getContext(), PGOFuncName, false);
368441959d2SXinliang David Li auto FuncNameVar =
369441959d2SXinliang David Li new GlobalVariable(M, Value->getType(), true, Linkage, Value,
370897d2923SXinliang David Li getPGOFuncNameVarName(PGOFuncName, Linkage));
371441959d2SXinliang David Li
372441959d2SXinliang David Li // Hide the symbol so that we correctly get a copy for each executable.
373441959d2SXinliang David Li if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
374441959d2SXinliang David Li FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);
375441959d2SXinliang David Li
376441959d2SXinliang David Li return FuncNameVar;
377441959d2SXinliang David Li }
378441959d2SXinliang David Li
createPGOFuncNameVar(Function & F,StringRef PGOFuncName)379897d2923SXinliang David Li GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) {
380897d2923SXinliang David Li return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
381441959d2SXinliang David Li }
382ee415895SXinliang David Li
create(Module & M,bool InLTO)383b5794ca9SVedant Kumar Error InstrProfSymtab::create(Module &M, bool InLTO) {
384b534166fSRong Xu for (Function &F : M) {
385b534166fSRong Xu // Function may not have a name: like using asm("") to overwrite the name.
386b534166fSRong Xu // Ignore in this case.
387b534166fSRong Xu if (!F.hasName())
388b534166fSRong Xu continue;
389b534166fSRong Xu const std::string &PGOFuncName = getPGOFuncName(F, InLTO);
390b5794ca9SVedant Kumar if (Error E = addFuncName(PGOFuncName))
391b5794ca9SVedant Kumar return E;
392d5a57b59SRong Xu MD5FuncMap.emplace_back(Function::getGUID(PGOFuncName), &F);
3934a435e08SDehao Chen // In ThinLTO, local function may have been promoted to global and have
394ef9d7db7SWei Mi // suffix ".llvm." added to the function name. We need to add the
395ef9d7db7SWei Mi // stripped function name to the symbol table so that we can find a match
396ef9d7db7SWei Mi // from profile.
397ef9d7db7SWei Mi //
398ef9d7db7SWei Mi // We may have other suffixes similar as ".llvm." which are needed to
399ef9d7db7SWei Mi // be stripped before the matching, but ".__uniq." suffix which is used
400ef9d7db7SWei Mi // to differentiate internal linkage functions in different modules
401ef9d7db7SWei Mi // should be kept. Now this is the only suffix with the pattern ".xxx"
402ef9d7db7SWei Mi // which is kept before matching.
403ef9d7db7SWei Mi const std::string UniqSuffix = ".__uniq.";
404ef9d7db7SWei Mi auto pos = PGOFuncName.find(UniqSuffix);
405ef9d7db7SWei Mi // Search '.' after ".__uniq." if ".__uniq." exists, otherwise
406ef9d7db7SWei Mi // search '.' from the beginning.
407ef9d7db7SWei Mi if (pos != std::string::npos)
408ef9d7db7SWei Mi pos += UniqSuffix.length();
409ef9d7db7SWei Mi else
410ef9d7db7SWei Mi pos = 0;
411ef9d7db7SWei Mi pos = PGOFuncName.find('.', pos);
412ef9d7db7SWei Mi if (pos != std::string::npos && pos != 0) {
4134a435e08SDehao Chen const std::string &OtherFuncName = PGOFuncName.substr(0, pos);
414b5794ca9SVedant Kumar if (Error E = addFuncName(OtherFuncName))
415b5794ca9SVedant Kumar return E;
4164a435e08SDehao Chen MD5FuncMap.emplace_back(Function::getGUID(OtherFuncName), &F);
4174a435e08SDehao Chen }
4184a435e08SDehao Chen }
41929a21babSMircea Trofin Sorted = false;
42059411db5SXinliang David Li finalizeSymtab();
421b5794ca9SVedant Kumar return Error::success();
42259411db5SXinliang David Li }
42359411db5SXinliang David Li
getFunctionHashFromAddress(uint64_t Address)424556f8f6aSMircea Trofin uint64_t InstrProfSymtab::getFunctionHashFromAddress(uint64_t Address) {
425556f8f6aSMircea Trofin finalizeSymtab();
42678ee2fbfSFangrui Song auto It = partition_point(AddrToMD5Map, [=](std::pair<uint64_t, uint64_t> A) {
42778ee2fbfSFangrui Song return A.first < Address;
428dc8de603SFangrui Song });
429556f8f6aSMircea Trofin // Raw function pointer collected by value profiler may be from
430556f8f6aSMircea Trofin // external functions that are not instrumented. They won't have
431556f8f6aSMircea Trofin // mapping data to be used by the deserializer. Force the value to
432556f8f6aSMircea Trofin // be 0 in this case.
43378ee2fbfSFangrui Song if (It != AddrToMD5Map.end() && It->first == Address)
43478ee2fbfSFangrui Song return (uint64_t)It->second;
435556f8f6aSMircea Trofin return 0;
436556f8f6aSMircea Trofin }
437556f8f6aSMircea Trofin
collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,bool doCompression,std::string & Result)4389d8ed265SBenjamin Kramer Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,
439e413f1a0SXinliang David Li bool doCompression, std::string &Result) {
440e78d131aSEugene Zelenko assert(!NameStrs.empty() && "No name data to emit");
44186705ba5SVedant Kumar
442e413f1a0SXinliang David Li uint8_t Header[16], *P = Header;
4430c677878SXinliang David Li std::string UncompressedNameStrings =
44486705ba5SVedant Kumar join(NameStrs.begin(), NameStrs.end(), getInstrProfNameSeparator());
44586705ba5SVedant Kumar
44686705ba5SVedant Kumar assert(StringRef(UncompressedNameStrings)
44786705ba5SVedant Kumar .count(getInstrProfNameSeparator()) == (NameStrs.size() - 1) &&
44886705ba5SVedant Kumar "PGO name is invalid (contains separator token)");
44913ea29b5SXinliang David Li
450e413f1a0SXinliang David Li unsigned EncLen = encodeULEB128(UncompressedNameStrings.length(), P);
451e413f1a0SXinliang David Li P += EncLen;
452120fe2e8SXinliang David Li
4530da23a27SBenjamin Kramer auto WriteStringToResult = [&](size_t CompressedLen, StringRef InputStr) {
454120fe2e8SXinliang David Li EncLen = encodeULEB128(CompressedLen, P);
455e413f1a0SXinliang David Li P += EncLen;
456120fe2e8SXinliang David Li char *HeaderStr = reinterpret_cast<char *>(&Header[0]);
457120fe2e8SXinliang David Li unsigned HeaderLen = P - &Header[0];
458120fe2e8SXinliang David Li Result.append(HeaderStr, HeaderLen);
459120fe2e8SXinliang David Li Result += InputStr;
4609152fd17SVedant Kumar return Error::success();
461120fe2e8SXinliang David Li };
462120fe2e8SXinliang David Li
4639152fd17SVedant Kumar if (!doCompression) {
464120fe2e8SXinliang David Li return WriteStringToResult(0, UncompressedNameStrings);
4659152fd17SVedant Kumar }
466120fe2e8SXinliang David Li
467*e690137dSFangrui Song SmallVector<uint8_t, 128> CompressedNameStrings;
468*e690137dSFangrui Song compression::zlib::compress(arrayRefFromStringRef(UncompressedNameStrings),
469ea61750cSCole Kissane CompressedNameStrings,
470ea61750cSCole Kissane compression::zlib::BestSizeCompression);
471120fe2e8SXinliang David Li
4720da23a27SBenjamin Kramer return WriteStringToResult(CompressedNameStrings.size(),
473*e690137dSFangrui Song toStringRef(CompressedNameStrings));
474e413f1a0SXinliang David Li }
475e413f1a0SXinliang David Li
getPGOFuncNameVarInitializer(GlobalVariable * NameVar)476eb7d7f87SXinliang David Li StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar) {
47737c1fa04SXinliang David Li auto *Arr = cast<ConstantDataArray>(NameVar->getInitializer());
47837c1fa04SXinliang David Li StringRef NameStr =
47937c1fa04SXinliang David Li Arr->isCString() ? Arr->getAsCString() : Arr->getAsString();
48037c1fa04SXinliang David Li return NameStr;
48137c1fa04SXinliang David Li }
48237c1fa04SXinliang David Li
collectPGOFuncNameStrings(ArrayRef<GlobalVariable * > NameVars,std::string & Result,bool doCompression)4839d8ed265SBenjamin Kramer Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
48473163756SXinliang David Li std::string &Result, bool doCompression) {
485e413f1a0SXinliang David Li std::vector<std::string> NameStrs;
486e413f1a0SXinliang David Li for (auto *NameVar : NameVars) {
487adcd0268SBenjamin Kramer NameStrs.push_back(std::string(getPGOFuncNameVarInitializer(NameVar)));
488e413f1a0SXinliang David Li }
48973163756SXinliang David Li return collectPGOFuncNameStrings(
490ea61750cSCole Kissane NameStrs, compression::zlib::isAvailable() && doCompression, Result);
491e413f1a0SXinliang David Li }
492e413f1a0SXinliang David Li
readPGOFuncNameStrings(StringRef NameStrings,InstrProfSymtab & Symtab)4939152fd17SVedant Kumar Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) {
4946a0746a9SFangrui Song const uint8_t *P = NameStrings.bytes_begin();
4956a0746a9SFangrui Song const uint8_t *EndP = NameStrings.bytes_end();
496e413f1a0SXinliang David Li while (P < EndP) {
497e413f1a0SXinliang David Li uint32_t N;
498e413f1a0SXinliang David Li uint64_t UncompressedSize = decodeULEB128(P, &N);
499e413f1a0SXinliang David Li P += N;
500e413f1a0SXinliang David Li uint64_t CompressedSize = decodeULEB128(P, &N);
501e413f1a0SXinliang David Li P += N;
502e413f1a0SXinliang David Li bool isCompressed = (CompressedSize != 0);
503*e690137dSFangrui Song SmallVector<uint8_t, 128> UncompressedNameStrings;
504e413f1a0SXinliang David Li StringRef NameStrings;
505e413f1a0SXinliang David Li if (isCompressed) {
506ea61750cSCole Kissane if (!llvm::compression::zlib::isAvailable())
507b8cc0544SDavid Blaikie return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
508b8cc0544SDavid Blaikie
509*e690137dSFangrui Song if (Error E = compression::zlib::uncompress(
510*e690137dSFangrui Song makeArrayRef(P, CompressedSize), UncompressedNameStrings,
511167ca4aeSGeorge Rimar UncompressedSize)) {
512167ca4aeSGeorge Rimar consumeError(std::move(E));
5139152fd17SVedant Kumar return make_error<InstrProfError>(instrprof_error::uncompress_failed);
514167ca4aeSGeorge Rimar }
515e413f1a0SXinliang David Li P += CompressedSize;
516*e690137dSFangrui Song NameStrings = toStringRef(UncompressedNameStrings);
517e413f1a0SXinliang David Li } else {
518e413f1a0SXinliang David Li NameStrings =
519e413f1a0SXinliang David Li StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
520e413f1a0SXinliang David Li P += UncompressedSize;
521e413f1a0SXinliang David Li }
522e413f1a0SXinliang David Li // Now parse the name strings.
523204efe2dSXinliang David Li SmallVector<StringRef, 0> Names;
52486705ba5SVedant Kumar NameStrings.split(Names, getInstrProfNameSeparator());
525204efe2dSXinliang David Li for (StringRef &Name : Names)
526b5794ca9SVedant Kumar if (Error E = Symtab.addFuncName(Name))
527b5794ca9SVedant Kumar return E;
528e413f1a0SXinliang David Li
529e413f1a0SXinliang David Li while (P < EndP && *P == 0)
530e413f1a0SXinliang David Li P++;
531e413f1a0SXinliang David Li }
5329152fd17SVedant Kumar return Error::success();
533e413f1a0SXinliang David Li }
534e413f1a0SXinliang David Li
accumulateCounts(CountSumOrPercent & Sum) const535e0fa2689SRong Xu void InstrProfRecord::accumulateCounts(CountSumOrPercent &Sum) const {
536998b97f6SRong Xu uint64_t FuncSum = 0;
537998b97f6SRong Xu Sum.NumEntries += Counts.size();
538ccdd5bb2SKazu Hirata for (uint64_t Count : Counts)
539ccdd5bb2SKazu Hirata FuncSum += Count;
540998b97f6SRong Xu Sum.CountSum += FuncSum;
541998b97f6SRong Xu
542998b97f6SRong Xu for (uint32_t VK = IPVK_First; VK <= IPVK_Last; ++VK) {
543998b97f6SRong Xu uint64_t KindSum = 0;
544998b97f6SRong Xu uint32_t NumValueSites = getNumValueSites(VK);
545998b97f6SRong Xu for (size_t I = 0; I < NumValueSites; ++I) {
546998b97f6SRong Xu uint32_t NV = getNumValueDataForSite(VK, I);
547998b97f6SRong Xu std::unique_ptr<InstrProfValueData[]> VD = getValueForSite(VK, I);
548998b97f6SRong Xu for (uint32_t V = 0; V < NV; V++)
549998b97f6SRong Xu KindSum += VD[V].Count;
550998b97f6SRong Xu }
551998b97f6SRong Xu Sum.ValueCounts[VK] += KindSum;
552998b97f6SRong Xu }
553998b97f6SRong Xu }
554998b97f6SRong Xu
overlap(InstrProfValueSiteRecord & Input,uint32_t ValueKind,OverlapStats & Overlap,OverlapStats & FuncLevelOverlap)555998b97f6SRong Xu void InstrProfValueSiteRecord::overlap(InstrProfValueSiteRecord &Input,
556998b97f6SRong Xu uint32_t ValueKind,
557998b97f6SRong Xu OverlapStats &Overlap,
558998b97f6SRong Xu OverlapStats &FuncLevelOverlap) {
559998b97f6SRong Xu this->sortByTargetValues();
560998b97f6SRong Xu Input.sortByTargetValues();
561998b97f6SRong Xu double Score = 0.0f, FuncLevelScore = 0.0f;
562998b97f6SRong Xu auto I = ValueData.begin();
563998b97f6SRong Xu auto IE = ValueData.end();
564998b97f6SRong Xu auto J = Input.ValueData.begin();
565998b97f6SRong Xu auto JE = Input.ValueData.end();
566998b97f6SRong Xu while (I != IE && J != JE) {
567998b97f6SRong Xu if (I->Value == J->Value) {
568998b97f6SRong Xu Score += OverlapStats::score(I->Count, J->Count,
569998b97f6SRong Xu Overlap.Base.ValueCounts[ValueKind],
570998b97f6SRong Xu Overlap.Test.ValueCounts[ValueKind]);
571998b97f6SRong Xu FuncLevelScore += OverlapStats::score(
572998b97f6SRong Xu I->Count, J->Count, FuncLevelOverlap.Base.ValueCounts[ValueKind],
573998b97f6SRong Xu FuncLevelOverlap.Test.ValueCounts[ValueKind]);
574998b97f6SRong Xu ++I;
575998b97f6SRong Xu } else if (I->Value < J->Value) {
576998b97f6SRong Xu ++I;
577998b97f6SRong Xu continue;
578998b97f6SRong Xu }
579998b97f6SRong Xu ++J;
580998b97f6SRong Xu }
581998b97f6SRong Xu Overlap.Overlap.ValueCounts[ValueKind] += Score;
582998b97f6SRong Xu FuncLevelOverlap.Overlap.ValueCounts[ValueKind] += FuncLevelScore;
583998b97f6SRong Xu }
584998b97f6SRong Xu
585998b97f6SRong Xu // Return false on mismatch.
overlapValueProfData(uint32_t ValueKind,InstrProfRecord & Other,OverlapStats & Overlap,OverlapStats & FuncLevelOverlap)586998b97f6SRong Xu void InstrProfRecord::overlapValueProfData(uint32_t ValueKind,
587998b97f6SRong Xu InstrProfRecord &Other,
588998b97f6SRong Xu OverlapStats &Overlap,
589998b97f6SRong Xu OverlapStats &FuncLevelOverlap) {
590998b97f6SRong Xu uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
5916435102cSEric Christopher assert(ThisNumValueSites == Other.getNumValueSites(ValueKind));
592998b97f6SRong Xu if (!ThisNumValueSites)
593998b97f6SRong Xu return;
594998b97f6SRong Xu
595998b97f6SRong Xu std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
596998b97f6SRong Xu getOrCreateValueSitesForKind(ValueKind);
597998b97f6SRong Xu MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
598998b97f6SRong Xu Other.getValueSitesForKind(ValueKind);
599998b97f6SRong Xu for (uint32_t I = 0; I < ThisNumValueSites; I++)
600998b97f6SRong Xu ThisSiteRecords[I].overlap(OtherSiteRecords[I], ValueKind, Overlap,
601998b97f6SRong Xu FuncLevelOverlap);
602998b97f6SRong Xu }
603998b97f6SRong Xu
overlap(InstrProfRecord & Other,OverlapStats & Overlap,OverlapStats & FuncLevelOverlap,uint64_t ValueCutoff)604998b97f6SRong Xu void InstrProfRecord::overlap(InstrProfRecord &Other, OverlapStats &Overlap,
605998b97f6SRong Xu OverlapStats &FuncLevelOverlap,
606998b97f6SRong Xu uint64_t ValueCutoff) {
607998b97f6SRong Xu // FuncLevel CountSum for other should already computed and nonzero.
608998b97f6SRong Xu assert(FuncLevelOverlap.Test.CountSum >= 1.0f);
609e0fa2689SRong Xu accumulateCounts(FuncLevelOverlap.Base);
610998b97f6SRong Xu bool Mismatch = (Counts.size() != Other.Counts.size());
611998b97f6SRong Xu
612998b97f6SRong Xu // Check if the value profiles mismatch.
613998b97f6SRong Xu if (!Mismatch) {
614998b97f6SRong Xu for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
615998b97f6SRong Xu uint32_t ThisNumValueSites = getNumValueSites(Kind);
616998b97f6SRong Xu uint32_t OtherNumValueSites = Other.getNumValueSites(Kind);
617998b97f6SRong Xu if (ThisNumValueSites != OtherNumValueSites) {
618998b97f6SRong Xu Mismatch = true;
619998b97f6SRong Xu break;
620998b97f6SRong Xu }
621998b97f6SRong Xu }
622998b97f6SRong Xu }
623998b97f6SRong Xu if (Mismatch) {
624998b97f6SRong Xu Overlap.addOneMismatch(FuncLevelOverlap.Test);
625998b97f6SRong Xu return;
626998b97f6SRong Xu }
627998b97f6SRong Xu
628998b97f6SRong Xu // Compute overlap for value counts.
629998b97f6SRong Xu for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
630998b97f6SRong Xu overlapValueProfData(Kind, Other, Overlap, FuncLevelOverlap);
631998b97f6SRong Xu
632998b97f6SRong Xu double Score = 0.0;
633998b97f6SRong Xu uint64_t MaxCount = 0;
634998b97f6SRong Xu // Compute overlap for edge counts.
635998b97f6SRong Xu for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
636998b97f6SRong Xu Score += OverlapStats::score(Counts[I], Other.Counts[I],
637998b97f6SRong Xu Overlap.Base.CountSum, Overlap.Test.CountSum);
638998b97f6SRong Xu MaxCount = std::max(Other.Counts[I], MaxCount);
639998b97f6SRong Xu }
640998b97f6SRong Xu Overlap.Overlap.CountSum += Score;
641998b97f6SRong Xu Overlap.Overlap.NumEntries += 1;
642998b97f6SRong Xu
643998b97f6SRong Xu if (MaxCount >= ValueCutoff) {
644998b97f6SRong Xu double FuncScore = 0.0;
645998b97f6SRong Xu for (size_t I = 0, E = Other.Counts.size(); I < E; ++I)
646998b97f6SRong Xu FuncScore += OverlapStats::score(Counts[I], Other.Counts[I],
647998b97f6SRong Xu FuncLevelOverlap.Base.CountSum,
648998b97f6SRong Xu FuncLevelOverlap.Test.CountSum);
649998b97f6SRong Xu FuncLevelOverlap.Overlap.CountSum = FuncScore;
650998b97f6SRong Xu FuncLevelOverlap.Overlap.NumEntries = Other.Counts.size();
651998b97f6SRong Xu FuncLevelOverlap.Valid = true;
652998b97f6SRong Xu }
653998b97f6SRong Xu }
654998b97f6SRong Xu
merge(InstrProfValueSiteRecord & Input,uint64_t Weight,function_ref<void (instrprof_error)> Warn)65598cce003SDavid Blaikie void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
65698cce003SDavid Blaikie uint64_t Weight,
65798cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
6585c24da5dSXinliang David Li this->sortByTargetValues();
6595c24da5dSXinliang David Li Input.sortByTargetValues();
6605c24da5dSXinliang David Li auto I = ValueData.begin();
6615c24da5dSXinliang David Li auto IE = ValueData.end();
662f240e528SKazu Hirata for (const InstrProfValueData &J : Input.ValueData) {
663f240e528SKazu Hirata while (I != IE && I->Value < J.Value)
6645c24da5dSXinliang David Li ++I;
665f240e528SKazu Hirata if (I != IE && I->Value == J.Value) {
6665c24da5dSXinliang David Li bool Overflowed;
667f240e528SKazu Hirata I->Count = SaturatingMultiplyAdd(J.Count, Weight, I->Count, &Overflowed);
6685c24da5dSXinliang David Li if (Overflowed)
66998cce003SDavid Blaikie Warn(instrprof_error::counter_overflow);
6705c24da5dSXinliang David Li ++I;
6715c24da5dSXinliang David Li continue;
6725c24da5dSXinliang David Li }
673f240e528SKazu Hirata ValueData.insert(I, J);
6745c24da5dSXinliang David Li }
6755c24da5dSXinliang David Li }
6765c24da5dSXinliang David Li
scale(uint64_t N,uint64_t D,function_ref<void (instrprof_error)> Warn)677a23f6234SWei Mi void InstrProfValueSiteRecord::scale(uint64_t N, uint64_t D,
67898cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
679ccdd5bb2SKazu Hirata for (InstrProfValueData &I : ValueData) {
68051dc04cfSXinliang David Li bool Overflowed;
681ccdd5bb2SKazu Hirata I.Count = SaturatingMultiply(I.Count, N, &Overflowed) / D;
68251dc04cfSXinliang David Li if (Overflowed)
68398cce003SDavid Blaikie Warn(instrprof_error::counter_overflow);
68451dc04cfSXinliang David Li }
68551dc04cfSXinliang David Li }
68651dc04cfSXinliang David Li
687020f22d8SXinliang David Li // Merge Value Profile data from Src record to this record for ValueKind.
688020f22d8SXinliang David Li // Scale merged value counts by \p Weight.
mergeValueProfData(uint32_t ValueKind,InstrProfRecord & Src,uint64_t Weight,function_ref<void (instrprof_error)> Warn)68998cce003SDavid Blaikie void InstrProfRecord::mergeValueProfData(
69098cce003SDavid Blaikie uint32_t ValueKind, InstrProfRecord &Src, uint64_t Weight,
69198cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
692020f22d8SXinliang David Li uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
693020f22d8SXinliang David Li uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
69442369dbcSVedant Kumar if (ThisNumValueSites != OtherNumValueSites) {
69598cce003SDavid Blaikie Warn(instrprof_error::value_site_count_mismatch);
69642369dbcSVedant Kumar return;
69742369dbcSVedant Kumar }
698d16a61d2SDavid Blaikie if (!ThisNumValueSites)
699d16a61d2SDavid Blaikie return;
700020f22d8SXinliang David Li std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
701d16a61d2SDavid Blaikie getOrCreateValueSitesForKind(ValueKind);
702d16a61d2SDavid Blaikie MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
703020f22d8SXinliang David Li Src.getValueSitesForKind(ValueKind);
704020f22d8SXinliang David Li for (uint32_t I = 0; I < ThisNumValueSites; I++)
70598cce003SDavid Blaikie ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight, Warn);
706020f22d8SXinliang David Li }
707020f22d8SXinliang David Li
merge(InstrProfRecord & Other,uint64_t Weight,function_ref<void (instrprof_error)> Warn)70898cce003SDavid Blaikie void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
70998cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
710020f22d8SXinliang David Li // If the number of counters doesn't match we either have bad data
711020f22d8SXinliang David Li // or a hash collision.
71242369dbcSVedant Kumar if (Counts.size() != Other.Counts.size()) {
71398cce003SDavid Blaikie Warn(instrprof_error::count_mismatch);
71442369dbcSVedant Kumar return;
71542369dbcSVedant Kumar }
716020f22d8SXinliang David Li
717020f22d8SXinliang David Li for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
718020f22d8SXinliang David Li bool Overflowed;
7197bee3168SNathan Slingerland Counts[I] =
7207bee3168SNathan Slingerland SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
721020f22d8SXinliang David Li if (Overflowed)
72298cce003SDavid Blaikie Warn(instrprof_error::counter_overflow);
723020f22d8SXinliang David Li }
724020f22d8SXinliang David Li
725020f22d8SXinliang David Li for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
72698cce003SDavid Blaikie mergeValueProfData(Kind, Other, Weight, Warn);
727020f22d8SXinliang David Li }
728a716cc5cSXinliang David Li
scaleValueProfData(uint32_t ValueKind,uint64_t N,uint64_t D,function_ref<void (instrprof_error)> Warn)72998cce003SDavid Blaikie void InstrProfRecord::scaleValueProfData(
730a23f6234SWei Mi uint32_t ValueKind, uint64_t N, uint64_t D,
73198cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
732d16a61d2SDavid Blaikie for (auto &R : getValueSitesForKind(ValueKind))
733a23f6234SWei Mi R.scale(N, D, Warn);
73451dc04cfSXinliang David Li }
73551dc04cfSXinliang David Li
scale(uint64_t N,uint64_t D,function_ref<void (instrprof_error)> Warn)736a23f6234SWei Mi void InstrProfRecord::scale(uint64_t N, uint64_t D,
73798cce003SDavid Blaikie function_ref<void(instrprof_error)> Warn) {
738a23f6234SWei Mi assert(D != 0 && "D cannot be 0");
73951dc04cfSXinliang David Li for (auto &Count : this->Counts) {
74051dc04cfSXinliang David Li bool Overflowed;
741a23f6234SWei Mi Count = SaturatingMultiply(Count, N, &Overflowed) / D;
74242369dbcSVedant Kumar if (Overflowed)
74398cce003SDavid Blaikie Warn(instrprof_error::counter_overflow);
74451dc04cfSXinliang David Li }
74551dc04cfSXinliang David Li for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
746a23f6234SWei Mi scaleValueProfData(Kind, N, D, Warn);
74751dc04cfSXinliang David Li }
74851dc04cfSXinliang David Li
749020f22d8SXinliang David Li // Map indirect call target name hash to name string.
remapValue(uint64_t Value,uint32_t ValueKind,InstrProfSymtab * SymTab)750020f22d8SXinliang David Li uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind,
751556f8f6aSMircea Trofin InstrProfSymtab *SymTab) {
752556f8f6aSMircea Trofin if (!SymTab)
753020f22d8SXinliang David Li return Value;
754556f8f6aSMircea Trofin
755556f8f6aSMircea Trofin if (ValueKind == IPVK_IndirectCallTarget)
756556f8f6aSMircea Trofin return SymTab->getFunctionHashFromAddress(Value);
757556f8f6aSMircea Trofin
758020f22d8SXinliang David Li return Value;
759020f22d8SXinliang David Li }
760020f22d8SXinliang David Li
addValueData(uint32_t ValueKind,uint32_t Site,InstrProfValueData * VData,uint32_t N,InstrProfSymtab * ValueMap)761020f22d8SXinliang David Li void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site,
762020f22d8SXinliang David Li InstrProfValueData *VData, uint32_t N,
763556f8f6aSMircea Trofin InstrProfSymtab *ValueMap) {
764020f22d8SXinliang David Li for (uint32_t I = 0; I < N; I++) {
765a716cc5cSXinliang David Li VData[I].Value = remapValue(VData[I].Value, ValueKind, ValueMap);
766020f22d8SXinliang David Li }
767020f22d8SXinliang David Li std::vector<InstrProfValueSiteRecord> &ValueSites =
768d16a61d2SDavid Blaikie getOrCreateValueSitesForKind(ValueKind);
769020f22d8SXinliang David Li if (N == 0)
7706b22ba68SVedant Kumar ValueSites.emplace_back();
771020f22d8SXinliang David Li else
772020f22d8SXinliang David Li ValueSites.emplace_back(VData, VData + N);
773020f22d8SXinliang David Li }
774020f22d8SXinliang David Li
775b75544a6SXinliang David Li #define INSTR_PROF_COMMON_API_IMPL
776b75544a6SXinliang David Li #include "llvm/ProfileData/InstrProfData.inc"
777ee415895SXinliang David Li
778b75544a6SXinliang David Li /*!
7795f8f34e4SAdrian Prantl * ValueProfRecordClosure Interface implementation for InstrProfRecord
780ed966771SXinliang David Li * class. These C wrappers are used as adaptors so that C++ code can be
781ed966771SXinliang David Li * invoked as callbacks.
782ed966771SXinliang David Li */
getNumValueKindsInstrProf(const void * Record)783f47cf550SXinliang David Li uint32_t getNumValueKindsInstrProf(const void *Record) {
784f47cf550SXinliang David Li return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
785f47cf550SXinliang David Li }
786f47cf550SXinliang David Li
getNumValueSitesInstrProf(const void * Record,uint32_t VKind)787f47cf550SXinliang David Li uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
788f47cf550SXinliang David Li return reinterpret_cast<const InstrProfRecord *>(Record)
789f47cf550SXinliang David Li ->getNumValueSites(VKind);
790f47cf550SXinliang David Li }
791f47cf550SXinliang David Li
getNumValueDataInstrProf(const void * Record,uint32_t VKind)792f47cf550SXinliang David Li uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
793f47cf550SXinliang David Li return reinterpret_cast<const InstrProfRecord *>(Record)
794f47cf550SXinliang David Li ->getNumValueData(VKind);
795f47cf550SXinliang David Li }
796f47cf550SXinliang David Li
getNumValueDataForSiteInstrProf(const void * R,uint32_t VK,uint32_t S)797f47cf550SXinliang David Li uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
798f47cf550SXinliang David Li uint32_t S) {
799f47cf550SXinliang David Li return reinterpret_cast<const InstrProfRecord *>(R)
800f47cf550SXinliang David Li ->getNumValueDataForSite(VK, S);
801f47cf550SXinliang David Li }
802f47cf550SXinliang David Li
getValueForSiteInstrProf(const void * R,InstrProfValueData * Dst,uint32_t K,uint32_t S)803f47cf550SXinliang David Li void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
8041e4c809cSXinliang David Li uint32_t K, uint32_t S) {
8051e4c809cSXinliang David Li reinterpret_cast<const InstrProfRecord *>(R)->getValueForSite(Dst, K, S);
806e809231bSXinliang David Li }
807e809231bSXinliang David Li
allocValueProfDataInstrProf(size_t TotalSizeInBytes)808f47cf550SXinliang David Li ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
80938b9a32fSXinliang David Li ValueProfData *VD =
81038b9a32fSXinliang David Li (ValueProfData *)(new (::operator new(TotalSizeInBytes)) ValueProfData());
81138b9a32fSXinliang David Li memset(VD, 0, TotalSizeInBytes);
81238b9a32fSXinliang David Li return VD;
813f47cf550SXinliang David Li }
814f47cf550SXinliang David Li
815f47cf550SXinliang David Li static ValueProfRecordClosure InstrProfRecordClosure = {
8166ac3f739SEugene Zelenko nullptr,
817f47cf550SXinliang David Li getNumValueKindsInstrProf,
818f47cf550SXinliang David Li getNumValueSitesInstrProf,
819f47cf550SXinliang David Li getNumValueDataInstrProf,
820f47cf550SXinliang David Li getNumValueDataForSiteInstrProf,
8216ac3f739SEugene Zelenko nullptr,
822f47cf550SXinliang David Li getValueForSiteInstrProf,
82338b9a32fSXinliang David Li allocValueProfDataInstrProf};
824f47cf550SXinliang David Li
825e809231bSXinliang David Li // Wrapper implementation using the closure mechanism.
getSize(const InstrProfRecord & Record)826f47cf550SXinliang David Li uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
827d6f10a62SXinliang David Li auto Closure = InstrProfRecordClosure;
828d6f10a62SXinliang David Li Closure.Record = &Record;
829d6f10a62SXinliang David Li return getValueProfDataSize(&Closure);
830f47cf550SXinliang David Li }
831f47cf550SXinliang David Li
832e809231bSXinliang David Li // Wrapper implementation using the closure mechanism.
833f47cf550SXinliang David Li std::unique_ptr<ValueProfData>
serializeFrom(const InstrProfRecord & Record)834f47cf550SXinliang David Li ValueProfData::serializeFrom(const InstrProfRecord &Record) {
835f47cf550SXinliang David Li InstrProfRecordClosure.Record = &Record;
836f47cf550SXinliang David Li
837f47cf550SXinliang David Li std::unique_ptr<ValueProfData> VPD(
8380e6a36e1SXinliang David Li serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr));
839f47cf550SXinliang David Li return VPD;
840f47cf550SXinliang David Li }
841f47cf550SXinliang David Li
deserializeTo(InstrProfRecord & Record,InstrProfSymtab * SymTab)842e809231bSXinliang David Li void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
843556f8f6aSMircea Trofin InstrProfSymtab *SymTab) {
844e809231bSXinliang David Li Record.reserveSites(Kind, NumValueSites);
845e809231bSXinliang David Li
846e809231bSXinliang David Li InstrProfValueData *ValueData = getValueProfRecordValueData(this);
847e809231bSXinliang David Li for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
848e809231bSXinliang David Li uint8_t ValueDataCount = this->SiteCountArray[VSite];
849556f8f6aSMircea Trofin Record.addValueData(Kind, VSite, ValueData, ValueDataCount, SymTab);
850e809231bSXinliang David Li ValueData += ValueDataCount;
851e809231bSXinliang David Li }
852e809231bSXinliang David Li }
853ed966771SXinliang David Li
854e809231bSXinliang David Li // For writing/serializing, Old is the host endianness, and New is
855e809231bSXinliang David Li // byte order intended on disk. For Reading/deserialization, Old
856e809231bSXinliang David Li // is the on-disk source endianness, and New is the host endianness.
swapBytes(support::endianness Old,support::endianness New)857e809231bSXinliang David Li void ValueProfRecord::swapBytes(support::endianness Old,
858e809231bSXinliang David Li support::endianness New) {
859e809231bSXinliang David Li using namespace support;
860e78d131aSEugene Zelenko
861e809231bSXinliang David Li if (Old == New)
862e809231bSXinliang David Li return;
863e809231bSXinliang David Li
864e809231bSXinliang David Li if (getHostEndianness() != Old) {
865e809231bSXinliang David Li sys::swapByteOrder<uint32_t>(NumValueSites);
866e809231bSXinliang David Li sys::swapByteOrder<uint32_t>(Kind);
867e809231bSXinliang David Li }
868e809231bSXinliang David Li uint32_t ND = getValueProfRecordNumValueData(this);
869e809231bSXinliang David Li InstrProfValueData *VD = getValueProfRecordValueData(this);
870e809231bSXinliang David Li
871e809231bSXinliang David Li // No need to swap byte array: SiteCountArrray.
872e809231bSXinliang David Li for (uint32_t I = 0; I < ND; I++) {
873e809231bSXinliang David Li sys::swapByteOrder<uint64_t>(VD[I].Value);
874e809231bSXinliang David Li sys::swapByteOrder<uint64_t>(VD[I].Count);
875e809231bSXinliang David Li }
876e809231bSXinliang David Li if (getHostEndianness() == Old) {
877e809231bSXinliang David Li sys::swapByteOrder<uint32_t>(NumValueSites);
878e809231bSXinliang David Li sys::swapByteOrder<uint32_t>(Kind);
879e809231bSXinliang David Li }
880e809231bSXinliang David Li }
881e809231bSXinliang David Li
deserializeTo(InstrProfRecord & Record,InstrProfSymtab * SymTab)882e809231bSXinliang David Li void ValueProfData::deserializeTo(InstrProfRecord &Record,
883556f8f6aSMircea Trofin InstrProfSymtab *SymTab) {
884e809231bSXinliang David Li if (NumValueKinds == 0)
885e809231bSXinliang David Li return;
886e809231bSXinliang David Li
887e809231bSXinliang David Li ValueProfRecord *VR = getFirstValueProfRecord(this);
888e809231bSXinliang David Li for (uint32_t K = 0; K < NumValueKinds; K++) {
889556f8f6aSMircea Trofin VR->deserializeTo(Record, SymTab);
890e809231bSXinliang David Li VR = getValueProfRecordNext(VR);
891e809231bSXinliang David Li }
892e809231bSXinliang David Li }
893e809231bSXinliang David Li
894e809231bSXinliang David Li template <class T>
swapToHostOrder(const unsigned char * & D,support::endianness Orig)895e809231bSXinliang David Li static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
896e809231bSXinliang David Li using namespace support;
897e78d131aSEugene Zelenko
898e809231bSXinliang David Li if (Orig == little)
899e809231bSXinliang David Li return endian::readNext<T, little, unaligned>(D);
900e809231bSXinliang David Li else
901e809231bSXinliang David Li return endian::readNext<T, big, unaligned>(D);
902e809231bSXinliang David Li }
903e809231bSXinliang David Li
allocValueProfData(uint32_t TotalSize)904e809231bSXinliang David Li static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
905e809231bSXinliang David Li return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
906e809231bSXinliang David Li ValueProfData());
907e809231bSXinliang David Li }
908e809231bSXinliang David Li
checkIntegrity()9099152fd17SVedant Kumar Error ValueProfData::checkIntegrity() {
9108e32f4d5SXinliang David Li if (NumValueKinds > IPVK_Last + 1)
911ee88b8d6SGulfem Savrun Yeniceri return make_error<InstrProfError>(
912ee88b8d6SGulfem Savrun Yeniceri instrprof_error::malformed, "number of value profile kinds is invalid");
913ee88b8d6SGulfem Savrun Yeniceri // Total size needs to be multiple of quadword size.
9148e32f4d5SXinliang David Li if (TotalSize % sizeof(uint64_t))
915ee88b8d6SGulfem Savrun Yeniceri return make_error<InstrProfError>(
916ee88b8d6SGulfem Savrun Yeniceri instrprof_error::malformed, "total size is not multiples of quardword");
9178e32f4d5SXinliang David Li
9188e32f4d5SXinliang David Li ValueProfRecord *VR = getFirstValueProfRecord(this);
9198e32f4d5SXinliang David Li for (uint32_t K = 0; K < this->NumValueKinds; K++) {
9208e32f4d5SXinliang David Li if (VR->Kind > IPVK_Last)
921ee88b8d6SGulfem Savrun Yeniceri return make_error<InstrProfError>(instrprof_error::malformed,
922ee88b8d6SGulfem Savrun Yeniceri "value kind is invalid");
9238e32f4d5SXinliang David Li VR = getValueProfRecordNext(VR);
9248e32f4d5SXinliang David Li if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
925ee88b8d6SGulfem Savrun Yeniceri return make_error<InstrProfError>(
926ee88b8d6SGulfem Savrun Yeniceri instrprof_error::malformed,
927ee88b8d6SGulfem Savrun Yeniceri "value profile address is greater than total size");
9288e32f4d5SXinliang David Li }
9299152fd17SVedant Kumar return Error::success();
9308e32f4d5SXinliang David Li }
9318e32f4d5SXinliang David Li
9329152fd17SVedant Kumar Expected<std::unique_ptr<ValueProfData>>
getValueProfData(const unsigned char * D,const unsigned char * const BufferEnd,support::endianness Endianness)933ee415895SXinliang David Li ValueProfData::getValueProfData(const unsigned char *D,
934ee415895SXinliang David Li const unsigned char *const BufferEnd,
935ee415895SXinliang David Li support::endianness Endianness) {
936ee415895SXinliang David Li using namespace support;
937e78d131aSEugene Zelenko
938ee415895SXinliang David Li if (D + sizeof(ValueProfData) > BufferEnd)
9399152fd17SVedant Kumar return make_error<InstrProfError>(instrprof_error::truncated);
940ee415895SXinliang David Li
941b8c3ad1dSXinliang David Li const unsigned char *Header = D;
942b8c3ad1dSXinliang David Li uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
943ee415895SXinliang David Li if (D + TotalSize > BufferEnd)
9449152fd17SVedant Kumar return make_error<InstrProfError>(instrprof_error::too_large);
945ee415895SXinliang David Li
946f47cf550SXinliang David Li std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
947ee415895SXinliang David Li memcpy(VPD.get(), D, TotalSize);
948ee415895SXinliang David Li // Byte swap.
949ee415895SXinliang David Li VPD->swapBytesToHost(Endianness);
950ee415895SXinliang David Li
9519152fd17SVedant Kumar Error E = VPD->checkIntegrity();
9529152fd17SVedant Kumar if (E)
953c55cf4afSBill Wendling return std::move(E);
954ee415895SXinliang David Li
955c55cf4afSBill Wendling return std::move(VPD);
956ee415895SXinliang David Li }
957ee415895SXinliang David Li
swapBytesToHost(support::endianness Endianness)958ee415895SXinliang David Li void ValueProfData::swapBytesToHost(support::endianness Endianness) {
959ee415895SXinliang David Li using namespace support;
960e78d131aSEugene Zelenko
961ee415895SXinliang David Li if (Endianness == getHostEndianness())
962ee415895SXinliang David Li return;
963ee415895SXinliang David Li
964ee415895SXinliang David Li sys::swapByteOrder<uint32_t>(TotalSize);
965ee415895SXinliang David Li sys::swapByteOrder<uint32_t>(NumValueKinds);
966ee415895SXinliang David Li
967f47cf550SXinliang David Li ValueProfRecord *VR = getFirstValueProfRecord(this);
968ee415895SXinliang David Li for (uint32_t K = 0; K < NumValueKinds; K++) {
969ee415895SXinliang David Li VR->swapBytes(Endianness, getHostEndianness());
970ac5b8606SXinliang David Li VR = getValueProfRecordNext(VR);
971ee415895SXinliang David Li }
972ee415895SXinliang David Li }
973ee415895SXinliang David Li
swapBytesFromHost(support::endianness Endianness)974ee415895SXinliang David Li void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
975ee415895SXinliang David Li using namespace support;
976e78d131aSEugene Zelenko
977ee415895SXinliang David Li if (Endianness == getHostEndianness())
978ee415895SXinliang David Li return;
979ee415895SXinliang David Li
980f47cf550SXinliang David Li ValueProfRecord *VR = getFirstValueProfRecord(this);
981ee415895SXinliang David Li for (uint32_t K = 0; K < NumValueKinds; K++) {
982ac5b8606SXinliang David Li ValueProfRecord *NVR = getValueProfRecordNext(VR);
983ee415895SXinliang David Li VR->swapBytes(getHostEndianness(), Endianness);
984ee415895SXinliang David Li VR = NVR;
985ee415895SXinliang David Li }
986ee415895SXinliang David Li sys::swapByteOrder<uint32_t>(TotalSize);
987ee415895SXinliang David Li sys::swapByteOrder<uint32_t>(NumValueKinds);
988ee415895SXinliang David Li }
989e809231bSXinliang David Li
annotateValueSite(Module & M,Instruction & Inst,const InstrProfRecord & InstrProfR,InstrProfValueKind ValueKind,uint32_t SiteIdx,uint32_t MaxMDCount)990402477d2SXinliang David Li void annotateValueSite(Module &M, Instruction &Inst,
991402477d2SXinliang David Li const InstrProfRecord &InstrProfR,
99269683f13SRong Xu InstrProfValueKind ValueKind, uint32_t SiteIdx,
99369683f13SRong Xu uint32_t MaxMDCount) {
994402477d2SXinliang David Li uint32_t NV = InstrProfR.getNumValueDataForSite(ValueKind, SiteIdx);
9954f1e8c94SBetul Buyukkurt if (!NV)
9964f1e8c94SBetul Buyukkurt return;
997402477d2SXinliang David Li
998402477d2SXinliang David Li uint64_t Sum = 0;
999402477d2SXinliang David Li std::unique_ptr<InstrProfValueData[]> VD =
1000402477d2SXinliang David Li InstrProfR.getValueForSite(ValueKind, SiteIdx, &Sum);
1001402477d2SXinliang David Li
1002311ada11SRong Xu ArrayRef<InstrProfValueData> VDs(VD.get(), NV);
1003311ada11SRong Xu annotateValueSite(M, Inst, VDs, Sum, ValueKind, MaxMDCount);
1004bb49490dSRong Xu }
1005bb49490dSRong Xu
annotateValueSite(Module & M,Instruction & Inst,ArrayRef<InstrProfValueData> VDs,uint64_t Sum,InstrProfValueKind ValueKind,uint32_t MaxMDCount)1006bb49490dSRong Xu void annotateValueSite(Module &M, Instruction &Inst,
1007311ada11SRong Xu ArrayRef<InstrProfValueData> VDs,
1008bb49490dSRong Xu uint64_t Sum, InstrProfValueKind ValueKind,
1009bb49490dSRong Xu uint32_t MaxMDCount) {
1010402477d2SXinliang David Li LLVMContext &Ctx = M.getContext();
1011402477d2SXinliang David Li MDBuilder MDHelper(Ctx);
1012402477d2SXinliang David Li SmallVector<Metadata *, 3> Vals;
1013402477d2SXinliang David Li // Tag
1014402477d2SXinliang David Li Vals.push_back(MDHelper.createString("VP"));
1015402477d2SXinliang David Li // Value Kind
1016402477d2SXinliang David Li Vals.push_back(MDHelper.createConstant(
1017402477d2SXinliang David Li ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind)));
1018402477d2SXinliang David Li // Total Count
1019402477d2SXinliang David Li Vals.push_back(
1020402477d2SXinliang David Li MDHelper.createConstant(ConstantInt::get(Type::getInt64Ty(Ctx), Sum)));
1021402477d2SXinliang David Li
1022402477d2SXinliang David Li // Value Profile Data
102369683f13SRong Xu uint32_t MDCount = MaxMDCount;
1024311ada11SRong Xu for (auto &VD : VDs) {
1025402477d2SXinliang David Li Vals.push_back(MDHelper.createConstant(
1026311ada11SRong Xu ConstantInt::get(Type::getInt64Ty(Ctx), VD.Value)));
1027402477d2SXinliang David Li Vals.push_back(MDHelper.createConstant(
1028311ada11SRong Xu ConstantInt::get(Type::getInt64Ty(Ctx), VD.Count)));
1029402477d2SXinliang David Li if (--MDCount == 0)
1030402477d2SXinliang David Li break;
1031402477d2SXinliang David Li }
1032402477d2SXinliang David Li Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals));
1033402477d2SXinliang David Li }
1034402477d2SXinliang David Li
getValueProfDataFromInst(const Instruction & Inst,InstrProfValueKind ValueKind,uint32_t MaxNumValueData,InstrProfValueData ValueData[],uint32_t & ActualNumValueData,uint64_t & TotalC,bool GetNoICPValue)1035402477d2SXinliang David Li bool getValueProfDataFromInst(const Instruction &Inst,
1036402477d2SXinliang David Li InstrProfValueKind ValueKind,
1037402477d2SXinliang David Li uint32_t MaxNumValueData,
1038402477d2SXinliang David Li InstrProfValueData ValueData[],
10395fb65c02SWei Mi uint32_t &ActualNumValueData, uint64_t &TotalC,
10402357d293SWei Mi bool GetNoICPValue) {
1041402477d2SXinliang David Li MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof);
1042402477d2SXinliang David Li if (!MD)
1043402477d2SXinliang David Li return false;
1044402477d2SXinliang David Li
1045402477d2SXinliang David Li unsigned NOps = MD->getNumOperands();
1046402477d2SXinliang David Li
1047402477d2SXinliang David Li if (NOps < 5)
1048402477d2SXinliang David Li return false;
1049402477d2SXinliang David Li
1050402477d2SXinliang David Li // Operand 0 is a string tag "VP":
1051402477d2SXinliang David Li MDString *Tag = cast<MDString>(MD->getOperand(0));
1052402477d2SXinliang David Li if (!Tag)
1053402477d2SXinliang David Li return false;
1054402477d2SXinliang David Li
1055402477d2SXinliang David Li if (!Tag->getString().equals("VP"))
1056402477d2SXinliang David Li return false;
1057402477d2SXinliang David Li
1058402477d2SXinliang David Li // Now check kind:
1059402477d2SXinliang David Li ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
1060402477d2SXinliang David Li if (!KindInt)
1061402477d2SXinliang David Li return false;
1062402477d2SXinliang David Li if (KindInt->getZExtValue() != ValueKind)
1063402477d2SXinliang David Li return false;
1064402477d2SXinliang David Li
1065402477d2SXinliang David Li // Get total count
1066402477d2SXinliang David Li ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
10672357d293SWei Mi if (!TotalCInt)
1068402477d2SXinliang David Li return false;
1069402477d2SXinliang David Li TotalC = TotalCInt->getZExtValue();
1070402477d2SXinliang David Li
1071402477d2SXinliang David Li ActualNumValueData = 0;
1072402477d2SXinliang David Li
1073402477d2SXinliang David Li for (unsigned I = 3; I < NOps; I += 2) {
1074402477d2SXinliang David Li if (ActualNumValueData >= MaxNumValueData)
1075402477d2SXinliang David Li break;
1076402477d2SXinliang David Li ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
1077402477d2SXinliang David Li ConstantInt *Count =
1078402477d2SXinliang David Li mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1));
10792357d293SWei Mi if (!Value || !Count)
1080402477d2SXinliang David Li return false;
10812357d293SWei Mi uint64_t CntValue = Count->getZExtValue();
10822357d293SWei Mi if (!GetNoICPValue && (CntValue == NOMORE_ICP_MAGICNUM))
10832357d293SWei Mi continue;
1084402477d2SXinliang David Li ValueData[ActualNumValueData].Value = Value->getZExtValue();
10852357d293SWei Mi ValueData[ActualNumValueData].Count = CntValue;
1086402477d2SXinliang David Li ActualNumValueData++;
1087402477d2SXinliang David Li }
1088402477d2SXinliang David Li return true;
1089402477d2SXinliang David Li }
10908e8fe859SRong Xu
getPGOFuncNameMetadata(const Function & F)109192c2eae4SRong Xu MDNode *getPGOFuncNameMetadata(const Function &F) {
109292c2eae4SRong Xu return F.getMetadata(getPGOFuncNameMetadataName());
109392c2eae4SRong Xu }
109492c2eae4SRong Xu
createPGOFuncNameMetadata(Function & F,StringRef PGOFuncName)10950da23a27SBenjamin Kramer void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName) {
1096f8f051cbSRong Xu // Only for internal linkage functions.
1097f8f051cbSRong Xu if (PGOFuncName == F.getName())
10988e8fe859SRong Xu return;
1099f8f051cbSRong Xu // Don't create duplicated meta-data.
1100f8f051cbSRong Xu if (getPGOFuncNameMetadata(F))
1101f8f051cbSRong Xu return;
11028e8fe859SRong Xu LLVMContext &C = F.getContext();
11030da23a27SBenjamin Kramer MDNode *N = MDNode::get(C, MDString::get(C, PGOFuncName));
11048e8fe859SRong Xu F.setMetadata(getPGOFuncNameMetadataName(), N);
11058e8fe859SRong Xu }
11068e8fe859SRong Xu
needsComdatForCounter(const Function & F,const Module & M)110797b68c5eSRong Xu bool needsComdatForCounter(const Function &F, const Module &M) {
110897b68c5eSRong Xu if (F.hasComdat())
110997b68c5eSRong Xu return true;
111097b68c5eSRong Xu
1111c6cf918fSReid Kleckner if (!Triple(M.getTargetTriple()).supportsCOMDAT())
111297b68c5eSRong Xu return false;
111397b68c5eSRong Xu
111497b68c5eSRong Xu // See createPGOFuncNameVar for more details. To avoid link errors, profile
111597b68c5eSRong Xu // counters for function with available_externally linkage needs to be changed
111697b68c5eSRong Xu // to linkonce linkage. On ELF based systems, this leads to weak symbols to be
111797b68c5eSRong Xu // created. Without using comdat, duplicate entries won't be removed by the
111897b68c5eSRong Xu // linker leading to increased data segement size and raw profile size. Even
111997b68c5eSRong Xu // worse, since the referenced counter from profile per-function data object
112097b68c5eSRong Xu // will be resolved to the common strong definition, the profile counts for
112197b68c5eSRong Xu // available_externally functions will end up being duplicated in raw profile
112297b68c5eSRong Xu // data. This can result in distorted profile as the counts of those dups
112397b68c5eSRong Xu // will be accumulated by the profile merger.
112497b68c5eSRong Xu GlobalValue::LinkageTypes Linkage = F.getLinkage();
112597b68c5eSRong Xu if (Linkage != GlobalValue::ExternalWeakLinkage &&
112697b68c5eSRong Xu Linkage != GlobalValue::AvailableExternallyLinkage)
112797b68c5eSRong Xu return false;
112897b68c5eSRong Xu
112997b68c5eSRong Xu return true;
113097b68c5eSRong Xu }
113120f5df1dSRong Xu
113220f5df1dSRong Xu // Check if INSTR_PROF_RAW_VERSION_VAR is defined.
isIRPGOFlagSet(const Module * M)113320f5df1dSRong Xu bool isIRPGOFlagSet(const Module *M) {
113420f5df1dSRong Xu auto IRInstrVar =
113520f5df1dSRong Xu M->getNamedGlobal(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1136de620f5bSRong Xu if (!IRInstrVar || IRInstrVar->hasLocalLinkage())
113720f5df1dSRong Xu return false;
113820f5df1dSRong Xu
1139de620f5bSRong Xu // For CSPGO+LTO, this variable might be marked as non-prevailing and we only
1140de620f5bSRong Xu // have the decl.
1141de620f5bSRong Xu if (IRInstrVar->isDeclaration())
1142de620f5bSRong Xu return true;
1143de620f5bSRong Xu
114420f5df1dSRong Xu // Check if the flag is set.
114520f5df1dSRong Xu if (!IRInstrVar->hasInitializer())
114620f5df1dSRong Xu return false;
114720f5df1dSRong Xu
1148339b1b5bSSimon Pilgrim auto *InitVal = dyn_cast_or_null<ConstantInt>(IRInstrVar->getInitializer());
114920f5df1dSRong Xu if (!InitVal)
115020f5df1dSRong Xu return false;
1151339b1b5bSSimon Pilgrim return (InitVal->getZExtValue() & VARIANT_MASK_IR_PROF) != 0;
115220f5df1dSRong Xu }
115320f5df1dSRong Xu
115420f5df1dSRong Xu // Check if we can safely rename this Comdat function.
canRenameComdatFunc(const Function & F,bool CheckAddressTaken)115520f5df1dSRong Xu bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken) {
115620f5df1dSRong Xu if (F.getName().empty())
115720f5df1dSRong Xu return false;
115820f5df1dSRong Xu if (!needsComdatForCounter(F, *(F.getParent())))
115920f5df1dSRong Xu return false;
116020f5df1dSRong Xu // Unsafe to rename the address-taken function (which can be used in
116120f5df1dSRong Xu // function comparison).
116220f5df1dSRong Xu if (CheckAddressTaken && F.hasAddressTaken())
116320f5df1dSRong Xu return false;
116420f5df1dSRong Xu // Only safe to do if this function may be discarded if it is not used
116520f5df1dSRong Xu // in the compilation unit.
116620f5df1dSRong Xu if (!GlobalValue::isDiscardableIfUnused(F.getLinkage()))
116720f5df1dSRong Xu return false;
116820f5df1dSRong Xu
116920f5df1dSRong Xu // For AvailableExternallyLinkage functions.
117020f5df1dSRong Xu if (!F.hasComdat()) {
117120f5df1dSRong Xu assert(F.getLinkage() == GlobalValue::AvailableExternallyLinkage);
117220f5df1dSRong Xu return true;
117320f5df1dSRong Xu }
117420f5df1dSRong Xu return true;
117520f5df1dSRong Xu }
1176e78d131aSEugene Zelenko
1177ce10d5eaSRong Xu // Create the variable for the profile file name.
createProfileFileNameVar(Module & M,StringRef InstrProfileOutput)1178ce10d5eaSRong Xu void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput) {
1179ce10d5eaSRong Xu if (InstrProfileOutput.empty())
1180ce10d5eaSRong Xu return;
1181ce10d5eaSRong Xu Constant *ProfileNameConst =
1182ce10d5eaSRong Xu ConstantDataArray::getString(M.getContext(), InstrProfileOutput, true);
1183ce10d5eaSRong Xu GlobalVariable *ProfileNameVar = new GlobalVariable(
1184ce10d5eaSRong Xu M, ProfileNameConst->getType(), true, GlobalValue::WeakAnyLinkage,
1185ce10d5eaSRong Xu ProfileNameConst, INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR));
1186ce10d5eaSRong Xu Triple TT(M.getTargetTriple());
1187ce10d5eaSRong Xu if (TT.supportsCOMDAT()) {
1188ce10d5eaSRong Xu ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
1189ce10d5eaSRong Xu ProfileNameVar->setComdat(M.getOrInsertComdat(
1190ce10d5eaSRong Xu StringRef(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR))));
1191ce10d5eaSRong Xu }
1192ce10d5eaSRong Xu }
1193ce10d5eaSRong Xu
accumulateCounts(const std::string & BaseFilename,const std::string & TestFilename,bool IsCS)1194e0fa2689SRong Xu Error OverlapStats::accumulateCounts(const std::string &BaseFilename,
1195998b97f6SRong Xu const std::string &TestFilename,
1196998b97f6SRong Xu bool IsCS) {
1197998b97f6SRong Xu auto getProfileSum = [IsCS](const std::string &Filename,
1198998b97f6SRong Xu CountSumOrPercent &Sum) -> Error {
1199998b97f6SRong Xu auto ReaderOrErr = InstrProfReader::create(Filename);
1200998b97f6SRong Xu if (Error E = ReaderOrErr.takeError()) {
1201998b97f6SRong Xu return E;
1202998b97f6SRong Xu }
1203998b97f6SRong Xu auto Reader = std::move(ReaderOrErr.get());
1204e0fa2689SRong Xu Reader->accumulateCounts(Sum, IsCS);
1205998b97f6SRong Xu return Error::success();
1206998b97f6SRong Xu };
1207998b97f6SRong Xu auto Ret = getProfileSum(BaseFilename, Base);
1208998b97f6SRong Xu if (Ret)
12096435102cSEric Christopher return Ret;
1210998b97f6SRong Xu Ret = getProfileSum(TestFilename, Test);
1211998b97f6SRong Xu if (Ret)
12126435102cSEric Christopher return Ret;
1213998b97f6SRong Xu this->BaseFilename = &BaseFilename;
1214998b97f6SRong Xu this->TestFilename = &TestFilename;
1215998b97f6SRong Xu Valid = true;
1216998b97f6SRong Xu return Error::success();
1217998b97f6SRong Xu }
1218998b97f6SRong Xu
addOneMismatch(const CountSumOrPercent & MismatchFunc)1219998b97f6SRong Xu void OverlapStats::addOneMismatch(const CountSumOrPercent &MismatchFunc) {
1220998b97f6SRong Xu Mismatch.NumEntries += 1;
1221998b97f6SRong Xu Mismatch.CountSum += MismatchFunc.CountSum / Test.CountSum;
1222998b97f6SRong Xu for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1223998b97f6SRong Xu if (Test.ValueCounts[I] >= 1.0f)
1224998b97f6SRong Xu Mismatch.ValueCounts[I] +=
1225998b97f6SRong Xu MismatchFunc.ValueCounts[I] / Test.ValueCounts[I];
1226998b97f6SRong Xu }
1227998b97f6SRong Xu }
1228998b97f6SRong Xu
addOneUnique(const CountSumOrPercent & UniqueFunc)1229998b97f6SRong Xu void OverlapStats::addOneUnique(const CountSumOrPercent &UniqueFunc) {
1230998b97f6SRong Xu Unique.NumEntries += 1;
1231998b97f6SRong Xu Unique.CountSum += UniqueFunc.CountSum / Test.CountSum;
1232998b97f6SRong Xu for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1233998b97f6SRong Xu if (Test.ValueCounts[I] >= 1.0f)
1234998b97f6SRong Xu Unique.ValueCounts[I] += UniqueFunc.ValueCounts[I] / Test.ValueCounts[I];
1235998b97f6SRong Xu }
1236998b97f6SRong Xu }
1237998b97f6SRong Xu
dump(raw_fd_ostream & OS) const1238998b97f6SRong Xu void OverlapStats::dump(raw_fd_ostream &OS) const {
1239998b97f6SRong Xu if (!Valid)
1240998b97f6SRong Xu return;
1241998b97f6SRong Xu
1242998b97f6SRong Xu const char *EntryName =
1243998b97f6SRong Xu (Level == ProgramLevel ? "functions" : "edge counters");
1244998b97f6SRong Xu if (Level == ProgramLevel) {
1245998b97f6SRong Xu OS << "Profile overlap infomation for base_profile: " << *BaseFilename
1246998b97f6SRong Xu << " and test_profile: " << *TestFilename << "\nProgram level:\n";
1247998b97f6SRong Xu } else {
1248998b97f6SRong Xu OS << "Function level:\n"
1249998b97f6SRong Xu << " Function: " << FuncName << " (Hash=" << FuncHash << ")\n";
1250998b97f6SRong Xu }
1251998b97f6SRong Xu
1252998b97f6SRong Xu OS << " # of " << EntryName << " overlap: " << Overlap.NumEntries << "\n";
1253998b97f6SRong Xu if (Mismatch.NumEntries)
1254998b97f6SRong Xu OS << " # of " << EntryName << " mismatch: " << Mismatch.NumEntries
1255998b97f6SRong Xu << "\n";
1256998b97f6SRong Xu if (Unique.NumEntries)
1257998b97f6SRong Xu OS << " # of " << EntryName
1258998b97f6SRong Xu << " only in test_profile: " << Unique.NumEntries << "\n";
1259998b97f6SRong Xu
1260998b97f6SRong Xu OS << " Edge profile overlap: " << format("%.3f%%", Overlap.CountSum * 100)
1261998b97f6SRong Xu << "\n";
1262998b97f6SRong Xu if (Mismatch.NumEntries)
1263998b97f6SRong Xu OS << " Mismatched count percentage (Edge): "
1264998b97f6SRong Xu << format("%.3f%%", Mismatch.CountSum * 100) << "\n";
1265998b97f6SRong Xu if (Unique.NumEntries)
1266998b97f6SRong Xu OS << " Percentage of Edge profile only in test_profile: "
1267998b97f6SRong Xu << format("%.3f%%", Unique.CountSum * 100) << "\n";
1268998b97f6SRong Xu OS << " Edge profile base count sum: " << format("%.0f", Base.CountSum)
1269998b97f6SRong Xu << "\n"
1270998b97f6SRong Xu << " Edge profile test count sum: " << format("%.0f", Test.CountSum)
1271998b97f6SRong Xu << "\n";
1272998b97f6SRong Xu
1273998b97f6SRong Xu for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1274998b97f6SRong Xu if (Base.ValueCounts[I] < 1.0f && Test.ValueCounts[I] < 1.0f)
1275998b97f6SRong Xu continue;
1276998b97f6SRong Xu char ProfileKindName[20];
1277998b97f6SRong Xu switch (I) {
1278998b97f6SRong Xu case IPVK_IndirectCallTarget:
1279998b97f6SRong Xu strncpy(ProfileKindName, "IndirectCall", 19);
1280998b97f6SRong Xu break;
1281998b97f6SRong Xu case IPVK_MemOPSize:
1282998b97f6SRong Xu strncpy(ProfileKindName, "MemOP", 19);
1283998b97f6SRong Xu break;
1284998b97f6SRong Xu default:
1285998b97f6SRong Xu snprintf(ProfileKindName, 19, "VP[%d]", I);
1286998b97f6SRong Xu break;
1287998b97f6SRong Xu }
1288998b97f6SRong Xu OS << " " << ProfileKindName
1289998b97f6SRong Xu << " profile overlap: " << format("%.3f%%", Overlap.ValueCounts[I] * 100)
1290998b97f6SRong Xu << "\n";
1291998b97f6SRong Xu if (Mismatch.NumEntries)
1292998b97f6SRong Xu OS << " Mismatched count percentage (" << ProfileKindName
1293998b97f6SRong Xu << "): " << format("%.3f%%", Mismatch.ValueCounts[I] * 100) << "\n";
1294998b97f6SRong Xu if (Unique.NumEntries)
1295998b97f6SRong Xu OS << " Percentage of " << ProfileKindName
1296998b97f6SRong Xu << " profile only in test_profile: "
1297998b97f6SRong Xu << format("%.3f%%", Unique.ValueCounts[I] * 100) << "\n";
1298998b97f6SRong Xu OS << " " << ProfileKindName
1299998b97f6SRong Xu << " profile base count sum: " << format("%.0f", Base.ValueCounts[I])
1300998b97f6SRong Xu << "\n"
1301998b97f6SRong Xu << " " << ProfileKindName
1302998b97f6SRong Xu << " profile test count sum: " << format("%.0f", Test.ValueCounts[I])
1303998b97f6SRong Xu << "\n";
1304998b97f6SRong Xu }
1305998b97f6SRong Xu }
1306998b97f6SRong Xu
1307a3beb340SSnehasish Kumar namespace IndexedInstrProf {
1308a3beb340SSnehasish Kumar // A C++14 compatible version of the offsetof macro.
1309a3beb340SSnehasish Kumar template <typename T1, typename T2>
offsetOf(T1 T2::* Member)1310a3beb340SSnehasish Kumar inline size_t constexpr offsetOf(T1 T2::*Member) {
1311a3beb340SSnehasish Kumar constexpr T2 Object{};
1312a3beb340SSnehasish Kumar return size_t(&(Object.*Member)) - size_t(&Object);
1313a3beb340SSnehasish Kumar }
1314a3beb340SSnehasish Kumar
read(const unsigned char * Buffer,size_t Offset)1315a3beb340SSnehasish Kumar static inline uint64_t read(const unsigned char *Buffer, size_t Offset) {
1316a3beb340SSnehasish Kumar return *reinterpret_cast<const uint64_t *>(Buffer + Offset);
1317a3beb340SSnehasish Kumar }
1318a3beb340SSnehasish Kumar
formatVersion() const1319a3beb340SSnehasish Kumar uint64_t Header::formatVersion() const {
1320a3beb340SSnehasish Kumar using namespace support;
1321a3beb340SSnehasish Kumar return endian::byte_swap<uint64_t, little>(Version);
1322a3beb340SSnehasish Kumar }
1323a3beb340SSnehasish Kumar
readFromBuffer(const unsigned char * Buffer)1324a3beb340SSnehasish Kumar Expected<Header> Header::readFromBuffer(const unsigned char *Buffer) {
1325a3beb340SSnehasish Kumar using namespace support;
1326a3beb340SSnehasish Kumar static_assert(std::is_standard_layout<Header>::value,
1327a3beb340SSnehasish Kumar "The header should be standard layout type since we use offset "
1328a3beb340SSnehasish Kumar "of fields to read.");
1329a3beb340SSnehasish Kumar Header H;
1330a3beb340SSnehasish Kumar
1331a3beb340SSnehasish Kumar H.Magic = read(Buffer, offsetOf(&Header::Magic));
1332a3beb340SSnehasish Kumar // Check the magic number.
1333a3beb340SSnehasish Kumar uint64_t Magic = endian::byte_swap<uint64_t, little>(H.Magic);
1334a3beb340SSnehasish Kumar if (Magic != IndexedInstrProf::Magic)
1335a3beb340SSnehasish Kumar return make_error<InstrProfError>(instrprof_error::bad_magic);
1336a3beb340SSnehasish Kumar
1337a3beb340SSnehasish Kumar // Read the version.
1338a3beb340SSnehasish Kumar H.Version = read(Buffer, offsetOf(&Header::Version));
1339a3beb340SSnehasish Kumar if (GET_VERSION(H.formatVersion()) >
1340a3beb340SSnehasish Kumar IndexedInstrProf::ProfVersion::CurrentVersion)
1341a3beb340SSnehasish Kumar return make_error<InstrProfError>(instrprof_error::unsupported_version);
1342a3beb340SSnehasish Kumar
1343a3beb340SSnehasish Kumar switch (GET_VERSION(H.formatVersion())) {
1344a3beb340SSnehasish Kumar // When a new field is added in the header add a case statement here to
1345a3beb340SSnehasish Kumar // populate it.
13460a418490SSnehasish Kumar static_assert(
13470a418490SSnehasish Kumar IndexedInstrProf::ProfVersion::CurrentVersion == Version8,
13480a418490SSnehasish Kumar "Please update the reading code below if a new field has been added, "
13490a418490SSnehasish Kumar "if not add a case statement to fall through to the latest version.");
13500a418490SSnehasish Kumar case 8ull:
13510a418490SSnehasish Kumar H.MemProfOffset = read(Buffer, offsetOf(&Header::MemProfOffset));
13520a418490SSnehasish Kumar LLVM_FALLTHROUGH;
1353a3beb340SSnehasish Kumar default: // Version7 (when the backwards compatible header was introduced).
1354a3beb340SSnehasish Kumar H.HashType = read(Buffer, offsetOf(&Header::HashType));
1355a3beb340SSnehasish Kumar H.HashOffset = read(Buffer, offsetOf(&Header::HashOffset));
1356a3beb340SSnehasish Kumar }
1357a3beb340SSnehasish Kumar
1358a3beb340SSnehasish Kumar return H;
1359a3beb340SSnehasish Kumar }
1360a3beb340SSnehasish Kumar
size() const1361a3beb340SSnehasish Kumar size_t Header::size() const {
1362a3beb340SSnehasish Kumar switch (GET_VERSION(formatVersion())) {
1363a3beb340SSnehasish Kumar // When a new field is added to the header add a case statement here to
1364a3beb340SSnehasish Kumar // compute the size as offset of the new field + size of the new field. This
1365a3beb340SSnehasish Kumar // relies on the field being added to the end of the list.
13660a418490SSnehasish Kumar static_assert(IndexedInstrProf::ProfVersion::CurrentVersion == Version8,
13670a418490SSnehasish Kumar "Please update the size computation below if a new field has "
13680a418490SSnehasish Kumar "been added to the header, if not add a case statement to "
13690a418490SSnehasish Kumar "fall through to the latest version.");
13700a418490SSnehasish Kumar case 8ull:
13710a418490SSnehasish Kumar return offsetOf(&Header::MemProfOffset) + sizeof(Header::MemProfOffset);
1372a3beb340SSnehasish Kumar default: // Version7 (when the backwards compatible header was introduced).
1373a3beb340SSnehasish Kumar return offsetOf(&Header::HashOffset) + sizeof(Header::HashOffset);
1374a3beb340SSnehasish Kumar }
1375a3beb340SSnehasish Kumar }
1376a3beb340SSnehasish Kumar
1377a3beb340SSnehasish Kumar } // namespace IndexedInstrProf
1378a3beb340SSnehasish Kumar
13796ac3f739SEugene Zelenko } // end namespace llvm
1380