Skip to content

Commit dda7333

Browse files
[ThinLTO]Record import type in GlobalValueSummary::GVFlags (#87597)
The motivating use case is to support import the function declaration across modules to construct call graph edges for indirect calls [1] when importing the function definition costs too much compile time (e.g., the function is too large has no `noinline` attribute). 1. Currently, when the compiled IR module doesn't have a function definition but its postlink combined summary contains the function summary or a global alias summary with this function as aliasee, the function definition will be imported from source module by IRMover. The implementation is in FunctionImporter::importFunctions [2] 2. In order for FunctionImporter to import a declaration of a function, both function summary and alias summary need to carry the def / decl state. Specifically, all existing summary fields doesn't differ across import modules, but the def / decl state of is decided by `<ImportModule, Function>`. This change encodes the def/decl state in `GlobalValueSummary::GVFlags`. In the subsequent changes 1. The indexing step `computeImportForModule` [3] will compute the set of definitions and the set of declarations for each module, and passing on the information to bitcode writer. 2. Bitcode writer will look up the def/decl state and sets the state when it writes out the flag value. This is demonstrated in #87600 3. Function importer will read the def/decl state when reading the combined summary to figure out two sets of global values, and IRMover will be updated to import the declaration (aka linkGlobalValuePrototype [4]) into the destination module. - The next change is #87600 [1] mentioned in rfc https://discourse.llvm.org/t/rfc-for-better-call-graph-sort-build-a-more-complete-call-graph-by-adding-more-indirect-call-edges/74029#support-cross-module-function-declaration-import-5 [2] https://github.com/llvm/llvm-project/blob/3b337242ee165554f0017b00671381ec5b1ba855/llvm/lib/Transforms/IPO/FunctionImport.cpp#L1608-L1764 [3] https://github.com/llvm/llvm-project/blob/3b337242ee165554f0017b00671381ec5b1ba855/llvm/lib/Transforms/IPO/FunctionImport.cpp#L856 [4] https://github.com/llvm/llvm-project/blob/3b337242ee165554f0017b00671381ec5b1ba855/llvm/lib/Linker/IRMover.cpp#L605
1 parent 999b9e6 commit dda7333

35 files changed

+241
-139
lines changed

clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
; Round trip it through llvm-as
3535
; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
3636
; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi-devirt.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
37-
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0))))))
37+
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 18, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2), typeCheckedLoadVCalls: (vFuncId: (^2, offset: 8), vFuncId: (^2, offset: 0))))))
3838
; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi"))))) ; guid = 7004155349499253778
3939

4040
; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \

clang/test/CodeGen/thinlto-distributed-cfi.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
; Round trip it through llvm-as
2525
; RUN: llvm-dis %t.o.thinlto.bc -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK-DIS
2626
; CHECK-DIS: ^0 = module: (path: "{{.*}}thinlto-distributed-cfi.ll.tmp.o", hash: ({{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}}))
27-
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2)))))
27+
; CHECK-DIS: ^1 = gv: (guid: 8346051122425466633, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 7, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0), typeIdInfo: (typeTests: (^2)))))
2828
; CHECK-DIS: ^2 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 7004155349499253778
2929

3030
; RUN: %clang_cc1 -triple x86_64-grtev4-linux-gnu \

clang/test/CodeGen/thinlto-funcattr-prop.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
; RUN: llvm-dis %t1.o.1.1.promote.bc -o - | FileCheck %s --check-prefix=CHECK-IR
1616

1717
;; Summary for call_extern. Note that llvm-lto2 writes out the index before propagation occurs so call_extern doesn't have its flags updated.
18-
; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), insts: 2, calls: ((callee: ^3)))))
18+
; CHECK-INDEX: ^2 = gv: (guid: 13959900437860518209, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 2, calls: ((callee: ^3)))))
1919
;; Summary for extern
20-
; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0))))
20+
; CHECK-INDEX: ^3 = gv: (guid: 14959766916849974397, summaries: (function: (module: ^1, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 1, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 1, mayThrow: 0, hasUnknownCall: 0, mustBeUnreachable: 0))))
2121

2222
;--- a.ll
2323
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

lld/test/ELF/lto/comdat-nodeduplicate.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@
5656
; IR_AB-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]]
5757

5858
;; Check extra attributes. b.bc:__profc_foo is prevailing, so it can be internalized.
59-
; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0),
60-
; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
59+
; IR_AB-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0),
60+
; IR_AB-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
6161

