Skip to content

[BOLT] Refactor SplitFunctions for function reuse. NFC. #73078

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

Closed
Closed
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
7 changes: 7 additions & 0 deletions bolt/include/bolt/Core/BinaryFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,13 @@ class BinaryFunction {
/// otherwise processed.
bool isPseudo() const { return IsPseudo; }

/// Return true if every block in the function has a zero execution count.
bool allBlocksCold() const {
return llvm::all_of(blocks(), [](const BinaryBasicBlock &BB) {
return BB.getExecutionCount() == 0;
});
}

/// Return true if the function contains explicit or implicit indirect branch
/// to its split fragments, e.g., split jump table, landing pad in split
/// fragment.
Expand Down
32 changes: 16 additions & 16 deletions bolt/include/bolt/Passes/SplitFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ class SplitFunctions : public BinaryFunctionPass {
/// Split function body into fragments.
void splitFunction(BinaryFunction &Function, SplitStrategy &Strategy);

std::atomic<uint64_t> SplitBytesHot{0ull};
std::atomic<uint64_t> SplitBytesCold{0ull};

public:
explicit SplitFunctions(const cl::opt<bool> &PrintPass)
: BinaryFunctionPass(PrintPass) {}

bool shouldOptimize(const BinaryFunction &BF) const override;

const char *getName() const override { return "split-functions"; }

void runOnFunctions(BinaryContext &BC) override;

struct TrampolineKey {
FragmentNum SourceFN = FragmentNum::main();
const MCSymbol *Target = nullptr;
Expand Down Expand Up @@ -81,27 +94,14 @@ class SplitFunctions : public BinaryFunctionPass {
/// corresponding thrower block. The trampoline landing pad, when created,
/// will redirect the execution to the real landing pad in a different
/// fragment.
TrampolineSetType createEHTrampolines(BinaryFunction &Function) const;
static TrampolineSetType createEHTrampolines(BinaryFunction &Function);

/// Merge trampolines into \p Layout without trampolines. The merge will place
/// a trampoline immediately before its destination. Used to revert the effect
/// of trampolines after createEHTrampolines().
BasicBlockOrderType
static BasicBlockOrderType
mergeEHTrampolines(BinaryFunction &BF, BasicBlockOrderType &Layout,
const TrampolineSetType &Trampolines) const;

std::atomic<uint64_t> SplitBytesHot{0ull};
std::atomic<uint64_t> SplitBytesCold{0ull};

public:
explicit SplitFunctions(const cl::opt<bool> &PrintPass)
: BinaryFunctionPass(PrintPass) {}

bool shouldOptimize(const BinaryFunction &BF) const override;

const char *getName() const override { return "split-functions"; }

void runOnFunctions(BinaryContext &BC) override;
const TrampolineSetType &Trampolines);
};

} // namespace bolt
Expand Down
12 changes: 3 additions & 9 deletions bolt/lib/Passes/SplitFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,9 @@ bool hasFullProfile(const BinaryFunction &BF) {
});
}

bool allBlocksCold(const BinaryFunction &BF) {
return llvm::all_of(BF.blocks(), [](const BinaryBasicBlock &BB) {
return BB.getExecutionCount() == 0;
});
}

struct SplitProfile2 final : public SplitStrategy {
bool canSplit(const BinaryFunction &BF) override {
return BF.hasValidProfile() && hasFullProfile(BF) && !allBlocksCold(BF);
return BF.hasValidProfile() && hasFullProfile(BF) && !BF.allBlocksCold();
}

bool keepEmpty() override { return false; }
Expand Down Expand Up @@ -434,7 +428,7 @@ void SplitFunctions::splitFunction(BinaryFunction &BF, SplitStrategy &S) {
}

SplitFunctions::TrampolineSetType
SplitFunctions::createEHTrampolines(BinaryFunction &BF) const {
SplitFunctions::createEHTrampolines(BinaryFunction &BF) {
const auto &MIB = BF.getBinaryContext().MIB;

// Map real landing pads to the corresponding trampolines.
Expand Down Expand Up @@ -501,7 +495,7 @@ SplitFunctions::createEHTrampolines(BinaryFunction &BF) const {

SplitFunctions::BasicBlockOrderType SplitFunctions::mergeEHTrampolines(
BinaryFunction &BF, SplitFunctions::BasicBlockOrderType &Layout,
const SplitFunctions::TrampolineSetType &Trampolines) const {
const SplitFunctions::TrampolineSetType &Trampolines) {
DenseMap<const MCSymbol *, SmallVector<const MCSymbol *, 0>>
IncomingTrampolines;
for (const auto &Entry : Trampolines) {
Expand Down