LLVM 24.0.0git
StaticDataProfileInfo.cpp
Go to the documentation of this file.
3#include "llvm/IR/Constant.h"
4#include "llvm/IR/Constants.h"
6#include "llvm/IR/Module.h"
10
11#define DEBUG_TYPE "static-data-profile-info"
12
13using namespace llvm;
14
16 "preserve-hot-data-section-prefix", cl::Hidden, cl::init(true),
17 cl::desc("If true, hot data section prefixes are preserved"));
18
19namespace llvm {
20// FIXME: This option is added for incremental rollout purposes.
21// After the option, string literal partitioning should be implied by
22// AnnotateStaticDataSectionPrefix in MemProfUse.cpp and this option should be
23// cleaned up.
25 "memprof-annotate-string-literal-section-prefix", cl::init(true),
27 cl::desc("If true, annotate the string literal data section prefix"));
28namespace memprof {
29// Returns true iff the global variable has custom section either by
30// __attribute__((section("name")))
31// (https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate)
32// or #pragma clang section directives
33// (https://clang.llvm.org/docs/LanguageExtensions.html#specifying-section-names-for-global-objects-pragma-clang-section).
34static bool hasExplicitSectionName(const GlobalVariable &GVar) {
35 if (GVar.hasSection())
36 return true;
37
38 auto Attrs = GVar.getAttributes();
39 if (Attrs.hasAttribute("bss-section") || Attrs.hasAttribute("data-section") ||
40 Attrs.hasAttribute("relro-section") ||
41 Attrs.hasAttribute("rodata-section"))
42 return true;
43 return false;
44}
45
49 // Skip 'llvm.'-prefixed global variables conservatively because they are
50 // often handled specially,
51 StringRef Name = GV.getName();
52 if (Name.starts_with("llvm."))
54 // Respect user-specified custom data sections.
58}
59
63} // namespace memprof
64} // namespace llvm
65
67 const Constant *C, std::optional<uint64_t> Count) {
68 if (!Count) {
70 return;
71 }
72 uint64_t &OriginalCount = ConstantProfileCounts[C];
73 OriginalCount = llvm::SaturatingAdd(*Count, OriginalCount);
74 // Clamp the count to getInstrMaxCountValue. InstrFDO reserves a few
75 // large values for special use.
76 if (OriginalCount > getInstrMaxCountValue())
77 OriginalCount = getInstrMaxCountValue();
78}
79
82 const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
83 // The accummulated counter shows the constant is hot. Return enum 'hot'
84 // whether this variable is seen by unprofiled functions or not.
85 if (PSI->isHotCount(Count))
87 // The constant is not hot, and seen by unprofiled functions. We don't want to
88 // assign it to unlikely sections, even if the counter says 'cold'. So return
89 // enum 'LukewarmOrUnknown'.
90 if (ConstantWithoutCounts.count(C))
92 // The accummulated counter shows the constant is cold so return enum 'cold'.
93 if (PSI->isColdCount(Count))
95
97}
98
101 std::optional<StringRef> MaybeSectionPrefix) const {
102 if (!MaybeSectionPrefix)
104 StringRef Prefix = *MaybeSectionPrefix;
105 assert((Prefix == "hot" || Prefix == "unlikely") &&
106 "Expect section_prefix to be one of hot or unlikely");
107 return Prefix == "hot" ? StaticDataHotness::Hot : StaticDataHotness::Cold;
108}
109
111 switch (Hotness) {
113 return "unlikely";
115 return PreserveHotDataSectionPrefix ? "hot" : "";
116 default:
117 return "";
118 }
119}
120
121std::optional<uint64_t>
123 auto I = ConstantProfileCounts.find(C);
124 if (I == ConstantProfileCounts.end())
125 return std::nullopt;
126 return I->second;
127}
128
130 const Constant *C, const ProfileSummaryInfo *PSI) const {
131 std::optional<uint64_t> Count = getConstantProfileCount(C);
132
133#ifndef NDEBUG
134 auto DbgPrintPrefix = [](StringRef Prefix) {
135 return Prefix.empty() ? "<empty>" : Prefix;
136 };
137#endif
138
140 // Both data access profiles and PGO counters are available. Use the
141 // hotter one to be conservative. Basically, we want the non-unlikely
142 // sections to have max coverage of accessed symbols and meanwhile can
143 // tolerant some cold symbols in it, and the unlikely section variant to not
144 // have potentially hot symbols if possible, to avoid the penalty of access
145 // cold pages.
149 !GV->getName().starts_with(".str"))) {
150 // Note a global var is covered by data access profiles iff the
151 // symbol name is preserved in the symbol table; most notably, a string
152 // literal with private linkage (e.g., those not externalized by ThinLTO
153 // and with insignificant address) won't have an entry in the symbol
154 // table (unless there is another string with identical content that
155 // gets a symbol table entry). For the private-linkage string literals,
156 // their hotness will be at least lukewarm (i.e., empty prefix).
157 auto HotnessFromDataAccessProf =
158 getSectionHotnessUsingDataAccessProfile(GV->getSectionPrefix());
159
160 if (!Count) {
161 StringRef Prefix = hotnessToStr(HotnessFromDataAccessProf);
162 LLVM_DEBUG(dbgs() << GV->getName() << " has section prefix "
163 << DbgPrintPrefix(Prefix)
164 << ", solely from data access profiles\n");
165 return Prefix;
166 }
167
168 auto HotnessFromPGO = getConstantHotnessUsingProfileCount(C, PSI, *Count);
170 if (HotnessFromDataAccessProf == StaticDataHotness::Hot ||
171 HotnessFromPGO == StaticDataHotness::Hot) {
172 GlobalVarHotness = StaticDataHotness::Hot;
173 } else if (HotnessFromDataAccessProf ==
175 HotnessFromPGO == StaticDataHotness::LukewarmOrUnknown) {
176 GlobalVarHotness = StaticDataHotness::LukewarmOrUnknown;
177 } else {
178 GlobalVarHotness = StaticDataHotness::Cold;
179 }
180 StringRef Prefix = hotnessToStr(GlobalVarHotness);
182 dbgs() << GV->getName() << " has section prefix "
183 << DbgPrintPrefix(Prefix)
184 << ", the max from data access profiles as "
185 << DbgPrintPrefix(hotnessToStr(HotnessFromDataAccessProf))
186 << " and PGO counters as "
187 << DbgPrintPrefix(hotnessToStr(HotnessFromPGO)) << "\n");
188 return Prefix;
189 }
190 }
191 if (!Count)
192 return "";
194}
195
196static std::unique_ptr<StaticDataProfileInfo>
198 bool EnableDataAccessProf = false;
200 M.getModuleFlag("EnableDataAccessProf")))
201 EnableDataAccessProf = MD->getZExtValue();
202 return std::make_unique<StaticDataProfileInfo>(EnableDataAccessProf);
203}
204
209
211 Info.reset();
212 return false;
213}
214
216 "Static Data Profile Info", false, true)
217
219 : ImmutablePass(ID) {}
220
222
227
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static std::unique_ptr< StaticDataProfileInfo > computeStaticDataProfileInfo(Module &M)
cl::opt< bool > PreserveHotDataSectionPrefix("preserve-hot-data-section-prefix", cl::Hidden, cl::init(true), cl::desc("If true, hot data section prefixes are preserved"))
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
#define LLVM_DEBUG(...)
Definition Debug.h:119
This is an important base class in LLVM.
Definition Constant.h:43
bool hasSection() const
Check if this global has a custom object file section.
bool isDeclarationForLinker() const
AttributeSet getAttributes() const
Return the attribute set for this global.
ImmutablePass class - This class is used to provide information that does not need to be run.
Definition Pass.h:285
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Analysis providing profile information.
LLVM_ABI bool isColdCount(uint64_t C) const
Returns true if count C is considered cold.
LLVM_ABI bool isHotCount(uint64_t C) const
Returns true if count C is considered hot.
Result run(Module &M, ModuleAnalysisManager &)
This wraps the StaticDataProfileInfo object as an immutable pass, for a backend pass to operate on.
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
LLVM_ABI std::optional< uint64_t > getConstantProfileCount(const Constant *C) const
If C has a count, return it. Otherwise, return std::nullopt.
LLVM_ABI StaticDataHotness getConstantHotnessUsingProfileCount(const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const
Return the hotness of the constant C based on its profile count Count.
LLVM_ABI StringRef hotnessToStr(StaticDataHotness Hotness) const
Return the string representation of the hotness enum Hotness.
StaticDataHotness
Use signed enums for enum value comparison, and make 'LukewarmOrUnknown' as 0 so any accidentally uni...
LLVM_ABI void addConstantProfileCount(const Constant *C, std::optional< uint64_t > Count)
If Count is not nullopt, add it to the profile count of the constant C in a saturating way,...
LLVM_ABI StringRef getConstantSectionPrefix(const Constant *C, const ProfileSummaryInfo *PSI) const
Given a constant C, returns a section prefix.
LLVM_ABI StaticDataHotness getSectionHotnessUsingDataAccessProfile(std::optional< StringRef > SectionPrefix) const
Return the hotness based on section prefix SectionPrefix.
DenseMap< const Constant *, uint64_t > ConstantProfileCounts
A constant is tracked only if the following conditions are met.
DenseSet< const Constant * > ConstantWithoutCounts
Keeps track of the constants that are seen at least once without profile counts.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:694
LLVM_ABI AnnotationKind getAnnotationKind(const GlobalVariable &GV)
Returns the annotation kind of the global variable GV.
LLVM_ABI bool IsAnnotationOK(const GlobalVariable &GV)
Returns true if the annotation kind of the global variable GV is AnnotationOK.
static bool hasExplicitSectionName(const GlobalVariable &GVar)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
uint64_t getInstrMaxCountValue()
Return the max count value. We reserver a few large values for special use.
Definition InstrProf.h:97
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
cl::opt< bool > AnnotateStringLiteralSectionPrefix("memprof-annotate-string-literal-section-prefix", cl::init(true), cl::Hidden, cl::desc("If true, annotate the string literal data section prefix"))
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingAdd(T X, T Y, bool *ResultOverflowed=nullptr)
Add two unsigned integers, X and Y, of type T.
Definition MathExtras.h:604
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29