LLVM 20.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// - Constant pools (TODO)
13// - Other module-internal data (TODO)
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
18#include "llvm/ADT/ScopeExit.h"
19#include "llvm/ADT/Statistic.h"
29#include "llvm/CodeGen/Passes.h"
31#include "llvm/Pass.h"
33
34using namespace llvm;
35
36#define DEBUG_TYPE "static-data-splitter"
37
38STATISTIC(NumHotJumpTables, "Number of hot jump tables seen");
39STATISTIC(NumColdJumpTables, "Number of cold jump tables seen");
40STATISTIC(NumUnknownJumpTables,
41 "Number of jump tables with unknown hotness. Option "
42 "-static-data-default-hotness specifies the hotness.");
43
45 "static-data-default-hotness", cl::Hidden,
46 cl::desc("This option specifies the hotness of static data when profile "
47 "information is unavailable"),
48 cl::init(MachineFunctionDataHotness::Hot),
49 cl::values(clEnumValN(MachineFunctionDataHotness::Hot, "hot", "Hot"),
50 clEnumValN(MachineFunctionDataHotness::Cold, "cold", "Cold")));
51
53 const MachineBranchProbabilityInfo *MBPI = nullptr;
54 const MachineBlockFrequencyInfo *MBFI = nullptr;
55 const ProfileSummaryInfo *PSI = nullptr;
56
57 // Returns true iff any jump table is hot-cold categorized.
58 bool splitJumpTables(MachineFunction &MF);
59
60 // Same as above but works on functions with profile information.
61 bool splitJumpTablesWithProfiles(const MachineFunction &MF,
63
64public:
65 static char ID;
66
69 }
70
71 StringRef getPassName() const override { return "Static Data Splitter"; }
72
73 void getAnalysisUsage(AnalysisUsage &AU) const override {
78 }
79
80 bool runOnMachineFunction(MachineFunction &MF) override;
81};
82
84 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
85 MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
86 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
87
88 return splitJumpTables(MF);
89}
90
91bool StaticDataSplitter::splitJumpTablesWithProfiles(
92 const MachineFunction &MF, MachineJumpTableInfo &MJTI) {
93 int NumChangedJumpTables = 0;
94
95 // Jump table could be used by either terminating instructions or
96 // non-terminating ones, so we walk all instructions and use
97 // `MachineOperand::isJTI()` to identify jump table operands.
98 // Similarly, `MachineOperand::isCPI()` can identify constant pool usages
99 // in the same loop.
100 for (const auto &MBB : MF) {
101 for (const MachineInstr &I : MBB) {
102 for (const MachineOperand &Op : I.operands()) {
103 if (!Op.isJTI())
104 continue;
105 const int JTI = Op.getIndex();
106 // This is not a source block of jump table.
107 if (JTI == -1)
108 continue;
109
110 auto Hotness = MachineFunctionDataHotness::Hot;
111
112 // Hotness is based on source basic block hotness.
113 // TODO: PSI APIs are about instruction hotness. Introduce API for data
114 // access hotness.
115 if (PSI->isColdBlock(&MBB, MBFI))
116 Hotness = MachineFunctionDataHotness::Cold;
117
118 if (MJTI.updateJumpTableEntryHotness(JTI, Hotness))
119 ++NumChangedJumpTables;
120 }
121 }
122 }
123 return NumChangedJumpTables > 0;
124}
125
126bool StaticDataSplitter::splitJumpTables(MachineFunction &MF) {
128 if (!MJTI || MJTI->getJumpTables().empty())
129 return false;
130
131 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
133 auto statOnExit = llvm::make_scope_exit([&] {
135 return;
136
137 if (!ProfileAvailable) {
138 NumUnknownJumpTables += MJTI->getJumpTables().size();
139 return;
140 }
141
142 for (size_t JTI = 0; JTI < MJTI->getJumpTables().size(); JTI++) {
143 auto Hotness = MJTI->getJumpTables()[JTI].Hotness;
144 if (Hotness == MachineFunctionDataHotness::Hot) {
145 ++NumHotJumpTables;
146 } else {
147 assert(Hotness == MachineFunctionDataHotness::Cold &&
148 "A jump table is either hot or cold when profile information is "
149 "available.");
150 ++NumColdJumpTables;
151 }
152 }
153 });
154
155 // Place jump tables according to block hotness if function has profile data.
156 if (ProfileAvailable)
157 return splitJumpTablesWithProfiles(MF, *MJTI);
158
159 // If function profile is unavailable (e.g., module not instrumented, or new
160 // code paths lacking samples), -static-data-default-hotness specifies the
161 // hotness.
162 for (size_t JTI = 0; JTI < MJTI->getJumpTables().size(); JTI++)
165
166 return true;
167}
168
170
172 false, false)
177 false)
178
180 return new StaticDataSplitter();
181}
MachineBasicBlock & MBB
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Definition: CommandLine.h:686
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static cl::opt< MachineFunctionDataHotness > StaticDataDefaultHotness("static-data-default-hotness", cl::Hidden, cl::desc("This option specifies the hotness of static data when profile " "information is unavailable"), cl::init(MachineFunctionDataHotness::Hot), cl::values(clEnumValN(MachineFunctionDataHotness::Hot, "hot", "Hot"), clEnumValN(MachineFunctionDataHotness::Cold, "cold", "Cold")))
static Split data
#define DEBUG_TYPE
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:166
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()
This class represents an Operation in the Expression.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
Definition: Function.h:329
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
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.
Representation of each machine instruction.
Definition: MachineInstr.h:71
bool updateJumpTableEntryHotness(size_t JTI, MachineFunctionDataHotness Hotness)
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Analysis providing profile information.
bool hasProfileSummary() const
Returns true if profile summary is available.
bool isColdBlock(const BBType *BB, BFIT *BFI) const
Returns true if BasicBlock BB is considered cold.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:711
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1697
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition: ScopeExit.h:59
MachineFunctionPass * createStaticDataSplitterPass()
createStaticDataSplitterPass - This pass partitions a static data section into a hot and cold section...
bool AreStatisticsEnabled()
Check if statistics are enabled.
Definition: Statistic.cpp:139
void initializeStaticDataSplitterPass(PassRegistry &)