[llvm] c71e991 - [Utils] Fix duplicate DomTree updates in SplitIndirectBrCriticalEdges (#196475)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 23:27:42 PDT 2026


Author: Maosu Zhao
Date: 2026-05-09T14:27:37+08:00
New Revision: c71e9918df120e272966ce4e9caa0e3abdb5a390

URL: https://github.com/llvm/llvm-project/commit/c71e9918df120e272966ce4e9caa0e3abdb5a390
DIFF: https://github.com/llvm/llvm-project/commit/c71e9918df120e272966ce4e9caa0e3abdb5a390.diff

LOG: [Utils] Fix duplicate DomTree updates in SplitIndirectBrCriticalEdges (#196475)

SplitIndirectBrCriticalEdges generates DomTree Insert/Delete pairs for
each predecessor in OtherPreds. However, OtherPreds can contain
duplicate entries when a conditional branch has both targets pointing to
the same block (e.g., `br i1 %c, label %X, label %X`). This produces
duplicate DomTree updates for the same edge, triggering the assertion
`std::abs(NumInsertions) <= 1 && "Unbalanced operations!"` in
LegalizeUpdates.

Fix by tracking which source blocks have already had DomTree updates
emitted, and skipping duplicates.

Added: 
    llvm/test/Transforms/CodeGenPrepare/X86/split-indirectbr-duplicate-pred.ll

Modified: 
    llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
index fd6b2562bee54..65bff2b878bda 100644
--- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
+++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp
@@ -416,6 +416,7 @@ bool llvm::SplitIndirectBrCriticalEdges(Function &F,
 
     BlockFrequency BlockFreqForDirectSucc;
     SmallVector<DominatorTree::UpdateType, 8> DTUpdates;
+    SmallPtrSet<BasicBlock *, 8> SeenSrcs;
     if (DTU)
       DTUpdates.reserve(OtherPreds.size() * 2 + 1);
     for (BasicBlock *Pred : OtherPreds) {
@@ -426,7 +427,10 @@ bool llvm::SplitIndirectBrCriticalEdges(Function &F,
       if (ShouldUpdateAnalysis)
         BlockFreqForDirectSucc += BFI->getBlockFreq(Src) *
             BPI->getEdgeProbability(Src, DirectSucc);
-      if (DTU) {
+      // A predecessor may appear multiple times in OtherPreds (e.g., a CondBr
+      // with both targets pointing to the same block). Only emit one pair of
+      // DomTree updates per unique source.
+      if (DTU && SeenSrcs.insert(Src).second) {
         DTUpdates.push_back({DominatorTree::Insert, Src, DirectSucc});
         DTUpdates.push_back({DominatorTree::Delete, Src, Target});
       }

diff  --git a/llvm/test/Transforms/CodeGenPrepare/X86/split-indirectbr-duplicate-pred.ll b/llvm/test/Transforms/CodeGenPrepare/X86/split-indirectbr-duplicate-pred.ll
new file mode 100644
index 0000000000000..d2c9941198c1e
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/X86/split-indirectbr-duplicate-pred.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -S -mtriple=x86_64 < %s | FileCheck %s
+
+; Test that SplitIndirectBrCriticalEdges does not crash when a predecessor
+; block has a conditional branch with both targets pointing to the same
+; destination (producing duplicate entries in the predecessor list).
+
+
+define i32 @duplicate_pred_condbr(ptr %addr, i1 %cond) {
+; CHECK-LABEL: define i32 @duplicate_pred_condbr(
+; CHECK-SAME: ptr [[ADDR:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    indirectbr ptr [[ADDR]], [label %[[TARGET:.*]], label %[[COND_BB:.*]]]
+; CHECK:       [[COND_BB]]:
+; CHECK-NEXT:    br [[DOTSPLIT:label %.*]]
+; CHECK:       [[TARGET]]:
+; CHECK-NEXT:    br [[DOTSPLIT]]
+; CHECK:       [[_SPLIT:.*:]]
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 0, %[[TARGET]] ], [ 1, %[[COND_BB]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+;
+entry:
+  indirectbr ptr %addr, [label %target, label %cond.bb]
+
+cond.bb:
+  br i1 %cond, label %target, label %target
+
+target:
+  %result = phi i32 [ 0, %entry ], [ 1, %cond.bb ], [ 1, %cond.bb ]
+  ret i32 %result
+}


        


More information about the llvm-commits mailing list