6262
; IR_ABC-DAG: gv: (name: "__profd_foo", {{.*}} guid = [[PROFD:[0-9]+]]
6363
; IR_ABC-DAG: gv: (name: "__profc_foo", {{.*}} guid = [[PROFC:[0-9]+]]
6464

6565
;; b.bc:__profc_foo prevails c.bc:__profc_foo, so it is exported and therefore not internalized.
66-
; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0),
67-
; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
66+
; IR_ABC-DAG: gv: (guid: [[PROFD]], summaries: (variable: (module: ^0, flags: (linkage: private, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0),
67+
; IR_ABC-DAG: gv: (guid: [[PROFC]], summaries: (variable: (module: ^0, flags: (linkage: weak, visibility: hidden, notEligibleToImport: 0, live: 1, dsoLocal: 1, canAutoHide: 0, importType: definition), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
6868

6969
;--- a.ll
7070
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ namespace llvm {
301301
bool &DSOLocal);
302302
void parseOptionalDSOLocal(bool &DSOLocal);
303303
void parseOptionalVisibility(unsigned &Res);
304+
bool parseOptionalImportType(lltok::Kind Kind,
305+
GlobalValueSummary::ImportKind &Res);
304306
void parseOptionalDLLStorageClass(unsigned &Res);
305307
bool parseOptionalCallingConv(unsigned &CC);
306308
bool parseOptionalAlignment(MaybeAlign &Alignment,

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ enum Kind {
370370
kw_live,
371371
kw_dsoLocal,
372372
kw_canAutoHide,
373+
kw_importType,
374+
kw_definition,
375+
kw_declaration,
373376
kw_function,
374377
kw_insts,
375378
kw_funcFlags,

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,18 @@ class GlobalValueSummary {
432432
/// Sububclass discriminator (for dyn_cast<> et al.)
433433
enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind };
434434

435+
enum ImportKind : unsigned {
436+
// The global value definition corresponding to the summary should be
437+
// imported from source module
438+
Definition = 0,
439+
440+
// When its definition doesn't exist in the destination module and not
441+
// imported (e.g., function is too large to be inlined), the global value
442+
// declaration corresponding to the summary should be imported, or the
443+
// attributes from summary should be annotated on the function declaration.
444+
Declaration = 1,
445+
};
446+
435447
/// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield.
436448
struct GVFlags {
437449
/// The linkage type of the associated global value.
@@ -472,14 +484,19 @@ class GlobalValueSummary {
472484
/// means the symbol was externally visible.
473485
unsigned CanAutoHide : 1;
474486

487+
/// This field is written by the ThinLTO indexing step to postlink combined
488+
/// summary. The value is interpreted as 'ImportKind' enum defined above.
489+
unsigned ImportType : 1;
490+
475491
/// Convenience Constructors
476492
explicit GVFlags(GlobalValue::LinkageTypes Linkage,
477493
GlobalValue::VisibilityTypes Visibility,
478494
bool NotEligibleToImport, bool Live, bool IsLocal,
479-
bool CanAutoHide)
495+
bool CanAutoHide, ImportKind ImportType)
480496
: Linkage(Linkage), Visibility(Visibility),
481497
NotEligibleToImport(NotEligibleToImport), Live(Live),
482-
DSOLocal(IsLocal), CanAutoHide(CanAutoHide) {}
498+
DSOLocal(IsLocal), CanAutoHide(CanAutoHide),
499+
ImportType(static_cast<unsigned>(ImportType)) {}
483500
};
484501

485502
private:
@@ -564,6 +581,12 @@ class GlobalValueSummary {
564581

565582
bool canAutoHide() const { return Flags.CanAutoHide; }
566583

584+
bool shouldImportAsDecl() const {
585+
return Flags.ImportType == GlobalValueSummary::ImportKind::Declaration;
586+
}
587+
588+
void setImportKind(ImportKind IK) { Flags.ImportType = IK; }
589+
567590
GlobalValue::VisibilityTypes getVisibility() const {
568591
return (GlobalValue::VisibilityTypes)Flags.Visibility;
569592
}
@@ -813,7 +836,7 @@ class FunctionSummary : public GlobalValueSummary {
813836
GlobalValue::LinkageTypes::AvailableExternallyLinkage,
814837
GlobalValue::DefaultVisibility,
815838
/*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false,
816-
/*CanAutoHide=*/false),
839+
/*CanAutoHide=*/false, GlobalValueSummary::ImportKind::Definition),
817840
/*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
818841
std::vector<ValueInfo>(), std::move(Edges),
819842
std::vector<GlobalValue::GUID>(),

llvm/include/llvm/IR/ModuleSummaryIndexYAML.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ template <> struct MappingTraits<TypeIdSummary> {
138138
struct FunctionSummaryYaml {
139139
unsigned Linkage, Visibility;
140140
bool NotEligibleToImport, Live, IsLocal, CanAutoHide;
141+
unsigned ImportType;
141142
std::vector<uint64_t> Refs;
142143
std::vector<uint64_t> TypeTests;
143144
std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
@@ -183,6 +184,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> {
183184
io.mapOptional("Live", summary.Live);
184185
io.mapOptional("Local", summary.IsLocal);
185186
io.mapOptional("CanAutoHide", summary.CanAutoHide);
187+
io.mapOptional("ImportType", summary.ImportType);
186188
io.mapOptional("Refs", summary.Refs);
187189
io.mapOptional("TypeTests", summary.TypeTests);
188190
io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
@@ -227,7 +229,8 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
227229
static_cast<GlobalValue::LinkageTypes>(FSum.Linkage),
228230
static_cast<GlobalValue::VisibilityTypes>(FSum.Visibility),
229231
FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal,
230-
FSum.CanAutoHide),
232+
FSum.CanAutoHide,
233+
static_cast<GlobalValueSummary::ImportKind>(FSum.ImportType)),
231234
/*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, Refs,
232235
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
233236
std::move(FSum.TypeTestAssumeVCalls),
@@ -251,9 +254,9 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
251254
static_cast<bool>(FSum->flags().NotEligibleToImport),
252255
static_cast<bool>(FSum->flags().Live),
253256
static_cast<bool>(FSum->flags().DSOLocal),
254-
static_cast<bool>(FSum->flags().CanAutoHide), Refs,
255-
FSum->type_tests(), FSum->type_test_assume_vcalls(),
256-
FSum->type_checked_load_vcalls(),
257+
static_cast<bool>(FSum->flags().CanAutoHide),
258+
FSum->flags().ImportType, Refs, FSum->type_tests(),
259+
FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(),
257260
FSum->type_test_assume_const_vcalls(),
258261
FSum->type_checked_load_const_vcalls()});
259262
}

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,8 @@ static void computeFunctionSummary(
635635
HasIndirBranchToBlockAddress || HasIFuncCall;
636636
GlobalValueSummary::GVFlags Flags(
637637
F.getLinkage(), F.getVisibility(), NotEligibleForImport,
638-
/* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable());
638+
/* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(),
639+
GlobalValueSummary::ImportKind::Definition);
639640
FunctionSummary::FFlags FunFlags{
640641
F.doesNotAccessMemory(), F.onlyReadsMemory() && !F.doesNotAccessMemory(),
641642
F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(),
@@ -761,7 +762,8 @@ static void computeVariableSummary(ModuleSummaryIndex &Index,
761762
bool NonRenamableLocal = isNonRenamableLocal(V);
762763
GlobalValueSummary::GVFlags Flags(
763764
V.getLinkage(), V.getVisibility(), NonRenamableLocal,
764-
/* Live = */ false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable());
765+
/* Live = */ false, V.isDSOLocal(), V.canBeOmittedFromSymbolTable(),
766+
GlobalValueSummary::Definition);
765767

766768
VTableFuncList VTableFuncs;
767769
// If splitting is not enabled, then we compute the summary information
@@ -807,7 +809,8 @@ static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A,
807809
bool NonRenamableLocal = isNonRenamableLocal(A);
808810
GlobalValueSummary::GVFlags Flags(
809811
A.getLinkage(), A.getVisibility(), NonRenamableLocal,
810-
/* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable());
812+
/* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable(),
813+
GlobalValueSummary::Definition);
811814
auto AS = std::make_unique<AliasSummary>(Flags);
812815
auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID());
813816
assert(AliaseeVI && "Alias expects aliasee summary to be available");
@@ -887,7 +890,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
887890
GlobalValue::InternalLinkage, GlobalValue::DefaultVisibility,
888891
/* NotEligibleToImport = */ true,
889892
/* Live = */ true,
890-
/* Local */ GV->isDSOLocal(), GV->canBeOmittedFromSymbolTable());
893+
/* Local */ GV->isDSOLocal(), GV->canBeOmittedFromSymbolTable(),
894+
GlobalValueSummary::Definition);
891895
CantBePromoted.insert(GV->getGUID());
892896
// Create the appropriate summary type.
893897
if (Function *F = dyn_cast<Function>(GV)) {

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,9 @@ lltok::Kind LLLexer::LexIdentifier() {
737737
KEYWORD(live);
738738
KEYWORD(dsoLocal);
739739
KEYWORD(canAutoHide);
740+
KEYWORD(importType);
741+
KEYWORD(definition);
742+
KEYWORD(declaration);
740743
KEYWORD(function);
741744
KEYWORD(insts);
742745
KEYWORD(funcFlags);

0 commit comments

Comments
 (0)