[llvm] [Uniformity] Fixed control-div early stop (PR #139667)

Sameer Sahasrabuddhe via llvm-commits llvm-commits at lists.llvm.org
Mon May 26 23:33:10 PDT 2025


================
@@ -626,14 +623,36 @@ template <typename ContextT> class DivergencePropagator {
         LLVM_DEBUG(dbgs() << "\tImmediate divergent cycle exit: "
                           << Context.print(SuccBlock) << "\n");
       }
-      auto SuccIdx = CyclePOT.getIndex(SuccBlock);
       visitEdge(*SuccBlock, *SuccBlock);
-      FloorIdx = std::min<int>(FloorIdx, SuccIdx);
     }
 
+    // Return true if B is inside an irreducible cycle
+    auto IsInIrreducibleCycle = [this](const BlockT *B) {
+      for (const auto *Cycle = CI.getCycle(B); Cycle;
+           Cycle = Cycle->getParentCycle()) {
+        // If everything is inside a reducible cycle, then look no further
+        if (Cycle->isReducible() && Cycle->contains(&DivTermBlock))
+          return false;
+        if (!Cycle->isReducible())
+          return true;
+      }
+      return false;
+    };
----------------
ssahasra wrote:

```suggestion
      // Locate the largest ancestor cycle that is not reducible and does not
      // contain a reducible ancestor. This is done with a lambda that is defined
      // and invoked in the same statement.
      const CycleT *IrreducibleAncestor = [](const CycleT *C) -> const CycleT* {
        if (!C) return nullptr;
        if (C->isReducible()) return nullptr;
        while (const CycleT *P = C->getParentCycle()) {
          if (P->isReducible()) return C;
          C = P;
        }
        assert(!C->getParentCycle());
        assert(!C->isReducible());
        return C;
      } (DivTermCycle);
```

I think I now understand what we have been missing. If `DivTermBlock` is inside a reducible cycle, the traversal does not need to propagate beyond that cycle. If it is not inside any cycle, then the traversal can stop at the IPD. In either case, traversal can stop when there is only one `FreshLabel` left. Let R be the largest irreducible cycle containing `DivTermBlock` such that any subcycle X that contains `DivTermBlock` is also irreducible. Thus, R either has no parent, or the parent is reducible. The traversal needs to visit every block of R. Thus for the stopping condition we have:

```
        if (FreshLabels.count() == 1 && (!IrreducibleAncestor || !IrreducibleAncestor->contains(Block)))
          break;
```

I have pushed this change to the following branch. It also contains all the extra tests that I had mentioned earlier.
https://github.com/llvm/llvm-project/tree/users/ssahasra/uniform_issue_137277

If this logic is convincing, please do cherry-pick this into your PR!

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


More information about the llvm-commits mailing list