[llvm-branch-commits] [llvm] [SimplifyCFG] Avoid threading loop-header branches in convergent functions (PR #204958)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Jun 20 19:29:42 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Shilei Tian (shiltian)
<details>
<summary>Changes</summary>
SimplifyCFG can fold a conditional branch when the condition is known from
a predecessor. When the destination is a loop header in a convergent function,
this can change the dynamic convergence structure of the loop even though the
scalar CFG rewrite is otherwise valid.
Skip this fold for loop-header branches in convergent functions so convergent
control flow is preserved.
Fixes ROCM-26496.
---
Full diff: https://github.com/llvm/llvm-project/pull/204958.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+4-1)
- (modified) llvm/test/Transforms/SimplifyCFG/convergent-loop-header.ll (+6-4)
``````````diff
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 524947dd2e95d..3166d56a4dc0b 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3713,7 +3713,10 @@ bool SimplifyCFGOpt::foldCondBranchOnValueKnownInPredecessor(CondBrInst *BI) {
// Note: If BB is a loop header then there is a risk that threading introduces
// a non-canonical loop by moving a back edge. So we avoid this optimization
// for loop headers if NeedCanonicalLoop is set.
- if (Options.NeedCanonicalLoop && is_contained(LoopHeaders, BI->getParent()))
+ // Also avoid threading loop headers in convergent functions, since changing
+ // the branch structure can change the dynamic instances of convergent ops.
+ if ((Options.NeedCanonicalLoop || BI->getFunction()->isConvergent()) &&
+ is_contained(LoopHeaders, BI->getParent()))
return false;
std::optional<bool> Result;
diff --git a/llvm/test/Transforms/SimplifyCFG/convergent-loop-header.ll b/llvm/test/Transforms/SimplifyCFG/convergent-loop-header.ll
index a988d9e469880..45ac7bef0edbb 100644
--- a/llvm/test/Transforms/SimplifyCFG/convergent-loop-header.ll
+++ b/llvm/test/Transforms/SimplifyCFG/convergent-loop-header.ll
@@ -12,13 +12,15 @@ define void @preserve_loop_header_branch(i32 %tid, ptr %ptr) convergent {
; CHECK-NEXT: br i1 [[COND]], label %[[OUTER_THEN:.*]], label %[[LOOP_HEADER:.*]]
; CHECK: [[OUTER_THEN]]:
; CHECK-NEXT: store i32 1, ptr [[PTR]], align 4
-; CHECK-NEXT: br label %[[LOOP_THEN:.*]]
-; CHECK: [[LOOP_THEN]]:
-; CHECK-NEXT: store i32 2, ptr [[PTR]], align 4
; CHECK-NEXT: br label %[[LOOP_HEADER]]
; CHECK: [[LOOP_HEADER]]:
+; CHECK-NEXT: br i1 [[COND]], label %[[LOOP_THEN:.*]], label %[[LOOP_BODY:.*]]
+; CHECK: [[LOOP_THEN]]:
+; CHECK-NEXT: store i32 2, ptr [[PTR]], align 4
+; CHECK-NEXT: br label %[[LOOP_BODY]]
+; CHECK: [[LOOP_BODY]]:
; CHECK-NEXT: call void @barrier()
-; CHECK-NEXT: br i1 [[COND]], label %[[LOOP_THEN]], label %[[EXIT:.*]]
+; CHECK-NEXT: br i1 [[COND]], label %[[LOOP_HEADER]], label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
``````````
</details>
https://github.com/llvm/llvm-project/pull/204958
More information about the llvm-branch-commits
mailing list