diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -468,24 +468,13 @@ if (!EnableLTOInternalization) continue; - // Ignore local and appending linkage values since the linker - // doesn't resolve them (and there is no need to internalize if this is - // already internal). - if (GlobalValue::isLocalLinkage(S->linkage()) || - S->linkage() == GlobalValue::AppendingLinkage) + // Non-exported objects with external linkage can be internalized. + if (GlobalValue::isExternalLinkage(S->linkage())) { + S->setLinkage(GlobalValue::InternalLinkage); continue; + } - // We can't internalize available_externally globals because this - // can break function pointer equality. - if (S->linkage() == GlobalValue::AvailableExternallyLinkage) - continue; - - bool IsPrevailing = isPrevailing(VI.getGUID(), S.get()); - - if (GlobalValue::isInterposableLinkage(S->linkage()) && !IsPrevailing) - continue; - - // Non-exported functions and variables with linkonce_odr or weak_odr + // Non-exported function and variable definitions with a weak-for-linker // linkage can be internalized in certain cases. The minimum legality // requirements would be that they are not address taken to ensure that we // don't break pointer equality checks, and that variables are either read- @@ -494,7 +483,7 @@ // (which is how this is guaranteed for variables, when analyzing whether // they are read or write-only). // - // However, we only get to this code for weak/linkonce ODR values in one of + // However, we only get to this code for weak-for-linkage values in one of // two cases: // 1) The prevailing copy is not in IR (it is in native code). // 2) The prevailing copy in IR is not exported from its module. @@ -506,10 +495,10 @@ // duplicate linkonce_odr copies as exported via the tool, so we need // to handle that case below by checking the number of copies. // - // Generally, we only want to internalize a linkonce/weak ODR value in case + // Generally, we only want to internalize a weak-for-linker value in case // 2, because in case 1 we cannot see how the value is used to know if it // is read or write-only. We also don't want to bloat the binary with - // multiple internalized copies of non-prevailing linkonce_odr functions. + // multiple internalized copies of non-prevailing linkonce/weak functions. // Note if we don't internalize, we will convert non-prevailing copies to // available_externally anyway, so that we drop them after inlining. The // only reason to internalize such a function is if we indeed have a single @@ -520,18 +509,16 @@ // already perform this elsewhere in the ThinLTO backend handling for // read or write-only variables (processGlobalForThinLTO). // - // Therefore, only internalize linkonce/weak ODR if there is a single copy, - // that is prevailing in this IR module. We can do so aggressively, without + // Therefore, only internalize linkonce/weak if there is a single copy, that + // is prevailing in this IR module. We can do so aggressively, without // requiring the address to be insignificant, or that a variable be read or // write-only. - if ((S->linkage() == GlobalValue::WeakODRLinkage || - S->linkage() == GlobalValue::LinkOnceODRLinkage) && - // We can have only one copy in ThinLTO that isn't prevailing, if the - // prevailing copy is in a native object. - (!IsPrevailing || ExternallyVisibleCopies > 1)) + if (!GlobalValue::isWeakForLinker(S->linkage()) || + GlobalValue::isExternalWeakLinkage(S->linkage())) continue; - S->setLinkage(GlobalValue::InternalLinkage); + if (isPrevailing(VI.getGUID(), S.get()) && ExternallyVisibleCopies == 1) + S->setLinkage(GlobalValue::InternalLinkage); } } diff --git a/llvm/test/ThinLTO/X86/weak_resolution.ll b/llvm/test/ThinLTO/X86/weak_resolution.ll --- a/llvm/test/ThinLTO/X86/weak_resolution.ll +++ b/llvm/test/ThinLTO/X86/weak_resolution.ll @@ -13,7 +13,7 @@ ; RUN: llvm-lto -thinlto-action=internalize %t.bc -thinlto-index=%t3.bc -exported-symbol=_linkoncefunc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD1-INT ; RUN: llvm-lto -thinlto-action=promote %t2.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD2 ; When exported, we always preserve a linkonce -; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - --exported-symbol=_linkonceodrfuncInSingleModule | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTED +; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - --exported-symbol=_linkonceodrfuncInSingleModule --exported-symbol=_weakfuncInSingleModule | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTED ;; Now try this with the new LTO API ; RUN: llvm-lto2 run %t.bc %t2.bc -o %t3.out -save-temps \ @@ -21,6 +21,7 @@ ; RUN: -r %t.bc,_linkoncealias,pl \ ; RUN: -r %t.bc,_linkonceodrvarInSingleModule,pl \ ; RUN: -r %t.bc,_weakodrvarInSingleModule,pl \ +; RUN: -r %t.bc,_weakvarInSingleModule,pl \ ; RUN: -r %t.bc,_linkonceodrfuncwithalias,pl \ ; RUN: -r %t.bc,_linkoncefuncwithalias,pl \ ; RUN: -r %t.bc,_linkonceodrfunc,pl \ @@ -28,6 +29,7 @@ ; RUN: -r %t.bc,_weakodrfunc,pl \ ; RUN: -r %t.bc,_weakfunc,pl \ ; RUN: -r %t.bc,_linkonceodrfuncInSingleModule,pl \ +; RUN: -r %t.bc,_weakfuncInSingleModule,pl \ ; RUN: -r %t2.bc,_linkonceodrfuncwithalias,l \ ; RUN: -r %t2.bc,_linkoncefuncwithalias,l \ ; RUN: -r %t2.bc,_linkonceodrfunc,l \ @@ -55,8 +57,10 @@ ;; of whether they are const or *unnamed_addr. ; MOD1-INT: @linkonceodrvarInSingleModule = internal global ; MOD1-INT: @weakodrvarInSingleModule = internal global +; MOD1-INT: @weakvarInSingleModule = internal global @linkonceodrvarInSingleModule = linkonce_odr dso_local global ptr null, align 8 @weakodrvarInSingleModule = weak_odr dso_local global ptr null, align 8 +@weakvarInSingleModule = weak dso_local global ptr null, align 8 ;; Function with an alias are resolved to weak_odr in prevailing module, but ;; not optimized in non-prevailing module (illegal to have an @@ -115,3 +119,11 @@ entry: ret void } + +; MOD1: define weak void @weakfuncInSingleModule() +; MOD1-INT: define internal void @weakfuncInSingleModule() +; EXPORTED: define weak void @weakfuncInSingleModule() +define weak void @weakfuncInSingleModule() { +entry: + ret void +}