[ThinLTO] Internalize readonly globals
An attempt to recommit r346584 after failure on OSX build bot.
Fixed cache key computation in ThinLTOCodeGenerator and added
test case
llvm-svn: 347033
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 1196dd0..d8807f8 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -294,10 +294,8 @@
LLVM_DEBUG(dbgs() << " ref -> " << VI << "\n");
for (auto &RefSummary : VI.getSummaryList())
- if (RefSummary->getSummaryKind() == GlobalValueSummary::GlobalVarKind &&
- !RefSummary->notEligibleToImport() &&
- !GlobalValue::isInterposableLinkage(RefSummary->linkage()) &&
- RefSummary->refs().empty()) {
+ if (isa<GlobalVarSummary>(RefSummary.get()) &&
+ canImportGlobalVar(RefSummary.get())) {
auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID());
// Only update stat if we haven't already imported this variable.
if (ILI.second)
@@ -824,6 +822,25 @@
NumLiveSymbols += LiveSymbols;
}
+// Compute dead symbols and propagate constants in combined index.
+void llvm::computeDeadSymbolsWithConstProp(
+ ModuleSummaryIndex &Index,
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
+ function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing,
+ bool ImportEnabled) {
+ computeDeadSymbols(Index, GUIDPreservedSymbols, isPrevailing);
+ if (ImportEnabled) {
+ Index.propagateConstants(GUIDPreservedSymbols);
+ } else {
+ // If import is disabled we should drop read-only attribute
+ // from all summaries to prevent internalization.
+ for (auto &P : Index)
+ for (auto &S : P.second.SummaryList)
+ if (auto *GVS = dyn_cast<GlobalVarSummary>(S.get()))
+ GVS->setReadOnly(false);
+ }
+}
+
/// Compute the set of summaries needed for a ThinLTO backend compilation of
/// \p ModulePath.
void llvm::gatherImportedSummariesForModule(
@@ -1020,6 +1037,18 @@
return NewFn;
}
+// Internalize values that we marked with specific attribute
+// in processGlobalForThinLTO.
+static void internalizeImmutableGVs(Module &M) {
+ for (auto &GV : M.globals())
+ // Skip GVs which have been converted to declarations
+ // by dropDeadSymbols.
+ if (!GV.isDeclaration() && GV.hasAttribute("thinlto-internalize")) {
+ GV.setLinkage(GlobalValue::InternalLinkage);
+ GV.setVisibility(GlobalValue::DefaultVisibility);
+ }
+}
+
// Automatically import functions in Module \p DestModule based on the summaries
// index.
Expected<bool> FunctionImporter::importFunctions(
@@ -1143,6 +1172,8 @@
NumImportedModules++;
}
+ internalizeImmutableGVs(DestModule);
+
NumImportedFunctions += (ImportedCount - ImportedGVCount);
NumImportedGlobalVars += ImportedGVCount;
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 479816a..dd952ea 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -204,8 +204,9 @@
// Check the summaries to see if the symbol gets resolved to a known local
// definition.
+ ValueInfo VI;
if (GV.hasName()) {
- ValueInfo VI = ImportIndex.getValueInfo(GV.getGUID());
+ VI = ImportIndex.getValueInfo(GV.getGUID());
if (VI && VI.isDSOLocal()) {
GV.setDSOLocal(true);
if (GV.hasDLLImportStorageClass())
@@ -213,6 +214,22 @@
}
}
+ // Mark read-only variables which can be imported with specific attribute.
+ // We can't internalize them now because IRMover will fail to link variable
+ // definitions to their external declarations during ThinLTO import. We'll
+ // internalize read-only variables later, after import is finished.
+ // See internalizeImmutableGVs.
+ //
+ // If global value dead stripping is not enabled in summary then
+ // propagateConstants hasn't been run. We can't internalize GV
+ // in such case.
+ if (!GV.isDeclaration() && VI && ImportIndex.withGlobalValueDeadStripping()) {
+ const auto &SL = VI.getSummaryList();
+ auto *GVS = SL.empty() ? nullptr : dyn_cast<GlobalVarSummary>(SL[0].get());
+ if (GVS && GVS->isReadOnly())
+ cast<GlobalVariable>(&GV)->addAttribute("thinlto-internalize");
+ }
+
bool DoPromote = false;
if (GV.hasLocalLinkage() &&
((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) {
@@ -230,7 +247,7 @@
// Remove functions imported as available externally defs from comdats,
// as this is a declaration for the linker, and will be dropped eventually.
// It is illegal for comdats to contain declarations.
- auto *GO = dyn_cast_or_null<GlobalObject>(&GV);
+ auto *GO = dyn_cast<GlobalObject>(&GV);
if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {
// The IRMover should not have placed any imported declarations in
// a comdat, so the only declaration that should be in a comdat