[llvm] CycleInfo: Fix splitCriticalEdge (PR #68584)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 9 06:08:22 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/68584.diff


2 Files Affected:

- (modified) llvm/include/llvm/ADT/GenericCycleImpl.h (+38-10) 
- (modified) llvm/include/llvm/ADT/GenericCycleInfo.h (+1) 


``````````diff
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index 2adec725cd3bf7d..6f74d0825e1346d 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -368,16 +368,14 @@ 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 = getCycleContaining(Pred, 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();
   }
   assert(validateTree());
 }
@@ -392,6 +390,36 @@ auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const
   return BlockMap.lookup(Block);
 }
 
+/// \brief Find the innermost cycle containing both given blocks.
+///
+/// \returns the innermost cycle containing both \p A and \p B or nullptr if
+///          they are not both contained in any cycle.
+template <typename ContextT>
+auto GenericCycleInfo<ContextT>::getCycleContaining(const BlockT *A,
+                                                    const BlockT *B) const
+    -> CycleT * {
+  CycleT *CycleA = getCycle(A);
+  CycleT *CycleB = getCycle(B);
+  if (!CycleA || !CycleB)
+    return nullptr;
+
+  // If CycleA and CycleB have different depth replace them with parents until
+  // they have the same depth.
+  while (CycleA->getDepth() > CycleB->getDepth())
+    CycleA = CycleA->getParentCycle();
+  while (CycleB->getDepth() > CycleA->getDepth())
+    CycleB = CycleB->getParentCycle();
+
+  // CycleA and CycleB are at same depth but may be disjoint, replace them with
+  // parents until we find cycle that contains both or we run out of parents.
+  while (CycleA != CycleB) {
+    CycleA = CycleA->getParentCycle();
+    CycleB = CycleB->getParentCycle();
+  }
+
+  return CycleA;
+}
+
 /// \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
diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h
index 18be7eb4a6cca9d..b6be59b75a6c1ab 100644
--- a/llvm/include/llvm/ADT/GenericCycleInfo.h
+++ b/llvm/include/llvm/ADT/GenericCycleInfo.h
@@ -261,6 +261,7 @@ template <typename ContextT> class GenericCycleInfo {
   const ContextT &getSSAContext() const { return Context; }
 
   CycleT *getCycle(const BlockT *Block) const;
+  CycleT *getCycleContaining(const BlockT *A, const BlockT *B) const;
   unsigned getCycleDepth(const BlockT *Block) const;
   CycleT *getTopLevelParentCycle(BlockT *Block);
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/68584


More information about the llvm-commits mailing list