Skip to content

Commit 29f37f8

Browse files
CycleInfo: Fix splitCriticalEdge (#68584)
There are cases when cycle that contains both Pred and Succ is not found: Pred is in a smaller cycle that is contained in a larger cycle that also contains Succ, or Pred and Succ are in disjointed innermost cycles but there is a larger cycle that contains both. Add efficient helper function that finds innermost cycle that contains both Pred and Succ if it exists.
1 parent bccf2c8 commit 29f37f8

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

llvm/include/llvm/ADT/GenericCycleImpl.h

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,24 @@ void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
184184
It.second = NewParent;
185185
}
186186

187+
template <typename ContextT>
188+
void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
189+
// FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
190+
// printing, cycle NewBlock is at the end of list but it should be in the
191+
// middle to represent actual traversal of a cycle.
192+
Cycle->appendBlock(Block);
193+
BlockMap.try_emplace(Block, Cycle);
194+
195+
CycleT *ParentCycle = Cycle->getParentCycle();
196+
while (ParentCycle) {
197+
Cycle = ParentCycle;
198+
Cycle->appendBlock(Block);
199+
ParentCycle = Cycle->getParentCycle();
200+
}
201+
202+
BlockMapTopLevel.try_emplace(Block, Cycle);
203+
}
204+
187205
/// \brief Main function of the cycle info computations.
188206
template <typename ContextT>
189207
void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
@@ -368,17 +386,11 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
368386
BlockT *NewBlock) {
369387
// Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
370388
// cycles that had blocks Pred and Succ also get NewBlock.
371-
CycleT *Cycle = this->getCycle(Pred);
372-
if (Cycle && Cycle->contains(Succ)) {
373-
while (Cycle) {
374-
// FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
375-
// printing cycle NewBlock is at the end of list but it should be in the
376-
// middle to represent actual traversal of a cycle.
377-
Cycle->appendBlock(NewBlock);
378-
BlockMap.try_emplace(NewBlock, Cycle);
379-
Cycle = Cycle->getParentCycle();
380-
}
381-
}
389+
CycleT *Cycle = getSmallestCommonCycle(getCycle(Pred), getCycle(Succ));
390+
if (!Cycle)
391+
return;
392+
393+
addBlockToCycle(NewBlock, Cycle);
382394
assert(validateTree());
383395
}
384396

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

407+
/// \brief Find the innermost cycle containing both given cycles.
408+
///
409+
/// \returns the innermost cycle containing both \p A and \p B
410+
/// or nullptr if there is no such cycle.
411+
template <typename ContextT>
412+
auto GenericCycleInfo<ContextT>::getSmallestCommonCycle(CycleT *A,
413+
CycleT *B) const
414+
-> CycleT * {
415+
if (!A || !B)
416+
return nullptr;
417+
418+
// If cycles A and B have different depth replace them with parent cycle
419+
// until they have the same depth.
420+
while (A->getDepth() > B->getDepth())
421+
A = A->getParentCycle();
422+
while (B->getDepth() > A->getDepth())
423+
B = B->getParentCycle();
424+
425+
// Cycles A and B are at same depth but may be disjoint, replace them with
426+
// parent cycles until we find cycle that contains both or we run out of
427+
// parent cycles.
428+
while (A != B) {
429+
A = A->getParentCycle();
430+
B = B->getParentCycle();
431+
}
432+
433+
return A;
434+
}
435+
395436
/// \brief get the depth for the cycle which containing a given block.
396437
///
397438
/// \returns the depth for the innermost cycle containing \p Block or 0 if it is

llvm/include/llvm/ADT/GenericCycleInfo.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ template <typename ContextT> class GenericCycleInfo {
248248
/// the subtree.
249249
void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);
250250

251+
/// Assumes that \p Cycle is the innermost cycle containing \p Block.
252+
/// \p Block will be appended to \p Cycle and all of its parent cycles.
253+
/// \p Block will be added to BlockMap with \p Cycle and
254+
/// BlockMapTopLevel with \p Cycle's top level parent cycle.
255+
void addBlockToCycle(BlockT *Block, CycleT *Cycle);
256+
251257
public:
252258
GenericCycleInfo() = default;
253259
GenericCycleInfo(GenericCycleInfo &&) = default;
@@ -261,6 +267,7 @@ template <typename ContextT> class GenericCycleInfo {
261267
const ContextT &getSSAContext() const { return Context; }
262268

263269
CycleT *getCycle(const BlockT *Block) const;
270+
CycleT *getSmallestCommonCycle(CycleT *A, CycleT *B) const;
264271
unsigned getCycleDepth(const BlockT *Block) const;
265272
CycleT *getTopLevelParentCycle(BlockT *Block);
266273

0 commit comments

Comments
 (0)