Skip to content

Commit f70e39e

Browse files
authored
[BasicBlockSections] Apply path cloning with -basic-block-sections. (#68860)
28b9126 introduced the path cloning format in the basic-block-sections profile. This PR validates and applies path clonings. A path cloning is valid if all of these conditions hold: 1. All bb ids in the path are mapped to existing blocks. 2. Each two consecutive bb ids in the path have a successor relationship in the CFG. 3. The path does not include a block with indirect branches, except possibly as the last block. Applying a path cloning involves cloning all blocks in the path (except the first one) and setting up their branches. Once all clonings are applied, the cluster information is used to guide block layout in the modified function.
1 parent 3cd2a0b commit f70e39e

23 files changed

+736
-134
lines changed

llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ void sortBasicBlocksAndUpdateBranches(MachineFunction &MF,
2727

2828
void avoidZeroOffsetLandingPad(MachineFunction &MF);
2929

30+
/// This checks if the source of this function has drifted since this binary was
31+
/// profiled previously.
32+
/// For now, we are piggy backing on what PGO does to
33+
/// detect this with instrumented profiles. PGO emits an hash of the IR and
34+
/// checks if the hash has changed. Advanced basic block layout is usually done
35+
/// on top of PGO optimized binaries and hence this check works well in
36+
/// practice.
37+
bool hasInstrProfHashMismatch(MachineFunction &MF);
38+
3039
} // end namespace llvm
3140

3241
#endif // LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H

llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,22 @@
1919
#include "llvm/ADT/SmallVector.h"
2020
#include "llvm/ADT/StringMap.h"
2121
#include "llvm/ADT/StringRef.h"
22+
#include "llvm/CodeGen/MachineBasicBlock.h"
2223
#include "llvm/IR/Module.h"
2324
#include "llvm/InitializePasses.h"
2425
#include "llvm/Pass.h"
2526
#include "llvm/Support/Error.h"
2627
#include "llvm/Support/LineIterator.h"
2728
#include "llvm/Support/MemoryBuffer.h"
29+
using namespace llvm;
2830

2931
namespace llvm {
3032

31-
// This structure represents a unique ID for every block specified in the
32-
// input profile.
33-
struct ProfileBBID {
34-
// Basic block id associated with `MachineBasicBlock::BBID`.
35-
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`.
39-
unsigned CloneID;
40-
};
41-
4233
// 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 {
34+
// which is specifed by a unique ID (`MachineBasicBlock::BBID`).
35+
struct BBClusterInfo {
4736
// Basic block ID.
48-
BBIDType BasicBlockID;
37+
UniqueBBID BBID;
4938
// Cluster ID this basic block belongs to.
5039
unsigned ClusterID;
5140
// Position of basic block within the cluster.
@@ -54,31 +43,31 @@ template <typename BBIDType> struct BBClusterInfo {
5443

5544
// This represents the raw input profile for one function.
5645
struct FunctionPathAndClusterInfo {
57-
// BB Cluster information specified by `ProfileBBID`s (before cloning).
58-
SmallVector<BBClusterInfo<ProfileBBID>> ClusterInfo;
46+
// BB Cluster information specified by `UniqueBBID`s.
47+
SmallVector<BBClusterInfo> ClusterInfo;
5948
// Paths to clone. A path a -> b -> c -> d implies cloning b, c, and d along
6049
// 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.
50+
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
6251
SmallVector<SmallVector<unsigned>> ClonePaths;
6352
};
6453

65-
// Provides DenseMapInfo for ProfileBBID.
66-
template <> struct DenseMapInfo<ProfileBBID> {
67-
static inline ProfileBBID getEmptyKey() {
54+
// Provides DenseMapInfo for UniqueBBID.
55+
template <> struct DenseMapInfo<UniqueBBID> {
56+
static inline UniqueBBID getEmptyKey() {
6857
unsigned EmptyKey = DenseMapInfo<unsigned>::getEmptyKey();
69-
return ProfileBBID{EmptyKey, EmptyKey};
58+
return UniqueBBID{EmptyKey, EmptyKey};
7059
}
71-
static inline ProfileBBID getTombstoneKey() {
60+
static inline UniqueBBID getTombstoneKey() {
7261
unsigned TombstoneKey = DenseMapInfo<unsigned>::getTombstoneKey();
73-
return ProfileBBID{TombstoneKey, TombstoneKey};
62+
return UniqueBBID{TombstoneKey, TombstoneKey};
7463
}
75-
static unsigned getHashValue(const ProfileBBID &Val) {
64+
static unsigned getHashValue(const UniqueBBID &Val) {
7665
std::pair<unsigned, unsigned> PairVal =
77-
std::make_pair(Val.BBID, Val.CloneID);
66+
std::make_pair(Val.BaseID, Val.CloneID);
7867
return DenseMapInfo<std::pair<unsigned, unsigned>>::getHashValue(PairVal);
7968
}
80-
static bool isEqual(const ProfileBBID &LHS, const ProfileBBID &RHS) {
81-
return DenseMapInfo<unsigned>::isEqual(LHS.BBID, RHS.BBID) &&
69+
static bool isEqual(const UniqueBBID &LHS, const UniqueBBID &RHS) {
70+
return DenseMapInfo<unsigned>::isEqual(LHS.BaseID, RHS.BaseID) &&
8271
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
8372
}
8473
};
@@ -113,8 +102,12 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
113102
// function. If the first element is true and the second element is empty, it
114103
// means unique basic block sections are desired for all basic blocks of the
115104
// function.
116-
std::pair<bool, FunctionPathAndClusterInfo>
117-
getPathAndClusterInfoForFunction(StringRef FuncName) const;
105+
std::pair<bool, SmallVector<BBClusterInfo>>
106+
getClusterInfoForFunction(StringRef FuncName) const;
107+
108+
// Returns the path clonings for the given function.
109+
SmallVector<SmallVector<unsigned>>
110+
getClonePathsForFunction(StringRef FuncName) const;
118111

119112
// Initializes the FunctionNameToDIFilename map for the current module and
120113
// then reads the profile for the matching functions.
@@ -134,11 +127,11 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
134127
inconvertibleErrorCode());
135128
}
136129

137-
// Parses a `ProfileBBID` from `S`. `S` must be in the form "<bbid>"
130+
// Parses a `UniqueBBID` from `S`. `S` must be in the form "<bbid>"
138131
// (representing an original block) or "<bbid>.<cloneid>" (representing a
139132
// cloned block) where bbid is a non-negative integer and cloneid is a
140133
// positive integer.
141-
Expected<ProfileBBID> parseProfileBBID(StringRef S) const;
134+
Expected<UniqueBBID> parseUniqueBBID(StringRef S) const;
142135

143136
// Reads the basic block sections profile for functions in this module.
144137
Error ReadProfile();

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ struct MBBSectionID {
7474
MBBSectionID(SectionType T) : Type(T), Number(0) {}
7575
};
7676

77+
// This structure represents the information for a basic block.
78+
struct UniqueBBID {
79+
unsigned BaseID;
80+
// sections profile).
81+
unsigned CloneID;
82+
};
83+
7784
template <> struct ilist_traits<MachineInstr> {
7885
private:
7986
friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
@@ -180,7 +187,7 @@ class MachineBasicBlock
180187

181188
/// Fixed unique ID assigned to this basic block upon creation. Used with
182189
/// basic block sections and basic block labels.
183-
std::optional<unsigned> BBID;
190+
std::optional<UniqueBBID> BBID;
184191

185192
/// With basic block sections, this stores the Section ID of the basic block.
186193
MBBSectionID SectionID{0};
@@ -633,7 +640,7 @@ class MachineBasicBlock
633640

634641
void setIsEndSection(bool V = true) { IsEndSection = V; }
635642

636-
std::optional<unsigned> getBBID() const { return BBID; }
643+
std::optional<UniqueBBID> getBBID() const { return BBID; }
637644

638645
/// Returns the section ID of this basic block.
639646
MBBSectionID getSectionID() const { return SectionID; }
@@ -645,7 +652,7 @@ class MachineBasicBlock
645652
}
646653

647654
/// Sets the fixed BBID of this basic block.
648-
void setBBID(unsigned V) {
655+
void setBBID(const UniqueBBID &V) {
649656
assert(!BBID.has_value() && "Cannot change BBID.");
650657
BBID = V;
651658
}
@@ -753,7 +760,7 @@ class MachineBasicBlock
753760
///
754761
/// This is useful when doing a partial clone of successors. Afterward, the
755762
/// probabilities may need to be normalized.
756-
void copySuccessor(MachineBasicBlock *Orig, succ_iterator I);
763+
void copySuccessor(const MachineBasicBlock *Orig, succ_iterator I);
757764

758765
/// Split the old successor into old plus new and updates the probability
759766
/// info.

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,8 +1013,11 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
10131013
void deleteMachineInstr(MachineInstr *MI);
10141014

10151015
/// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this
1016-
/// instead of `new MachineBasicBlock'.
1017-
MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = nullptr);
1016+
/// instead of `new MachineBasicBlock'. Sets `MachineBasicBlock::BBID` if
1017+
/// basic-block-sections is enabled for the function.
1018+
MachineBasicBlock *
1019+
CreateMachineBasicBlock(const BasicBlock *BB = nullptr,
1020+
std::optional<UniqueBBID> BBID = std::nullopt);
10181021

10191022
/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
10201023
void deleteMachineBasicBlock(MachineBasicBlock *MBB);

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ namespace llvm {
6565
/// basic blocks and is enabled with -fbasic-block-sections.
6666
MachineFunctionPass *createBasicBlockSectionsPass();
6767

68+
MachineFunctionPass *createBasicBlockPathCloningPass();
69+
6870
/// createMachineFunctionSplitterPass - This pass splits machine functions
6971
/// using profile information.
7072
MachineFunctionPass *createMachineFunctionSplitterPass();

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void initializeAssignmentTrackingAnalysisPass(PassRegistry &);
5555
void initializeAssumeBuilderPassLegacyPassPass(PassRegistry &);
5656
void initializeAssumptionCacheTrackerPass(PassRegistry&);
5757
void initializeAtomicExpandPass(PassRegistry&);
58+
void initializeBasicBlockPathCloningPass(PassRegistry &);
5859
void initializeBasicBlockSectionsProfileReaderPass(PassRegistry &);
5960
void initializeBasicBlockSectionsPass(PassRegistry &);
6061
void initializeBarrierNoopPass(PassRegistry&);

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,11 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
13721372
if (BBAddrMapVersion > 1) {
13731373
OutStreamer->AddComment("BB id");
13741374
// Emit the BB ID for this basic block.
1375-
OutStreamer->emitULEB128IntValue(*MBB.getBBID());
1375+
// We only emit BaseID since CloneID is unset for
1376+
// basic-block-sections=labels.
1377+
// TODO: Emit the full BBID when labels and sections can be mixed
1378+
// together.
1379+
OutStreamer->emitULEB128IntValue(MBB.getBBID()->BaseID);
13761380
}
13771381
// Emit the basic block offset relative to the end of the previous block.
13781382
// This is zero unless the block is padded due to alignment.
@@ -1932,30 +1936,33 @@ void AsmPrinter::emitFunctionBody() {
19321936
// MBB profile information has been set
19331937
if (MBBProfileDumpFileOutput && !MF->empty() &&
19341938
MF->getFunction().getEntryCount()) {
1935-
if (!MF->hasBBLabels())
1939+
if (!MF->hasBBLabels()) {
19361940
MF->getContext().reportError(
19371941
SMLoc(),
19381942
"Unable to find BB labels for MBB profile dump. -mbb-profile-dump "
19391943
"must be called with -basic-block-sections=labels");
1940-
MachineBlockFrequencyInfo &MBFI =
1941-
getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
1942-
// The entry count and the entry basic block frequency aren't the same. We
1943-
// want to capture "absolute" frequencies, i.e. the frequency with which a
1944-
// MBB is executed when the program is executed. From there, we can derive
1945-
// Function-relative frequencies (divide by the value for the first MBB).
1946-
// We also have the information about frequency with which functions
1947-
// were called. This helps, for example, in a type of integration tests
1948-
// where we want to cross-validate the compiler's profile with a real
1949-
// profile.
1950-
// Using double precision because uint64 values used to encode mbb
1951-
// "frequencies" may be quite large.
1952-
const double EntryCount =
1953-
static_cast<double>(MF->getFunction().getEntryCount()->getCount());
1954-
for (const auto &MBB : *MF) {
1955-
const double MBBRelFreq = MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
1956-
const double AbsMBBFreq = MBBRelFreq * EntryCount;
1957-
*MBBProfileDumpFileOutput.get()
1958-
<< MF->getName() << "," << MBB.getBBID() << "," << AbsMBBFreq << "\n";
1944+
} else {
1945+
MachineBlockFrequencyInfo &MBFI =
1946+
getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
1947+
// The entry count and the entry basic block frequency aren't the same. We
1948+
// want to capture "absolute" frequencies, i.e. the frequency with which a
1949+
// MBB is executed when the program is executed. From there, we can derive
1950+
// Function-relative frequencies (divide by the value for the first MBB).
1951+
// We also have the information about frequency with which functions
1952+
// were called. This helps, for example, in a type of integration tests
1953+
// where we want to cross-validate the compiler's profile with a real
1954+
// profile.
1955+
// Using double precision because uint64 values used to encode mbb
1956+
// "frequencies" may be quite large.
1957+
const double EntryCount =
1958+
static_cast<double>(MF->getFunction().getEntryCount()->getCount());
1959+
for (const auto &MBB : *MF) {
1960+
const double MBBRelFreq = MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
1961+
const double AbsMBBFreq = MBBRelFreq * EntryCount;
1962+
*MBBProfileDumpFileOutput.get()
1963+
<< MF->getName() << "," << MBB.getBBID()->BaseID << ","
1964+
<< AbsMBBFreq << "\n";
1965+
}
19591966
}
19601967
}
19611968
}

0 commit comments

Comments
 (0)