[NFC][StaticDataProfileInfo] Refactor StaticDataProfileInfo::getConstantSectionPrefix and extract analysis based on PGO-counter to be a helper function (#162388)

`StaticDataProfileInfo::getConstantSectionPrefix` is used twice in
codegen ([1] and [2]) to emit section prefix for constants.

Before this patch, its implementation does analysis using PGO-counters,
and PGO-counters are only available on module-internal constants.

After this patch, the PGO-counter analysis are extracted to a helper
function, and returns enum rather than StringPrefix. This way, the
follow up patch https://github.com/llvm/llvm-project/pull/163325 can
extend this function to use global variable section prefix and compute a
max (the hotter one).

[1]
975fba1b49/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (L3014-L3019)
[2]
975fba1b49/llvm/lib/CodeGen/StaticDataAnnotator.cpp (L77-L84)
This commit is contained in:
Mingming Liu
2025-10-14 21:15:31 -07:00
committed by GitHub
parent 9a46060aed
commit c63002eb9a
2 changed files with 53 additions and 17 deletions

View File

@@ -32,8 +32,11 @@ bool IsAnnotationOK(const GlobalVariable &GV);
/// profile information and provides methods to operate on them.
class StaticDataProfileInfo {
public:
/// Accummulate the profile count of a constant that will be lowered to static
/// data sections.
/// A constant is tracked only if the following conditions are met.
/// 1) It has local (i.e., private or internal) linkage.
// 2) Its data kind is one of {.rodata, .data, .bss, .data.rel.ro}.
// 3) It's eligible for section prefix annotation. See `AnnotationKind`
// above for ineligible reasons.
DenseMap<const Constant *, uint64_t> ConstantProfileCounts;
/// Keeps track of the constants that are seen at least once without profile
@@ -44,6 +47,22 @@ public:
LLVM_ABI std::optional<uint64_t>
getConstantProfileCount(const Constant *C) const;
/// Use signed enums for enum value comparison, and make 'LukewarmOrUnknown'
/// as 0 so any accidentally uninitialized value will default to unknown.
enum class StaticDataHotness : int8_t {
Cold = -1,
LukewarmOrUnknown = 0,
Hot = 1,
};
/// Return the hotness of the constant \p C based on its profile count \p
/// Count.
LLVM_ABI StaticDataHotness getConstantHotnessUsingProfileCount(
const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const;
/// Return the string representation of the hotness enum \p Hotness.
LLVM_ABI StringRef hotnessToStr(StaticDataHotness Hotness) const;
public:
StaticDataProfileInfo() = default;

View File

@@ -60,6 +60,36 @@ void StaticDataProfileInfo::addConstantProfileCount(
OriginalCount = getInstrMaxCountValue();
}
StaticDataProfileInfo::StaticDataHotness
StaticDataProfileInfo::getConstantHotnessUsingProfileCount(
const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
// The accummulated counter shows the constant is hot. Return enum 'hot'
// whether this variable is seen by unprofiled functions or not.
if (PSI->isHotCount(Count))
return StaticDataHotness::Hot;
// The constant is not hot, and seen by unprofiled functions. We don't want to
// assign it to unlikely sections, even if the counter says 'cold'. So return
// enum 'LukewarmOrUnknown'.
if (ConstantWithoutCounts.count(C))
return StaticDataHotness::LukewarmOrUnknown;
// The accummulated counter shows the constant is cold so return enum 'cold'.
if (PSI->isColdCount(Count))
return StaticDataHotness::Cold;
return StaticDataHotness::LukewarmOrUnknown;
}
StringRef StaticDataProfileInfo::hotnessToStr(StaticDataHotness Hotness) const {
switch (Hotness) {
case StaticDataHotness::Cold:
return "unlikely";
case StaticDataHotness::Hot:
return "hot";
default:
return "";
}
}
std::optional<uint64_t>
StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
auto I = ConstantProfileCounts.find(C);
@@ -70,23 +100,10 @@ StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
StringRef StaticDataProfileInfo::getConstantSectionPrefix(
const Constant *C, const ProfileSummaryInfo *PSI) const {
auto Count = getConstantProfileCount(C);
std::optional<uint64_t> Count = getConstantProfileCount(C);
if (!Count)
return "";
// The accummulated counter shows the constant is hot. Return 'hot' whether
// this variable is seen by unprofiled functions or not.
if (PSI->isHotCount(*Count))
return "hot";
// The constant is not hot, and seen by unprofiled functions. We don't want to
// assign it to unlikely sections, even if the counter says 'cold'. So return
// an empty prefix before checking whether the counter is cold.
if (ConstantWithoutCounts.count(C))
return "";
// The accummulated counter shows the constant is cold. Return 'unlikely'.
if (PSI->isColdCount(*Count))
return "unlikely";
// The counter says lukewarm. Return an empty prefix.
return "";
return hotnessToStr(getConstantHotnessUsingProfileCount(C, PSI, *Count));
}
bool StaticDataProfileInfoWrapperPass::doInitialization(Module &M) {