Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -122,10 +122,11 @@ return true; } -static GlobalValue::LinkageTypes ResolveODR(const ModuleSummaryIndex &Index, - StringRef ModuleIdentifier, - GlobalValue::GUID GUID, - const GlobalValueSummary &GV) { +static GlobalValue::LinkageTypes +ResolveODR(const ModuleSummaryIndex &Index, + const FunctionImporter::ExportSetTy &ExportList, + StringRef ModuleIdentifier, GlobalValue::GUID GUID, + const GlobalValueSummary &GV) { auto HasMultipleCopies = [&](const GlobalValueInfoList &GVInfo) { return GVInfo.size() > 1; }; @@ -146,13 +147,19 @@ auto &GVInfo = Index.findGlobalValueInfoList(GUID)->second; // We need to emit only one of these, the first module will keep // it, but turned into a weak while the others will drop it. - if (!HasMultipleCopies(GVInfo)) + if (!HasMultipleCopies(GVInfo)) { + // Exported LinkonceODR needs to be promoted to not be discarded + if (GlobalValue::isDiscardableIfUnused(OriginalLinkage) && + ExportList.count(GUID)) + return GlobalValue::WeakODRLinkage; break; + } if (IsFirstDefinitionForLinker(GVInfo, Index, ModuleIdentifier)) return GlobalValue::WeakODRLinkage; - else - return GlobalValue::AvailableExternallyLinkage; - break; + else if (isa(&GV)) + // Alias can't be turned into available_externally. + return OriginalLinkage; + return GlobalValue::AvailableExternallyLinkage; } } return OriginalLinkage; @@ -166,6 +173,7 @@ /// one copy. static void ResolveODR( const ModuleSummaryIndex &Index, + const FunctionImporter::ExportSetTy &ExportList, const std::map &DefinedGlobals, StringRef ModuleIdentifier, DenseMap &ResolvedODR) { @@ -185,7 +193,8 @@ for (auto &GV : DefinedGlobals) { if (GlobalInvolvedWithAlias.count(GV.second)) continue; - auto NewLinkage = ResolveODR(Index, ModuleIdentifier, GV.first, *GV.second); + auto NewLinkage = + ResolveODR(Index, ExportList, ModuleIdentifier, GV.first, *GV.second); if (NewLinkage != GV.second->linkage()) { ResolvedODR[GV.first] = NewLinkage; } @@ -213,6 +222,14 @@ << GV.getLinkage() << " to " << NewLinkage->second << "\n"); GV.setLinkage(NewLinkage->second); } + for (auto &GV : TheModule.aliases()) { + auto NewLinkage = ResolvedODR.find(GV.getGUID()); + if (NewLinkage == ResolvedODR.end()) + continue; + DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from " + << GV.getLinkage() << " to " << NewLinkage->second << "\n"); + GV.setLinkage(NewLinkage->second); + } } static StringMap @@ -453,17 +470,25 @@ */ void ThinLTOCodeGenerator::promote(Module &TheModule, ModuleSummaryIndex &Index) { + auto ModuleCount = Index.modulePaths().size(); auto ModuleIdentifier = TheModule.getModuleIdentifier(); // Collect for each module the list of function it defines (GUID -> Summary). StringMap> ModuleToDefinedGVSummaries; Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + // Generate import/export list + StringMap ImportLists(ModuleCount); + StringMap ExportLists(ModuleCount); + ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, + ExportLists); + auto &ExportList = ExportLists[ModuleIdentifier]; + // Resolve the LinkOnceODR, trying to turn them into "available_externally" // where possible. // This is a compile-time optimization. DenseMap ResolvedODR; - ResolveODR(Index, ModuleToDefinedGVSummaries[ModuleIdentifier], + ResolveODR(Index, ExportList, ModuleToDefinedGVSummaries[ModuleIdentifier], ModuleIdentifier, ResolvedODR); fixupODR(TheModule, ResolvedODR); @@ -577,9 +602,11 @@ Context.setDiscardValueNames(LTODiscardValueNames); Context.enableDebugTypeODRUniquing(); auto ModuleIdentifier = ModuleBuffer.getBufferIdentifier(); + auto &ExportList = ExportLists[ModuleIdentifier]; DenseMap ResolvedODR; - ResolveODR(*Index, ModuleToDefinedGVSummaries[ModuleIdentifier], + ResolveODR(*Index, ExportList, + ModuleToDefinedGVSummaries[ModuleIdentifier], ModuleIdentifier, ResolvedODR); // Parse module now Index: test/ThinLTO/X86/odr_resolution.ll =================================================================== --- test/ThinLTO/X86/odr_resolution.ll +++ test/ThinLTO/X86/odr_resolution.ll @@ -10,8 +10,9 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" -; Alias are not optimized -; MOD1: @linkoncealias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias +; Alias are resolved like functions are: we select one "weak_odr". +; MOD1: @linkoncealias = weak_odr alias void (), void ()* @linkonceodrfuncwithalias +; This one wasn't selected, but aliases can't be turned into "available_externally" ; MOD2: @linkoncealias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias @linkoncealias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias