66//
77// ===----------------------------------------------------------------------===//
88//
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.
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)
1214//
1315// For the original RFC of this pass please see
14- // https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744.
16+ // https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744
1517
18+ #include " llvm/ADT/ScopeExit.h"
1619#include " llvm/ADT/Statistic.h"
1720#include " llvm/Analysis/ProfileSummaryInfo.h"
1821#include " llvm/CodeGen/MBFIWrapper.h"
@@ -35,8 +38,15 @@ using namespace llvm;
3538STATISTIC (NumHotJumpTables, " Number of hot jump tables seen" );
3639STATISTIC (NumColdJumpTables, " Number of cold jump tables seen" );
3740STATISTIC (NumUnknownJumpTables,
38- " Number of jump tables with unknown hotness. Such jump tables will "
39- " be placed in the hot-suffixed section by default." );
41+ " Number of jump tables with unknown hotness. Option "
42+ " -static-data-default-hotness specifies the hotness." );
43+
44+ static cl::opt<MachineFunctionDataHotness> StaticDataDefaultHotness (
45+ " static-data-default-hotness" , cl::Hidden,
46+ cl::desc (" The hotness for static data with unknown hotness" ),
47+ cl::init(MachineFunctionDataHotness::Hot),
48+ cl::values(clEnumValN(MachineFunctionDataHotness::Hot, " hot" , " Hot" ),
49+ clEnumValN(MachineFunctionDataHotness::Cold, " cold" , " Cold" )));
4050
4151class StaticDataSplitter : public MachineFunctionPass {
4252 const MachineBranchProbabilityInfo *MBPI = nullptr ;
@@ -82,12 +92,7 @@ bool StaticDataSplitter::runOnMachineFunction(MachineFunction &MF) {
8292bool StaticDataSplitter::splitJumpTablesWithProfiles (
8393 MachineFunction &MF, MachineJumpTableInfo &MJTI) {
8494 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. While a destination block
87- // does not read a jump table (unless it's also a source block), a hot
88- // destination heuristically makes its jump table hot to accommodate for
89- // potential profile data skews (from sampled profiles, for example).
90- DataHotness Hotness = DataHotness::Hot;
95+
9196 for (const auto &MBB : MF) {
9297 // IMPORTANT, `getJumpTableIndex` is a thin wrapper around per-target
9398 // interface `TargetInstrInfo::getjumpTableIndex`, and only X86 implements
@@ -97,24 +102,14 @@ bool StaticDataSplitter::splitJumpTablesWithProfiles(
97102 if (JTI == -1 )
98103 continue ;
99104
100- bool AllBlocksCold = true ;
101-
102- if (!PSI->isColdBlock (&MBB, MBFI))
103- AllBlocksCold = false ;
105+ auto Hotness = MachineFunctionDataHotness::Hot;
104106
105- for (const MachineBasicBlock *MBB : MJTI.getJumpTables ()[JTI].MBBs )
106- if (!PSI->isColdBlock (MBB, MBFI))
107- AllBlocksCold = false ;
108-
109- if (AllBlocksCold) {
110- Hotness = DataHotness::Cold;
111- ++NumColdJumpTables;
112- } else {
113- ++NumHotJumpTables;
114- }
107+ // Hotness is based on source basic block hotness.
108+ if (PSI->isColdBlock (&MBB, MBFI))
109+ Hotness = MachineFunctionDataHotness::Cold;
115110
116- MF.getJumpTableInfo ()->updateJumpTableHotness (JTI, Hotness);
117- ++NumChangedJumpTables;
111+ if ( MF.getJumpTableInfo ()->updateJumpTableEntryHotness (JTI, Hotness))
112+ ++NumChangedJumpTables;
118113 }
119114 return NumChangedJumpTables > 0 ;
120115}
@@ -124,18 +119,40 @@ bool StaticDataSplitter::splitJumpTables(MachineFunction &MF) {
124119 if (!MJTI || MJTI->getJumpTables ().empty ())
125120 return false ;
126121
122+ const bool ProfileAvailable = PSI && PSI->hasProfileSummary () && MBFI &&
123+ MF.getFunction ().hasProfileData ();
124+ auto statOnExit = llvm::make_scope_exit ([&] {
125+ if (!AreStatisticsEnabled ())
126+ return ;
127+
128+ if (!ProfileAvailable) {
129+ NumUnknownJumpTables += MJTI->getJumpTables ().size ();
130+ return ;
131+ }
132+
133+ for (size_t JTI = 0 ; JTI < MJTI->getJumpTables ().size (); JTI++) {
134+ auto Hotness = MJTI->getJumpTables ()[JTI].Hotness ;
135+ if (Hotness == MachineFunctionDataHotness::Hot)
136+ NumHotJumpTables++;
137+ else {
138+ assert (Hotness == MachineFunctionDataHotness::Cold &&
139+ " A jump table is hot or cold when profile information is "
140+ " available." );
141+ NumColdJumpTables++;
142+ }
143+ }
144+ });
145+
127146 // Place jump tables according to block hotness if function has profile data.
128- if (PSI && PSI->hasProfileSummary () && MBFI &&
129- MF.getFunction ().hasProfileData ())
147+ if (ProfileAvailable)
130148 return splitJumpTablesWithProfiles (MF, *MJTI);
131149
132- // Conservatively place all jump tables in the hot-suffixed section if profile
133- // information for the function is not available, or the target doesn't
134- // implement `TargetInstrInfo::getJumpTableIndex` yet.
150+ // If function profile is unavailable, -static-data-default-hotness specifies
151+ // the hotness.
135152 for (size_t JTI = 0 ; JTI < MJTI->getJumpTables ().size (); JTI++)
136- MF.getJumpTableInfo ()->updateJumpTableHotness (JTI, DataHotness::Hot);
153+ MF.getJumpTableInfo ()->updateJumpTableEntryHotness (
154+ JTI, StaticDataDefaultHotness);
137155
138- NumUnknownJumpTables += MJTI->getJumpTables ().size ();
139156 return true ;
140157}
141158
0 commit comments