Skip to content

Commit 5336259

Browse files
committed
Show ascii art of the CFG for cloning.
1 parent b2a9bf4 commit 5336259

File tree

3 files changed

+107
-75
lines changed

3 files changed

+107
-75
lines changed

llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,39 @@
2929
namespace llvm {
3030

3131
// This structure represents a unique ID for every block specified in the
32-
// profile.
32+
// input profile.
3333
struct ProfileBBID {
34+
// Basic block id associated with `MachineBasicBlock::BBID`.
3435
unsigned BBID;
36+
// The clone id associated with the block. This is zero for the original
37+
// block. For the cloned ones, it is equal to 1 + index of the associated
38+
// path in `FunctionPathAndClusterInfo::ClonePaths`.
3539
unsigned CloneID;
3640
};
3741

42+
// This struct represents the cluster information for a machine basic block,
43+
// which is specifed by a unique ID. This templated struct is used for both the
44+
// raw input profile (as `BBClusterInfo<ProfileBBID>`) and the processed profile
45+
// after applying the clonings (as `BBClusterInfo<unsigned>`).
46+
template <typename BBIDType> struct BBClusterInfo {
47+
// Basic block ID.
48+
BBIDType BasicBlockID;
49+
// Cluster ID this basic block belongs to.
50+
unsigned ClusterID;
51+
// Position of basic block within the cluster.
52+
unsigned PositionInCluster;
53+
};
54+
55+
// This represents the raw input profile for one function.
56+
struct FunctionPathAndClusterInfo {
57+
// BB Cluster information specified by `ProfileBBID`s (before cloning).
58+
SmallVector<BBClusterInfo<ProfileBBID>> ClusterInfo;
59+
// Paths to clone. A path a -> b -> c -> d implies cloning b, c, and d along
60+
// the edge a -> b (a is not cloned). The index of the path in this vector
61+
// determines the `ProfileBBID::CloneID` of the cloned blocks in that path.
62+
SmallVector<SmallVector<unsigned>> ClonePaths;
63+
};
64+
3865
// Provides DenseMapInfo for ProfileBBID.
3966
template <> struct DenseMapInfo<ProfileBBID> {
4067
static inline ProfileBBID getEmptyKey() {
@@ -56,26 +83,6 @@ template <> struct DenseMapInfo<ProfileBBID> {
5683
}
5784
};
5885

59-
// This struct represents the cluster information for a machine basic block,
60-
// which is specifed by a unique ID.
61-
template <typename BBIDType> struct BBProfile {
62-
// Basic block ID.
63-
BBIDType BasicBlockID;
64-
// Cluster ID this basic block belongs to.
65-
unsigned ClusterID;
66-
// Position of basic block within the cluster.
67-
unsigned PositionInCluster;
68-
};
69-
70-
// This represents the profile for one function.
71-
struct RawFunctionProfile {
72-
// BB Cluster information specified by `ProfileBBID`s (before cloning).
73-
SmallVector<BBProfile<ProfileBBID>> RawBBProfiles;
74-
// Paths to clone. A path a -> b -> c -> d implies cloning b, c, and d along
75-
// the edge a -> b.
76-
SmallVector<SmallVector<unsigned>> ClonePaths;
77-
};
78-
7986
class BasicBlockSectionsProfileReader : public ImmutablePass {
8087
public:
8188
static char ID;
@@ -106,11 +113,11 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
106113
// function. If the first element is true and the second element is empty, it
107114
// means unique basic block sections are desired for all basic blocks of the
108115
// function.
109-
std::pair<bool, RawFunctionProfile>
110-
getRawProfileForFunction(StringRef FuncName) const;
116+
std::pair<bool, FunctionPathAndClusterInfo>
117+
getPathAndClusterInfoForFunction(StringRef FuncName) const;
111118

112119
// Initializes the FunctionNameToDIFilename map for the current module and
113-
// then reads the profile for matching functions.
120+
// then reads the profile for the matching functions.
114121
bool doInitialization(Module &M) override;
115122

116123
private:
@@ -127,7 +134,7 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
127134
inconvertibleErrorCode());
128135
}
129136

130-
// Parses a `ProfileBBID` from `S`.
137+
// Parses a `ProfileBBID` from `S`. `S` should be in the form "<bbid>" (representing an original block) or "<bbid>.<cloneid>" (representing a cloned block) where bbid is a non-negative integer and cloneid is a positive integer.
131138
Expected<ProfileBBID> parseProfileBBID(StringRef S) const;
132139

133140
// Reads the basic block sections profile for functions in this module.
@@ -150,16 +157,16 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
150157
// empty string if no debug info is available.
151158
StringMap<SmallString<128>> FunctionNameToDIFilename;
152159

153-
// This encapsulates the BB cluster information for the whole program.
160+
// This contains the BB cluster information for the whole program.
154161
//
155162
// For every function name, it contains the cloning and cluster information
156163
// for (all or some of) its basic blocks. The cluster information for every
157164
// basic block includes its cluster ID along with the position of the basic
158165
// block in that cluster.
159-
StringMap<RawFunctionProfile> RawProgramProfile;
166+
StringMap<FunctionPathAndClusterInfo> ProgramPathAndClusterInfo;
160167

161168
// Some functions have alias names. We use this map to find the main alias
162-
// name for which we have mapping in ProgramBBClusterInfo.
169+
// name which appears in ProgramPathAndClusterInfo as a key.
163170
StringMap<StringRef> FuncAliasMap;
164171
};
165172

