LLVM: include/llvm/ProfileData/SampleProf.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H
15#define LLVM_PROFILEDATA_SAMPLEPROF_H
16
29#include
30#include
31#include
32#include
33#include
34#include
35#include
36#include <system_error>
37#include <unordered_map>
38#include
39
40namespace llvm {
41
42class DILocation;
43class raw_ostream;
44
46
63};
64
67}
68
71
72
77}
78
79}
80
81namespace std {
82
83template <>
84struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
85
86}
87
88namespace llvm {
89namespace sampleprof {
90
99
104};
105
107 return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) |
111}
112
114
115
116
117
126
130
132 switch (static_cast<int>(Type)) {
134 return "InvalidSection";
136 return "ProfileSummarySection";
138 return "NameTableSection";
140 return "ProfileSymbolListSection";
142 return "FuncOffsetTableSection";
144 return "FunctionMetadata";
146 return "CSNameTableSection";
148 return "LBRProfileSection";
149 default:
150 return "UnknownSection";
151 }
152}
153
154
155
161
162
164};
165
166
167
168
172
174};
175
176
177
178
182
183
185
186
188};
191
192
193
195
196
198
199
201
202
204};
205
210};
211
214
215
217};
218
219
220template
222
223 if (std::is_same<SecCommonFlags, SecFlagType>())
224 return;
225
226
227 bool IsFlagLegal = false;
228 switch (Type) {
230 IsFlagLegal = std::is_same<SecNameTableFlags, SecFlagType>();
231 break;
233 IsFlagLegal = std::is_same<SecProfSummaryFlags, SecFlagType>();
234 break;
236 IsFlagLegal = std::is_same<SecFuncMetadataFlags, SecFlagType>();
237 break;
238 default:
240 IsFlagLegal = std::is_same<SecFuncOffsetFlags, SecFlagType>();
241 break;
242 }
243 if (!IsFlagLegal)
244 llvm_unreachable("Misuse of a flag in an incompatible section");
245}
246
247template
250 auto FVal = static_cast<uint64_t>(Flag);
251 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
252 Entry.Flags |= IsCommon ? FVal : (FVal << 32);
253}
254
255template
258 auto FVal = static_cast<uint64_t>(Flag);
259 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
260 Entry.Flags &= ~(IsCommon ? FVal : (FVal << 32));
261}
262
263template
266 auto FVal = static_cast<uint64_t>(Flag);
267 bool IsCommon = std::is_same<SecCommonFlags, SecFlagType>();
268 return Entry.Flags & (IsCommon ? FVal : (FVal << 32));
269}
270
271
272
273
274
275
276
277
278
279
282
284 void dump() const;
285
289 }
290
293 }
294
297 }
298
301 }
302
305};
306
310 }
311};
312
314
315
316
317
318
319
320
321
322
323
324
326public:
327 using CallTarget = std::pair<FunctionId, uint64_t>;
330 if (LHS.second != RHS.second)
331 return LHS.second > RHS.second;
332
333 return LHS.first < RHS.first;
334 }
335 };
336
338 using CallTargetMap = std::unordered_map<FunctionId, uint64_t>;
340
341
342
343
344
345
347 bool Overflowed;
351 }
352
353
354
356 if (S > NumSamples)
357 S = NumSamples;
358 NumSamples -= S;
359 return S;
360 }
361
362
363
364
365
366
369 uint64_t &TargetSamples = CallTargets[F];
370 bool Overflowed;
371 TargetSamples =
375 }
376
377
378
381 auto I = CallTargets.find(F);
382 if (I != CallTargets.end()) {
383 Count = I->second;
384 CallTargets.erase(I);
385 }
386 return Count;
387 }
388
389
390 bool hasCalls() const { return !CallTargets.empty(); }
391
396 }
397
400 for (const auto &I : CallTargets)
401 Sum += I.second;
402 return Sum;
403 }
404
405
409 for (const auto &[Target, Frequency] : Targets) {
410 SortedTargets.emplace(Target, Frequency);
411 }
412 return SortedTargets;
413 }
414
415
417 float DistributionFactor) {
419 for (const auto &[Target, Frequency] : Targets) {
420 AdjustedTargets[Target] = Frequency * DistributionFactor;
421 }
422 return AdjustedTargets;
423 }
424
425
426
429 void dump() const;
430
432 return NumSamples == Other.NumSamples && CallTargets == Other.CallTargets;
433 }
434
436 return !(*this == Other);
437 }
438
439private:
442};
443
445
446
449 RawContext = 0x1,
450 SyntheticContext = 0x2,
451 InlinedContext = 0x4,
452 MergedContext = 0x8
454
455
461 0x4,
462};
463
464
468
470
473
476 }
477
479 return !(*this == That);
480 }
481
482 std::string toString(bool OutputLineLocation) const {
483 std::ostringstream OContextStr;
484 OContextStr << Func.str();
485 if (OutputLineLocation) {
489 }
490 return OContextStr.str();
491 }
492
496 return NameHash + (LocId << 5) + LocId;
497 }
498};
499
502}
503
506
510 }
511};
512
513
514
515
516
517
518
519
520
521
522
524public:
526
529 assert(.empty() && "Name is empty");
530 }
531
534
538 assert(!Context.empty() && "Context is empty");
540 }
541
542
543
544
546 std::list &CSNameTable,
550
551
552 bool HasContext = ContextStr.starts_with("[");
553 if (!HasContext) {
556 } else {
557 CSNameTable.emplace_back();
561 }
562 }
563
564
565
568
569 ContextStr = ContextStr.substr(1, ContextStr.size() - 2);
570 StringRef ContextRemain = ContextStr;
573 while (!ContextRemain.empty()) {
574 auto ContextSplit = ContextRemain.split(" @ ");
575 ChildContext = ContextSplit.first;
576 ContextRemain = ContextSplit.second;
580 }
581 }
582
583
584
588
589 auto EntrySplit = ContextStr.split(':');
591
592 LineLoc = {0, 0};
593 if (!EntrySplit.second.empty()) {
594
595
596 int LineOffset = 0;
597 auto LocSplit = EntrySplit.second.split('.');
598 LocSplit.first.getAsInteger(10, LineOffset);
600
601
602 if (!LocSplit.second.empty())
603 LocSplit.second.getAsInteger(10, LineLoc.Discriminator);
604 }
605 }
606
619
621 bool IncludeLeafLineLocation = false) {
622 std::ostringstream OContextStr;
624 if (OContextStr.str().size()) {
625 OContextStr << " @ ";
626 }
627 OContextStr << Context[I].toString(I != Context.size() - 1 ||
628 IncludeLeafLineLocation);
629 }
630 return OContextStr.str();
631 }
632
635 return Func.str();
637 }
638
643 }
644
645
647 Func = NewFunctionID;
650 }
651
655 FullContext = Context;
657 State = CState;
658 }
659
661 return State == That.State && Func == That.Func &&
662 FullContext == That.FullContext;
663 }
664
666
668 if (State != That.State)
669 return State < That.State;
670
672 return Func < That.Func;
673 }
674
676 while (I < std::min(FullContext.size(), That.FullContext.size())) {
677 auto &Context1 = FullContext[I];
678 auto &Context2 = That.FullContext[I];
679 auto V = Context1.Func.compare(Context2.Func);
680 if (V)
681 return V < 0;
682 if (Context1.Location != Context2.Location)
683 return Context1.Location < Context2.Location;
684 I++;
685 }
686
687 return FullContext.size() < That.FullContext.size();
688 }
689
693 }
694 };
695
697 auto ThisContext = FullContext;
698 auto ThatContext = That.FullContext;
699 if (ThatContext.size() < ThisContext.size())
700 return false;
701 ThatContext = ThatContext.take_front(ThisContext.size());
702
703 if (ThisContext.back().Func != ThatContext.back().Func)
704 return false;
705
707 }
708
709private:
710
711
713
715
717
719};
720
723}
724
727}
728
731
733
734
738 std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
739
740
741
742
743
744
746public:
748
750 void dump() const;
751
753 bool Overflowed;
754 TotalSamples =
758 }
759
761 if (TotalSamples < Num)
762 TotalSamples = 0;
763 else
764 TotalSamples -= Num;
765 }
766
768
770
772 bool Overflowed;
773 TotalHeadSamples =
777 }
778
781 return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
782 Num, Weight);
783 }
784
790 return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
791 Func, Num, Weight);
792 }
793
797 return BodySamples[Location].merge(SampleRecord, Weight);
798 }
799
800
801
806 auto I = BodySamples.find(LineLocation(LineOffset, Discriminator));
807 if (I != BodySamples.end()) {
808 Count = I->second.removeCalledTarget(Func);
809 Count = I->second.removeSamples(Count);
810 if (->second.getSamples())
811 BodySamples.erase(I);
812 }
813 return Count;
814 }
815
816
817
819 CallsiteSamples.clear();
820 }
821
822
824 for (auto &I : BodySamples) {
825 uint64_t TargetSamples = I.second.getCallTargetSum();
826
827
828
829
830 if (TargetSamples > I.second.getSamples())
831 I.second.addSamples(TargetSamples - I.second.getSamples());
832 }
833 }
834
835
838 for (const auto &I : BodySamples)
840
841 for (auto &I : CallsiteSamples) {
842 for (auto &CS : I.second) {
843 CS.second.updateTotalSamples();
845 }
846 }
847 }
848
849
852 for (auto &I : CallsiteSamples) {
853 for (auto &CS : I.second) {
854 CS.second.setContextSynthetic();
855 }
856 }
857 }
858
859
861
862
863 if (!IRToProfileLocationMap)
864 return IRLoc;
865 const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc);
866 if (ProfileLoc != IRToProfileLocationMap->end())
867 return ProfileLoc->second;
868 return IRLoc;
869 }
870
871
872
873
875 uint32_t Discriminator) const {
876 const auto &Ret = BodySamples.find(
878 if (Ret == BodySamples.end())
879 return std::error_code();
880 return Ret->second.getSamples();
881 }
882
883
884
885
888 const auto &Ret = BodySamples.find(
890 if (Ret == BodySamples.end())
891 return std::error_code();
892 return Ret->second.getCallTargets();
893 }
894
895
896
900 if (Ret == BodySamples.end())
901 return std::error_code();
902 return Ret->second.getCallTargets();
903 }
904
905
908 }
909
910
914 if (Iter == CallsiteSamples.end())
915 return nullptr;
916 return &Iter->second;
917 }
918
919
920
921
922
923
924
929 *FuncNameToProfNameMap = nullptr) const;
930
931 bool empty() const { return TotalSamples == 0; }
932
933
935
936
937
938
939
940
941
943
944
945
946
947
948
951
952
954 }
956
957
958 if (!BodySamples.empty() &&
959 (CallsiteSamples.empty() ||
960 BodySamples.begin()->first < CallsiteSamples.begin()->first))
961 Count = BodySamples.begin()->second.getSamples();
962 else if (!CallsiteSamples.empty()) {
963
964
965 for (const auto &FuncSamples : CallsiteSamples.begin()->second)
966 Count += FuncSamples.second.getHeadSamplesEstimate();
967 }
968
969 return Count ? Count : TotalSamples > 0;
970 }
971
972
974
975
977 return CallsiteSamples;
978 }
979
980
981
982
983
987 MaxCount = std::max(MaxCount, L.second.getSamples());
988 if (SkipCallSite)
989 return MaxCount;
991 for (const FunctionSamplesMap::value_type &F : C.second)
992 MaxCount = std::max(MaxCount, F.second.getMaxCountInside());
993 return MaxCount;
994 }
995
996
997
1003 Context = Other.getContext();
1004 if (FunctionHash == 0) {
1005
1006 FunctionHash = Other.getFunctionHash();
1007 } else if (FunctionHash != Other.getFunctionHash()) {
1008
1009
1010
1011
1012
1013
1014
1016 }
1017
1022 for (const auto &I : Other.getBodySamples()) {
1026 }
1027 for (const auto &I : Other.getCallsiteSamples()) {
1030 for (const auto &Rec : I.second)
1032 FSMap[Rec.first].merge(Rec.second, Weight));
1033 }
1034 return Result;
1035 }
1036
1037
1038
1039
1040
1045 if (TotalSamples <= Threshold)
1046 return;
1047 auto IsDeclaration = [](const Function *F) {
1048 return || F->isDeclaration();
1049 };
1051
1053 }
1054
1055
1056 for (const auto &BS : BodySamples)
1057 for (const auto &TS : BS.second.getCallTargets())
1058 if (TS.second > Threshold) {
1059 const Function *Callee = SymbolMap.lookup(TS.first);
1060 if (IsDeclaration(Callee))
1061 S.insert(TS.first.getHashCode());
1062 }
1063 for (const auto &CS : CallsiteSamples)
1064 for (const auto &NameFS : CS.second)
1065 NameFS.second.findInlinedFunctions(S, SymbolMap, Threshold);
1066 }
1067
1068
1071 }
1072
1073
1075
1076
1078
1080
1082
1084 assert(IRToProfileLocationMap == nullptr && "this should be set only once");
1085 IRToProfileLocationMap = LTLM;
1086 }
1087
1088
1089
1091 const char *AttrName = "sample-profile-suffix-elision-policy";
1092 auto Attr = F.getFnAttribute(AttrName).getValueAsString();
1094 }
1095
1096
1097
1100 static constexpr const char *UniqSuffix = ".__uniq.";
1101
1104
1105
1106
1108 if (Attr == "" || Attr == "all")
1109 return FnName.split('.').first;
1110 if (Attr == "selected") {
1112 for (const auto &Suf : KnownSuffixes) {
1114
1115
1117 continue;
1118 auto It = Cand.rfind(Suffix);
1120 continue;
1121 auto Dit = Cand.rfind('.');
1122 if (Dit == It + Suffix.size() - 1)
1123 Cand = Cand.substr(0, It);
1124 }
1125 return Cand;
1126 }
1127 if (Attr == "none")
1128 return FnName;
1129 assert(false && "internal error: unknown suffix elision policy");
1130 return FnName;
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1142 return Func.stringRef();
1143
1146 }
1147
1148
1149
1151
1152
1153
1154
1155
1158
1159
1160
1161
1162
1166 }
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1184 *FuncNameToProfNameMap = nullptr) const;
1185
1187
1189
1191
1193
1195
1196
1198
1199
1201
1202
1204
1205
1206
1208
1209
1210
1213 }
1214
1215
1216
1218
1223 FunctionHash == Other.FunctionHash && Context == Other.Context &&
1224 TotalSamples == Other.TotalSamples &&
1225 TotalHeadSamples == Other.TotalHeadSamples &&
1226 BodySamples == Other.BodySamples &&
1227 CallsiteSamples == Other.CallsiteSamples;
1228 }
1229
1231 return !(*this == Other);
1232 }
1233
1234private:
1235
1237
1238
1240
1241
1242
1243
1244
1246
1247
1248
1249
1250 uint64_t TotalHeadSamples = 0;
1251
1252
1253
1254
1255
1256
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294 const LocToLocMap *IRToProfileLocationMap = nullptr;
1295};
1296
1297
1298
1303}
1304
1306
1307
1308
1309
1310
1311
1313 : public HashKeyMap<std::unordered_map, SampleContext, FunctionSamples> {
1314public:
1315
1316
1319 if (Ret.second)
1320 Ret.first->second.setContext(Ctx);
1321 return Ret.first->second;
1322 }
1323
1326 Ctx);
1327 }
1328
1331 Ctx);
1332 }
1333
1337 }
1338
1339 size_t erase(const key_type &Key) { return base_type::erase(Key); }
1340
1342};
1343
1345
1347 std::vector &SortedProfiles);
1348
1349
1350
1351
1352
1353template <class LocationT, class SampleT> class SampleSorter {
1354public:
1357
1359 for (const auto &I : Samples)
1362 return A->first < B->first;
1363 });
1364 }
1365
1367
1368private:
1370};
1371
1372
1373
1374
1376public:
1378
1379
1380
1381
1382
1383
1384
1386 bool TrimColdContext,
1387 bool MergeColdContext,
1388 uint32_t ColdContextFrameLength,
1389 bool TrimBaseProfileOnly);
1390
1391private:
1393};
1394
1395
1396
1397
1398
1400public:
1402
1403
1410
1411
1413
1415
1417
1419
1422 };
1423
1425 bool ProfileIsCS = false) {
1427 flattenProfile(ProfileMap, TmpProfiles, ProfileIsCS);
1428 ProfileMap = std::move(TmpProfiles);
1429 }
1430
1433 bool ProfileIsCS = false) {
1434 if (ProfileIsCS) {
1435 for (const auto &I : InputProfiles) {
1436
1437
1439 FS.merge(I.second);
1440 }
1441 } else {
1442 for (const auto &I : InputProfiles)
1443 flattenNestedProfile(OutputProfiles, I.second);
1444 }
1445 }
1446
1447private:
1448 static void flattenNestedProfile(SampleProfileMap &OutputProfiles,
1450
1451
1453 auto Ret = OutputProfiles.try_emplace(Context, FS);
1455 if (Ret.second) {
1456
1457
1458 Profile.removeAllCallsiteSamples();
1459
1460 Profile.setTotalSamples(0);
1461 } else {
1464 }
1465 }
1466
1468 "There should be no inlinees' profiles after flattening.");
1469
1470
1471
1472
1473
1474 uint64_t TotalSamples = FS.getTotalSamples();
1475
1476 for (const auto &I : FS.getCallsiteSamples()) {
1477 for (const auto &Callee : I.second) {
1478 const auto &CalleeProfile = Callee.second;
1479
1480 Profile.addBodySamples(I.first.LineOffset, I.first.Discriminator,
1481 CalleeProfile.getHeadSamplesEstimate());
1482
1483 Profile.addCalledTargetSamples(
1484 I.first.LineOffset, I.first.Discriminator,
1485 CalleeProfile.getFunction(),
1486 CalleeProfile.getHeadSamplesEstimate());
1487
1488 TotalSamples = TotalSamples >= CalleeProfile.getTotalSamples()
1489 ? TotalSamples - CalleeProfile.getTotalSamples()
1490 : 0;
1491 TotalSamples += CalleeProfile.getHeadSamplesEstimate();
1492
1493 flattenNestedProfile(OutputProfiles, CalleeProfile);
1494 }
1495 }
1496 Profile.addTotalSamples(TotalSamples);
1497
1498 Profile.setHeadSamples(Profile.getHeadSamplesEstimate());
1499 }
1500
1501
1503 FrameNode *getOrCreateContextPath(const SampleContext &Context);
1504
1505 SampleProfileMap &ProfileMap;
1506 FrameNode RootFrame;
1507};
1508
1509
1510
1511
1512
1514public:
1515
1516
1518 if (!Copy) {
1519 Syms.insert(Name);
1520 return;
1521 }
1522 Syms.insert(Name.copy(Allocator));
1523 }
1524
1526
1528 for (auto Sym : List.Syms)
1530 }
1531
1532 unsigned size() { return Syms.size(); }
1533
1536
1540
1541private:
1542
1543
1544
1545 bool ToCompress = false;
1548};
1549
1550}
1551
1552using namespace sampleprof;
1553
1556
1559 }
1560
1563 }
1564
1567 }
1568};
1569
1570
1571
1572
1573
1574
1582
1583
1584 llvm::APInt IntHash(128, Str.str(), 16);
1585 return toString(IntHash, 10, false)
1587}
1588
1589}
1590
1591#endif
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
Provides ErrorOr smart pointer.
Defines HashKeyMap template.
static cl::opt< unsigned > ColdCountThreshold("mfs-count-threshold", cl::desc("Minimum number of times a block must be executed to be retained."), cl::init(1), cl::Hidden)
Defines FunctionId class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
Class for arbitrary precision integers.
const T & back() const
back - Get the last element.
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
size_t size() const
size - Get the array size.
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
bool empty() const
empty - Check if the array is empty.
Allocate memory in an ever growing pool, as if by bump-pointer.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Implements a dense probed hash-table based set.
Represents either an error or a value T.
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
static void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)
Translates the bytes in Res to a hex string that is deposited into Str.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
static constexpr size_t npos
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
std::pair< iterator, bool > insert(const ValueT &V)
An opaque object representing a hash code.
This class implements an extremely fast bulk output stream that can only output to a stream.
This class represents a function that is read from a sample profile.
uint64_t getHashCode() const
Get hash code of this object.
std::string str() const
Convert to a string, usually for output purpose.
Representation of the samples collected for a function.
void setTotalSamples(uint64_t Num)
static bool ProfileIsPreInlined
void findInlinedFunctions(DenseSet< GlobalValue::GUID > &S, const HashKeyMap< std::unordered_map, FunctionId, Function * > &SymbolMap, uint64_t Threshold) const
Recursively traverses all children, if the total sample count of the corresponding function is no les...
bool operator!=(const FunctionSamples &Other) const
void updateTotalSamples()
void setHeadSamples(uint64_t Num)
const FunctionSamples * findFunctionSamplesAt(const LineLocation &Loc, StringRef CalleeName, SampleProfileReaderItaniumRemapper *Remapper, const HashKeyMap< std::unordered_map, FunctionId, FunctionId > *FuncNameToProfNameMap=nullptr) const
Returns a pointer to FunctionSamples at the given callsite location Loc with callee CalleeName.
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight=1)
static constexpr const char * UniqSuffix
void updateCallsiteSamples()
static StringRef getCanonicalFnName(StringRef FnName, StringRef Attr="selected")
bool operator==(const FunctionSamples &Other) const
static constexpr const char * PartSuffix
static uint64_t getCallSiteHash(FunctionId Callee, const LineLocation &Callsite)
Returns a unique hash code for a combination of a callsite location and the callee function name.
const FunctionSamplesMap * findFunctionSamplesMapAt(const LineLocation &Loc) const
Returns the FunctionSamplesMap at the given Loc.
void removeAllCallsiteSamples()
uint64_t getMaxCountInside(bool SkipCallSite=false) const
Return the maximum of sample counts in a function body.
void removeTotalSamples(uint64_t Num)
uint64_t getHeadSamples() const
For top-level functions, return the total number of branch samples that have the function as the bran...
void setFunction(FunctionId NewFunctionID)
Set the name of the function.
ErrorOr< uint64_t > findSamplesAt(uint32_t LineOffset, uint32_t Discriminator) const
Return the number of samples collected at the given location.
ErrorOr< const SampleRecord::CallTargetMap & > findCallTargetMapAt(const LineLocation &CallSite) const
Returns the call target map collected at a given location specified by CallSite.
const LineLocation & mapIRLocToProfileLoc(const LineLocation &IRLoc) const
FunctionId getFunction() const
Return the function name.
uint64_t getFunctionHash() const
static constexpr const char * LLVMSuffix
Name suffixes which canonicalization should handle to avoid profile mismatch.
StringRef getFuncName(FunctionId Func) const
Translate Func into its original name.
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight=1)
sampleprof_error addSampleRecord(LineLocation Location, const SampleRecord &SampleRecord, uint64_t Weight=1)
uint64_t removeCalledTargetAndBodySample(uint32_t LineOffset, uint32_t Discriminator, FunctionId Func)
DenseMap< uint64_t, StringRef > * GUIDToFuncNameMap
GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for all the function symbols define...
sampleprof_error addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator, FunctionId Func, uint64_t Num, uint64_t Weight=1)
FunctionSamplesMap & functionSamplesAt(const LineLocation &Loc)
Return the function samples at the given callsite location.
const FunctionSamples * findFunctionSamples(const DILocation *DIL, SampleProfileReaderItaniumRemapper *Remapper=nullptr, const HashKeyMap< std::unordered_map, FunctionId, FunctionId > *FuncNameToProfNameMap=nullptr) const
Get the FunctionSamples of the inline instance where DIL originates from.
static bool ProfileIsProbeBased
void setIRToProfileLocationMap(const LocToLocMap *LTLM)
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
StringRef getFuncName() const
Return the original function name.
void findAllNames(DenseSet< FunctionId > &NameSet) const
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num, uint64_t Weight=1)
static unsigned getOffset(const DILocation *DIL)
Returns the line offset to the start line of the subprogram.
void setContextSynthetic()
void setFunctionHash(uint64_t Hash)
static bool ProfileIsFS
If this profile uses flow sensitive discriminators.
ErrorOr< const SampleRecord::CallTargetMap & > findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const
Returns the call target map collected at a given location.
SampleContext & getContext() const
static bool HasUniqSuffix
Whether the profile contains any ".__uniq." suffix in a name.
uint64_t getTotalSamples() const
Return the total number of samples collected inside the function.
void print(raw_ostream &OS=dbgs(), unsigned Indent=0) const
Print the samples collected for a function on stream OS.
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
FunctionSamples()=default
const CallsiteSampleMap & getCallsiteSamples() const
Return all the callsite samples collected in the body of the function.
void setContext(const SampleContext &FContext)
static LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
uint64_t getHeadSamplesEstimate() const
Return an estimate of the sample count of the function entry basic block.
uint64_t getGUID() const
Return the GUID of the context's name.
const BodySampleMap & getBodySamples() const
Return all the samples collected in the body of the function.
static bool UseMD5
Whether the profile uses MD5 to represent string.
This class is a wrapper to associative container MapT<KeyT, ValueT> using the hash value of the origi...
std::pair< iterator, bool > try_emplace(const key_type &Hash, const original_key_type &Key, Ts &&...Args)
typename base_type::iterator iterator
decltype(hash_value(SampleContext())) key_type
size_t erase(const original_key_type &Ctx)
iterator find(const original_key_type &Key)
typename base_type::const_iterator const_iterator
Helper class for profile conversion.
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
static void flattenProfile(const SampleProfileMap &InputProfiles, SampleProfileMap &OutputProfiles, bool ProfileIsCS=false)
ProfileSymbolList records the list of function symbols shown up in the binary used to generate the pr...
void setToCompress(bool TC)
void add(StringRef Name, bool Copy=false)
copy indicates whether we need to copy the underlying memory for the input Name.
std::error_code write(raw_ostream &OS)
void dump(raw_ostream &OS=dbgs()) const
void merge(const ProfileSymbolList &List)
bool contains(StringRef Name)
std::error_code read(const uint8_t *Data, uint64_t ListSize)
SampleContextTrimmer impelements helper functions to trim, merge cold context profiles.
SampleContextTrimmer(SampleProfileMap &Profiles)
void trimAndMergeColdContextProfiles(uint64_t ColdCountThreshold, bool TrimColdContext, bool MergeColdContext, uint32_t ColdContextFrameLength, bool TrimBaseProfileOnly)
static void createCtxVectorFromStr(StringRef ContextStr, SampleContextFrameVector &Context)
Create a context vector from a given context string and save it in Context.
bool operator==(const SampleContext &That) const
void setFunction(FunctionId NewFunctionID)
Set the name of the function and clear the current context.
SampleContext(SampleContextFrames Context, ContextStateMask CState=RawContext)
bool operator<(const SampleContext &That) const
SampleContext(StringRef ContextStr, std::list< SampleContextFrameVector > &CSNameTable, ContextStateMask CState=RawContext)
bool hasState(ContextStateMask S)
void clearState(ContextStateMask S)
SampleContextFrames getContextFrames() const
SampleContext(FunctionId Func)
bool isBaseContext() const
static void decodeContextString(StringRef ContextStr, FunctionId &Func, LineLocation &LineLoc)
static std::string getContextString(SampleContextFrames Context, bool IncludeLeafLineLocation=false)
bool operator!=(const SampleContext &That) const
void setState(ContextStateMask S)
void setAllAttributes(uint32_t A)
uint64_t getHashCode() const
void setContext(SampleContextFrames Context, ContextStateMask CState=RawContext)
FunctionId getFunction() const
uint32_t getAllAttributes()
void setAttribute(ContextAttributeMask A)
bool hasAttribute(ContextAttributeMask A)
std::string toString() const
SampleContext(StringRef Name)
bool isPrefixOf(const SampleContext &That) const
This class provides operator overloads to the map container using MD5 as the key type,...
iterator find(const SampleContext &Ctx)
mapped_type & create(const SampleContext &Ctx)
iterator erase(iterator It)
size_t erase(const key_type &Key)
const_iterator find(const SampleContext &Ctx) const
size_t erase(const SampleContext &Ctx)
SampleProfileReaderItaniumRemapper remaps the profile data from a sample profile data reader,...
Representation of a single sample record.
std::unordered_map< FunctionId, uint64_t > CallTargetMap
bool hasCalls() const
Return true if this sample record contains function calls.
sampleprof_error merge(const SampleRecord &Other, uint64_t Weight=1)
Merge the samples in Other into this record.
static const SortedCallTargetSet sortCallTargets(const CallTargetMap &Targets)
Sort call targets in descending order of call frequency.
const CallTargetMap & getCallTargets() const
std::set< CallTarget, CallTargetComparator > SortedCallTargetSet
uint64_t getSamples() const
uint64_t getCallTargetSum() const
uint64_t removeSamples(uint64_t S)
Decrease the number of samples for this record by S.
sampleprof_error addSamples(uint64_t S, uint64_t Weight=1)
Increment the number of samples for this record by S.
uint64_t removeCalledTarget(FunctionId F)
Remove called function from the call target map.
const SortedCallTargetSet getSortedCallTargets() const
static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, float DistributionFactor)
Prorate call targets by a distribution factor.
std::pair< FunctionId, uint64_t > CallTarget
bool operator!=(const SampleRecord &Other) const
bool operator==(const SampleRecord &Other) const
void print(raw_ostream &OS, unsigned Indent) const
Print the sample record to the stream OS indented by Indent.
sampleprof_error addCalledTarget(FunctionId F, uint64_t S, uint64_t Weight=1)
Add called function F with samples S.
Sort a LocationT->SampleT map by LocationT.
std::pair< const LocationT, SampleT > SamplesWithLoc
SampleSorter(const std::map< LocationT, SampleT > &Samples)
const SamplesWithLocList & get() const
SmallVector< const SamplesWithLoc *, 20 > SamplesWithLocList
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
static FunctionId getRepInFormat(StringRef Name)
Get the proper representation of a string according to whether the current Format uses MD5 to represe...
static void verifySecFlag(SecType Type, SecFlagType Flag)
ArrayRef< SampleContextFrame > SampleContextFrames
void sortFuncProfiles(const SampleProfileMap &ProfileMap, std::vector< NameFunctionSamples > &SortedProfiles)
static uint64_t SPMagic(SampleProfileFormat Format=SPF_Binary)
std::unordered_map< LineLocation, LineLocation, LineLocationHash > LocToLocMap
std::pair< hash_code, const FunctionSamples * > NameFunctionSamples
static void addSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
static bool hasSecFlag(const SecHdrTableEntry &Entry, SecFlagType Flag)
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
@ ContextDuplicatedIntoBase
std::map< LineLocation, SampleRecord > BodySampleMap
@ SecFlagIsPreInlined
SecFlagIsPreInlined means this profile contains ShouldBeInlined contexts thus this is CS preinliner c...
@ SecFlagPartial
SecFlagPartial means the profile is for common/shared code.
@ SecFlagFSDiscriminator
SecFlagFSDiscriminator means this profile uses flow-sensitive discriminators.
@ SecFlagFullContext
SecFlagContext means this is context-sensitive flat profile for CSSPGO.
static void removeSecFlag(SecHdrTableEntry &Entry, SecFlagType Flag)
std::map< FunctionId, FunctionSamples > FunctionSamplesMap
raw_ostream & operator<<(raw_ostream &OS, const FunctionId &Obj)
static std::string getSecName(SecType Type)
uint64_t hash_value(const FunctionId &Obj)
static uint64_t SPVersion()
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
std::error_code make_error_code(BitcodeError E)
sampleprof_error mergeSampleProfErrors(sampleprof_error &Accumulator, sampleprof_error Result)
@ unsupported_writing_format
@ ostream_seek_unsupported
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed=nullptr)
Multiply two unsigned integers, X and Y, and add the unsigned integer, A to the product.
const std::error_category & sampleprof_category()
std::string getUniqueInternalLinkagePostfix(const StringRef &FName)
const char * toString(DWARFSectionKind Kind)
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Implement std::hash so that hash_code can be used in STL containers.
static unsigned getHashValue(const SampleContext &Val)
static SampleContext getTombstoneKey()
static SampleContext getEmptyKey()
static bool isEqual(const SampleContext &LHS, const SampleContext &RHS)
An information struct used to provide DenseMap with the various necessary components for a given valu...
uint64_t operator()(const LineLocation &Loc) const
Represents the relative location of an instruction.
void print(raw_ostream &OS) const
LineLocation(uint32_t L, uint32_t D)
bool operator!=(const LineLocation &O) const
bool operator<(const LineLocation &O) const
uint64_t getHashCode() const
bool operator==(const LineLocation &O) const
FunctionSamples * FuncSamples
FrameNode(FunctionId FName=FunctionId(), FunctionSamples *FSamples=nullptr, LineLocation CallLoc={0, 0})
FrameNode * getOrCreateChildFrame(const LineLocation &CallSite, FunctionId CalleeName)
std::map< uint64_t, FrameNode > AllChildFrames
uint64_t operator()(const SampleContextFrameVector &S) const
bool operator==(const SampleContextFrame &That) const
SampleContextFrame(FunctionId Func, LineLocation Location)
bool operator!=(const SampleContextFrame &That) const
std::string toString(bool OutputLineLocation) const
uint64_t getHashCode() const
uint64_t operator()(const SampleContext &Context) const
bool operator()(const CallTarget &LHS, const CallTarget &RHS) const