LLVM 21.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. They are from functions "
42 "without profile information.");
43
45 const MachineBranchProbabilityInfo *MBPI = nullptr;
46 const MachineBlockFrequencyInfo *MBFI = nullptr;
47 const ProfileSummaryInfo *PSI = nullptr;
48
49 // Returns true iff any jump table is hot-cold categorized.
50 bool splitJumpTables(MachineFunction &MF);
51
52 // Same as above but works on functions with profile information.
53 bool splitJumpTablesWithProfiles(const MachineFunction &MF,
55
56public:
57 static char ID;
58
61 }
62
63 StringRef getPassName() const override { return "Static Data Splitter"; }
64
65 void getAnalysisUsage(AnalysisUsage &AU) const override {
70 }
71
72 bool runOnMachineFunction(MachineFunction &MF) override;
73};
74
76 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
77 MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
78 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
79
80 return splitJumpTables(MF);
81}
82
83bool StaticDataSplitter::splitJumpTablesWithProfiles(
84 const MachineFunction &MF, MachineJumpTableInfo &MJTI) {
85 int NumChangedJumpTables = 0;
86
87 // Jump table could be used by either terminating instructions or
88 // non-terminating ones, so we walk all instructions and use
89 // `MachineOperand::isJTI()` to identify jump table operands.
90 // Similarly, `MachineOperand::isCPI()` can identify constant pool usages
91 // in the same loop.
92 for (const auto &MBB : MF) {
93 for (const MachineInstr &I : MBB) {
94 for (const MachineOperand &Op : I.operands()) {
95 if (!Op.isJTI())
96 continue;
97 const int JTI = Op.getIndex();
98 // This is not a source block of jump table.
99 if (JTI == -1)
100 continue;
101
102 auto Hotness = MachineFunctionDataHotness::Hot;
103
104 // Hotness is based on source basic block hotness.
105 // TODO: PSI APIs are about instruction hotness. Introduce API for data
106 // access hotness.
107 if (PSI->isColdBlock(&MBB, MBFI))
108 Hotness = MachineFunctionDataHotness::Cold;
109
110 if (MJTI.updateJumpTableEntryHotness(JTI, Hotness))
111 ++NumChangedJumpTables;
112 }
113 }
114 }
115 return NumChangedJumpTables > 0;
116}
117
118bool StaticDataSplitter::splitJumpTables(MachineFunction &MF) {
120 if (!MJTI || MJTI->getJumpTables().empty())
121 return false;
122
123 const bool ProfileAvailable = PSI && PSI->hasProfileSummary() && MBFI &&
125 auto statOnExit = llvm::make_scope_exit([&] {
127 return;
128
129 if (!ProfileAvailable) {
130 NumUnknownJumpTables += MJTI->getJumpTables().size();
131 return;
132 }
133
134 for (size_t JTI = 0; JTI < MJTI->getJumpTables().size(); JTI++) {
135 auto Hotness = MJTI->getJumpTables()[JTI].Hotness;
136 if (Hotness == MachineFunctionDataHotness::Hot) {
137 ++NumHotJumpTables;
138 } else {
139 assert(Hotness == MachineFunctionDataHotness::Cold &&
140 "A jump table is either hot or cold when profile information is "
141 "available.");
142 ++NumColdJumpTables;
143 }
144 }
145 });
146
147 // Place jump tables according to block hotness if function has profile data.
148 if (ProfileAvailable)
149 return splitJumpTablesWithProfiles(MF, *MJTI);
150
151 return true;
152}
153
155
157 false, false)
162 false)
163
165 return new StaticDataSplitter();
166}
MachineBasicBlock & MBB
#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 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:341
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
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 &)