[llvm] [Analysis][NFC] Store CallbackVH in vector, not in map (PR #184323)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 3 03:15:41 PST 2026
https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/184323
This avoid non-trivial move operations whenever the map grows.
-0.09% perf improvement: https://llvm-compile-time-tracker.com/compare.php?from=7b6751916cf74692df9c331ecdc731c42addafdf&to=4448dbb3626ba122434057b0c7c96690e5bd97d7&stat=instructions:u
>From 35366ec3425fd78f2b6ed8b921d250e5f5d49e39 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Sun, 18 Jan 2026 12:15:50 +0000
Subject: [PATCH] [Analysis][NFC] Store CallbackVH in vector, not in map
This avoid non-trivial move operations whenever the map grows.
-0.09% perf improvement: https://llvm-compile-time-tracker.com/compare.php?from=7b6751916cf74692df9c331ecdc731c42addafdf&to=4448dbb3626ba122434057b0c7c96690e5bd97d7&stat=instructions:u
---
.../llvm/Analysis/BlockFrequencyInfoImpl.h | 60 ++++++++++---------
1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 3d0942aa2d9f3..b3c48ee02d01a 100644
--- a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -857,21 +857,10 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
const FunctionT *F = nullptr;
// All blocks in reverse postorder.
- std::vector<const BlockT *> RPOT;
- DenseMap<BlockKeyT, std::pair<BlockNode, BFICallbackVH>> Nodes;
+ std::vector<BFICallbackVH> RPOT;
+ DenseMap<const BlockT *, BlockNode> Nodes;
- using rpot_iterator = typename std::vector<const BlockT *>::const_iterator;
-
- rpot_iterator rpot_begin() const { return RPOT.begin(); }
- rpot_iterator rpot_end() const { return RPOT.end(); }
-
- size_t getIndex(const rpot_iterator &I) const { return I - rpot_begin(); }
-
- BlockNode getNode(const rpot_iterator &I) const {
- return BlockNode(getIndex(I));
- }
-
- BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB).first; }
+ BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); }
const BlockT *getBlock(const BlockNode &Node) const {
assert(Node.Index < RPOT.size());
@@ -1035,7 +1024,10 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
// We don't erase corresponding items from `Freqs`, `RPOT` and other to
// avoid invalidating indices. Doing so would have saved some memory, but
// it's not worth it.
- Nodes.erase(BB);
+ auto It = Nodes.find(BB);
+ assert(It != Nodes.end() && "cannot forget block that was never seen");
+ RPOT[It->second.Index] = {}; // Clear value handle.
+ Nodes.erase(It);
}
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
@@ -1079,15 +1071,24 @@ class BFICallbackVH<BasicBlock, BFIImplT> : public CallbackVH {
void deleted() override {
BFIImpl->forgetBlock(cast<BasicBlock>(getValPtr()));
}
+
+ operator const BasicBlock *() const {
+ Value *V = *static_cast<const CallbackVH *>(this);
+ return cast<BasicBlock>(V);
+ }
};
/// Dummy implementation since MachineBasicBlocks aren't Values, so ValueHandles
/// don't apply to them.
template <class BFIImplT>
class BFICallbackVH<MachineBasicBlock, BFIImplT> {
+ const MachineBasicBlock *MBB;
+
public:
BFICallbackVH() = default;
- BFICallbackVH(const MachineBasicBlock *, BFIImplT *) {}
+ BFICallbackVH(const MachineBasicBlock *MBB, BFIImplT *) : MBB(MBB) {}
+
+ operator const MachineBasicBlock *() const { return MBB; }
};
} // end namespace bfi_detail
@@ -1139,14 +1140,15 @@ void BlockFrequencyInfoImpl<BT>::setBlockFreq(const BlockT *BB,
BlockFrequency Freq) {
auto [It, Inserted] = Nodes.try_emplace(BB);
if (!Inserted)
- BlockFrequencyInfoImplBase::setBlockFreq(It->second.first, Freq);
+ BlockFrequencyInfoImplBase::setBlockFreq(It->second, Freq);
else {
// If BB is a newly added block after BFI is done, we need to create a new
// BlockNode for it assigned with a new index. The index can be determined
// by the size of Freqs.
BlockNode NewNode(Freqs.size());
- It->second = {NewNode, BFICallbackVH(BB, this)};
+ It->second = NewNode;
Freqs.emplace_back();
+ RPOT.emplace_back(BB, this);
BlockFrequencyInfoImplBase::setBlockFreq(NewNode, Freq);
}
}
@@ -1154,18 +1156,19 @@ void BlockFrequencyInfoImpl<BT>::setBlockFreq(const BlockT *BB,
template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() {
const BlockT *Entry = &F->front();
RPOT.reserve(F->size());
- std::copy(po_begin(Entry), po_end(Entry), std::back_inserter(RPOT));
+ for (const BlockT *BB : post_order(Entry))
+ RPOT.emplace_back(BB, this);
std::reverse(RPOT.begin(), RPOT.end());
assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() &&
"More nodes in function than Block Frequency Info supports");
LLVM_DEBUG(dbgs() << "reverse-post-order-traversal\n");
- for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
- BlockNode Node = getNode(I);
- LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node)
+ for (auto [Idx, Block] : enumerate(RPOT)) {
+ BlockNode Node = BlockNode(Idx);
+ LLVM_DEBUG(dbgs() << " - " << Idx << ": " << getBlockName(Node)
<< "\n");
- Nodes[*I] = {Node, BFICallbackVH(*I, this)};
+ Nodes[Block] = Node;
}
Working.reserve(RPOT.size());
@@ -1323,13 +1326,12 @@ bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() {
assert(!Working[0].isLoopHeader() && "entry block is a loop header");
Working[0].getMass() = BlockMass::getFull();
- for (rpot_iterator I = rpot_begin(), IE = rpot_end(); I != IE; ++I) {
+ for (size_t i = 0, n = RPOT.size(); i != n; ++i) {
// Check for nodes that have been packaged.
- BlockNode Node = getNode(I);
- if (Working[Node.Index].isPackaged())
+ if (Working[i].isPackaged())
continue;
- if (!propagateMassToSuccessors(nullptr, Node))
+ if (!propagateMassToSuccessors(nullptr, BlockNode(i)))
return false;
}
return true;
@@ -1720,13 +1722,13 @@ void BlockFrequencyInfoImpl<BT>::verifyMatch(
for (auto &Entry : Nodes) {
const BlockT *BB = Entry.first;
if (BB) {
- ValidNodes[BB] = Entry.second.first;
+ ValidNodes[BB] = Entry.second;
}
}
for (auto &Entry : Other.Nodes) {
const BlockT *BB = Entry.first;
if (BB) {
- OtherValidNodes[BB] = Entry.second.first;
+ OtherValidNodes[BB] = Entry.second;
}
}
unsigned NumValidNodes = ValidNodes.size();
More information about the llvm-commits
mailing list