1*700637cbSDimitry Andric #include "llvm/Analysis/StaticDataProfileInfo.h"
2*700637cbSDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
3*700637cbSDimitry Andric #include "llvm/IR/Constant.h"
4*700637cbSDimitry Andric #include "llvm/IR/GlobalVariable.h"
5*700637cbSDimitry Andric #include "llvm/InitializePasses.h"
6*700637cbSDimitry Andric #include "llvm/ProfileData/InstrProf.h"
7*700637cbSDimitry Andric
8*700637cbSDimitry Andric using namespace llvm;
addConstantProfileCount(const Constant * C,std::optional<uint64_t> Count)9*700637cbSDimitry Andric void StaticDataProfileInfo::addConstantProfileCount(
10*700637cbSDimitry Andric const Constant *C, std::optional<uint64_t> Count) {
11*700637cbSDimitry Andric if (!Count) {
12*700637cbSDimitry Andric ConstantWithoutCounts.insert(C);
13*700637cbSDimitry Andric return;
14*700637cbSDimitry Andric }
15*700637cbSDimitry Andric uint64_t &OriginalCount = ConstantProfileCounts[C];
16*700637cbSDimitry Andric OriginalCount = llvm::SaturatingAdd(*Count, OriginalCount);
17*700637cbSDimitry Andric // Clamp the count to getInstrMaxCountValue. InstrFDO reserves a few
18*700637cbSDimitry Andric // large values for special use.
19*700637cbSDimitry Andric if (OriginalCount > getInstrMaxCountValue())
20*700637cbSDimitry Andric OriginalCount = getInstrMaxCountValue();
21*700637cbSDimitry Andric }
22*700637cbSDimitry Andric
23*700637cbSDimitry Andric std::optional<uint64_t>
getConstantProfileCount(const Constant * C) const24*700637cbSDimitry Andric StaticDataProfileInfo::getConstantProfileCount(const Constant *C) const {
25*700637cbSDimitry Andric auto I = ConstantProfileCounts.find(C);
26*700637cbSDimitry Andric if (I == ConstantProfileCounts.end())
27*700637cbSDimitry Andric return std::nullopt;
28*700637cbSDimitry Andric return I->second;
29*700637cbSDimitry Andric }
30*700637cbSDimitry Andric
getConstantSectionPrefix(const Constant * C,const ProfileSummaryInfo * PSI) const31*700637cbSDimitry Andric StringRef StaticDataProfileInfo::getConstantSectionPrefix(
32*700637cbSDimitry Andric const Constant *C, const ProfileSummaryInfo *PSI) const {
33*700637cbSDimitry Andric auto Count = getConstantProfileCount(C);
34*700637cbSDimitry Andric if (!Count)
35*700637cbSDimitry Andric return "";
36*700637cbSDimitry Andric // The accummulated counter shows the constant is hot. Return 'hot' whether
37*700637cbSDimitry Andric // this variable is seen by unprofiled functions or not.
38*700637cbSDimitry Andric if (PSI->isHotCount(*Count))
39*700637cbSDimitry Andric return "hot";
40*700637cbSDimitry Andric // The constant is not hot, and seen by unprofiled functions. We don't want to
41*700637cbSDimitry Andric // assign it to unlikely sections, even if the counter says 'cold'. So return
42*700637cbSDimitry Andric // an empty prefix before checking whether the counter is cold.
43*700637cbSDimitry Andric if (ConstantWithoutCounts.count(C))
44*700637cbSDimitry Andric return "";
45*700637cbSDimitry Andric // The accummulated counter shows the constant is cold. Return 'unlikely'.
46*700637cbSDimitry Andric if (PSI->isColdCount(*Count))
47*700637cbSDimitry Andric return "unlikely";
48*700637cbSDimitry Andric // The counter says lukewarm. Return an empty prefix.
49*700637cbSDimitry Andric return "";
50*700637cbSDimitry Andric }
51*700637cbSDimitry Andric
doInitialization(Module & M)52*700637cbSDimitry Andric bool StaticDataProfileInfoWrapperPass::doInitialization(Module &M) {
53*700637cbSDimitry Andric Info.reset(new StaticDataProfileInfo());
54*700637cbSDimitry Andric return false;
55*700637cbSDimitry Andric }
56*700637cbSDimitry Andric
doFinalization(Module & M)57*700637cbSDimitry Andric bool StaticDataProfileInfoWrapperPass::doFinalization(Module &M) {
58*700637cbSDimitry Andric Info.reset();
59*700637cbSDimitry Andric return false;
60*700637cbSDimitry Andric }
61*700637cbSDimitry Andric
62*700637cbSDimitry Andric INITIALIZE_PASS(StaticDataProfileInfoWrapperPass, "static-data-profile-info",
63*700637cbSDimitry Andric "Static Data Profile Info", false, true)
64*700637cbSDimitry Andric
StaticDataProfileInfoWrapperPass()65*700637cbSDimitry Andric StaticDataProfileInfoWrapperPass::StaticDataProfileInfoWrapperPass()
66*700637cbSDimitry Andric : ImmutablePass(ID) {}
67*700637cbSDimitry Andric
68*700637cbSDimitry Andric char StaticDataProfileInfoWrapperPass::ID = 0;
69