Skip to content

Commit bae05ce

Browse files
DaniilSuchkovmemfrob
authored and
memfrob
committed
[BFI] Use CallbackVH to notify BFI about deletion of basic blocks
With AssertingVHs instead of bare pointers in BlockFrequencyInfoImpl::Nodes (but without CallbackVHs) ~1/36 of all tests ran by make check fail. It means that there are users of BFI that delete basic blocks while keeping BFI. Some of those transformations add new basic blocks, so if a new basic block happens to be allocated at address where an already deleted block was and we don't explicitly set block frequency for that new block, BFI will report some non-default frequency for the block even though frequency for the block was never set. Inliner is an example of a transformation that adds and removes BBs while querying and updating BFI. With this patch, thanks to updates via CallbackVH, BFI won't keep stale pointers in its Nodes map. This is a resubmission of 408349a25d0f5a012003f84c95b49bcc7782fa70 with fixed compiler warning and MSVC compilation error. Reviewers: davidxl, yamauchi, asbirlea, fhahn, fedor.sergeev Reviewed-By: asbirlea, davidxl Tags: #llvm Differential Revision: https://reviews.llvm.org/D75341
1 parent 17e065f commit bae05ce

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h

+51-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/Twine.h"
2525
#include "llvm/ADT/iterator_range.h"
2626
#include "llvm/IR/BasicBlock.h"
27+
#include "llvm/IR/ValueHandle.h"
2728
#include "llvm/Support/BlockFrequency.h"
2829
#include "llvm/Support/BranchProbability.h"
2930
#include "llvm/Support/CommandLine.h"
@@ -547,19 +548,24 @@ namespace bfi_detail {
547548
template <class BlockT> struct TypeMap {};
548549
template <> struct TypeMap<BasicBlock> {
549550
using BlockT = BasicBlock;
551+
using BlockKeyT = AssertingVH<const BasicBlock>;
550552
using FunctionT = Function;
551553
using BranchProbabilityInfoT = BranchProbabilityInfo;
552554
using LoopT = Loop;
553555
using LoopInfoT = LoopInfo;
554556
};
555557
template <> struct TypeMap<MachineBasicBlock> {
556558
using BlockT = MachineBasicBlock;
559+
using BlockKeyT = const MachineBasicBlock *;
557560
using FunctionT = MachineFunction;
558561
using BranchProbabilityInfoT = MachineBranchProbabilityInfo;
559562
using LoopT = MachineLoop;
560563
using LoopInfoT = MachineLoopInfo;
561564
};
562565

566+
template <class BlockT, class BFIImplT>
567+
class BFICallbackVH;
568+
563569
/// Get the name of a MachineBasicBlock.
564570
///
565571
/// Get the name of a MachineBasicBlock. It's templated so that including from
@@ -845,21 +851,24 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
845851
friend struct bfi_detail::BlockEdgesAdder<BT>;
846852

847853
using BlockT = typename bfi_detail::TypeMap<BT>::BlockT;
854+
using BlockKeyT = typename bfi_detail::TypeMap<BT>::BlockKeyT;
848855
using FunctionT = typename bfi_detail::TypeMap<BT>::FunctionT;
849856
using BranchProbabilityInfoT =
850857
typename bfi_detail::TypeMap<BT>::BranchProbabilityInfoT;
851858
using LoopT = typename bfi_detail::TypeMap<BT>::LoopT;
852859
using LoopInfoT = typename bfi_detail::TypeMap<BT>::LoopInfoT;
853860
using Successor = GraphTraits<const BlockT *>;
854861
using Predecessor = GraphTraits<Inverse<const BlockT *>>;
862+
using BFICallbackVH =
863+
bfi_detail::BFICallbackVH<BlockT, BlockFrequencyInfoImpl>;
855864

856865
const BranchProbabilityInfoT *BPI = nullptr;
857866
const LoopInfoT *LI = nullptr;
858867
const FunctionT *F = nullptr;
859868

860869
// All blocks in reverse postorder.
861870
std::vector<const BlockT *> RPOT;
862-
DenseMap<const BlockT *, BlockNode> Nodes;
871+
DenseMap<BlockKeyT, std::pair<BlockNode, BFICallbackVH>> Nodes;
863872

864873
using rpot_iterator = typename std::vector<const BlockT *>::const_iterator;
865874

@@ -871,7 +880,8 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
871880
BlockNode getNode(const rpot_iterator &I) const {
872881
return BlockNode(getIndex(I));
873882
}
874-
BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); }
883+
884+
BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB).first; }
875885

