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 {
99 // This pass does not modify any required analysis results except
100 // StaticDataProfileInfoWrapperPass, but StaticDataProfileInfoWrapperPass
101 // is made an immutable pass that it won't be re-scheduled by pass manager
102 // anyway. So mark setPreservesAll() here for faster compile time.
103 AU.setPreservesAll();
104 }
105
106 bool runOnMachineFunction(MachineFunction &MF) override;
107};
108
110 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
112
113 if (!ProfileAvailable) {
114 annotateStaticDataWithoutProfiles(MF);
115 updateStatsWithoutProfiles(MF);
116 return false;
117 }
118
119 bool Changed = partitionStaticDataWithProfiles(MF);
120
121 updateStatsWithProfiles(MF);
122 return Changed;
123}
124
125const Constant *
126StaticDataSplitterImpl::getConstant(const MachineOperand &Op,
127 const TargetMachine &TM,
128 const MachineConstantPool *MCP) {
129 if (!Op.isGlobal() && !Op.isCPI())
130 return nullptr;
131
132 if (Op.isGlobal()) {
133 // Find global variables with local linkage.
134 const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
135 // Skip those not eligible for annotation or not in static data sections.
136 if (!GV || !llvm::memprof::IsAnnotationOK(*GV) ||
137 !inStaticDataSection(*GV, TM))
138 return nullptr;
139 return GV;
140 }
141 assert(Op.isCPI() && "Op must be constant pool index in this branch");
142 int CPI = Op.getIndex();
143 if (CPI == -1)
144 return nullptr;
145
146 assert(MCP != nullptr && "Constant pool info is not available.");
147 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
148
150 return nullptr;
151
152 return CPE.Val.ConstVal;
153}
154
155bool StaticDataSplitterImpl::partitionStaticDataWithProfiles(
156 MachineFunction &MF) {
157 // If any of the static data (jump tables, global variables, constant pools)
158 // are captured by the analysis, set `Changed` to true. Note this pass won't
159 // invalidate any analysis pass (see `getAnalysisUsage` above), so the main
160 // purpose of tracking and conveying the change (to pass manager) is
161 // informative as opposed to invalidating any analysis results. As an example
162 // of where this information is useful, `PMDataManager::dumpPassInfo` will
163 // only dump pass info if a local change happens, otherwise a pass appears as
164 // "skipped".
165 bool Changed = false;
166
167 MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
168
169 // Jump table could be used by either terminating instructions or
170 // non-terminating ones, so we walk all instructions and use
171 // `MachineOperand::isJTI()` to identify jump table operands.
172 // Similarly, `MachineOperand::isCPI()` is used to identify constant pool
173 // usages in the same loop.
174 for (const auto &MBB : MF) {
175 std::optional<uint64_t> Count = MBFI->getBlockProfileCount(&MBB);
176 for (const MachineInstr &I : MBB) {
177 for (const MachineOperand &Op : I.operands()) {
178 if (!Op.isJTI() && !Op.isGlobal() && !Op.isCPI())
179 continue;
180
181 if (Op.isJTI()) {
182 assert(MJTI != nullptr && "Jump table info is not available.");
183 const int JTI = Op.getIndex();
184 // This is not a source block of jump table.
185 if (JTI == -1)
186 continue;
187
188 auto Hotness = MachineFunctionDataHotness::Hot;
189
190 // Hotness is based on source basic block hotness.
191 // TODO: PSI APIs are about instruction hotness. Introduce API for
192 // data access hotness.
193 if (Count && PSI->isColdCount(*Count))
194 Hotness = MachineFunctionDataHotness::Cold;
195
196 Changed |= MJTI->updateJumpTableEntryHotness(JTI, Hotness);
197 } else if (const Constant *C =
198 getConstant(Op, MF.getTarget(), MF.getConstantPool())) {
199 SDPI->addConstantProfileCount(C, Count);
200 Changed = true;
201 }
202 }
203 }
204 }
205 return Changed;
206}
207
208const GlobalVariable *
209StaticDataSplitterImpl::getLocalLinkageGlobalVariable(const GlobalValue *GV) {
210 // LLVM IR Verifier requires that a declaration must have valid declaration
211 // linkage, and local linkages are not among the valid ones. So there is no
212 // need to check GV is not a declaration here.
213 return (GV && GV->hasLocalLinkage()) ? dyn_cast<GlobalVariable>(GV) : nullptr;
214}
215
216bool StaticDataSplitterImpl::inStaticDataSection(const GlobalVariable &GV,
217 const TargetMachine &TM) {
218
220 return Kind.isData() || Kind.isReadOnly() || Kind.isReadOnlyWithRel() ||
221 Kind.isBSS();
222}
223
224void StaticDataSplitterImpl::updateStatsWithProfiles(
225 const MachineFunction &MF) {
227 return;
228
229 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
230 for (const auto &JumpTable : MJTI->getJumpTables()) {
231 if (JumpTable.Hotness == MachineFunctionDataHotness::Hot) {
232 ++NumHotJumpTables;
233 } else {
234 assert(JumpTable.Hotness == MachineFunctionDataHotness::Cold &&
235 "A jump table is either hot or cold when profile information is "
236 "available.");
237 ++NumColdJumpTables;
238 }
239 }
240 }
241}
242
243void StaticDataSplitterImpl::annotateStaticDataWithoutProfiles(
244 const MachineFunction &MF) {
245 for (const auto &MBB : MF)
246 for (const MachineInstr &I : MBB)
247 for (const MachineOperand &Op : I.operands())
248 if (const Constant *C =
249 getConstant(Op, MF.getTarget(), MF.getConstantPool()))
250 SDPI->addConstantProfileCount(C, std::nullopt);
251}
252
253void StaticDataSplitterImpl::updateStatsWithoutProfiles(
254 const MachineFunction &MF) {
256 return;
257
258 if (const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) {
259 NumUnknownJumpTables += MJTI->getJumpTables().size();
260 }
261}
262
264
266 false, false)
273
277
281 ProfileSummaryInfo *PSI =
284 .getStaticDataProfileInfo();
285 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
286 return Impl.runOnMachineFunction(MF);
287}
288
294 auto &ModuleAnalysisManagerProxy =
296 ProfileSummaryInfo *PSI =
297 ModuleAnalysisManagerProxy.getCachedResult<ProfileSummaryAnalysis>(
298 *MF.getFunction().getParent());
300 &ModuleAnalysisManagerProxy
301 .getCachedResult<StaticDataProfileInfoAnalysis>(
302 *MF.getFunction().getParent())
303 ->getStaticDataProfileInfo();
304 StaticDataSplitterImpl Impl(MBFI, PSI, SDPI);
305 return Impl.runOnMachineFunction(MF)
309}
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...