diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h index c40f0c95faf9..aa43430b2283 100644 --- a/llvm/include/llvm/ADT/GenericCycleImpl.h +++ b/llvm/include/llvm/ADT/GenericCycleImpl.h @@ -313,13 +313,34 @@ void GenericCycleInfo::moveTopLevelCycleToNewParent(CycleT *NewParent, Child->clearCache(); } +template +void GenericCycleInfo::verifyBlockNumberEpoch( + const FunctionT *Fn) const { + assert(BlockNumberEpoch == + GraphTraits::getNumberEpoch(Fn) && + "CycleInfo used with outdated block number epoch"); +} + +template +void GenericCycleInfo::addToBlockMap(BlockT *Block, CycleT *Cycle) { + // The caller should ensure that BlockMap is large enough. + verifyBlockNumberEpoch(Block->getParent()); + unsigned Number = GraphTraits::getNumber(Block); + BlockMap[Number] = Cycle; +} + template void GenericCycleInfo::addBlockToCycle(BlockT *Block, CycleT *Cycle) { + // Make sure BlockMap is large enough for the new block. + unsigned Number = GraphTraits::getNumber(Block); + if (Number >= BlockMap.size()) + BlockMap.resize(GraphTraits::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::run(FunctionT *F) { std::unique_ptr NewCycle = std::make_unique(); 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::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 void GenericCycleInfo::compute(FunctionT &F) { GenericCycleInfoCompute Compute(*this); Context = ContextT(&F); + BlockNumberEpoch = GraphTraits::getNumberEpoch(&F); + BlockMap.resize(GraphTraits::getMaxNumber(&F)); LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName() << "\n"); @@ -534,7 +557,9 @@ void GenericCycleInfo::splitCriticalEdge(BlockT *Pred, BlockT *Succ, template auto GenericCycleInfo::getCycle(const BlockT *Block) const -> CycleT * { - return BlockMap.lookup(Block); + verifyBlockNumberEpoch(Block->getParent()); + unsigned Number = GraphTraits::getNumber(Block); + return Number < BlockMap.size() ? BlockMap[Number] : nullptr; } /// \brief Find the innermost cycle containing both given cycles. @@ -608,9 +633,9 @@ void GenericCycleInfo::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)); } } } diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h index ca481b1b3949..bfa7cb5731e2 100644 --- a/llvm/include/llvm/ADT/GenericCycleInfo.h +++ b/llvm/include/llvm/ADT/GenericCycleInfo.h @@ -266,9 +266,10 @@ public: private: ContextT Context; + unsigned BlockNumberEpoch; - /// Map basic blocks to their inner-most containing cycle. - DenseMap BlockMap; + /// Map basic block numbers to their inner-most containing cycle. + SmallVector 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;