mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-31 15:53:42 +00:00
Make aliases explicit in the summary
Summary: To be able to work accurately on the reference graph when taking decision about internalizing, promoting, renaming, etc. We need to have the alias information explicit. Reviewers: tejohnson Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D18836 From: Mehdi Amini <mehdi.amini@apple.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266214 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7739723f0d
commit
e618ec9378
@ -213,6 +213,10 @@ enum GlobalValueSummarySymtabCodes {
|
||||
FS_COMBINED_PROFILE = 5,
|
||||
// COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]
|
||||
FS_COMBINED_GLOBALVAR_INIT_REFS = 6,
|
||||
// ALIAS: [valueid, linkage, valueid]
|
||||
FS_ALIAS = 7,
|
||||
// COMBINED_ALIAS: [modid, linkage, offset]
|
||||
FS_COMBINED_ALIAS = 8,
|
||||
};
|
||||
|
||||
enum MetadataCodes {
|
||||
|
@ -93,7 +93,7 @@ struct ValueInfo {
|
||||
class GlobalValueSummary {
|
||||
public:
|
||||
/// \brief Sububclass discriminator (for dyn_cast<> et al.)
|
||||
enum SummaryKind { FunctionKind, GlobalVarKind };
|
||||
enum SummaryKind { AliasKind, FunctionKind, GlobalVarKind };
|
||||
|
||||
private:
|
||||
/// Kind of summary for use in dyn_cast<> et al.
|
||||
@ -164,6 +164,32 @@ public:
|
||||
const std::vector<ValueInfo> &refs() const { return RefEdgeList; }
|
||||
};
|
||||
|
||||
/// \brief Alias summary information.
|
||||
class AliasSummary : public GlobalValueSummary {
|
||||
GlobalValueSummary *AliaseeSummary;
|
||||
|
||||
public:
|
||||
/// Summary constructors.
|
||||
AliasSummary(GlobalValue::LinkageTypes Linkage)
|
||||
: GlobalValueSummary(AliasKind, Linkage) {}
|
||||
|
||||
/// Check if this is an alias summary.
|
||||
static bool classof(const GlobalValueSummary *GVS) {
|
||||
return GVS->getSummaryKind() == AliasKind;
|
||||
}
|
||||
|
||||
void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
|
||||
|
||||
const GlobalValueSummary &getAliasee() const {
|
||||
return const_cast<AliasSummary *>(this)->getAliasee();
|
||||
}
|
||||
|
||||
GlobalValueSummary &getAliasee() {
|
||||
assert(AliaseeSummary && "Unexpected missing aliasee summary");
|
||||
return *AliaseeSummary;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Function summary information to aid decisions and implementation of
|
||||
/// importing.
|
||||
class FunctionSummary : public GlobalValueSummary {
|
||||
@ -439,7 +465,7 @@ public:
|
||||
/// (GUID -> Summary).
|
||||
void collectDefinedFunctionsForModule(
|
||||
StringRef ModulePath,
|
||||
std::map<GlobalValue::GUID, FunctionSummary *> &FunctionInfoMap) const;
|
||||
std::map<GlobalValue::GUID, GlobalValueSummary *> &FunctionInfoMap) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -5848,6 +5848,35 @@ std::error_code ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
|
||||
Info->setSummary(std::move(FS));
|
||||
break;
|
||||
}
|
||||
// FS_ALIAS: [valueid, linkage, valueid]
|
||||
// Aliases must be emitted (and parsed) after all FS_PERMODULE entries, as
|
||||
// they expect all aliasee summaries to be available.
|
||||
case bitc::FS_ALIAS: {
|
||||
unsigned ValueID = Record[0];
|
||||
uint64_t RawLinkage = Record[1];
|
||||
unsigned AliaseeID = Record[2];
|
||||
std::unique_ptr<AliasSummary> AS =
|
||||
llvm::make_unique<AliasSummary>(getDecodedLinkage(RawLinkage));
|
||||
// The module path string ref set in the summary must be owned by the
|
||||
// index's module string table. Since we don't have a module path
|
||||
// string table section in the per-module index, we create a single
|
||||
// module path string table entry with an empty (0) ID to take
|
||||
// ownership.
|
||||
AS->setModulePath(
|
||||
TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0)->first());
|
||||
|
||||
GlobalValue::GUID AliaseeGUID = getGUIDFromValueId(AliaseeID);
|
||||
auto *AliaseeInfo = TheIndex->getGlobalValueInfo(AliaseeGUID);
|
||||
if (!AliaseeInfo->summary())
|
||||
return error("Alias expects aliasee summary to be parsed");
|
||||
AS->setAliasee(AliaseeInfo->summary());
|
||||
|
||||
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID);
|
||||
auto *Info = TheIndex->getGlobalValueInfo(GUID);
|
||||
assert(!Info->summary() && "Expected a single summary per VST entry");
|
||||
Info->setSummary(std::move(AS));
|
||||
break;
|
||||
}
|
||||
// FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, linkage, n x valueid]
|
||||
case bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS: {
|
||||
unsigned ValueID = Record[0];
|
||||
@ -5906,6 +5935,28 @@ std::error_code ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
|
||||
Combined = true;
|
||||
break;
|
||||
}
|
||||
// FS_COMBINED_ALIAS: [modid, linkage, offset]
|
||||
// Aliases must be emitted (and parsed) after all FS_PERMODULE entries, as
|
||||
// they expect all aliasee summaries to be available.
|
||||
case bitc::FS_COMBINED_ALIAS: {
|
||||
uint64_t ModuleId = Record[0];
|
||||
uint64_t RawLinkage = Record[1];
|
||||
uint64_t AliaseeSummaryOffset = Record[2];
|
||||
std::unique_ptr<AliasSummary> AS =
|
||||
llvm::make_unique<AliasSummary>(getDecodedLinkage(RawLinkage));
|
||||
AS->setModulePath(ModuleIdMap[ModuleId]);
|
||||
|
||||
auto *AliaseeInfo = getInfoFromSummaryOffset(AliaseeSummaryOffset);
|
||||
if (!AliaseeInfo->summary())
|
||||
return error("Alias expects aliasee summary to be parsed");
|
||||
AS->setAliasee(AliaseeInfo->summary());
|
||||
|
||||
auto *Info = getInfoFromSummaryOffset(CurRecordBit);
|
||||
assert(!Info->summary() && "Expected a single summary per VST entry");
|
||||
Info->setSummary(std::move(AS));
|
||||
Combined = true;
|
||||
break;
|
||||
}
|
||||
// FS_COMBINED_GLOBALVAR_INIT_REFS: [modid, linkage, n x valueid]
|
||||
case bitc::FS_COMBINED_GLOBALVAR_INIT_REFS: {
|
||||
uint64_t ModuleId = Record[0];
|
||||
|
@ -2924,16 +2924,24 @@ static void WritePerModuleGlobalValueSummary(const Module *M,
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
||||
unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
|
||||
// Abbrev for FS_ALIAS.
|
||||
Abbv = new BitCodeAbbrev();
|
||||
Abbv->Add(BitCodeAbbrevOp(bitc::FS_ALIAS));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
|
||||
unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
|
||||
SmallVector<uint64_t, 64> NameVals;
|
||||
// Iterate over the list of functions instead of the Index to
|
||||
// ensure the ordering is stable.
|
||||
for (const Function &F : *M) {
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
// Skip anonymous functions. We will emit a function summary for
|
||||
// any aliases below.
|
||||
// We shouldn't have any anonymous functions as they are not supported in
|
||||
// ThinLTO and should be renamed.
|
||||
if (!F.hasName())
|
||||
continue;
|
||||
report_fatal_error("Unexpected anonymous function when writing summary");
|
||||
|
||||
auto *Info = Index.getGlobalValueInfo(F);
|
||||
WritePerModuleFunctionSummaryRecord(
|
||||
@ -2947,6 +2955,20 @@ static void WritePerModuleGlobalValueSummary(const Module *M,
|
||||
for (const GlobalVariable &G : M->globals())
|
||||
WriteModuleLevelReferences(G, Index, VE, NameVals, FSModRefsAbbrev, Stream);
|
||||
|
||||
for (const GlobalAlias &A : M->aliases()) {
|
||||
auto *Aliasee = A.getBaseObject();
|
||||
if (!Aliasee->hasName())
|
||||
// Nameless function don't have an entry in the summary, skip it.
|
||||
continue;
|
||||
auto AliasId = VE.getValueID(&A);
|
||||
auto AliaseeId = VE.getValueID(Aliasee);
|
||||
NameVals.push_back(AliasId);
|
||||
NameVals.push_back(getEncodedLinkage(A.getLinkage()));
|
||||
NameVals.push_back(AliaseeId);
|
||||
Stream.EmitRecord(bitc::FS_ALIAS, NameVals, FSAliasAbbrev);
|
||||
NameVals.clear();
|
||||
}
|
||||
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
||||
@ -2990,11 +3012,31 @@ static void WriteCombinedGlobalValueSummary(
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
||||
unsigned FSModRefsAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
|
||||
// Abbrev for FS_COMBINED_ALIAS.
|
||||
Abbv = new BitCodeAbbrev();
|
||||
Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED_ALIAS));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // modid
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // linkage
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // offset
|
||||
unsigned FSAliasAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
|
||||
// The aliases are emitted as a post-pass, and will point to the summary
|
||||
// offset id of the aliasee. For this purpose we need to be able to get back
|
||||
// from the summary to the offset
|
||||
SmallVector<GlobalValueInfo *, 64> Aliases;
|
||||
DenseMap<const GlobalValueSummary *, uint64_t> SummaryToOffsetMap;
|
||||
|
||||
SmallVector<uint64_t, 64> NameVals;
|
||||
for (const auto &FII : Index) {
|
||||
for (auto &FI : FII.second) {
|
||||
GlobalValueSummary *S = FI->summary();
|
||||
assert(S);
|
||||
if (isa<AliasSummary>(S)) {
|
||||
// Will process aliases as a post-pass because the reader wants all
|
||||
// global to be loaded first.
|
||||
Aliases.push_back(FI.get());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto *VS = dyn_cast<GlobalVarSummary>(S)) {
|
||||
NameVals.push_back(Index.getModuleId(VS->modulePath()));
|
||||
@ -3017,6 +3059,8 @@ static void WriteCombinedGlobalValueSummary(
|
||||
// reader will invoke readRecord after the abbrev id read.
|
||||
FI->setBitcodeIndex(Stream.GetCurrentBitNo() +
|
||||
Stream.GetAbbrevIDWidth());
|
||||
// Store temporarily the offset in the map for a possible alias.
|
||||
SummaryToOffsetMap[S] = FI->bitcodeIndex();
|
||||
|
||||
// Emit the finished record.
|
||||
Stream.EmitRecord(bitc::FS_COMBINED_GLOBALVAR_INIT_REFS, NameVals,
|
||||
@ -3068,6 +3112,8 @@ static void WriteCombinedGlobalValueSummary(
|
||||
// in the VST entry. Add the current code size since the
|
||||
// reader will invoke readRecord after the abbrev id read.
|
||||
FI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth());
|
||||
// Store temporarily the offset in the map for a possible alias.
|
||||
SummaryToOffsetMap[S] = FI->bitcodeIndex();
|
||||
|
||||
unsigned FSAbbrev =
|
||||
(HasProfileData ? FSCallsProfileAbbrev : FSCallsAbbrev);
|
||||
@ -3080,6 +3126,24 @@ static void WriteCombinedGlobalValueSummary(
|
||||
}
|
||||
}
|
||||
|
||||
for (auto GVI : Aliases) {
|
||||
AliasSummary *AS = cast<AliasSummary>(GVI->summary());
|
||||
NameVals.push_back(Index.getModuleId(AS->modulePath()));
|
||||
NameVals.push_back(getEncodedLinkage(AS->linkage()));
|
||||
auto AliaseeOffset = SummaryToOffsetMap[&AS->getAliasee()];
|
||||
assert(AliaseeOffset);
|
||||
NameVals.push_back(AliaseeOffset);
|
||||
|
||||
// Record the starting offset of this summary entry for use
|
||||
// in the VST entry. Add the current code size since the
|
||||
// reader will invoke readRecord after the abbrev id read.
|
||||
GVI->setBitcodeIndex(Stream.GetCurrentBitNo() + Stream.GetAbbrevIDWidth());
|
||||
|
||||
// Emit the finished record.
|
||||
Stream.EmitRecord(bitc::FS_COMBINED_ALIAS, NameVals, FSAliasAbbrev);
|
||||
NameVals.clear();
|
||||
}
|
||||
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ void ModuleSummaryIndex::removeEmptySummaryEntries() {
|
||||
// (GUID -> Summary).
|
||||
void ModuleSummaryIndex::collectDefinedFunctionsForModule(
|
||||
StringRef ModulePath,
|
||||
std::map<GlobalValue::GUID, FunctionSummary *> &FunctionInfoMap) const {
|
||||
std::map<GlobalValue::GUID, GlobalValueSummary *> &FunctionInfoMap) const {
|
||||
for (auto &GlobalList : *this) {
|
||||
auto GUID = GlobalList.first;
|
||||
for (auto &GlobInfo : GlobalList.second) {
|
||||
|
@ -79,13 +79,16 @@ namespace {
|
||||
/// number of source modules parsed/linked.
|
||||
/// - One that has PGO data attached.
|
||||
/// - [insert you fancy metric here]
|
||||
static const FunctionSummary *
|
||||
static const GlobalValueSummary *
|
||||
selectCallee(const GlobalValueInfoList &CalleeInfoList, unsigned Threshold) {
|
||||
auto It = llvm::find_if(
|
||||
CalleeInfoList, [&](const std::unique_ptr<GlobalValueInfo> &GlobInfo) {
|
||||
assert(GlobInfo->summary() &&
|
||||
"We should not have a Global Info without summary");
|
||||
auto *Summary = cast<FunctionSummary>(GlobInfo->summary());
|
||||
auto *GVSummary = GlobInfo->summary();
|
||||
if (auto *AS = dyn_cast<AliasSummary>(GVSummary))
|
||||
GVSummary = &AS->getAliasee();
|
||||
auto *Summary = cast<FunctionSummary>(GVSummary);
|
||||
|
||||
if (GlobalValue::isWeakAnyLinkage(Summary->linkage()))
|
||||
return false;
|
||||
@ -98,12 +101,12 @@ selectCallee(const GlobalValueInfoList &CalleeInfoList, unsigned Threshold) {
|
||||
if (It == CalleeInfoList.end())
|
||||
return nullptr;
|
||||
|
||||
return cast<FunctionSummary>((*It)->summary());
|
||||
return cast<GlobalValueSummary>((*It)->summary());
|
||||
}
|
||||
|
||||
/// Return the summary for the function \p GUID that fits the \p Threshold, or
|
||||
/// null if there's no match.
|
||||
static const FunctionSummary *selectCallee(GlobalValue::GUID GUID,
|
||||
static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID,
|
||||
unsigned Threshold,
|
||||
const ModuleSummaryIndex &Index) {
|
||||
auto CalleeInfoList = Index.findGlobalValueInfoList(GUID);
|
||||
@ -140,7 +143,7 @@ using EdgeInfo = std::pair<const FunctionSummary *, unsigned /* Threshold */>;
|
||||
static void computeImportForFunction(
|
||||
const FunctionSummary &Summary, const ModuleSummaryIndex &Index,
|
||||
unsigned Threshold,
|
||||
const std::map<GlobalValue::GUID, FunctionSummary *> &DefinedFunctions,
|
||||
const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
|
||||
SmallVectorImpl<EdgeInfo> &Worklist,
|
||||
FunctionImporter::ImportMapTy &ImportsForModule,
|
||||
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
|
||||
@ -158,11 +161,19 @@ static void computeImportForFunction(
|
||||
DEBUG(dbgs() << "ignored! No qualifying callee with summary found.\n");
|
||||
continue;
|
||||
}
|
||||
assert(CalleeSummary->instCount() <= Threshold &&
|
||||
// "Resolve" the summary, traversing alias,
|
||||
const FunctionSummary *ResolvedCalleeSummary;
|
||||
if (isa<AliasSummary>(CalleeSummary))
|
||||
ResolvedCalleeSummary = cast<FunctionSummary>(
|
||||
&cast<AliasSummary>(CalleeSummary)->getAliasee());
|
||||
else
|
||||
ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
|
||||
|
||||
assert(ResolvedCalleeSummary->instCount() <= Threshold &&
|
||||
"selectCallee() didn't honor the threshold");
|
||||
|
||||
auto &ProcessedThreshold =
|
||||
ImportsForModule[CalleeSummary->modulePath()][GUID];
|
||||
auto ExportModulePath = ResolvedCalleeSummary->modulePath();
|
||||
auto &ProcessedThreshold = ImportsForModule[ExportModulePath][GUID];
|
||||
/// Since the traversal of the call graph is DFS, we can revisit a function
|
||||
/// a second time with a higher threshold. In this case, it is added back to
|
||||
/// the worklist with the new threshold.
|
||||
@ -175,18 +186,17 @@ static void computeImportForFunction(
|
||||
ProcessedThreshold = Threshold;
|
||||
|
||||
// Make exports in the source module.
|
||||
auto ExportModulePath = CalleeSummary->modulePath();
|
||||
if (ExportLists) {
|
||||
auto &ExportList = (*ExportLists)[ExportModulePath];
|
||||
ExportList.insert(GUID);
|
||||
// Mark all functions and globals referenced by this function as exported
|
||||
// to the outside if they are defined in the same source module.
|
||||
for (auto &Edge : CalleeSummary->calls()) {
|
||||
for (auto &Edge : ResolvedCalleeSummary->calls()) {
|
||||
auto CalleeGUID = Edge.first.getGUID();
|
||||
if (isGlobalExported(Index, ExportModulePath, CalleeGUID))
|
||||
ExportList.insert(CalleeGUID);
|
||||
}
|
||||
for (auto &Ref : CalleeSummary->refs()) {
|
||||
for (auto &Ref : ResolvedCalleeSummary->refs()) {
|
||||
auto GUID = Ref.getGUID();
|
||||
if (isGlobalExported(Index, ExportModulePath, GUID))
|
||||
ExportList.insert(GUID);
|
||||
@ -194,7 +204,7 @@ static void computeImportForFunction(
|
||||
}
|
||||
|
||||
// Insert the newly imported function to the worklist.
|
||||
Worklist.push_back(std::make_pair(CalleeSummary, Threshold));
|
||||
Worklist.push_back(std::make_pair(ResolvedCalleeSummary, Threshold));
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +212,7 @@ static void computeImportForFunction(
|
||||
/// as well as the list of "exports", i.e. the list of symbols referenced from
|
||||
/// another module (that may require promotion).
|
||||
static void ComputeImportForModule(
|
||||
const std::map<GlobalValue::GUID, FunctionSummary *> &DefinedFunctions,
|
||||
const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
|
||||
const ModuleSummaryIndex &Index,
|
||||
FunctionImporter::ImportMapTy &ImportsForModule,
|
||||
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
|
||||
@ -214,8 +224,11 @@ static void ComputeImportForModule(
|
||||
// module
|
||||
for (auto &FuncInfo : DefinedFunctions) {
|
||||
auto *Summary = FuncInfo.second;
|
||||
if (auto *AS = dyn_cast<AliasSummary>(Summary))
|
||||
Summary = &AS->getAliasee();
|
||||
auto *FuncSummary = cast<FunctionSummary>(Summary);
|
||||
DEBUG(dbgs() << "Initalize import for " << FuncInfo.first << "\n");
|
||||
computeImportForFunction(*Summary, Index, ImportInstrLimit,
|
||||
computeImportForFunction(*FuncSummary, Index, ImportInstrLimit,
|
||||
DefinedFunctions, Worklist, ImportsForModule,
|
||||
ExportLists);
|
||||
}
|
||||
@ -245,16 +258,20 @@ void llvm::ComputeCrossModuleImport(
|
||||
|
||||
// Collect for each module the list of function it defines.
|
||||
// GUID -> Summary
|
||||
StringMap<std::map<GlobalValue::GUID, FunctionSummary *>>
|
||||
StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
|
||||
Module2FunctionInfoMap(ModuleCount);
|
||||
|
||||
for (auto &GlobalList : Index) {
|
||||
auto GUID = GlobalList.first;
|
||||
for (auto &GlobInfo : GlobalList.second) {
|
||||
auto *Summary = dyn_cast_or_null<FunctionSummary>(GlobInfo->summary());
|
||||
if (!Summary)
|
||||
auto *Summary = GlobInfo->summary();
|
||||
if (isa<GlobalVarSummary>(Summary))
|
||||
/// Ignore global variable, focus on functions
|
||||
continue;
|
||||
if (auto *AS = dyn_cast<AliasSummary>(Summary))
|
||||
if (isa<GlobalVarSummary>(&AS->getAliasee()))
|
||||
/// Ignore alias to global variable, focus on functions
|
||||
continue;
|
||||
DEBUG(dbgs() << "Adding definition: Module '" << Summary->modulePath()
|
||||
<< "' defines '" << GUID << "'\n");
|
||||
Module2FunctionInfoMap[Summary->modulePath()][GUID] = Summary;
|
||||
@ -295,7 +312,7 @@ void llvm::ComputeCrossModuleImportForModule(
|
||||
|
||||
// Collect the list of functions this module defines.
|
||||
// GUID -> Summary
|
||||
std::map<GlobalValue::GUID, FunctionSummary *> FunctionInfoMap;
|
||||
std::map<GlobalValue::GUID, GlobalValueSummary *> FunctionInfoMap;
|
||||
Index.collectDefinedFunctionsForModule(ModulePath, FunctionInfoMap);
|
||||
|
||||
// Compute the import list for this module.
|
||||
@ -358,6 +375,19 @@ bool FunctionImporter::importFunctions(
|
||||
GlobalsToImport.insert(&GV);
|
||||
}
|
||||
}
|
||||
for (auto &GV : SrcModule->globals()) {
|
||||
if (!GV.hasName())
|
||||
continue;
|
||||
auto GUID = GV.getGUID();
|
||||
auto Import = ImportGUIDs.count(GUID);
|
||||
DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing " << GUID << " "
|
||||
<< GV.getName() << " from " << SrcModule->getSourceFileName()
|
||||
<< "\n");
|
||||
if (Import) {
|
||||
GV.materialize();
|
||||
GlobalsToImport.insert(&GV);
|
||||
}
|
||||
}
|
||||
for (auto &GV : SrcModule->aliases()) {
|
||||
if (!GV.hasName())
|
||||
continue;
|
||||
@ -370,23 +400,17 @@ bool FunctionImporter::importFunctions(
|
||||
// Alias can't point to "available_externally". However when we import
|
||||
// linkOnceODR the linkage does not change. So we import the alias
|
||||
// and aliasee only in this case.
|
||||
const GlobalObject *GO = GV.getBaseObject();
|
||||
GlobalObject *GO = GV.getBaseObject();
|
||||
if (!GO->hasLinkOnceODRLinkage())
|
||||
continue;
|
||||
GV.materialize();
|
||||
GlobalsToImport.insert(&GV);
|
||||
#ifndef NDEBUG
|
||||
if (!GlobalsToImport.count(GO))
|
||||
DEBUG(dbgs() << " alias triggers importing aliasee " << GO->getGUID()
|
||||
<< " " << GO->getName() << " from "
|
||||
<< SrcModule->getSourceFileName() << "\n");
|
||||
#endif
|
||||
GO->materialize();
|
||||
GlobalsToImport.insert(GO);
|
||||
}
|
||||
}
|
||||
for (auto &GV : SrcModule->globals()) {
|
||||
if (!GV.hasName())
|
||||
continue;
|
||||
auto GUID = GV.getGUID();
|
||||
auto Import = ImportGUIDs.count(GUID);
|
||||
DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing " << GUID << " "
|
||||
<< GV.getName() << " from " << SrcModule->getSourceFileName()
|
||||
<< "\n");
|
||||
if (Import) {
|
||||
GV.materialize();
|
||||
GlobalsToImport.insert(&GV);
|
||||
}
|
||||
@ -464,9 +488,7 @@ public:
|
||||
static char ID;
|
||||
|
||||
/// Specify pass name for debug output
|
||||
const char *getPassName() const override {
|
||||
return "Function Importing";
|
||||
}
|
||||
const char *getPassName() const override { return "Function Importing"; }
|
||||
|
||||
explicit FunctionImportPass(const ModuleSummaryIndex *Index = nullptr)
|
||||
: ModulePass(ID), Index(Index) {}
|
||||
|
13
test/Bitcode/Inputs/thinlto-alias.ll
Normal file
13
test/Bitcode/Inputs/thinlto-alias.ll
Normal file
@ -0,0 +1,13 @@
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
|
||||
|
||||
@analias = alias void (...), bitcast (void ()* @aliasee to void (...)*)
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define void @aliasee() #0 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
45
test/Bitcode/thinlto-alias.ll
Normal file
45
test/Bitcode/thinlto-alias.ll
Normal file
@ -0,0 +1,45 @@
|
||||
; Test to check the callgraph in summary
|
||||
; RUN: opt -module-summary %s -o %t.o
|
||||
; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s
|
||||
; RUN: opt -module-summary %p/Inputs/thinlto-alias.ll -o %t2.o
|
||||
; RUN: llvm-lto -thinlto -o %t3 %t.o %t2.o
|
||||
; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED
|
||||
|
||||
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
|
||||
; See if the call to func is registered, using the expected callsite count
|
||||
; and value id matching the subsequent value symbol table.
|
||||
; CHECK-NEXT: <PERMODULE {{.*}} op4=[[FUNCID:[0-9]+]] op5=1/>
|
||||
; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK>
|
||||
; CHECK-NEXT: <VALUE_SYMTAB
|
||||
; CHECK-NEXT: <FNENTRY {{.*}} record string = 'main'
|
||||
; External function analias should have entry with value id FUNCID
|
||||
; CHECK-NEXT: <ENTRY {{.*}} op0=[[FUNCID]] {{.*}} record string = 'analias'
|
||||
; CHECK-NEXT: </VALUE_SYMTAB>
|
||||
|
||||
; COMBINED: <GLOBALVAL_SUMMARY_BLOCK
|
||||
; See if the call to analias is registered, using the expected callsite count
|
||||
; and value id matching the subsequent value symbol table.
|
||||
; COMBINED-NEXT: <COMBINED {{.*}} op4=[[ALIASID:[0-9]+]] op5=1/>
|
||||
; Followed by the alias and aliasee
|
||||
; COMBINED-NEXT: <COMBINED {{.*}}
|
||||
; COMBINED-NEXT: <COMBINED_ALIAS {{.*}} op2=[[ALIASEEOFFSET:[0-9]+]]
|
||||
; COMBINED-NEXT: </GLOBALVAL_SUMMARY_BLOCK
|
||||
; COMBINED-NEXT: <VALUE_SYMTAB
|
||||
; Entry for function func should have entry with value id ALIASID
|
||||
; COMBINED-NEXT: <COMBINED_GVDEFENTRY {{.*}} op0=[[ALIASID]] {{.*}} op2=-5751648690987223394/>
|
||||
; COMBINED-NEXT: <COMBINED_GVDEFENTRY
|
||||
; COMBINED-NEXT: <COMBINED_GVDEFENTRY {{.*}} op1=[[ALIASEEOFFSET]] op2=-1039159065113703048/>
|
||||
; COMBINED-NEXT: </VALUE_SYMTAB>
|
||||
|
||||
; ModuleID = 'thinlto-function-summary-callgraph.ll'
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define i32 @main() {
|
||||
entry:
|
||||
call void (...) @analias()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare void @analias(...)
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -module-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC
|
||||
; RUN: opt -name-anon-functions -module-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC
|
||||
; Check for summary block/records.
|
||||
|
||||
; Check the value ids in the summary entries against the
|
||||
@ -7,13 +7,13 @@
|
||||
; BC: <GLOBALVAL_SUMMARY_BLOCK
|
||||
; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0
|
||||
; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0
|
||||
; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK
|
||||
; BC: </GLOBALVAL_SUMMARY_BLOCK
|
||||
; BC-NEXT: <VALUE_SYMTAB
|
||||
; BC-NEXT: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'
|
||||
; BC: <FNENTRY {{.*}} op0=1 {{.*}}> record string = 'foo'
|
||||
; BC-NEXT: <FNENTRY {{.*}} op0=2 {{.*}}> record string = 'bar'
|
||||
; BC-NEXT: <FNENTRY {{.*}} op0=4 {{.*}}> record string = 'f'
|
||||
|
||||
; RUN: opt -module-summary < %s | llvm-dis | FileCheck %s
|
||||
; RUN: opt -name-anon-functions -module-summary < %s | llvm-dis | FileCheck %s
|
||||
; Check that this round-trips correctly.
|
||||
|
||||
; ModuleID = '<stdin>'
|
||||
|
@ -87,7 +87,7 @@ declare void @weakfunc(...) #1
|
||||
; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.{{.*}}()
|
||||
|
||||
; INSTLIMDEF-DAG: Import globalfunc2
|
||||
; INSTLIMDEF-DAG: 9 function-import - Number of functions imported
|
||||
; INSTLIMDEF-DAG: 11 function-import - Number of functions imported
|
||||
|
||||
; The actual GUID values will depend on path to test.
|
||||
; GUID-DAG: GUID {{.*}} is weakalias
|
||||
|
@ -308,6 +308,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
|
||||
STRINGIFY_CODE(FS, COMBINED)
|
||||
STRINGIFY_CODE(FS, COMBINED_PROFILE)
|
||||
STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
|
||||
STRINGIFY_CODE(FS, ALIAS)
|
||||
STRINGIFY_CODE(FS, COMBINED_ALIAS)
|
||||
}
|
||||
case bitc::METADATA_ATTACHMENT_ID:
|
||||
switch(CodeID) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user