File indexing completed on 2026-05-10 08:44:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_PROFILEDATA_INSTRPROF_H
0016 #define LLVM_PROFILEDATA_INSTRPROF_H
0017
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/ADT/BitmaskEnum.h"
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/IntervalMap.h"
0022 #include "llvm/ADT/STLExtras.h"
0023 #include "llvm/ADT/StringRef.h"
0024 #include "llvm/ADT/StringSet.h"
0025 #include "llvm/IR/GlobalValue.h"
0026 #include "llvm/IR/ProfileSummary.h"
0027 #include "llvm/ProfileData/InstrProfData.inc"
0028 #include "llvm/Support/BalancedPartitioning.h"
0029 #include "llvm/Support/CommandLine.h"
0030 #include "llvm/Support/Compiler.h"
0031 #include "llvm/Support/Error.h"
0032 #include "llvm/Support/ErrorHandling.h"
0033 #include "llvm/Support/MD5.h"
0034 #include "llvm/Support/MathExtras.h"
0035 #include "llvm/Support/raw_ostream.h"
0036 #include "llvm/TargetParser/Host.h"
0037 #include "llvm/TargetParser/Triple.h"
0038 #include <algorithm>
0039 #include <cassert>
0040 #include <cstddef>
0041 #include <cstdint>
0042 #include <cstring>
0043 #include <list>
0044 #include <memory>
0045 #include <string>
0046 #include <system_error>
0047 #include <utility>
0048 #include <vector>
0049
0050 namespace llvm {
0051
0052 class Function;
0053 class GlobalVariable;
0054 struct InstrProfRecord;
0055 class InstrProfSymtab;
0056 class Instruction;
0057 class MDNode;
0058 class Module;
0059
0060 enum InstrProfSectKind {
0061 #define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind,
0062 #include "llvm/ProfileData/InstrProfData.inc"
0063 };
0064
0065
0066 inline uint64_t getInstrMaxCountValue() {
0067 return std::numeric_limits<uint64_t>::max() - 2;
0068 }
0069
0070
0071
0072
0073
0074
0075 std::string getInstrProfSectionName(InstrProfSectKind IPSK,
0076 Triple::ObjectFormatType OF,
0077 bool AddSegmentInfo = true);
0078
0079
0080
0081 inline StringRef getInstrProfValueProfFuncName() {
0082 return INSTR_PROF_VALUE_PROF_FUNC_STR;
0083 }
0084
0085
0086
0087 inline StringRef getInstrProfValueProfMemOpFuncName() {
0088 return INSTR_PROF_VALUE_PROF_MEMOP_FUNC_STR;
0089 }
0090
0091
0092 inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; }
0093
0094
0095 inline StringRef getInstrProfVTableVarPrefix() { return "__profvt_"; }
0096
0097
0098 inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; }
0099
0100
0101 inline StringRef getInstrProfCountersVarPrefix() { return "__profc_"; }
0102
0103
0104 inline StringRef getInstrProfBitmapVarPrefix() { return "__profbm_"; }
0105
0106
0107 inline StringRef getInstrProfValuesVarPrefix() { return "__profvp_"; }
0108
0109
0110 inline StringRef getInstrProfVNodesVarName() { return "__llvm_prf_vnodes"; }
0111
0112
0113
0114 inline StringRef getInstrProfNamesVarName() { return "__llvm_prf_nm"; }
0115
0116 inline StringRef getInstrProfVTableNamesVarName() { return "__llvm_prf_vnm"; }
0117
0118
0119
0120
0121 inline StringRef getCoverageMappingVarName() {
0122 return "__llvm_coverage_mapping";
0123 }
0124
0125
0126
0127
0128
0129 inline StringRef getCoverageUnusedNamesVarName() {
0130 return "__llvm_coverage_names";
0131 }
0132
0133
0134
0135
0136
0137
0138 inline StringRef getInstrProfRegFuncsName() {
0139 return "__llvm_profile_register_functions";
0140 }
0141
0142
0143
0144 inline StringRef getInstrProfRegFuncName() {
0145 return "__llvm_profile_register_function";
0146 }
0147
0148
0149
0150 inline StringRef getInstrProfNamesRegFuncName() {
0151 return "__llvm_profile_register_names_function";
0152 }
0153
0154
0155
0156
0157
0158 inline StringRef getInstrProfInitFuncName() { return "__llvm_profile_init"; }
0159
0160
0161
0162
0163 inline StringRef getInstrProfRuntimeHookVarName() {
0164 return INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_RUNTIME_VAR);
0165 }
0166
0167
0168
0169 inline StringRef getInstrProfRuntimeHookVarUseFuncName() {
0170 return "__llvm_profile_runtime_user";
0171 }
0172
0173 inline StringRef getInstrProfCounterBiasVarName() {
0174 return INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR);
0175 }
0176
0177 inline StringRef getInstrProfBitmapBiasVarName() {
0178 return INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_BITMAP_BIAS_VAR);
0179 }
0180
0181
0182 inline StringRef getInstrProfNameSeparator() { return "\01"; }
0183
0184
0185
0186 bool isGPUProfTarget(const Module &M);
0187
0188
0189
0190
0191
0192
0193 std::string getPGOFuncName(const Function &F, bool InLTO = false,
0194 uint64_t Version = INSTR_PROF_INDEX_VERSION);
0195
0196
0197
0198
0199
0200 std::string getPGOFuncName(StringRef RawFuncName,
0201 GlobalValue::LinkageTypes Linkage,
0202 StringRef FileName,
0203 uint64_t Version = INSTR_PROF_INDEX_VERSION);
0204
0205
0206
0207
0208 std::string getIRPGOFuncName(const Function &F, bool InLTO = false);
0209
0210
0211
0212 std::pair<StringRef, StringRef> getParsedIRPGOName(StringRef IRPGOName);
0213
0214
0215
0216
0217
0218 std::string getPGOFuncNameVarName(StringRef FuncName,
0219 GlobalValue::LinkageTypes Linkage);
0220
0221
0222
0223
0224
0225 GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
0226
0227
0228
0229
0230
0231 GlobalVariable *createPGOFuncNameVar(Module &M,
0232 GlobalValue::LinkageTypes Linkage,
0233 StringRef PGOFuncName);
0234
0235
0236 StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
0237
0238
0239
0240 StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
0241 StringRef FileName = "<unknown>");
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 Error collectGlobalObjectNameStrings(ArrayRef<std::string> NameStrs,
0253 bool doCompression, std::string &Result);
0254
0255
0256
0257
0258
0259
0260 Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
0261 std::string &Result, bool doCompression = true);
0262
0263 Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables,
0264 std::string &Result, bool doCompression);
0265
0266
0267
0268 bool isIRPGOFlagSet(const Module *M);
0269
0270
0271
0272
0273 bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false);
0274
0275 enum InstrProfValueKind : uint32_t {
0276 #define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value,
0277 #include "llvm/ProfileData/InstrProfData.inc"
0278 };
0279
0280
0281
0282
0283 void annotateValueSite(Module &M, Instruction &Inst,
0284 const InstrProfRecord &InstrProfR,
0285 InstrProfValueKind ValueKind, uint32_t SiteIndx,
0286 uint32_t MaxMDCount = 3);
0287
0288
0289
0290
0291 void annotateValueSite(Module &M, Instruction &Inst,
0292 ArrayRef<InstrProfValueData> VDs, uint64_t Sum,
0293 InstrProfValueKind ValueKind, uint32_t MaxMDCount);
0294
0295
0296
0297
0298
0299 SmallVector<InstrProfValueData, 4>
0300 getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind,
0301 uint32_t MaxNumValueData, uint64_t &TotalC,
0302 bool GetNoICPValue = false);
0303
0304 inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; }
0305
0306 inline StringRef getPGONameMetadataName() { return "PGOName"; }
0307
0308
0309 MDNode *getPGOFuncNameMetadata(const Function &F);
0310
0311 std::string getPGOName(const GlobalVariable &V, bool InLTO = false);
0312
0313
0314
0315
0316
0317
0318 void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName);
0319
0320
0321
0322 void createPGONameMetadata(GlobalObject &GO, StringRef PGOName);
0323
0324
0325
0326 bool needsComdatForCounter(const GlobalObject &GV, const Module &M);
0327
0328
0329 enum class InstrProfKind {
0330 Unknown = 0x0,
0331
0332 FrontendInstrumentation = 0x1,
0333
0334 IRInstrumentation = 0x2,
0335
0336 FunctionEntryInstrumentation = 0x4,
0337
0338 ContextSensitive = 0x8,
0339
0340 SingleByteCoverage = 0x10,
0341
0342 FunctionEntryOnly = 0x20,
0343
0344 MemProf = 0x40,
0345
0346 TemporalProfile = 0x80,
0347
0348 LoopEntriesInstrumentation = 0x100,
0349 LLVM_MARK_AS_BITMASK_ENUM(LoopEntriesInstrumentation)
0350 };
0351
0352 const std::error_category &instrprof_category();
0353
0354 enum class instrprof_error {
0355 success = 0,
0356 eof,
0357 unrecognized_format,
0358 bad_magic,
0359 bad_header,
0360 unsupported_version,
0361 unsupported_hash_type,
0362 too_large,
0363 truncated,
0364 malformed,
0365 missing_correlation_info,
0366 unexpected_correlation_info,
0367 unable_to_correlate_profile,
0368 unknown_function,
0369 invalid_prof,
0370 hash_mismatch,
0371 count_mismatch,
0372 bitmap_mismatch,
0373 counter_overflow,
0374 value_site_count_mismatch,
0375 compress_failed,
0376 uncompress_failed,
0377 empty_raw_profile,
0378 zlib_unavailable,
0379 raw_profile_version_mismatch,
0380 counter_value_too_large,
0381 };
0382
0383
0384
0385 struct TemporalProfTraceTy {
0386 std::vector<uint64_t> FunctionNameRefs;
0387 uint64_t Weight;
0388 TemporalProfTraceTy(std::initializer_list<uint64_t> Trace = {},
0389 uint64_t Weight = 1)
0390 : FunctionNameRefs(Trace), Weight(Weight) {}
0391
0392
0393
0394
0395 static void createBPFunctionNodes(ArrayRef<TemporalProfTraceTy> Traces,
0396 std::vector<BPFunctionNode> &Nodes,
0397 bool RemoveOutlierUNs = true);
0398 };
0399
0400 inline std::error_code make_error_code(instrprof_error E) {
0401 return std::error_code(static_cast<int>(E), instrprof_category());
0402 }
0403
0404 class InstrProfError : public ErrorInfo<InstrProfError> {
0405 public:
0406 InstrProfError(instrprof_error Err, const Twine &ErrStr = Twine())
0407 : Err(Err), Msg(ErrStr.str()) {
0408 assert(Err != instrprof_error::success && "Not an error");
0409 }
0410
0411 std::string message() const override;
0412
0413 void log(raw_ostream &OS) const override { OS << message(); }
0414
0415 std::error_code convertToErrorCode() const override {
0416 return make_error_code(Err);
0417 }
0418
0419 instrprof_error get() const { return Err; }
0420 const std::string &getMessage() const { return Msg; }
0421
0422
0423
0424
0425 static std::pair<instrprof_error, std::string> take(Error E) {
0426 auto Err = instrprof_error::success;
0427 std::string Msg = "";
0428 handleAllErrors(std::move(E), [&Err, &Msg](const InstrProfError &IPE) {
0429 assert(Err == instrprof_error::success && "Multiple errors encountered");
0430 Err = IPE.get();
0431 Msg = IPE.getMessage();
0432 });
0433 return {Err, Msg};
0434 }
0435
0436 static char ID;
0437
0438 private:
0439 instrprof_error Err;
0440 std::string Msg;
0441 };
0442
0443 namespace object {
0444
0445 class SectionRef;
0446
0447 }
0448
0449 namespace IndexedInstrProf {
0450
0451 uint64_t ComputeHash(StringRef K);
0452
0453 }
0454
0455
0456
0457
0458
0459
0460 class InstrProfSymtab {
0461 public:
0462 using AddrHashMap = std::vector<std::pair<uint64_t, uint64_t>>;
0463
0464 private:
0465 using AddrIntervalMap =
0466 IntervalMap<uint64_t, uint64_t, 4, IntervalMapHalfOpenInfo<uint64_t>>;
0467 StringRef Data;
0468 uint64_t Address = 0;
0469
0470
0471 StringSet<> NameTab;
0472
0473
0474
0475
0476 StringSet<> VTableNames;
0477
0478 std::vector<std::pair<uint64_t, StringRef>> MD5NameMap;
0479
0480
0481 std::vector<std::pair<uint64_t, Function *>> MD5FuncMap;
0482
0483
0484
0485
0486
0487 DenseMap<uint64_t, GlobalVariable *> MD5VTableMap;
0488
0489
0490 AddrHashMap AddrToMD5Map;
0491
0492 AddrIntervalMap::Allocator VTableAddrMapAllocator;
0493
0494 AddrIntervalMap VTableAddrMap;
0495 bool Sorted = false;
0496
0497 static StringRef getExternalSymbol() { return "** External Symbol **"; }
0498
0499
0500
0501
0502 static StringRef getCanonicalName(StringRef PGOName);
0503
0504
0505
0506
0507
0508
0509
0510 Error addFuncWithName(Function &F, StringRef PGOFuncName, bool AddCanonical);
0511
0512
0513
0514
0515
0516
0517 Error addVTableWithName(GlobalVariable &V, StringRef PGOVTableName);
0518
0519
0520
0521
0522
0523 inline void finalizeSymtab();
0524
0525 public:
0526 InstrProfSymtab() : VTableAddrMap(VTableAddrMapAllocator) {}
0527
0528
0529
0530 InstrProfSymtab(const InstrProfSymtab &) = delete;
0531 InstrProfSymtab &operator=(const InstrProfSymtab &) = delete;
0532 InstrProfSymtab(InstrProfSymtab &&) = delete;
0533 InstrProfSymtab &operator=(InstrProfSymtab &&) = delete;
0534
0535
0536
0537
0538
0539
0540
0541 Error create(object::SectionRef &Section);
0542
0543
0544
0545
0546 Error create(StringRef NameStrings);
0547
0548
0549
0550
0551
0552 Error create(StringRef FuncNameStrings, StringRef VTableNameStrings);
0553
0554
0555
0556 Error initVTableNamesFromCompressedStrings(StringRef CompressedVTableNames);
0557
0558
0559
0560 inline Error create(StringRef D, uint64_t BaseAddr);
0561
0562
0563
0564
0565
0566
0567
0568 Error create(Module &M, bool InLTO = false, bool AddCanonical = true);
0569
0570
0571
0572 template <typename NameIterRange>
0573 Error create(const NameIterRange &IterRange);
0574
0575
0576
0577
0578 template <typename FuncNameIterRange, typename VTableNameIterRange>
0579 Error create(const FuncNameIterRange &FuncIterRange,
0580 const VTableNameIterRange &VTableIterRange);
0581
0582
0583 Error addSymbolName(StringRef SymbolName) {
0584 if (SymbolName.empty())
0585 return make_error<InstrProfError>(instrprof_error::malformed,
0586 "symbol name is empty");
0587
0588
0589
0590 auto Ins = NameTab.insert(SymbolName);
0591 if (Ins.second) {
0592 MD5NameMap.push_back(std::make_pair(
0593 IndexedInstrProf::ComputeHash(SymbolName), Ins.first->getKey()));
0594 Sorted = false;
0595 }
0596 return Error::success();
0597 }
0598
0599
0600
0601 Error addFuncName(StringRef FuncName) { return addSymbolName(FuncName); }
0602
0603
0604
0605 Error addVTableName(StringRef VTableName) {
0606 if (Error E = addSymbolName(VTableName))
0607 return E;
0608
0609
0610
0611 VTableNames.insert(VTableName);
0612 return Error::success();
0613 }
0614
0615 const StringSet<> &getVTableNames() const { return VTableNames; }
0616
0617
0618
0619 void mapAddress(uint64_t Addr, uint64_t MD5Val) {
0620 AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val));
0621 }
0622
0623
0624
0625
0626 void mapVTableAddress(uint64_t StartAddr, uint64_t EndAddr, uint64_t MD5Val) {
0627 VTableAddrMap.insert(StartAddr, EndAddr, MD5Val);
0628 }
0629
0630
0631 uint64_t getFunctionHashFromAddress(uint64_t Address);
0632
0633
0634 uint64_t getVTableHashFromAddress(uint64_t Address);
0635
0636
0637
0638
0639 StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize);
0640
0641
0642
0643 inline StringRef getFuncOrVarName(uint64_t ValMD5Hash);
0644
0645
0646
0647
0648 inline StringRef getFuncOrVarNameIfDefined(uint64_t ValMD5Hash);
0649
0650
0651 static bool isExternalSymbol(const StringRef &Symbol) {
0652 return Symbol == InstrProfSymtab::getExternalSymbol();
0653 }
0654
0655
0656 inline Function *getFunction(uint64_t FuncMD5Hash);
0657
0658
0659
0660 inline GlobalVariable *getGlobalVariable(uint64_t MD5Hash);
0661
0662
0663 inline StringRef getNameData() const { return Data; }
0664
0665
0666 void dumpNames(raw_ostream &OS) const;
0667 };
0668
0669 Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
0670 Data = D;
0671 Address = BaseAddr;
0672 return Error::success();
0673 }
0674
0675 template <typename NameIterRange>
0676 Error InstrProfSymtab::create(const NameIterRange &IterRange) {
0677 for (auto Name : IterRange)
0678 if (Error E = addFuncName(Name))
0679 return E;
0680
0681 finalizeSymtab();
0682 return Error::success();
0683 }
0684
0685 template <typename FuncNameIterRange, typename VTableNameIterRange>
0686 Error InstrProfSymtab::create(const FuncNameIterRange &FuncIterRange,
0687 const VTableNameIterRange &VTableIterRange) {
0688
0689
0690
0691 for (StringRef Name : FuncIterRange)
0692 if (Error E = addFuncName(Name))
0693 return E;
0694
0695 for (StringRef VTableName : VTableIterRange)
0696 if (Error E = addVTableName(VTableName))
0697 return E;
0698
0699 finalizeSymtab();
0700 return Error::success();
0701 }
0702
0703 void InstrProfSymtab::finalizeSymtab() {
0704 if (Sorted)
0705 return;
0706 llvm::sort(MD5NameMap, less_first());
0707 llvm::sort(MD5FuncMap, less_first());
0708 llvm::sort(AddrToMD5Map, less_first());
0709 AddrToMD5Map.erase(llvm::unique(AddrToMD5Map), AddrToMD5Map.end());
0710 Sorted = true;
0711 }
0712
0713 StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
0714 StringRef ret = getFuncOrVarName(MD5Hash);
0715 if (ret.empty())
0716 return InstrProfSymtab::getExternalSymbol();
0717 return ret;
0718 }
0719
0720 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
0721 finalizeSymtab();
0722 auto Result = llvm::lower_bound(MD5NameMap, MD5Hash,
0723 [](const std::pair<uint64_t, StringRef> &LHS,
0724 uint64_t RHS) { return LHS.first < RHS; });
0725 if (Result != MD5NameMap.end() && Result->first == MD5Hash)
0726 return Result->second;
0727 return StringRef();
0728 }
0729
0730 Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) {
0731 finalizeSymtab();
0732 auto Result = llvm::lower_bound(MD5FuncMap, FuncMD5Hash,
0733 [](const std::pair<uint64_t, Function *> &LHS,
0734 uint64_t RHS) { return LHS.first < RHS; });
0735 if (Result != MD5FuncMap.end() && Result->first == FuncMD5Hash)
0736 return Result->second;
0737 return nullptr;
0738 }
0739
0740 GlobalVariable *InstrProfSymtab::getGlobalVariable(uint64_t MD5Hash) {
0741 return MD5VTableMap.lookup(MD5Hash);
0742 }
0743
0744
0745
0746 struct CountSumOrPercent {
0747 uint64_t NumEntries = 0;
0748 double CountSum = 0.0f;
0749 std::array<double, IPVK_Last - IPVK_First + 1> ValueCounts = {};
0750 CountSumOrPercent() = default;
0751 void reset() {
0752 NumEntries = 0;
0753 CountSum = 0.0f;
0754 ValueCounts.fill(0.0f);
0755 }
0756 };
0757
0758
0759 struct OverlapStats {
0760 enum OverlapStatsLevel { ProgramLevel, FunctionLevel };
0761
0762 CountSumOrPercent Base;
0763
0764 CountSumOrPercent Test;
0765
0766 CountSumOrPercent Overlap;
0767 CountSumOrPercent Mismatch;
0768 CountSumOrPercent Unique;
0769 OverlapStatsLevel Level;
0770 const std::string *BaseFilename = nullptr;
0771 const std::string *TestFilename = nullptr;
0772 StringRef FuncName;
0773 uint64_t FuncHash = 0;
0774 bool Valid = false;
0775
0776 OverlapStats(OverlapStatsLevel L = ProgramLevel) : Level(L) {}
0777
0778 void dump(raw_fd_ostream &OS) const;
0779
0780 void setFuncInfo(StringRef Name, uint64_t Hash) {
0781 FuncName = Name;
0782 FuncHash = Hash;
0783 }
0784
0785 Error accumulateCounts(const std::string &BaseFilename,
0786 const std::string &TestFilename, bool IsCS);
0787 void addOneMismatch(const CountSumOrPercent &MismatchFunc);
0788 void addOneUnique(const CountSumOrPercent &UniqueFunc);
0789
0790 static inline double score(uint64_t Val1, uint64_t Val2, double Sum1,
0791 double Sum2) {
0792 if (Sum1 < 1.0f || Sum2 < 1.0f)
0793 return 0.0f;
0794 return std::min(Val1 / Sum1, Val2 / Sum2);
0795 }
0796 };
0797
0798
0799
0800 struct OverlapFuncFilters {
0801 uint64_t ValueCutoff;
0802 const std::string NameFilter;
0803 };
0804
0805 struct InstrProfValueSiteRecord {
0806
0807 std::vector<InstrProfValueData> ValueData;
0808
0809 InstrProfValueSiteRecord() = default;
0810 InstrProfValueSiteRecord(std::vector<InstrProfValueData> &&VD)
0811 : ValueData(VD) {}
0812
0813
0814 void sortByTargetValues() {
0815 llvm::sort(ValueData,
0816 [](const InstrProfValueData &L, const InstrProfValueData &R) {
0817 return L.Value < R.Value;
0818 });
0819 }
0820
0821 inline void sortByCount();
0822
0823
0824
0825 void merge(InstrProfValueSiteRecord &Input, uint64_t Weight,
0826 function_ref<void(instrprof_error)> Warn);
0827
0828 void scale(uint64_t N, uint64_t D, function_ref<void(instrprof_error)> Warn);
0829
0830
0831 void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
0832 OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
0833 };
0834
0835
0836 struct InstrProfRecord {
0837 std::vector<uint64_t> Counts;
0838 std::vector<uint8_t> BitmapBytes;
0839
0840 InstrProfRecord() = default;
0841 InstrProfRecord(std::vector<uint64_t> Counts) : Counts(std::move(Counts)) {}
0842 InstrProfRecord(std::vector<uint64_t> Counts,
0843 std::vector<uint8_t> BitmapBytes)
0844 : Counts(std::move(Counts)), BitmapBytes(std::move(BitmapBytes)) {}
0845 InstrProfRecord(InstrProfRecord &&) = default;
0846 InstrProfRecord(const InstrProfRecord &RHS)
0847 : Counts(RHS.Counts), BitmapBytes(RHS.BitmapBytes),
0848 ValueData(RHS.ValueData
0849 ? std::make_unique<ValueProfData>(*RHS.ValueData)
0850 : nullptr) {}
0851 InstrProfRecord &operator=(InstrProfRecord &&) = default;
0852 InstrProfRecord &operator=(const InstrProfRecord &RHS) {
0853 Counts = RHS.Counts;
0854 BitmapBytes = RHS.BitmapBytes;
0855 if (!RHS.ValueData) {
0856 ValueData = nullptr;
0857 return *this;
0858 }
0859 if (!ValueData)
0860 ValueData = std::make_unique<ValueProfData>(*RHS.ValueData);
0861 else
0862 *ValueData = *RHS.ValueData;
0863 return *this;
0864 }
0865
0866
0867
0868 inline uint32_t getNumValueKinds() const;
0869
0870 inline uint32_t getNumValueSites(uint32_t ValueKind) const;
0871
0872
0873 inline uint32_t getNumValueData(uint32_t ValueKind) const;
0874
0875
0876 inline ArrayRef<InstrProfValueData> getValueArrayForSite(uint32_t ValueKind,
0877 uint32_t Site) const;
0878
0879
0880 inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites);
0881
0882
0883
0884 void addValueData(uint32_t ValueKind, uint32_t Site,
0885 ArrayRef<InstrProfValueData> VData,
0886 InstrProfSymtab *SymTab);
0887
0888
0889
0890 void merge(InstrProfRecord &Other, uint64_t Weight,
0891 function_ref<void(instrprof_error)> Warn);
0892
0893
0894
0895 void scale(uint64_t N, uint64_t D, function_ref<void(instrprof_error)> Warn);
0896
0897
0898 void sortValueData() {
0899 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
0900 for (auto &SR : getValueSitesForKind(Kind))
0901 SR.sortByCount();
0902 }
0903
0904
0905 void Clear() {
0906 Counts.clear();
0907 clearValueData();
0908 }
0909
0910
0911 void clearValueData() { ValueData = nullptr; }
0912
0913
0914 void accumulateCounts(CountSumOrPercent &Sum) const;
0915
0916
0917 void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
0918 OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
0919
0920
0921 void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
0922 OverlapStats &Overlap,
0923 OverlapStats &FuncLevelOverlap);
0924
0925 enum CountPseudoKind {
0926 NotPseudo = 0,
0927 PseudoHot,
0928 PseudoWarm,
0929 };
0930 enum PseudoCountVal {
0931 HotFunctionVal = -1,
0932 WarmFunctionVal = -2,
0933 };
0934 CountPseudoKind getCountPseudoKind() const {
0935 uint64_t FirstCount = Counts[0];
0936 if (FirstCount == (uint64_t)HotFunctionVal)
0937 return PseudoHot;
0938 if (FirstCount == (uint64_t)WarmFunctionVal)
0939 return PseudoWarm;
0940 return NotPseudo;
0941 }
0942 void setPseudoCount(CountPseudoKind Kind) {
0943 if (Kind == PseudoHot)
0944 Counts[0] = (uint64_t)HotFunctionVal;
0945 else if (Kind == PseudoWarm)
0946 Counts[0] = (uint64_t)WarmFunctionVal;
0947 }
0948
0949 private:
0950 using ValueProfData = std::array<std::vector<InstrProfValueSiteRecord>,
0951 IPVK_Last - IPVK_First + 1>;
0952 std::unique_ptr<ValueProfData> ValueData;
0953
0954 MutableArrayRef<InstrProfValueSiteRecord>
0955 getValueSitesForKind(uint32_t ValueKind) {
0956
0957
0958
0959 auto AR = const_cast<const InstrProfRecord *>(this)->getValueSitesForKind(
0960 ValueKind);
0961 return MutableArrayRef(
0962 const_cast<InstrProfValueSiteRecord *>(AR.data()), AR.size());
0963 }
0964 ArrayRef<InstrProfValueSiteRecord>
0965 getValueSitesForKind(uint32_t ValueKind) const {
0966 if (!ValueData)
0967 return {};
0968 assert(IPVK_First <= ValueKind && ValueKind <= IPVK_Last &&
0969 "Unknown value kind!");
0970 return (*ValueData)[ValueKind - IPVK_First];
0971 }
0972
0973 std::vector<InstrProfValueSiteRecord> &
0974 getOrCreateValueSitesForKind(uint32_t ValueKind) {
0975 if (!ValueData)
0976 ValueData = std::make_unique<ValueProfData>();
0977 assert(IPVK_First <= ValueKind && ValueKind <= IPVK_Last &&
0978 "Unknown value kind!");
0979 return (*ValueData)[ValueKind - IPVK_First];
0980 }
0981
0982
0983 uint64_t remapValue(uint64_t Value, uint32_t ValueKind,
0984 InstrProfSymtab *SymTab);
0985
0986
0987
0988 void mergeValueProfData(uint32_t ValkeKind, InstrProfRecord &Src,
0989 uint64_t Weight,
0990 function_ref<void(instrprof_error)> Warn);
0991
0992
0993 void scaleValueProfData(uint32_t ValueKind, uint64_t N, uint64_t D,
0994 function_ref<void(instrprof_error)> Warn);
0995 };
0996
0997 struct NamedInstrProfRecord : InstrProfRecord {
0998 StringRef Name;
0999 uint64_t Hash;
1000
1001
1002 static const int CS_FLAG_IN_FUNC_HASH = 60;
1003
1004 NamedInstrProfRecord() = default;
1005 NamedInstrProfRecord(StringRef Name, uint64_t Hash,
1006 std::vector<uint64_t> Counts)
1007 : InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {}
1008 NamedInstrProfRecord(StringRef Name, uint64_t Hash,
1009 std::vector<uint64_t> Counts,
1010 std::vector<uint8_t> BitmapBytes)
1011 : InstrProfRecord(std::move(Counts), std::move(BitmapBytes)), Name(Name),
1012 Hash(Hash) {}
1013
1014 static bool hasCSFlagInHash(uint64_t FuncHash) {
1015 return ((FuncHash >> CS_FLAG_IN_FUNC_HASH) & 1);
1016 }
1017 static void setCSFlagInHash(uint64_t &FuncHash) {
1018 FuncHash |= ((uint64_t)1 << CS_FLAG_IN_FUNC_HASH);
1019 }
1020 };
1021
1022 uint32_t InstrProfRecord::getNumValueKinds() const {
1023 uint32_t NumValueKinds = 0;
1024 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
1025 NumValueKinds += !(getValueSitesForKind(Kind).empty());
1026 return NumValueKinds;
1027 }
1028
1029 uint32_t InstrProfRecord::getNumValueData(uint32_t ValueKind) const {
1030 uint32_t N = 0;
1031 for (const auto &SR : getValueSitesForKind(ValueKind))
1032 N += SR.ValueData.size();
1033 return N;
1034 }
1035
1036 uint32_t InstrProfRecord::getNumValueSites(uint32_t ValueKind) const {
1037 return getValueSitesForKind(ValueKind).size();
1038 }
1039
1040 ArrayRef<InstrProfValueData>
1041 InstrProfRecord::getValueArrayForSite(uint32_t ValueKind, uint32_t Site) const {
1042 return getValueSitesForKind(ValueKind)[Site].ValueData;
1043 }
1044
1045 void InstrProfRecord::reserveSites(uint32_t ValueKind, uint32_t NumValueSites) {
1046 if (!NumValueSites)
1047 return;
1048 getOrCreateValueSitesForKind(ValueKind).reserve(NumValueSites);
1049 }
1050
1051
1052 #define INSTR_PROF_VALUE_PROF_DATA
1053 #include "llvm/ProfileData/InstrProfData.inc"
1054
1055 void InstrProfValueSiteRecord::sortByCount() {
1056 llvm::stable_sort(
1057 ValueData, [](const InstrProfValueData &L, const InstrProfValueData &R) {
1058 return L.Count > R.Count;
1059 });
1060
1061 size_t max_s = INSTR_PROF_MAX_NUM_VAL_PER_SITE;
1062 if (ValueData.size() > max_s)
1063 ValueData.resize(max_s);
1064 }
1065
1066 namespace IndexedInstrProf {
1067
1068 enum class HashT : uint32_t {
1069 MD5,
1070 Last = MD5
1071 };
1072
1073 inline uint64_t ComputeHash(HashT Type, StringRef K) {
1074 switch (Type) {
1075 case HashT::MD5:
1076 return MD5Hash(K);
1077 }
1078 llvm_unreachable("Unhandled hash type");
1079 }
1080
1081 const uint64_t Magic = 0x8169666f72706cff;
1082
1083 enum ProfVersion {
1084
1085
1086
1087
1088 Version1 = 1,
1089
1090
1091
1092
1093 Version2 = 2,
1094
1095
1096 Version3 = 3,
1097
1098
1099 Version4 = 4,
1100
1101 Version5 = 5,
1102
1103
1104 Version6 = 6,
1105
1106 Version7 = 7,
1107
1108 Version8 = 8,
1109
1110 Version9 = 9,
1111
1112 Version10 = 10,
1113
1114 Version11 = 11,
1115
1116 Version12 = 12,
1117
1118 CurrentVersion = INSTR_PROF_INDEX_VERSION
1119 };
1120 const uint64_t Version = ProfVersion::CurrentVersion;
1121
1122 const HashT HashType = HashT::MD5;
1123
1124 inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); }
1125
1126
1127
1128
1129 struct Header {
1130 uint64_t Magic = IndexedInstrProf::Magic;
1131
1132
1133
1134 uint64_t Version = 0;
1135 uint64_t Unused = 0;
1136 uint64_t HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
1137
1138
1139
1140 uint64_t HashOffset = 0;
1141 uint64_t MemProfOffset = 0;
1142 uint64_t BinaryIdOffset = 0;
1143 uint64_t TemporalProfTracesOffset = 0;
1144 uint64_t VTableNamesOffset = 0;
1145
1146
1147
1148
1149
1150
1151 static Expected<Header> readFromBuffer(const unsigned char *Buffer);
1152
1153
1154
1155 size_t size() const;
1156
1157
1158
1159 uint64_t getIndexedProfileVersion() const;
1160 };
1161
1162
1163
1164
1165 struct Summary {
1166 struct Entry {
1167 uint64_t Cutoff;
1168 uint64_t
1169 MinBlockCount;
1170 uint64_t NumBlocks;
1171 };
1172
1173
1174
1175 enum SummaryFieldKind {
1176
1177 TotalNumFunctions = 0,
1178
1179 TotalNumBlocks = 1,
1180
1181
1182
1183 MaxFunctionCount = 2,
1184
1185 MaxBlockCount = 3,
1186
1187 MaxInternalBlockCount = 4,
1188
1189 TotalBlockCount = 5,
1190 NumKinds = TotalBlockCount + 1
1191 };
1192
1193
1194 uint64_t NumSummaryFields;
1195
1196 uint64_t NumCutoffEntries;
1197
1198 Summary() = delete;
1199 Summary(uint32_t Size) { memset(this, 0, Size); }
1200
1201 void operator delete(void *ptr) { ::operator delete(ptr); }
1202
1203 static uint32_t getSize(uint32_t NumSumFields, uint32_t NumCutoffEntries) {
1204 return sizeof(Summary) + NumCutoffEntries * sizeof(Entry) +
1205 NumSumFields * sizeof(uint64_t);
1206 }
1207
1208 const uint64_t *getSummaryDataBase() const {
1209 return reinterpret_cast<const uint64_t *>(this + 1);
1210 }
1211
1212 uint64_t *getSummaryDataBase() {
1213 return reinterpret_cast<uint64_t *>(this + 1);
1214 }
1215
1216 const Entry *getCutoffEntryBase() const {
1217 return reinterpret_cast<const Entry *>(
1218 &getSummaryDataBase()[NumSummaryFields]);
1219 }
1220
1221 Entry *getCutoffEntryBase() {
1222 return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]);
1223 }
1224
1225 uint64_t get(SummaryFieldKind K) const {
1226 return getSummaryDataBase()[K];
1227 }
1228
1229 void set(SummaryFieldKind K, uint64_t V) {
1230 getSummaryDataBase()[K] = V;
1231 }
1232
1233 const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; }
1234
1235 void setEntry(uint32_t I, const ProfileSummaryEntry &E) {
1236 Entry &ER = getCutoffEntryBase()[I];
1237 ER.Cutoff = E.Cutoff;
1238 ER.MinBlockCount = E.MinCount;
1239 ER.NumBlocks = E.NumCounts;
1240 }
1241 };
1242
1243 inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) {
1244 return std::unique_ptr<Summary>(new (::operator new(TotalSize))
1245 Summary(TotalSize));
1246 }
1247
1248 }
1249
1250 namespace RawInstrProf {
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266 const uint64_t Version = INSTR_PROF_RAW_VERSION;
1267
1268 template <class IntPtrT> inline uint64_t getMagic();
1269 template <> inline uint64_t getMagic<uint64_t>() {
1270 return INSTR_PROF_RAW_MAGIC_64;
1271 }
1272
1273 template <> inline uint64_t getMagic<uint32_t>() {
1274 return INSTR_PROF_RAW_MAGIC_32;
1275 }
1276
1277
1278
1279
1280
1281
1282 template <class IntPtrT> struct alignas(8) ProfileData {
1283 #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name;
1284 #include "llvm/ProfileData/InstrProfData.inc"
1285 };
1286
1287 template <class IntPtrT> struct alignas(8) VTableProfileData {
1288 #define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Init) Type Name;
1289 #include "llvm/ProfileData/InstrProfData.inc"
1290 };
1291
1292
1293
1294
1295
1296 struct Header {
1297 #define INSTR_PROF_RAW_HEADER(Type, Name, Init) const Type Name;
1298 #include "llvm/ProfileData/InstrProfData.inc"
1299 };
1300
1301 }
1302
1303
1304 void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
1305
1306
1307
1308 extern cl::opt<bool> DoInstrProfNameCompression;
1309
1310 }
1311 #endif