Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -730,6 +730,11 @@ } bool isGUIDLive(GlobalValue::GUID GUID) const; + bool canGlobalValueAutoHide(const GlobalValue *GV) const { + return canGUIDAutoHide(GV->getGUID()); + } + bool canGUIDAutoHide(GlobalValue::GUID GUID) const; + /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo(). ValueInfo getValueInfo(GlobalValue::GUID GUID) const { auto I = GlobalValueMap.find(GUID); Index: include/llvm/LTO/LTO.h =================================================================== --- include/llvm/LTO/LTO.h +++ include/llvm/LTO/LTO.h @@ -52,7 +52,8 @@ function_ref isPrevailing, function_ref - recordNewLinkage); + recordNewLinkage, + function_ref recordAutoHide); /// Update the linkages in the given \p Index to mark exported values /// as external and non-exported values as internal. The ThinLTO backends Index: include/llvm/LTO/LTOBackend.h =================================================================== --- include/llvm/LTO/LTOBackend.h +++ include/llvm/LTO/LTOBackend.h @@ -45,7 +45,8 @@ const ModuleSummaryIndex &CombinedIndex, const FunctionImporter::ImportMapTy &ImportList, const GVSummaryMapTy &DefinedGlobals, - MapVector &ModuleMap); + MapVector &ModuleMap, + const DenseSet &AutoHideCandidates); } } Index: include/llvm/Transforms/IPO/FunctionImport.h =================================================================== --- include/llvm/Transforms/IPO/FunctionImport.h +++ include/llvm/Transforms/IPO/FunctionImport.h @@ -149,8 +149,9 @@ /// Resolve WeakForLinker values in \p TheModule based on the information /// recorded in the summaries during global summary-based analysis. -void thinLTOResolveWeakForLinkerModule(Module &TheModule, - const GVSummaryMapTy &DefinedGlobals); +void thinLTOResolveWeakForLinkerModule( + Module &TheModule, const GVSummaryMapTy &DefinedGlobals, + const DenseSet &AutoHideCandidates); /// Internalize \p TheModule based on the information recorded in the summaries /// during global summary-based analysis. Index: lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- lib/Analysis/ModuleSummaryAnalysis.cpp +++ lib/Analysis/ModuleSummaryAnalysis.cpp @@ -324,9 +324,10 @@ F.isVarArg() || // Don't try to import functions with noinline attribute. F.getAttributes().hasFnAttribute(Attribute::NoInline); - GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport, - /* Live = */ false, F.isDSOLocal(), - /* UnnamedAddr= */false); + GlobalValueSummary::GVFlags Flags( + F.getLinkage(), NotEligibleForImport, + /* Live = */ false, F.isDSOLocal(), + /* UnnamedAddr= */ F.hasAtLeastLocalUnnamedAddr()); FunctionSummary::FFlags FunFlags{ F.hasFnAttribute(Attribute::ReadNone), F.hasFnAttribute(Attribute::ReadOnly), @@ -351,9 +352,10 @@ SmallPtrSet Visited; findRefEdges(Index, &V, RefEdges, Visited); bool NonRenamableLocal = isNonRenamableLocal(V); - GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, - /* Live = */ false, V.isDSOLocal(), - /* UnnamedAddr= */false); + GlobalValueSummary::GVFlags Flags( + V.getLinkage(), NonRenamableLocal, + /* Live = */ false, V.isDSOLocal(), + /* UnnamedAddr= */ V.hasAtLeastLocalUnnamedAddr()); auto GVarSummary = llvm::make_unique(Flags, RefEdges.takeVector()); if (NonRenamableLocal) @@ -365,9 +367,10 @@ computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, DenseSet &CantBePromoted) { bool NonRenamableLocal = isNonRenamableLocal(A); - GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal, - /* Live = */ false, A.isDSOLocal(), - /* UnnamedAddr= */false); + GlobalValueSummary::GVFlags Flags( + A.getLinkage(), NonRenamableLocal, + /* Live = */ false, A.isDSOLocal(), + /* UnnamedAddr= */ A.hasAtLeastLocalUnnamedAddr()); auto AS = llvm::make_unique(Flags); auto *Aliasee = A.getBaseObject(); auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee); @@ -433,11 +436,12 @@ if (!GV) return; assert(GV->isDeclaration() && "Def in module asm already has definition"); - GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage, - /* NotEligibleToImport = */ true, - /* Live = */ true, - /* Local */ GV->isDSOLocal(), - /* UnnamedAddr= */ false); + GlobalValueSummary::GVFlags GVFlags( + GlobalValue::InternalLinkage, + /* NotEligibleToImport = */ true, + /* Live = */ true, + /* Local */ GV->isDSOLocal(), + /* UnnamedAddr= */ GV->hasAtLeastLocalUnnamedAddr()); CantBePromoted.insert(GlobalValue::getGUID(Name)); // Create the appropriate summary type. if (Function *F = dyn_cast(GV)) { Index: lib/IR/ModuleSummaryIndex.cpp =================================================================== --- lib/IR/ModuleSummaryIndex.cpp +++ lib/IR/ModuleSummaryIndex.cpp @@ -80,6 +80,20 @@ return false; } +bool ModuleSummaryIndex::canGUIDAutoHide(GlobalValue::GUID GUID) const { + auto VI = getValueInfo(GUID); + if (!VI) + return false; + const auto &SummaryList = VI.getSummaryList(); + if (SummaryList.empty()) + return false; + bool canBeAutoHide = true; + for (auto &I : SummaryList) + canBeAutoHide &= I->flags().UnnamedAddr && + I->linkage() == GlobalValue::LinkOnceODRLinkage; + return canBeAutoHide; +} + namespace { struct Attributes { void add(const Twine &Name, const Twine &Value, Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -315,7 +315,8 @@ function_ref isPrevailing, function_ref - recordNewLinkage) { + recordNewLinkage, + function_ref recordAutoHide) { // We won't optimize the globals that are referenced by an alias for now // Ideally we should turn the alias into a global and duplicate the definition // when needed. @@ -325,6 +326,13 @@ if (auto AS = dyn_cast(S.get())) GlobalInvolvedWithAlias.insert(&AS->getAliasee()); + // Record the symbols that can be auto hide. This needs to be completed + // before resolve linkage. + for (auto &I : Index) { + if (Index.canGUIDAutoHide(I.first)) + recordAutoHide(I.first); + } + for (auto &I : Index) thinLTOResolveWeakForLinkerGUID(I.second.SummaryList, I.first, GlobalInvolvedWithAlias, isPrevailing, @@ -876,7 +884,8 @@ const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map &ResolvedODR, - MapVector &ModuleMap) = 0; + MapVector &ModuleMap, + const DenseSet &AutoHideCandidates) = 0; virtual Error wait() = 0; }; @@ -923,7 +932,8 @@ const std::map &ResolvedODR, const GVSummaryMapTy &DefinedGlobals, MapVector &ModuleMap, - const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) { + const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid, + const DenseSet &AutoHideCandidates) { auto RunThinBackend = [&](AddStreamFn AddStream) { LTOLLVMContext BackendContext(Conf); Expected> MOrErr = BM.parseModule(BackendContext); @@ -931,7 +941,8 @@ return MOrErr.takeError(); return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex, - ImportList, DefinedGlobals, ModuleMap); + ImportList, DefinedGlobals, ModuleMap, + AutoHideCandidates); }; auto ModuleID = BM.getModuleIdentifier(); @@ -959,7 +970,8 @@ const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map &ResolvedODR, - MapVector &ModuleMap) override { + MapVector &ModuleMap, + const DenseSet &AutoHideCandidates) override { StringRef ModulePath = BM.getModuleIdentifier(); assert(ModuleToDefinedGVSummaries.count(ModulePath)); const GVSummaryMapTy &DefinedGlobals = @@ -975,7 +987,8 @@ const TypeIdSummariesByGuidTy &TypeIdSummariesByGuid) { Error E = runThinLTOBackendThread( AddStream, Cache, Task, BM, CombinedIndex, ImportList, ExportList, - ResolvedODR, DefinedGlobals, ModuleMap, TypeIdSummariesByGuid); + ResolvedODR, DefinedGlobals, ModuleMap, TypeIdSummariesByGuid, + AutoHideCandidates); if (E) { std::unique_lock L(ErrMu); if (Err) @@ -1056,7 +1069,8 @@ const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map &ResolvedODR, - MapVector &ModuleMap) override { + MapVector &ModuleMap, + const DenseSet &AutoHideCandidates) override { StringRef ModulePath = BM.getModuleIdentifier(); std::string NewModulePath = getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix); @@ -1186,8 +1200,13 @@ GlobalValue::LinkageTypes NewLinkage) { ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; + DenseSet AutoHideCandidates; + auto recordAutoHide = [&](GlobalValue::GUID GUID) { + AutoHideCandidates.insert(GUID); + }; + thinLTOResolveWeakForLinkerInIndex(ThinLTO.CombinedIndex, isPrevailing, - recordNewLinkage); + recordNewLinkage, recordAutoHide); std::unique_ptr BackendProc = ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, @@ -1197,9 +1216,9 @@ // module and parallel code generation partitions. unsigned Task = RegularLTO.ParallelCodeGenParallelismLevel; for (auto &Mod : ThinLTO.ModuleMap) { - if (Error E = BackendProc->start(Task, Mod.second, ImportLists[Mod.first], - ExportLists[Mod.first], - ResolvedODR[Mod.first], ThinLTO.ModuleMap)) + if (Error E = BackendProc->start( + Task, Mod.second, ImportLists[Mod.first], ExportLists[Mod.first], + ResolvedODR[Mod.first], ThinLTO.ModuleMap, AutoHideCandidates)) return E; ++Task; } Index: lib/LTO/LTOBackend.cpp =================================================================== --- lib/LTO/LTOBackend.cpp +++ lib/LTO/LTOBackend.cpp @@ -424,7 +424,8 @@ Module &Mod, const ModuleSummaryIndex &CombinedIndex, const FunctionImporter::ImportMapTy &ImportList, const GVSummaryMapTy &DefinedGlobals, - MapVector &ModuleMap) { + MapVector &ModuleMap, + const DenseSet &AutoHideCandidates) { Expected TOrErr = initAndLookupTarget(Conf, Mod); if (!TOrErr) return TOrErr.takeError(); @@ -443,7 +444,7 @@ dropDeadSymbols(Mod, DefinedGlobals, CombinedIndex); - thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); + thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals, AutoHideCandidates); if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod)) return Error::success(); Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -430,6 +430,7 @@ const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const DenseSet &GUIDPreservedSymbols, + const DenseSet &AutoHideCandidates, const GVSummaryMapTy &DefinedGlobals, const ThinLTOCodeGenerator::CachingOptions &CacheOptions, bool DisableCodeGen, StringRef SaveTempsDir, @@ -442,7 +443,8 @@ promoteModule(TheModule, Index); // Apply summary-based LinkOnce/Weak resolution decisions. - thinLTOResolveWeakForLinkerModule(TheModule, DefinedGlobals); + thinLTOResolveWeakForLinkerModule(TheModule, DefinedGlobals, + AutoHideCandidates); // Save temps: after promotion. saveTempBitcode(TheModule, SaveTempsDir, count, ".1.promoted.bc"); @@ -492,8 +494,8 @@ static void resolveWeakForLinkerInIndex( ModuleSummaryIndex &Index, StringMap> - &ResolvedODR) { - + &ResolvedODR, + DenseSet &AutoHideCandidates) { DenseMap PrevailingCopy; computePrevailingCopies(Index, PrevailingCopy); @@ -511,7 +513,12 @@ ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; }; - thinLTOResolveWeakForLinkerInIndex(Index, isPrevailing, recordNewLinkage); + auto recordAutoHide = [&](GlobalValue::GUID GUID) { + AutoHideCandidates.insert(GUID); + }; + + thinLTOResolveWeakForLinkerInIndex(Index, isPrevailing, recordNewLinkage, + recordAutoHide); } // Initialize the TargetMachine builder for a given Triple @@ -661,10 +668,12 @@ // Resolve LinkOnce/Weak symbols. StringMap> ResolvedODR; - resolveWeakForLinkerInIndex(Index, ResolvedODR); + DenseSet AutoHideCandidates; + resolveWeakForLinkerInIndex(Index, ResolvedODR, AutoHideCandidates); thinLTOResolveWeakForLinkerModule( - TheModule, ModuleToDefinedGVSummaries[ModuleIdentifier]); + TheModule, ModuleToDefinedGVSummaries[ModuleIdentifier], + AutoHideCandidates); // Promote the exported values in the index, so that they are promoted // in the module. @@ -930,7 +939,8 @@ // Resolve LinkOnce/Weak symbols, this has to be computed early because it // impacts the caching. - resolveWeakForLinkerInIndex(*Index, ResolvedODR); + DenseSet AutoHideCandidates; + resolveWeakForLinkerInIndex(*Index, ResolvedODR, AutoHideCandidates); // Use global summary-based analysis to identify symbols that can be // internalized (because they aren't exported or preserved as per callback). @@ -1017,7 +1027,7 @@ // Run the main process now, and generates a binary auto OutputBuffer = ProcessThinLTOModule( *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList, - ExportList, GUIDPreservedSymbols, + ExportList, GUIDPreservedSymbols, AutoHideCandidates, ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions, DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count); Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -646,7 +646,8 @@ /// Fixup WeakForLinker linkages in \p TheModule based on summary analysis. void llvm::thinLTOResolveWeakForLinkerModule( - Module &TheModule, const GVSummaryMapTy &DefinedGlobals) { + Module &TheModule, const GVSummaryMapTy &DefinedGlobals, + const DenseSet &AutoHideCandidates) { auto updateLinkage = [&](GlobalValue &GV) { // See if the global summary analysis computed a new resolved linkage. const auto &GS = DefinedGlobals.find(GV.getGUID()); @@ -683,11 +684,12 @@ // changed to enable this for aliases. llvm_unreachable("Expected GV to be converted"); } else { - // If the original symbols has global unnamed addr and linkonce_odr linkage, - // it should be an auto hide symbol. Add hidden visibility to the symbol to - // preserve the property. - if (GV.hasLinkOnceODRLinkage() && GV.hasGlobalUnnamedAddr() && - NewLinkage == GlobalValue::WeakODRLinkage) + // If linkonce_odr symbols are promoted to weak_odr, make sure we don't + // lose the auto hide property. If linkonce_odr symbols has unnamed_addr + // or it is a candidate of auto hide, add hidden visibility to the symbol. + if ((GV.hasLinkOnceODRLinkage() && + NewLinkage == GlobalValue::WeakODRLinkage) && // Is promote to weak. + (GV.hasGlobalUnnamedAddr() || AutoHideCandidates.count(GV.getGUID()))) GV.setVisibility(GlobalValue::HiddenVisibility); DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from " Index: test/ThinLTO/X86/Inputs/linkonce_odr_unnamed_addr.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/Inputs/linkonce_odr_unnamed_addr.ll @@ -0,0 +1,7 @@ +@linkonceodrunnamed = linkonce_odr unnamed_addr constant i32 0 + +@linkonceodrunnamed_local = linkonce_odr local_unnamed_addr constant i32 0 + +@linkonceodrunnamed_m = linkonce_odr constant i32 0 + +@linkonceodrunnamed_n = linkonce_odr unnamed_addr constant i32 0 Index: test/ThinLTO/X86/linkonce_odr_unnamed_addr.ll =================================================================== --- test/ThinLTO/X86/linkonce_odr_unnamed_addr.ll +++ test/ThinLTO/X86/linkonce_odr_unnamed_addr.ll @@ -2,9 +2,18 @@ ; weak symbols, it preserves the auto hide property. ; RUN: opt -module-summary %s -o %t.bc -; RUN: opt -module-summary %s -o %t2.bc +; RUN: opt -module-summary %p/Inputs/linkonce_odr_unnamed_addr.ll -o %t2.bc ; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc ; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s ; CHECK: @linkonceodrunnamed = weak_odr hidden unnamed_addr constant i32 0 @linkonceodrunnamed = linkonce_odr unnamed_addr constant i32 0 + +; CHECK: @linkonceodrunnamed_local = weak_odr hidden local_unnamed_addr constant i32 0 +@linkonceodrunnamed_local = linkonce_odr local_unnamed_addr constant i32 0 + +; CHECK: @linkonceodrunnamed_m = weak_odr local_unnamed_addr constant i32 0 +@linkonceodrunnamed_m = linkonce_odr local_unnamed_addr constant i32 0 + +; CHECK: @linkonceodrunnamed_n = weak_odr hidden local_unnamed_addr constant i32 0 +@linkonceodrunnamed_n = linkonce_odr local_unnamed_addr constant i32 0