Index: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h +++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h @@ -246,6 +246,7 @@ /// If this is an alias summary, returns the summary of the aliased object (a /// global variable or function), otherwise returns itself. GlobalValueSummary *getBaseObject(); + const GlobalValueSummary *getBaseObject() const; friend class ModuleSummaryIndex; friend void computeDeadSymbols(class ModuleSummaryIndex &, @@ -255,10 +256,14 @@ /// \brief Alias summary information. class AliasSummary : public GlobalValueSummary { GlobalValueSummary *AliaseeSummary; + // AliaseeGUID is only set and accessed when we are building a combined index + // via the BitcodeReader. + GlobalValue::GUID AliaseeGUID; public: AliasSummary(GVFlags Flags) - : GlobalValueSummary(AliasKind, Flags, ArrayRef{}) {} + : GlobalValueSummary(AliasKind, Flags, ArrayRef{}), + AliaseeSummary(nullptr), AliaseeGUID(0) {} /// Check if this is an alias summary. static bool classof(const GlobalValueSummary *GVS) { @@ -266,6 +271,7 @@ } void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; } + void setAliaseeGUID(GlobalValue::GUID GUID) { AliaseeGUID = GUID; } const GlobalValueSummary &getAliasee() const { assert(AliaseeSummary && "Unexpected missing aliasee summary"); @@ -276,8 +282,18 @@ return const_cast( static_cast(this)->getAliasee()); } + const GlobalValue::GUID &getAliaseeGUID() const { + assert(AliaseeGUID && "Unexpected missing aliasee GUID"); + return AliaseeGUID; + } }; +const inline GlobalValueSummary *GlobalValueSummary::getBaseObject() const { + if (auto *AS = dyn_cast(this)) + return &AS->getAliasee(); + return this; +} + inline GlobalValueSummary *GlobalValueSummary::getBaseObject() { if (auto *AS = dyn_cast(this)) return &AS->getAliasee(); Index: llvm/trunk/include/llvm/IR/Value.h =================================================================== --- llvm/trunk/include/llvm/IR/Value.h +++ llvm/trunk/include/llvm/IR/Value.h @@ -330,6 +330,10 @@ return UseList == nullptr; } + bool materialized_use_empty() const { + return UseList == nullptr; + } + using use_iterator = use_iterator_impl; using const_use_iterator = use_iterator_impl; Index: llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h =================================================================== --- llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h +++ llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h @@ -98,6 +98,15 @@ StringRef ModulePath, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList); +/// Mark all external summaries in \p Index for import into the given module. +/// Used for distributed builds using a distributed index. +/// +/// \p ImportList will be populated with a map that can be passed to +/// FunctionImporter::importFunctions() above (see description there). +void ComputeCrossModuleImportForModuleFromIndex( + StringRef ModulePath, const ModuleSummaryIndex &Index, + FunctionImporter::ImportMapTy &ImportList); + /// Compute all the symbols that are "dead": i.e these that can't be reached /// in the graph from any of the given symbols listed in /// \p GUIDPreservedSymbols. Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5202,6 +5202,7 @@ if (!AliaseeInModule) return error("Alias expects aliasee summary to be parsed"); AS->setAliasee(AliaseeInModule); + AS->setAliaseeGUID(AliaseeGUID); auto GUID = getValueInfoFromValueId(ValueID); AS->setOriginalName(GUID.second); @@ -5288,9 +5289,8 @@ getValueInfoFromValueId(AliaseeValueId).first.getGUID(); auto AliaseeInModule = TheIndex.findSummaryInModule(AliaseeGUID, AS->modulePath()); - if (!AliaseeInModule) - return error("Alias expects aliasee summary to be parsed"); AS->setAliasee(AliaseeInModule); + AS->setAliaseeGUID(AliaseeGUID); ValueInfo VI = getValueInfoFromValueId(ValueID).first; LastSeenGUID = VI.getGUID(); Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -413,7 +413,7 @@ // in writing out the call graph edges. Save the mapping from GUID // to the new global value id to use when writing those edges, which // are currently saved in the index in terms of GUID. - forEachSummary([&](GVInfo I) { + forEachSummary([&](GVInfo I, bool) { GUIDToValueIdMap[I.first] = ++GlobalValueId; }); } @@ -428,12 +428,18 @@ void forEachSummary(Functor Callback) { if (ModuleToSummariesForIndex) { for (auto &M : *ModuleToSummariesForIndex) - for (auto &Summary : M.second) - Callback(Summary); + for (auto &Summary : M.second) { + Callback(Summary, false); + // Ensure aliasee is handled, e.g. for assigning a valueId, + // even if we are not importing the aliasee directly (the + // imported alias will contain a copy of aliasee). + if (auto *AS = dyn_cast(Summary.getSecond())) + Callback({AS->getAliaseeGUID(), &AS->getAliasee()}, true); + } } else { for (auto &Summaries : Index) for (auto &Summary : Summaries.second.SummaryList) - Callback({Summaries.first, Summary.get()}); + Callback({Summaries.first, Summary.get()}, false); } } @@ -3604,7 +3610,7 @@ NameVals.clear(); }; - forEachSummary([&](GVInfo I) { + forEachSummary([&](GVInfo I, bool IsAliasee) { GlobalValueSummary *S = I.second; assert(S); @@ -3612,6 +3618,12 @@ assert(ValueId); SummaryToValueIdMap[S] = *ValueId; + // If this is invoked for an aliasee, we want to record the above + // mapping, but then not emit a summary entry (if the aliasee is + // to be imported, we will invoke this separately with IsAliasee=false). + if (IsAliasee) + return; + if (auto *AS = dyn_cast(S)) { // Will process aliases as a post-pass because the reader wants all // global to be loaded first. Index: llvm/trunk/lib/IR/Value.cpp =================================================================== --- llvm/trunk/lib/IR/Value.cpp +++ llvm/trunk/lib/IR/Value.cpp @@ -409,7 +409,7 @@ if (!NoMetadata && isUsedByMetadata()) ValueAsMetadata::handleRAUW(this, New); - while (!use_empty()) { + while (!materialized_use_empty()) { Use &U = *UseList; // Must handle Constants specially, we cannot call replaceUsesOfWith on a // constant because they are uniqued. Index: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp +++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/AutoUpgrade.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalObject.h" @@ -44,7 +45,9 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO/Internalize.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" +#include "llvm/Transforms/Utils/ValueMapper.h" #include #include #include @@ -118,6 +121,12 @@ SummaryFile("summary-file", cl::desc("The summary file to use for function importing.")); +/// Used when testing importing from distributed indexes via opt +// -function-import. +static cl::opt + ImportAllIndex("import-all-index", + cl::desc("Import all external functions in index.")); + // Load lazily a module from \p FileName in \p Context. static std::unique_ptr loadFile(const std::string &FileName, LLVMContext &Context) { @@ -172,13 +181,8 @@ if (GlobalValue::isInterposableLinkage(GVSummary->linkage())) // There is no point in importing these, we can't inline them return false; - if (isa(GVSummary)) - // Aliases can't point to "available_externally". - // FIXME: we should import alias as available_externally *function*, - // the destination module does not need to know it is an alias. - return false; - auto *Summary = cast(GVSummary); + auto *Summary = cast(GVSummary->getBaseObject()); // If this is a local function, make sure we import the copy // in the caller's module. The only time a local function can @@ -275,9 +279,7 @@ } // "Resolve" the summary - assert(!isa(CalleeSummary) && - "Unexpected alias in import list"); - const auto *ResolvedCalleeSummary = cast(CalleeSummary); + const auto *ResolvedCalleeSummary = cast(CalleeSummary->getBaseObject()); assert(ResolvedCalleeSummary->instCount() <= NewThreshold && "selectCallee() didn't honor the threshold"); @@ -432,6 +434,19 @@ #endif } +#ifndef NDEBUG +static void dumpImportListForModule(StringRef ModulePath, + FunctionImporter::ImportMapTy &ImportList) { + DEBUG(dbgs() << "* Module " << ModulePath << " imports from " + << ImportList.size() << " modules.\n"); + for (auto &Src : ImportList) { + auto SrcModName = Src.first(); + DEBUG(dbgs() << " - " << Src.second.size() << " functions imported from " + << SrcModName << "\n"); + } +#endif +} + /// Compute all the imports for the given module in the Index. void llvm::ComputeCrossModuleImportForModule( StringRef ModulePath, const ModuleSummaryIndex &Index, @@ -446,13 +461,34 @@ ComputeImportForModule(FunctionSummaryMap, Index, ImportList); #ifndef NDEBUG - DEBUG(dbgs() << "* Module " << ModulePath << " imports from " - << ImportList.size() << " modules.\n"); - for (auto &Src : ImportList) { - auto SrcModName = Src.first(); - DEBUG(dbgs() << " - " << Src.second.size() << " functions imported from " - << SrcModName << "\n"); + dumpImportListForModule(ModulePath, ImportList); +#endif +} + +// Mark all external summaries in Index for import into the given module. +// Used for distributed builds using a distributed index. +void llvm::ComputeCrossModuleImportForModuleFromIndex( + StringRef ModulePath, const ModuleSummaryIndex &Index, + FunctionImporter::ImportMapTy &ImportList) { + for (auto &GlobalList : Index) { + // Ignore entries for undefined references. + if (GlobalList.second.SummaryList.empty()) + continue; + + auto GUID = GlobalList.first; + assert(GlobalList.second.SummaryList.size() == 1 && + "Expected individual combined index to have one summary per GUID"); + auto &Summary = GlobalList.second.SummaryList[0]; + // Skip the summaries for the importing module. These are included to + // e.g. record required linkage changes. + if (Summary->modulePath() == ModulePath) + continue; + // Doesn't matter what value we plug in to the map, just needs an entry + // to provoke importing by thinBackend. + ImportList[Summary->modulePath()][GUID] = 1; } +#ifndef NDEBUG + dumpImportListForModule(ModulePath, ImportList); #endif } @@ -692,6 +728,20 @@ internalizeModule(TheModule, MustPreserveGV); } +/// Make alias a clone of its aliasee. +static Function *replaceAliasWithAliasee(Module *SrcModule, GlobalAlias *GA) { + Function *Fn = cast(GA->getBaseObject()); + + ValueToValueMapTy VMap; + Function *NewFn = CloneFunction(Fn, VMap); + // Clone should use the original alias's linkage and name, and we ensure + // all uses of alias instead use the new clone (casted if necessary). + NewFn->setLinkage(GA->getLinkage()); + GA->replaceAllUsesWith(ConstantExpr::getBitCast(NewFn, GA->getType())); + NewFn->takeName(GA); + return NewFn; +} + // Automatically import functions in Module \p DestModule based on the summaries // index. Expected FunctionImporter::importFunctions( @@ -761,17 +811,36 @@ GlobalsToImport.insert(&GV); } } -#ifndef NDEBUG for (GlobalAlias &GA : SrcModule->aliases()) { if (!GA.hasName()) continue; auto GUID = GA.getGUID(); - assert(!ImportGUIDs.count(GUID) && "Unexpected alias in import list"); - DEBUG(dbgs() << "Not importing alias " << GUID + auto Import = ImportGUIDs.count(GUID); + DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing alias " << GUID << " " << GA.getName() << " from " << SrcModule->getSourceFileName() << "\n"); + if (Import) { + if (Error Err = GA.materialize()) + return std::move(Err); + // Import alias as a copy of its aliasee. + GlobalObject *Base = GA.getBaseObject(); + if (Error Err = Base->materialize()) + return std::move(Err); + auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA); + DEBUG(dbgs() << "Is importing aliasee fn " << Base->getGUID() + << " " << Base->getName() << " from " + << SrcModule->getSourceFileName() << "\n"); + if (EnableImportMetadata) { + // Add 'thinlto_src_module' metadata for statistics and debugging. + Fn->setMetadata( + "thinlto_src_module", + MDNode::get(DestModule.getContext(), + {MDString::get(DestModule.getContext(), + SrcModule->getSourceFileName())})); + } + GlobalsToImport.insert(Fn); + } } -#endif // Upgrade debug info after we're done materializing all the globals and we // have loaded all the required metadata! @@ -817,8 +886,15 @@ // First step is collecting the import list. FunctionImporter::ImportMapTy ImportList; - ComputeCrossModuleImportForModule(M.getModuleIdentifier(), *Index, - ImportList); + // If requested, simply import all functions in the index. This is used + // when testing distributed backend handling via the opt tool, when + // we have distributed indexes containing exactly the summaries to import. + if (ImportAllIndex) + ComputeCrossModuleImportForModuleFromIndex(M.getModuleIdentifier(), *Index, + ImportList); + else + ComputeCrossModuleImportForModule(M.getModuleIdentifier(), *Index, + ImportList); // Conservatively mark all internal values as promoted. This interface is // only used when doing importing via the function importing pass. The pass Index: llvm/trunk/test/ThinLTO/X86/Inputs/distributed_import.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/Inputs/distributed_import.ll +++ llvm/trunk/test/ThinLTO/X86/Inputs/distributed_import.ll @@ -6,3 +6,9 @@ %0 = load i32, i32* @G ret i32 %0 } + +@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*) +define void @aliasee() { +entry: + ret void +} Index: llvm/trunk/test/ThinLTO/X86/Inputs/distributed_indexes.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/Inputs/distributed_indexes.ll +++ llvm/trunk/test/ThinLTO/X86/Inputs/distributed_indexes.ll @@ -2,3 +2,9 @@ entry: ret void } + +@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*) +define void @aliasee() { +entry: + ret void +} Index: llvm/trunk/test/ThinLTO/X86/alias_import.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/alias_import.ll +++ llvm/trunk/test/ThinLTO/X86/alias_import.ll @@ -4,9 +4,9 @@ ; 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 they cannot be imported for -; now. This could be implemented by importing the alias as an -; available_externally definition copied from the aliasee's body. +; Alias can't point to "available_externally", so they are implemented by +; importing the alias as an available_externally definition copied from the +; aliasee's body. ; PROMOTE-DAG: @globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*) ; PROMOTE-DAG: @globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*) ; PROMOTE-DAG: @globalfuncLinkonceAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*) @@ -45,45 +45,43 @@ ; PROMOTE-DAG: define weak void @linkoncefunc() ; PROMOTE-DAG: define weak void @weakfunc() -; On the import side now, verify that aliases are not imported -; IMPORT-DAG: declare void @linkonceODRfuncWeakAlias -; IMPORT-DAG: declare void @linkonceODRfuncLinkonceAlias -; IMPORT-DAG: declare void @linkonceODRfuncAlias -; IMPORT-DAG: declare void @linkonceODRfuncWeakODRAlias -; IMPORT-DAG: declare void @linkonceODRfuncLinkonceODRAlias - - -; On the import side, these aliases are not imported (they don't point to a linkonce_odr) -; IMPORT-DAG: declare void @globalfuncAlias() +; On the import side now, verify that aliases are imported unless they +; are preemptible (non-ODR weak/linkonce). +; IMPORT-DAG: declare void @linkonceODRfuncWeakAlias +; IMPORT-DAG: declare void @linkonceODRfuncLinkonceAlias +; IMPORT-DAG: define available_externally void @linkonceODRfuncAlias +; IMPORT-DAG: define available_externally void @linkonceODRfuncWeakODRAlias +; IMPORT-DAG: define available_externally void @linkonceODRfuncLinkonceODRAlias +; IMPORT-DAG: define available_externally 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: define available_externally void @globalfuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @globalfuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally 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: define available_externally void @internalfuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @internalfuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally 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: define available_externally void @weakODRfuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @weakODRfuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally 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: define available_externally void @linkoncefuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @linkoncefuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally void @weakfuncAlias() ; IMPORT-DAG: declare void @weakfuncWeakAlias() ; IMPORT-DAG: declare void @weakfuncLinkonceAlias() -; IMPORT-DAG: declare void @weakfuncWeakODRAlias() -; IMPORT-DAG: declare void @weakfuncLinkonceODRAlias() -; IMPORT-DAG: declare void @linkonceODRfuncAlias() +; IMPORT-DAG: define available_externally void @weakfuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @weakfuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally void @linkonceODRfuncAlias() ; IMPORT-DAG: declare void @linkonceODRfuncWeakAlias() -; IMPORT-DAG: declare void @linkonceODRfuncWeakODRAlias() +; IMPORT-DAG: define available_externally void @linkonceODRfuncWeakODRAlias() ; IMPORT-DAG: declare void @linkonceODRfuncLinkonceAlias() -; IMPORT-DAG: declare void @linkonceODRfuncLinkonceODRAlias() +; IMPORT-DAG: define available_externally void @linkonceODRfuncLinkonceODRAlias() define i32 @main() #0 { entry: Index: llvm/trunk/test/ThinLTO/X86/distributed_import.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/distributed_import.ll +++ llvm/trunk/test/ThinLTO/X86/distributed_import.ll @@ -10,11 +10,15 @@ ; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t.o -save-temps \ ; RUN: -thinlto-distributed-indexes \ ; RUN: -r=%t1.bc,g, \ +; RUN: -r=%t1.bc,analias, \ ; RUN: -r=%t1.bc,f,px \ -; RUN: -r=%t2.bc,g,px -; RUN: opt -function-import -summary-file %t1.bc.thinlto.bc %t1.bc -o %t1.out -; RUN: opt -function-import -summary-file %t2.bc.thinlto.bc %t2.bc -o %t2.out -; RUN: llvm-dis -o - %t2.out | FileCheck %s +; RUN: -r=%t2.bc,g,px \ +; RUN: -r=%t2.bc,analias,px \ +; RUN: -r=%t2.bc,aliasee,px +; RUN: opt -function-import -import-all-index -summary-file %t1.bc.thinlto.bc %t1.bc -o %t1.out +; RUN: opt -function-import -import-all-index -summary-file %t2.bc.thinlto.bc %t2.bc -o %t2.out +; RUN: llvm-dis -o - %t1.out | FileCheck %s --check-prefix=IMPORT +; RUN: llvm-dis -o - %t2.out | FileCheck %s --check-prefix=EXPORT ; Save the generated index files. ; RUN: cp %t1.bc.thinlto.bc %t1.bc.thinlto.bc.orig @@ -34,26 +38,35 @@ ; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t.o -save-temps \ ; RUN: -thinlto-distributed-indexes \ ; RUN: -r=%t1.bc,g, \ +; RUN: -r=%t1.bc,analias, \ ; RUN: -r=%t1.bc,f,px \ -; RUN: -r=%t2.bc,g,px +; RUN: -r=%t2.bc,g,px \ +; RUN: -r=%t2.bc,analias,px \ +; RUN: -r=%t2.bc,aliasee,px ; RUN: diff %t1.bc.thinlto.bc.orig %t1.bc.thinlto.bc ; RUN: diff %t2.bc.thinlto.bc.orig %t2.bc.thinlto.bc ; Make sure importing occurs as expected ; RUN: cp %t1.bc.sv %t1.bc ; RUN: cp %t2.bc.sv %t2.bc -; RUN: opt -function-import -summary-file %t2.bc.thinlto.bc %t2.bc -o %t2.out -; RUN: llvm-dis -o - %t2.out | FileCheck %s - -; CHECK: @G.llvm. +; RUN: opt -function-import -import-all-index -summary-file %t1.bc.thinlto.bc %t1.bc -o %t1.out +; RUN: opt -function-import -import-all-index -summary-file %t2.bc.thinlto.bc %t2.bc -o %t2.out +; RUN: llvm-dis -o - %t1.out | FileCheck %s --check-prefix=IMPORT +; RUN: llvm-dis -o - %t2.out | FileCheck %s --check-prefix=EXPORT + +; IMPORT: define available_externally i32 @g() !thinlto_src_module +; IMPORT: define available_externally void @analias() !thinlto_src_module +; EXPORT: @G.llvm. target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" declare i32 @g(...) +declare void @analias(...) define void @f() { entry: call i32 (...) @g() + call void (...) @analias() ret void } Index: llvm/trunk/test/ThinLTO/X86/distributed_indexes.ll =================================================================== --- llvm/trunk/test/ThinLTO/X86/distributed_indexes.ll +++ llvm/trunk/test/ThinLTO/X86/distributed_indexes.ll @@ -7,16 +7,22 @@ ; The backend index for this module contains summaries from itself and ; Inputs/distributed_indexes.ll, as it imports from the latter. +; We should import @g and alias @analias. While we don't import the aliasee +; directly (and therefore don't have a third COMBINED record from module +; id 1), we will have a VALUE_GUID for it (hence the 4 VALUE_GUID entries). ; BACKEND1: +; BACKEND2-DAG: +; BACKEND2-DAG: ; BACKEND2-NEXT: