File indexing completed on 2026-05-10 08:44:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_IR_MODULESUMMARYINDEX_H
0016 #define LLVM_IR_MODULESUMMARYINDEX_H
0017
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/ADT/DenseMap.h"
0020 #include "llvm/ADT/STLExtras.h"
0021 #include "llvm/ADT/SmallString.h"
0022 #include "llvm/ADT/SmallVector.h"
0023 #include "llvm/ADT/StringExtras.h"
0024 #include "llvm/ADT/StringMap.h"
0025 #include "llvm/ADT/StringRef.h"
0026 #include "llvm/IR/ConstantRange.h"
0027 #include "llvm/IR/GlobalValue.h"
0028 #include "llvm/IR/Module.h"
0029 #include "llvm/Support/Allocator.h"
0030 #include "llvm/Support/MathExtras.h"
0031 #include "llvm/Support/ScaledNumber.h"
0032 #include "llvm/Support/StringSaver.h"
0033 #include "llvm/Support/raw_ostream.h"
0034 #include <algorithm>
0035 #include <array>
0036 #include <cassert>
0037 #include <cstddef>
0038 #include <cstdint>
0039 #include <map>
0040 #include <memory>
0041 #include <optional>
0042 #include <set>
0043 #include <string>
0044 #include <unordered_set>
0045 #include <utility>
0046 #include <vector>
0047
0048 namespace llvm {
0049
0050 template <class GraphType> struct GraphTraits;
0051
0052 namespace yaml {
0053
0054 template <typename T> struct MappingTraits;
0055
0056 }
0057
0058
0059 struct CalleeInfo {
0060 enum class HotnessType : uint8_t {
0061 Unknown = 0,
0062 Cold = 1,
0063 None = 2,
0064 Hot = 3,
0065 Critical = 4
0066 };
0067
0068
0069
0070 uint32_t Hotness : 3;
0071
0072
0073 bool HasTailCall : 1;
0074
0075
0076
0077 static constexpr unsigned RelBlockFreqBits = 28;
0078 uint32_t RelBlockFreq : RelBlockFreqBits;
0079 static constexpr int32_t ScaleShift = 8;
0080 static constexpr uint64_t MaxRelBlockFreq = (1 << RelBlockFreqBits) - 1;
0081
0082 CalleeInfo()
0083 : Hotness(static_cast<uint32_t>(HotnessType::Unknown)),
0084 HasTailCall(false), RelBlockFreq(0) {}
0085 explicit CalleeInfo(HotnessType Hotness, bool HasTC, uint64_t RelBF)
0086 : Hotness(static_cast<uint32_t>(Hotness)), HasTailCall(HasTC),
0087 RelBlockFreq(RelBF) {}
0088
0089 void updateHotness(const HotnessType OtherHotness) {
0090 Hotness = std::max(Hotness, static_cast<uint32_t>(OtherHotness));
0091 }
0092
0093 bool hasTailCall() const { return HasTailCall; }
0094
0095 void setHasTailCall(const bool HasTC) { HasTailCall = HasTC; }
0096
0097 HotnessType getHotness() const { return HotnessType(Hotness); }
0098
0099
0100
0101
0102
0103
0104 void updateRelBlockFreq(uint64_t BlockFreq, uint64_t EntryFreq) {
0105 if (EntryFreq == 0)
0106 return;
0107 using Scaled64 = ScaledNumber<uint64_t>;
0108 Scaled64 Temp(BlockFreq, ScaleShift);
0109 Temp /= Scaled64::get(EntryFreq);
0110
0111 uint64_t Sum =
0112 SaturatingAdd<uint64_t>(Temp.toInt<uint64_t>(), RelBlockFreq);
0113 Sum = std::min(Sum, uint64_t(MaxRelBlockFreq));
0114 RelBlockFreq = static_cast<uint32_t>(Sum);
0115 }
0116 };
0117
0118 inline const char *getHotnessName(CalleeInfo::HotnessType HT) {
0119 switch (HT) {
0120 case CalleeInfo::HotnessType::Unknown:
0121 return "unknown";
0122 case CalleeInfo::HotnessType::Cold:
0123 return "cold";
0124 case CalleeInfo::HotnessType::None:
0125 return "none";
0126 case CalleeInfo::HotnessType::Hot:
0127 return "hot";
0128 case CalleeInfo::HotnessType::Critical:
0129 return "critical";
0130 }
0131 llvm_unreachable("invalid hotness");
0132 }
0133
0134 class GlobalValueSummary;
0135
0136 using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
0137
0138 struct alignas(8) GlobalValueSummaryInfo {
0139 union NameOrGV {
0140 NameOrGV(bool HaveGVs) {
0141 if (HaveGVs)
0142 GV = nullptr;
0143 else
0144 Name = "";
0145 }
0146
0147
0148
0149
0150
0151 const GlobalValue *GV;
0152
0153
0154
0155
0156
0157
0158 StringRef Name;
0159 } U;
0160
0161 inline GlobalValueSummaryInfo(bool HaveGVs);
0162
0163
0164
0165
0166 GlobalValueSummaryList SummaryList;
0167 };
0168
0169
0170
0171
0172
0173
0174
0175 using GlobalValueSummaryMapTy =
0176 std::map<GlobalValue::GUID, GlobalValueSummaryInfo>;
0177
0178
0179
0180 struct ValueInfo {
0181 enum Flags { HaveGV = 1, ReadOnly = 2, WriteOnly = 4 };
0182 PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 3, int>
0183 RefAndFlags;
0184
0185 ValueInfo() = default;
0186 ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) {
0187 RefAndFlags.setPointer(R);
0188 RefAndFlags.setInt(HaveGVs);
0189 }
0190
0191 explicit operator bool() const { return getRef(); }
0192
0193 GlobalValue::GUID getGUID() const { return getRef()->first; }
0194 const GlobalValue *getValue() const {
0195 assert(haveGVs());
0196 return getRef()->second.U.GV;
0197 }
0198
0199 ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
0200 return getRef()->second.SummaryList;
0201 }
0202
0203
0204
0205 bool hasName() const { return !haveGVs() || getValue(); }
0206
0207 StringRef name() const {
0208 assert(!haveGVs() || getRef()->second.U.GV);
0209 return haveGVs() ? getRef()->second.U.GV->getName()
0210 : getRef()->second.U.Name;
0211 }
0212
0213 bool haveGVs() const { return RefAndFlags.getInt() & HaveGV; }
0214 bool isReadOnly() const {
0215 assert(isValidAccessSpecifier());
0216 return RefAndFlags.getInt() & ReadOnly;
0217 }
0218 bool isWriteOnly() const {
0219 assert(isValidAccessSpecifier());
0220 return RefAndFlags.getInt() & WriteOnly;
0221 }
0222 unsigned getAccessSpecifier() const {
0223 assert(isValidAccessSpecifier());
0224 return RefAndFlags.getInt() & (ReadOnly | WriteOnly);
0225 }
0226 bool isValidAccessSpecifier() const {
0227 unsigned BadAccessMask = ReadOnly | WriteOnly;
0228 return (RefAndFlags.getInt() & BadAccessMask) != BadAccessMask;
0229 }
0230 void setReadOnly() {
0231
0232
0233 assert(getAccessSpecifier() == 0);
0234 RefAndFlags.setInt(RefAndFlags.getInt() | ReadOnly);
0235 }
0236 void setWriteOnly() {
0237 assert(getAccessSpecifier() == 0);
0238 RefAndFlags.setInt(RefAndFlags.getInt() | WriteOnly);
0239 }
0240
0241 const GlobalValueSummaryMapTy::value_type *getRef() const {
0242 return RefAndFlags.getPointer();
0243 }
0244
0245
0246
0247
0248 GlobalValue::VisibilityTypes getELFVisibility() const;
0249
0250
0251
0252 bool isDSOLocal(bool WithDSOLocalPropagation = false) const;
0253
0254
0255 bool canAutoHide() const;
0256 };
0257
0258 inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) {
0259 OS << VI.getGUID();
0260 if (!VI.name().empty())
0261 OS << " (" << VI.name() << ")";
0262 return OS;
0263 }
0264
0265 inline bool operator==(const ValueInfo &A, const ValueInfo &B) {
0266 assert(A.getRef() && B.getRef() &&
0267 "Need ValueInfo with non-null Ref for comparison");
0268 return A.getRef() == B.getRef();
0269 }
0270
0271 inline bool operator!=(const ValueInfo &A, const ValueInfo &B) {
0272 assert(A.getRef() && B.getRef() &&
0273 "Need ValueInfo with non-null Ref for comparison");
0274 return A.getRef() != B.getRef();
0275 }
0276
0277 inline bool operator<(const ValueInfo &A, const ValueInfo &B) {
0278 assert(A.getRef() && B.getRef() &&
0279 "Need ValueInfo with non-null Ref to compare GUIDs");
0280 return A.getGUID() < B.getGUID();
0281 }
0282
0283 template <> struct DenseMapInfo<ValueInfo> {
0284 static inline ValueInfo getEmptyKey() {
0285 return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
0286 }
0287
0288 static inline ValueInfo getTombstoneKey() {
0289 return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
0290 }
0291
0292 static inline bool isSpecialKey(ValueInfo V) {
0293 return V == getTombstoneKey() || V == getEmptyKey();
0294 }
0295
0296 static bool isEqual(ValueInfo L, ValueInfo R) {
0297
0298
0299 assert(isSpecialKey(L) || isSpecialKey(R) || (L.haveGVs() == R.haveGVs()));
0300 return L.getRef() == R.getRef();
0301 }
0302 static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
0303 };
0304
0305
0306
0307
0308 struct ContextTotalSize {
0309 uint64_t FullStackId;
0310 uint64_t TotalSize;
0311 };
0312
0313
0314 struct CallsiteInfo {
0315
0316 ValueInfo Callee;
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326 SmallVector<unsigned> Clones{0};
0327
0328
0329
0330
0331
0332 SmallVector<unsigned> StackIdIndices;
0333
0334 CallsiteInfo(ValueInfo Callee, SmallVector<unsigned> StackIdIndices)
0335 : Callee(Callee), StackIdIndices(std::move(StackIdIndices)) {}
0336 CallsiteInfo(ValueInfo Callee, SmallVector<unsigned> Clones,
0337 SmallVector<unsigned> StackIdIndices)
0338 : Callee(Callee), Clones(std::move(Clones)),
0339 StackIdIndices(std::move(StackIdIndices)) {}
0340 };
0341
0342 inline raw_ostream &operator<<(raw_ostream &OS, const CallsiteInfo &SNI) {
0343 OS << "Callee: " << SNI.Callee;
0344 bool First = true;
0345 OS << " Clones: ";
0346 for (auto V : SNI.Clones) {
0347 if (!First)
0348 OS << ", ";
0349 First = false;
0350 OS << V;
0351 }
0352 First = true;
0353 OS << " StackIds: ";
0354 for (auto Id : SNI.StackIdIndices) {
0355 if (!First)
0356 OS << ", ";
0357 First = false;
0358 OS << Id;
0359 }
0360 return OS;
0361 }
0362
0363
0364
0365
0366
0367
0368 enum class AllocationType : uint8_t {
0369 None = 0,
0370 NotCold = 1,
0371 Cold = 2,
0372 Hot = 4,
0373 All = 7
0374 };
0375
0376
0377 struct MIBInfo {
0378
0379 AllocationType AllocType;
0380
0381
0382
0383
0384
0385 SmallVector<unsigned> StackIdIndices;
0386
0387 MIBInfo(AllocationType AllocType, SmallVector<unsigned> StackIdIndices)
0388 : AllocType(AllocType), StackIdIndices(std::move(StackIdIndices)) {}
0389 };
0390
0391 inline raw_ostream &operator<<(raw_ostream &OS, const MIBInfo &MIB) {
0392 OS << "AllocType " << (unsigned)MIB.AllocType;
0393 bool First = true;
0394 OS << " StackIds: ";
0395 for (auto Id : MIB.StackIdIndices) {
0396 if (!First)
0397 OS << ", ";
0398 First = false;
0399 OS << Id;
0400 }
0401 return OS;
0402 }
0403
0404
0405 struct AllocInfo {
0406
0407
0408
0409
0410
0411
0412
0413
0414 SmallVector<uint8_t> Versions;
0415
0416
0417 std::vector<MIBInfo> MIBs;
0418
0419
0420
0421
0422
0423
0424
0425 std::vector<std::vector<ContextTotalSize>> ContextSizeInfos;
0426
0427 AllocInfo(std::vector<MIBInfo> MIBs) : MIBs(std::move(MIBs)) {
0428 Versions.push_back(0);
0429 }
0430 AllocInfo(SmallVector<uint8_t> Versions, std::vector<MIBInfo> MIBs)
0431 : Versions(std::move(Versions)), MIBs(std::move(MIBs)) {}
0432 };
0433
0434 inline raw_ostream &operator<<(raw_ostream &OS, const AllocInfo &AE) {
0435 bool First = true;
0436 OS << "Versions: ";
0437 for (auto V : AE.Versions) {
0438 if (!First)
0439 OS << ", ";
0440 First = false;
0441 OS << (unsigned)V;
0442 }
0443 OS << " MIB:\n";
0444 for (auto &M : AE.MIBs) {
0445 OS << "\t\t" << M << "\n";
0446 }
0447 if (!AE.ContextSizeInfos.empty()) {
0448 OS << "\tContextSizeInfo per MIB:\n";
0449 for (auto Infos : AE.ContextSizeInfos) {
0450 OS << "\t\t";
0451 bool FirstInfo = true;
0452 for (auto [FullStackId, TotalSize] : Infos) {
0453 if (!FirstInfo)
0454 OS << ", ";
0455 FirstInfo = false;
0456 OS << "{ " << FullStackId << ", " << TotalSize << " }";
0457 }
0458 OS << "\n";
0459 }
0460 }
0461 return OS;
0462 }
0463
0464
0465
0466 class GlobalValueSummary {
0467 public:
0468
0469 enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind };
0470
0471 enum ImportKind : unsigned {
0472
0473
0474 Definition = 0,
0475
0476
0477
0478
0479
0480 Declaration = 1,
0481 };
0482
0483
0484 struct GVFlags {
0485
0486
0487
0488
0489
0490
0491
0492 unsigned Linkage : 4;
0493
0494
0495 unsigned Visibility : 2;
0496
0497
0498
0499 unsigned NotEligibleToImport : 1;
0500
0501
0502
0503
0504
0505
0506 unsigned Live : 1;
0507
0508
0509
0510 unsigned DSOLocal : 1;
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521 unsigned CanAutoHide : 1;
0522
0523
0524
0525 unsigned ImportType : 1;
0526
0527
0528 explicit GVFlags(GlobalValue::LinkageTypes Linkage,
0529 GlobalValue::VisibilityTypes Visibility,
0530 bool NotEligibleToImport, bool Live, bool IsLocal,
0531 bool CanAutoHide, ImportKind ImportType)
0532 : Linkage(Linkage), Visibility(Visibility),
0533 NotEligibleToImport(NotEligibleToImport), Live(Live),
0534 DSOLocal(IsLocal), CanAutoHide(CanAutoHide),
0535 ImportType(static_cast<unsigned>(ImportType)) {}
0536 };
0537
0538 private:
0539
0540 SummaryKind Kind;
0541
0542 GVFlags Flags;
0543
0544
0545
0546
0547 GlobalValue::GUID OriginalName = 0;
0548
0549
0550
0551
0552
0553
0554
0555
0556 StringRef ModulePath;
0557
0558
0559
0560
0561
0562
0563
0564 SmallVector<ValueInfo, 0> RefEdgeList;
0565
0566 protected:
0567 GlobalValueSummary(SummaryKind K, GVFlags Flags,
0568 SmallVectorImpl<ValueInfo> &&Refs)
0569 : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {
0570 assert((K != AliasKind || Refs.empty()) &&
0571 "Expect no references for AliasSummary");
0572 }
0573
0574 public:
0575 virtual ~GlobalValueSummary() = default;
0576
0577
0578
0579 GlobalValue::GUID getOriginalName() const { return OriginalName; }
0580
0581
0582 void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; }
0583
0584
0585 SummaryKind getSummaryKind() const { return Kind; }
0586
0587
0588
0589 void setModulePath(StringRef ModPath) { ModulePath = ModPath; }
0590
0591
0592 StringRef modulePath() const { return ModulePath; }
0593
0594
0595 GVFlags flags() const { return Flags; }
0596
0597
0598 GlobalValue::LinkageTypes linkage() const {
0599 return static_cast<GlobalValue::LinkageTypes>(Flags.Linkage);
0600 }
0601
0602
0603
0604 void setLinkage(GlobalValue::LinkageTypes Linkage) {
0605 Flags.Linkage = Linkage;
0606 }
0607
0608
0609 bool notEligibleToImport() const { return Flags.NotEligibleToImport; }
0610
0611 bool isLive() const { return Flags.Live; }
0612
0613 void setLive(bool Live) { Flags.Live = Live; }
0614
0615 void setDSOLocal(bool Local) { Flags.DSOLocal = Local; }
0616
0617 bool isDSOLocal() const { return Flags.DSOLocal; }
0618
0619 void setCanAutoHide(bool CanAutoHide) { Flags.CanAutoHide = CanAutoHide; }
0620
0621 bool canAutoHide() const { return Flags.CanAutoHide; }
0622
0623 bool shouldImportAsDecl() const {
0624 return Flags.ImportType == GlobalValueSummary::ImportKind::Declaration;
0625 }
0626
0627 void setImportKind(ImportKind IK) { Flags.ImportType = IK; }
0628
0629 GlobalValueSummary::ImportKind importType() const {
0630 return static_cast<ImportKind>(Flags.ImportType);
0631 }
0632
0633 GlobalValue::VisibilityTypes getVisibility() const {
0634 return (GlobalValue::VisibilityTypes)Flags.Visibility;
0635 }
0636 void setVisibility(GlobalValue::VisibilityTypes Vis) {
0637 Flags.Visibility = (unsigned)Vis;
0638 }
0639
0640
0641 void setNotEligibleToImport() { Flags.NotEligibleToImport = true; }
0642
0643
0644 ArrayRef<ValueInfo> refs() const { return RefEdgeList; }
0645
0646
0647
0648 GlobalValueSummary *getBaseObject();
0649 const GlobalValueSummary *getBaseObject() const;
0650
0651 friend class ModuleSummaryIndex;
0652 };
0653
0654 GlobalValueSummaryInfo::GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {}
0655
0656
0657 class AliasSummary : public GlobalValueSummary {
0658 ValueInfo AliaseeValueInfo;
0659
0660
0661
0662
0663
0664 GlobalValueSummary *AliaseeSummary = nullptr;
0665
0666 public:
0667 AliasSummary(GVFlags Flags)
0668 : GlobalValueSummary(AliasKind, Flags, SmallVector<ValueInfo, 0>{}) {}
0669
0670
0671 static bool classof(const GlobalValueSummary *GVS) {
0672 return GVS->getSummaryKind() == AliasKind;
0673 }
0674
0675 void setAliasee(ValueInfo &AliaseeVI, GlobalValueSummary *Aliasee) {
0676 AliaseeValueInfo = AliaseeVI;
0677 AliaseeSummary = Aliasee;
0678 }
0679
0680 bool hasAliasee() const {
0681 assert(!!AliaseeSummary == (AliaseeValueInfo &&
0682 !AliaseeValueInfo.getSummaryList().empty()) &&
0683 "Expect to have both aliasee summary and summary list or neither");
0684 return !!AliaseeSummary;
0685 }
0686
0687 const GlobalValueSummary &getAliasee() const {
0688 assert(AliaseeSummary && "Unexpected missing aliasee summary");
0689 return *AliaseeSummary;
0690 }
0691
0692 GlobalValueSummary &getAliasee() {
0693 return const_cast<GlobalValueSummary &>(
0694 static_cast<const AliasSummary *>(this)->getAliasee());
0695 }
0696 ValueInfo getAliaseeVI() const {
0697 assert(AliaseeValueInfo && "Unexpected missing aliasee");
0698 return AliaseeValueInfo;
0699 }
0700 GlobalValue::GUID getAliaseeGUID() const {
0701 assert(AliaseeValueInfo && "Unexpected missing aliasee");
0702 return AliaseeValueInfo.getGUID();
0703 }
0704 };
0705
0706 const inline GlobalValueSummary *GlobalValueSummary::getBaseObject() const {
0707 if (auto *AS = dyn_cast<AliasSummary>(this))
0708 return &AS->getAliasee();
0709 return this;
0710 }
0711
0712 inline GlobalValueSummary *GlobalValueSummary::getBaseObject() {
0713 if (auto *AS = dyn_cast<AliasSummary>(this))
0714 return &AS->getAliasee();
0715 return this;
0716 }
0717
0718
0719
0720 class FunctionSummary : public GlobalValueSummary {
0721 public:
0722
0723 using EdgeTy = std::pair<ValueInfo, CalleeInfo>;
0724
0725
0726 enum ForceSummaryHotnessType : unsigned {
0727 FSHT_None,
0728 FSHT_AllNonCritical,
0729 FSHT_All
0730 };
0731
0732
0733
0734
0735
0736 struct VFuncId {
0737 GlobalValue::GUID GUID;
0738 uint64_t Offset;
0739 };
0740
0741
0742
0743
0744 struct ConstVCall {
0745 VFuncId VFunc;
0746 std::vector<uint64_t> Args;
0747 };
0748
0749
0750
0751 struct TypeIdInfo {
0752
0753
0754
0755 std::vector<GlobalValue::GUID> TypeTests;
0756
0757
0758
0759
0760 std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
0761
0762
0763
0764
0765 std::vector<ConstVCall> TypeTestAssumeConstVCalls,
0766 TypeCheckedLoadConstVCalls;
0767 };
0768
0769
0770 struct FFlags {
0771
0772
0773 unsigned ReadNone : 1;
0774 unsigned ReadOnly : 1;
0775 unsigned NoRecurse : 1;
0776 unsigned ReturnDoesNotAlias : 1;
0777
0778
0779 unsigned NoInline : 1;
0780
0781 unsigned AlwaysInline : 1;
0782
0783
0784 unsigned NoUnwind : 1;
0785
0786 unsigned MayThrow : 1;
0787
0788
0789 unsigned HasUnknownCall : 1;
0790
0791
0792
0793
0794
0795
0796 unsigned MustBeUnreachable : 1;
0797
0798 FFlags &operator&=(const FFlags &RHS) {
0799 this->ReadNone &= RHS.ReadNone;
0800 this->ReadOnly &= RHS.ReadOnly;
0801 this->NoRecurse &= RHS.NoRecurse;
0802 this->ReturnDoesNotAlias &= RHS.ReturnDoesNotAlias;
0803 this->NoInline &= RHS.NoInline;
0804 this->AlwaysInline &= RHS.AlwaysInline;
0805 this->NoUnwind &= RHS.NoUnwind;
0806 this->MayThrow &= RHS.MayThrow;
0807 this->HasUnknownCall &= RHS.HasUnknownCall;
0808 this->MustBeUnreachable &= RHS.MustBeUnreachable;
0809 return *this;
0810 }
0811
0812 bool anyFlagSet() {
0813 return this->ReadNone | this->ReadOnly | this->NoRecurse |
0814 this->ReturnDoesNotAlias | this->NoInline | this->AlwaysInline |
0815 this->NoUnwind | this->MayThrow | this->HasUnknownCall |
0816 this->MustBeUnreachable;
0817 }
0818
0819 operator std::string() {
0820 std::string Output;
0821 raw_string_ostream OS(Output);
0822 OS << "funcFlags: (";
0823 OS << "readNone: " << this->ReadNone;
0824 OS << ", readOnly: " << this->ReadOnly;
0825 OS << ", noRecurse: " << this->NoRecurse;
0826 OS << ", returnDoesNotAlias: " << this->ReturnDoesNotAlias;
0827 OS << ", noInline: " << this->NoInline;
0828 OS << ", alwaysInline: " << this->AlwaysInline;
0829 OS << ", noUnwind: " << this->NoUnwind;
0830 OS << ", mayThrow: " << this->MayThrow;
0831 OS << ", hasUnknownCall: " << this->HasUnknownCall;
0832 OS << ", mustBeUnreachable: " << this->MustBeUnreachable;
0833 OS << ")";
0834 return Output;
0835 }
0836 };
0837
0838
0839 struct ParamAccess {
0840 static constexpr uint32_t RangeWidth = 64;
0841
0842
0843
0844
0845 struct Call {
0846 uint64_t ParamNo = 0;
0847 ValueInfo Callee;
0848 ConstantRange Offsets{RangeWidth, true};
0849
0850 Call() = default;
0851 Call(uint64_t ParamNo, ValueInfo Callee, const ConstantRange &Offsets)
0852 : ParamNo(ParamNo), Callee(Callee), Offsets(Offsets) {}
0853 };
0854
0855 uint64_t ParamNo = 0;
0856
0857
0858
0859
0860 ConstantRange Use{RangeWidth, true};
0861
0862
0863
0864
0865 std::vector<Call> Calls;
0866
0867 ParamAccess() = default;
0868 ParamAccess(uint64_t ParamNo, const ConstantRange &Use)
0869 : ParamNo(ParamNo), Use(Use) {}
0870 };
0871
0872
0873
0874 static FunctionSummary
0875 makeDummyFunctionSummary(SmallVectorImpl<FunctionSummary::EdgeTy> &&Edges) {
0876 return FunctionSummary(
0877 FunctionSummary::GVFlags(
0878 GlobalValue::LinkageTypes::AvailableExternallyLinkage,
0879 GlobalValue::DefaultVisibility,
0880 true, true, false,
0881 false, GlobalValueSummary::ImportKind::Definition),
0882 0, FunctionSummary::FFlags{}, SmallVector<ValueInfo, 0>(),
0883 std::move(Edges), std::vector<GlobalValue::GUID>(),
0884 std::vector<FunctionSummary::VFuncId>(),
0885 std::vector<FunctionSummary::VFuncId>(),
0886 std::vector<FunctionSummary::ConstVCall>(),
0887 std::vector<FunctionSummary::ConstVCall>(),
0888 std::vector<FunctionSummary::ParamAccess>(),
0889 std::vector<CallsiteInfo>(), std::vector<AllocInfo>());
0890 }
0891
0892
0893 static FunctionSummary ExternalNode;
0894
0895 private:
0896
0897
0898 unsigned InstCount;
0899
0900
0901 FFlags FunFlags;
0902
0903
0904
0905
0906 SmallVector<EdgeTy, 0> CallGraphEdgeList;
0907
0908 std::unique_ptr<TypeIdInfo> TIdInfo;
0909
0910
0911 using ParamAccessesTy = std::vector<ParamAccess>;
0912 std::unique_ptr<ParamAccessesTy> ParamAccesses;
0913
0914
0915
0916
0917
0918
0919
0920 using CallsitesTy = std::vector<CallsiteInfo>;
0921 std::unique_ptr<CallsitesTy> Callsites;
0922
0923
0924
0925
0926
0927
0928
0929
0930 using AllocsTy = std::vector<AllocInfo>;
0931 std::unique_ptr<AllocsTy> Allocs;
0932
0933 public:
0934 FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags,
0935 SmallVectorImpl<ValueInfo> &&Refs,
0936 SmallVectorImpl<EdgeTy> &&CGEdges,
0937 std::vector<GlobalValue::GUID> TypeTests,
0938 std::vector<VFuncId> TypeTestAssumeVCalls,
0939 std::vector<VFuncId> TypeCheckedLoadVCalls,
0940 std::vector<ConstVCall> TypeTestAssumeConstVCalls,
0941 std::vector<ConstVCall> TypeCheckedLoadConstVCalls,
0942 std::vector<ParamAccess> Params, CallsitesTy CallsiteList,
0943 AllocsTy AllocList)
0944 : GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
0945 InstCount(NumInsts), FunFlags(FunFlags),
0946 CallGraphEdgeList(std::move(CGEdges)) {
0947 if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
0948 !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
0949 !TypeCheckedLoadConstVCalls.empty())
0950 TIdInfo = std::make_unique<TypeIdInfo>(
0951 TypeIdInfo{std::move(TypeTests), std::move(TypeTestAssumeVCalls),
0952 std::move(TypeCheckedLoadVCalls),
0953 std::move(TypeTestAssumeConstVCalls),
0954 std::move(TypeCheckedLoadConstVCalls)});
0955 if (!Params.empty())
0956 ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(Params));
0957 if (!CallsiteList.empty())
0958 Callsites = std::make_unique<CallsitesTy>(std::move(CallsiteList));
0959 if (!AllocList.empty())
0960 Allocs = std::make_unique<AllocsTy>(std::move(AllocList));
0961 }
0962
0963 std::pair<unsigned, unsigned> specialRefCounts() const;
0964
0965
0966 static bool classof(const GlobalValueSummary *GVS) {
0967 return GVS->getSummaryKind() == FunctionKind;
0968 }
0969
0970
0971 FFlags fflags() const { return FunFlags; }
0972
0973 void setNoRecurse() { FunFlags.NoRecurse = true; }
0974
0975 void setNoUnwind() { FunFlags.NoUnwind = true; }
0976
0977
0978 unsigned instCount() const { return InstCount; }
0979
0980
0981 ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
0982
0983 SmallVector<EdgeTy, 0> &mutableCalls() { return CallGraphEdgeList; }
0984
0985 void addCall(EdgeTy E) { CallGraphEdgeList.push_back(E); }
0986
0987
0988
0989
0990 ArrayRef<GlobalValue::GUID> type_tests() const {
0991 if (TIdInfo)
0992 return TIdInfo->TypeTests;
0993 return {};
0994 }
0995
0996
0997
0998
0999 ArrayRef<VFuncId> type_test_assume_vcalls() const {
1000 if (TIdInfo)
1001 return TIdInfo->TypeTestAssumeVCalls;
1002 return {};
1003 }
1004
1005
1006
1007
1008 ArrayRef<VFuncId> type_checked_load_vcalls() const {
1009 if (TIdInfo)
1010 return TIdInfo->TypeCheckedLoadVCalls;
1011 return {};
1012 }
1013
1014
1015
1016
1017 ArrayRef<ConstVCall> type_test_assume_const_vcalls() const {
1018 if (TIdInfo)
1019 return TIdInfo->TypeTestAssumeConstVCalls;
1020 return {};
1021 }
1022
1023
1024
1025 ArrayRef<ConstVCall> type_checked_load_const_vcalls() const {
1026 if (TIdInfo)
1027 return TIdInfo->TypeCheckedLoadConstVCalls;
1028 return {};
1029 }
1030
1031
1032 ArrayRef<ParamAccess> paramAccesses() const {
1033 if (ParamAccesses)
1034 return *ParamAccesses;
1035 return {};
1036 }
1037
1038
1039 void setParamAccesses(std::vector<ParamAccess> NewParams) {
1040 if (NewParams.empty())
1041 ParamAccesses.reset();
1042 else if (ParamAccesses)
1043 *ParamAccesses = std::move(NewParams);
1044 else
1045 ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(NewParams));
1046 }
1047
1048
1049
1050 void addTypeTest(GlobalValue::GUID Guid) {
1051 if (!TIdInfo)
1052 TIdInfo = std::make_unique<TypeIdInfo>();
1053 TIdInfo->TypeTests.push_back(Guid);
1054 }
1055
1056 const TypeIdInfo *getTypeIdInfo() const { return TIdInfo.get(); };
1057
1058 ArrayRef<CallsiteInfo> callsites() const {
1059 if (Callsites)
1060 return *Callsites;
1061 return {};
1062 }
1063
1064 CallsitesTy &mutableCallsites() {
1065 assert(Callsites);
1066 return *Callsites;
1067 }
1068
1069 void addCallsite(CallsiteInfo &Callsite) {
1070 if (!Callsites)
1071 Callsites = std::make_unique<CallsitesTy>();
1072 Callsites->push_back(Callsite);
1073 }
1074
1075 ArrayRef<AllocInfo> allocs() const {
1076 if (Allocs)
1077 return *Allocs;
1078 return {};
1079 }
1080
1081 AllocsTy &mutableAllocs() {
1082 assert(Allocs);
1083 return *Allocs;
1084 }
1085
1086 friend struct GraphTraits<ValueInfo>;
1087 };
1088
1089 template <> struct DenseMapInfo<FunctionSummary::VFuncId> {
1090 static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; }
1091
1092 static FunctionSummary::VFuncId getTombstoneKey() {
1093 return {0, uint64_t(-2)};
1094 }
1095
1096 static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) {
1097 return L.GUID == R.GUID && L.Offset == R.Offset;
1098 }
1099
1100 static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; }
1101 };
1102
1103 template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
1104 static FunctionSummary::ConstVCall getEmptyKey() {
1105 return {{0, uint64_t(-1)}, {}};
1106 }
1107
1108 static FunctionSummary::ConstVCall getTombstoneKey() {
1109 return {{0, uint64_t(-2)}, {}};
1110 }
1111
1112 static bool isEqual(FunctionSummary::ConstVCall L,
1113 FunctionSummary::ConstVCall R) {
1114 return DenseMapInfo<FunctionSummary::VFuncId>::isEqual(L.VFunc, R.VFunc) &&
1115 L.Args == R.Args;
1116 }
1117
1118 static unsigned getHashValue(FunctionSummary::ConstVCall I) {
1119 return I.VFunc.GUID;
1120 }
1121 };
1122
1123
1124
1125 struct VirtFuncOffset {
1126 VirtFuncOffset(ValueInfo VI, uint64_t Offset)
1127 : FuncVI(VI), VTableOffset(Offset) {}
1128
1129 ValueInfo FuncVI;
1130 uint64_t VTableOffset;
1131 };
1132
1133 using VTableFuncList = std::vector<VirtFuncOffset>;
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 class GlobalVarSummary : public GlobalValueSummary {
1145 private:
1146
1147
1148 std::unique_ptr<VTableFuncList> VTableFuncs;
1149
1150 public:
1151 struct GVarFlags {
1152 GVarFlags(bool ReadOnly, bool WriteOnly, bool Constant,
1153 GlobalObject::VCallVisibility Vis)
1154 : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly),
1155 Constant(Constant), VCallVisibility(Vis) {}
1156
1157
1158
1159
1160
1161
1162 unsigned MaybeReadOnly : 1;
1163
1164
1165
1166 unsigned MaybeWriteOnly : 1;
1167
1168
1169
1170
1171
1172
1173
1174
1175 unsigned Constant : 1;
1176
1177
1178 unsigned VCallVisibility : 2;
1179 } VarFlags;
1180
1181 GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
1182 SmallVectorImpl<ValueInfo> &&Refs)
1183 : GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)),
1184 VarFlags(VarFlags) {}
1185
1186
1187 static bool classof(const GlobalValueSummary *GVS) {
1188 return GVS->getSummaryKind() == GlobalVarKind;
1189 }
1190
1191 GVarFlags varflags() const { return VarFlags; }
1192 void setReadOnly(bool RO) { VarFlags.MaybeReadOnly = RO; }
1193 void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
1194 bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
1195 bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
1196 bool isConstant() const { return VarFlags.Constant; }
1197 void setVCallVisibility(GlobalObject::VCallVisibility Vis) {
1198 VarFlags.VCallVisibility = Vis;
1199 }
1200 GlobalObject::VCallVisibility getVCallVisibility() const {
1201 return (GlobalObject::VCallVisibility)VarFlags.VCallVisibility;
1202 }
1203
1204 void setVTableFuncs(VTableFuncList Funcs) {
1205 assert(!VTableFuncs);
1206 VTableFuncs = std::make_unique<VTableFuncList>(std::move(Funcs));
1207 }
1208
1209 ArrayRef<VirtFuncOffset> vTableFuncs() const {
1210 if (VTableFuncs)
1211 return *VTableFuncs;
1212 return {};
1213 }
1214 };
1215
1216 struct TypeTestResolution {
1217
1218
1219
1220
1221 enum Kind {
1222 Unsat,
1223 ByteArray,
1224 Inline,
1225 Single,
1226 AllOnes,
1227
1228 Unknown,
1229 } TheKind = Unknown;
1230
1231
1232
1233
1234 unsigned SizeM1BitWidth = 0;
1235
1236
1237
1238
1239
1240
1241 uint64_t AlignLog2 = 0;
1242 uint64_t SizeM1 = 0;
1243 uint8_t BitMask = 0;
1244 uint64_t InlineBits = 0;
1245 };
1246
1247 struct WholeProgramDevirtResolution {
1248 enum Kind {
1249 Indir,
1250 SingleImpl,
1251 BranchFunnel,
1252
1253
1254 } TheKind = Indir;
1255
1256 std::string SingleImplName;
1257
1258 struct ByArg {
1259 enum Kind {
1260 Indir,
1261 UniformRetVal,
1262 UniqueRetVal,
1263 VirtualConstProp,
1264 } TheKind = Indir;
1265
1266
1267
1268
1269
1270 uint64_t Info = 0;
1271
1272
1273
1274
1275 uint32_t Byte = 0;
1276 uint32_t Bit = 0;
1277 };
1278
1279
1280
1281 std::map<std::vector<uint64_t>, ByArg> ResByArg;
1282 };
1283
1284 struct TypeIdSummary {
1285 TypeTestResolution TTRes;
1286
1287
1288
1289 std::map<uint64_t, WholeProgramDevirtResolution> WPDRes;
1290 };
1291
1292
1293 using ModuleHash = std::array<uint32_t, 5>;
1294
1295
1296 using const_gvsummary_iterator = GlobalValueSummaryMapTy::const_iterator;
1297 using gvsummary_iterator = GlobalValueSummaryMapTy::iterator;
1298
1299
1300
1301 using ModulePathStringTableTy = StringMap<ModuleHash>;
1302
1303
1304
1305 using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>;
1306
1307
1308
1309 using ModuleToSummariesForIndexTy =
1310 std::map<std::string, GVSummaryMapTy, std::less<>>;
1311
1312
1313 using GVSummaryPtrSet = std::unordered_set<GlobalValueSummary *>;
1314
1315
1316
1317 using TypeIdSummaryMapTy =
1318 std::multimap<GlobalValue::GUID, std::pair<StringRef, TypeIdSummary>>;
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330 struct TypeIdOffsetVtableInfo {
1331 TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI)
1332 : AddressPointOffset(Offset), VTableVI(VI) {}
1333
1334 uint64_t AddressPointOffset;
1335 ValueInfo VTableVI;
1336 };
1337
1338
1339
1340
1341 using TypeIdCompatibleVtableInfo = std::vector<TypeIdOffsetVtableInfo>;
1342
1343
1344
1345 class ModuleSummaryIndex {
1346 private:
1347
1348
1349 GlobalValueSummaryMapTy GlobalValueMap;
1350
1351
1352 ModulePathStringTableTy ModulePathStringTable;
1353
1354 BumpPtrAllocator TypeIdSaverAlloc;
1355 UniqueStringSaver TypeIdSaver;
1356
1357
1358
1359 TypeIdSummaryMapTy TypeIdMap;
1360
1361
1362
1363
1364
1365 std::map<StringRef, TypeIdCompatibleVtableInfo, std::less<>>
1366 TypeIdCompatibleVtableMap;
1367
1368
1369
1370 DenseMap<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
1371
1372
1373
1374
1375 bool WithGlobalValueDeadStripping = false;
1376
1377
1378
1379
1380 bool WithAttributePropagation = false;
1381
1382
1383
1384 bool WithDSOLocalPropagation = false;
1385
1386
1387 bool WithWholeProgramVisibility = false;
1388
1389
1390 bool HasSyntheticEntryCounts = false;
1391
1392
1393 bool WithSupportsHotColdNew = false;
1394
1395
1396
1397
1398
1399
1400 bool SkipModuleByDistributedBackend = false;
1401
1402
1403
1404
1405
1406 bool HaveGVs;
1407
1408
1409 bool EnableSplitLTOUnit;
1410
1411
1412 bool UnifiedLTO;
1413
1414
1415
1416 bool PartiallySplitLTOUnits = false;
1417
1418
1419 bool HasParamAccess = false;
1420
1421 std::set<std::string, std::less<>> CfiFunctionDefs;
1422 std::set<std::string, std::less<>> CfiFunctionDecls;
1423
1424
1425
1426 BumpPtrAllocator Alloc;
1427 StringSaver Saver;
1428
1429
1430
1431
1432
1433
1434
1435
1436 uint64_t BlockCount = 0;
1437
1438
1439
1440
1441
1442 std::vector<uint64_t> StackIds;
1443
1444
1445
1446 DenseMap<uint64_t, unsigned> StackIdToIndex;
1447
1448
1449 friend yaml::MappingTraits<ModuleSummaryIndex>;
1450
1451 GlobalValueSummaryMapTy::value_type *
1452 getOrInsertValuePtr(GlobalValue::GUID GUID) {
1453 return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(HaveGVs))
1454 .first;
1455 }
1456
1457 public:
1458
1459 ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false,
1460 bool UnifiedLTO = false)
1461 : TypeIdSaver(TypeIdSaverAlloc), HaveGVs(HaveGVs),
1462 EnableSplitLTOUnit(EnableSplitLTOUnit), UnifiedLTO(UnifiedLTO),
1463 Saver(Alloc) {}
1464
1465
1466
1467
1468
1469
1470 static constexpr uint64_t BitcodeSummaryVersion = 12;
1471
1472
1473 static constexpr const char *getRegularLTOModuleName() {
1474 return "[Regular LTO]";
1475 }
1476
1477 bool haveGVs() const { return HaveGVs; }
1478
1479 uint64_t getFlags() const;
1480 void setFlags(uint64_t Flags);
1481
1482 uint64_t getBlockCount() const { return BlockCount; }
1483 void addBlockCount(uint64_t C) { BlockCount += C; }
1484 void setBlockCount(uint64_t C) { BlockCount = C; }
1485
1486 gvsummary_iterator begin() { return GlobalValueMap.begin(); }
1487 const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
1488 gvsummary_iterator end() { return GlobalValueMap.end(); }
1489 const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
1490 size_t size() const { return GlobalValueMap.size(); }
1491
1492 const std::vector<uint64_t> &stackIds() const { return StackIds; }
1493
1494 unsigned addOrGetStackIdIndex(uint64_t StackId) {
1495 auto Inserted = StackIdToIndex.insert({StackId, StackIds.size()});
1496 if (Inserted.second)
1497 StackIds.push_back(StackId);
1498 return Inserted.first->second;
1499 }
1500
1501 uint64_t getStackIdAtIndex(unsigned Index) const {
1502 assert(StackIds.size() > Index);
1503 return StackIds[Index];
1504 }
1505
1506
1507
1508
1509
1510
1511 void releaseTemporaryMemory() {
1512 assert(StackIdToIndex.size() == StackIds.size());
1513 StackIdToIndex.clear();
1514 StackIds.shrink_to_fit();
1515 }
1516
1517
1518
1519 static void discoverNodes(ValueInfo V,
1520 std::map<ValueInfo, bool> &FunctionHasParent) {
1521 if (!V.getSummaryList().size())
1522 return;
1523
1524
1525 auto S = FunctionHasParent.emplace(V, false);
1526
1527
1528 if (!S.second)
1529 return;
1530
1531 FunctionSummary *F =
1532 dyn_cast<FunctionSummary>(V.getSummaryList().front().get());
1533 assert(F != nullptr && "Expected FunctionSummary node");
1534
1535 for (const auto &C : F->calls()) {
1536
1537 auto S = FunctionHasParent.emplace(C.first, true);
1538
1539
1540 if (!S.second && S.first->second)
1541 continue;
1542
1543 if (S.second)
1544 discoverNodes(C.first, FunctionHasParent);
1545 else
1546 S.first->second = true;
1547 }
1548 }
1549
1550
1551 FunctionSummary calculateCallGraphRoot() {
1552
1553
1554
1555 std::map<ValueInfo, bool> FunctionHasParent;
1556
1557 for (auto &S : *this) {
1558
1559 if (!S.second.SummaryList.size() ||
1560 !isa<FunctionSummary>(S.second.SummaryList.front().get()))
1561 continue;
1562 discoverNodes(ValueInfo(HaveGVs, &S), FunctionHasParent);
1563 }
1564
1565 SmallVector<FunctionSummary::EdgeTy, 0> Edges;
1566
1567 for (auto &P : FunctionHasParent) {
1568 if (P.second)
1569 continue;
1570 Edges.push_back(std::make_pair(P.first, CalleeInfo{}));
1571 }
1572 return FunctionSummary::makeDummyFunctionSummary(std::move(Edges));
1573 }
1574
1575 bool withGlobalValueDeadStripping() const {
1576 return WithGlobalValueDeadStripping;
1577 }
1578 void setWithGlobalValueDeadStripping() {
1579 WithGlobalValueDeadStripping = true;
1580 }
1581
1582 bool withAttributePropagation() const { return WithAttributePropagation; }
1583 void setWithAttributePropagation() {
1584 WithAttributePropagation = true;
1585 }
1586
1587 bool withDSOLocalPropagation() const { return WithDSOLocalPropagation; }
1588 void setWithDSOLocalPropagation() { WithDSOLocalPropagation = true; }
1589
1590 bool withWholeProgramVisibility() const { return WithWholeProgramVisibility; }
1591 void setWithWholeProgramVisibility() { WithWholeProgramVisibility = true; }
1592
1593 bool isReadOnly(const GlobalVarSummary *GVS) const {
1594 return WithAttributePropagation && GVS->maybeReadOnly();
1595 }
1596 bool isWriteOnly(const GlobalVarSummary *GVS) const {
1597 return WithAttributePropagation && GVS->maybeWriteOnly();
1598 }
1599
1600 bool withSupportsHotColdNew() const { return WithSupportsHotColdNew; }
1601 void setWithSupportsHotColdNew() { WithSupportsHotColdNew = true; }
1602
1603 bool skipModuleByDistributedBackend() const {
1604 return SkipModuleByDistributedBackend;
1605 }
1606 void setSkipModuleByDistributedBackend() {
1607 SkipModuleByDistributedBackend = true;
1608 }
1609
1610 bool enableSplitLTOUnit() const { return EnableSplitLTOUnit; }
1611 void setEnableSplitLTOUnit() { EnableSplitLTOUnit = true; }
1612
1613 bool hasUnifiedLTO() const { return UnifiedLTO; }
1614 void setUnifiedLTO() { UnifiedLTO = true; }
1615
1616 bool partiallySplitLTOUnits() const { return PartiallySplitLTOUnits; }
1617 void setPartiallySplitLTOUnits() { PartiallySplitLTOUnits = true; }
1618
1619 bool hasParamAccess() const { return HasParamAccess; }
1620
1621 bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
1622 return !WithGlobalValueDeadStripping || GVS->isLive();
1623 }
1624 bool isGUIDLive(GlobalValue::GUID GUID) const;
1625
1626
1627
1628 ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const {
1629 return ValueInfo(HaveGVs, &R);
1630 }
1631
1632
1633 ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
1634 auto I = GlobalValueMap.find(GUID);
1635 return ValueInfo(HaveGVs, I == GlobalValueMap.end() ? nullptr : &*I);
1636 }
1637
1638
1639 ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
1640 return ValueInfo(HaveGVs, getOrInsertValuePtr(GUID));
1641 }
1642
1643
1644
1645
1646 StringRef saveString(StringRef String) { return Saver.save(String); }
1647
1648
1649 ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
1650 assert(!HaveGVs);
1651 auto VP = getOrInsertValuePtr(GUID);
1652 VP->second.U.Name = Name;
1653 return ValueInfo(HaveGVs, VP);
1654 }
1655
1656
1657 ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
1658 assert(HaveGVs);
1659 auto VP = getOrInsertValuePtr(GV->getGUID());
1660 VP->second.U.GV = GV;
1661 return ValueInfo(HaveGVs, VP);
1662 }
1663
1664
1665 GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const {
1666 const auto I = OidGuidMap.find(OriginalID);
1667 return I == OidGuidMap.end() ? 0 : I->second;
1668 }
1669
1670 std::set<std::string, std::less<>> &cfiFunctionDefs() {
1671 return CfiFunctionDefs;
1672 }
1673 const std::set<std::string, std::less<>> &cfiFunctionDefs() const {
1674 return CfiFunctionDefs;
1675 }
1676
1677 std::set<std::string, std::less<>> &cfiFunctionDecls() {
1678 return CfiFunctionDecls;
1679 }
1680 const std::set<std::string, std::less<>> &cfiFunctionDecls() const {
1681 return CfiFunctionDecls;
1682 }
1683
1684
1685 void addGlobalValueSummary(const GlobalValue &GV,
1686 std::unique_ptr<GlobalValueSummary> Summary) {
1687 addGlobalValueSummary(getOrInsertValueInfo(&GV), std::move(Summary));
1688 }
1689
1690
1691 void addGlobalValueSummary(StringRef ValueName,
1692 std::unique_ptr<GlobalValueSummary> Summary) {
1693 addGlobalValueSummary(getOrInsertValueInfo(GlobalValue::getGUID(ValueName)),
1694 std::move(Summary));
1695 }
1696
1697
1698 void addGlobalValueSummary(ValueInfo VI,
1699 std::unique_ptr<GlobalValueSummary> Summary) {
1700 if (const FunctionSummary *FS = dyn_cast<FunctionSummary>(Summary.get()))
1701 HasParamAccess |= !FS->paramAccesses().empty();
1702 addOriginalName(VI.getGUID(), Summary->getOriginalName());
1703
1704
1705 const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef())
1706 ->second.SummaryList.push_back(std::move(Summary));
1707 }
1708
1709
1710 void addOriginalName(GlobalValue::GUID ValueGUID,
1711 GlobalValue::GUID OrigGUID) {
1712 if (OrigGUID == 0 || ValueGUID == OrigGUID)
1713 return;
1714 auto [It, Inserted] = OidGuidMap.try_emplace(OrigGUID, ValueGUID);
1715 if (!Inserted && It->second != ValueGUID)
1716 It->second = 0;
1717 }
1718
1719
1720
1721 GlobalValueSummary *findSummaryInModule(ValueInfo VI, StringRef ModuleId) const {
1722 auto SummaryList = VI.getSummaryList();
1723 auto Summary =
1724 llvm::find_if(SummaryList,
1725 [&](const std::unique_ptr<GlobalValueSummary> &Summary) {
1726 return Summary->modulePath() == ModuleId;
1727 });
1728 if (Summary == SummaryList.end())
1729 return nullptr;
1730 return Summary->get();
1731 }
1732
1733
1734
1735 GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
1736 StringRef ModuleId) const {
1737 auto CalleeInfo = getValueInfo(ValueGUID);
1738 if (!CalleeInfo)
1739 return nullptr;
1740 return findSummaryInModule(CalleeInfo, ModuleId);
1741 }
1742
1743
1744
1745 GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV,
1746 bool PerModuleIndex = true) const {
1747 assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name");
1748 return getGlobalValueSummary(GV.getGUID(), PerModuleIndex);
1749 }
1750
1751
1752
1753
1754 GlobalValueSummary *getGlobalValueSummary(GlobalValue::GUID ValueGUID,
1755 bool PerModuleIndex = true) const;
1756
1757
1758 const StringMap<ModuleHash> &modulePaths() const {
1759 return ModulePathStringTable;
1760 }
1761
1762
1763 StringMap<ModuleHash> &modulePaths() { return ModulePathStringTable; }
1764
1765
1766 const ModuleHash &getModuleHash(const StringRef ModPath) const {
1767 auto It = ModulePathStringTable.find(ModPath);
1768 assert(It != ModulePathStringTable.end() && "Module not registered");
1769 return It->second;
1770 }
1771
1772
1773
1774 static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash) {
1775 std::string Suffix = utostr((uint64_t(ModHash[0]) << 32) |
1776 ModHash[1]);
1777 return getGlobalNameForLocal(Name, Suffix);
1778 }
1779
1780 static std::string getGlobalNameForLocal(StringRef Name, StringRef Suffix) {
1781 SmallString<256> NewName(Name);
1782 NewName += ".llvm.";
1783 NewName += Suffix;
1784 return std::string(NewName);
1785 }
1786
1787
1788
1789
1790
1791 static StringRef getOriginalNameBeforePromote(StringRef Name) {
1792 std::pair<StringRef, StringRef> Pair = Name.rsplit(".llvm.");
1793 return Pair.first;
1794 }
1795
1796 typedef ModulePathStringTableTy::value_type ModuleInfo;
1797
1798
1799
1800 ModuleInfo *addModule(StringRef ModPath, ModuleHash Hash = ModuleHash{{0}}) {
1801 return &*ModulePathStringTable.insert({ModPath, Hash}).first;
1802 }
1803
1804
1805 ModuleInfo *getModule(StringRef ModPath) {
1806 auto It = ModulePathStringTable.find(ModPath);
1807 assert(It != ModulePathStringTable.end() && "Module not registered");
1808 return &*It;
1809 }
1810
1811
1812 const ModuleInfo *getModule(StringRef ModPath) const {
1813 auto It = ModulePathStringTable.find(ModPath);
1814 assert(It != ModulePathStringTable.end() && "Module not registered");
1815 return &*It;
1816 }
1817
1818
1819
1820
1821 bool hasExportedFunctions(const Module &M) const {
1822 return ModulePathStringTable.count(M.getModuleIdentifier());
1823 }
1824
1825 const TypeIdSummaryMapTy &typeIds() const { return TypeIdMap; }
1826
1827
1828
1829
1830 TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
1831 auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
1832 for (auto &[GUID, TypeIdPair] : make_range(TidIter))
1833 if (TypeIdPair.first == TypeId)
1834 return TypeIdPair.second;
1835 auto It = TypeIdMap.insert({GlobalValue::getGUID(TypeId),
1836 {TypeIdSaver.save(TypeId), TypeIdSummary()}});
1837 return It->second.second;
1838 }
1839
1840
1841
1842 const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
1843 auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
1844 for (const auto &[GUID, TypeIdPair] : make_range(TidIter))
1845 if (TypeIdPair.first == TypeId)
1846 return &TypeIdPair.second;
1847 return nullptr;
1848 }
1849
1850 TypeIdSummary *getTypeIdSummary(StringRef TypeId) {
1851 return const_cast<TypeIdSummary *>(
1852 static_cast<const ModuleSummaryIndex *>(this)->getTypeIdSummary(
1853 TypeId));
1854 }
1855
1856 const auto &typeIdCompatibleVtableMap() const {
1857 return TypeIdCompatibleVtableMap;
1858 }
1859
1860
1861
1862
1863 TypeIdCompatibleVtableInfo &
1864 getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) {
1865 return TypeIdCompatibleVtableMap[TypeIdSaver.save(TypeId)];
1866 }
1867
1868
1869
1870 std::optional<TypeIdCompatibleVtableInfo>
1871 getTypeIdCompatibleVtableSummary(StringRef TypeId) const {
1872 auto I = TypeIdCompatibleVtableMap.find(TypeId);
1873 if (I == TypeIdCompatibleVtableMap.end())
1874 return std::nullopt;
1875 return I->second;
1876 }
1877
1878
1879
1880 void collectDefinedFunctionsForModule(StringRef ModulePath,
1881 GVSummaryMapTy &GVSummaryMap) const;
1882
1883
1884
1885 template <class Map>
1886 void
1887 collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const {
1888 for (const auto &GlobalList : *this) {
1889 auto GUID = GlobalList.first;
1890 for (const auto &Summary : GlobalList.second.SummaryList) {
1891 ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get();
1892 }
1893 }
1894 }
1895
1896
1897 void print(raw_ostream &OS, bool IsForDebug = false) const;
1898
1899
1900 void dump() const;
1901
1902
1903 void
1904 exportToDot(raw_ostream &OS,
1905 const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) const;
1906
1907
1908 void dumpSCCs(raw_ostream &OS);
1909
1910
1911 void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
1912
1913
1914 bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs) const;
1915
1916
1917
1918 bool canImportGlobalVar(const GlobalValueSummary *S, bool AnalyzeRefs,
1919 bool &CanImportDecl) const;
1920 };
1921
1922
1923 template <> struct GraphTraits<ValueInfo> {
1924 typedef ValueInfo NodeRef;
1925 using EdgeRef = FunctionSummary::EdgeTy &;
1926
1927 static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) {
1928 return P.first;
1929 }
1930 using ChildIteratorType =
1931 mapped_iterator<SmallVector<FunctionSummary::EdgeTy, 0>::iterator,
1932 decltype(&valueInfoFromEdge)>;
1933
1934 using ChildEdgeIteratorType =
1935 SmallVector<FunctionSummary::EdgeTy, 0>::iterator;
1936
1937 static NodeRef getEntryNode(ValueInfo V) { return V; }
1938
1939 static ChildIteratorType child_begin(NodeRef N) {
1940 if (!N.getSummaryList().size())
1941 return ChildIteratorType(
1942 FunctionSummary::ExternalNode.CallGraphEdgeList.begin(),
1943 &valueInfoFromEdge);
1944 FunctionSummary *F =
1945 cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
1946 return ChildIteratorType(F->CallGraphEdgeList.begin(), &valueInfoFromEdge);
1947 }
1948
1949 static ChildIteratorType child_end(NodeRef N) {
1950 if (!N.getSummaryList().size())
1951 return ChildIteratorType(
1952 FunctionSummary::ExternalNode.CallGraphEdgeList.end(),
1953 &valueInfoFromEdge);
1954 FunctionSummary *F =
1955 cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
1956 return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge);
1957 }
1958
1959 static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
1960 if (!N.getSummaryList().size())
1961 return FunctionSummary::ExternalNode.CallGraphEdgeList.begin();
1962
1963 FunctionSummary *F =
1964 cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
1965 return F->CallGraphEdgeList.begin();
1966 }
1967
1968 static ChildEdgeIteratorType child_edge_end(NodeRef N) {
1969 if (!N.getSummaryList().size())
1970 return FunctionSummary::ExternalNode.CallGraphEdgeList.end();
1971
1972 FunctionSummary *F =
1973 cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
1974 return F->CallGraphEdgeList.end();
1975 }
1976
1977 static NodeRef edge_dest(EdgeRef E) { return E.first; }
1978 };
1979
1980 template <>
1981 struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
1982 static NodeRef getEntryNode(ModuleSummaryIndex *I) {
1983 std::unique_ptr<GlobalValueSummary> Root =
1984 std::make_unique<FunctionSummary>(I->calculateCallGraphRoot());
1985 GlobalValueSummaryInfo G(I->haveGVs());
1986 G.SummaryList.push_back(std::move(Root));
1987 static auto P =
1988 GlobalValueSummaryMapTy::value_type(GlobalValue::GUID(0), std::move(G));
1989 return ValueInfo(I->haveGVs(), &P);
1990 }
1991 };
1992 }
1993
1994 #endif