[CycleInfo] Index using block numbers instead of pointers (#187500)

Replace the DenseMap from block pointer to cycle with a vector indexed
by block number, which makes the lookup more efficient.
This commit is contained in:
Nikita Popov 2026-03-19 16:12:21 +01:00 committed by GitHub
parent 5ae5f9df42
commit 70bb9e2452
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 9 deletions

View File

@ -313,13 +313,34 @@ void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
Child->clearCache();
}
template <typename ContextT>
void GenericCycleInfo<ContextT>::verifyBlockNumberEpoch(
const FunctionT *Fn) const {
assert(BlockNumberEpoch ==
GraphTraits<const FunctionT *>::getNumberEpoch(Fn) &&
"CycleInfo used with outdated block number epoch");
}
template <typename ContextT>
void GenericCycleInfo<ContextT>::addToBlockMap(BlockT *Block, CycleT *Cycle) {
// The caller should ensure that BlockMap is large enough.
verifyBlockNumberEpoch(Block->getParent());
unsigned Number = GraphTraits<BlockT *>::getNumber(Block);
BlockMap[Number] = Cycle;
}
template <typename ContextT>
void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
// Make sure BlockMap is large enough for the new block.
unsigned Number = GraphTraits<BlockT *>::getNumber(Block);
if (Number >= BlockMap.size())
BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(Block->getParent()));
// FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
// printing, cycle NewBlock is at the end of list but it should be in the
// middle to represent actual traversal of a cycle.
Cycle->appendBlock(Block);
BlockMap.try_emplace(Block, Cycle);
addToBlockMap(Block, Cycle);
CycleT *ParentCycle = Cycle->getParentCycle();
while (ParentCycle) {
@ -361,7 +382,7 @@ void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>();
NewCycle->appendEntry(HeaderCandidate);
NewCycle->appendBlock(HeaderCandidate);
Info.BlockMap.try_emplace(HeaderCandidate, NewCycle.get());
Info.addToBlockMap(HeaderCandidate, NewCycle.get());
// Helper function to process (non-back-edge) predecessors of a discovered
// block and either add them to the worklist or recognize that the given
@ -417,7 +438,7 @@ void GenericCycleInfoCompute<ContextT>::run(FunctionT *F) {
<< Info.Context.print(BlockParent->getHeader()) << "\n");
}
} else {
Info.BlockMap.try_emplace(Block, NewCycle.get());
Info.addToBlockMap(Block, NewCycle.get());
assert(!is_contained(NewCycle->Blocks, Block));
NewCycle->Blocks.insert(Block);
ProcessPredecessors(Block);
@ -508,6 +529,8 @@ template <typename ContextT>
void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
GenericCycleInfoCompute<ContextT> Compute(*this);
Context = ContextT(&F);
BlockNumberEpoch = GraphTraits<FunctionT *>::getNumberEpoch(&F);
BlockMap.resize(GraphTraits<FunctionT *>::getMaxNumber(&F));
LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
<< "\n");
@ -534,7 +557,9 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
template <typename ContextT>
auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const
-> CycleT * {
return BlockMap.lookup(Block);
verifyBlockNumberEpoch(Block->getParent());
unsigned Number = GraphTraits<const BlockT *>::getNumber(Block);
return Number < BlockMap.size() ? BlockMap[Number] : nullptr;
}
/// \brief Find the innermost cycle containing both given cycles.
@ -608,9 +633,9 @@ void GenericCycleInfo<ContextT>::verifyCycleNest(bool VerifyFull) const {
Cycle->verifyCycleNest();
// Check the block map entries for blocks contained in this cycle.
for (BlockT *BB : Cycle->blocks()) {
auto MapIt = BlockMap.find(BB);
assert(MapIt != BlockMap.end());
assert(Cycle->contains(MapIt->second));
CycleT *CycleInBlockMap = getCycle(BB);
assert(CycleInBlockMap != nullptr);
assert(Cycle->contains(CycleInBlockMap));
}
}
}

View File

@ -266,9 +266,10 @@ public:
private:
ContextT Context;
unsigned BlockNumberEpoch;
/// Map basic blocks to their inner-most containing cycle.
DenseMap<BlockT *, CycleT *> BlockMap;
/// Map basic block numbers to their inner-most containing cycle.
SmallVector<CycleT *> BlockMap;
/// Top-level cycles discovered by any DFS.
///
@ -282,6 +283,9 @@ private:
/// the subtree.
void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);
void verifyBlockNumberEpoch(const FunctionT *Fn) const;
void addToBlockMap(BlockT *Block, CycleT *Cycle);
public:
GenericCycleInfo() = default;
GenericCycleInfo(GenericCycleInfo &&) = default;