summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/FunctionImport.cpp
diff options
context:
space:
mode:
authorevgeny <eleviant@accesssoftek.com>2019-11-14 12:24:05 +0300
committerevgeny <eleviant@accesssoftek.com>2019-11-14 12:24:05 +0300
commita2292cc537b561416c21e8d4017715d652c144cc (patch)
tree25a1ee4080caa66aaeec153b3d15289ee545317e /llvm/lib/Transforms/IPO/FunctionImport.cpp
parenteafe0cf5fa8255257bac3923237e62382610e6d6 (diff)
downloadbcm5719-llvm-a2292cc537b561416c21e8d4017715d652c144cc.tar.gz
bcm5719-llvm-a2292cc537b561416c21e8d4017715d652c144cc.zip
[ThinLTO] Add correctness check for RO/WO variable import
This patch adds an assertion check for exported read/write-only variables to be also in import list for module. If they aren't we may face linker errors, because read/write-only variables are internalized in their source modules. The patch also changes export lists to store ValueInfo instead of GUID for performance considerations. Differential revision: https://reviews.llvm.org/D70128
Diffstat (limited to 'llvm/lib/Transforms/IPO/FunctionImport.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/FunctionImport.cpp59
1 files changed, 43 insertions, 16 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index b22cf47a797..d5419e1a1b9 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -308,7 +308,7 @@ static void computeImportForReferencedGlobals(
auto MarkExported = [&](const ValueInfo &VI, const GlobalValueSummary *S) {
if (ExportLists)
- (*ExportLists)[S->modulePath()].insert(VI.getGUID());
+ (*ExportLists)[S->modulePath()].insert(VI);
};
for (auto &RefSummary : VI.getSummaryList())
@@ -497,7 +497,7 @@ static void computeImportForFunction(
// Make exports in the source module.
if (ExportLists) {
auto &ExportList = (*ExportLists)[ExportModulePath];
- ExportList.insert(VI.getGUID());
+ ExportList.insert(VI);
if (!PreviouslyImported) {
// This is the first time this function was exported from its source
// module, so mark all functions and globals it references as exported
@@ -505,14 +505,11 @@ static void computeImportForFunction(
// For efficiency, we unconditionally add all the referenced GUIDs
// to the ExportList for this module, and will prune out any not
// defined in the module later in a single pass.
- for (auto &Edge : ResolvedCalleeSummary->calls()) {
- auto CalleeGUID = Edge.first.getGUID();
- ExportList.insert(CalleeGUID);
- }
- for (auto &Ref : ResolvedCalleeSummary->refs()) {
- auto GUID = Ref.getGUID();
- ExportList.insert(GUID);
- }
+ for (auto &Edge : ResolvedCalleeSummary->calls())
+ ExportList.insert(Edge.first);
+
+ for (auto &Ref : ResolvedCalleeSummary->refs())
+ ExportList.insert(Ref);
}
}
}
@@ -630,6 +627,37 @@ static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index,
}
#endif
+static bool
+checkVariableImport(const ModuleSummaryIndex &Index,
+ StringMap<FunctionImporter::ImportMapTy> &ImportLists,
+ StringMap<FunctionImporter::ExportSetTy> &ExportLists) {
+
+ DenseSet<GlobalValue::GUID> FlattenedImports;
+
+ for (auto &ImportPerModule : ImportLists)
+ for (auto &ExportPerModule : ImportPerModule.second)
+ FlattenedImports.insert(ExportPerModule.second.begin(),
+ ExportPerModule.second.end());
+
+ // Checks that all GUIDs of read/writeonly vars we see in export lists
+ // are also in the import lists. Otherwise we my face linker undefs,
+ // because readonly and writeonly vars are internalized in their
+ // source modules.
+ auto IsReadOrWriteOnlyVar = [&](StringRef ModulePath, const ValueInfo &VI) {
+ auto *GVS = dyn_cast_or_null<GlobalVarSummary>(
+ Index.findSummaryInModule(VI, ModulePath));
+ return GVS && (Index.isReadOnly(GVS) || Index.isWriteOnly(GVS));
+ };
+
+ for (auto &ExportPerModule : ExportLists)
+ for (auto &VI : ExportPerModule.second)
+ if (!FlattenedImports.count(VI.getGUID()) &&
+ IsReadOrWriteOnlyVar(ExportPerModule.first(), VI))
+ return false;
+
+ return true;
+}
+
/// Compute all the import and export for every module using the Index.
void llvm::ComputeCrossModuleImport(
const ModuleSummaryIndex &Index,
@@ -654,14 +682,13 @@ void llvm::ComputeCrossModuleImport(
for (auto &ELI : ExportLists) {
const auto &DefinedGVSummaries =
ModuleToDefinedGVSummaries.lookup(ELI.first());
- for (auto EI = ELI.second.begin(); EI != ELI.second.end();) {
- if (!DefinedGVSummaries.count(*EI))
- EI = ELI.second.erase(EI);
- else
- ++EI;
- }
+ std::remove_if(ELI.second.begin(), ELI.second.end(),
+ [&](const ValueInfo &VI) {
+ return !DefinedGVSummaries.count(VI.getGUID());
+ });
}
+ assert(checkVariableImport(Index, ImportLists, ExportLists));
#ifndef NDEBUG
LLVM_DEBUG(dbgs() << "Import/Export lists for " << ImportLists.size()
<< " modules:\n");
OpenPOWER on IntegriCloud