Skip to content

Commit aae52ce

Browse files
For static data layout, update codegen passes to reconcile data hotness from two sources of profile information
1 parent 8f8cd69 commit aae52ce

File tree

4 files changed

+63
-24
lines changed

4 files changed

+63
-24
lines changed

llvm/include/llvm/Analysis/StaticDataProfileInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class StaticDataProfileInfo {
2626
LLVM_ABI std::optional<uint64_t>
2727
getConstantProfileCount(const Constant *C) const;
2828

29+
LLVM_ABI std::optional<StringRef>
30+
getDataHotnessBasedOnProfileCount(const Constant *C,
31+
const ProfileSummaryInfo *PSI) const;
32+
2933
public:
3034
StaticDataProfileInfo() = default;
3135

llvm/lib/Analysis/StaticDataProfileInfo.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
2828
return I->second;
2929
}
3030

31-
StringRef StaticDataProfileInfo::getConstantSectionPrefix(
31+
std::optional<StringRef>
32+
StaticDataProfileInfo::getDataHotnessBasedOnProfileCount(
3233
const Constant *C, const ProfileSummaryInfo *PSI) const {
3334
auto Count = getConstantProfileCount(C);
35+
// The constant `C` doesn't have a profile count. `C` might be a external
36+
// linkage global variable, whose PGO-based counter is not tracked within one
37+
// IR module.
3438
if (!Count)
35-
return "";
39+
return std::nullopt;
3640
// The accummulated counter shows the constant is hot. Return 'hot' whether
3741
// this variable is seen by unprofiled functions or not.
3842
if (PSI->isHotCount(*Count))
@@ -41,14 +45,46 @@ StringRef StaticDataProfileInfo::getConstantSectionPrefix(
4145
// assign it to unlikely sections, even if the counter says 'cold'. So return
4246
// an empty prefix before checking whether the counter is cold.
4347
if (ConstantWithoutCounts.count(C))
44-
return "";
48+
return std::nullopt;
4549
// The accummulated counter shows the constant is cold. Return 'unlikely'.
46-
if (PSI->isColdCount(*Count))
50+
if (PSI->isColdCount(*Count)) {
4751
return "unlikely";
48-
// The counter says lukewarm. Return an empty prefix.
52+
}
4953
return "";
5054
}
5155

56+
static StringRef reconcileHotness(StringRef SectionPrefix, StringRef Hotness) {
57+
assert((SectionPrefix == "hot" || SectionPrefix == "unlikely") &&
58+
"Section prefix must be 'hot' or 'unlikely'");
59+
60+
if (SectionPrefix == "hot" || Hotness == "hot")
61+
return "hot";
62+
assert(SectionPrefix == "unlikely" && "Section prefix must be 'unlikely'.");
63+
return Hotness;
64+
}
65+
66+
static StringRef
67+
reconcileOptionalHotness(std::optional<StringRef> SectionPrefix,
68+
std::optional<StringRef> Hotness) {
69+
if (!SectionPrefix)
70+
return Hotness.value_or("");
71+
if (!Hotness)
72+
return SectionPrefix.value_or("");
73+
74+
return reconcileHotness(*SectionPrefix, *Hotness);
75+
}
76+
77+
StringRef StaticDataProfileInfo::getConstantSectionPrefix(
78+
const Constant *C, const ProfileSummaryInfo *PSI) const {
79+
std::optional<StringRef> HotnessBasedOnCount =
80+
getDataHotnessBasedOnProfileCount(C, PSI);
81+
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
82+
return reconcileOptionalHotness(GV->getSectionPrefix(),
83+
HotnessBasedOnCount);
84+
85+
return HotnessBasedOnCount.value_or("");
86+
}
87+
5288
bool StaticDataProfileInfoWrapperPass::doInitialization(Module &M) {
5389
Info.reset(new StaticDataProfileInfo());
5490
return false;

llvm/lib/CodeGen/StaticDataAnnotator.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,6 @@ bool StaticDataAnnotator::runOnModule(Module &M) {
7878
if (GV.isDeclarationForLinker())
7979
continue;
8080

81-
// The implementation below assumes prior passes don't set section prefixes,
82-
// and specifically do 'assign' rather than 'update'. So report error if a
83-
// section prefix is already set.
84-
if (auto maybeSectionPrefix = GV.getSectionPrefix();
85-
maybeSectionPrefix && !maybeSectionPrefix->empty())
86-
llvm::report_fatal_error("Global variable " + GV.getName() +
87-
" already has a section prefix " +
88-
*maybeSectionPrefix);
89-
9081
StringRef SectionPrefix = SDPI->getConstantSectionPrefix(&GV, PSI);
9182
if (SectionPrefix.empty())
9283
continue;

llvm/test/CodeGen/X86/global-variable-partition.ll

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,24 @@ target triple = "x86_64-unknown-linux-gnu"
9090
; UNIQ-NEXT: .section .data.rel.ro.unlikely.,"aw",@progbits,unique,6
9191
; AGG-NEXT: .section .data.rel.ro.unlikely.,"aw",@progbits
9292

93-
; Currently static-data-splitter only analyzes access from code.
94-
; @bss2 and @data3 are indirectly accessed by code through @hot_relro_array
95-
; and @cold_relro_array. A follow-up item is to analyze indirect access via data
96-
; and prune the unlikely list.
97-
; For @bss2
93+
94+
; @bss2 and @data3 are indirectly accessed via @hot_relro_array and
95+
; @cold_relro_array, and actually hot due to accesses via @hot_relro_array.
96+
; Under the hood, the static data splitter pass analyzes accesses from code but
97+
; won't aggressively propgate the hotness of @hot_relro_array into the array
98+
; elements -- instead, this pass reconciles the hotness information from both
99+
; global variable section prefix and PGO counters.
100+
101+
; @bss2 has a section prefix 'hot' in the IR. StaticDataProfileInfo reconciles
102+
; it into a hot prefix.
98103
; COMMON: .type bss2,@object
99-
; SYM-NEXT: .section .bss.unlikely.bss2,"aw",@nobits
100-
; UNIQ-NEXT: .section .bss.unlikely.,"aw",@nobits,unique,7
101-
; AGG-NEXT: .section .bss.unlikely.,"aw",@nobits
104+
; SYM-NEXT: .section .bss.hot.bss2,"aw",@nobits
105+
; UNIQ-NEXT: .section .bss.hot.,"aw",@nobits,unique,7
106+
; AGG-NEXT: .section .bss.hot.,"aw",@nobits
102107

103-
; For @data3
108+
; @data3 doesn't have data access profile coverage and thereby doesn't have a
109+
; section prefix. PGO counter analysis categorizes it as cold, so it will have
110+
; section name `.data.unlikely`.
104111
; COMMON: .type data3,@object
105112
; SYM-NEXT: .section .data.unlikely.data3,"aw",@progbits
106113
; UNIQ-NEXT: .section .data.unlikely.,"aw",@progbits,unique,8
@@ -133,7 +140,7 @@ target triple = "x86_64-unknown-linux-gnu"
133140
@cold_data = internal global i32 4
134141
@cold_data_custom_foo_section = internal global i32 100, section "foo"
135142
@cold_relro_array = internal constant [2 x ptr] [ptr @data3, ptr @bss2]
136-
@bss2 = internal global i32 0
143+
@bss2 = internal global i32 0, !section_prefix !17
137144
@data3 = internal global i32 3
138145
@data_with_unknown_hotness = private global i32 5
139146
@hot_data_custom_bar_section = internal global i32 101 #0
@@ -227,3 +234,4 @@ attributes #0 = {"data-section"="bar"}
227234
!14 = !{!"function_entry_count", i64 100000}
228235
!15 = !{!"function_entry_count", i64 1}
229236
!16 = !{!"branch_weights", i32 1, i32 99999}
237+
!17 = !{!"section_prefix", !"hot"}

0 commit comments

Comments
 (0)