[ThinLTO] Enable importing of aliases as copy of aliasee

Summary:
This implements a missing feature to allow importing of aliases, which
was previously disabled because alias cannot be available_externally.
We instead import an alias as a copy of its aliasee.

Some additional work was required in the IndexBitcodeWriter for the
distributed build case, to ensure that the aliasee has a value id
in the distributed index file (i.e. even when it is not being
imported directly).

This is a performance win in codes that have many aliases, e.g. C++
applications that have many constructor and destructor aliases.

Reviewers: pcc

Subscribers: mehdi_amini, inglorion, eraman, llvm-commits

Differential Revision: https://reviews.llvm.org/D40747

llvm-svn: 320895
This commit is contained in:
Teresa Johnson 2017-12-16 00:18:12 +00:00
parent c4fdbca604
commit 81bbf74265
14 changed files with 236 additions and 81 deletions

View File

@ -246,6 +246,7 @@ public:
/// 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 @@ public:
/// \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<ValueInfo>{}) {}
: GlobalValueSummary(AliasKind, Flags, ArrayRef<ValueInfo>{}),
AliaseeSummary(nullptr), AliaseeGUID(0) {}
/// Check if this is an alias summary.
static bool classof(const GlobalValueSummary *GVS) {
@ -266,6 +271,7 @@ public:
}
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 @@ public:
return const_cast<GlobalValueSummary &>(
static_cast<const AliasSummary *>(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<AliasSummary>(this))
return &AS->getAliasee();
return this;
}
inline GlobalValueSummary *GlobalValueSummary::getBaseObject() {
if (auto *AS = dyn_cast<AliasSummary>(this))
return &AS->getAliasee();

View File

@ -330,6 +330,10 @@ public:
return UseList == nullptr;
}
bool materialized_use_empty() const {
return UseList == nullptr;
}
using use_iterator = use_iterator_impl<Use>;
using const_use_iterator = use_iterator_impl<const Use>;

View File

