Skip to content
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

[BasicBlockSections] Apply path cloning with -basic-block-sections. #68860

Merged
merged 14 commits into from
Oct 28, 2023
Merged
9 changes: 9 additions & 0 deletions llvm/include/llvm/CodeGen/BasicBlockSectionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ void sortBasicBlocksAndUpdateBranches(MachineFunction &MF,

void avoidZeroOffsetLandingPad(MachineFunction &MF);

/// This checks if the source of this function has drifted since this binary was
/// profiled previously.
/// For now, we are piggy backing on what PGO does to
/// detect this with instrumented profiles. PGO emits an hash of the IR and
/// checks if the hash has changed. Advanced basic block layout is usually done
/// on top of PGO optimized binaries and hence this check works well in
/// practice.
bool hasInstrProfHashMismatch(MachineFunction &MF);

} // end namespace llvm

#endif // LLVM_CODEGEN_BASICBLOCKSECTIONUTILS_H
59 changes: 26 additions & 33 deletions llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,22 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace llvm;

namespace llvm {

// 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 {
// which is specifed by a unique ID (`MachineBasicBlock::BBID`).
struct BBClusterInfo {
// Basic block ID.
BBIDType BasicBlockID;
UniqueBBID BBID;
// Cluster ID this basic block belongs to.
unsigned ClusterID;
// Position of basic block within the cluster.
Expand All @@ -54,31 +43,31 @@ template <typename BBIDType> struct 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;
// BB Cluster information specified by `UniqueBBID`s.
SmallVector<BBClusterInfo> 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.
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
};

// Provides DenseMapInfo for ProfileBBID.
template <> struct DenseMapInfo<ProfileBBID> {
static inline ProfileBBID getEmptyKey() {
// Provides DenseMapInfo for UniqueBBID.
template <> struct DenseMapInfo<UniqueBBID> {
static inline UniqueBBID getEmptyKey() {
unsigned EmptyKey = DenseMapInfo<unsigned>::getEmptyKey();
return ProfileBBID{EmptyKey, EmptyKey};
return UniqueBBID{EmptyKey, EmptyKey};
}
static inline ProfileBBID getTombstoneKey() {
static inline UniqueBBID getTombstoneKey() {
unsigned TombstoneKey = DenseMapInfo<unsigned>::getTombstoneKey();
return ProfileBBID{TombstoneKey, TombstoneKey};
return UniqueBBID{TombstoneKey, TombstoneKey};
}
static unsigned getHashValue(const ProfileBBID &Val) {
static unsigned getHashValue(const UniqueBBID &Val) {
std::pair<unsigned, unsigned> PairVal =
std::make_pair(Val.BBID, Val.CloneID);
std::make_pair(Val.BaseID, 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) &&
static bool isEqual(const UniqueBBID &LHS, const UniqueBBID &RHS) {
return DenseMapInfo<unsigned>::isEqual(LHS.BaseID, RHS.BaseID) &&
DenseMapInfo<unsigned>::isEqual(LHS.CloneID, RHS.CloneID);
}
};
Expand Down Expand Up @@ -113,8 +102,12 @@ 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, FunctionPathAndClusterInfo>
getPathAndClusterInfoForFunction(StringRef FuncName) const;
std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const;

// Returns the path clonings for the given function.
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;

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

// Parses a `ProfileBBID` from `S`. `S` must be in the form "<bbid>"
// Parses a `UniqueBBID` 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;
Expected<UniqueBBID> parseUniqueBBID(StringRef S) const;

// Reads the basic block sections profile for functions in this module.
Error ReadProfile();
Expand Down
15 changes: 11 additions & 4 deletions llvm/include/llvm/CodeGen/MachineBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ struct MBBSectionID {
MBBSectionID(SectionType T) : Type(T), Number(0) {}
};

// This structure represents the information for a basic block.
struct UniqueBBID {
unsigned BaseID;
// sections profile).
unsigned CloneID;
};

template <> struct ilist_traits<MachineInstr> {
private:
friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
Expand Down Expand Up @@ -180,7 +187,7 @@ class MachineBasicBlock

/// Fixed unique ID assigned to this basic block upon creation. Used with
/// basic block sections and basic block labels.
std::optional<unsigned> BBID;
std::optional<UniqueBBID> BBID;

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

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

std::optional<unsigned> getBBID() const { return BBID; }
std::optional<UniqueBBID> getBBID() const { return BBID; }

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

/// Sets the fixed BBID of this basic block.
void setBBID(unsigned V) {
void setBBID(const UniqueBBID &V) {
assert(!BBID.has_value() && "Cannot change BBID.");
BBID = V;
}
Expand Down Expand Up @@ -753,7 +760,7 @@ class MachineBasicBlock
///
/// This is useful when doing a partial clone of successors. Afterward, the
/// probabilities may need to be normalized.
void copySuccessor(MachineBasicBlock *Orig, succ_iterator I);
void copySuccessor(const MachineBasicBlock *Orig, succ_iterator I);

/// Split the old successor into old plus new and updates the probability
/// info.
Expand Down
7 changes: 5 additions & 2 deletions llvm/include/llvm/CodeGen/MachineFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,11 @@ class LLVM_EXTERNAL_VISIBILITY MachineFunction {
void deleteMachineInstr(MachineInstr *MI);

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

/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
void deleteMachineBasicBlock(MachineBasicBlock *MBB);
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ namespace llvm {
/// basic blocks and is enabled with -fbasic-block-sections.
MachineFunctionPass *createBasicBlockSectionsPass();

MachineFunctionPass *createBasicBlockPathCloningPass();

/// createMachineFunctionSplitterPass - This pass splits machine functions
/// using profile information.
MachineFunctionPass *createMachineFunctionSplitterPass();
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/InitializePasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ void initializeAssignmentTrackingAnalysisPass(PassRegistry &);
void initializeAssumeBuilderPassLegacyPassPass(PassRegistry &);
void initializeAssumptionCacheTrackerPass(PassRegistry&);
void initializeAtomicExpandPass(PassRegistry&);
void initializeBasicBlockPathCloningPass(PassRegistry &);
void initializeBasicBlockSectionsProfileReaderPass(PassRegistry &);
void initializeBasicBlockSectionsPass(PassRegistry &);
void initializeBarrierNoopPass(PassRegistry&);
Expand Down
49 changes: 28 additions & 21 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,11 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
if (BBAddrMapVersion > 1) {
OutStreamer->AddComment("BB id");
// Emit the BB ID for this basic block.
OutStreamer->emitULEB128IntValue(*MBB.getBBID());
// We only emit BaseID since CloneID is unset for
// basic-block-sections=labels.
// TODO: Emit the full BBID when labels and sections can be mixed
// together.
OutStreamer->emitULEB128IntValue(MBB.getBBID()->BaseID);
}
// Emit the basic block offset relative to the end of the previous block.
// This is zero unless the block is padded due to alignment.
Expand Down Expand Up @@ -1932,30 +1936,33 @@ void AsmPrinter::emitFunctionBody() {
// MBB profile information has been set
if (MBBProfileDumpFileOutput && !MF->empty() &&
MF->getFunction().getEntryCount()) {
if (!MF->hasBBLabels())
if (!MF->hasBBLabels()) {
MF->getContext().reportError(
SMLoc(),
"Unable to find BB labels for MBB profile dump. -mbb-profile-dump "
"must be called with -basic-block-sections=labels");
MachineBlockFrequencyInfo &MBFI =
getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
// The entry count and the entry basic block frequency aren't the same. We
// want to capture "absolute" frequencies, i.e. the frequency with which a
// MBB is executed when the program is executed. From there, we can derive
// Function-relative frequencies (divide by the value for the first MBB).
// We also have the information about frequency with which functions
// were called. This helps, for example, in a type of integration tests
// where we want to cross-validate the compiler's profile with a real
// profile.
// Using double precision because uint64 values used to encode mbb
// "frequencies" may be quite large.
const double EntryCount =
static_cast<double>(MF->getFunction().getEntryCount()->getCount());
for (const auto &MBB : *MF) {
const double MBBRelFreq = MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
const double AbsMBBFreq = MBBRelFreq * EntryCount;
*MBBProfileDumpFileOutput.get()
<< MF->getName() << "," << MBB.getBBID() << "," << AbsMBBFreq << "\n";
} else {
MachineBlockFrequencyInfo &MBFI =
getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI();
// The entry count and the entry basic block frequency aren't the same. We
// want to capture "absolute" frequencies, i.e. the frequency with which a
// MBB is executed when the program is executed. From there, we can derive
// Function-relative frequencies (divide by the value for the first MBB).
// We also have the information about frequency with which functions
// were called. This helps, for example, in a type of integration tests
// where we want to cross-validate the compiler's profile with a real
// profile.
// Using double precision because uint64 values used to encode mbb
// "frequencies" may be quite large.
const double EntryCount =
static_cast<double>(MF->getFunction().getEntryCount()->getCount());
for (const auto &MBB : *MF) {
const double MBBRelFreq = MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
const double AbsMBBFreq = MBBRelFreq * EntryCount;
*MBBProfileDumpFileOutput.get()
<< MF->getName() << "," << MBB.getBBID()->BaseID << ","
<< AbsMBBFreq << "\n";
}
}
}
}
Expand Down
Loading
Loading