summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/LTO/LTO.cpp21
-rw-r--r--llvm/test/LTO/Resolution/X86/Inputs/link-odr-availextern-odr.ll6
-rw-r--r--llvm/test/LTO/Resolution/X86/link-odr-availextern.ll13
3 files changed, 36 insertions, 4 deletions
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4d0c039891e..df19ded398d 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -446,6 +446,11 @@ Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
if (GV.hasAppendingLinkage())
Keep.push_back(&GV);
+ DenseSet<GlobalObject *> AliasedGlobals;
+ for (auto &GA : M.aliases())
+ if (GlobalObject *GO = GA.getBaseObject())
+ AliasedGlobals.insert(GO);
+
for (const InputFile::Symbol &Sym :
make_range(InputFile::symbol_iterator(SymTab.symbols().begin(), SymTab,
nullptr),
@@ -471,13 +476,21 @@ Error LTO::addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
GV->setLinkage(GlobalValue::WeakODRLinkage);
break;
}
- } else if (GV->hasAvailableExternallyLinkage()) {
- // We can link available_externally symbols even if they are
- // non-prevailing.
+ } else if (isa<GlobalObject>(GV) &&
+ (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
+ GV->hasAvailableExternallyLinkage()) &&
+ !AliasedGlobals.count(cast<GlobalObject>(GV))) {
+ // Either of the above three types of linkage indicates that the
+ // chosen prevailing symbol will have the same semantics as this copy of
+ // the symbol, so we can link it with available_externally linkage. We
+ // only need to do this if the symbol is undefined.
GlobalValue *CombinedGV =
RegularLTO.CombinedModule->getNamedValue(GV->getName());
- if (!CombinedGV || CombinedGV->isDeclaration())
+ if (!CombinedGV || CombinedGV->isDeclaration()) {
Keep.push_back(GV);
+ GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ cast<GlobalObject>(GV)->setComdat(nullptr);
+ }
}
}
// Common resolution: collect the maximum size/alignment over all commons.
diff --git a/llvm/test/LTO/Resolution/X86/Inputs/link-odr-availextern-odr.ll b/llvm/test/LTO/Resolution/X86/Inputs/link-odr-availextern-odr.ll
new file mode 100644
index 00000000000..76e745a444f
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/Inputs/link-odr-availextern-odr.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define linkonce_odr i32 @f() {
+ ret i32 2
+}
diff --git a/llvm/test/LTO/Resolution/X86/link-odr-availextern.ll b/llvm/test/LTO/Resolution/X86/link-odr-availextern.ll
index 4af79b64b2a..5a3cc3884db 100644
--- a/llvm/test/LTO/Resolution/X86/link-odr-availextern.ll
+++ b/llvm/test/LTO/Resolution/X86/link-odr-availextern.ll
@@ -3,16 +3,29 @@
; RUN: llvm-as %s -o %t1
; RUN: llvm-as %S/Inputs/link-odr-availextern-ae.ll -o %t2ae
+; RUN: llvm-as %S/Inputs/link-odr-availextern-odr.ll -o %t2odr
; RUN: llvm-lto2 -o %t3 %t1 %t2ae -r %t1,f,p -r %t2ae,f, -save-temps
; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=PREVAILING %s
+; RUN: llvm-lto2 -o %t3 %t1 %t2odr -r %t1,f,p -r %t2odr,f, -save-temps
+; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=PREVAILING %s
+
; RUN: llvm-lto2 -o %t3 %t2ae %t1 -r %t1,f,p -r %t2ae,f, -save-temps
; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=PREVAILING %s
+; RUN: llvm-lto2 -o %t3 %t2odr %t1 -r %t1,f,p -r %t2odr,f, -save-temps
+; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=PREVAILING %s
+
; RUN: llvm-lto2 -o %t3 %t2ae -r %t2ae,f, -save-temps
; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=NONPREVAILING %s
+; RUN: llvm-lto2 -o %t3 %t2odr -r %t2odr,f, -save-temps
+; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=NONPREVAILING %s
+
+; RUN: llvm-lto2 -o %t3 %t2odr %t1 -r %t1,f, -r %t2odr,f, -save-temps
+; RUN: llvm-dis < %t3.0.0.preopt.bc -o - | FileCheck --check-prefix=NONPREVAILING %s
+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
OpenPOWER on IntegriCloud