[llvm] [ThinLTO] Fix parsing null aliasee in alias summary (PR #169490)
Mingjie Xu via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 26 05:53:14 PST 2025
https://github.com/Enna1 updated https://github.com/llvm/llvm-project/pull/169490
>From eb0cfdace254a19116d6c96989e332f460e5ef8f Mon Sep 17 00:00:00 2001
From: "xumingjie.enna1" <xumingjie.enna1 at bytedance.com>
Date: Tue, 25 Nov 2025 20:00:34 +0800
Subject: [PATCH 1/2] [ThinLTO] Fix parsing null aliasee in alias summary
In https://github.com/llvm/llvm-project/commit/f8182f1aef5b6ec74cbe2c1618e759f0113921ba, we add support for printing "null" aliasee in AsmWriter, but missing support in LLParser.
---
llvm/lib/AsmParser/LLParser.cpp | 32 ++++++++++++++------------
llvm/test/Assembler/thinlto-summary.ll | 3 +++
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 61d5c2c81df2e..a7d5724057a40 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -9981,25 +9981,27 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID,
ValueInfo AliaseeVI;
unsigned GVId;
- if (parseGVReference(AliaseeVI, GVId))
- return true;
-
- if (parseToken(lltok::rparen, "expected ')' here"))
- return true;
+ std::unique_ptr<AliasSummary> AS;
- auto AS = std::make_unique<AliasSummary>(GVFlags);
-
- AS->setModulePath(ModulePath);
+ if (!EatIfPresent(lltok::kw_null)) {
+ if (parseGVReference(AliaseeVI, GVId))
+ return true;
- // Record forward reference if the aliasee is not parsed yet.
- if (AliaseeVI.getRef() == FwdVIRef) {
- ForwardRefAliasees[GVId].emplace_back(AS.get(), Loc);
- } else {
- auto Summary = Index->findSummaryInModule(AliaseeVI, ModulePath);
- assert(Summary && "Aliasee must be a definition");
- AS->setAliasee(AliaseeVI, Summary);
+ AS = std::make_unique<AliasSummary>(GVFlags);
+ AS->setModulePath(ModulePath);
+ // Record forward reference if the aliasee is not parsed yet.
+ if (AliaseeVI.getRef() == FwdVIRef) {
+ ForwardRefAliasees[GVId].emplace_back(AS.get(), Loc);
+ } else {
+ auto Summary = Index->findSummaryInModule(AliaseeVI, ModulePath);
+ assert(Summary && "Aliasee must be a definition");
+ AS->setAliasee(AliaseeVI, Summary);
+ }
}
+ if (parseToken(lltok::rparen, "expected ')' here"))
+ return true;
+
return addGlobalValueToIndex(Name, GUID,
(GlobalValue::LinkageTypes)GVFlags.Linkage, ID,
std::move(AS), Loc);
diff --git a/llvm/test/Assembler/thinlto-summary.ll b/llvm/test/Assembler/thinlto-summary.ll
index e0d866da0d8a2..7af446a17da13 100644
--- a/llvm/test/Assembler/thinlto-summary.ll
+++ b/llvm/test/Assembler/thinlto-summary.ll
@@ -73,6 +73,9 @@
^31 = flags: 8
^32 = blockcount: 1888
+; Alias summary with null aliasee.
+^33 = gv: (guid: 32, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: null)))
+
; Make sure we get back from llvm-dis essentially what we put in via llvm-as.
; CHECK: ^0 = module: (path: "thinlto-summary1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049))
; CHECK: ^1 = module: (path: "thinlto-summary2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156))
>From fd8d1696227c994d25d250faca6342d0a7ba2ebd Mon Sep 17 00:00:00 2001
From: "xumingjie.enna1" <xumingjie.enna1 at bytedance.com>
Date: Wed, 26 Nov 2025 20:05:58 +0800
Subject: [PATCH 2/2] Make sure round trips through bitcode and back as
expected
---
llvm/lib/AsmParser/LLParser.cpp | 5 ++-
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 19 +++++++----
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 11 ++++---
llvm/test/Assembler/thinlto-summary.ll | 39 ++++++++++++-----------
4 files changed, 41 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index a7d5724057a40..a799dd279f448 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -9981,14 +9981,13 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID,
ValueInfo AliaseeVI;
unsigned GVId;
- std::unique_ptr<AliasSummary> AS;
+ auto AS = std::make_unique<AliasSummary>(GVFlags);
+ AS->setModulePath(ModulePath);
if (!EatIfPresent(lltok::kw_null)) {
if (parseGVReference(AliaseeVI, GVId))
return true;
- AS = std::make_unique<AliasSummary>(GVFlags);
- AS->setModulePath(ModulePath);
// Record forward reference if the aliasee is not parsed yet.
if (AliaseeVI.getRef() == FwdVIRef) {
ForwardRefAliasees[GVId].emplace_back(AS.get(), Loc);
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 9f3bb230440fb..3b84f2aa27426 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -7181,9 +7181,11 @@ template <bool AllowNullValueInfo>
std::pair<ValueInfo, GlobalValue::GUID>
ModuleSummaryIndexBitcodeReader::getValueInfoFromValueId(unsigned ValueId) {
auto VGI = ValueIdToValueInfoMap[ValueId];
- // We can have a null value info for memprof callsite info records in
- // distributed ThinLTO index files when the callee function summary is not
- // included in the index. The bitcode writer records 0 in that case,
+ // We can have a null value info in distributed ThinLTO index files:
+ // - For memprof callsite info records when the callee function summary is not
+ // included in the index.
+ // - For alias summary when its aliasee summary is not included in the index.
+ // The bitcode writer records 0 in these cases,
// and the caller of this helper will set AllowNullValueInfo to true.
assert(AllowNullValueInfo || std::get<0>(VGI));
return VGI;
@@ -7971,10 +7973,13 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
LastSeenSummary = AS.get();
AS->setModulePath(ModuleIdMap[ModuleId]);
- auto AliaseeVI = std::get<0>(getValueInfoFromValueId(AliaseeValueId));
- auto AliaseeInModule = TheIndex.findSummaryInModule(AliaseeVI, AS->modulePath());
- AS->setAliasee(AliaseeVI, AliaseeInModule);
-
+ auto AliaseeVI = std::get<0>(
+ getValueInfoFromValueId</*AllowNullValueInfo*/ true>(AliaseeValueId));
+ if (AliaseeVI) {
+ auto AliaseeInModule =
+ TheIndex.findSummaryInModule(AliaseeVI, AS->modulePath());
+ AS->setAliasee(AliaseeVI, AliaseeInModule);
+ }
ValueInfo VI = std::get<0>(getValueInfoFromValueId(ValueID));
LastSeenGUID = VI.getGUID();
TheIndex.addGlobalValueSummary(VI, std::move(AS));
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 1d0461478b90c..d39d4d1c75256 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -5247,8 +5247,10 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.push_back(ModuleIdMap[AS->modulePath()]);
NameVals.push_back(
getEncodedGVSummaryFlags(AS->flags(), shouldImportValueAsDecl(AS)));
- auto AliaseeValueId = SummaryToValueIdMap[&AS->getAliasee()];
- assert(AliaseeValueId);
+ // Set value id to 0 when an alias is imported but the aliasee summary is
+ // not contained in the index.
+ auto AliaseeValueId =
+ AS->hasAliasee() ? SummaryToValueIdMap[&AS->getAliasee()] : 0;
NameVals.push_back(AliaseeValueId);
// Emit the finished record.
@@ -5256,8 +5258,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
NameVals.clear();
MaybeEmitOriginalName(*AS);
- if (auto *FS = dyn_cast<FunctionSummary>(&AS->getAliasee()))
- getReferencedTypeIds(FS, ReferencedTypeIds);
+ if (AS->hasAliasee())
+ if (auto *FS = dyn_cast<FunctionSummary>(&AS->getAliasee()))
+ getReferencedTypeIds(FS, ReferencedTypeIds);
}
SmallVector<StringRef, 4> Functions;
diff --git a/llvm/test/Assembler/thinlto-summary.ll b/llvm/test/Assembler/thinlto-summary.ll
index 7af446a17da13..ab7c98dd46bb7 100644
--- a/llvm/test/Assembler/thinlto-summary.ll
+++ b/llvm/test/Assembler/thinlto-summary.ll
@@ -55,26 +55,26 @@
; Function summary with an import type of declaration
^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, importType: declaration), insts: 5)))
+; Alias summary with null aliasee.
+^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: null)))
+
; GUID that are 64-bit
-^25 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1)))
+^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, importType: definition), insts: 1)))
; Test TypeId summaries:
-^26 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0)))
+^27 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0)))
; Test TypeId with other optional fields (alignLog2/sizeM1/bitMask/inlineBits)
-^27 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4)))
+^28 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4)))
; Test the AllOnes resolution, and all kinds of WholeProgramDevirtResolution
; types, including all optional resolution by argument kinds.
-^28 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp)))))))
+^29 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp)))))))
; Test the other kinds of type test resoultions
-^29 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0)))
-^30 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0)))
-^31 = flags: 8
-^32 = blockcount: 1888
-
-; Alias summary with null aliasee.
-^33 = gv: (guid: 32, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: null)))
+^30 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0)))
+^31 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0)))
+^32 = flags: 8
+^33 = blockcount: 1888
; Make sure we get back from llvm-dis essentially what we put in via llvm-as.
; CHECK: ^0 = module: (path: "thinlto-summary1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049))
@@ -104,14 +104,15 @@
; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: ((vFuncId: (^29, offset: 16), args: (42)), (vFuncId: (^29, offset: 24)))))))
; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: definition), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: ((vFuncId: (^30, offset: 16), args: (42)))))))
; CHECK: ^24 = gv: (guid: 23, summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0, importType: declaration), insts: 5)))
-; CHECK: ^25 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1)))
-; CHECK: ^26 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584
-; CHECK: ^27 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976
-; CHECK: ^28 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778
-; CHECK: ^29 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0))) ; guid = 9614786172484273522
-; CHECK: ^30 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0))) ; guid = 17437243864166745132
-; CHECK: ^31 = flags: 8
-; CHECK: ^32 = blockcount: 1888
+; CHECK: ^25 = gv: (guid: 24, summaries: (alias: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), aliasee: null)))
+; CHECK: ^26 = gv: (guid: 9123456789101112131, summaries: (function: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0, importType: definition), insts: 1)))
+; CHECK: ^27 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584
+; CHECK: ^28 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976
+; CHECK: ^29 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778
+; CHECK: ^30 = typeid: (name: "_ZTS1D", summary: (typeTestRes: (kind: byteArray, sizeM1BitWidth: 0))) ; guid = 9614786172484273522
+; CHECK: ^31 = typeid: (name: "_ZTS1E", summary: (typeTestRes: (kind: unsat, sizeM1BitWidth: 0))) ; guid = 17437243864166745132
+; CHECK: ^32 = flags: 8
+; CHECK: ^33 = blockcount: 1888
; Make sure parsing of a non-summary entry containing a ":" does not fail
; after summary parsing, which handles colons differently.
More information about the llvm-commits
mailing list