|
10 | 10 | #define LLVM_TRANSFORMS_IPO_FUNCTIONIMPORT_H
|
11 | 11 |
|
12 | 12 | #include "llvm/ADT/DenseSet.h"
|
| 13 | +#include "llvm/ADT/MapVector.h" |
13 | 14 | #include "llvm/ADT/StringRef.h"
|
14 | 15 | #include "llvm/IR/GlobalValue.h"
|
15 | 16 | #include "llvm/IR/ModuleSummaryIndex.h"
|
@@ -96,6 +97,76 @@ class FunctionImporter {
|
96 | 97 | std::tuple<unsigned, const GlobalValueSummary *,
|
97 | 98 | std::unique_ptr<ImportFailureInfo>>>;
|
98 | 99 |
|
| 100 | + // Issues import IDs. Each ID uniquely corresponds to a tuple of |
| 101 | + // (FromModule, GUID, Definition/Declaration). |
| 102 | + // |
| 103 | + // The import IDs make the import list space efficient by referring to each |
| 104 | + // import with a 32-bit integer ID while maintaining a central table that maps |
| 105 | + // those integer IDs to tuples of (FromModule, GUID, Def/Decl). |
| 106 | + // |
| 107 | + // In one large application, a pair of (FromModule, GUID) is mentioned in |
| 108 | + // import lists more than 50 times on average across all destination modules. |
| 109 | + // Mentioning the 32-byte tuple: |
| 110 | + // |
| 111 | + // std::tuple<StringRef, GlobalValue::GUID, GlobalValueSummary::ImportKind> |
| 112 | + // |
| 113 | + // 50 times by value in various import lists would be costly. We can reduce |
| 114 | + // the memory footprint of import lists by placing one copy in a central table |
| 115 | + // and referring to it with 32-bit integer IDs. |
| 116 | + // |
| 117 | + // To save space within the central table, we only store pairs of |
| 118 | + // (FromModule, GUID) in the central table. In the actual 32-bit integer ID, |
| 119 | + // the top 31 bits index into the central table while the bottom 1 bit |
| 120 | + // indicates whether an ID is for GlobalValueSummary::Declaration or |
| 121 | + // GlobalValueSummary::Definition. |
| 122 | + class ImportIDTable { |
| 123 | + public: |
| 124 | + using ImportIDTy = uint32_t; |
| 125 | + |
| 126 | + // Create a pair of import IDs [Def, Decl] for a given pair of FromModule |
| 127 | + // and GUID. |
| 128 | + std::pair<ImportIDTy, ImportIDTy> createImportIDs(StringRef FromModule, |
| 129 | + GlobalValue::GUID GUID) { |
| 130 | + auto Key = std::make_pair(FromModule, GUID); |
| 131 | + auto InsertResult = TheTable.try_emplace(Key, TheTable.size()); |
| 132 | + return makeIDPair(InsertResult.first->second); |
| 133 | + } |
| 134 | + |
| 135 | + // Get a pair of previously created import IDs [Def, Decl] for a given pair |
| 136 | + // of FromModule and GUID. Returns std::nullopt if not available. |
| 137 | + std::optional<std::pair<ImportIDTy, ImportIDTy>> |
| 138 | + getImportIDs(StringRef FromModule, GlobalValue::GUID GUID) { |
| 139 | + auto Key = std::make_pair(FromModule, GUID); |
| 140 | + auto It = TheTable.find(Key); |
| 141 | + if (It != TheTable.end()) |
| 142 | + return makeIDPair(It->second); |
| 143 | + return std::nullopt; |
| 144 | + } |
| 145 | + |
| 146 | + // Return a tuple of [FromModule, GUID, Def/Decl] that a given ImportID |
| 147 | + // corresponds to. |
| 148 | + std::tuple<StringRef, GlobalValue::GUID, GlobalValueSummary::ImportKind> |
| 149 | + lookup(ImportIDTy ImportID) const { |
| 150 | + GlobalValueSummary::ImportKind Kind = |
| 151 | + (ImportID & 1) ? GlobalValueSummary::Declaration |
| 152 | + : GlobalValueSummary::Definition; |
| 153 | + auto It = TheTable.begin() + (ImportID >> 1); |
| 154 | + StringRef FromModule = It->first.first; |
| 155 | + GlobalValue::GUID GUID = It->first.second; |
| 156 | + return std::make_tuple(FromModule, GUID, Kind); |
| 157 | + } |
| 158 | + |
| 159 | + private: |
| 160 | + // Make a pair of import IDs [Def, Decl] from an index into TheTable. |
| 161 | + static std::pair<ImportIDTy, ImportIDTy> makeIDPair(ImportIDTy Index) { |
| 162 | + ImportIDTy Def = Index << 1; |
| 163 | + ImportIDTy Decl = Def | 1; |
| 164 | + return std::make_pair(Def, Decl); |
| 165 | + } |
| 166 | + |
| 167 | + MapVector<std::pair<StringRef, GlobalValue::GUID>, ImportIDTy> TheTable; |
| 168 | + }; |
| 169 | + |
99 | 170 | /// The map maintains the list of imports. Conceptually, it is a collection
|
100 | 171 | /// of tuples of the form:
|
101 | 172 | ///
|
|
0 commit comments