1//===- StaticDataSplitter.cpp ---------------------------------------------===//
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
7//===----------------------------------------------------------------------===//
9// The pass uses branch profile data to assign hotness based section qualifiers
10// for the following types of static data:
12// - Module-internal global variables
15// For the original RFC of this pass please see
16// https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744
37 #define DEBUG_TYPE "static-data-splitter"
39 STATISTIC(NumHotJumpTables,
"Number of hot jump tables seen.");
40 STATISTIC(NumColdJumpTables,
"Number of cold jump tables seen.");
42 "Number of jump tables with unknown hotness. They are from functions "
43 "without profile information.");
51 // If the global value is a local linkage global variable, return it.
52 // Otherwise, return nullptr.
55 // Returns true if the global variable is in one of {.rodata, .bss, .data,
56 // .data.rel.ro} sections.
59 // Returns the constant if the operand refers to a global variable or constant
60 // that gets lowered to static data sections. Otherwise, return nullptr.
64 // Use profiles to partition static data.
67 // Update LLVM statistics for a machine function with profiles.
70 // Update LLVM statistics for a machine function without profiles.
90 // This pass does not modify any required analysis results except
91 // StaticDataProfileInfoWrapperPass, but StaticDataProfileInfoWrapperPass
92 // is made an immutable pass that it won't be re-scheduled by pass manager
93 // anyway. So mark setPreservesAll() here for faster compile time.
106 .getStaticDataProfileInfo();
108 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
111 if (!ProfileAvailable) {
112 annotateStaticDataWithoutProfiles(MF);
113 updateStatsWithoutProfiles(MF);
117 bool Changed = partitionStaticDataWithProfiles(MF);
119 updateStatsWithProfiles(MF);
127 if (!
Op.isGlobal() && !
Op.isCPI())
131 // Find global variables with local linkage.
133 // Skip those not eligible for annotation or not in static data sections.
135 !inStaticDataSection(*GV, TM))
139 assert(
Op.isCPI() &&
"Op must be constant pool index in this branch");
140 int CPI =
Op.getIndex();
144 assert(MCP !=
nullptr &&
"Constant pool info is not available.");
145 const MachineConstantPoolEntry &CPE = MCP->
getConstants()[CPI];
153bool StaticDataSplitter::partitionStaticDataWithProfiles(
MachineFunction &MF) {
154 // If any of the static data (jump tables, global variables, constant pools)
155 // are captured by the analysis, set `Changed` to true. Note this pass won't
156 // invalidate any analysis pass (see `getAnalysisUsage` above), so the main
157 // purpose of tracking and conveying the change (to pass manager) is
158 // informative as opposed to invalidating any analysis results. As an example
159 // of where this information is useful, `PMDataManager::dumpPassInfo` will
160 // only dump pass info if a local change happens, otherwise a pass appears as
166 // Jump table could be used by either terminating instructions or
167 // non-terminating ones, so we walk all instructions and use
168 // `MachineOperand::isJTI()` to identify jump table operands.
169 // Similarly, `MachineOperand::isCPI()` is used to identify constant pool
170 // usages in the same loop.
171 for (
const auto &
MBB : MF) {
172 std::optional<uint64_t>
Count = MBFI->getBlockProfileCount(&
MBB);
173 for (
const MachineInstr &
I :
MBB) {
174 for (
const MachineOperand &
Op :
I.operands()) {
175 if (!
Op.isJTI() && !
Op.isGlobal() && !
Op.isCPI())
179 assert(MJTI !=
nullptr &&
"Jump table info is not available.");
180 const int JTI =
Op.getIndex();
181 // This is not a source block of jump table.
185 auto Hotness = MachineFunctionDataHotness::Hot;
187 // Hotness is based on source basic block hotness.
188 // TODO: PSI APIs are about instruction hotness. Introduce API for
189 // data access hotness.
191 Hotness = MachineFunctionDataHotness::Cold;
194 }
else if (
const Constant *
C =
195 getConstant(
Op, MF.getTarget(), MF.getConstantPool())) {
196 SDPI->addConstantProfileCount(
C,
Count);
206StaticDataSplitter::getLocalLinkageGlobalVariable(
const GlobalValue *GV) {
207 // LLVM IR Verifier requires that a declaration must have valid declaration
208 // linkage, and local linkages are not among the valid ones. So there is no
209 // need to check GV is not a declaration here.
213bool StaticDataSplitter::inStaticDataSection(
const GlobalVariable &GV,
217 return Kind.isData() || Kind.isReadOnly() || Kind.isReadOnlyWithRel() ||
221void StaticDataSplitter::updateStatsWithProfiles(
const MachineFunction &MF) {
227 if (
JumpTable.Hotness == MachineFunctionDataHotness::Hot) {
231 "A jump table is either hot or cold when profile information is "
239void StaticDataSplitter::annotateStaticDataWithoutProfiles(
241 for (
const auto &
MBB : MF)
242 for (
const MachineInstr &
I :
MBB)
243 for (
const MachineOperand &
Op :
I.operands())
244 if (
const Constant *
C =
245 getConstant(
Op, MF.getTarget(), MF.getConstantPool()))
246 SDPI->addConstantProfileCount(
C, std::nullopt);
249void StaticDataSplitter::updateStatsWithoutProfiles(
const MachineFunction &MF) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
This is an important base class in LLVM.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
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 ...
const Constant * ConstVal
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...
MachineFunctionPass(char &ID)
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.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
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...
StringRef - Represent a constant reference to a string, i.e.
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.
@ C
The default llvm calling convention, compatible with C.
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void initializeStaticDataSplitterPass(PassRegistry &)
LLVM_ABI MachineFunctionPass * createStaticDataSplitterPass()
createStaticDataSplitterPass - This is a machine-function pass that categorizes static data hotness u...
FunctionAddr VTableAddr Count
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
DWARFExpression::Operation Op