diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -228,7 +228,9 @@ /// protected and hidden. GlobalValue::VisibilityTypes getELFVisibility() const; - bool isDSOLocal() const; + /// Checks if all summaries are DSO local (have the flag set). When DSOLocal + /// propagation has been done, set the parameter to enable fast check. + bool isDSOLocal(bool WithDSOLocalPropagation = false) const; /// Checks if all copies are eligible for auto-hiding (have flag set). bool canAutoHide() const; @@ -1055,6 +1057,10 @@ /// read/write only. bool WithAttributePropagation = false; + /// Indicates that summary-based DSOLocal propagation has run and the flag in + /// every summary of a GV is synchronized. + bool WithDSOLocalPropagation = false; + /// Indicates that summary-based synthetic entry count propagation has run bool HasSyntheticEntryCounts = false; @@ -1210,6 +1216,9 @@ WithAttributePropagation = true; } + bool withDSOLocalPropagation() const { return WithDSOLocalPropagation; } + void setWithDSOLocalPropagation() { WithDSOLocalPropagation = true; } + bool isReadOnly(const GlobalVarSummary *GVS) const { return WithAttributePropagation && GVS->maybeReadOnly(); } diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -52,13 +52,17 @@ : GlobalValue::DefaultVisibility; } -bool ValueInfo::isDSOLocal() const { - // Need to check all summaries are local in case of hash collisions. - return getSummaryList().size() && - llvm::all_of(getSummaryList(), - [](const std::unique_ptr &Summary) { - return Summary->isDSOLocal(); - }); +bool ValueInfo::isDSOLocal(bool WithDSOLocalPropagation) const { + // With DSOLocal propagation done, the flag in evey summary is the same. + // Check the first one is enough. + return WithDSOLocalPropagation + ? getSummaryList().size() && getSummaryList()[0]->isDSOLocal() + : getSummaryList().size() && + llvm::all_of( + getSummaryList(), + [](const std::unique_ptr &Summary) { + return Summary->isDSOLocal(); + }); } bool ValueInfo::canAutoHide() const { @@ -205,7 +209,7 @@ } } -// Do the access attribute propagation in combined index. +// Do the access attribute and DSOLocal propagation in combined index. // The goal of attribute propagation is internalization of readonly (RO) // or writeonly (WO) variables. To determine which variables are RO or WO // and which are not we take following steps: @@ -216,7 +220,7 @@ // or doesn't read it (writeonly). // // - After computing dead symbols in combined index we do the attribute -// propagation. During this step we: +// and DSOLocal propagation. During this step we: // a. clear RO and WO attributes from variables which are preserved or // can't be imported // b. clear RO and WO attributes from variables referenced by any global @@ -225,6 +229,7 @@ // reference is not readonly // d. clear WO attribute from variable referenced by a function when // reference is not writeonly +// e. clear IsDSOLocal flag in every summary if any of them is false. // // Because of (c, d) we don't internalize variables read by function A // and modified by function B. @@ -236,7 +241,8 @@ if (!PropagateAttrs) return; DenseSet MarkedNonReadWriteOnly; - for (auto &P : *this) + for (auto &P : *this) { + bool IsDSOLocal = true; for (auto &S : P.second.SummaryList) { if (!isGlobalValueLive(S.get())) { // computeDeadSymbols should have marked all copies live. Note that @@ -273,8 +279,20 @@ GVS->setWriteOnly(false); } propagateAttributesToRefs(S.get(), MarkedNonReadWriteOnly); + + // If the flag from any summary is false, the GV is not DSOLocal. + IsDSOLocal &= S->isDSOLocal(); } + if (!IsDSOLocal) + // Mark the flag in all summaries false so that we can do quick check + // without going through the whole list. + llvm::for_each(P.second.SummaryList, + [](const std::unique_ptr &Summary) { + return Summary->setDSOLocal(false); + }); + } setWithAttributePropagation(); + setWithDSOLocalPropagation(); if (llvm::AreStatisticsEnabled()) for (auto &P : *this) if (P.second.SummaryList.size()) diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -207,7 +207,7 @@ AddUnsigned(GS->isLive()); AddUnsigned(GS->canAutoHide()); for (const ValueInfo &VI : GS->refs()) { - AddUnsigned(VI.isDSOLocal()); + AddUnsigned(VI.isDSOLocal(Index.withDSOLocalPropagation())); AddUsedCfiGlobal(VI.getGUID()); } if (auto *GVS = dyn_cast(GS)) { @@ -226,7 +226,7 @@ for (auto &TT : FS->type_checked_load_const_vcalls()) UsedTypeIds.insert(TT.VFunc.GUID); for (auto &ET : FS->calls()) { - AddUnsigned(ET.first.isDSOLocal()); + AddUnsigned(ET.first.isDSOLocal(Index.withDSOLocalPropagation())); AddUsedCfiGlobal(ET.first.getGUID()); } } diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -279,7 +279,7 @@ if (ClearDSOLocalOnDeclarations && GV.isDeclarationForLinker() && !GV.isImplicitDSOLocal()) { GV.setDSOLocal(false); - } else if (VI && VI.isDSOLocal()) { + } else if (VI && VI.isDSOLocal(ImportIndex.withDSOLocalPropagation())) { // If all summaries are dso_local, symbol gets resolved to a known local // definition. GV.setDSOLocal(true);