Skip to content

Commit 5d207e9

Browse files
[SDP]Introduce StaticDataSplitter pass and implemenet jump table splitting
1 parent cd66c9b commit 5d207e9

13 files changed

+363
-2
lines changed

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,12 @@ class MachineBasicBlock
997997
/// no changes occurred in the meantime.
998998
bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const;
999999

1000+
/// Return an index for MachineJumpTableInfo if \p this basic block ends with
1001+
/// an indirect jump using a jump table, otherwise -1.
1002+
/// This function is a thin wrapper and forward calls to the per-target method
1003+
/// `TargetInstrInfo::getjumpTableIndex`.
1004+
int getJumpTableIndex() const;
1005+
10001006
void pop_front() { Insts.pop_front(); }
10011007
void pop_back() { Insts.pop_back(); }
10021008
void push_back(MachineInstr *MI) { Insts.push_back(MI); }

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ template <> struct ilist_callback_traits<MachineBasicBlock> {
8888
}
8989
};
9090

91+
// The hotness of static data tracked by a MachineFunction and not represented
92+
// as a global object in the module IR / MIR. Typical examples are
93+
// MachineJumpTableInfo and MachineConstantPool.
94+
enum class DataHotness {
95+
Unknown,
96+
Cold,
97+
Hot,
98+
};
99+
91100
/// MachineFunctionInfo - This class can be derived from and used by targets to
92101
/// hold private target-specific information for each MachineFunction. Objects
93102
/// of type are accessed/created with MF::getInfo and destroyed when the

