11#include " llvm/Analysis/StaticDataProfileInfo.h"
22#include " llvm/Analysis/ProfileSummaryInfo.h"
33#include " llvm/IR/Constant.h"
4+ #include " llvm/IR/Constants.h"
45#include " llvm/IR/GlobalVariable.h"
6+ #include " llvm/IR/Metadata.h"
7+ #include " llvm/IR/Module.h"
58#include " llvm/InitializePasses.h"
69#include " llvm/ProfileData/InstrProf.h"
710
811using namespace llvm ;
12+
13+ extern cl::opt<bool > AnnotateStaticDataSectionPrefix;
14+
915void StaticDataProfileInfo::addConstantProfileCount (
1016 const Constant *C, std::optional<uint64_t > Count) {
1117 if (!Count) {
@@ -28,65 +34,79 @@ StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
2834 return I->second ;
2935}
3036
31- std::optional<StringRef>
32- StaticDataProfileInfo::getDataHotnessBasedOnProfileCount (
33- const Constant *C, const ProfileSummaryInfo *PSI) const {
34- 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.
38- if (!Count)
39- return std::nullopt ;
37+ StaticDataProfileInfo::StaticDataHotness
38+ StaticDataProfileInfo::getSectionHotnessUsingProfileCount (
39+ const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
4040 // The accummulated counter shows the constant is hot. Return 'hot' whether
4141 // this variable is seen by unprofiled functions or not.
42- if (PSI->isHotCount (* Count))
43- return " hot " ;
42+ if (PSI->isHotCount (Count))
43+ return StaticDataHotness::Hot ;
4444 // The constant is not hot, and seen by unprofiled functions. We don't want to
4545 // assign it to unlikely sections, even if the counter says 'cold'. So return
4646 // an empty prefix before checking whether the counter is cold.
4747 if (ConstantWithoutCounts.count (C))
48- return std:: nullopt ;
48+ return StaticDataHotness::LukewarmOrUnknown ;
4949 // The accummulated counter shows the constant is cold. Return 'unlikely'.
50- if (PSI->isColdCount (*Count)) {
51- return " unlikely" ;
52- }
53- return " " ;
54- }
50+ if (PSI->isColdCount (Count))
51+ return StaticDataHotness::Cold;
5552
56- static StringRef reconcileHotness (StringRef SectionPrefix, StringRef Hotness) {
57- assert ((SectionPrefix == " hot" || SectionPrefix == " unlikely" ) &&
58- " Section prefix must be 'hot' or 'unlikely'" );
53+ return StaticDataHotness::LukewarmOrUnknown;
54+ }
5955
60- if (SectionPrefix == " hot" || Hotness == " hot" )
56+ StringRef StaticDataProfileInfo::hotnessToStr (
57+ StaticDataProfileInfo::StaticDataHotness Hotness) const {
58+ switch (Hotness) {
59+ case StaticDataProfileInfo::StaticDataHotness::Cold:
60+ return " unlikely" ;
61+ case StaticDataProfileInfo::StaticDataHotness::Hot:
6162 return " hot" ;
62- assert (SectionPrefix == " unlikely" && " Section prefix must be 'unlikely'." );
63- return Hotness;
63+ default :
64+ return " " ;
65+ }
6466}
6567
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);
68+ StaticDataProfileInfo::StaticDataHotness
69+ StaticDataProfileInfo::getSectionHotnessUsingDAP (
70+ std::optional<StringRef> MaybeSectionPrefix) const {
71+ if (!MaybeSectionPrefix)
72+ return StaticDataProfileInfo::StaticDataHotness::LukewarmOrUnknown;
73+ StringRef Prefix = *MaybeSectionPrefix;
74+ assert ((Prefix == " hot" || Prefix == " unlikely" ) &&
75+ " Expect section_prefix to be one of hot or unlikely" );
76+ return Prefix == " hot" ? StaticDataProfileInfo::StaticDataHotness::Hot
77+ : StaticDataProfileInfo::StaticDataHotness::Cold;
7578}
7679
7780StringRef StaticDataProfileInfo::getConstantSectionPrefix (
7881 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);
82+ auto Count = getConstantProfileCount (C);
8483
85- return HotnessBasedOnCount.value_or (" " );
84+ if (HasDataAccessProf) {
85+ // Module flag `HasDataAccessProf` is 1 -> empty section prefix means uknown
86+ // hotness except for string literals.
87+ if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C);
88+ GV && !GV->getName ().starts_with (" .str" )) {
89+ auto HotnessFromDAP = getSectionHotnessUsingDAP (GV->getSectionPrefix ());
90+
91+ if (!Count)
92+ return hotnessToStr (HotnessFromDAP);
93+
94+ auto HotnessFromPGO = getSectionHotnessUsingProfileCount (C, PSI, *Count);
95+ return hotnessToStr (std::max (HotnessFromDAP, HotnessFromPGO));
96+ }
97+ }
98+
99+ if (!Count)
100+ return " " ;
101+ return hotnessToStr (getSectionHotnessUsingProfileCount (C, PSI, *Count));
86102}
87103
88104bool StaticDataProfileInfoWrapperPass::doInitialization (Module &M) {
89- Info.reset (new StaticDataProfileInfo ());
105+ bool HasDataAccessProf = false ;
106+ if (auto *MD = mdconst::extract_or_null<ConstantInt>(
107+ M.getModuleFlag (" HasDataAccessProf" )))
108+ HasDataAccessProf = MD->getZExtValue ();
109+ Info.reset (new StaticDataProfileInfo (HasDataAccessProf));
90110 return false ;
91111}
92112
0 commit comments