Skip to content

[BasicBlockSections] Introduce the path cloning profile format to BasicBlockSectionsProfileReader. #67214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 63 additions & 14 deletions llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,60 @@

namespace llvm {

// The cluster information for a machine basic block.
struct BBClusterInfo {
// Unique ID for this basic block.
// This structure represents a unique ID for every block specified in the
// input profile.
struct ProfileBBID {
// Basic block id associated with `MachineBasicBlock::BBID`.
unsigned BBID;
// The clone id associated with the block. This is zero for the original
// block. For the cloned ones, it is equal to 1 + index of the associated
// path in `FunctionPathAndClusterInfo::ClonePaths`.
unsigned CloneID;
};

// This struct represents the cluster information for a machine basic block,
// which is specifed by a unique ID. This templated struct is used for both the
// raw input profile (as `BBClusterInfo<ProfileBBID>`) and the processed profile
// after applying the clonings (as `BBClusterInfo<unsigned>`).
template <typename BBIDType> struct BBClusterInfo {
// Basic block ID.
BBIDType BasicBlockID;
// Cluster ID this basic block belongs to.
unsigned ClusterID;
// Position of basic block within the cluster.
unsigned PositionInCluster;
};

using ProgramBBClusterInfoMapTy = StringMap<SmallVector<BBClusterInfo>>;
// This represents the raw input profile for one function.
struct FunctionPathAndClusterInfo {
// BB Cluster information specified by `ProfileBBID`s (before cloning).
SmallVector<BBClusterInfo<ProfileBBID>> ClusterInfo;
// Paths to clone. A path a -> b -> c -> d implies cloning b, c, and d along
// the edge a -> b (a is not cloned). The index of the path in this vector
// determines the `ProfileBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
};

// Provides DenseMapInfo for ProfileBBID.
template <> struct DenseMapInfo<ProfileBBID> {
static inline ProfileBBID getEmptyKey() {
unsigned EmptyKey = DenseMapInfo<unsigned>::getEmptyKey();
return ProfileBBID{EmptyKey, EmptyKey};
}
static inline ProfileBBID getTombstoneKey() {
unsigned TombstoneKey = DenseMapInfo<unsigned>::getTombstoneKey();
return ProfileBBID{TombstoneKey, TombstoneKey};
}
static unsigned getHashValue(const ProfileBBID &Val) {
std::pair<unsigned, unsigned> PairVal =
std::make_pair(Val.BBID, Val.CloneID);
return DenseMapInfo<std::pair<unsigned, unsigned>>::getHashValue(PairVal);
}
static bool isEqual(const ProfileBBID &LHS, const ProfileBBID &RHS) {
return DenseMapInfo<unsigned>::isEqual(LHS.BBID, RHS.BBID) &&
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
}
};

class BasicBlockSectionsProfileReader : public ImmutablePass {
public:
Expand Down Expand Up @@ -70,11 +113,11 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
// function. If the first element is true and the second element is empty, it
// means unique basic block sections are desired for all basic blocks of the
// function.
std::pair<bool, SmallVector<BBClusterInfo>>
getBBClusterInfoForFunction(StringRef FuncName) const;
std::pair<bool, FunctionPathAndClusterInfo>
getPathAndClusterInfoForFunction(StringRef FuncName) const;

// Initializes the FunctionNameToDIFilename map for the current module and
// then reads the profile for matching functions.
// then reads the profile for the matching functions.
bool doInitialization(Module &M) override;

private:
Expand All @@ -91,6 +134,12 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
inconvertibleErrorCode());
}

// Parses a `ProfileBBID` from `S`. `S` must 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.
Expected<ProfileBBID> parseProfileBBID(StringRef S) const;

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

Expand All @@ -111,16 +160,16 @@ class BasicBlockSectionsProfileReader : public ImmutablePass {
// empty string if no debug info is available.
StringMap<SmallString<128>> FunctionNameToDIFilename;

// This encapsulates the BB cluster information for the whole program.
// This contains the BB cluster information for the whole program.
//
// For every function name, it contains the cluster information for (all or
// some of) its basic blocks. The cluster information for every basic block
// includes its cluster ID along with the position of the basic block in that
// cluster.
ProgramBBClusterInfoMapTy ProgramBBClusterInfo;
// For every function name, it contains the cloning and cluster information
// for (all or some of) its basic blocks. The cluster information for every
// basic block includes its cluster ID along with the position of the basic
// block in that cluster.
StringMap<FunctionPathAndClusterInfo> ProgramPathAndClusterInfo;

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

Expand Down
73 changes: 30 additions & 43 deletions llvm/lib/CodeGen/BasicBlockSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,44 +168,19 @@ updateBranches(MachineFunction &MF,
}
}

// This function provides the BBCluster information associated with a function.
// Returns true if a valid association exists and false otherwise.
bool getBBClusterInfoForFunction(
const MachineFunction &MF,
BasicBlockSectionsProfileReader *BBSectionsProfileReader,
DenseMap<unsigned, BBClusterInfo> &V) {

// Find the assoicated cluster information.
std::pair<bool, SmallVector<BBClusterInfo, 4>> P =
BBSectionsProfileReader->getBBClusterInfoForFunction(MF.getName());
if (!P.first)
return false;

if (P.second.empty()) {
// This indicates that sections are desired for all basic blocks of this
// function. We clear the BBClusterInfo vector to denote this.
V.clear();
return true;
}

for (const BBClusterInfo &BBCI : P.second)
V[BBCI.BBID] = BBCI;
return true;
}

// This function sorts basic blocks according to the cluster's information.
// All explicitly specified clusters of basic blocks will be ordered
// accordingly. All non-specified BBs go into a separate "Cold" section.
// Additionally, if exception handling landing pads end up in more than one
// clusters, they are moved into a single "Exception" section. Eventually,
// clusters are ordered in increasing order of their IDs, with the "Exception"
// and "Cold" succeeding all other clusters.
// FuncBBClusterInfo represent the cluster information for basic blocks. It
// ClusterInfoByBBID represents the cluster information for basic blocks. It
// maps from BBID of basic blocks to their cluster information. If this is
// empty, it means unique sections for all basic blocks in the function.
static void
assignSections(MachineFunction &MF,
const DenseMap<unsigned, BBClusterInfo> &FuncBBClusterInfo) {
static void assignSections(
MachineFunction &MF,
const DenseMap<unsigned, BBClusterInfo<unsigned>> &ClusterInfoByBBID) {
assert(MF.hasBBSections() && "BB Sections is not set for function.");
// This variable stores the section ID of the cluster containing eh_pads (if
// all eh_pads are one cluster). If more than one cluster contain eh_pads, we
Expand All @@ -216,17 +191,17 @@ assignSections(MachineFunction &MF,
// With the 'all' option, every basic block is placed in a unique section.
// With the 'list' option, every basic block is placed in a section
// associated with its cluster, unless we want individual unique sections
// for every basic block in this function (if FuncBBClusterInfo is empty).
// for every basic block in this function (if ClusterInfoByBBID is empty).
if (MF.getTarget().getBBSectionsType() == llvm::BasicBlockSection::All ||
FuncBBClusterInfo.empty()) {
ClusterInfoByBBID.empty()) {
// If unique sections are desired for all basic blocks of the function, we
// set every basic block's section ID equal to its original position in
// the layout (which is equal to its number). This ensures that basic
// blocks are ordered canonically.
MBB.setSectionID(MBB.getNumber());
} else {
auto I = FuncBBClusterInfo.find(*MBB.getBBID());
if (I != FuncBBClusterInfo.end()) {
auto I = ClusterInfoByBBID.find(*MBB.getBBID());
if (I != ClusterInfoByBBID.end()) {
MBB.setSectionID(I->second.ClusterID);
} else {
// BB goes into the special cold section if it is not specified in the
Expand Down Expand Up @@ -333,16 +308,28 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
return true;
}

BBSectionsProfileReader = &getAnalysis<BasicBlockSectionsProfileReader>();
DenseMap<unsigned, BBClusterInfo<unsigned>> ClusterInfoByBBID;
if (BBSectionsType == BasicBlockSection::List) {
auto [HasProfile, PathAndClusterInfo] =
getAnalysis<BasicBlockSectionsProfileReader>()
.getPathAndClusterInfoForFunction(MF.getName());
if (!HasProfile)
return true;
for (const BBClusterInfo<ProfileBBID> &BBP :
PathAndClusterInfo.ClusterInfo) {
// TODO: Apply the path cloning profile.
assert(!BBP.BasicBlockID.CloneID && "Path cloning is not supported yet");
const auto [I, Inserted] = ClusterInfoByBBID.try_emplace(
BBP.BasicBlockID.BBID,
BBClusterInfo<unsigned>{BBP.BasicBlockID.BBID, BBP.ClusterID,
BBP.PositionInCluster});
(void)I;
assert(Inserted && "Duplicate BBID found in profile");
}
}

// Map from BBID of blocks to their cluster information.
DenseMap<unsigned, BBClusterInfo> FuncBBClusterInfo;
if (BBSectionsType == BasicBlockSection::List &&
!getBBClusterInfoForFunction(MF, BBSectionsProfileReader,
FuncBBClusterInfo))
return true;
MF.setBBSectionsType(BBSectionsType);
assignSections(MF, FuncBBClusterInfo);
assignSections(MF, ClusterInfoByBBID);

// We make sure that the cluster including the entry basic block precedes all
// other clusters.
Expand Down Expand Up @@ -376,8 +363,8 @@ bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
// If the two basic block are in the same section, the order is decided by
// their position within the section.
if (XSectionID.Type == MBBSectionID::SectionType::Default)
return FuncBBClusterInfo.lookup(*X.getBBID()).PositionInCluster <
FuncBBClusterInfo.lookup(*Y.getBBID()).PositionInCluster;
return ClusterInfoByBBID.lookup(*X.getBBID()).PositionInCluster <
ClusterInfoByBBID.lookup(*Y.getBBID()).PositionInCluster;
return X.getNumber() < Y.getNumber();
};

Expand Down
Loading