diff options
author | Mehdi Amini <mehdi.amini@apple.com> | 2016-04-21 05:47:17 +0000 |
---|---|---|
committer | Mehdi Amini <mehdi.amini@apple.com> | 2016-04-21 05:47:17 +0000 |
commit | 5d79e77524667c8f6a7402fb8c443fb1ca954777 (patch) | |
tree | 1a6425dd0f18c1cae4a3db560a61b167937c8137 | |
parent | 84a84a172346b2f67cad36f520bcf430c44fb511 (diff) |
ThinLTO: Resolve linkonce_odr aliases just like functions
This help to streamline the process of handling importing since
we don't need to special case alias everywhere: just like
linkonce_odr function, make sure at least one alias is emitted
by turning it weak.
Differential Revision: http://reviews.llvm.org/D19308
From: Mehdi Amini <mehdi.amini@apple.com>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266958 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/LTO/ThinLTOCodeGenerator.cpp | 49 | ||||
-rw-r--r-- | test/ThinLTO/X86/Inputs/alias_import.ll | 64 | ||||
-rw-r--r-- | test/ThinLTO/X86/Inputs/alias_resolution.ll | 64 | ||||
-rw-r--r-- | test/ThinLTO/X86/alias_import.ll | 168 | ||||
-rw-r--r-- | test/ThinLTO/X86/alias_resolution.ll | 82 | ||||
-rw-r--r-- | test/ThinLTO/X86/odr_resolution.ll | 4 |
6 files changed, 418 insertions, 13 deletions
diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp index 271520e4dd3..ee219799458 100644 --- a/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/lib/LTO/ThinLTOCodeGenerator.cpp @@ -122,10 +122,11 @@ bool IsFirstDefinitionForLinker(const GlobalValueInfoList &GVInfo, 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 @@ static GlobalValue::LinkageTypes ResolveODR(const ModuleSummaryIndex &Index, 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<AliasSummary>(&GV)) + // Alias can't be turned into available_externally. + return OriginalLinkage; + return GlobalValue::AvailableExternallyLinkage; } } return OriginalLinkage; @@ -166,6 +173,7 @@ static GlobalValue::LinkageTypes ResolveODR(const ModuleSummaryIndex &Index, /// one copy. static void ResolveODR( const ModuleSummaryIndex &Index, + const FunctionImporter::ExportSetTy &ExportList, const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGlobals, StringRef ModuleIdentifier, DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR) { @@ -185,7 +193,8 @@ static void ResolveODR( 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 @@ void fixupODR( << 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<MemoryBufferRef> @@ -453,17 +470,25 @@ std::unique_ptr<ModuleSummaryIndex> ThinLTOCodeGenerator::linkCombinedIndex() { */ 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<std::map<GlobalValue::GUID, GlobalValueSummary *>> ModuleToDefinedGVSummaries; Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + // Generate import/export list + StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount); + StringMap<FunctionImporter::ExportSetTy> 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<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR; - ResolveODR(Index, ModuleToDefinedGVSummaries[ModuleIdentifier], + ResolveODR(Index, ExportList, ModuleToDefinedGVSummaries[ModuleIdentifier], ModuleIdentifier, ResolvedODR); fixupODR(TheModule, ResolvedODR); @@ -577,9 +602,11 @@ void ThinLTOCodeGenerator::run() { Context.setDiscardValueNames(LTODiscardValueNames); Context.enableDebugTypeODRUniquing(); auto ModuleIdentifier = ModuleBuffer.getBufferIdentifier(); + auto &ExportList = ExportLists[ModuleIdentifier]; DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR; - ResolveODR(*Index, ModuleToDefinedGVSummaries[ModuleIdentifier], + ResolveODR(*Index, ExportList, + ModuleToDefinedGVSummaries[ModuleIdentifier], ModuleIdentifier, ResolvedODR); // Parse module now diff --git a/test/ThinLTO/X86/Inputs/alias_import.ll b/test/ThinLTO/X86/Inputs/alias_import.ll new file mode 100644 index 00000000000..36e5ad1e91e --- /dev/null +++ b/test/ThinLTO/X86/Inputs/alias_import.ll @@ -0,0 +1,64 @@ + + + + +@globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +define void @globalfunc() { +entry: + ret void +} + +@internalfuncAlias = alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncWeakAlias = weak alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @internalfunc to void (...)*) +define internal void @internalfunc() { +entry: + ret void +} + +@linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +define linkonce_odr void @linkonceODRfunc() { +entry: + ret void +} + +@weakODRfuncAlias = alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +define weak_odr void @weakODRfunc() { +entry: + ret void +} + +@linkoncefuncAlias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncWeakAlias = weak alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +define linkonce void @linkoncefunc() { +entry: + ret void +} + +@weakfuncAlias = alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +define weak void @weakfunc() { +entry: + ret void +} + diff --git a/test/ThinLTO/X86/Inputs/alias_resolution.ll b/test/ThinLTO/X86/Inputs/alias_resolution.ll new file mode 100644 index 00000000000..36e5ad1e91e --- /dev/null +++ b/test/ThinLTO/X86/Inputs/alias_resolution.ll @@ -0,0 +1,64 @@ + + + + +@globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +@globalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +define void @globalfunc() { +entry: + ret void +} + +@internalfuncAlias = alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncWeakAlias = weak alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @internalfunc to void (...)*) +@internalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @internalfunc to void (...)*) +define internal void @internalfunc() { +entry: + ret void +} + +@linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +@linkonceODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +define linkonce_odr void @linkonceODRfunc() { +entry: + ret void +} + +@weakODRfuncAlias = alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +@weakODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +define weak_odr void @weakODRfunc() { +entry: + ret void +} + +@linkoncefuncAlias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncWeakAlias = weak alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +@linkoncefuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +define linkonce void @linkoncefunc() { +entry: + ret void +} + +@weakfuncAlias = alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +@weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +define weak void @weakfunc() { +entry: + ret void +} + diff --git a/test/ThinLTO/X86/alias_import.ll b/test/ThinLTO/X86/alias_import.ll new file mode 100644 index 00000000000..6ba0da0d765 --- /dev/null +++ b/test/ThinLTO/X86/alias_import.ll @@ -0,0 +1,168 @@ +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/alias_import.ll -o %t2.bc +; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc +; RUN: llvm-lto -thinlto-action=promote -thinlto-index %t.index.bc %t2.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=PROMOTE +; RUN: llvm-lto -thinlto-action=import -thinlto-index %t.index.bc %t1.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORT + +; +; Alias can't point to "available_externally", so we can only import an alias +; when we can import the aliasee with a linkage that won't be +; available_externally, i.e linkOnceODR. (FIXME this limitation could be lifted) +; PROMOTE-DAG: @globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*) +; PROMOTE-DAG: @globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*) +; PROMOTE-DAG: @globalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @globalfunc to void (...)*) +; PROMOTE-DAG: @globalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +; PROMOTE-DAG: @globalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @globalfunc to void (...)*) +; PROMOTE-DAG: @internalfuncAlias = alias void (...), bitcast (void ()* @internalfunc.llvm.0 to void (...)*) +; PROMOTE-DAG: @internalfuncWeakAlias = weak alias void (...), bitcast (void ()* @internalfunc.llvm.0 to void (...)*) +; PROMOTE-DAG: @internalfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @internalfunc.llvm.0 to void (...)*) +; PROMOTE-DAG: @internalfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @internalfunc.llvm.0 to void (...)*) +; PROMOTE-DAG: @internalfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @internalfunc.llvm.0 to void (...)*) +; PROMOTE-DAG: @linkoncefuncAlias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE-DAG: @linkoncefuncWeakAlias = weak alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE-DAG: @linkoncefuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE-DAG: @linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE-DAG: @linkoncefuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE-DAG: @weakfuncAlias = alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE-DAG: @weakfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE-DAG: @weakfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE-DAG: @weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE-DAG: @weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE-DAG: @weakODRfuncAlias = alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +; PROMOTE-DAG: @weakODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +; PROMOTE-DAG: @weakODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +; PROMOTE-DAG: @weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +; PROMOTE-DAG: @weakODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) + +; Only alias to LinkonceODR aliasee can be imported +; PROMOTE-DAG: @linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; PROMOTE-DAG: @linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; PROMOTE-DAG: @linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; Amongst these that are imported, check that we promote only linkonce->weak +; PROMOTE-DAG: @linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; PROMOTE-DAG: @linkonceODRfuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) + +; These will be imported, check the linkage/renaming after promotion +; PROMOTE-DAG: define void @globalfunc() +; PROMOTE-DAG: define hidden void @internalfunc.llvm.0() +; PROMOTE-DAG: define linkonce_odr void @linkonceODRfunc() +; PROMOTE-DAG: define weak_odr void @weakODRfunc() +; PROMOTE-DAG: define linkonce void @linkoncefunc() +; PROMOTE-DAG: define weak void @weakfunc() + +; On the import side now, verify that aliases to a linkonce_odr are imported, but the weak (never import weak) +; IMPORT-DAG: declare void @linkonceODRfuncWeakAlias +; IMPORT-DAG: @linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; IMPORT-DAG: @linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; IMPORT-DAG: @linkonceODRfuncWeakODRAlias = alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; IMPORT-DAG: @linkonceODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; IMPORT-DAG: define linkonce_odr void @linkonceODRfunc() + + +; On the import side, these aliases are not imported (they don't point to a linkonce_odr) +; IMPORT-DAG: declare void @globalfuncAlias() +; IMPORT-DAG: declare void @globalfuncWeakAlias() +; IMPORT-DAG: declare void @globalfuncLinkonceAlias() +; IMPORT-DAG: declare void @globalfuncWeakODRAlias() +; IMPORT-DAG: declare void @globalfuncLinkonceODRAlias() +; IMPORT-DAG: declare void @internalfuncAlias() +; IMPORT-DAG: declare void @internalfuncWeakAlias() +; IMPORT-DAG: declare void @internalfuncLinkonceAlias() +; IMPORT-DAG: declare void @internalfuncWeakODRAlias() +; IMPORT-DAG: declare void @internalfuncLinkonceODRAlias() +; IMPORT-DAG: declare void @weakODRfuncAlias() +; IMPORT-DAG: declare void @weakODRfuncWeakAlias() +; IMPORT-DAG: declare void @weakODRfuncLinkonceAlias() +; IMPORT-DAG: declare void @weakODRfuncWeakODRAlias() +; IMPORT-DAG: declare void @weakODRfuncLinkonceODRAlias() +; IMPORT-DAG: declare void @linkoncefuncAlias() +; IMPORT-DAG: declare void @linkoncefuncWeakAlias() +; IMPORT-DAG: declare void @linkoncefuncLinkonceAlias() +; IMPORT-DAG: declare void @linkoncefuncWeakODRAlias() +; IMPORT-DAG: declare void @linkoncefuncLinkonceODRAlias() +; IMPORT-DAG: declare void @weakfuncAlias() +; IMPORT-DAG: declare void @weakfuncWeakAlias() +; IMPORT-DAG: declare void @weakfuncLinkonceAlias() +; IMPORT-DAG: declare void @weakfuncWeakODRAlias() +; IMPORT-DAG: declare void @weakfuncLinkonceODRAlias() + + + +define i32 @main() #0 { +entry: + call void @globalfuncAlias() + call void @globalfuncWeakAlias() + call void @globalfuncLinkonceAlias() + call void @globalfuncWeakODRAlias() + call void @globalfuncLinkonceODRAlias() + + call void @internalfuncAlias() + call void @internalfuncWeakAlias() + call void @internalfuncLinkonceAlias() + call void @internalfuncWeakODRAlias() + call void @internalfuncLinkonceODRAlias() + call void @linkonceODRfuncAlias() + call void @linkonceODRfuncWeakAlias() + call void @linkonceODRfuncLinkonceAlias() + call void @linkonceODRfuncWeakODRAlias() + call void @linkonceODRfuncLinkonceODRAlias() + + call void @weakODRfuncAlias() + call void @weakODRfuncWeakAlias() + call void @weakODRfuncLinkonceAlias() + call void @weakODRfuncWeakODRAlias() + call void @weakODRfuncLinkonceODRAlias() + + call void @linkoncefuncAlias() + call void @linkoncefuncWeakAlias() + call void @linkoncefuncLinkonceAlias() + call void @linkoncefuncWeakODRAlias() + call void @linkoncefuncLinkonceODRAlias() + + call void @weakfuncAlias() + call void @weakfuncWeakAlias() + call void @weakfuncLinkonceAlias() + call void @weakfuncWeakODRAlias() + call void @weakfuncLinkonceODRAlias() + + ret i32 0 +} + + +declare void @globalfuncAlias() +declare void @globalfuncWeakAlias() +declare void @globalfuncLinkonceAlias() +declare void @globalfuncWeakODRAlias() +declare void @globalfuncLinkonceODRAlias() + +declare void @internalfuncAlias() +declare void @internalfuncWeakAlias() +declare void @internalfuncLinkonceAlias() +declare void @internalfuncWeakODRAlias() +declare void @internalfuncLinkonceODRAlias() + +declare void @linkonceODRfuncAlias() +declare void @linkonceODRfuncWeakAlias() +declare void @linkonceODRfuncLinkonceAlias() +declare void @linkonceODRfuncWeakODRAlias() +declare void @linkonceODRfuncLinkonceODRAlias() + +declare void @weakODRfuncAlias() +declare void @weakODRfuncWeakAlias() +declare void @weakODRfuncLinkonceAlias() +declare void @weakODRfuncWeakODRAlias() +declare void @weakODRfuncLinkonceODRAlias() + +declare void @linkoncefuncAlias() +declare void @linkoncefuncWeakAlias() +declare void @linkoncefuncLinkonceAlias() +declare void @linkoncefuncWeakODRAlias() +declare void @linkoncefuncLinkonceODRAlias() + +declare void @weakfuncAlias() +declare void @weakfuncWeakAlias() +declare void @weakfuncLinkonceAlias() +declare void @weakfuncWeakODRAlias() +declare void @weakfuncLinkonceODRAlias() + + diff --git a/test/ThinLTO/X86/alias_resolution.ll b/test/ThinLTO/X86/alias_resolution.ll new file mode 100644 index 00000000000..29a01ff9008 --- /dev/null +++ b/test/ThinLTO/X86/alias_resolution.ll @@ -0,0 +1,82 @@ +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/alias_resolution.ll -o %t2.bc +; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc +; RUN: llvm-lto -thinlto-action=promote -thinlto-index %t.index.bc %t2.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=PROMOTE_MOD2 --check-prefix=NOTPROMOTED +; RUN: llvm-lto -thinlto-action=promote -thinlto-index %t.index.bc %t1.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=PROMOTE --check-prefix=NOTPROMOTED + +; There is no importing going on with this IR, but let's check the ODR resolution for compile time + +; NOTPROMOTED: @linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc{{.*}} to void (...)*) +; NOTPROMOTED: @linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc{{.*}} to void (...)*) +; NOTPROMOTED: @linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc{{.*}} to void (...)*) +; PROMOTE_MOD1: @linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) +; PROMOTE_MOD1: @linkonceODRfuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @linkonceODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkonceODRfunc to void (...)*) + +; NOTPROMOTED: @weakODRfuncAlias = alias void (...), bitcast (void ()* @weakODRfunc{{.*}} to void (...)*) +; NOTPROMOTED: @weakODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakODRfunc{{.*}} to void (...)*) +; NOTPROMOTED: @weakODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakODRfunc{{.*}} to void (...)*) +; PROMOTE_MOD1: @weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) +; PROMOTE_MOD1: @weakODRfuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @weakODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakODRfunc to void (...)*) + +; NOTPROMOTED: @linkoncefuncAlias = alias void (...), bitcast (void ()* @linkoncefunc{{.*}} to void (...)*) +; NOTPROMOTED: @linkoncefuncWeakAlias = weak alias void (...), bitcast (void ()* @linkoncefunc{{.*}} to void (...)*) +; NOTPROMOTED: @linkoncefuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkoncefunc{{.*}} to void (...)*) +; PROMOTE_MOD1: @linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +; PROMOTE_MOD2: @linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) +; PROMOTE_MOD1: @linkoncefuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +; PROMOTE_MOD2: @linkoncefuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkoncefunc to void (...)*) + +; NOTPROMOTED: @weakfuncAlias = alias void (...), bitcast (void ()* @weakfunc{{.*}} to void (...)*) +; NOTPROMOTED: @weakfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakfunc{{.*}} to void (...)*) +; NOTPROMOTED: @weakfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakfunc{{.*}} to void (...)*) +; FIXME: The "resolution" should turn one of these to linkonce_odr +; PROMOTE_MOD1: @weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) +; PROMOTE_MOD1: @weakfuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +; PROMOTE_MOD2: @weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*) + + +@linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +@linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +@linkonceODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +@linkonceODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +@linkonceODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*) +define linkonce_odr void @linkonceODRfunc.mod1() { +entry: + ret void +} + +@weakODRfuncAlias = alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +@weakODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +@weakODRfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +@weakODRfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +@weakODRfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakODRfunc.mod1 to void (...)*) +define weak_odr void @weakODRfunc.mod1() { +entry: + ret void +} + +@linkoncefuncAlias = alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +@linkoncefuncWeakAlias = weak alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +@linkoncefuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +@linkoncefuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +@linkoncefuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @linkoncefunc.mod1 to void (...)*) +define linkonce void @linkoncefunc.mod1() { +entry: + ret void +} + +@weakfuncAlias = alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +@weakfuncWeakAlias = weak alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +@weakfuncLinkonceAlias = linkonce alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +@weakfuncWeakODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +@weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*) +define weak void @weakfunc.mod1() { +entry: + ret void +} + diff --git a/test/ThinLTO/X86/odr_resolution.ll b/test/ThinLTO/X86/odr_resolution.ll index 1db966862d7..4292dfcba03 100644 --- a/test/ThinLTO/X86/odr_resolution.ll +++ b/test/ThinLTO/X86/odr_resolution.ll @@ -10,8 +10,8 @@ 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, but can't be turned into "available_externally" +; MOD1: @linkoncealias = weak_odr alias void (), void ()* @linkonceodrfuncwithalias ; MOD2: @linkoncealias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias @linkoncealias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias |