Skip to content

Commit a7c64ca

Browse files
committed
[BasicBlockSections] Introduce the path cloning profile format to BasicBlockSectionsProfileReader.
Following up on prior RFC (https://lists.llvm.org/pipermail/llvm-dev/2020-September/145357.html) we can now improve above our highly-optimized basic-block-sections binary (e.g., 2% for clang) by applying path cloning. Cloning can improve performance by reducing taken branches. This patch prepares the profile format for applying cloning actions. The basic block cloning profile format extends the basic block sections profile in two ways. 1. Specifies the cloning paths with a 'p' specifier. For example, `p 1 4 5` specifies that blocks with BB ids 4 and 5 must be cloned along the edge 1 --> 4. 2. For each cloned block, it will appear in the cluster info as `<bb_id>.<clone_id>` where `clone_id` is the id associated with this clone. For example, the following profile specifies one cloned block (2) and determines its cluster position as well. ``` f foo p 1 2 c 0 1 2.1 3 2 5 ``` This patch keeps backward-compatibility (retains the behavior for old profile formats). This feature is only introduced for profile version >= 1.
1 parent 28245b4 commit a7c64ca

File tree

4 files changed

+190
-92
lines changed

4 files changed

+190
-92
lines changed

llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,53 @@
2828

2929
namespace llvm {
3030

31-
// The cluster information for a machine basic block.
32-
struct BBClusterInfo {
33-
// Unique ID for this basic block.
31+
// This structure represents a unique ID for every block specified in the
32+
// profile.
33+
struct ProfileBBID {
3434
unsigned BBID;
35+
unsigned CloneID;
36+
};
37+
38+
// Provides DenseMapInfo for ProfileBBID.
39+
template <> struct DenseMapInfo<ProfileBBID> {
40+
static inline ProfileBBID getEmptyKey() {
41+
unsigned EmptyKey = DenseMapInfo<unsigned>::getEmptyKey();
42+
return ProfileBBID{EmptyKey, EmptyKey};
43+
}
44+
static inline ProfileBBID getTombstoneKey() {
45+
unsigned TombstoneKey = DenseMapInfo<unsigned>::getTombstoneKey();
46+
return ProfileBBID{TombstoneKey, TombstoneKey};
47+
}
48+
static unsigned getHashValue(const ProfileBBID &Val) {
49+
std::pair<unsigned, unsigned> PairVal =
50+
std::make_pair(Val.BBID, Val.CloneID);
51+
return DenseMapInfo<std::pair<unsigned, unsigned>>::getHashValue(PairVal);
52+
}
53+
static bool isEqual(const ProfileBBID &LHS, const ProfileBBID &RHS) {
54+
return DenseMapInfo<unsigned>::isEqual(LHS.BBID, RHS.BBID) &&
55+
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
56+
}
57+
};
58+
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;
3564
// Cluster ID this basic block belongs to.
3665
unsigned ClusterID;
3766
// Position of basic block within the cluster.
3867
unsigned PositionInCluster;
3968
};
4069

41-
using ProgramBBClusterInfoMapTy = StringMap<SmallVector<BBClusterInfo>>;
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+
};
4278

4379
class BasicBlockSectionsProfileReader : public ImmutablePass {
4480
public:
@@ -70,8 +106,8 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
70106
// function. If the first element is true and the second element is empty, it
71107
// means unique basic block sections are desired for all basic blocks of the
72108
// function.
73-
std::pair<bool, SmallVector<BBClusterInfo>>
74-
getBBClusterInfoForFunction(StringRef FuncName) const;
109+
std::pair<bool, RawFunctionProfile>
110+
getRawProfileForFunction(StringRef FuncName) const;
75111

76112
// Initializes the FunctionNameToDIFilename map for the current module and
77113
// then reads the profile for matching functions.
@@ -91,6 +127,9 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
91127
inconvertibleErrorCode());
92128
}
93129

130+
// Parses a `ProfileBBID` from `S`.
131+
Expected<ProfileBBID> parseProfileBBID(StringRef S) const;
132+
94133
// Reads the basic block sections profile for functions in this module.
95134
Error ReadProfile();
96135

@@ -113,11 +152,11 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
113152

114153
// This encapsulates the BB cluster information for the whole program.
115154
//
116-
// For every function name, it contains the cluster information for (all or
117-
// some of) its basic blocks. The cluster information for every basic block
118-
// includes its cluster ID along with the position of the basic block in that
119-
// cluster.
120-
ProgramBBClusterInfoMapTy ProgramBBClusterInfo;
155+
// For every function name, it contains the cloning and cluster information
156+
// for (all or some of) its basic blocks. The cluster information for every
157+
// basic block includes its cluster ID along with the position of the basic
158+
// block in that cluster.
159+
StringMap<RawFunctionProfile> RawProgramProfile;
121160

122161
// Some functions have alias names. We use this map to find the main alias
123162
// name for which we have mapping in ProgramBBClusterInfo.

llvm/lib/CodeGen/BasicBlockSections.cpp

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -168,44 +168,19 @@ updateBranches(MachineFunction &MF,
168168
}
169169
}
170170

