Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions llvm/include/llvm/Analysis/StaticDataProfileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -44,6 +47,20 @@ class StaticDataProfileInfo {
LLVM_ABI std::optional<uint64_t>
getConstantProfileCount(const Constant *C) const;

enum class StaticDataHotness : uint8_t {
Cold = 0,
LukewarmOrUnknown = 1,
Hot = 2,
};

/// Return the hotness of the constant \p C based on its profile count \p
/// Count.
LLVM_ABI StaticDataHotness getSectionHotnessUsingProfileCount(
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;

Expand Down
48 changes: 33 additions & 15 deletions llvm/lib/Analysis/StaticDataProfileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,37 @@ void StaticDataProfileInfo::addConstantProfileCount(
OriginalCount = getInstrMaxCountValue();
}

StaticDataProfileInfo::StaticDataHotness
StaticDataProfileInfo::getSectionHotnessUsingProfileCount(
const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
// 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 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
// an empty prefix before checking whether the counter is cold.
if (ConstantWithoutCounts.count(C))
return StaticDataHotness::LukewarmOrUnknown;
// The accummulated counter shows the constant is cold. Return 'unlikely'.
if (PSI->isColdCount(Count))
return StaticDataHotness::Cold;

return StaticDataHotness::LukewarmOrUnknown;
}

StringRef StaticDataProfileInfo::hotnessToStr(
StaticDataProfileInfo::StaticDataHotness Hotness) const {
switch (Hotness) {
case StaticDataProfileInfo::StaticDataHotness::Cold:
return "unlikely";
case StaticDataProfileInfo::StaticDataHotness::Hot:
return "hot";
default:
return "";
}
}

std::optional<uint64_t>
StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
auto I = ConstantProfileCounts.find(C);
Expand All @@ -70,23 +101,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(getSectionHotnessUsingProfileCount(C, PSI, *Count));
}

bool StaticDataProfileInfoWrapperPass::doInitialization(Module &M) {
Expand Down