Skip to content

Commit 14deb75

Browse files
[ThinLTO] Track definitions only in export-set
1 parent 9b94056 commit 14deb75

File tree

3 files changed

+41
-36
lines changed

3 files changed

+41
-36
lines changed

llvm/include/llvm/Transforms/IPO/FunctionImport.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,10 @@ class FunctionImporter {
104104
/// index's module path string table).
105105
using ImportMapTy = DenseMap<StringRef, FunctionsToImportTy>;
106106

107-
/// The map contains an entry for every global value the module exports.
108-
/// The key is ValueInfo, and the value indicates whether the definition
109-
/// or declaration is visible to another module. If a function's definition is
110-
/// visible to other modules, the global values this function referenced are
111-
/// visible and shouldn't be internalized.
112-
/// TODO: Rename to `ExportMapTy`.
113-
using ExportSetTy = DenseMap<ValueInfo, GlobalValueSummary::ImportKind>;
107+
/// The set contains an entry for every global value that the module exports.
108+
/// Depending on the user context, this container is allowed to contain
109+
/// definitions, declarations or a mix of both.
110+
using ExportSetTy = DenseSet<ValueInfo>;
114111

115112
/// A function of this type is used to load modules referenced by the index.
116113
using ModuleLoaderTy =

llvm/lib/LTO/LTO.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,17 @@ void llvm::computeLTOCacheKey(
161161
auto ModHash = Index.getModuleHash(ModuleID);
162162
Hasher.update(ArrayRef<uint8_t>((uint8_t *)&ModHash[0], sizeof(ModHash)));
163163

164-
std::vector<std::pair<uint64_t, uint8_t>> ExportsGUID;
164+
// TODO: `ExportList` is determined by `ImportList`. Since `ImportList` is
165+
// used to compute cache key, we could omit hashing `ExportList` here.
166+
std::vector<uint64_t> ExportsGUID;
165167
ExportsGUID.reserve(ExportList.size());
166-
for (const auto &[VI, ExportType] : ExportList)
167-
ExportsGUID.push_back(
168-
std::make_pair(VI.getGUID(), static_cast<uint8_t>(ExportType)));
168+
for (const auto &VI : ExportList)
169+
ExportsGUID.push_back(VI.getGUID());
169170

170171
// Sort the export list elements GUIDs.
171172
llvm::sort(ExportsGUID);
172-
for (auto [GUID, ExportType] : ExportsGUID) {
173-
// The export list can impact the internalization, be conservative here
173+
for (auto GUID : ExportsGUID)
174174
Hasher.update(ArrayRef<uint8_t>((uint8_t *)&GUID, sizeof(GUID)));
175-
AddUint8(ExportType);
176-
}
177175

178176
// Include the hash for every module we import functions from. The set of
179177
// imported symbols for each module may affect code generation and is

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,7 @@ class GlobalsImporter final {
400400
// later, in ComputeCrossModuleImport, after import decisions are
401401
// complete, which is more efficient than adding them here.
402402
if (ExportLists)
403-
(*ExportLists)[RefSummary->modulePath()][VI] =
404-
GlobalValueSummary::Definition;
403+
(*ExportLists)[RefSummary->modulePath()].insert(VI);
405404

406405
// If variable is not writeonly we attempt to recursively analyze
407406
// its references in order to import referenced constants.
@@ -582,7 +581,7 @@ class WorkloadImportsManager : public ModuleImportsManager {
582581
GlobalValueSummary::Definition;
583582
GVI.onImportingSummary(*GVS);
584583
if (ExportLists)
585-
(*ExportLists)[ExportingModule][VI] = GlobalValueSummary::Definition;
584+
(*ExportLists)[ExportingModule].insert(VI);
586585
}
587586
LLVM_DEBUG(dbgs() << "[Workload] Done\n");
588587
}
@@ -818,10 +817,8 @@ static void computeImportForFunction(
818817
// Since definition takes precedence over declaration for the same VI,
819818
// try emplace <VI, declaration> pair without checking insert result.
820819
// If insert doesn't happen, there must be an existing entry keyed by
821-
// VI.
822-
if (ExportLists)
823-
(*ExportLists)[DeclSourceModule].try_emplace(
824-
VI, GlobalValueSummary::Declaration);
820+
// VI. Note `ExportLists` only keeps track of definitions so VI won't
821+
// be inserted.
825822
ImportList[DeclSourceModule].try_emplace(
826823
VI.getGUID(), GlobalValueSummary::Declaration);
827824
}
@@ -892,7 +889,7 @@ static void computeImportForFunction(
892889
// later, in ComputeCrossModuleImport, after import decisions are
893890
// complete, which is more efficient than adding them here.
894891
if (ExportLists)
895-
(*ExportLists)[ExportModulePath][VI] = GlobalValueSummary::Definition;
892+
(*ExportLists)[ExportModulePath].insert(VI);
896893
}
897894

898895
auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) {
@@ -998,14 +995,29 @@ static bool isGlobalVarSummary(const ModuleSummaryIndex &Index,
998995
return false;
999996
}
1000997

1001-
template <class T>
1002-
static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, T &Cont,
998+
static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index,
999+
FunctionImporter::ExportSetTy &ExportSet,
10031000
unsigned &DefinedGVS,
10041001
unsigned &DefinedFS) {
1002+
DefinedGVS = 0;
1003+
DefinedFS = 0;
1004+
for (auto &VI : ExportSet) {
1005+
if (isGlobalVarSummary(Index, VI.getGUID())) {
1006+
++DefinedGVS;
1007+
} else
1008+
++DefinedFS;
1009+
}
1010+
return DefinedGVS;
1011+
}
1012+
1013+
static unsigned
1014+
numGlobalVarSummaries(const ModuleSummaryIndex &Index,
1015+
FunctionImporter::FunctionsToImportTy &ImportMap,
1016+
unsigned &DefinedGVS, unsigned &DefinedFS) {
10051017
unsigned NumGVS = 0;
10061018
DefinedGVS = 0;
10071019
DefinedFS = 0;
1008-
for (auto &[GUID, Type] : Cont) {
1020+
for (auto &[GUID, Type] : ImportMap) {
10091021
if (isGlobalVarSummary(Index, GUID)) {
10101022
if (Type == GlobalValueSummary::Definition)
10111023
++DefinedGVS;
@@ -1046,7 +1058,7 @@ static bool checkVariableImport(
10461058
};
10471059

10481060
for (auto &ExportPerModule : ExportLists)
1049-
for (auto &[VI, Unused] : ExportPerModule.second)
1061+
for (auto &VI : ExportPerModule.second)
10501062
if (!FlattenedImports.count(VI.getGUID()) &&
10511063
IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI))
10521064
return false;
@@ -1079,14 +1091,12 @@ void llvm::ComputeCrossModuleImport(
10791091
// since we may import the same values multiple times into different modules
10801092
// during the import computation.
10811093
for (auto &ELI : ExportLists) {
1094+
// `NewExports` tracks the VI that gets exported because the full definition
1095+
// of its user/referencer gets exported.
10821096
FunctionImporter::ExportSetTy NewExports;
10831097
const auto &DefinedGVSummaries =
10841098
ModuleToDefinedGVSummaries.lookup(ELI.first);
1085-
for (auto &[EI, Type] : ELI.second) {
1086-
// If a variable is exported as a declaration, its 'refs' and 'calls' are
1087-
// not further exported.
1088-
if (Type == GlobalValueSummary::Declaration)
1089-
continue;
1099+
for (auto &EI : ELI.second) {
10901100
// Find the copy defined in the exporting module so that we can mark the
10911101
// values it references in that specific definition as exported.
10921102
// Below we will add all references and called values, without regard to
@@ -1108,19 +1118,19 @@ void llvm::ComputeCrossModuleImport(
11081118
for (const auto &VI : GVS->refs()) {
11091119
// Try to emplace the declaration entry. If a definition entry
11101120
// already exists for key `VI`, this is a no-op.
1111-
NewExports.try_emplace(VI, GlobalValueSummary::Declaration);
1121+
NewExports.insert(VI);
11121122
}
11131123
} else {
11141124
auto *FS = cast<FunctionSummary>(S);
11151125
for (const auto &Edge : FS->calls()) {
11161126
// Try to emplace the declaration entry. If a definition entry
11171127
// already exists for key `VI`, this is a no-op.
1118-
NewExports.try_emplace(Edge.first, GlobalValueSummary::Declaration);
1128+
NewExports.insert(Edge.first);
11191129
}
11201130
for (const auto &Ref : FS->refs()) {
11211131
// Try to emplace the declaration entry. If a definition entry
11221132
// already exists for key `VI`, this is a no-op.
1123-
NewExports.try_emplace(Ref, GlobalValueSummary::Declaration);
1133+
NewExports.insert(Ref);
11241134
}
11251135
}
11261136
}
@@ -1129,7 +1139,7 @@ void llvm::ComputeCrossModuleImport(
11291139
// the same ref/call target multiple times in above loop, and it is more
11301140
// efficient to avoid a set lookup each time.
11311141
for (auto EI = NewExports.begin(); EI != NewExports.end();) {
1132-
if (!DefinedGVSummaries.count(EI->first.getGUID()))
1142+
if (!DefinedGVSummaries.count(EI->getGUID()))
11331143
NewExports.erase(EI++);
11341144
else
11351145
++EI;

0 commit comments

Comments
 (0)