876886
const BlockT *getBlock(const BlockNode &Node) const {
877887
assert(Node.Index < RPOT.size());
@@ -992,6 +1002,13 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
9921002

9931003
void setBlockFreq(const BlockT *BB, uint64_t Freq);
9941004

1005+
void forgetBlock(const BlockT *BB) {
1006+
// We don't erase corresponding items from `Freqs`, `RPOT` and other to
1007+
// avoid invalidating indices. Doing so would have saved some memory, but
1008+
// it's not worth it.
1009+
Nodes.erase(BB);
1010+
}
1011+
9951012
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
9961013
return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB));
9971014
}
@@ -1019,6 +1036,36 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
10191036
}
10201037
};
10211038

1039+
namespace bfi_detail {
1040+
1041+
template <class BFIImplT>
1042+
class BFICallbackVH<BasicBlock, BFIImplT> : public CallbackVH {
1043+
BFIImplT *BFIImpl;
1044+
1045+
public:
1046+
BFICallbackVH() = default;
1047+
1048+
BFICallbackVH(const BasicBlock *BB, BFIImplT *BFIImpl)
1049+
: CallbackVH(BB), BFIImpl(BFIImpl) {}
1050+
1051+
virtual ~BFICallbackVH() = default;
1052+
1053+
void deleted() override {
1054+
BFIImpl->forgetBlock(cast<BasicBlock>(getValPtr()));
1055+
}
1056+
};
1057+
1058+
/// Dummy implementation since MachineBasicBlocks aren't Values, so ValueHandles
1059+
/// don't apply to them.
1060+
template <class BFIImplT>
1061+
class BFICallbackVH<MachineBasicBlock, BFIImplT> {
1062+
public:
1063+
BFICallbackVH() = default;
1064+
BFICallbackVH(const MachineBasicBlock *, BFIImplT *) {}
1065+
};
1066+
1067+
} // end namespace bfi_detail
1068+
10221069
template <class BT>
10231070
void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
10241071
const BranchProbabilityInfoT &BPI,
@@ -1066,7 +1113,7 @@ void BlockFrequencyInfoImpl<BT>::setBlockFreq(const BlockT *BB, uint64_t Freq) {
10661113
// BlockNode for it assigned with a new index. The index can be determined
10671114
// by the size of Freqs.
10681115
BlockNode NewNode(Freqs.size());
1069-
Nodes[BB] = NewNode;
1116+
Nodes[BB] = {NewNode, BFICallbackVH(BB, this)};
10701117
Freqs.emplace_back();
10711118
BlockFrequencyInfoImplBase::setBlockFreq(NewNode, Freq);
10721119
}
@@ -1086,7 +1133,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() {
10861133
BlockNode Node = getNode(I);
10871134
LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node)
10881135
<< "\n");
1089-
Nodes[*I] = Node;
1136+
Nodes[*I] = {Node, BFICallbackVH(*I, this)};
10901137
}
10911138

10921139
Working.reserve(RPOT.size());

llvm/include/llvm/IR/ValueHandle.h

+1
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ class CallbackVH : public ValueHandleBase {
414414
public:
415415
CallbackVH() : ValueHandleBase(Callback) {}
416416
CallbackVH(Value *P) : ValueHandleBase(Callback, P) {}
417+
CallbackVH(const Value *P) : CallbackVH(const_cast<Value *>(P)) {}
417418

418419
operator Value*() const {
419420
return getValPtr();

0 commit comments

Comments
 (0)