llvm/include/llvm/CodeGen/MachineJumpTableInfo.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ namespace llvm {
2828
class MachineBasicBlock;
2929
class DataLayout;
3030
class raw_ostream;
31+
enum class DataHotness;
3132

3233
/// MachineJumpTableEntry - One jump table in the jump table info.
3334
///
3435
struct MachineJumpTableEntry {
3536
/// MBBs - The vector of basic blocks from which to create the jump table.
3637
std::vector<MachineBasicBlock*> MBBs;
3738

38-
explicit MachineJumpTableEntry(const std::vector<MachineBasicBlock*> &M)
39-
: MBBs(M) {}
39+
DataHotness Hotness;
40+
41+
explicit MachineJumpTableEntry(const std::vector<MachineBasicBlock *> &M);
4042
};
4143

4244
class MachineJumpTableInfo {
@@ -107,6 +109,8 @@ class MachineJumpTableInfo {
107109
return JumpTables;
108110
}
109111

112+
void updateJumpTableHotness(size_t JTI, DataHotness Hotness);
113+
110114
/// RemoveJumpTable - Mark the specific index as being dead. This will
111115
/// prevent it from being emitted.
112116
void RemoveJumpTable(unsigned Idx) {

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ namespace llvm {
7171
/// using profile information.
7272
MachineFunctionPass *createMachineFunctionSplitterPass();
7373

74+
/// createStaticDataSplitterPass - This pass partions static data sections
75+
/// into a hot and cold section using profile information.
76+
MachineFunctionPass *createStaticDataSplitterPass();
77+
7478
/// MachineFunctionPrinter pass - This pass prints out the machine function to
7579
/// the given stream as a debugging tool.
7680
MachineFunctionPass *

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ void initializeSpeculativeExecutionLegacyPassPass(PassRegistry &);
293293
void initializeSpillPlacementWrapperLegacyPass(PassRegistry &);
294294
void initializeStackColoringLegacyPass(PassRegistry &);
295295
void initializeStackFrameLayoutAnalysisPassPass(PassRegistry &);
296+
void initializeStaticDataSplitterPass(PassRegistry &);
296297
void initializeStackMapLivenessPass(PassRegistry &);
297298
void initializeStackProtectorPass(PassRegistry &);
298299
void initializeStackSafetyGlobalInfoWrapperPassPass(PassRegistry &);

llvm/include/llvm/Passes/MachinePassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass)
236236
DUMMY_MACHINE_FUNCTION_PASS("lrshrink", LiveRangeShrinkPass)
237237
DUMMY_MACHINE_FUNCTION_PASS("machine-combiner", MachineCombinerPass)
238238
DUMMY_MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass)
239+
DUMMY_MACHINE_FUNCTION_PASS("static-data-splitter", StaticDataSplitter)
239240
DUMMY_MACHINE_FUNCTION_PASS("machine-function-splitter", MachineFunctionSplitterPass)
240241
DUMMY_MACHINE_FUNCTION_PASS("machine-latecleanup", MachineLateInstrsCleanupPass)
241242
DUMMY_MACHINE_FUNCTION_PASS("machine-sanmd", MachineSanitizerBinaryMetadata)

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ add_llvm_component_library(LLVMCodeGen
226226
StackMaps.cpp
227227
StackProtector.cpp
228228
StackSlotColoring.cpp
229+
StaticDataSplitter.cpp
229230
SwiftErrorValueTracking.cpp
230231
SwitchLoweringUtils.cpp
231232
TailDuplication.cpp

llvm/lib/CodeGen/CodeGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
130130
initializeStackMapLivenessPass(Registry);
131131
initializeStackProtectorPass(Registry);
132132
initializeStackSlotColoringPass(Registry);
133+
initializeStaticDataSplitterPass(Registry);
133134
initializeStripDebugMachineModulePass(Registry);
134135
initializeTailDuplicateLegacyPass(Registry);
135136
initializeTargetPassConfigPass(Registry);

llvm/lib/CodeGen/MachineBasicBlock.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,10 @@ bool MachineBasicBlock::canSplitCriticalEdge(
14261426
return true;
14271427
}
14281428

1429+
int MachineBasicBlock::getJumpTableIndex() const {
1430+
return findJumpTableIndex(*this);
1431+
}
1432+
14291433
/// Prepare MI to be removed from its bundle. This fixes bundle flags on MI's
14301434
/// neighboring instructions so the bundle won't be broken by removing MI.
14311435
static void unbundleSingleMI(MachineInstr *MI) {

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,10 @@ const unsigned MachineFunction::DebugOperandMemNumber = 1000000;
12911291
// MachineJumpTableInfo implementation
12921292
//===----------------------------------------------------------------------===//
12931293

1294+
MachineJumpTableEntry::MachineJumpTableEntry(
1295+
const std::vector<MachineBasicBlock *> &MBBs)
1296+
: MBBs(MBBs), Hotness(DataHotness::Unknown) {}
1297+
12941298
/// Return the size of each entry in the jump table.
12951299
unsigned MachineJumpTableInfo::getEntrySize(const DataLayout &TD) const {
12961300
// The size of a jump table entry is 4 bytes unless the entry is just the
@@ -1340,6 +1344,15 @@ unsigned MachineJumpTableInfo::createJumpTableIndex(
13401344
return JumpTables.size()-1;
13411345
}
13421346

1347+
void MachineJumpTableInfo::updateJumpTableHotness(size_t JTI,
1348+
DataHotness Hotness) {
1349+
assert(JTI < JumpTables.size() && "Invalid JTI!");
1350+
// Note record the largest hotness is important for mergable data (constant
1351+
// pools). Even if jump table instances are not merged, record the largest
1352+
// value seen fwiw.
1353+
JumpTables[JTI].Hotness = std::max(JumpTables[JTI].Hotness, Hotness);
1354+
}
1355+
13431356
/// If Old is the target of any jump tables, update the jump tables to branch
13441357
/// to New instead.
13451358
bool MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old,
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
// This pass uses profile information to partition static data sections into
10+
// hot and cold ones. It begins to split jump tables based on profile, and
11+
// subsequent patches will handle constant pools and other module internal data.
12+
//
13+
// For the original RFC of this pass please see
14+
// https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744.
15+
16+
#include "llvm/ADT/Statistic.h"
17+
#include "llvm/Analysis/ProfileSummaryInfo.h"
18+
#include "llvm/CodeGen/MBFIWrapper.h"
19+
#include "llvm/CodeGen/MachineBasicBlock.h"
20+
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
21+
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
22+
#include "llvm/CodeGen/MachineConstantPool.h"
23+
#include "llvm/CodeGen/MachineFunction.h"
24+
#include "llvm/CodeGen/MachineFunctionPass.h"
25+
#include "llvm/CodeGen/MachineJumpTableInfo.h"
26+
#include "llvm/CodeGen/Passes.h"
27+
#include "llvm/InitializePasses.h"
28+
#include "llvm/Pass.h"
29+
#include "llvm/Support/CommandLine.h"
30+
31+
using namespace llvm;
32+
33+
#define DEBUG_TYPE "static-data-splitter"
34+
35+
STATISTIC(NumHotJumpTables, "Number of hot jump tables seen");
36+
STATISTIC(NumColdJumpTables, "Number of cold jump tables seen");
37+
STATISTIC(NumUnknownJumpTables,
38+
"Number of jump tables with unknown hotness. Such jump tables will "
39+
"be placed in the hot-suffixed section by default.");
40+
41+
class StaticDataSplitter : public MachineFunctionPass {
42+
const MachineBranchProbabilityInfo *MBPI = nullptr;
43+
const MachineBlockFrequencyInfo *MBFI = nullptr;
44+
const ProfileSummaryInfo *PSI = nullptr;
45+
46+
// Returns true iff any jump table is hot-cold categorized.
47+
bool splitJumpTables(MachineFunction &MF);
48+
49+
// Same as above but works on functions with profile information.
50+
bool splitJumpTablesWithProfiles(MachineFunction &MF,
51+
MachineJumpTableInfo &MJTI);
52+
53+
public:
54+
static char ID;
55+
56+
StaticDataSplitter() : MachineFunctionPass(ID) {
57+
initializeStaticDataSplitterPass(*PassRegistry::getPassRegistry());
58+
}
59+
60+
StringRef getPassName() const override { return "Static Data Splitter"; }
61+
62+
void getAnalysisUsage(AnalysisUsage &AU) const override {
63+
MachineFunctionPass::getAnalysisUsage(AU);
64+
AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
65+
AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
66+
AU.addRequired<ProfileSummaryInfoWrapperPass>();
67+
}
68+
69+
bool runOnMachineFunction(MachineFunction &MF) override;
70+
};
71+
72+
bool StaticDataSplitter::runOnMachineFunction(MachineFunction &MF) {
73+
MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
74+
MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
75+
PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
76+
77+
// Split jump tables based on profile information. Subsequent patches will
78+
// handle other data types like constant pools, module-internal data, etc.
79+
return splitJumpTables(MF);
80+
}
81+
82+
bool StaticDataSplitter::splitJumpTablesWithProfiles(
83+
MachineFunction &MF, MachineJumpTableInfo &MJTI) {
84+
int NumChangedJumpTables = 0;
85+
// Regard a jump table as hot by default. If the source and all of destination
86+
// blocks are cold, regard the jump table as cold.
87+
DataHotness Hotness = DataHotness::Hot;
88+
for (const auto &MBB : MF) {
89+
// IMPORTANT, `getJumpTableIndex` is a thin wrapper around per-target
90+
// interface `TargetInstrInfo::getjumpTableIndex`, and only X86 implements
91+
// it so far.
92+
const int JTI = MBB.getJumpTableIndex();
93+
// This is not a source block of jump table.
94+
if (JTI == -1)
95+
continue;
96+
97+
bool AllBlocksCold = true;
98+
99+
if (!PSI->isColdBlock(&MBB, MBFI))
100+
AllBlocksCold = false;
101+
102+
for (const MachineBasicBlock *MBB : MJTI.getJumpTables()[JTI].MBBs)
103+
if (!PSI->isColdBlock(MBB, MBFI))
104+
AllBlocksCold = false;
105+
106+
if (AllBlocksCold) {
107+
Hotness = DataHotness::Cold;
108+
++NumColdJumpTables;
109+
} else {
110+
++NumHotJumpTables;
111+
}
112+
113+
MF.getJumpTableInfo()->updateJumpTableHotness(JTI, Hotness);
114+
++NumChangedJumpTables;
115+
}
116+
return NumChangedJumpTables > 0;
117+
}
118+
119+
bool StaticDataSplitter::splitJumpTables(MachineFunction &MF) {
120+
MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
121+
if (!MJTI || MJTI->getJumpTables().empty())
122+
return false;
123+
124+
// Place jump tables according to block hotness if block counters are
125+
// available. Check function entry count because BFI depends on it to derive
126+
// block counters.
127+
if (PSI && PSI->hasProfileSummary() && MBFI &&
128+
MF.getFunction().getEntryCount())
129+
return splitJumpTablesWithProfiles(MF, *MJTI);
130+
131+
// Conservatively place all jump tables in the hot-suffixed section if profile
132+
// information for the function is not available, or the target doesn't
133+
// implement `TargetInstrInfo::getJumpTableIndex` yet.
134+
for (size_t JTI = 0; JTI < MJTI->getJumpTables().size(); JTI++)
135+
MF.getJumpTableInfo()->updateJumpTableHotness(JTI, DataHotness::Hot);
136+
137+
NumUnknownJumpTables += MJTI->getJumpTables().size();
138+
return true;
139+
}
140+
141+
char StaticDataSplitter::ID = 0;
142+
143+
INITIALIZE_PASS_BEGIN(StaticDataSplitter, DEBUG_TYPE, "Split static data",
144+
false, false)
145+
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
146+
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
147+
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
148+
INITIALIZE_PASS_END(StaticDataSplitter, DEBUG_TYPE, "Split static data", false,
149+
false)
150+
151+
MachineFunctionPass *llvm::createStaticDataSplitterPass() {
152+
return new StaticDataSplitter();
153+
}

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,7 @@ void TargetPassConfig::addMachinePasses() {
12561256
"performance.\n";
12571257
}
12581258
}
1259+
addPass(createStaticDataSplitterPass());
12591260
addPass(createMachineFunctionSplitterPass());
12601261
}
12611262
// We run the BasicBlockSections pass if either we need BB sections or BB

0 commit comments

Comments
 (0)