summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/IPO/FunctionImport.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Transforms/IPO/FunctionImport.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Transforms/IPO/FunctionImport.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/FunctionImport.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 18343030bc6a..2f6cf0ca7087 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -84,6 +84,10 @@ static cl::opt<int> ImportCutoff(
"import-cutoff", cl::init(-1), cl::Hidden, cl::value_desc("N"),
cl::desc("Only import first N functions if N>=0 (default -1)"));
+static cl::opt<bool>
+ ForceImportAll("force-import-all", cl::init(false), cl::Hidden,
+ cl::desc("Import functions with noinline attribute"));
+
static cl::opt<float>
ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7),
cl::Hidden, cl::value_desc("x"),
@@ -227,7 +231,7 @@ selectCallee(const ModuleSummaryIndex &Index,
}
if ((Summary->instCount() > Threshold) &&
- !Summary->fflags().AlwaysInline) {
+ !Summary->fflags().AlwaysInline && !ForceImportAll) {
Reason = FunctionImporter::ImportFailureReason::TooLarge;
return false;
}
@@ -240,7 +244,7 @@ selectCallee(const ModuleSummaryIndex &Index,
}
// Don't bother importing if we can't inline it anyway.
- if (Summary->fflags().NoInline) {
+ if (Summary->fflags().NoInline && !ForceImportAll) {
Reason = FunctionImporter::ImportFailureReason::NoInline;
return false;
}
@@ -275,6 +279,29 @@ updateValueInfoForIndirectCalls(const ModuleSummaryIndex &Index, ValueInfo VI) {
return Index.getValueInfo(GUID);
}
+static bool shouldImportGlobal(const ValueInfo &VI,
+ const GVSummaryMapTy &DefinedGVSummaries) {
+ const auto &GVS = DefinedGVSummaries.find(VI.getGUID());
+ if (GVS == DefinedGVSummaries.end())
+ return true;
+ // We should not skip import if the module contains a definition with
+ // interposable linkage type. This is required for correctness in
+ // the situation with two following conditions:
+ // * the def with interposable linkage is non-prevailing,
+ // * there is a prevailing def available for import and marked read-only.
+ // In this case, the non-prevailing def will be converted to a declaration,
+ // while the prevailing one becomes internal, thus no definitions will be
+ // available for linking. In order to prevent undefined symbol link error,
+ // the prevailing definition must be imported.
+ // FIXME: Consider adding a check that the suitable prevailing definition
+ // exists and marked read-only.
+ if (VI.getSummaryList().size() > 1 &&
+ GlobalValue::isInterposableLinkage(GVS->second->linkage()))
+ return true;
+
+ return false;
+}
+
static void computeImportForReferencedGlobals(
const GlobalValueSummary &Summary, const ModuleSummaryIndex &Index,
const GVSummaryMapTy &DefinedGVSummaries,
@@ -282,7 +309,7 @@ static void computeImportForReferencedGlobals(
FunctionImporter::ImportMapTy &ImportList,
StringMap<FunctionImporter::ExportSetTy> *ExportLists) {
for (auto &VI : Summary.refs()) {
- if (DefinedGVSummaries.count(VI.getGUID())) {
+ if (!shouldImportGlobal(VI, DefinedGVSummaries)) {
LLVM_DEBUG(
dbgs() << "Ref ignored! Target already in destination module.\n");
continue;
@@ -378,6 +405,9 @@ static void computeImportForFunction(
continue;
if (DefinedGVSummaries.count(VI.getGUID())) {
+ // FIXME: Consider not skipping import if the module contains
+ // a non-prevailing def with interposable linkage. The prevailing copy
+ // can safely be imported (see shouldImportGlobal()).
LLVM_DEBUG(dbgs() << "ignored! Target already in destination module.\n");
continue;
}
@@ -461,17 +491,28 @@ static void computeImportForFunction(
FailureInfo = std::make_unique<FunctionImporter::ImportFailureInfo>(
VI, Edge.second.getHotness(), Reason, 1);
}
- LLVM_DEBUG(
- dbgs() << "ignored! No qualifying callee with summary found.\n");
- continue;
+ if (ForceImportAll) {
+ std::string Msg = std::string("Failed to import function ") +
+ VI.name().str() + " due to " +
+ getFailureName(Reason);
+ auto Error = make_error<StringError>(
+ Msg, std::make_error_code(std::errc::operation_not_supported));
+ logAllUnhandledErrors(std::move(Error), errs(),
+ "Error importing module: ");
+ break;
+ } else {
+ LLVM_DEBUG(dbgs()
+ << "ignored! No qualifying callee with summary found.\n");
+ continue;
+ }
}
// "Resolve" the summary
CalleeSummary = CalleeSummary->getBaseObject();
ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
- assert((ResolvedCalleeSummary->fflags().AlwaysInline ||
- (ResolvedCalleeSummary->instCount() <= NewThreshold)) &&
+ assert((ResolvedCalleeSummary->fflags().AlwaysInline || ForceImportAll ||
+ (ResolvedCalleeSummary->instCount() <= NewThreshold)) &&
"selectCallee() didn't honor the threshold");
auto ExportModulePath = ResolvedCalleeSummary->modulePath();
@@ -888,7 +929,6 @@ void llvm::computeDeadSymbols(
while (!Worklist.empty()) {
auto VI = Worklist.pop_back_val();
for (auto &Summary : VI.getSummaryList()) {
- Summary->setLive(true);
if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
// If this is an alias, visit the aliasee VI to ensure that all copies
// are marked live and it is added to the worklist for further
@@ -1000,7 +1040,6 @@ bool llvm::convertToDeclaration(GlobalValue &GV) {
return true;
}
-/// Fixup prevailing symbol linkages in \p TheModule based on summary analysis.
void llvm::thinLTOResolvePrevailingInModule(
Module &TheModule, const GVSummaryMapTy &DefinedGlobals) {
auto updateLinkage = [&](GlobalValue &GV) {
@@ -1009,8 +1048,6 @@ void llvm::thinLTOResolvePrevailingInModule(
if (GS == DefinedGlobals.end())
return;
auto NewLinkage = GS->second->linkage();
- if (NewLinkage == GV.getLinkage())
- return;
if (GlobalValue::isLocalLinkage(GV.getLinkage()) ||
// Don't internalize anything here, because the code below
// lacks necessary correctness checks. Leave this job to
@@ -1020,6 +1057,16 @@ void llvm::thinLTOResolvePrevailingInModule(
GV.isDeclaration())
return;
+ // Set the potentially more constraining visibility computed from summaries.
+ // The DefaultVisibility condition is because older GlobalValueSummary does
+ // not record DefaultVisibility and we don't want to change protected/hidden
+ // to default.
+ if (GS->second->getVisibility() != GlobalValue::DefaultVisibility)
+ GV.setVisibility(GS->second->getVisibility());
+
+ if (NewLinkage == GV.getLinkage())
+ return;
+
// Check for a non-prevailing def that has interposable linkage
// (e.g. non-odr weak or linkonce). In that case we can't simply
// convert to available_externally, since it would lose the