summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/LTO/LTO.cpp65
-rw-r--r--llvm/lib/Transforms/IPO/PassManagerBuilder.cpp8
-rw-r--r--llvm/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll8
-rw-r--r--llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll10
4 files changed, 59 insertions, 32 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4fb36e7998e..017dd201f9c 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1098,42 +1098,45 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
ThinLTO.ModuleMap.size());
StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
- if (Conf.OptLevel > 0) {
+ if (Conf.OptLevel > 0)
ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
ImportLists, ExportLists);
- std::set<GlobalValue::GUID> ExportedGUIDs;
- for (auto &Res : GlobalResolutions) {
- // First check if the symbol was flagged as having external references.
- if (Res.second.Partition != GlobalResolution::External)
- continue;
- // IRName will be defined if we have seen the prevailing copy of
- // this value. If not, no need to mark as exported from a ThinLTO
- // partition (and we can't get the GUID).
- if (Res.second.IRName.empty())
- continue;
- auto GUID = GlobalValue::getGUID(
- GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
- // Mark exported unless index-based analysis determined it to be dead.
- if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
- ExportedGUIDs.insert(GUID);
- }
-
- // Any functions referenced by the jump table in the regular LTO object must
- // be exported.
- for (auto &Def : ThinLTO.CombinedIndex.cfiFunctionDefs())
- ExportedGUIDs.insert(
- GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Def)));
-
- auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
- const auto &ExportList = ExportLists.find(ModuleIdentifier);
- return (ExportList != ExportLists.end() &&
- ExportList->second.count(GUID)) ||
- ExportedGUIDs.count(GUID);
- };
- thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
+ // Figure out which symbols need to be internalized. This also needs to happen
+ // at -O0 because summary-based DCE is implemented using internalization, and
+ // we must apply DCE consistently with the full LTO module in order to avoid
+ // undefined references during the final link.
+ std::set<GlobalValue::GUID> ExportedGUIDs;
+ for (auto &Res : GlobalResolutions) {
+ // First check if the symbol was flagged as having external references.
+ if (Res.second.Partition != GlobalResolution::External)
+ continue;
+ // IRName will be defined if we have seen the prevailing copy of
+ // this value. If not, no need to mark as exported from a ThinLTO
+ // partition (and we can't get the GUID).
+ if (Res.second.IRName.empty())
+ continue;
+ auto GUID = GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+ // Mark exported unless index-based analysis determined it to be dead.
+ if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
+ ExportedGUIDs.insert(GUID);
}
+ // Any functions referenced by the jump table in the regular LTO object must
+ // be exported.
+ for (auto &Def : ThinLTO.CombinedIndex.cfiFunctionDefs())
+ ExportedGUIDs.insert(
+ GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Def)));
+
+ auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
+ const auto &ExportList = ExportLists.find(ModuleIdentifier);
+ return (ExportList != ExportLists.end() &&
+ ExportList->second.count(GUID)) ||
+ ExportedGUIDs.count(GUID);
+ };
+ thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
+
auto isPrevailing = [&](GlobalValue::GUID GUID,
const GlobalValueSummary *S) {
return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
index bb15cf510c7..828eb5eee29 100644
--- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -418,6 +418,14 @@ void PassManagerBuilder::populateModulePassManager(
else if (GlobalExtensionsNotEmpty() || !Extensions.empty())
MPM.add(createBarrierNoopPass());
+ if (PerformThinLTO) {
+ // Drop available_externally and unreferenced globals. This is necessary
+ // with ThinLTO in order to avoid leaving undefined references to dead
+ // globals in the object file.
+ MPM.add(createEliminateAvailableExternallyPass());
+ MPM.add(createGlobalDCEPass());
+ }
+
addExtensionsToPM(EP_EnabledOnOptLevel0, MPM);
// Rename anon globals to be able to export them in the summary.
diff --git a/llvm/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll b/llvm/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
index 66754889f8b..cc508924c67 100644
--- a/llvm/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
+++ b/llvm/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
@@ -14,3 +14,11 @@ define void @dead1() {
}
declare void @dead2()
+
+define linkonce_odr i8* @odr() {
+ ret i8* bitcast (void ()* @dead3 to i8*)
+}
+
+define internal void @dead3() {
+ ret void
+}
diff --git a/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll b/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll
index a9be2751c81..02b0e38fb9b 100644
--- a/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll
+++ b/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll
@@ -1,11 +1,18 @@
; RUN: opt -module-summary -o %t %s
; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll
+
; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \
-; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, \
+; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, -r %t2,odr, \
; RUN: -save-temps -o %t3
; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s
+; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \
+; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, -r %t2,odr, \
+; RUN: -save-temps -o %t3 -O0
+; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
+; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s
+
; FULL-NOT: dead
; FULL: U live1
; FULL: T live2
@@ -14,6 +21,7 @@
; THIN-NOT: dead
; THIN: T live1
; THIN: U live2
+; THIN-NOT: odr
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
OpenPOWER on IntegriCloud