[llvm] [UniformityAnalysis] Propagate label to cycle exit blocks (PR #216296)
Pankaj Dwivedi via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 04:59:02 PDT 2026
https://github.com/PankajDwivedi-25 updated https://github.com/llvm/llvm-project/pull/216296
>From 1471ad9eee2751bba202a6247b8b204f93775da1 Mon Sep 17 00:00:00 2001
From: padivedi <pankajkumar.divedi at amd.com>
Date: Thu, 20 Aug 2026 17:00:55 +0530
Subject: [PATCH 1/3] [UniformityAnalysis][AMDGPU] Add tests for phi at
divergent cycle exit (NFC)
---
.../AMDGPU/divergent-cycle-exit-phi.ll | 112 ++++++++++++++++++
1 file changed, 112 insertions(+)
create mode 100644 llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
new file mode 100644
index 0000000000000..cb66fbb4e036d
--- /dev/null
+++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
@@ -0,0 +1,112 @@
+; RUN: opt -mtriple amdgcn-unknown-amdhsa -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s
+
+declare i32 @llvm.amdgcn.workitem.id.x()
+
+; Divergent exit: the exit phi selects a different constant along each in-cycle
+; exit edge and threads leave divergently.
+define amdgpu_kernel void @divergent_cycle_exit_phi(i32 %n) {
+; CHECK-LABEL: UniformityInfo for function 'divergent_cycle_exit_phi':
+; CHECK-NOT: DIVERGENT: %acc
+entry:
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %body ]
+ %exit.cond = icmp uge i32 %iv, %n
+ br i1 %exit.cond, label %exit, label %body
+
+body:
+ %div.cond = icmp eq i32 %tid, 0
+ %iv.next = add i32 %iv, 1
+ br i1 %div.cond, label %exit, label %loop
+
+exit:
+ %acc = phi i32 [ 1, %body ], [ 0, %loop ]
+ ret void
+}
+
+; Uniform: both in-cycle exit edges carry the same value.
+define amdgpu_kernel void @uniform_cycle_exit_phi(i32 %n) {
+; CHECK-LABEL: UniformityInfo for function 'uniform_cycle_exit_phi':
+; CHECK-NOT: DIVERGENT: %acc
+entry:
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %body ]
+ %exit.cond = icmp uge i32 %iv, %n
+ br i1 %exit.cond, label %exit, label %body
+
+body:
+ %div.cond = icmp eq i32 %tid, 0
+ %iv.next = add i32 %iv, 1
+ br i1 %div.cond, label %exit, label %loop
+
+exit:
+ %acc = phi i32 [ 7, %body ], [ 7, %loop ]
+ ret void
+}
+
+; Nested cycles: the divergent branch is in the inner cycle but the exit edge
+; leaves both cycles at once.
+define amdgpu_kernel void @nested_cycle_exit_phi() {
+; CHECK-LABEL: UniformityInfo for function 'nested_cycle_exit_phi':
+; CHECK-NOT: DIVERGENT: %acc
+entry:
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ br label %outer.header
+
+outer.header:
+ %o = phi i32 [ 0, %entry ], [ %o.next, %outer.latch ]
+ %o.cond = icmp slt i32 %o, 2
+ br i1 %o.cond, label %inner.header, label %exit
+
+inner.header:
+ %i = phi i32 [ 0, %outer.header ], [ %i.next, %inner.body ]
+ %i.cond = icmp slt i32 %i, 2
+ br i1 %i.cond, label %inner.body, label %outer.latch
+
+inner.body:
+ %i.next = add i32 %i, 1
+ %div.cond = icmp eq i32 %tid, 0
+ br i1 %div.cond, label %exit, label %inner.header
+
+outer.latch:
+ %o.next = add i32 %o, 1
+ br label %outer.header
+
+exit:
+ %acc = phi i32 [ 1, %inner.body ], [ 0, %outer.header ]
+ ret void
+}
+
+; Uniform multi-predecessor exit reached only via uniform branches, alongside a
+; separate divergent exit from the same cycle.
+define amdgpu_kernel void @uniform_multi_exit_cycle_phi(i32 %n) {
+; CHECK-LABEL: UniformityInfo for function 'uniform_multi_exit_cycle_phi':
+; CHECK-NOT: DIVERGENT: %acc
+entry:
+ %tid = call i32 @llvm.amdgcn.workitem.id.x()
+ br label %loop
+
+loop:
+ %uni.cond = icmp slt i32 %n, 3
+ br i1 %uni.cond, label %body, label %exit.uniform
+
+body:
+ %div.cond = icmp eq i32 %tid, 0
+ br i1 %div.cond, label %exit.divergent, label %mid
+
+mid:
+ %uni.cond2 = icmp sgt i32 %n, 1
+ br i1 %uni.cond2, label %exit.uniform, label %loop
+
+exit.divergent:
+ ret void
+
+exit.uniform:
+ %acc = phi i32 [ 0, %loop ], [ 1, %mid ]
+ ret void
+}
>From 540330f91de6334c78d2db1c28b1f0f23b440b7b Mon Sep 17 00:00:00 2001
From: padivedi <pankajkumar.divedi at amd.com>
Date: Thu, 20 Aug 2026 17:07:27 +0530
Subject: [PATCH 2/3] [UniformityAnalysis] Propagate divergence label to cycle
exit blocks
---
llvm/include/llvm/ADT/GenericUniformityImpl.h | 4 ++--
.../UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index d066e11c117df..9c8e421d3e5c5 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -731,8 +731,8 @@ template <typename ContextT> class DivergencePropagator {
for (auto *BlockCycleExit : BlockCycleExits) {
if (BranchIsInside)
visitCycleExitEdge(*BlockCycleExit, *Label);
- else
- visitEdge(*BlockCycleExit, *Label);
+ // Propagate the label to the exit block.
+ visitEdge(*BlockCycleExit, *Label);
}
} else {
for (const auto *SuccBlock : successors(Block))
diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
index cb66fbb4e036d..a60c233890802 100644
--- a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
+++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
@@ -6,7 +6,7 @@ declare i32 @llvm.amdgcn.workitem.id.x()
; exit edge and threads leave divergently.
define amdgpu_kernel void @divergent_cycle_exit_phi(i32 %n) {
; CHECK-LABEL: UniformityInfo for function 'divergent_cycle_exit_phi':
-; CHECK-NOT: DIVERGENT: %acc
+; CHECK: DIVERGENT: %acc
entry:
%tid = call i32 @llvm.amdgcn.workitem.id.x()
br label %loop
@@ -53,7 +53,7 @@ exit:
; leaves both cycles at once.
define amdgpu_kernel void @nested_cycle_exit_phi() {
; CHECK-LABEL: UniformityInfo for function 'nested_cycle_exit_phi':
-; CHECK-NOT: DIVERGENT: %acc
+; CHECK: DIVERGENT: %acc
entry:
%tid = call i32 @llvm.amdgcn.workitem.id.x()
br label %outer.header
>From 483d3c409eff6e85ebad6f957fd33bcd6acde293 Mon Sep 17 00:00:00 2001
From: Pankaj Dwivedi <pankajkumar.divedi at amd.com>
Date: Thu, 20 Aug 2026 17:28:51 +0530
Subject: [PATCH 3/3] Update
llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
Co-authored-by: Matt Arsenault <Matthew.Arsenault at amd.com>
---
.../UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
index a60c233890802..945c1df09d14d 100644
--- a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
+++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/divergent-cycle-exit-phi.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple amdgcn-unknown-amdhsa -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s
+; RUN: opt -mtriple=amdgpu7.00-unknown-amdhsa -passes='print<uniformity>' -disable-output %s 2>&1 | FileCheck %s
declare i32 @llvm.amdgcn.workitem.id.x()
More information about the llvm-commits
mailing list