diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 31c2f13a63e5..5ede26cc7923 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -509,6 +509,10 @@ public: /// summary. The value is interpreted as 'ImportKind' enum defined above. unsigned ImportType : 1; + /// This symbol was promoted. Thinlink stages need to be aware of this + /// transition + unsigned Promoted : 1; + /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, GlobalValue::VisibilityTypes Visibility, @@ -517,7 +521,7 @@ public: : Linkage(Linkage), Visibility(Visibility), NotEligibleToImport(NotEligibleToImport), Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide), - ImportType(static_cast(ImportType)) {} + ImportType(static_cast(ImportType)), Promoted(false) {} }; private: @@ -584,12 +588,28 @@ public: return static_cast(Flags.Linkage); } + bool wasPromoted() const { return Flags.Promoted; } + + void promote() { + assert(GlobalValue::isLocalLinkage(linkage()) && + "unexpected (re-)promotion of non-local symbol"); + assert(!Flags.Promoted); + Flags.Promoted = true; + Flags.Linkage = GlobalValue::LinkageTypes::ExternalLinkage; + } + /// Sets the linkage to the value determined by global summary-based /// optimization. Will be applied in the ThinLTO backends. void setLinkage(GlobalValue::LinkageTypes Linkage) { + assert(!wasPromoted()); + assert(!GlobalValue::isExternalLinkage(Linkage) && "use `promote` instead"); Flags.Linkage = Linkage; } + void setExternalLinkageForTest() { + Flags.Linkage = GlobalValue::LinkageTypes::ExternalLinkage; + } + /// Return true if this global value can't be imported. bool notEligibleToImport() const { return Flags.NotEligibleToImport; } diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 749af6eda3fd..c88ec5e09396 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -393,6 +393,9 @@ static void thinLTOResolvePrevailingGUID( // FIXME: We may want to split the compile time and correctness // aspects into separate routines. if (isPrevailing(VI.getGUID(), S.get())) { + assert(!S->wasPromoted() && + "promoted symbols used to be internal linkage and shouldn't have " + "a prevailing variant"); if (GlobalValue::isLinkOnceLinkage(OriginalLinkage)) { S->setLinkage(GlobalValue::getWeakLinkage( GlobalValue::isLinkOnceODRLinkage(OriginalLinkage))); @@ -415,8 +418,11 @@ static void thinLTOResolvePrevailingGUID( // When force-import-all is used, it indicates that object linking is not // supported by the target. In this case, we can't change the linkage as // well in case the global is converted to declaration. + // Also, if the symbol was promoted, it wouldn't have a prevailing variant, + // but also its linkage is set correctly (to External) already. else if (!isa(S.get()) && - !GlobalInvolvedWithAlias.count(S.get()) && !ForceImportAll) + !GlobalInvolvedWithAlias.count(S.get()) && !ForceImportAll && + !S->wasPromoted()) S->setLinkage(GlobalValue::AvailableExternallyLinkage); // For ELF, set visibility to the computed visibility from summaries. We @@ -485,7 +491,7 @@ static void thinLTOInternalizeAndPromoteGUID( // exported. if (isExported(S->modulePath(), VI)) { if (GlobalValue::isLocalLinkage(S->linkage())) - S->setLinkage(GlobalValue::ExternalLinkage); + S->promote(); continue; } diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 855692db006f..626d28d4c50d 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -387,7 +387,7 @@ static FunctionSummary *calculatePrevailingSummary( } Local = FS; } else if (GlobalValue::isExternalLinkage(Linkage)) { - assert(IsPrevailing(VI.getGUID(), GVS.get())); + assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted()); Prevailing = FS; break; } else if (GlobalValue::isWeakODRLinkage(Linkage) || diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index 077ab72c15e1..4d4b32749a04 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -2106,7 +2106,7 @@ static bool doImportingForModuleForTest( for (auto &I : *Index) { for (auto &S : I.second.getSummaryList()) { if (GlobalValue::isLocalLinkage(S->linkage())) - S->setLinkage(GlobalValue::ExternalLinkage); + S->setExternalLinkageForTest(); } } diff --git a/llvm/test/ThinLTO/X86/Inputs/export2.ll b/llvm/test/ThinLTO/X86/Inputs/export2.ll new file mode 100644 index 000000000000..f70b21b2a567 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/export2.ll @@ -0,0 +1,9 @@ +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() { +entry: + call void @callstaticfunc() + ret i32 0 +} + +declare void @callstaticfunc() diff --git a/llvm/test/ThinLTO/X86/export2.ll b/llvm/test/ThinLTO/X86/export2.ll new file mode 100644 index 000000000000..7909543e68e6 --- /dev/null +++ b/llvm/test/ThinLTO/X86/export2.ll @@ -0,0 +1,27 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/export2.ll -o %t2.bc +; +; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t3 \ +; RUN: -thinlto-distributed-indexes \ +; RUN: -r=%t1.bc,callstaticfunc,px \ +; RUN: -r=%t2.bc,main,px \ +; RUN: -r=%t2.bc,callstaticfunc, + +; both functions must appear as external linkage in the index. +; RUN: llvm-dis %t1.bc.thinlto.bc -o - | FileCheck %s +; CHECK: linkage: external +; CHECK: linkage: external + +target triple = "x86_64-unknown-linux-gnu" + +define void @callstaticfunc() { +entry: + call void @staticfunc() + ret void +} + +define internal void @staticfunc() { +entry: + ret void +} diff --git a/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll index 2b2228f1158d..3080842c4010 100644 --- a/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll +++ b/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll @@ -27,7 +27,7 @@ define void @importer() { ; If somehow the caller doesn't get the attributes, we ; shouldn't propagate from the internal callee. -; CHECK: define void @importer_noattr() { +; CHECK: define void @importer_noattr() #0 { define void @importer_noattr() { call void @caller_noattr() ret void diff --git a/llvm/test/ThinLTO/X86/module_asm2.ll b/llvm/test/ThinLTO/X86/module_asm2.ll index 7ab7847f7943..8d4d19110541 100644 --- a/llvm/test/ThinLTO/X86/module_asm2.ll +++ b/llvm/test/ThinLTO/X86/module_asm2.ll @@ -9,7 +9,7 @@ ; RUN: llvm-nm %t2.bc.thinlto.o | FileCheck %s --check-prefix=NM1 ; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t.o -save-temps \ -; RUN: -r=%t1.bc,foo,plx \ +; RUN: -r=%t1.bc,foo,lx \ ; RUN: -r=%t1.bc,globalfunc,plx \ ; RUN: -r=%t1.bc,globalfunc,lx \ ; RUN: -r=%t1.bc,weakfunc,plx \ diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 33c3e6fc350f..f6fc41d750b5 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -422,7 +422,7 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L, for (auto &I : *Index) { for (auto &S : I.second.getSummaryList()) { if (GlobalValue::isLocalLinkage(S->linkage())) - S->setLinkage(GlobalValue::ExternalLinkage); + S->setExternalLinkageForTest(); } }