@ -98,6 +98,15 @@ void ComputeCrossModuleImportForModule(
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.

View File

@ -5202,6 +5202,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
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 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
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();

View File

@ -413,7 +413,7 @@ public:
// 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 @@ public:
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<AliasSummary>(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 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.clear();
};
forEachSummary([&](GVInfo I) {
forEachSummary([&](GVInfo I, bool IsAliasee) {
GlobalValueSummary *S = I.second;
assert(S);
@ -3612,6 +3618,12 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
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<AliasSummary>(S)) {
// Will process aliases as a post-pass because the reader wants all
// global to be loaded first.

View File

@ -409,7 +409,7 @@ void Value::doRAUW(Value *New, bool NoMetadata) {
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.

View File

@ -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 <cassert>
#include <memory>
#include <set>
@ -118,6 +121,12 @@ static cl::opt<std::string>
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<bool>
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<Module> loadFile(const std::string &FileName,
LLVMContext &Context) {
@ -172,13 +181,8 @@ selectCallee(const ModuleSummaryIndex &Index,
if (GlobalValue::isInterposableLinkage(GVSummary->linkage()))
// There is no point in importing these, we can't inline them
return false;
if (isa<AliasSummary>(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<FunctionSummary>(GVSummary);
auto *Summary = cast<FunctionSummary>(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 @@ static void computeImportForFunction(
}
// "Resolve" the summary
assert(!isa<AliasSummary>(CalleeSummary) &&
"Unexpected alias in import list");
const auto *ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
const auto *ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary->getBaseObject());
assert(ResolvedCalleeSummary->instCount() <= NewThreshold &&
"selectCallee() didn't honor the threshold");
@ -432,6 +434,19 @@ void llvm::ComputeCrossModuleImport(
#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 @@ void llvm::ComputeCrossModuleImportForModule(
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 @@ void llvm::thinLTOInternalizeModule(Module &TheModule,
internalizeModule(TheModule, MustPreserveGV);
}
/// Make alias a clone of its aliasee.
static Function *replaceAliasWithAliasee(Module *SrcModule, GlobalAlias *GA) {
Function *Fn = cast<Function>(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<bool> FunctionImporter::importFunctions(
@ -761,17 +811,36 @@ Expected<bool> FunctionImporter::importFunctions(
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 @@ static bool doImportingForModule(Module &M) {
// 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

View File

@ -6,3 +6,9 @@ entry:
%0 = load i32, i32* @G
ret i32 %0
}
@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*)
define void @aliasee() {
entry:
ret void
}

View File

@ -2,3 +2,9 @@ define void @g() {
entry:
ret void
}
@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*)
define void @aliasee() {
entry:
ret void
}

View File

@ -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:

View File

@ -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
; 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
; CHECK: @G.llvm.
; 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
}

View File

@ -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: <MODULE_STRTAB_BLOCK
; BACKEND1-NEXT: <ENTRY {{.*}} record string = '{{.*}}distributed_indexes.ll.tmp{{.*}}.bc'
; BACKEND1-NEXT: <ENTRY {{.*}} record string = '{{.*}}distributed_indexes.ll.tmp{{.*}}.bc'
; BACKEND1-NEXT: </MODULE_STRTAB_BLOCK
; BACKEND1-NEXT: <GLOBALVAL_SUMMARY_BLOCK
; BACKEND1-NEXT: <VERSION
; BACKEND1-NEXT: <VALUE_GUID op0={{1|2}} op1={{-3706093650706652785|-5300342847281564238}}
; BACKEND1-NEXT: <VALUE_GUID op0={{1|2}} op1={{-3706093650706652785|-5300342847281564238}}
; BACKEND1-NEXT: <COMBINED
; BACKEND1-NEXT: <COMBINED
; BACKEND1-DAG: <VALUE_GUID op0=2 op1=-5751648690987223394
; BACKEND1-DAG: <VALUE_GUID op0=4 op1=-5300342847281564238
; BACKEND1-DAG: <VALUE_GUID op0=1 op1=-3706093650706652785
; BACKEND1-DAG: <VALUE_GUID op0=3 op1=-1039159065113703048
; BACKEND1-DAG: <COMBINED {{.*}} op1=0
; BACKEND1-DAG: <COMBINED {{.*}} op1=1
; BACKEND1-DAG: <COMBINED_ALIAS {{.*}} op1=1
; BACKEND1-NEXT: </GLOBALVAL_SUMMARY_BLOCK
; The backend index for Input/distributed_indexes.ll contains summaries from
@ -26,14 +32,20 @@
; BACKEND2-NEXT: </MODULE_STRTAB_BLOCK
; BACKEND2-NEXT: <GLOBALVAL_SUMMARY_BLOCK
; BACKEND2-NEXT: <VERSION
; BACKEND2-NEXT: <VALUE_GUID op0=1 op1=-5300342847281564238
; BACKEND2-DAG: <VALUE_GUID op0=1 op1=-5751648690987223394/>
; BACKEND2-DAG: <VALUE_GUID op0=4 op1=-5300342847281564238/>
; BACKEND2-DAG: <VALUE_GUID op0=3 op1=-1039159065113703048/>
; BACKEND2-NEXT: <COMBINED
; BACKEND2-NEXT: <COMBINED
; BACKEND2-NEXT: <COMBINED_ALIAS
; BACKEND2-NEXT: </GLOBALVAL_SUMMARY_BLOCK
declare void @g(...)
declare void @analias(...)
define void @f() {
entry:
call void (...) @g()
call void (...) @analias()
ret void
}

View File

@ -16,17 +16,19 @@
; EXPORTSTATIC-DAG: define hidden i32 @staticfunc.llvm.0
; EXPORTSTATIC-DAG: define hidden void @staticfunc2.llvm.0
; Ensure that both weak alias to an imported function and strong alias to a
; non-imported function are correctly turned into declarations.
; Ensure that weak alias to an imported function is correctly turned into
; a declaration.
; Also ensures that alias to a linkonce function is turned into a declaration
; and that the associated linkonce function is not in the output, as it is
; lazily linked and never referenced/materialized.
; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORTGLOB1
; IMPORTGLOB1-DAG: define available_externally void @globalfunc1
; IMPORTGLOB1-DAG: declare void @weakalias
; IMPORTGLOB1-DAG: declare void @analias
; IMPORTGLOB1-NOT: @linkoncealias
; IMPORTGLOB1-NOT: @linkoncefunc
; A strong alias is imported as an available_externally copy of its aliasee.
; IMPORTGLOB1-DAG: define available_externally void @analias
; IMPORTGLOB1-NOT: declare void @globalfunc2
; Verify that the optimizer run

View File

@ -36,13 +36,14 @@ entry:
; CHECK-DAG: declare void @weakalias
declare void @weakalias(...) #1
; Cannot create an alias to available_externally
; CHECK-DAG: declare void @analias
; External alias imported as available_externally copy of aliasee
; CHECK-DAG: define available_externally void @analias
declare void @analias(...) #1
; Aliases are not imported
; External alias imported as available_externally copy of aliasee
; (linkoncealias is an external alias to a linkonce_odr)
declare void @linkoncealias(...) #1
; CHECK-DAG: declare void @linkoncealias(...)
; CHECK-DAG: define available_externally void @linkoncealias()
; INSTLIMDEF-DAG: Import referencestatics
; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) !thinlto_src_module !0 {
@ -105,7 +106,7 @@ declare void @linkoncefunc2(...) #1
declare void @variadic(...)
; INSTLIMDEF-DAG: Import globalfunc2
; INSTLIMDEF-DAG: 11 function-import - Number of functions imported
; INSTLIMDEF-DAG: 13 function-import - Number of functions imported
; CHECK-DAG: !0 = !{!"{{.*}}/Inputs/funcimport.ll"}
; The actual GUID values will depend on path to test.