[LTO] Perform DSOLocal propagation in combined index

Perform DSOLocal propagation within summary list of every GV. This
avoids the repeated query of this information during function
importing.

Differential Revision: https://reviews.llvm.org/D96398
This commit is contained in:
Wei Wang 2021-02-09 21:14:43 -08:00
parent 1f6ec3d08f
commit 80dc0661bd
8 changed files with 56 additions and 23 deletions

View File

@ -228,7 +228,9 @@ struct ValueInfo {
/// 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 @@ private:
/// 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 @@ public:
WithAttributePropagation = true;
}
bool withDSOLocalPropagation() const { return WithDSOLocalPropagation; }
void setWithDSOLocalPropagation() { WithDSOLocalPropagation = true; }
bool isReadOnly(const GlobalVarSummary *GVS) const {
return WithAttributePropagation && GVS->maybeReadOnly();
}
@ -1513,7 +1522,7 @@ public:
/// Print out strongly connected components for debugging.
void dumpSCCs(raw_ostream &OS);
/// Analyze index and detect unmodified globals
/// Do the access attribute and DSOLocal propagation in combined index.
void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
/// Checks if we can import global variable from another module.

View File

@ -6845,7 +6845,7 @@ static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
case bitc::FS_FLAGS: { // [flags]
uint64_t Flags = Record[0];
// Scan flags.
assert(Flags <= 0x3f && "Unexpected bits in flag");
assert(Flags <= 0x7f && "Unexpected bits in flag");
return Flags & 0x8;
}

View File

@ -52,13 +52,17 @@ GlobalValue::VisibilityTypes ValueInfo::getELFVisibility() const {
: 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<GlobalValueSummary> &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<GlobalValueSummary> &Summary) {
return Summary->isDSOLocal();
});
}
bool ValueInfo::canAutoHide() const {
@ -100,11 +104,13 @@ uint64_t ModuleSummaryIndex::getFlags() const {
Flags |= 0x10;
if (withAttributePropagation())
Flags |= 0x20;
if (withDSOLocalPropagation())
Flags |= 0x40;
return Flags;
}
void ModuleSummaryIndex::setFlags(uint64_t Flags) {
assert(Flags <= 0x3f && "Unexpected bits in flag");
assert(Flags <= 0x7f && "Unexpected bits in flag");
// 1 bit: WithGlobalValueDeadStripping flag.
// Set on combined index only.
if (Flags & 0x1)
@ -130,6 +136,10 @@ void ModuleSummaryIndex::setFlags(uint64_t Flags) {
// Set on combined index only.
if (Flags & 0x20)
setWithAttributePropagation();
// 1 bit: WithDSOLocalPropagation flag.
// Set on combined index only.
if (Flags & 0x40)
setWithDSOLocalPropagation();
}
// Collect for the given module the list of function it defines
@ -205,7 +215,7 @@ propagateAttributesToRefs(GlobalValueSummary *S,
}
}
// 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 +226,7 @@ propagateAttributesToRefs(GlobalValueSummary *S,
// 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 +235,7 @@ propagateAttributesToRefs(GlobalValueSummary *S,
// 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 +247,8 @@ void ModuleSummaryIndex::propagateAttributes(
if (!PropagateAttrs)
return;
DenseSet<ValueInfo> 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 +285,20 @@ void ModuleSummaryIndex::propagateAttributes(
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<GlobalValueSummary> &Summary) {
return Summary->setDSOLocal(false);
});
}
setWithAttributePropagation();
setWithDSOLocalPropagation();
if (llvm::AreStatisticsEnabled())
for (auto &P : *this)
if (P.second.SummaryList.size())

View File

@ -207,7 +207,7 @@ void llvm::computeLTOCacheKey(
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<GlobalVarSummary>(GS)) {
@ -226,7 +226,7 @@ void llvm::computeLTOCacheKey(
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());
}
}

View File

@ -279,7 +279,7 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
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);

View File

@ -5,8 +5,8 @@ source_filename = "tmp.bc"
; RUN: llvm-as %s -o - | llvm-dis -o - | FileCheck %s
; CHECK: ^0 = module
; CHECK-NEXT: ^1 = gv
; CHECK-NEXT: ^2 = flags: 33
; CHECK-NEXT: ^2 = flags: 97
^0 = module: (path: "main.bc", hash: (3499594384, 1671013073, 3271036935, 1830411232, 59290952))
^1 = gv: (guid: 15822663052811949562, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), insts: 2)))
^2 = flags: 33
^2 = flags: 97

View File

@ -5,14 +5,14 @@
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
; RUN: -r %t.o,glob,plx
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=WITHDEAD
; WITHDEAD: <FLAGS op0=33/>
; WITHDEAD: <FLAGS op0=97/>
; Ensure dead stripping performed flag is not set on distributed index
; when option used to disable dead stripping computation.
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
; RUN: -r %t.o,glob,plx -compute-dead=false
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=NODEAD
; NODEAD: <FLAGS op0=32/>
; NODEAD: <FLAGS op0=96/>
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -5,7 +5,7 @@
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
; RUN: -r %t.o,glob,plx -compute-dead=false
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=NOSYNTHETIC
; NOSYNTHETIC: <FLAGS op0=32/>
; NOSYNTHETIC: <FLAGS op0=96/>
; Ensure synthetic entry count flag is set on distributed index
; when option used to enable synthetic count propagation
@ -13,7 +13,7 @@
; RUN: -r %t.o,glob,plx -thinlto-synthesize-entry-counts \
; RUN: -compute-dead=false
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=HASSYNTHETIC
; HASSYNTHETIC: <FLAGS op0=36/>
; HASSYNTHETIC: <FLAGS op0=100/>
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"