[llvm] r266519 - ThinLTO: Move the ODR resolution to be based purely on the summary.
Mehdi Amini via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 16 00:02:16 PDT 2016
Author: mehdi_amini
Date: Sat Apr 16 02:02:16 2016
New Revision: 266519
URL: http://llvm.org/viewvc/llvm-project?rev=266519&view=rev
Log:
ThinLTO: Move the ODR resolution to be based purely on the summary.
This is a requirement for the cache handling in D18494
Differential Revision: http://reviews.llvm.org/D18908
From: Mehdi Amini <mehdi.amini at apple.com>
Modified:
llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h
llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
Modified: llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h?rev=266519&r1=266518&r2=266519&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h (original)
+++ llvm/trunk/include/llvm/IR/ModuleSummaryIndex.h Sat Apr 16 02:02:16 2016
@@ -466,6 +466,12 @@ public:
void collectDefinedFunctionsForModule(
StringRef ModulePath,
std::map<GlobalValue::GUID, GlobalValueSummary *> &FunctionInfoMap) const;
+
+ /// Collect for each module the list of Summaries it defines (GUID ->
+ /// Summary).
+ void collectDefinedGVSummariesPerModule(
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>> &
+ ModuleToDefinedGVSummaries) const;
};
} // End llvm namespace
Modified: llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h?rev=266519&r1=266518&r2=266519&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO/FunctionImport.h Sat Apr 16 02:02:16 2016
@@ -19,6 +19,7 @@
namespace llvm {
class LLVMContext;
+class GlobalValueSummary;
class Module;
class ModuleSummaryIndex;
@@ -59,6 +60,9 @@ private:
/// Compute all the imports and exports for every module in the Index.
///
+/// \p ModuleToDefinedGVSummaries contains for each Module a map
+/// (GUID -> Summary) for every global defined in the module.
+///
/// \p ImportLists will be populated with an entry for every Module we are
/// importing into. This entry is itself a map that can be passed to
/// FunctionImporter::importFunctions() above (see description there).
@@ -68,6 +72,8 @@ private:
/// is the set of globals that need to be promoted/renamed appropriately.
void ComputeCrossModuleImport(
const ModuleSummaryIndex &Index,
+ const StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>> &
+ ModuleToDefinedGVSummaries,
StringMap<FunctionImporter::ImportMapTy> &ImportLists,
StringMap<FunctionImporter::ExportSetTy> &ExportLists);
Modified: llvm/trunk/lib/IR/ModuleSummaryIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ModuleSummaryIndex.cpp?rev=266519&r1=266518&r2=266519&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ModuleSummaryIndex.cpp (original)
+++ llvm/trunk/lib/IR/ModuleSummaryIndex.cpp Sat Apr 16 02:02:16 2016
@@ -89,6 +89,19 @@ void ModuleSummaryIndex::collectDefinedF
}
}
+// Collect for each module the list of function it defines (GUID -> Summary).
+void ModuleSummaryIndex::collectDefinedGVSummariesPerModule(
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>> &
+ Module2FunctionInfoMap) const {
+ for (auto &GlobalList : *this) {
+ auto GUID = GlobalList.first;
+ for (auto &GlobInfo : GlobalList.second) {
+ auto *Summary = GlobInfo->summary();
+ Module2FunctionInfoMap[Summary->modulePath()][GUID] = Summary;
+ }
+ }
+}
+
GlobalValueInfo *
ModuleSummaryIndex::getGlobalValueInfo(uint64_t ValueGUID,
bool PerModuleIndex) const {
Modified: llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp?rev=266519&r1=266518&r2=266519&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp (original)
+++ llvm/trunk/lib/LTO/ThinLTOCodeGenerator.cpp Sat Apr 16 02:02:16 2016
@@ -30,6 +30,7 @@
#include "llvm/Linker/Linker.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ThreadPool.h"
@@ -42,6 +43,8 @@
using namespace llvm;
+#define DEBUG_TYPE "thinlto"
+
namespace llvm {
// Flags -discard-value-names, defined in LTOCodeGenerator.cpp
extern cl::opt<bool> LTODiscardValueNames;
@@ -119,24 +122,15 @@ bool IsFirstDefinitionForLinker(const Gl
return true;
}
-static void ResolveODR(GlobalValue &GV, const ModuleSummaryIndex &Index,
- StringRef ModulePath) {
- if (GV.isDeclaration())
- return;
-
+static GlobalValue::LinkageTypes ResolveODR(const ModuleSummaryIndex &Index,
+ StringRef ModuleIdentifier,
+ GlobalValue::GUID GUID,
+ const GlobalValueSummary &GV) {
auto HasMultipleCopies =
[&](const GlobalValueInfoList &GVInfo) { return GVInfo.size() > 1; };
- auto getGVInfo = [&](GlobalValue &GV) -> const GlobalValueInfoList *{
- auto GUID = Function::getGlobalIdentifier(GV.getName(), GV.getLinkage(),
- ModulePath);
- auto It = Index.findGlobalValueInfoList(GV.getName());
- if (It == Index.end())
- return nullptr;
- return &It->second;
- };
-
- switch (GV.getLinkage()) {
+ auto OriginalLinkage = GV.linkage();
+ switch (OriginalLinkage) {
case GlobalValue::ExternalLinkage:
case GlobalValue::AvailableExternallyLinkage:
case GlobalValue::AppendingLinkage:
@@ -149,20 +143,19 @@ static void ResolveODR(GlobalValue &GV,
break;
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakODRLinkage: {
- auto *GVInfo = getGVInfo(GV);
- if (!GVInfo)
- break;
+ auto &GVInfo = Index.findGlobalValueInfoList(GUID)->second;
// We need to emit only one of these, the first module will keep
// it, but turned into a weak while the others will drop it.
- if (!HasMultipleCopies(*GVInfo))
+ if (!HasMultipleCopies(GVInfo))
break;
- if (IsFirstDefinitionForLinker(*GVInfo, Index, ModulePath))
- GV.setLinkage(GlobalValue::WeakODRLinkage);
+ if (IsFirstDefinitionForLinker(GVInfo, Index, ModuleIdentifier))
+ return GlobalValue::WeakODRLinkage;
else
- GV.setLinkage(GlobalValue::AvailableExternallyLinkage);
+ return GlobalValue::AvailableExternallyLinkage;
break;
}
}
+ return OriginalLinkage;
}
/// Resolve LinkOnceODR and WeakODR.
@@ -171,8 +164,11 @@ static void ResolveODR(GlobalValue &GV,
/// current module. However there is a chance that another module is still
/// referencing them because of the import. We make sure we always emit at least
/// one copy.
-static void ResolveODR(Module &TheModule,
- const ModuleSummaryIndex &Index) {
+static void ResolveODR(
+ const ModuleSummaryIndex &Index,
+ const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGlobals,
+ StringRef ModuleIdentifier,
+ DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR) {
if (Index.modulePaths().size() == 1)
// Nothing to do if we don't have multiple modules
return;
@@ -180,20 +176,42 @@ static void ResolveODR(Module &TheModule
// We won't optimize the globals that are referenced by an alias for now
// Ideally we should turn the alias into a global and duplicate the definition
// when needed.
- DenseSet<GlobalValue *> GlobalInvolvedWithAlias;
- for (auto &GA : TheModule.aliases()) {
- auto *GO = GA.getBaseObject();
- if (auto *GV = dyn_cast<GlobalValue>(GO))
- GlobalInvolvedWithAlias.insert(GV);
+ DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
+ for (auto &GA : DefinedGlobals) {
+ if (auto AS = dyn_cast<AliasSummary>(GA.second))
+ GlobalInvolvedWithAlias.insert(&AS->getAliasee());
+ }
+
+ for (auto &GV : DefinedGlobals) {
+ if (GlobalInvolvedWithAlias.count(GV.second))
+ continue;
+ auto NewLinkage = ResolveODR(Index, ModuleIdentifier, GV.first, *GV.second);
+ if (NewLinkage != GV.second->linkage()) {
+ ResolvedODR[GV.first] = NewLinkage;
+ }
}
+}
+
+/// Fixup linkage, see ResolveODR() above.
+void fixupODR(
+ Module &TheModule,
+ const DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR) {
// Process functions and global now
for (auto &GV : TheModule) {
- if (!GlobalInvolvedWithAlias.count(&GV))
- ResolveODR(GV, Index, TheModule.getModuleIdentifier());
+ auto NewLinkage = ResolvedODR.find(GV.getGUID());
+ if (NewLinkage == ResolvedODR.end())
+ continue;
+ DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
+ << GV.getLinkage() << " to " << NewLinkage->second << "\n");
+ GV.setLinkage(NewLinkage->second);
}
for (auto &GV : TheModule.globals()) {
- if (!GlobalInvolvedWithAlias.count(&GV))
- ResolveODR(GV, Index, TheModule.getModuleIdentifier());
+ auto NewLinkage = ResolvedODR.find(GV.getGUID());
+ if (NewLinkage == ResolvedODR.end())
+ continue;
+ DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName() << "` from "
+ << GV.getLinkage() << " to " << NewLinkage->second << "\n");
+ GV.setLinkage(NewLinkage->second);
}
}
@@ -291,13 +309,13 @@ std::unique_ptr<MemoryBuffer> codegenMod
return make_unique<ObjectMemoryBuffer>(std::move(OutputBuffer));
}
-static std::unique_ptr<MemoryBuffer>
-ProcessThinLTOModule(Module &TheModule, const ModuleSummaryIndex &Index,
- StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
- const FunctionImporter::ImportMapTy &ImportList,
- ThinLTOCodeGenerator::CachingOptions CacheOptions,
- bool DisableCodeGen, StringRef SaveTempsDir,
- unsigned count) {
+static std::unique_ptr<MemoryBuffer> ProcessThinLTOModule(
+ Module &TheModule, const ModuleSummaryIndex &Index,
+ StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
+ const FunctionImporter::ImportMapTy &ImportList,
+ DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
+ ThinLTOCodeGenerator::CachingOptions CacheOptions, bool DisableCodeGen,
+ StringRef SaveTempsDir, unsigned count) {
// Save temps: after IPO.
saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc");
@@ -311,7 +329,7 @@ ProcessThinLTOModule(Module &TheModule,
// Resolve the LinkOnce/Weak ODR, trying to turn them into
// "available_externally" when possible.
// This is a compile-time optimization.
- ResolveODR(TheModule, Index);
+ fixupODR(TheModule, ResolvedODR);
// Save temps: after promotion.
saveTempBitcode(TheModule, SaveTempsDir, count, ".2.promoted.bc");
@@ -435,10 +453,19 @@ std::unique_ptr<ModuleSummaryIndex> Thin
*/
void ThinLTOCodeGenerator::promote(Module &TheModule,
ModuleSummaryIndex &Index) {
+ auto ModuleIdentifier = TheModule.getModuleIdentifier();
+ // Collect for each module the list of function it defines (GUID -> Summary).
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+ ModuleToDefinedGVSummaries;
+ Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
// Resolve the LinkOnceODR, trying to turn them into "available_externally"
// where possible.
- ResolveODR(TheModule, Index);
+ // This is a compile-time optimization.
+ DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR;
+ ResolveODR(Index, ModuleToDefinedGVSummaries[ModuleIdentifier],
+ ModuleIdentifier, ResolvedODR);
+ fixupODR(TheModule, ResolvedODR);
promoteModule(TheModule, Index);
}
@@ -449,12 +476,18 @@ void ThinLTOCodeGenerator::promote(Modul
void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
ModuleSummaryIndex &Index) {
auto ModuleMap = generateModuleMap(Modules);
+ auto ModuleCount = Index.modulePaths().size();
+
+ // Collect for each module the list of function it defines (GUID -> Summary).
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+ ModuleToDefinedGVSummaries(ModuleCount);
+ Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
// Generate import/export list
- auto ModuleCount = Index.modulePaths().size();
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
- ComputeCrossModuleImport(Index, ImportLists, ExportLists);
+ ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists,
+ ExportLists);
auto &ImportList = ImportLists[TheModule.getModuleIdentifier()];
crossImportIntoModule(TheModule, Index, ModuleMap, ImportList);
@@ -522,11 +555,17 @@ void ThinLTOCodeGenerator::run() {
auto ModuleMap = generateModuleMap(Modules);
auto ModuleCount = Modules.size();
+ // Collect for each module the list of function it defines (GUID -> Summary).
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+ ModuleToDefinedGVSummaries(ModuleCount);
+ Index->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
+
// Collect the import/export lists for all modules from the call-graph in the
// combined index.
StringMap<FunctionImporter::ImportMapTy> ImportLists(ModuleCount);
StringMap<FunctionImporter::ExportSetTy> ExportLists(ModuleCount);
- ComputeCrossModuleImport(*Index, ImportLists, ExportLists);
+ ComputeCrossModuleImport(*Index, ModuleToDefinedGVSummaries, ImportLists,
+ ExportLists);
// Parallel optimizer + codegen
{
@@ -536,6 +575,11 @@ void ThinLTOCodeGenerator::run() {
Pool.async([&](int count) {
LLVMContext Context;
Context.setDiscardValueNames(LTODiscardValueNames);
+ auto ModuleIdentifier = ModuleBuffer.getBufferIdentifier();
+
+ DenseMap<GlobalValue::GUID, GlobalValue::LinkageTypes> ResolvedODR;
+ ResolveODR(*Index, ModuleToDefinedGVSummaries[ModuleIdentifier],
+ ModuleIdentifier, ResolvedODR);
// Parse module now
auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
@@ -545,10 +589,10 @@ void ThinLTOCodeGenerator::run() {
saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
}
- auto &ImportList = ImportLists[TheModule->getModuleIdentifier()];
+ auto &ImportList = ImportLists[ModuleIdentifier];
ProducedBinaries[count] = ProcessThinLTOModule(
*TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
- CacheOptions, DisableCodeGen, SaveTempsDir, count);
+ ResolvedODR, CacheOptions, DisableCodeGen, SaveTempsDir, count);
}, count);
count++;
}
Modified: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp?rev=266519&r1=266518&r2=266519&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp Sat Apr 16 02:02:16 2016
@@ -143,7 +143,7 @@ using EdgeInfo = std::pair<const Functio
static void computeImportForFunction(
const FunctionSummary &Summary, const ModuleSummaryIndex &Index,
unsigned Threshold,
- const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedFunctions,
+ const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGVSummaries,
SmallVectorImpl<EdgeInfo> &Worklist,
FunctionImporter::ImportMapTy &ImportsForModule,
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
@@ -151,7 +151,7 @@ static void computeImportForFunction(
auto GUID = Edge.first.getGUID();
DEBUG(dbgs() << " edge -> " << GUID << " Threshold:" << Threshold << "\n");
- if (DefinedFunctions.count(GUID)) {
+ if (DefinedGVSummaries.count(GUID)) {
DEBUG(dbgs() << "ignored! Target already in destination module.\n");
continue;
}
@@ -212,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, GlobalValueSummary *> &DefinedFunctions,
+ const std::map<GlobalValue::GUID, GlobalValueSummary *> &DefinedGVSummaries,
const ModuleSummaryIndex &Index,
FunctionImporter::ImportMapTy &ImportsForModule,
StringMap<FunctionImporter::ExportSetTy> *ExportLists = nullptr) {
@@ -222,14 +222,17 @@ static void ComputeImportForModule(
// Populate the worklist with the import for the functions in the current
// module
- for (auto &FuncInfo : DefinedFunctions) {
- auto *Summary = FuncInfo.second;
+ for (auto &GVInfo : DefinedGVSummaries) {
+ auto *Summary = GVInfo.second;
if (auto *AS = dyn_cast<AliasSummary>(Summary))
Summary = &AS->getAliasee();
- auto *FuncSummary = cast<FunctionSummary>(Summary);
- DEBUG(dbgs() << "Initalize import for " << FuncInfo.first << "\n");
+ auto *FuncSummary = dyn_cast<FunctionSummary>(Summary);
+ if (!FuncSummary)
+ // Skip import for global variables
+ continue;
+ DEBUG(dbgs() << "Initalize import for " << GVInfo.first << "\n");
computeImportForFunction(*FuncSummary, Index, ImportInstrLimit,
- DefinedFunctions, Worklist, ImportsForModule,
+ DefinedGVSummaries, Worklist, ImportsForModule,
ExportLists);
}
@@ -242,7 +245,7 @@ static void ComputeImportForModule(
// Adjust the threshold
Threshold = Threshold * ImportInstrFactor;
- computeImportForFunction(*Summary, Index, Threshold, DefinedFunctions,
+ computeImportForFunction(*Summary, Index, Threshold, DefinedGVSummaries,
Worklist, ImportsForModule, ExportLists);
}
}
@@ -252,38 +255,16 @@ static void ComputeImportForModule(
/// Compute all the import and export for every module using the Index.
void llvm::ComputeCrossModuleImport(
const ModuleSummaryIndex &Index,
+ const StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>> &
+ ModuleToDefinedGVSummaries,
StringMap<FunctionImporter::ImportMapTy> &ImportLists,
StringMap<FunctionImporter::ExportSetTy> &ExportLists) {
- auto ModuleCount = Index.modulePaths().size();
-
- // Collect for each module the list of function it defines.
- // GUID -> Summary
- StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
- Module2FunctionInfoMap(ModuleCount);
-
- for (auto &GlobalList : Index) {
- auto GUID = GlobalList.first;
- for (auto &GlobInfo : GlobalList.second) {
- 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;
- }
- }
-
// For each module that has function defined, compute the import/export lists.
- for (auto &DefinedFunctions : Module2FunctionInfoMap) {
- auto &ImportsForModule = ImportLists[DefinedFunctions.first()];
- DEBUG(dbgs() << "Computing import for Module '" << DefinedFunctions.first()
- << "'\n");
- ComputeImportForModule(DefinedFunctions.second, Index, ImportsForModule,
+ for (auto &DefinedGVSummaries : ModuleToDefinedGVSummaries) {
+ auto &ImportsForModule = ImportLists[DefinedGVSummaries.first()];
+ DEBUG(dbgs() << "Computing import for Module '"
+ << DefinedGVSummaries.first() << "'\n");
+ ComputeImportForModule(DefinedGVSummaries.second, Index, ImportsForModule,
&ExportLists);
}
More information about the llvm-commits
mailing list