Skip to content

Commit c9a3ab2

Browse files
authored
[AMDGPU][UnifyLoopExits] Fix duplicate successor handling (#170759)
Fixes llvm/llvm-project#170730 Maybe I can also come up with a more elegant solution. But I think it wouldn't make a lot of sense trying to avoid multiple "fake" target blocks. Would require a mapping between original and fake target blocks...
1 parent 4709018 commit c9a3ab2

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,9 +755,11 @@ BasicBlock *llvm::SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ,
755755
updateCycleLoopInfo<CycleInfo, Cycle>(CI, CallBrBlock, CallBrTarget, Succ);
756756
if (DTU) {
757757
DTU->applyUpdates({{DominatorTree::Insert, CallBrBlock, CallBrTarget}});
758-
if (DTU->getDomTree().dominates(CallBrBlock, Succ))
759-
DTU->applyUpdates({{DominatorTree::Delete, CallBrBlock, Succ},
760-
{DominatorTree::Insert, CallBrTarget, Succ}});
758+
if (DTU->getDomTree().dominates(CallBrBlock, Succ)) {
759+
if (!is_contained(successors(CallBrBlock), Succ))
760+
DTU->applyUpdates({{DominatorTree::Delete, CallBrBlock, Succ}});
761+
DTU->applyUpdates({{DominatorTree::Insert, CallBrTarget, Succ}});
762+
}
761763
}
762764

763765
return CallBrTarget;

llvm/test/Transforms/UnifyLoopExits/basic.ll

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ define void @loop_1_callbr(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
6161
; CHECK-NEXT: br label [[B:%.*]]
6262
; CHECK: B:
6363
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
64-
; CHECK-NEXT: to label [[C:%.*]] [label %B.target.E]
64+
; CHECK-NEXT: to label [[C:%.*]] [label [[B_TARGET_E:%.*]]]
6565
; CHECK: C:
6666
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])
67-
; CHECK-NEXT: to label [[D:%.*]] [label %C.target.F]
67+
; CHECK-NEXT: to label [[D:%.*]] [label [[C_TARGET_F:%.*]]]
6868
; CHECK: D:
6969
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDD:%.*]])
70-
; CHECK-NEXT: to label [[A]] [label %D.target.F]
70+
; CHECK-NEXT: to label [[A]] [label [[D_TARGET_F:%.*]]]
7171
; CHECK: E:
7272
; CHECK-NEXT: br label [[EXIT:%.*]]
7373
; CHECK: F:
@@ -83,7 +83,7 @@ define void @loop_1_callbr(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
8383
; CHECK: D.target.F:
8484
; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
8585
; CHECK: loop.exit.guard:
86-
; CHECK-NEXT: [[GUARD_X:%.*]] = phi i1 [ true, [[B_TARGET_E:%.*]] ], [ false, [[C_TARGET_F:%.*]] ], [ false, [[D_TARGET_F:%.*]] ]
86+
; CHECK-NEXT: [[GUARD_X:%.*]] = phi i1 [ true, [[B_TARGET_E]] ], [ false, [[C_TARGET_F]] ], [ false, [[D_TARGET_F]] ]
8787
; CHECK-NEXT: br i1 [[GUARD_X]], label [[X:%.*]], label [[Y]]
8888
;
8989
entry:
@@ -175,13 +175,13 @@ define void @loop_2_callbr(i1 %PredA, i1 %PredB, i1 %PredC) {
175175
; CHECK-NEXT: br label [[A:%.*]]
176176
; CHECK: A:
177177
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
178-
; CHECK-NEXT: to label [[B:%.*]] [label %A.target.X]
178+
; CHECK-NEXT: to label [[B:%.*]] [label [[A_TARGET_X:%.*]]]
179179
; CHECK: B:
180180
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
181-
; CHECK-NEXT: to label [[C:%.*]] [label %B.target.Y]
181+
; CHECK-NEXT: to label [[C:%.*]] [label [[B_TARGET_Y:%.*]]]
182182
; CHECK: C:
183183
; CHECK-NEXT: callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])
184-
; CHECK-NEXT: to label [[D:%.*]] [label %C.target.Z]
184+
; CHECK-NEXT: to label [[D:%.*]] [label [[C_TARGET_Z:%.*]]]
185185
; CHECK: D:
186186
; CHECK-NEXT: br label [[A]]
187187
; CHECK: X:
@@ -199,7 +199,7 @@ define void @loop_2_callbr(i1 %PredA, i1 %PredB, i1 %PredC) {
199199
; CHECK: C.target.Z:
200200
; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
201201
; CHECK: loop.exit.guard:
202-
; CHECK-NEXT: [[GUARD_X:%.*]] = phi i1 [ true, [[A_TARGET_X:%.*]] ], [ false, [[B_TARGET_Y:%.*]] ], [ false, [[C_TARGET_Z:%.*]] ]
202+
; CHECK-NEXT: [[GUARD_X:%.*]] = phi i1 [ true, [[A_TARGET_X]] ], [ false, [[B_TARGET_Y]] ], [ false, [[C_TARGET_Z]] ]
203203
; CHECK-NEXT: [[GUARD_Y:%.*]] = phi i1 [ false, [[A_TARGET_X]] ], [ true, [[B_TARGET_Y]] ], [ false, [[C_TARGET_Z]] ]
204204
; CHECK-NEXT: br i1 [[GUARD_X]], label [[X:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
205205
; CHECK: loop.exit.guard1:
@@ -232,3 +232,30 @@ Z:
232232
exit:
233233
ret void
234234
}
235+
236+
; Test that UnifyLoopExits handles callbr with duplicate successors correctly.
237+
; The exit block appears twice as a successor of the callbr instruction.
238+
define void @callbr_duplicate_successors() {
239+
; CHECK-LABEL: @callbr_duplicate_successors(
240+
; CHECK-NEXT: entry:
241+
; CHECK-NEXT: br label [[LOOP:%.*]]
242+
; CHECK: loop:
243+
; CHECK-NEXT: callbr void asm sideeffect "", "!i,!i"()
244+
; CHECK-NEXT: to label [[LOOP_TARGET_EXIT:%.*]] [label [[LOOP]], label [[LOOP_TARGET_EXIT1:%.*]]]
245+
; CHECK: exit:
246+
; CHECK-NEXT: ret void
247+
; CHECK: loop.target.exit:
248+
; CHECK-NEXT: br label [[EXIT:%.*]]
249+
; CHECK: loop.target.exit1:
250+
; CHECK-NEXT: br label [[EXIT]]
251+
;
252+
entry:
253+
br label %loop
254+
255+
loop:
256+
callbr void asm sideeffect "", "!i,!i"()
257+
to label %exit [label %loop, label %exit]
258+
259+
exit:
260+
ret void
261+
}

0 commit comments

Comments
 (0)