diff options
author | Mehdi Amini <mehdi.amini@apple.com> | 2016-04-13 17:18:42 +0000 |
---|---|---|
committer | Mehdi Amini <mehdi.amini@apple.com> | 2016-04-13 17:18:42 +0000 |
commit | ce744a95fd99e7b9ae368e2f98de60b09c70fed0 (patch) | |
tree | ef64981e3528a03565000d7b4a5fe58d6a5e8179 /llvm/lib | |
parent | f5a7ec7a5ced6720b84dbebe2b396bc95cadce09 (diff) | |
download | bcm5719-llvm-ce744a95fd99e7b9ae368e2f98de60b09c70fed0.tar.gz bcm5719-llvm-ce744a95fd99e7b9ae368e2f98de60b09c70fed0.zip |
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>
llvm-svn: 266214
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 70 | ||||
-rw-r--r-- | llvm/lib/IR/ModuleSummaryIndex.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionImport.cpp | 86 |
4 files changed, 173 insertions, 36 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 321c775531e..e5fb51b1bed 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -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]; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 1b90c885a9b..a55f4954b45 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -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(); } diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp index aa34532ea13..cc1e8a9657c 100644 --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -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) { diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index 088b114e787..d6dfe17518b 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -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,14 +101,14 @@ 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, - unsigned Threshold, - const ModuleSummaryIndex &Index) { +static const GlobalValueSummary *selectCallee(GlobalValue::GUID GUID, + unsigned Threshold, + const ModuleSummaryIndex &Index) { auto CalleeInfoList = Index.findGlobalValueInfoList(GUID); if (CalleeInfoList == Index.end()) { return nullptr; // This function does not have a summary @@ -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,7 +375,7 @@ bool FunctionImporter::importFunctions( GlobalsToImport.insert(&GV); } } - for (auto &GV : SrcModule->aliases()) { + for (auto &GV : SrcModule->globals()) { if (!GV.hasName()) continue; auto GUID = GV.getGUID(); @@ -367,18 +384,11 @@ bool FunctionImporter::importFunctions( << GV.getName() << " from " << SrcModule->getSourceFileName() << "\n"); if (Import) { - // 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(); - if (!GO->hasLinkOnceODRLinkage()) - continue; GV.materialize(); GlobalsToImport.insert(&GV); - GlobalsToImport.insert(GO); } } - for (auto &GV : SrcModule->globals()) { + for (auto &GV : SrcModule->aliases()) { if (!GV.hasName()) continue; auto GUID = GV.getGUID(); @@ -387,6 +397,20 @@ bool FunctionImporter::importFunctions( << GV.getName() << " from " << SrcModule->getSourceFileName() << "\n"); if (Import) { + // 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. + GlobalObject *GO = GV.getBaseObject(); + if (!GO->hasLinkOnceODRLinkage()) + continue; +#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); 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) {} |