Skip to content

Commit 480d48e

Browse files
[BOLT] Optimize basic block loops to avoid n^2 loop
This improves BOLT runtime when optimizing rustc_driver.so from 15 minutes to 7 minutes (49 minutes to 37 minutes of userspace time).
1 parent 7c5b535 commit 480d48e

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3591,6 +3591,18 @@ void BinaryFunction::fixBranches() {
35913591
auto &MIB = BC.MIB;
35923592
MCContext *Ctx = BC.Ctx.get();
35933593

3594+
// Caches `FunctionLayout::nextBasicBlock(IgnoreSplits = false)`.
3595+
// nextBasicBlock uses linear search to find the next block, so the loop
3596+
// below becomes O(n^2). This avoids that.
3597+
DenseMap<BinaryBasicBlock *, BinaryBasicBlock *> nextBasicBlock(
3598+
Layout.block_size());
3599+
for (size_t i = 0; i + 1 < Layout.block_size(); i++) {
3600+
auto current = Layout.block_begin() + i;
3601+
auto next = Layout.block_begin() + i + 1;
3602+
if (next != Layout.getFragment((*current)->getFragmentNum()).end())
3603+
nextBasicBlock.insert(std::pair(*current, *next));
3604+
}
3605+
35943606
for (BinaryBasicBlock *BB : BasicBlocks) {
35953607
const MCSymbol *TBB = nullptr;
35963608
const MCSymbol *FBB = nullptr;
@@ -3605,7 +3617,7 @@ void BinaryFunction::fixBranches() {
36053617

36063618
// Basic block that follows the current one in the final layout.
36073619
const BinaryBasicBlock *const NextBB =
3608-
Layout.getBasicBlockAfter(BB, /*IgnoreSplits=*/false);
3620+
nextBasicBlock.lookup_or(BB, nullptr);
36093621

36103622
if (BB->succ_size() == 1) {
36113623
// __builtin_unreachable() could create a conditional branch that

0 commit comments

Comments
 (0)