LLVM 24.0.0git
StaticDataProfileInfo.cpp
Go to the documentation of this file.
2#include "AnalysisOptions.h"
4#include "llvm/IR/Constant.h"
5#include "llvm/IR/Constants.h"
7#include "llvm/IR/Module.h"
11
12#define DEBUG_TYPE "static-data-profile-info"
13
14using namespace llvm;
15
17 const LLVMContext &C) {
18 return getAnalysisOptions(C).preserve_hot_data_section_prefix;
19}
20
22 const LLVMContext &C) {
23 return getAnalysisOptions(C).memprof_annotate_string_literal_section_prefix;
24}
25
26namespace llvm {
27namespace memprof {
28// Returns true iff the global variable has custom section either by
29// __attribute__((section("name")))
30// (https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate)
31// or #pragma clang section directives
32// (https://clang.llvm.org/docs/LanguageExtensions.html#specifying-section-names-for-global-objects-pragma-clang-section).
33static bool hasExplicitSectionName(const GlobalVariable &GVar) {
34 if (GVar.hasSection())
35 return true;
36
37 auto Attrs = GVar.getAttributes();
38 if (Attrs.hasAttribute("bss-section") || Attrs.hasAttribute("data-section") ||
39 Attrs.hasAttribute("relro-section") ||
40 Attrs.hasAttribute("rodata-section"))
41 return true;
42 return false;
43}
44
48 // Skip 'llvm.'-prefixed global variables conservatively because they are
49 // often handled specially,
50 StringRef Name = GV.getName();
51 if (Name.starts_with("llvm."))
53 // Respect user-specified custom data sections.
57}
58
62} // namespace memprof
63} // namespace llvm
64
66 const Constant *C, std::optional<uint64_t> Count) {
67 if (!Count) {
69 return;
70 }
71 uint64_t &OriginalCount = ConstantProfileCounts[C];
72 OriginalCount = llvm::SaturatingAdd(*Count, OriginalCount);
73 // Clamp the count to getInstrMaxCountValue. InstrFDO reserves a few
74 // large values for special use.
75 if (OriginalCount > getInstrMaxCountValue())
76 OriginalCount = getInstrMaxCountValue();
77}
78
81 const Constant *C, const ProfileSummaryInfo *PSI, uint64_t Count) const {
82 // The accummulated counter shows the constant is hot. Return enum 'hot'
83 // whether this variable is seen by unprofiled functions or not.
84 if (PSI->isHotCount(Count))
86 // The constant is not hot, and seen by unprofiled functions. We don't want to
87 // assign it to unlikely sections, even if the counter says 'cold'. So return
88 // enum 'LukewarmOrUnknown'.
89 if (ConstantWithoutCounts.count(C))
91 // The accummulated counter shows the constant is cold so return enum 'cold'.
92 if (PSI->isColdCount(Count))
94
96}
97
100 std::optional<StringRef> MaybeSectionPrefix) const {
101 if (!MaybeSectionPrefix)
103 StringRef Prefix = *MaybeSectionPrefix;
104 assert((Prefix == "hot" || Prefix == "unlikely") &&
105 "Expect section_prefix to be one of hot or unlikely");
106 return Prefix == "hot" ? StaticDataHotness::Hot : StaticDataHotness::Cold;
107}
108
110 switch (Hotness) {
112 return "unlikely";
114 return Opts.preserve_hot_data_section_prefix ? "hot" : "";
115 default:
116 return "";
117 }
118}
119
120std::optional<uint64_t>
122 auto I = ConstantProfileCounts.find(C);
123 if (I == ConstantProfileCounts.end())
124 return std::nullopt;
125 return I->second;
126}
127
129 const Constant *C, const ProfileSummaryInfo *PSI) const {
130 std::optional<uint64_t> Count = getConstantProfileCount(C);
131
132#ifndef NDEBUG
133 auto DbgPrintPrefix = [](StringRef Prefix) {
134 return Prefix.empty() ? "<empty>" : Prefix;
135 };
136#endif
137
139 // Both data access profiles and PGO counters are available. Use the
140 // hotter one to be conservative. Basically, we want the non-unlikely
141 // sections to have max coverage of accessed symbols and meanwhile can
142 // tolerant some cold symbols in it, and the unlikely section variant to not
143 // have potentially hot symbols if possible, to avoid the penalty of access
144 // cold pages.
147 (Opts.memprof_annotate_string_literal_section_prefix ||
148 !GV->getName().starts_with(".str"))) {
149 // Note a global var is covered by data access profiles iff the
150 // symbol name is preserved in the symbol table; most notably, a string
151 // literal with private linkage (e.g., those not externalized by ThinLTO
152 // and with insignificant address) won't have an entry in the symbol
153 // table (unless there is another string with identical content that
154 // gets a symbol table entry). For the private-linkage string literals,
155 // their hotness will be at least lukewarm (i.e., empty prefix).
156 auto HotnessFromDataAccessProf =
157 getSectionHotnessUsingDataAccessProfile(GV->getSectionPrefix());
158
159 if (!Count) {
160 StringRef Prefix = hotnessToStr(HotnessFromDataAccessProf);
161 LLVM_DEBUG(dbgs() << GV->getName() << " has section prefix "
162 << DbgPrintPrefix(Prefix)
163 << ", solely from data access profiles\n");
164 return Prefix;
165 }
166
167 auto HotnessFromPGO = getConstantHotnessUsingProfileCount(C, PSI, *Count);
169 if (HotnessFromDataAccessProf == StaticDataHotness::Hot ||
170 HotnessFromPGO == StaticDataHotness::Hot) {
171 GlobalVarHotness = StaticDataHotness::Hot;
172 } else if (HotnessFromDataAccessProf ==
174 HotnessFromPGO == StaticDataHotness::LukewarmOrUnknown) {
175 GlobalVarHotness = StaticDataHotness::LukewarmOrUnknown;
176 } else {
177 GlobalVarHotness = StaticDataHotness::Cold;
178 }
179 StringRef Prefix = hotnessToStr(GlobalVarHotness);
181 dbgs() << GV->getName() << " has section prefix "
182 << DbgPrintPrefix(Prefix)
183 << ", the max from data access profiles as "
184 << DbgPrintPrefix(hotnessToStr(HotnessFromDataAccessProf))
185 << " and PGO counters as "
186 << DbgPrintPrefix(hotnessToStr(HotnessFromPGO)) << "\n");
187 return Prefix;
188 }
189 }
190 if (!Count)
191 return "";
193}
194
195static std::unique_ptr<StaticDataProfileInfo>
197 bool EnableDataAccessProf = false;
199 M.getModuleFlag("EnableDataAccessProf")))
200 EnableDataAccessProf = MD->getZExtValue();
201 return std::make_unique<StaticDataProfileInfo>(getAnalysisOptions(M),
202 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)
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:44
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:283
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
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...
static LLVM_ABI bool shouldPreserveHotDataSectionPrefix(const LLVMContext &C)
Return -preserve-hot-data-section-prefix.
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:315
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 shouldAnnotateStringLiteralSectionPrefix(const LLVMContext &C)
Return -memprof-annotate-string-literal-section-prefix.
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
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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:609
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