Skip to content

Commit 25a915a

Browse files
[ThinLTO] Add HasLocal flag to GlobalValueSummaryInfo (llvm#164647)
Add a flag to the GlobalValueSummaryInfo indicating whether the associated SummaryList (all summaries with the same GUID) contains any summaries with local linkage. This flag is set when building the index, so it is associated with the original linkage type before internalization and promotion. Consumers should check the withInternalizeAndPromote() flag on the index before using it. In most cases we expect a 1-1 mapping between a GUID and a summary with local linkage, because for locals the GUID is computed from the hash of "modulepath;name". However, there can be multiple locals with the same GUID if translation units are not compiled with enough path. And in rare but theoretically possible cases, there can be hash collisions on the underlying MD5 computation. So to be safe when looking for local summaries, analyses currently look through all summaries in the list. These lists can be extremely long in the case of large binaries with template function defs in widely used headers (i.e. linkonce_odr). A follow on change will use this flag to reduce ThinLTO analysis time in WPD by 5-6% for a large target (details in PR164046 which will be reworked to use this flag). Note that in the past we have tried to keep bits related to the GUID in the ValueInfo (which has a pointer to the associated GlobalValueSummaryInfo), via its PointerIntPair. However, we are out of bits there. This change does add a byte to every GlobalValueSummaryInfo instance, which I measured as a little under 0.90% overhead in a large target. However, it enables adding 7 bits of other per-GUID flags in the future without adding more overhead. Note that it was lower overhead to add this to the GlobalValueSummaryInfo than the ValueInfo, which tends to be copied into other maps.
1 parent 5d6c00c commit 25a915a

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

llvm/include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,11 @@ struct alignas(8) GlobalValueSummaryInfo {
172172

173173
/// Add a summary corresponding to a global value definition in a module with
174174
/// the corresponding GUID.
175-
void addSummary(std::unique_ptr<GlobalValueSummary> Summary) {
176-
return SummaryList.push_back(std::move(Summary));
177-
}
175+
inline void addSummary(std::unique_ptr<GlobalValueSummary> Summary);
176+
177+
/// Verify that the HasLocal flag is consistent with the SummaryList. Should
178+
/// only be called prior to index-based internalization and promotion.
179+
inline void verifyLocal() const;
178180

179181
private:
180182
/// List of global value summary structures for a particular value held
@@ -183,6 +185,22 @@ struct alignas(8) GlobalValueSummaryInfo {
183185
/// compiling without sufficient distinguishing path, or (theoretically) hash
184186
/// collisions. Each summary is from a different module.
185187
GlobalValueSummaryList SummaryList;
188+
189+
/// True if the SummaryList contains at least one summary with local linkage.
190+
/// In most cases there should be only one, unless translation units with
191+
/// same-named locals were compiled without distinguishing path. And generally
192+
/// there should not be a mix of local and non-local summaries, because the
193+
/// GUID for a local is computed with the path prepended and a ';' delimiter.
194+
/// In extremely rare cases there could be a GUID hash collision. Having the
195+
/// flag saves having to walk through all summaries to prove the existence or
196+
/// not of any locals.
197+
/// NOTE: this flag is set when the index is built. It does not reflect
198+
/// index-based internalization and promotion decisions. Generally most
199+
/// index-based analysis occurs before then, but any users should assert that
200+
/// the withInternalizeAndPromote() flag is not set on the index.
201+
/// TODO: Replace checks in various ThinLTO analyses that loop through all
202+
/// summaries to handle the local case with a check of the flag.
203+
bool HasLocal : 1;
186204
};
187205

188206
/// Map from global value GUID to corresponding summary structures. Use a
@@ -219,6 +237,8 @@ struct ValueInfo {
219237
return getRef()->second.getSummaryList();
220238
}
221239

240+
void verifyLocal() const { getRef()->second.verifyLocal(); }
241+
222242
// Even if the index is built with GVs available, we may not have one for
223243
// summary entries synthesized for profiled indirect call targets.
224244
bool hasName() const { return !haveGVs() || getValue(); }
@@ -649,7 +669,23 @@ class GlobalValueSummary {
649669
friend class ModuleSummaryIndex;
650670
};
651671

652-
GlobalValueSummaryInfo::GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {}
672+
GlobalValueSummaryInfo::GlobalValueSummaryInfo(bool HaveGVs)
673+
: U(HaveGVs), HasLocal(false) {}
674+
675+
void GlobalValueSummaryInfo::addSummary(
676+
std::unique_ptr<GlobalValueSummary> Summary) {
677+
if (GlobalValue::isLocalLinkage(Summary->linkage()))
678+
HasLocal = true;
679+
return SummaryList.push_back(std::move(Summary));
680+
}
681+
682+
void GlobalValueSummaryInfo::verifyLocal() const {
683+
assert(HasLocal ==
684+
llvm::any_of(SummaryList,
685+
[](const std::unique_ptr<GlobalValueSummary> &Summary) {
686+
return GlobalValue::isLocalLinkage(Summary->linkage());
687+
}));
688+
}
653689

654690
/// Alias summary information.
655691
class AliasSummary : public GlobalValueSummary {

llvm/lib/LTO/LTO.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ static void thinLTOInternalizeAndPromoteGUID(
477477
return !GlobalValue::isLocalLinkage(Summary->linkage());
478478
});
479479

480+
// Before performing index-based internalization and promotion for this GUID,
481+
// the local flag should be consistent with the summary list linkage types.
482+
VI.verifyLocal();
483+
480484
for (auto &S : VI.getSummaryList()) {
481485
// First see if we need to promote an internal value because it is not
482486
// exported.

0 commit comments

Comments
 (0)