#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CommandLine.h"
template <class BlockT> struct TypeMap {};
template <> struct TypeMap<BasicBlock> {
using BlockT = BasicBlock;
+ using BlockKeyT = AssertingVH<const BasicBlock>;
using FunctionT = Function;
using BranchProbabilityInfoT = BranchProbabilityInfo;
using LoopT = Loop;
};
template <> struct TypeMap<MachineBasicBlock> {
using BlockT = MachineBasicBlock;
+ using BlockKeyT = const MachineBasicBlock *;
using FunctionT = MachineFunction;
using BranchProbabilityInfoT = MachineBranchProbabilityInfo;
using LoopT = MachineLoop;
friend struct bfi_detail::BlockEdgesAdder<BT>;
using BlockT = typename bfi_detail::TypeMap<BT>::BlockT;
+ using BlockKeyT = typename bfi_detail::TypeMap<BT>::BlockKeyT;
using FunctionT = typename bfi_detail::TypeMap<BT>::FunctionT;
using BranchProbabilityInfoT =
typename bfi_detail::TypeMap<BT>::BranchProbabilityInfoT;
const LoopInfoT *LI = nullptr;
const FunctionT *F = nullptr;
+ class BFICallbackVH;
+
// All blocks in reverse postorder.
std::vector<const BlockT *> RPOT;
- DenseMap<const BlockT *, BlockNode> Nodes;
+ DenseMap<BlockKeyT, std::pair<BlockNode, BFICallbackVH>> Nodes;
using rpot_iterator = typename std::vector<const BlockT *>::const_iterator;
BlockNode getNode(const rpot_iterator &I) const {
return BlockNode(getIndex(I));
}
- BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); }
+
+ BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB).first; }
const BlockT *getBlock(const BlockNode &Node) const {
assert(Node.Index < RPOT.size());
void setBlockFreq(const BlockT *BB, uint64_t Freq);
+ void forgetBlock(const BlockT *BB) {
+ // 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);
+ }
+
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB));
}
}
};
+template <>
+class BlockFrequencyInfoImpl<BasicBlock>::BFICallbackVH : public CallbackVH {
+ BlockFrequencyInfoImpl *BFIImpl;
+
+public:
+ BFICallbackVH() = default;
+
+ BFICallbackVH(const BasicBlock *BB, BlockFrequencyInfoImpl *BFIImpl)
+ : CallbackVH(BB), BFIImpl(BFIImpl) {}
+
+ void deleted() override {
+ BFIImpl->forgetBlock(cast<BasicBlock>(getValPtr()));
+ }
+};
+
+/// Dummy implementation since MachineBasicBlocks aren't Values, so ValueHandles
+/// don't apply to them.
+template <>
+class BlockFrequencyInfoImpl<MachineBasicBlock>::BFICallbackVH {
+public:
+ BFICallbackVH() = default;
+ BFICallbackVH(const MachineBasicBlock *, BlockFrequencyInfoImpl *) {}
+};
+
template <class BT>
void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
const BranchProbabilityInfoT &BPI,
// BlockNode for it assigned with a new index. The index can be determined
// by the size of Freqs.
BlockNode NewNode(Freqs.size());
- Nodes[BB] = NewNode;
+ Nodes[BB] = {NewNode, BFICallbackVH(BB, this)};
Freqs.emplace_back();
BlockFrequencyInfoImplBase::setBlockFreq(NewNode, Freq);
}
BlockNode Node = getNode(I);
LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node)
<< "\n");
- Nodes[*I] = Node;
+ Nodes[*I] = {Node, BFICallbackVH(*I, this)};
}
Working.reserve(RPOT.size());