Skip to content

CycleInfo: Fix splitCriticalEdge #68584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 52 additions & 11 deletions llvm/include/llvm/ADT/GenericCycleImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,24 @@ void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
It.second = NewParent;
}

template <typename ContextT>
void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
// 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);

CycleT *ParentCycle = Cycle->getParentCycle();
while (ParentCycle) {
Cycle = ParentCycle;
Cycle->appendBlock(Block);
ParentCycle = Cycle->getParentCycle();
}

BlockMapTopLevel.try_emplace(Block, Cycle);
}

/// \brief Main function of the cycle info computations.
template <typename ContextT>
void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
Expand Down Expand Up @@ -368,17 +386,11 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
BlockT *NewBlock) {
// Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
// cycles that had blocks Pred and Succ also get NewBlock.
CycleT *Cycle = this->getCycle(Pred);
if (Cycle && Cycle->contains(Succ)) {
while (Cycle) {
// 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(NewBlock);
BlockMap.try_emplace(NewBlock, Cycle);
Cycle = Cycle->getParentCycle();
}
}
CycleT *Cycle = getSmallestCommonCycle(getCycle(Pred), getCycle(Succ));
if (!Cycle)
return;

addBlockToCycle(NewBlock, Cycle);
assert(validateTree());
}

Expand All @@ -392,6 +404,35 @@ auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const
return BlockMap.lookup(Block);
}

/// \brief Find the innermost cycle containing both given cycles.
///
/// \returns the innermost cycle containing both \p A and \p B
/// or nullptr if there is no such cycle.
template <typename ContextT>
auto GenericCycleInfo<ContextT>::getSmallestCommonCycle(CycleT *A,
CycleT *B) const
-> CycleT * {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should take cycles as arguments. It is more likely that the client has already located the cycles for A and B, so we can avoid the calls to getCycle() inside this function.

if (!A || !B)
return nullptr;

// If cycles A and B have different depth replace them with parent cycle
// until they have the same depth.
while (A->getDepth() > B->getDepth())
A = A->getParentCycle();
while (B->getDepth() > A->getDepth())
B = B->getParentCycle();

// Cycles A and B are at same depth but may be disjoint, replace them with
// parent cycles until we find cycle that contains both or we run out of
// parent cycles.
while (A != B) {
A = A->getParentCycle();
B = B->getParentCycle();
}

return A;
}

/// \brief get the depth for the cycle which containing a given block.
///
/// \returns the depth for the innermost cycle containing \p Block or 0 if it is
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/ADT/GenericCycleInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ template <typename ContextT> class GenericCycleInfo {
/// the subtree.
void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);

/// Assumes that \p Cycle is the innermost cycle containing \p Block.
/// \p Block will be appended to \p Cycle and all of its parent cycles.
/// \p Block will be added to BlockMap with \p Cycle and
/// BlockMapTopLevel with \p Cycle's top level parent cycle.
void addBlockToCycle(BlockT *Block, CycleT *Cycle);

public:
GenericCycleInfo() = default;
GenericCycleInfo(GenericCycleInfo &&) = default;
Expand All @@ -261,6 +267,7 @@ template <typename ContextT> class GenericCycleInfo {
const ContextT &getSSAContext() const { return Context; }

CycleT *getCycle(const BlockT *Block) const;
CycleT *getSmallestCommonCycle(CycleT *A, CycleT *B) const;
unsigned getCycleDepth(const BlockT *Block) const;
CycleT *getTopLevelParentCycle(BlockT *Block);

Expand Down