blob: fa15170ef6c4ba9048579e1e55b48ffaf713499b [file] [log] [blame]
Justin Bognerf8d79192014-03-21 17:24:48 +00001//=-- InstrProf.cpp - Instrumented profiling format support -----------------=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for clang's instrumentation based PGO and
11// coverage.
12//
13//===----------------------------------------------------------------------===//
14
Xinliang David Lie413f1a2015-12-31 07:57:16 +000015#include "llvm/ProfileData/InstrProf.h"
Xinliang David Li0c677872016-01-04 21:31:09 +000016#include "llvm/ADT/StringExtras.h"
Xinliang David Li441959d2015-11-09 00:01:22 +000017#include "llvm/IR/Constants.h"
18#include "llvm/IR/Function.h"
Xinliang David Li441959d2015-11-09 00:01:22 +000019#include "llvm/IR/GlobalVariable.h"
Xinliang David Li402477d2016-02-04 19:11:43 +000020#include "llvm/IR/MDBuilder.h"
Xinliang David Lie413f1a2015-12-31 07:57:16 +000021#include "llvm/IR/Module.h"
22#include "llvm/Support/Compression.h"
Justin Bognerf8d79192014-03-21 17:24:48 +000023#include "llvm/Support/ErrorHandling.h"
Xinliang David Lie413f1a2015-12-31 07:57:16 +000024#include "llvm/Support/LEB128.h"
Chris Bieneman1efe8012014-09-19 23:19:24 +000025#include "llvm/Support/ManagedStatic.h"
Justin Bognerf8d79192014-03-21 17:24:48 +000026
27using namespace llvm;
28
29namespace {
Rafael Espindola25188c92014-06-12 01:45:43 +000030class InstrProfErrorCategoryType : public std::error_category {
Rafael Espindolaf5d07fa2014-06-10 21:26:47 +000031 const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
Justin Bognerf8d79192014-03-21 17:24:48 +000032 std::string message(int IE) const override {
Rafael Espindola92512e82014-06-03 05:12:33 +000033 instrprof_error E = static_cast<instrprof_error>(IE);
Justin Bognerf8d79192014-03-21 17:24:48 +000034 switch (E) {
35 case instrprof_error::success:
36 return "Success";
37 case instrprof_error::eof:
38 return "End of File";
Nathan Slingerland4f823662015-11-13 03:47:58 +000039 case instrprof_error::unrecognized_format:
40 return "Unrecognized instrumentation profile encoding format";
Justin Bognerf8d79192014-03-21 17:24:48 +000041 case instrprof_error::bad_magic:
Nathan Slingerland4f823662015-11-13 03:47:58 +000042 return "Invalid instrumentation profile data (bad magic)";
Duncan P. N. Exon Smith531bb482014-03-21 20:42:28 +000043 case instrprof_error::bad_header:
Nathan Slingerland4f823662015-11-13 03:47:58 +000044 return "Invalid instrumentation profile data (file header is corrupt)";
Justin Bognerf8d79192014-03-21 17:24:48 +000045 case instrprof_error::unsupported_version:
Nathan Slingerland4f823662015-11-13 03:47:58 +000046 return "Unsupported instrumentation profile format version";
Justin Bognerb7aa2632014-04-18 21:48:40 +000047 case instrprof_error::unsupported_hash_type:
Nathan Slingerland4f823662015-11-13 03:47:58 +000048 return "Unsupported instrumentation profile hash type";
Justin Bognerf8d79192014-03-21 17:24:48 +000049 case instrprof_error::too_large:
50 return "Too much profile data";
51 case instrprof_error::truncated:
52 return "Truncated profile data";
53 case instrprof_error::malformed:
Nathan Slingerland4f823662015-11-13 03:47:58 +000054 return "Malformed instrumentation profile data";
Justin Bognerf8d79192014-03-21 17:24:48 +000055 case instrprof_error::unknown_function:
56 return "No profile data available for function";
Justin Bognerb9bd7f82014-03-21 17:46:22 +000057 case instrprof_error::hash_mismatch:
Nathan Slingerlande6e30d52015-11-17 22:08:53 +000058 return "Function control flow change detected (hash mismatch)";
Justin Bognerb9bd7f82014-03-21 17:46:22 +000059 case instrprof_error::count_mismatch:
Nathan Slingerlande6e30d52015-11-17 22:08:53 +000060 return "Function basic block count change detected (counter mismatch)";
Justin Bognerb9bd7f82014-03-21 17:46:22 +000061 case instrprof_error::counter_overflow:
62 return "Counter overflow";
Justin Bogner9e9a0572015-09-29 22:13:58 +000063 case instrprof_error::value_site_count_mismatch:
Nathan Slingerlande6e30d52015-11-17 22:08:53 +000064 return "Function value site count change detected (counter mismatch)";
Justin Bognerf8d79192014-03-21 17:24:48 +000065 }
66 llvm_unreachable("A value of instrprof_error has no message.");
67 }
Justin Bognerf8d79192014-03-21 17:24:48 +000068};
Eugene Zelenko6ac3f732016-01-26 18:48:36 +000069} // end anonymous namespace
Justin Bognerf8d79192014-03-21 17:24:48 +000070
Chris Bieneman1efe8012014-09-19 23:19:24 +000071static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;
72
Rafael Espindola25188c92014-06-12 01:45:43 +000073const std::error_category &llvm::instrprof_category() {
Chris Bieneman1efe8012014-09-19 23:19:24 +000074 return *ErrorCategory;
Justin Bognerf8d79192014-03-21 17:24:48 +000075}
Xinliang David Li441959d2015-11-09 00:01:22 +000076
77namespace llvm {
78
79std::string getPGOFuncName(StringRef RawFuncName,
80 GlobalValue::LinkageTypes Linkage,
Xinliang David Lia86545b2015-12-11 20:23:22 +000081 StringRef FileName,
82 uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
Teresa Johnsonb43027d2016-03-15 02:13:19 +000083 return GlobalValue::getGlobalIdentifier(RawFuncName, Linkage, FileName);
Xinliang David Li441959d2015-11-09 00:01:22 +000084}
85
Rong Xub5341662016-03-30 18:37:52 +000086// Return the PGOFuncName. This function has some special handling when called
87// in LTO optimization. The following only applies when calling in LTO passes
88// (when \c InLTO is true): LTO's internalization privatizes many global linkage
89// symbols. This happens after value profile annotation, but those internal
90// linkage functions should not have a source prefix.
91// To differentiate compiler generated internal symbols from original ones,
92// PGOFuncName meta data are created and attached to the original internal
93// symbols in the value profile annotation step
94// (PGOUseFunc::annotateIndirectCallSites). If a symbol does not have the meta
95// data, its original linkage must be non-internal.
96std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) {
97 if (!InLTO)
98 return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName(),
99 Version);
100
101 // InLTO mode. First check if these is a meta data.
102 MDNode *MD = F.getMetadata("PGOFuncName");
103 if (MD != nullptr) {
104 StringRef S = cast<MDString>(MD->getOperand(0))->getString();
105 return S.str();
106 }
107
108 // If there is no meta data, the function must be a global before the value
109 // profile annotation pass. Its current linkage may be internal if it is
110 // internalized in LTO mode.
111 return getPGOFuncName (F.getName(), GlobalValue::ExternalLinkage, "");
Xinliang David Li441959d2015-11-09 00:01:22 +0000112}
113
Xinliang David Li4ec40142015-12-15 19:44:45 +0000114StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) {
115 if (FileName.empty())
Vedant Kumar43a85652016-03-28 15:49:08 +0000116 return PGOFuncName;
Xinliang David Li4ec40142015-12-15 19:44:45 +0000117 // Drop the file name including ':'. See also getPGOFuncName.
118 if (PGOFuncName.startswith(FileName))
119 PGOFuncName = PGOFuncName.drop_front(FileName.size() + 1);
120 return PGOFuncName;
121}
122
Xinliang David Lid1bab962015-12-12 17:28:03 +0000123// \p FuncName is the string used as profile lookup key for the function. A
124// symbol is created to hold the name. Return the legalized symbol name.
Vedant Kumaraa0cae62016-03-16 20:49:26 +0000125std::string getPGOFuncNameVarName(StringRef FuncName,
126 GlobalValue::LinkageTypes Linkage) {
Xinliang David Lid1bab962015-12-12 17:28:03 +0000127 std::string VarName = getInstrProfNameVarPrefix();
128 VarName += FuncName;
129
130 if (!GlobalValue::isLocalLinkage(Linkage))
131 return VarName;
132
133 // Now fix up illegal chars in local VarName that may upset the assembler.
134 const char *InvalidChars = "-:<>\"'";
135 size_t found = VarName.find_first_of(InvalidChars);
136 while (found != std::string::npos) {
137 VarName[found] = '_';
138 found = VarName.find_first_of(InvalidChars, found + 1);
139 }
140 return VarName;
141}
142
Xinliang David Li441959d2015-11-09 00:01:22 +0000143GlobalVariable *createPGOFuncNameVar(Module &M,
144 GlobalValue::LinkageTypes Linkage,
Xinliang David Li897d2922016-03-16 22:13:41 +0000145 StringRef PGOFuncName) {
Xinliang David Li441959d2015-11-09 00:01:22 +0000146
147 // We generally want to match the function's linkage, but available_externally
148 // and extern_weak both have the wrong semantics, and anything that doesn't
149 // need to link across compilation units doesn't need to be visible at all.
150 if (Linkage == GlobalValue::ExternalWeakLinkage)
151 Linkage = GlobalValue::LinkOnceAnyLinkage;
152 else if (Linkage == GlobalValue::AvailableExternallyLinkage)
153 Linkage = GlobalValue::LinkOnceODRLinkage;
154 else if (Linkage == GlobalValue::InternalLinkage ||
155 Linkage == GlobalValue::ExternalLinkage)
156 Linkage = GlobalValue::PrivateLinkage;
157
Xinliang David Li897d2922016-03-16 22:13:41 +0000158 auto *Value =
159 ConstantDataArray::getString(M.getContext(), PGOFuncName, false);
Xinliang David Li441959d2015-11-09 00:01:22 +0000160 auto FuncNameVar =
161 new GlobalVariable(M, Value->getType(), true, Linkage, Value,
Xinliang David Li897d2922016-03-16 22:13:41 +0000162 getPGOFuncNameVarName(PGOFuncName, Linkage));
Xinliang David Li441959d2015-11-09 00:01:22 +0000163
164 // Hide the symbol so that we correctly get a copy for each executable.
165 if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
166 FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);
167
168 return FuncNameVar;
169}
170
Xinliang David Li897d2922016-03-16 22:13:41 +0000171GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) {
172 return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
Xinliang David Li441959d2015-11-09 00:01:22 +0000173}
Xinliang David Liee415892015-11-10 00:24:45 +0000174
Rong Xub5341662016-03-30 18:37:52 +0000175void InstrProfSymtab::create(Module &M, bool InLTO) {
176 for (Function &F : M) {
177 // Function may not have a name: like using asm("") to overwrite the name.
178 // Ignore in this case.
179 if (!F.hasName())
180 continue;
181 const std::string &PGOFuncName = getPGOFuncName(F, InLTO);
182 addFuncName(PGOFuncName);
183 MD5FuncMap.push_back(std::make_pair(Function::getGUID(PGOFuncName), &F));
184 }
Xinliang David Li59411db2016-01-20 01:26:34 +0000185
186 finalizeSymtab();
187}
188
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000189int collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
190 bool doCompression, std::string &Result) {
Vedant Kumar86705ba2016-03-28 21:06:42 +0000191 assert(NameStrs.size() && "No name data to emit");
192
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000193 uint8_t Header[16], *P = Header;
Xinliang David Li0c677872016-01-04 21:31:09 +0000194 std::string UncompressedNameStrings =
Vedant Kumar86705ba2016-03-28 21:06:42 +0000195 join(NameStrs.begin(), NameStrs.end(), getInstrProfNameSeparator());
196
197 assert(StringRef(UncompressedNameStrings)
198 .count(getInstrProfNameSeparator()) == (NameStrs.size() - 1) &&
199 "PGO name is invalid (contains separator token)");
Xinliang David Li13ea29b2016-01-04 20:26:05 +0000200
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000201 unsigned EncLen = encodeULEB128(UncompressedNameStrings.length(), P);
202 P += EncLen;
Xinliang David Li120fe2e2016-01-04 22:01:02 +0000203
204 auto WriteStringToResult = [&](size_t CompressedLen,
205 const std::string &InputStr) {
206 EncLen = encodeULEB128(CompressedLen, P);
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000207 P += EncLen;
Xinliang David Li120fe2e2016-01-04 22:01:02 +0000208 char *HeaderStr = reinterpret_cast<char *>(&Header[0]);
209 unsigned HeaderLen = P - &Header[0];
210 Result.append(HeaderStr, HeaderLen);
211 Result += InputStr;
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000212 return 0;
Xinliang David Li120fe2e2016-01-04 22:01:02 +0000213 };
214
215 if (!doCompression)
216 return WriteStringToResult(0, UncompressedNameStrings);
217
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000218 SmallVector<char, 128> CompressedNameStrings;
219 zlib::Status Success =
220 zlib::compress(StringRef(UncompressedNameStrings), CompressedNameStrings,
221 zlib::BestSizeCompression);
Xinliang David Li120fe2e2016-01-04 22:01:02 +0000222
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000223 if (Success != zlib::StatusOK)
224 return 1;
Xinliang David Li120fe2e2016-01-04 22:01:02 +0000225
226 return WriteStringToResult(
227 CompressedNameStrings.size(),
228 std::string(CompressedNameStrings.data(), CompressedNameStrings.size()));
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000229}
230
Xinliang David Lieb7d7f82016-02-04 23:59:09 +0000231StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar) {
Xinliang David Li37c1fa02016-01-03 04:38:13 +0000232 auto *Arr = cast<ConstantDataArray>(NameVar->getInitializer());
233 StringRef NameStr =
234 Arr->isCString() ? Arr->getAsCString() : Arr->getAsString();
235 return NameStr;
236}
237
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000238int collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
Xinliang David Li73163752016-01-26 23:13:00 +0000239 std::string &Result, bool doCompression) {
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000240 std::vector<std::string> NameStrs;
241 for (auto *NameVar : NameVars) {
Xinliang David Lieb7d7f82016-02-04 23:59:09 +0000242 NameStrs.push_back(getPGOFuncNameVarInitializer(NameVar));
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000243 }
Xinliang David Li73163752016-01-26 23:13:00 +0000244 return collectPGOFuncNameStrings(
245 NameStrs, zlib::isAvailable() && doCompression, Result);
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000246}
247
248int readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) {
249 const uint8_t *P = reinterpret_cast<const uint8_t *>(NameStrings.data());
250 const uint8_t *EndP = reinterpret_cast<const uint8_t *>(NameStrings.data() +
251 NameStrings.size());
252 while (P < EndP) {
253 uint32_t N;
254 uint64_t UncompressedSize = decodeULEB128(P, &N);
255 P += N;
256 uint64_t CompressedSize = decodeULEB128(P, &N);
257 P += N;
258 bool isCompressed = (CompressedSize != 0);
259 SmallString<128> UncompressedNameStrings;
260 StringRef NameStrings;
261 if (isCompressed) {
262 StringRef CompressedNameStrings(reinterpret_cast<const char *>(P),
263 CompressedSize);
264 if (zlib::uncompress(CompressedNameStrings, UncompressedNameStrings,
265 UncompressedSize) != zlib::StatusOK)
266 return 1;
267 P += CompressedSize;
268 NameStrings = StringRef(UncompressedNameStrings.data(),
269 UncompressedNameStrings.size());
270 } else {
271 NameStrings =
272 StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
273 P += UncompressedSize;
274 }
275 // Now parse the name strings.
Xinliang David Li204efe22016-01-04 22:09:26 +0000276 SmallVector<StringRef, 0> Names;
Vedant Kumar86705ba2016-03-28 21:06:42 +0000277 NameStrings.split(Names, getInstrProfNameSeparator());
Xinliang David Li204efe22016-01-04 22:09:26 +0000278 for (StringRef &Name : Names)
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000279 Symtab.addFuncName(Name);
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000280
281 while (P < EndP && *P == 0)
282 P++;
283 }
284 Symtab.finalizeSymtab();
285 return 0;
286}
287
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000288instrprof_error InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
289 uint64_t Weight) {
Xinliang David Li5c24da52015-12-20 05:15:45 +0000290 this->sortByTargetValues();
291 Input.sortByTargetValues();
292 auto I = ValueData.begin();
293 auto IE = ValueData.end();
294 instrprof_error Result = instrprof_error::success;
295 for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
296 ++J) {
297 while (I != IE && I->Value < J->Value)
298 ++I;
299 if (I != IE && I->Value == J->Value) {
Xinliang David Li5c24da52015-12-20 05:15:45 +0000300 bool Overflowed;
Nathan Slingerland7bee3162016-01-12 22:34:00 +0000301 I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);
Xinliang David Li5c24da52015-12-20 05:15:45 +0000302 if (Overflowed)
303 Result = instrprof_error::counter_overflow;
304 ++I;
305 continue;
306 }
307 ValueData.insert(I, *J);
308 }
309 return Result;
310}
311
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000312instrprof_error InstrProfValueSiteRecord::scale(uint64_t Weight) {
313 instrprof_error Result = instrprof_error::success;
314 for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) {
315 bool Overflowed;
316 I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed);
317 if (Overflowed)
318 Result = instrprof_error::counter_overflow;
319 }
320 return Result;
321}
322
Xinliang David Li020f22d2015-12-18 23:06:37 +0000323// Merge Value Profile data from Src record to this record for ValueKind.
324// Scale merged value counts by \p Weight.
325instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind,
326 InstrProfRecord &Src,
327 uint64_t Weight) {
328 uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
329 uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
330 if (ThisNumValueSites != OtherNumValueSites)
331 return instrprof_error::value_site_count_mismatch;
332 std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
333 getValueSitesForKind(ValueKind);
334 std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
335 Src.getValueSitesForKind(ValueKind);
336 instrprof_error Result = instrprof_error::success;
337 for (uint32_t I = 0; I < ThisNumValueSites; I++)
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000338 MergeResult(Result, ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight));
Xinliang David Li020f22d2015-12-18 23:06:37 +0000339 return Result;
340}
341
342instrprof_error InstrProfRecord::merge(InstrProfRecord &Other,
343 uint64_t Weight) {
344 // If the number of counters doesn't match we either have bad data
345 // or a hash collision.
346 if (Counts.size() != Other.Counts.size())
347 return instrprof_error::count_mismatch;
348
349 instrprof_error Result = instrprof_error::success;
350
351 for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
352 bool Overflowed;
Nathan Slingerland7bee3162016-01-12 22:34:00 +0000353 Counts[I] =
354 SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
Xinliang David Li020f22d2015-12-18 23:06:37 +0000355 if (Overflowed)
356 Result = instrprof_error::counter_overflow;
357 }
358
359 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
360 MergeResult(Result, mergeValueProfData(Kind, Other, Weight));
361
362 return Result;
363}
Xinliang David Lia716cc52015-12-20 06:22:13 +0000364
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000365instrprof_error InstrProfRecord::scaleValueProfData(uint32_t ValueKind,
366 uint64_t Weight) {
367 uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
368 std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
369 getValueSitesForKind(ValueKind);
370 instrprof_error Result = instrprof_error::success;
371 for (uint32_t I = 0; I < ThisNumValueSites; I++)
372 MergeResult(Result, ThisSiteRecords[I].scale(Weight));
373 return Result;
374}
375
376instrprof_error InstrProfRecord::scale(uint64_t Weight) {
377 instrprof_error Result = instrprof_error::success;
378 for (auto &Count : this->Counts) {
379 bool Overflowed;
380 Count = SaturatingMultiply(Count, Weight, &Overflowed);
381 if (Overflowed && Result == instrprof_error::success) {
382 Result = instrprof_error::counter_overflow;
383 }
384 }
385 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
386 MergeResult(Result, scaleValueProfData(Kind, Weight));
387
388 return Result;
389}
390
Xinliang David Li020f22d2015-12-18 23:06:37 +0000391// Map indirect call target name hash to name string.
392uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind,
Xinliang David Lia716cc52015-12-20 06:22:13 +0000393 ValueMapType *ValueMap) {
394 if (!ValueMap)
Xinliang David Li020f22d2015-12-18 23:06:37 +0000395 return Value;
396 switch (ValueKind) {
397 case IPVK_IndirectCallTarget: {
398 auto Result =
Xinliang David Lia716cc52015-12-20 06:22:13 +0000399 std::lower_bound(ValueMap->begin(), ValueMap->end(), Value,
400 [](const std::pair<uint64_t, uint64_t> &LHS,
Xinliang David Li020f22d2015-12-18 23:06:37 +0000401 uint64_t RHS) { return LHS.first < RHS; });
Xinliang David Lia716cc52015-12-20 06:22:13 +0000402 if (Result != ValueMap->end())
Xinliang David Li020f22d2015-12-18 23:06:37 +0000403 Value = (uint64_t)Result->second;
404 break;
405 }
406 }
407 return Value;
408}
409
Xinliang David Li020f22d2015-12-18 23:06:37 +0000410void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site,
411 InstrProfValueData *VData, uint32_t N,
Xinliang David Lia716cc52015-12-20 06:22:13 +0000412 ValueMapType *ValueMap) {
Xinliang David Li020f22d2015-12-18 23:06:37 +0000413 for (uint32_t I = 0; I < N; I++) {
Xinliang David Lia716cc52015-12-20 06:22:13 +0000414 VData[I].Value = remapValue(VData[I].Value, ValueKind, ValueMap);
Xinliang David Li020f22d2015-12-18 23:06:37 +0000415 }
416 std::vector<InstrProfValueSiteRecord> &ValueSites =
417 getValueSitesForKind(ValueKind);
418 if (N == 0)
419 ValueSites.push_back(InstrProfValueSiteRecord());
420 else
421 ValueSites.emplace_back(VData, VData + N);
422}
423
Xinliang David Lib75544a2015-11-28 19:07:09 +0000424#define INSTR_PROF_COMMON_API_IMPL
425#include "llvm/ProfileData/InstrProfData.inc"
Xinliang David Liee415892015-11-10 00:24:45 +0000426
Xinliang David Li020f22d2015-12-18 23:06:37 +0000427/*!
Xinliang David Lib75544a2015-11-28 19:07:09 +0000428 * \brief ValueProfRecordClosure Interface implementation for InstrProfRecord
Xinliang David Lied966772015-11-25 23:31:18 +0000429 * class. These C wrappers are used as adaptors so that C++ code can be
430 * invoked as callbacks.
431 */
Xinliang David Lif47cf552015-11-25 06:23:38 +0000432uint32_t getNumValueKindsInstrProf(const void *Record) {
433 return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
434}
435
436uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
437 return reinterpret_cast<const InstrProfRecord *>(Record)
438 ->getNumValueSites(VKind);
439}
440
441uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
442 return reinterpret_cast<const InstrProfRecord *>(Record)
443 ->getNumValueData(VKind);
444}
445
446uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
447 uint32_t S) {
448 return reinterpret_cast<const InstrProfRecord *>(R)
449 ->getNumValueDataForSite(VK, S);
450}
451
452void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
Xinliang David Li1e4c8092016-02-04 05:29:51 +0000453 uint32_t K, uint32_t S) {
454 reinterpret_cast<const InstrProfRecord *>(R)->getValueForSite(Dst, K, S);
455 return;
Xinliang David Lie8092312015-11-25 19:13:00 +0000456}
457
Xinliang David Lif47cf552015-11-25 06:23:38 +0000458ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
Xinliang David Li38b9a322015-12-15 21:57:08 +0000459 ValueProfData *VD =
460 (ValueProfData *)(new (::operator new(TotalSizeInBytes)) ValueProfData());
461 memset(VD, 0, TotalSizeInBytes);
462 return VD;
Xinliang David Lif47cf552015-11-25 06:23:38 +0000463}
464
465static ValueProfRecordClosure InstrProfRecordClosure = {
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000466 nullptr,
Xinliang David Lif47cf552015-11-25 06:23:38 +0000467 getNumValueKindsInstrProf,
468 getNumValueSitesInstrProf,
469 getNumValueDataInstrProf,
470 getNumValueDataForSiteInstrProf,
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000471 nullptr,
Xinliang David Lif47cf552015-11-25 06:23:38 +0000472 getValueForSiteInstrProf,
Xinliang David Li38b9a322015-12-15 21:57:08 +0000473 allocValueProfDataInstrProf};
Xinliang David Lif47cf552015-11-25 06:23:38 +0000474
Xinliang David Lie8092312015-11-25 19:13:00 +0000475// Wrapper implementation using the closure mechanism.
Xinliang David Lif47cf552015-11-25 06:23:38 +0000476uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
477 InstrProfRecordClosure.Record = &Record;
478 return getValueProfDataSize(&InstrProfRecordClosure);
479}
480
Xinliang David Lie8092312015-11-25 19:13:00 +0000481// Wrapper implementation using the closure mechanism.
Xinliang David Lif47cf552015-11-25 06:23:38 +0000482std::unique_ptr<ValueProfData>
483ValueProfData::serializeFrom(const InstrProfRecord &Record) {
484 InstrProfRecordClosure.Record = &Record;
485
486 std::unique_ptr<ValueProfData> VPD(
Xinliang David Li0e6a36e2015-12-01 19:47:32 +0000487 serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr));
Xinliang David Lif47cf552015-11-25 06:23:38 +0000488 return VPD;
489}
490
Xinliang David Lie8092312015-11-25 19:13:00 +0000491void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
492 InstrProfRecord::ValueMapType *VMap) {
493 Record.reserveSites(Kind, NumValueSites);
494
495 InstrProfValueData *ValueData = getValueProfRecordValueData(this);
496 for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
497 uint8_t ValueDataCount = this->SiteCountArray[VSite];
498 Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
499 ValueData += ValueDataCount;
500 }
501}
Xinliang David Lied966772015-11-25 23:31:18 +0000502
Xinliang David Lie8092312015-11-25 19:13:00 +0000503// For writing/serializing, Old is the host endianness, and New is
504// byte order intended on disk. For Reading/deserialization, Old
505// is the on-disk source endianness, and New is the host endianness.
506void ValueProfRecord::swapBytes(support::endianness Old,
507 support::endianness New) {
508 using namespace support;
509 if (Old == New)
510 return;
511
512 if (getHostEndianness() != Old) {
513 sys::swapByteOrder<uint32_t>(NumValueSites);
514 sys::swapByteOrder<uint32_t>(Kind);
515 }
516 uint32_t ND = getValueProfRecordNumValueData(this);
517 InstrProfValueData *VD = getValueProfRecordValueData(this);
518
519 // No need to swap byte array: SiteCountArrray.
520 for (uint32_t I = 0; I < ND; I++) {
521 sys::swapByteOrder<uint64_t>(VD[I].Value);
522 sys::swapByteOrder<uint64_t>(VD[I].Count);
523 }
524 if (getHostEndianness() == Old) {
525 sys::swapByteOrder<uint32_t>(NumValueSites);
526 sys::swapByteOrder<uint32_t>(Kind);
527 }
528}
529
530void ValueProfData::deserializeTo(InstrProfRecord &Record,
531 InstrProfRecord::ValueMapType *VMap) {
532 if (NumValueKinds == 0)
533 return;
534
535 ValueProfRecord *VR = getFirstValueProfRecord(this);
536 for (uint32_t K = 0; K < NumValueKinds; K++) {
537 VR->deserializeTo(Record, VMap);
538 VR = getValueProfRecordNext(VR);
539 }
540}
541
542template <class T>
543static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
544 using namespace support;
545 if (Orig == little)
546 return endian::readNext<T, little, unaligned>(D);
547 else
548 return endian::readNext<T, big, unaligned>(D);
549}
550
551static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
552 return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
553 ValueProfData());
554}
555
Xinliang David Li8e32f4d2015-11-28 04:56:07 +0000556instrprof_error ValueProfData::checkIntegrity() {
557 if (NumValueKinds > IPVK_Last + 1)
558 return instrprof_error::malformed;
559 // Total size needs to be mulltiple of quadword size.
560 if (TotalSize % sizeof(uint64_t))
561 return instrprof_error::malformed;
562
563 ValueProfRecord *VR = getFirstValueProfRecord(this);
564 for (uint32_t K = 0; K < this->NumValueKinds; K++) {
565 if (VR->Kind > IPVK_Last)
566 return instrprof_error::malformed;
567 VR = getValueProfRecordNext(VR);
568 if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
569 return instrprof_error::malformed;
570 }
571 return instrprof_error::success;
572}
573
Xinliang David Liee415892015-11-10 00:24:45 +0000574ErrorOr<std::unique_ptr<ValueProfData>>
575ValueProfData::getValueProfData(const unsigned char *D,
576 const unsigned char *const BufferEnd,
577 support::endianness Endianness) {
578 using namespace support;
579 if (D + sizeof(ValueProfData) > BufferEnd)
580 return instrprof_error::truncated;
581
Xinliang David Lib8c3ad12015-11-17 03:47:21 +0000582 const unsigned char *Header = D;
583 uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
Xinliang David Liee415892015-11-10 00:24:45 +0000584 if (D + TotalSize > BufferEnd)
585 return instrprof_error::too_large;
Xinliang David Liee415892015-11-10 00:24:45 +0000586
Xinliang David Lif47cf552015-11-25 06:23:38 +0000587 std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
Xinliang David Liee415892015-11-10 00:24:45 +0000588 memcpy(VPD.get(), D, TotalSize);
589 // Byte swap.
590 VPD->swapBytesToHost(Endianness);
591
Xinliang David Li8e32f4d2015-11-28 04:56:07 +0000592 instrprof_error EC = VPD->checkIntegrity();
593 if (EC != instrprof_error::success)
594 return EC;
Xinliang David Liee415892015-11-10 00:24:45 +0000595
Xinliang David Liee415892015-11-10 00:24:45 +0000596 return std::move(VPD);
597}
598
599void ValueProfData::swapBytesToHost(support::endianness Endianness) {
600 using namespace support;
601 if (Endianness == getHostEndianness())
602 return;
603
604 sys::swapByteOrder<uint32_t>(TotalSize);
605 sys::swapByteOrder<uint32_t>(NumValueKinds);
606
Xinliang David Lif47cf552015-11-25 06:23:38 +0000607 ValueProfRecord *VR = getFirstValueProfRecord(this);
Xinliang David Liee415892015-11-10 00:24:45 +0000608 for (uint32_t K = 0; K < NumValueKinds; K++) {
609 VR->swapBytes(Endianness, getHostEndianness());
Xinliang David Liac5b8602015-11-25 04:29:24 +0000610 VR = getValueProfRecordNext(VR);
Xinliang David Liee415892015-11-10 00:24:45 +0000611 }
612}
613
614void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
615 using namespace support;
616 if (Endianness == getHostEndianness())
617 return;
618
Xinliang David Lif47cf552015-11-25 06:23:38 +0000619 ValueProfRecord *VR = getFirstValueProfRecord(this);
Xinliang David Liee415892015-11-10 00:24:45 +0000620 for (uint32_t K = 0; K < NumValueKinds; K++) {
Xinliang David Liac5b8602015-11-25 04:29:24 +0000621 ValueProfRecord *NVR = getValueProfRecordNext(VR);
Xinliang David Liee415892015-11-10 00:24:45 +0000622 VR->swapBytes(getHostEndianness(), Endianness);
623 VR = NVR;
624 }
625 sys::swapByteOrder<uint32_t>(TotalSize);
626 sys::swapByteOrder<uint32_t>(NumValueKinds);
627}
Xinliang David Lie8092312015-11-25 19:13:00 +0000628
Xinliang David Li402477d2016-02-04 19:11:43 +0000629void annotateValueSite(Module &M, Instruction &Inst,
630 const InstrProfRecord &InstrProfR,
Rong Xu69683f12016-02-10 22:19:43 +0000631 InstrProfValueKind ValueKind, uint32_t SiteIdx,
632 uint32_t MaxMDCount) {
Xinliang David Li402477d2016-02-04 19:11:43 +0000633 uint32_t NV = InstrProfR.getNumValueDataForSite(ValueKind, SiteIdx);
634
635 uint64_t Sum = 0;
636 std::unique_ptr<InstrProfValueData[]> VD =
637 InstrProfR.getValueForSite(ValueKind, SiteIdx, &Sum);
638
Rong Xu311ada12016-03-30 16:56:31 +0000639 ArrayRef<InstrProfValueData> VDs(VD.get(), NV);
640 annotateValueSite(M, Inst, VDs, Sum, ValueKind, MaxMDCount);
Rong Xubb494902016-02-12 21:36:17 +0000641}
642
643void annotateValueSite(Module &M, Instruction &Inst,
Rong Xu311ada12016-03-30 16:56:31 +0000644 ArrayRef<InstrProfValueData> VDs,
Rong Xubb494902016-02-12 21:36:17 +0000645 uint64_t Sum, InstrProfValueKind ValueKind,
646 uint32_t MaxMDCount) {
Xinliang David Li402477d2016-02-04 19:11:43 +0000647 LLVMContext &Ctx = M.getContext();
648 MDBuilder MDHelper(Ctx);
649 SmallVector<Metadata *, 3> Vals;
650 // Tag
651 Vals.push_back(MDHelper.createString("VP"));
652 // Value Kind
653 Vals.push_back(MDHelper.createConstant(
654 ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind)));
655 // Total Count
656 Vals.push_back(
657 MDHelper.createConstant(ConstantInt::get(Type::getInt64Ty(Ctx), Sum)));
658
659 // Value Profile Data
Rong Xu69683f12016-02-10 22:19:43 +0000660 uint32_t MDCount = MaxMDCount;
Rong Xu311ada12016-03-30 16:56:31 +0000661 for (auto &VD : VDs) {
Xinliang David Li402477d2016-02-04 19:11:43 +0000662 Vals.push_back(MDHelper.createConstant(
Rong Xu311ada12016-03-30 16:56:31 +0000663 ConstantInt::get(Type::getInt64Ty(Ctx), VD.Value)));
Xinliang David Li402477d2016-02-04 19:11:43 +0000664 Vals.push_back(MDHelper.createConstant(
Rong Xu311ada12016-03-30 16:56:31 +0000665 ConstantInt::get(Type::getInt64Ty(Ctx), VD.Count)));
Xinliang David Li402477d2016-02-04 19:11:43 +0000666 if (--MDCount == 0)
667 break;
668 }
669 Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals));
670}
671
672bool getValueProfDataFromInst(const Instruction &Inst,
673 InstrProfValueKind ValueKind,
674 uint32_t MaxNumValueData,
675 InstrProfValueData ValueData[],
676 uint32_t &ActualNumValueData, uint64_t &TotalC) {
677 MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof);
678 if (!MD)
679 return false;
680
681 unsigned NOps = MD->getNumOperands();
682
683 if (NOps < 5)
684 return false;
685
686 // Operand 0 is a string tag "VP":
687 MDString *Tag = cast<MDString>(MD->getOperand(0));
688 if (!Tag)
689 return false;
690
691 if (!Tag->getString().equals("VP"))
692 return false;
693
694 // Now check kind:
695 ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
696 if (!KindInt)
697 return false;
698 if (KindInt->getZExtValue() != ValueKind)
699 return false;
700
701 // Get total count
702 ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
703 if (!TotalCInt)
704 return false;
705 TotalC = TotalCInt->getZExtValue();
706
707 ActualNumValueData = 0;
708
709 for (unsigned I = 3; I < NOps; I += 2) {
710 if (ActualNumValueData >= MaxNumValueData)
711 break;
712 ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I));
713 ConstantInt *Count =
714 mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1));
715 if (!Value || !Count)
716 return false;
717 ValueData[ActualNumValueData].Value = Value->getZExtValue();
718 ValueData[ActualNumValueData].Count = Count->getZExtValue();
719 ActualNumValueData++;
720 }
721 return true;
722}
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000723} // end namespace llvm