llvm/lib/CodeGen/BasicBlockSections.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ updateBranches(MachineFunction &MF,
175175
// clusters, they are moved into a single "Exception" section. Eventually,
176176
// clusters are ordered in increasing order of their IDs, with the "Exception"
177177
// and "Cold" succeeding all other clusters.
178-
// BBProfilesByBBID represents the cluster information for basic blocks. It
178+
// ClusterInfoByBBID represents the cluster information for basic blocks. It
179179
// maps from BBID of basic blocks to their cluster information. If this is
180180
// empty, it means unique sections for all basic blocks in the function.
181181
static void assignSections(
182182
MachineFunction &MF,
183-
const DenseMap<unsigned, BBProfile<unsigned>> &BBProfilesByBBID) {
183+
const DenseMap<unsigned, BBClusterInfo<unsigned>> &ClusterInfoByBBID) {
184184
assert(MF.hasBBSections() && "BB Sections is not set for function.");
185185
// This variable stores the section ID of the cluster containing eh_pads (if
186186
// all eh_pads are one cluster). If more than one cluster contain eh_pads, we
@@ -191,17 +191,17 @@ static void assignSections(
191191
// With the 'all' option, every basic block is placed in a unique section.
192192
// With the 'list' option, every basic block is placed in a section
193193
// associated with its cluster, unless we want individual unique sections
194-
// for every basic block in this function (if BBProfilesByBBID is empty).
194+
// for every basic block in this function (if ClusterInfoByBBID is empty).
195195
if (MF.getTarget().getBBSectionsType() == llvm::BasicBlockSection::All ||
196-
BBProfilesByBBID.empty()) {
196+
ClusterInfoByBBID.empty()) {
197197
// If unique sections are desired for all basic blocks of the function, we
198198
// set every basic block's section ID equal to its original position in
199199
// the layout (which is equal to its number). This ensures that basic
200200
// blocks are ordered canonically.
201201
MBB.setSectionID(MBB.getNumber());
202202
} else {
203-
auto I = BBProfilesByBBID.find(*MBB.getBBID());
204-
if (I != BBProfilesByBBID.end()) {
203+
auto I = ClusterInfoByBBID.find(*MBB.getBBID());
204+
if (I != ClusterInfoByBBID.end()) {
205205
MBB.setSectionID(I->second.ClusterID);
206206
} else {
207207
// BB goes into the special cold section if it is not specified in the
@@ -308,25 +308,27 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
308308
return true;
309309
}
310310

311-
DenseMap<unsigned, BBProfile<unsigned>> BBProfilesByBBID;
311+
DenseMap<unsigned, BBClusterInfo<unsigned>> ClusterInfoByBBID;
312312
if (BBSectionsType == BasicBlockSection::List) {
313-
auto [HasProfile, RawProfile] =
314-
getAnalysis<BasicBlockSectionsProfileReader>().getRawProfileForFunction(
313+
auto [HasProfile, PathAndClusterInfo] =
314+
getAnalysis<BasicBlockSectionsProfileReader>().getPathAndClusterInfoForFunction(
315315
MF.getName());
316316
if (!HasProfile)
317317
return true;
318-
// TODO: Apply the path cloning profile.
319-
for (const BBProfile<ProfileBBID> &BBP : RawProfile.RawBBProfiles) {
320-
assert(!BBP.BasicBlockID.CloneID && "Path cloning is not supported yet.");
321-
BBProfilesByBBID.try_emplace(BBP.BasicBlockID.BBID,
322-
BBProfile<unsigned>{BBP.BasicBlockID.BBID,
323-
BBP.ClusterID,
324-
BBP.PositionInCluster});
318+
for (const BBClusterInfo<ProfileBBID> &BBP : PathAndClusterInfo.ClusterInfo) {
319+
// TODO: Apply the path cloning profile.
320+
assert(!BBP.BasicBlockID.CloneID && "Path cloning is not supported yet");
321+
const auto [I, Inserted] = ClusterInfoByBBID.try_emplace(
322+
BBP.BasicBlockID.BBID,
323+
BBClusterInfo<unsigned>{BBP.BasicBlockID.BBID, BBP.ClusterID,
324+
BBP.PositionInCluster});
325+
(void)I;
326+
assert(Inserted && "Duplicate BBID found in profile");
325327
}
326328
}
327329

328330
MF.setBBSectionsType(BBSectionsType);
329-
assignSections(MF, BBProfilesByBBID);
331+
assignSections(MF, ClusterInfoByBBID);
330332

331333
// We make sure that the cluster including the entry basic block precedes all
332334
// other clusters.
@@ -360,8 +362,8 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
360362
// If the two basic block are in the same section, the order is decided by
361363
// their position within the section.
362364
if (XSectionID.Type == MBBSectionID::SectionType::Default)
363-
return BBProfilesByBBID.lookup(*X.getBBID()).PositionInCluster <
364-
BBProfilesByBBID.lookup(*Y.getBBID()).PositionInCluster;
365+
return ClusterInfoByBBID.lookup(*X.getBBID()).PositionInCluster <
366+
ClusterInfoByBBID.lookup(*Y.getBBID()).PositionInCluster;
365367
return X.getNumber() < Y.getNumber();
366368
};
367369

llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ BasicBlockSectionsProfileReader::parseProfileBBID(StringRef S) const {
5656
}
5757

5858
bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
59-
return getRawProfileForFunction(FuncName).first;
59+
return getPathAndClusterInfoForFunction(FuncName).first;
6060
}
6161

62-
std::pair<bool, RawFunctionProfile>
63-
BasicBlockSectionsProfileReader::getRawProfileForFunction(
62+
std::pair<bool, FunctionPathAndClusterInfo>
63+
BasicBlockSectionsProfileReader::getPathAndClusterInfoForFunction(
6464
StringRef FuncName) const {
65-
auto R = RawProgramProfile.find(getAliasName(FuncName));
66-
return R != RawProgramProfile.end() ? std::pair(true, R->second)
67-
: std::pair(false, RawFunctionProfile());
65+
auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
66+
return R != ProgramPathAndClusterInfo.end() ? std::pair(true, R->second)
67+
: std::pair(false, FunctionPathAndClusterInfo());
6868
}
6969

7070
// Reads the version 1 basic block sections profile. Profile for each function
@@ -85,20 +85,42 @@ BasicBlockSectionsProfileReader::getRawProfileForFunction(
8585
// clone basic blocks along a path. The cloned blocks are then specified in the
8686
// cluster information.
8787
// The following profile lists two cloning paths (starting with 'p') for
88-
// function bar and places the total 11 blocks within two clusters. Each cloned
89-
// block is identified by its original block id, along with its clone id. A
90-
// block cloned multiple times (2 in this example) appears with distinct clone
91-
// ids (2.1 and 2.2).
92-
// ---------------------------
88+
// function bar and places the total 9 blocks within two clusters. The blocks in each path are cloned along the path from the first block (the first block is not cloned).
89+
// For instance, path 1 (1 -> 3 -> 4) specifies that 3 and 4 must be cloned along the edge 1->3. In the clusters, each cloned
90+
// block is identified by its original block id, along with its clone id. For instance, the cloned blocks from path 1 are represented by 3.1 and 4.1.
91+
// A block cloned multiple times appears with distinct clone ids. The CFG for bar
92+
// is shown below before and after cloning with its final clusters labeled.
9393
//
9494
// f main
9595
// f bar
96-
// p 1 2 3
97-
// p 4 2 5
98-
// c 2 3 5 6 7
99-
// c 1 2.1 3.1 4 2.2 5.1
96+
// p 1 3 4 # cloning path 1
97+
// p 4 2 # cloning path 2
98+
// c 1 3.1 4.1 6 # basic block cluster 1
99+
// c 0 2 3 4 2.1 5 # basic block cluster 2
100+
// ****************************************************************************
101+
// function bar before and after cloning with basic block clusters shown.
102+
// ****************************************************************************
103+
// .... ..............
104+
// 0 -------+ : 0 :---->: 1 ---> 3.1 :
105+
// | | : | : :........ | :
106+
// v v : v : : v :
107+
// +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1
108+
// | | | | : | : : | :
109+
// | v | | : v ....... : v :
110+
// | 3 <------+ | : 3 <--+ : : 6 :
111+
// | | | : | | : :....:
112+
// | v | : v | :
113+
// +--- 4 ---> 6 | : 4 | :
114+
// | : | | :
115+
// | : v | :
116+
// | :2.1---+ : cluster 2
117+
// | : | ......:
118+
// | : v :
119+
// +-->: 5 :
120+
// ....
121+
// ****************************************************************************
100122
Error BasicBlockSectionsProfileReader::ReadV1Profile() {
101-
auto FI = RawProgramProfile.end();
123+
auto FI = ProgramPathAndClusterInfo.end();
102124

103125
// Current cluster ID corresponding to this function.
104126
unsigned CurrentCluster = 0;
@@ -121,7 +143,7 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
121143
S.split(Values, ' ');
122144
switch (Specifier) {
123145
case '@':
124-
break;
146+
continue;
125147
case 'm': // Module name speicifer.
126148
if (Values.size() != 1) {
127149
return createProfileParseError(Twine("invalid module name value: '") +
@@ -142,7 +164,7 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
142164
if (!FunctionFound) {
143165
// Skip the following profile by setting the profile iterator (FI) to
144166
// the past-the-end element.
145-
FI = RawProgramProfile.end();
167+
FI = ProgramPathAndClusterInfo.end();
146168
DIFilename = "";
147169
continue;
148170
}
@@ -151,7 +173,7 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
151173

152174
// Prepare for parsing clusters of this function name.
153175
// Start a new cluster map for this function name.
154-
auto R = RawProgramProfile.try_emplace(Values.front());
176+
auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());
155177
// Report error when multiple profiles have been specified for the same
156178
// function.
157179
if (!R.second)
@@ -168,8 +190,8 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
168190
case 'c': // Basic block cluster specifier.
169191
// Skip the profile when we the profile iterator (FI) refers to the
170192
// past-the-end element.
171-
if (FI == RawProgramProfile.end())
172-
break;
193+
if (FI == ProgramPathAndClusterInfo.end())
194+
continue;
173195
// Reset current cluster position.
174196
CurrentPosition = 0;
175197
for (auto BasicBlockIDStr : Values) {
@@ -185,7 +207,7 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
185207
return createProfileParseError(
186208
"entry BB (0) does not begin a cluster.");
187209

188-
FI->second.RawBBProfiles.emplace_back(BBProfile<ProfileBBID>{
210+
FI->second.ClusterInfo.emplace_back(BBClusterInfo<ProfileBBID>{
189211
*std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
190212
}
191213
CurrentCluster++;
@@ -210,12 +232,13 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
210232
return createProfileParseError(Twine("invalid specifier: '") +
211233
Twine(Specifier) + "'");
212234
}
235+
llvm_unreachable("should not break from this switch statement");
213236
}
214237
return Error::success();
215238
}
216239

217240
Error BasicBlockSectionsProfileReader::ReadV0Profile() {
218-
auto FI = RawProgramProfile.end();
241+
auto FI = ProgramPathAndClusterInfo.end();
219242
// Current cluster ID corresponding to this function.
220243
unsigned CurrentCluster = 0;
221244
// Current position in the current cluster.
@@ -236,7 +259,7 @@ Error BasicBlockSectionsProfileReader::ReadV0Profile() {
236259
if (S.consume_front("!")) {
237260
// Skip the profile when we the profile iterator (FI) refers to the
238261
// past-the-end element.
239-
if (FI == RawProgramProfile.end())
262+
if (FI == ProgramPathAndClusterInfo.end())
240263
continue;
241264
SmallVector<StringRef, 4> BBIDs;
242265
S.split(BBIDs, ' ');
@@ -254,8 +277,8 @@ Error BasicBlockSectionsProfileReader::ReadV0Profile() {
254277
return createProfileParseError(
255278
"entry BB (0) does not begin a cluster");
256279

257-
FI->second.RawBBProfiles.emplace_back(
258-
BBProfile<ProfileBBID>({{static_cast<unsigned>(BBID), 0},
280+
FI->second.ClusterInfo.emplace_back(
281+
BBClusterInfo<ProfileBBID>({{static_cast<unsigned>(BBID), 0},
259282
CurrentCluster,
260283
CurrentPosition++}));
261284
}
@@ -291,15 +314,15 @@ Error BasicBlockSectionsProfileReader::ReadV0Profile() {
291314
if (!FunctionFound) {
292315
// Skip the following profile by setting the profile iterator (FI) to
293316
// the past-the-end element.
294-
FI = RawProgramProfile.end();
317+
FI = ProgramPathAndClusterInfo.end();
295318
continue;
296319
}
297320
for (size_t i = 1; i < Aliases.size(); ++i)
298321
FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
299322

300323
// Prepare for parsing clusters of this function name.
301324
// Start a new cluster map for this function name.
302-
auto R = RawProgramProfile.try_emplace(Aliases.front());
325+
auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
303326
// Report error when multiple profiles have been specified for the same
304327
// function.
305328
if (!R.second)

0 commit comments

Comments
 (0)