[llvm] [AMDGPU][FixIrreducible][UnifyLoopExits] Support callbr with inline-asm (PR #149308)

Sameer Sahasrabuddhe via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 14 01:17:46 PDT 2025


================
@@ -342,3 +345,76 @@ std::pair<BasicBlock *, bool> ControlFlowHub::finalize(
 
   return {FirstGuardBlock, true};
 }
+
+// Check if the given cycle is disjoint with the cycle of the given basic block.
+// If the basic block does not belong to any cycle, this is regarded as
+// disjoint, too.
+static bool disjointWithBlock(CycleInfo *CI, Cycle *C, BasicBlock *BB) {
+  Cycle *CC = CI->getCycle(BB);
+  if (!CC)
+    return true;
+  Cycle *CommonC = CI->getSmallestCommonCycle(C, CC);
+  return CommonC != C && CommonC != CC;
+}
+
+// Check if the given loop is disjoint with the loop of the given basic block.
+// If the basic block does not belong to any loop, this is regarded as
+// disjoint, too.
+static bool disjointWithBlock(LoopInfo *LI, Loop *L, BasicBlock *BB) {
+  Loop *LL = LI->getLoopFor(BB);
+  return LL && !L->contains(LL) && !LL->contains(L);
+}
+
+template <typename TI, typename T>
+static void updateCycleLoopInfo(TI *LCI, bool AttachToCallBr,
+                                BasicBlock *CallBrBlock,
+                                BasicBlock *CallBrTarget, BasicBlock *Succ) {
+  static_assert(std::is_same_v<TI, CycleInfo> || std::is_same_v<TI, LoopInfo>,
+                "type must be CycleInfo or LoopInfo");
+  if (!LCI)
+    return;
+
+  T *LC;
+  if constexpr (std::is_same_v<TI, CycleInfo>)
+    LC = LCI->getCycle(AttachToCallBr ? CallBrBlock : Succ);
+  else
+    LC = LCI->getLoopFor(AttachToCallBr ? CallBrBlock : Succ);
+  if (!LC)
+    return;
+
+  // Check if the cycles/loops are disjoint. In that case, we do not add the
+  // intermediate target to any cycle/loop.
+  if (AttachToCallBr && disjointWithBlock(LCI, LC, Succ))
----------------
ssahasra wrote:

If we return at the next line, then `CallBrTarget` is not added to any cycle, although there could be an outer cycle that contains both `LC` and `Succ`. Is there a test which demonstrate such a nesting?

Generalizing that, I am not sure we even need the complication of passing `AttachToCallBr` and checking `disjointWithBlock`. Isn't it sufficient to add `CallBrTarget` to the smallest common parent `CP` of `CallBrBlock` and `Succ`? If we added it to the parent of either block and that parent did not contain the other block, then that parent would no longer be strongly connected and `LCI` should fail validation.

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


More information about the llvm-commits mailing list