Skip to content

Commit dde5893

Browse files
committed
[ThinLTO] Import readonly vars with refs
Patch allows importing declarations of functions and variables, referenced by the initializer of some other readonly variable. Differential revision: https://reviews.llvm.org/D69561
1 parent 7ff5770 commit dde5893

File tree

12 files changed

+76
-31
lines changed

12 files changed

+76
-31
lines changed

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,11 @@ class ModuleSummaryIndex {
941941
/// considered live.
942942
bool WithGlobalValueDeadStripping = false;
943943

944+
/// Indicates that summary-based attribute propagation has run and
945+
/// GVarFlags::MaybeReadonly / GVarFlags::MaybeWriteonly are really
946+
/// read/write only.
947+
bool WithAttributePropagation = false;
948+
944949
/// Indicates that summary-based synthetic entry count propagation has run
945950
bool HasSyntheticEntryCounts = false;
946951

@@ -1065,6 +1070,18 @@ class ModuleSummaryIndex {
10651070
WithGlobalValueDeadStripping = true;
10661071
}
10671072

1073+
bool withAttributePropagation() const { return WithAttributePropagation; }
1074+
void setWithAttributePropagation() {
1075+
WithAttributePropagation = true;
1076+
}
1077+
1078+
bool isReadOnly(const GlobalVarSummary *GVS) const {
1079+
return WithAttributePropagation && GVS->maybeReadOnly();
1080+
}
1081+
bool isWriteOnly(const GlobalVarSummary *GVS) const {
1082+
return WithAttributePropagation && GVS->maybeWriteOnly();
1083+
}
1084+
10681085
bool hasSyntheticEntryCounts() const { return HasSyntheticEntryCounts; }
10691086
void setHasSyntheticEntryCounts() { HasSyntheticEntryCounts = true; }
10701087

@@ -1356,6 +1373,9 @@ class ModuleSummaryIndex {
13561373

13571374
/// Analyze index and detect unmodified globals
13581375
void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
1376+
1377+
/// Checks if we can import global variable from another module.
1378+
bool canImportGlobalVar(GlobalValueSummary *S, bool AnalyzeRefs) const;
13591379
};
13601380

13611381
/// GraphTraits definition to build SCC for the index
@@ -1427,15 +1447,6 @@ struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
14271447
return ValueInfo(I->haveGVs(), &P);
14281448
}
14291449
};
1430-
1431-
static inline bool canImportGlobalVar(GlobalValueSummary *S) {
1432-
assert(isa<GlobalVarSummary>(S->getBaseObject()));
1433-
1434-
// We don't import GV with references, because it can result
1435-
// in promotion of local variables in the source module.
1436-
return !GlobalValue::isInterposableLinkage(S->linkage()) &&
1437-
!S->notEligibleToImport() && S->refs().empty();
1438-
}
14391450
} // end namespace llvm
14401451

