LLVM 24.0.0git
StaticDataSplitter.cpp
Go to the documentation of this file.
1//===- StaticDataSplitter.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The pass uses branch profile data to assign hotness based section qualifiers
10// for the following types of static data:
11// - Jump tables
12// - Module-internal global variables
13// - Constant pools
14//
15// For the original RFC of this pass please see
16// https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744
17
19#include "llvm/ADT/Statistic.h"
31#include "llvm/CodeGen/Passes.h"
32#include "llvm/IR/Analysis.h"
35#include "llvm/Pass.h"
37
38using namespace llvm;
39
40#define DEBUG_TYPE "static-data-splitter"
41
42STATISTIC(NumHotJumpTables, "Number of hot jump tables seen.");
43STATISTIC(NumColdJumpTables, "Number of cold jump tables seen.");
44STATISTIC(NumUnknownJumpTables,
45 "Number of jump tables with unknown hotness. They are from functions "
46 "without profile information.");
47
49 const MachineBlockFrequencyInfo *MBFI = nullptr;
50 const ProfileSummaryInfo *PSI = nullptr;
51 StaticDataProfileInfo *SDPI = nullptr;
52
53 // If the global value is a local linkage global variable, return it.
54 // Otherwise, return nullptr.
55 const GlobalVariable *getLocalLinkageGlobalVariable(const GlobalValue *GV);
56
57 // Returns true if the global variable is in one of {.rodata, .bss, .data,
58 // .data.rel.ro} sections.
59 bool inStaticDataSection(const GlobalVariable &GV, const TargetMachine &TM);
60
61 // Returns the constant if the operand refers to a global variable or constant
62 // that gets lowered to static data sections. Otherwise, return nullptr.
63 const Constant *getConstant(const MachineOperand &Op, const TargetMachine &TM,
64 const MachineConstantPool *MCP);
65
66 // Use profiles to partition static data.
67 bool partitionStaticDataWithProfiles(MachineFunction &MF);
68
69 // Update LLVM statistics for a machine function with profiles.
70 void updateStatsWithProfiles(const MachineFunction &MF);
71
72 // Update LLVM statistics for a machine function without profiles.
73 void updateStatsWithoutProfiles(const MachineFunction &MF);
74
75 void annotateStaticDataWithoutProfiles(const MachineFunction &MF);
76
77public:
81 : MBFI(MBFI), PSI(PSI), SDPI(SDPI) {}
83};
84
86public:
87 static char ID;
88
90
91 StringRef getPassName() const override { return "Static Data Splitter"; }
92
93 void getAnalysisUsage(AnalysisUsage &AU) const override {
98 // This pass does not modify any required analysis results except
99 // StaticDataProfileInfoWrapperPass, but StaticDataProfileInfoWrapperPass
100 // is made an immutable pass that it won't be re-scheduled by pass manager
101 // anyway. So mark setPreservesAll() here for faster compile time.
102 AU.setPreservesAll();
103 }
104
105 bool runOnMachineFunction(MachineFunction &MF) override;
106};
107
109 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
111
112 if (!ProfileAvailable) {
113 annotateStaticDataWithoutProfiles(MF);
114 updateStatsWithoutProfiles(MF);
115 return false;
116 }
117
118 bool Changed = partitionStaticDataWithProfiles(MF);
119
120 updateStatsWithProfiles(MF);
121 return Changed;
122}
123
124const Constant *
125StaticDataSplitterImpl::getConstant(const MachineOperand &Op,
126 const TargetMachine &TM,
127 const MachineConstantPool *MCP) {
128 if (!Op.isGlobal() && !Op.isCPI())
129 return nullptr;
130
131 if (Op.isGlobal()) {
132 // Find global variables with local linkage.
133 const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
134 // Skip those not eligible for annotation or not in static data sections.
135 if (!GV || !llvm::memprof::IsAnnotationOK(*GV) ||
136 !inStaticDataSection(*GV, TM))
137 return nullptr;
138 return GV;
139 }
140 assert(Op.isCPI() && "Op must be constant pool index in this branch");
141 int CPI = Op.getIndex();
142 if (CPI == -1)
143 return nullptr;
144
145 assert(MCP != nullptr && "Constant pool info is not available.");
146 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
147
149 return nullptr;
150
151 return CPE.Val.ConstVal;
152}
153
154bool StaticDataSplitterImpl::partitionStaticDataWithProfiles(
155 MachineFunction &MF) {
156 // If any of the static data (jump tables, global variables, constant pools)
157 // are captured by the analysis, set `Changed` to true. Note this pass won't
158 // invalidate any analysis pass (see `getAnalysisUsage` above), so the main
159 // purpose of tracking and conveying the change (to pass manager) is
160 // informative as opposed to invalidating any analysis results. As an example
161 // of where this information is useful, `PMDataManager::dumpPassInfo` will
162 // only dump pass info if a local change happens, otherwise a pass appears as
163 // "skipped".
164 bool Changed = false;
165
166 MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
167
168 // Jump table could be used by either terminating instructions or
169 // non-terminating ones, so we walk all instructions and use
170 // `MachineOperand::isJTI()` to identify jump table operands.
171 // Similarly, `MachineOperand::isCPI()` is used to identify constant pool
172 // usages in the same loop.
173 for (const auto &MBB : MF) {
174 std::optional<uint64_t> Count = MBFI->getBlockProfileCount(&MBB);
175 for (const MachineInstr &I : MBB) {
176 for (const MachineOperand &Op : I.operands()) {
177 if (!Op.isJTI() && !Op.isGlobal() && !Op.isCPI())
178 continue;
179
180 if (Op.isJTI()) {
181 assert(MJTI != nullptr && "Jump table info is not available.");
182 const int JTI = Op.getIndex();
183 // This is not a source block of jump table.
184 if (JTI == -1)
185 continue;
186
187 auto Hotness = MachineFunctionDataHotness::Hot;
188
189 // Hotness is based on source basic block hotness.
190 // TODO: PSI APIs are about instruction hotness. Introduce API for
191 // data access hotness.
192 if (Count && PSI->isColdCount(*Count))
193 Hotness = MachineFunctionDataHotness::Cold;
194
195 Changed |= MJTI->updateJumpTableEntryHotness(JTI, Hotness);
196 } else if (const Constant *C =
197 getConstant(Op, MF.getTarget(), MF.getConstantPool())) {
198 SDPI->addConstantProfileCount(C, Count);
199 Changed = true;
200 }
201 }
202 }
203 }
204 return Changed;
205}
206
207const GlobalVariable *
208StaticDataSplitterImpl::getLocalLinkageGlobalVariable(const GlobalValue *GV) {
209 // LLVM IR Verifier requires that a declaration must have valid declaration
210 // linkage, and local linkages are not among the valid ones. So there is no
211 // need to check GV is not a declaration here.
212 return (GV && GV->hasLocalLinkage()) ? dyn_cast<GlobalVariable>(GV) : nullptr;
213}
214
215bool StaticDataSplitterImpl::inStaticDataSection(const GlobalVariable &GV,
216 const TargetMachine &TM) {
217
219 return Kind.isData() || Kind.isReadOnly() || Kind.isReadOnlyWithRel() ||
220 Kind.isBSS();
221}
222
223void StaticDataSplitterImpl::updateStatsWithProfiles(
224 const MachineFunction &MF) {
226 return;
227
228 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
229 for (const auto &JumpTable : MJTI->getJumpTables()) {
230 if (JumpTable.Hotness == MachineFunctionDataHotness::Hot) {
231 ++NumHotJumpTables;
232 } else {
233 assert(JumpTable.Hotness == MachineFunctionDataHotness::Cold &&
234 "A jump table is either hot or cold when profile information is "
235 "available.");
236 ++NumColdJumpTables;
237 }
238 }
239 }
240}
241
242void StaticDataSplitterImpl::annotateStaticDataWithoutProfiles(
243 const MachineFunction &MF) {
244 for (const auto &MBB : MF)
245 for (const MachineInstr &I : MBB)
246 for (const MachineOperand &Op : I.operands())
247 if (const Constant *C =
248 getConstant(Op, MF.getTarget(), MF.getConstantPool()))
249 SDPI->addConstantProfileCount(C, std::nullopt);
250}
251
252void StaticDataSplitterImpl::updateStatsWithoutProfiles(
253 const MachineFunction &MF) {
255 return;
256
257 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
258 NumUnknownJumpTables += MJTI->getJumpTables().size();
259 }
260}
261
263
265 false, false)
272
276
280 ProfileSummaryInfo *PSI =
283 .getStaticDataProfileInfo();
284 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
285 return Impl.runOnMachineFunction(MF);
286}
287
293 auto &ModuleAnalysisManagerProxy =
295 ProfileSummaryInfo *PSI =
296 ModuleAnalysisManagerProxy.getCachedResult<ProfileSummaryAnalysis>(
297 *MF.getFunction().getParent());
299 &ModuleAnalysisManagerProxy
300 .getCachedResult<StaticDataProfileInfoAnalysis>(
301 *MF.getFunction().getParent())
302 ->getStaticDataProfileInfo();
303 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
304 return Impl.runOnMachineFunction(MF)
308}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define DEBUG_TYPE
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
bool runOnMachineFunction(MachineFunction &MF)
StaticDataSplitterImpl(MachineBlockFrequencyInfo *MBFI, ProfileSummaryInfo *PSI, StaticDataProfileInfo *SDPI)
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
This is an important base class in LLVM.
Definition Constant.h:43
bool hasProfileData() const
Return true if the function is annotated with profile data.
Definition Function.h:312
bool hasLocalLinkage() const
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
LLVM_ABI bool updateJumpTableEntryHotness(size_t JTI, MachineFunctionDataHotness Hotness)
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Analysis providing profile information.
This wraps the StaticDataProfileInfo object as an immutable pass, for a backend pass to operate on.
A class that holds the constants that represent static data and their profile information and provide...
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static SectionKind getKindForGlobal(const GlobalObject *GO, const TargetMachine &TM)
Classify the specified global variable into a set of target independent categories embodied in Sectio...
Primary interface to the complete machine description for the target machine.
Changed
Pass manager infrastructure for declaring and invalidating analyses.
LLVM_ABI bool IsAnnotationOK(const GlobalVariable &GV)
Returns true if the annotation kind of the global variable GV is AnnotationOK.
This is an optimization pass for GlobalISel generic memory operations.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
LLVM_ABI MachineFunctionPass * createStaticDataSplitterLegacyPass()
createStaticDataSplitterPass - This is a machine-function pass that categorizes static data hotness u...