171-
// This function provides the BBCluster information associated with a function.
172-
// Returns true if a valid association exists and false otherwise.
173-
bool getBBClusterInfoForFunction(
174-
const MachineFunction &MF,
175-
BasicBlockSectionsProfileReader *BBSectionsProfileReader,
176-
DenseMap<unsigned, BBClusterInfo> &V) {
177-
178-
// Find the assoicated cluster information.
179-
std::pair<bool, SmallVector<BBClusterInfo, 4>> P =
180-
BBSectionsProfileReader->getBBClusterInfoForFunction(MF.getName());
181-
if (!P.first)
182-
return false;
183-
184-
if (P.second.empty()) {
185-
// This indicates that sections are desired for all basic blocks of this
186-
// function. We clear the BBClusterInfo vector to denote this.
187-
V.clear();
188-
return true;
189-
}
190-
191-
for (const BBClusterInfo &BBCI : P.second)
192-
V[BBCI.BBID] = BBCI;
193-
return true;
194-
}
195-
196171
// This function sorts basic blocks according to the cluster's information.
197172
// All explicitly specified clusters of basic blocks will be ordered
198173
// accordingly. All non-specified BBs go into a separate "Cold" section.
199174
// Additionally, if exception handling landing pads end up in more than one
200175
// clusters, they are moved into a single "Exception" section. Eventually,
201176
// clusters are ordered in increasing order of their IDs, with the "Exception"
202177
// and "Cold" succeeding all other clusters.
203-
// FuncBBClusterInfo represent the cluster information for basic blocks. It
178+
// BBProfilesByBBID represents the cluster information for basic blocks. It
204179
// maps from BBID of basic blocks to their cluster information. If this is
205180
// empty, it means unique sections for all basic blocks in the function.
206-
static void
207-
assignSections(MachineFunction &MF,
208-
const DenseMap<unsigned, BBClusterInfo> &FuncBBClusterInfo) {
181+
static void assignSections(
182+
MachineFunction &MF,
183+
const DenseMap<unsigned, BBProfile<unsigned>> &BBProfilesByBBID) {
209184
assert(MF.hasBBSections() && "BB Sections is not set for function.");
210185
// This variable stores the section ID of the cluster containing eh_pads (if
211186
// all eh_pads are one cluster). If more than one cluster contain eh_pads, we
@@ -216,17 +191,17 @@ assignSections(MachineFunction &MF,
216191
// With the 'all' option, every basic block is placed in a unique section.
217192
// With the 'list' option, every basic block is placed in a section
218193
// associated with its cluster, unless we want individual unique sections
219-
// for every basic block in this function (if FuncBBClusterInfo is empty).
194+
// for every basic block in this function (if BBProfilesByBBID is empty).
220195
if (MF.getTarget().getBBSectionsType() == llvm::BasicBlockSection::All ||
221-
FuncBBClusterInfo.empty()) {
196+
BBProfilesByBBID.empty()) {
222197
// If unique sections are desired for all basic blocks of the function, we
223198
// set every basic block's section ID equal to its original position in
224199
// the layout (which is equal to its number). This ensures that basic
225200
// blocks are ordered canonically.
226201
MBB.setSectionID(MBB.getNumber());
227202
} else {
228-
auto I = FuncBBClusterInfo.find(*MBB.getBBID());
229-
if (I != FuncBBClusterInfo.end()) {
203+
auto I = BBProfilesByBBID.find(*MBB.getBBID());
204+
if (I != BBProfilesByBBID.end()) {
230205
MBB.setSectionID(I->second.ClusterID);
231206
} else {
232207
// BB goes into the special cold section if it is not specified in the
@@ -333,16 +308,25 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
333308
return true;
334309
}
335310

336-
BBSectionsProfileReader = &getAnalysis<BasicBlockSectionsProfileReader>();
311+
DenseMap<unsigned, BBProfile<unsigned>> BBProfilesByBBID;
312+
if (BBSectionsType == BasicBlockSection::List) {
313+
auto [HasProfile, RawProfile] =
314+
getAnalysis<BasicBlockSectionsProfileReader>().getRawProfileForFunction(
315+
MF.getName());
316+
if (!HasProfile)
317+
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});
325+
}
326+
}
337327

338-
// Map from BBID of blocks to their cluster information.
339-
DenseMap<unsigned, BBClusterInfo> FuncBBClusterInfo;
340-
if (BBSectionsType == BasicBlockSection::List &&
341-
!getBBClusterInfoForFunction(MF, BBSectionsProfileReader,
342-
FuncBBClusterInfo))
343-
return true;
344328
MF.setBBSectionsType(BBSectionsType);
345-
assignSections(MF, FuncBBClusterInfo);
329+
assignSections(MF, BBProfilesByBBID);
346330

347331
// We make sure that the cluster including the entry basic block precedes all
348332
// other clusters.
@@ -376,8 +360,8 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
376360
// If the two basic block are in the same section, the order is decided by
377361
// their position within the section.
378362
if (XSectionID.Type == MBBSectionID::SectionType::Default)
379-
return FuncBBClusterInfo.lookup(*X.getBBID()).PositionInCluster <
380-
FuncBBClusterInfo.lookup(*Y.getBBID()).PositionInCluster;
363+
return BBProfilesByBBID.lookup(*X.getBBID()).PositionInCluster <
364+
BBProfilesByBBID.lookup(*Y.getBBID()).PositionInCluster;
381365
return X.getNumber() < Y.getNumber();
382366
};
383367

0 commit comments

Comments
 (0)