14411452
#endif // LLVM_IR_MODULESUMMARYINDEX_H

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5761,7 +5761,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
57615761
}
57625762
const uint64_t Version = Record[0];
57635763
const bool IsOldProfileFormat = Version == 1;
5764-
if (Version < 1 || Version > 7)
5764+
if (Version < 1 || Version > 8)
57655765
return error("Invalid summary version " + Twine(Version) +
57665766
". Version should be in the range [1-7].");
57675767
Record.clear();
@@ -5814,7 +5814,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
58145814
case bitc::FS_FLAGS: { // [flags]
58155815
uint64_t Flags = Record[0];
58165816
// Scan flags.
5817-
assert(Flags <= 0x1f && "Unexpected bits in flag");
5817+
assert(Flags <= 0x3f && "Unexpected bits in flag");
58185818

58195819
// 1 bit: WithGlobalValueDeadStripping flag.
58205820
// Set on combined index only.
@@ -5837,6 +5837,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
58375837
// Set on combined index only.
58385838
if (Flags & 0x10)
58395839
TheIndex.setPartiallySplitLTOUnits();
5840+
// 1 bit: WithAttributePropagation flag.
5841+
// Set on combined index only.
5842+
if (Flags & 0x20)
5843+
TheIndex.setWithAttributePropagation();
58405844
break;
58415845
}
58425846
case bitc::FS_VALUE_GUID: { // [valueid, refguid]
@@ -6542,7 +6546,7 @@ static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
65426546
case bitc::FS_FLAGS: { // [flags]
65436547
uint64_t Flags = Record[0];
65446548
// Scan flags.
6545-
assert(Flags <= 0x1f && "Unexpected bits in flag");
6549+
assert(Flags <= 0x3f && "Unexpected bits in flag");
65466550

65476551
return Flags & 0x8;
65486552
}

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3723,7 +3723,7 @@ void ModuleBitcodeWriterBase::writeModuleLevelReferences(
37233723
// Current version for the summary.
37243724
// This is bumped whenever we introduce changes in the way some record are
37253725
// interpreted, like flags for instance.
3726-
static const uint64_t INDEX_VERSION = 7;
3726+
static const uint64_t INDEX_VERSION = 8;
37273727

37283728
/// Emit the per-module summary section alongside the rest of
37293729
/// the module's bitcode.
@@ -3899,6 +3899,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
38993899
Flags |= 0x8;
39003900
if (Index.partiallySplitLTOUnits())
39013901
Flags |= 0x10;
3902+
if (Index.withAttributePropagation())
3903+
Flags |= 0x20;
39023904
Stream.EmitRecord(bitc::FS_FLAGS, ArrayRef<uint64_t>{Flags});
39033905

39043906
for (const auto &GVI : valueIds()) {

llvm/lib/IR/ModuleSummaryIndex.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,9 @@ void ModuleSummaryIndex::propagateAttributes(
172172
// assembly leading it to be in the @llvm.*used).
173173
if (auto *GVS = dyn_cast<GlobalVarSummary>(S->getBaseObject()))
174174
// Here we intentionally pass S.get() not GVS, because S could be
175-
// an alias.
176-
if (!canImportGlobalVar(S.get()) ||
175+
// an alias. We don't analyze references here, because we have to
176+
// know exactly if GV is readonly to do so.
177+
if (!canImportGlobalVar(S.get(), /* AnalyzeRefs */ false) ||
177178
GUIDPreservedSymbols.count(P.first)) {
178179
GVS->setReadOnly(false);
179180
GVS->setWriteOnly(false);
@@ -193,6 +194,23 @@ void ModuleSummaryIndex::propagateAttributes(
193194
}
194195
}
195196

197+
bool ModuleSummaryIndex::canImportGlobalVar(GlobalValueSummary *S,
198+
bool AnalyzeRefs) const {
199+
auto HasRefsPreventingImport = [this](const GlobalVarSummary *GVS) {
200+
return !isReadOnly(GVS) && GVS->refs().size();
201+
};
202+
auto *GVS = cast<GlobalVarSummary>(S->getBaseObject());
203+
204+
// Global variable with non-trivial initializer can be imported
205+
// if it's readonly. This gives us extra opportunities for constant
206+
// folding and converting indirect calls to direct calls. We don't
207+
// analyze GV references during attribute propagation, because we
208+
// don't know yet if it is readonly or not.
209+
return !GlobalValue::isInterposableLinkage(S->linkage()) &&
210+
!S->notEligibleToImport() &&
211+
(!AnalyzeRefs || !HasRefsPreventingImport(GVS));
212+
}
213+
196214
// TODO: write a graphviz dumper for SCCs (see ModuleSummaryIndex::exportToDot)
197215
// then delete this function and update its tests
198216
LLVM_DUMP_METHOD

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ updateValueInfoForIndirectCalls(const ModuleSummaryIndex &Index, ValueInfo VI) {
280280
}
281281

282282
static void computeImportForReferencedGlobals(
283-
const FunctionSummary &Summary, const GVSummaryMapTy &DefinedGVSummaries,
283+
const FunctionSummary &Summary, const ModuleSummaryIndex &Index,
284+
const GVSummaryMapTy &DefinedGVSummaries,
284285
FunctionImporter::ImportMapTy &ImportList,
285286
StringMap<FunctionImporter::ExportSetTy> *ExportLists) {
286287
for (auto &VI : Summary.refs()) {
@@ -303,16 +304,24 @@ static void computeImportForReferencedGlobals(
303304
RefSummary->modulePath() != Summary.modulePath();
304305
};
305306

307+
auto MarkExported = [&](const ValueInfo &VI, const GlobalValueSummary *S) {
308+
if (ExportLists)
309+
(*ExportLists)[S->modulePath()].insert(VI.getGUID());
310+
};
311+
306312
for (auto &RefSummary : VI.getSummaryList())
307313
if (isa<GlobalVarSummary>(RefSummary.get()) &&
308-
canImportGlobalVar(RefSummary.get()) &&
314+
Index.canImportGlobalVar(RefSummary.get(), /* AnalyzeRefs */ true) &&
309315
!LocalNotInModule(RefSummary.get())) {
310316
auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID());
311317
// Only update stat if we haven't already imported this variable.
312318
if (ILI.second)
313319
NumImportedGlobalVarsThinLink++;
314-
if (ExportLists)
315-
(*ExportLists)[RefSummary->modulePath()].insert(VI.getGUID());
320+
MarkExported(VI, RefSummary.get());
321+
// Promote referenced functions and variables
322+
for (const auto &VI : RefSummary->refs())
323+
for (const auto &RefFn : VI.getSummaryList())
324+
MarkExported(VI, RefFn.get());
316325
break;
317326
}
318327
}
@@ -351,8 +360,8 @@ static void computeImportForFunction(
351360
FunctionImporter::ImportMapTy &ImportList,
352361
StringMap<FunctionImporter::ExportSetTy> *ExportLists,
353362
FunctionImporter::ImportThresholdsTy &ImportThresholds) {
354-
computeImportForReferencedGlobals(Summary, DefinedGVSummaries, ImportList,
355-
ExportLists);
363+
computeImportForReferencedGlobals(Summary, Index, DefinedGVSummaries,
364+
ImportList, ExportLists);
356365
static int ImportCount = 0;
357366
for (auto &Edge : Summary.calls()) {
358367
ValueInfo VI = Edge.first;
@@ -864,6 +873,7 @@ void llvm::computeDeadSymbolsWithConstProp(
864873
GVS->setWriteOnly(false);
865874
}
866875
}
876+
Index.setWithAttributePropagation();
867877
}
868878

869879
/// Compute the set of summaries needed for a ThinLTO backend compilation of

llvm/lib/Transforms/Utils/FunctionImportUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
238238
// If global value dead stripping is not enabled in summary then
239239
// propagateConstants hasn't been run. We can't internalize GV
240240
// in such case.
241-
if (!GV.isDeclaration() && VI && ImportIndex.withGlobalValueDeadStripping()) {
241+
if (!GV.isDeclaration() && VI && ImportIndex.withAttributePropagation()) {
242242
if (GlobalVariable *V = dyn_cast<GlobalVariable>(&GV)) {
243243
// We can have more than one local with the same GUID, in the case of
244244
// same-named locals in different but same-named source files that were
@@ -252,7 +252,7 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
252252
auto* GVS = dyn_cast_or_null<GlobalVarSummary>(
253253
ImportIndex.findSummaryInModule(VI, M.getModuleIdentifier()));
254254
// At this stage "maybe" is "definitely"
255-
if (GVS && (GVS->maybeReadOnly() || GVS->maybeWriteOnly()))
255+
if (GVS && (ImportIndex.isReadOnly(GVS) || ImportIndex.isWriteOnly(GVS)))
256256
V->addAttribute("thinlto-internalize");
257257
}
258258
}

llvm/test/Bitcode/summary_version.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; RUN: opt -module-summary %s -o - | llvm-bcanalyzer -dump | FileCheck %s
33

44
; CHECK: <GLOBALVAL_SUMMARY_BLOCK
5-
; CHECK: <VERSION op0=7/>
5+
; CHECK: <VERSION op0=8/>
66

77

88

llvm/test/Bitcode/thinlto-deadstrip-flag.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
66
; RUN: -r %t.o,glob,plx
77
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=WITHDEAD
8-
; WITHDEAD: <FLAGS op0=1/>
8+
; WITHDEAD: <FLAGS op0=33/>
99

1010
; Ensure dead stripping performed flag is not set on distributed index
1111
; when option used to disable dead stripping computation.
1212
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
1313
; RUN: -r %t.o,glob,plx -compute-dead=false
1414
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=NODEAD
15-
; NODEAD: <FLAGS op0=0/>
15+
; NODEAD: <FLAGS op0=32/>
1616

1717
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
1818
target triple = "x86_64-unknown-linux-gnu"

llvm/test/Bitcode/thinlto-synthetic-count-flag.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
66
; RUN: -r %t.o,glob,plx -compute-dead=false
77
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=NOSYNTHETIC
8-
; NOSYNTHETIC: <FLAGS op0=0/>
8+
; NOSYNTHETIC: <FLAGS op0=32/>
99

1010
; Ensure synthetic entry count flag is set on distributed index
1111
; when option used to enable synthetic count propagation
1212
; RUN: llvm-lto2 run %t.o -o %t.out -thinlto-distributed-indexes \
1313
; RUN: -r %t.o,glob,plx -thinlto-synthesize-entry-counts \
1414
; RUN: -compute-dead=false
1515
; RUN: llvm-bcanalyzer -dump %t.o.thinlto.bc | FileCheck %s --check-prefix=HASSYNTHETIC
16-
; HASSYNTHETIC: <FLAGS op0=4/>
16+
; HASSYNTHETIC: <FLAGS op0=36/>
1717

1818
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
1919
target triple = "x86_64-unknown-linux-gnu"

llvm/test/ThinLTO/X86/globals-import.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
; RUN: llvm-dis %t2.bc.thinlto.promoted.bc -o - | FileCheck --check-prefix=PROMOTE1 %s
1616
; RUN: llvm-dis %t2b.bc.thinlto.promoted.bc -o - | FileCheck --check-prefix=PROMOTE2 %s
1717

18-
; IMPORT: @baz.llvm.0 = available_externally hidden constant i32 10, align 4
18+
; IMPORT: @baz.llvm.0 = internal constant i32 10, align 4
1919

2020
; PROMOTE1: @baz.llvm.0 = hidden constant i32 10, align 4
2121
; PROMOTE1: define weak_odr i32 @foo() {

llvm/test/ThinLTO/X86/local_name_conflict.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
; that module (%t3.bc) to be imported. Check that the imported reference's
1313
; promoted name matches the imported copy.
1414
; RUN: llvm-lto -thinlto-action=import %t.bc -thinlto-index=%t4.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORT
15-
; IMPORT: @baz.llvm.[[HASH:[0-9]+]] = available_externally hidden constant i32 10, align 4
15+
; IMPORT: @baz.llvm.[[HASH:[0-9]+]] = internal constant i32 10, align 4
1616
; IMPORT: call i32 @foo.llvm.[[HASH]]
1717
; IMPORT: define available_externally hidden i32 @foo.llvm.[[HASH]]()
1818

llvm/test/tools/gold/X86/v1.12/thinlto_emit_linked_objects.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
; should not be set.
3636
; RUN: llvm-bcanalyzer --dump %t1.o.thinlto.bc | FileCheck %s -check-prefixes=CHECK-BC1
3737
; CHECK-BC1: <GLOBALVAL_SUMMARY_BLOCK
38-
; CHECK-BC1: <FLAGS op0=1/>
38+
; CHECK-BC1: <FLAGS op0=33/>
3939
; CHECK-BC1: </GLOBALVAL_SUMMARY_BLOCK
4040

4141
; Nothing interesting in the corresponding object file, so

0 commit comments

Comments
 (0)