diff options
author | evgeny <eleviant@accesssoftek.com> | 2019-11-08 20:50:34 +0300 |
---|---|---|
committer | evgeny <eleviant@accesssoftek.com> | 2019-11-08 20:50:34 +0300 |
commit | 7f92d66f378574ab2a02935b6614560ae9000539 (patch) | |
tree | 02f3b59559b0e6db29d6ec6b4fcc2382a144a08c /llvm/lib | |
parent | caad2170aed76d1df8b4305b1b7d81c4943626db (diff) | |
download | llvm-7f92d66f378574ab2a02935b6614560ae9000539.zip llvm-7f92d66f378574ab2a02935b6614560ae9000539.tar.gz llvm-7f92d66f378574ab2a02935b6614560ae9000539.tar.bz2 |
[ThinLTO] Fix bug when importing writeonly variables
Patch enables import of write-only variables with non-trivial initializers
to fix linker errors. Initializers of imported variables are converted to
'zeroinitializer' to avoid promotion of referenced objects.
Differential revision: https://reviews.llvm.org/D70006
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/IR/ModuleSummaryIndex.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionImport.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/FunctionImportUtils.cpp | 17 |
3 files changed, 37 insertions, 8 deletions
diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp index d82d2e9..b575b5b6 100644 --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -197,7 +197,21 @@ void ModuleSummaryIndex::propagateAttributes( bool ModuleSummaryIndex::canImportGlobalVar(GlobalValueSummary *S, bool AnalyzeRefs) const { auto HasRefsPreventingImport = [this](const GlobalVarSummary *GVS) { - return !isReadOnly(GVS) && GVS->refs().size(); + // We don't analyze GV references during attribute propagation, so + // GV with non-trivial initializer can be marked either read or + // write-only. + // Importing definiton of readonly GV with non-trivial initializer + // allows us doing some extra optimizations (like converting indirect + // calls to direct). + // Definition of writeonly GV with non-trivial initializer should also + // be imported. Not doing so will result in: + // a) GV internalization in source module (because it's writeonly) + // b) Importing of GV declaration to destination module as a result + // of promotion. + // c) Link error (external declaration with internal definition). + // However we do not promote objects referenced by writeonly GV + // initializer by means of converting it to 'zeroinitializer' + return !isReadOnly(GVS) && !isWriteOnly(GVS) && GVS->refs().size(); }; auto *GVS = cast<GlobalVarSummary>(S->getBaseObject()); diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index afc31bf..83b03a0 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -318,10 +318,14 @@ static void computeImportForReferencedGlobals( if (ILI.second) NumImportedGlobalVarsThinLink++; MarkExported(VI, RefSummary.get()); - // Promote referenced functions and variables - for (const auto &VI : RefSummary->refs()) - for (const auto &RefFn : VI.getSummaryList()) - MarkExported(VI, RefFn.get()); + // Promote referenced functions and variables. We don't promote + // objects referenced by writeonly variable initializer, because + // we convert such variables initializers to "zeroinitializer". + // See processGlobalForThinLTO. + if (!Index.isWriteOnly(cast<GlobalVarSummary>(RefSummary.get()))) + for (const auto &VI : RefSummary->refs()) + for (const auto &RefFn : VI.getSummaryList()) + MarkExported(VI, RefFn.get()); break; } } diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp index dc98591..401be68 100644 --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/FunctionImportUtils.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/InstIterator.h" using namespace llvm; @@ -250,10 +251,20 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { // We might have a non-null VI and get here even in that case if the name // matches one in this module (e.g. weak or appending linkage). auto* GVS = dyn_cast_or_null<GlobalVarSummary>( - ImportIndex.findSummaryInModule(VI, M.getModuleIdentifier())); - // At this stage "maybe" is "definitely" - if (GVS && (ImportIndex.isReadOnly(GVS) || ImportIndex.isWriteOnly(GVS))) + ImportIndex.findSummaryInModule(VI, M.getModuleIdentifier())); + if (GVS && + (ImportIndex.isReadOnly(GVS) || ImportIndex.isWriteOnly(GVS))) { V->addAttribute("thinlto-internalize"); + // Objects referenced by writeonly GV initializer should not be + // promoted, because there is no any kind of read access to them + // on behalf of this writeonly GV. To avoid promotion we convert + // GV initializer to 'zeroinitializer'. This effectively drops + // references in IR module (not in combined index), so we can + // ignore them when computing import. We do not export references + // of writeonly object. See computeImportForReferencedGlobals + if (ImportIndex.isWriteOnly(GVS) && GVS->refs().size()) + V->setInitializer(Constant::getNullValue(V->getValueType())); + } } } |