[llvm] [Analysis] Require explict updates to BFI (PR #185184)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 7 08:51:21 PST 2026
================
@@ -841,26 +835,34 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
/// series by simulation.)
template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
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;
using LoopT = typename bfi_detail::TypeMap<BT>::LoopT;
using LoopInfoT = typename bfi_detail::TypeMap<BT>::LoopInfoT;
using Successor = GraphTraits<const BlockT *>;
using Predecessor = GraphTraits<Inverse<const BlockT *>>;
- using BFICallbackVH =
- bfi_detail::BFICallbackVH<BlockT, BlockFrequencyInfoImpl>;
const BranchProbabilityInfoT *BPI = nullptr;
const LoopInfoT *LI = nullptr;
const FunctionT *F = nullptr;
// All blocks in reverse postorder.
- std::vector<BFICallbackVH> RPOT;
+ std::vector<const BlockT *> RPOT;
DenseMap<const BlockT *, BlockNode> Nodes;
- BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); }
+ BlockNode getNode(const BlockT *BB) const {
+#ifdef EXPENSIVE_CHECKS
+ // Try to catch cases where blocks were deleted (use-after-free can be
+ // caught by ASan) or moved to a different function, but the BFI was not
+ // updated. This is an asymptotically expensive check.
+ for (auto Node : RPOT)
+ assert((!Node || Node->getParent() == F) &&
+ "BFI stores basic block outside of function, missing update!");
+#endif
----------------
aengelke wrote:
AssertingVH is too strong, because there are too many cases where a cached BFI is stored in the analysis manager and is only invalidated at the end of a pass that deletes a block. It would require all passes to explicitly invalidate the BFI *before* erasing any blocks, even if they don't use it at all and don't claim to preserve it.
PoisoningVH is too weak: the stale block pointers aren't actually accessed, they're just there and in very rare cases cause problems when the address of a deleted BasicBlock gets reused, but this is too unlikely to be caught in non-release builds.
What we'd want is a value handle that poisons the entire BFI and assert that the BFI is not poisoned if the BFI continues to be used. (Doable but a bit annoying to implement due to joint handling of MIR.) MachineBasicBlocks have no ValueHandle and the staleness problem can occur there as well (allocations are recycled); this pretty hacky implementation did catch issues there that a purely VH-based implementation would not catch.
(NB: CallbackVH was introduced in [D75341](https://reviews.llvm.org/D75341).)
https://github.com/llvm/llvm-project/pull/185184
More information about the llvm-commits
mailing list