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"
32#include "llvm/CodeGen/Passes.h"
33#include "llvm/IR/Analysis.h"
36#include "llvm/Pass.h"
38
39using namespace llvm;
40
41#define DEBUG_TYPE "static-data-splitter"
42
43STATISTIC(NumHotJumpTables, "Number of hot jump tables seen.");
44STATISTIC(NumColdJumpTables, "Number of cold jump tables seen.");
45STATISTIC(NumUnknownJumpTables,
46 "Number of jump tables with unknown hotness. They are from functions "
47 "without profile information.");
48
50 const MachineBlockFrequencyInfo *MBFI = nullptr;
51 const ProfileSummaryInfo *PSI = nullptr;
52 StaticDataProfileInfo *SDPI = nullptr;
53
54 // If the global value is a local linkage global variable, return it.
55 // Otherwise, return nullptr.
56 const GlobalVariable *getLocalLinkageGlobalVariable(const GlobalValue *GV);
57
58 // Returns true if the global variable is in one of {.rodata, .bss, .data,
59 // .data.rel.ro} sections.
60 bool inStaticDataSection(const GlobalVariable &GV, const TargetMachine &TM);
61
62 // Returns the constant if the operand refers to a global variable or constant
63 // that gets lowered to static data sections. Otherwise, return nullptr.
64 const Constant *getConstant(const MachineOperand &Op, const TargetMachine &TM,
65 const MachineConstantPool *MCP);
66
67 // Use profiles to partition static data.
68 bool partitionStaticDataWithProfiles(MachineFunction &MF);
69
70 // Update LLVM statistics for a machine function with profiles.
71 void updateStatsWithProfiles(const MachineFunction &MF);
72
73 // Update LLVM statistics for a machine function without profiles.
74 void updateStatsWithoutProfiles(const MachineFunction &MF);
75
76 void annotateStaticDataWithoutProfiles(const MachineFunction &MF);
77
78public:
82 : MBFI(MBFI), PSI(PSI), SDPI(SDPI) {}
84};
85
87public:
88 static char ID;
89
91
92 StringRef getPassName() const override { return "Static Data Splitter"; }
93
94 void getAnalysisUsage(AnalysisUsage &AU) const override {
100 // This pass does not modify any required analysis results except
101 // StaticDataProfileInfoWrapperPass, but StaticDataProfileInfoWrapperPass
102 // is made an immutable pass that it won't be re-scheduled by pass manager
103 // anyway. So mark setPreservesAll() here for faster compile time.
104 AU.setPreservesAll();
105 }
106
107 bool runOnMachineFunction(MachineFunction &MF) override;
108};
109
111 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
113
114 if (!ProfileAvailable) {
115 annotateStaticDataWithoutProfiles(MF);
116 updateStatsWithoutProfiles(MF);
117 return false;
118 }
119
120 bool Changed = partitionStaticDataWithProfiles(MF);
121
122 updateStatsWithProfiles(MF);
123 return Changed;
124}
125
126const Constant *
127StaticDataSplitterImpl::getConstant(const MachineOperand &Op,
128 const TargetMachine &TM,
129 const MachineConstantPool *MCP) {
130 if (!Op.isGlobal() && !Op.isCPI())
131 return nullptr;
132
133 if (Op.isGlobal()) {
134 // Find global variables with local linkage.
135 const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
136 // Skip those not eligible for annotation or not in static data sections.
137 if (!GV || !llvm::memprof::IsAnnotationOK(*GV) ||
138 !inStaticDataSection(*GV, TM))
139 return nullptr;
140 return GV;
141 }
142 assert(Op.isCPI() && "Op must be constant pool index in this branch");
143 int CPI = Op.getIndex();
144 if (CPI == -1)
145 return nullptr;
146
147 assert(MCP != nullptr && "Constant pool info is not available.");
148 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
149
151 return nullptr;
152
153 return CPE.Val.ConstVal;
154}
155
156bool StaticDataSplitterImpl::partitionStaticDataWithProfiles(
157 MachineFunction &MF) {
158 // If any of the static data (jump tables, global variables, constant pools)
159 // are captured by the analysis, set `Changed` to true. Note this pass won't
160 // invalidate any analysis pass (see `getAnalysisUsage` above), so the main
161 // purpose of tracking and conveying the change (to pass manager) is
162 // informative as opposed to invalidating any analysis results. As an example
163 // of where this information is useful, `PMDataManager::dumpPassInfo` will
164 // only dump pass info if a local change happens, otherwise a pass appears as
165 // "skipped".
166 bool Changed = false;
167
168 MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
169
170 // Jump table could be used by either terminating instructions or
171 // non-terminating ones, so we walk all instructions and use
172 // `MachineOperand::isJTI()` to identify jump table operands.
173 // Similarly, `MachineOperand::isCPI()` is used to identify constant pool
174 // usages in the same loop.
175 for (const auto &MBB : MF) {
176 std::optional<uint64_t> Count = MBFI->getBlockProfileCount(&MBB);
177 for (const MachineInstr &I : MBB) {
178 for (const MachineOperand &Op : I.operands()) {
179 if (!Op.isJTI() && !Op.isGlobal() && !Op.isCPI())
180 continue;
181
182 if (Op.isJTI()) {
183 assert(MJTI != nullptr && "Jump table info is not available.");
184 const int JTI = Op.getIndex();
185 // This is not a source block of jump table.
186 if (JTI == -1)
187 continue;
188
189 auto Hotness = MachineFunctionDataHotness::Hot;
190
191 // Hotness is based on source basic block hotness.
192 // TODO: PSI APIs are about instruction hotness. Introduce API for
193 // data access hotness.
194 if (Count && PSI->isColdCount(*Count))
195 Hotness = MachineFunctionDataHotness::Cold;
196
197 Changed |= MJTI->updateJumpTableEntryHotness(JTI, Hotness);
198 } else if (const Constant *C =
199 getConstant(Op, MF.getTarget(), MF.getConstantPool())) {
200 SDPI->addConstantProfileCount(C, Count);
201 Changed = true;
202 }
203 }
204 }
205 }
206 return Changed;
207}
208
209const GlobalVariable *
210StaticDataSplitterImpl::getLocalLinkageGlobalVariable(const GlobalValue *GV) {
211 // LLVM IR Verifier requires that a declaration must have valid declaration
212 // linkage, and local linkages are not among the valid ones. So there is no
213 // need to check GV is not a declaration here.
214 return (GV && GV->hasLocalLinkage()) ? dyn_cast<GlobalVariable>(GV) : nullptr;
215}
216
217bool StaticDataSplitterImpl::inStaticDataSection(const GlobalVariable &GV,
218 const TargetMachine &TM) {
219
221 return Kind.isData() || Kind.isReadOnly() || Kind.isReadOnlyWithRel() ||
222 Kind.isBSS();
223}
224
225void StaticDataSplitterImpl::updateStatsWithProfiles(
226 const MachineFunction &MF) {
228 return;
229
230 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
231 for (const auto &JumpTable : MJTI->getJumpTables()) {
232 if (JumpTable.Hotness == MachineFunctionDataHotness::Hot) {
233 ++NumHotJumpTables;
234 } else {
235 assert(JumpTable.Hotness == MachineFunctionDataHotness::Cold &&
236 "A jump table is either hot or cold when profile information is "
237 "available.");
238 ++NumColdJumpTables;
239 }
240 }
241 }
242}
243
244void StaticDataSplitterImpl::annotateStaticDataWithoutProfiles(
245 const MachineFunction &MF) {
246 for (const auto &MBB : MF)
247 for (const MachineInstr &I : MBB)
248 for (const MachineOperand &Op : I.operands())
249 if (const Constant *C =
250 getConstant(Op, MF.getTarget(), MF.getConstantPool()))
251 SDPI->addConstantProfileCount(C, std::nullopt);
252}
253
254void StaticDataSplitterImpl::updateStatsWithoutProfiles(
255 const MachineFunction &MF) {
257 return;
258
259 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
260 NumUnknownJumpTables += MJTI->getJumpTables().size();
261 }
262}
263
265
267 false, false)
274
278
282 ProfileSummaryInfo *PSI =
285 .getStaticDataProfileInfo();
286 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
287 return Impl.runOnMachineFunction(MF);
288}
289
295 auto &ModuleAnalysisManagerProxy =
297 ProfileSummaryInfo *PSI =
298 ModuleAnalysisManagerProxy.getCachedResult<ProfileSummaryAnalysis>(
299 *MF.getFunction().getParent());
301 &ModuleAnalysisManagerProxy
302 .getCachedResult<StaticDataProfileInfoAnalysis>(
303 *MF.getFunction().getParent())
304 ->getStaticDataProfileInfo();
305 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
306 return Impl.runOnMachineFunction(MF)
310}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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...