Since D129288, callbr is allowed to have duplicate successors. This patch removes a limitation which prevents optimizations from actually producing such callbrs.
This is probably the riskiest of all the recent callbr changes, because code with incorrect assumptions might be lurking somewhere. I fixed the one case I encountered ahead of time in https://github.com/llvm/llvm-project/commit/
8201e3ef5c84561260218bc041209611aac690e3.
Reviewed By: nickdesaulniers
Differential Revision: https://reviews.llvm.org/D129997
Originally landed as
commit
08860f525a23 ("[Local] Allow creating callbr with duplicate successors")
Reverted in
commit
1cf6b93df168 ("Revert "[Local] Allow creating callbr with duplicate successors"")
}
}
- // We cannot fold the block if it's a branch to an already present callbr
- // successor because that creates duplicate successors.
- for (BasicBlock *PredBB : predecessors(BB)) {
- if (auto *CBI = dyn_cast<CallBrInst>(PredBB->getTerminator())) {
- if (Succ == CBI->getDefaultDest())
- return false;
- for (unsigned i = 0, e = CBI->getNumIndirectDests(); i != e; ++i)
- if (Succ == CBI->getIndirectDest(i))
- return false;
- }
- }
-
LLVM_DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);
SmallVector<DominatorTree::UpdateType, 32> Updates;
; CHECK-LABEL: <test3>:
; CHECK-LABEL: <$d.9>:
; CHECK-LABEL: <$x.10>:
-; CHECK-NEXT: b {{.*}} <$x.12+0x4>
+; CHECK-NEXT: b {{.*}} <$x.12>
; CHECK-LABEL: <$x.12>:
-; CHECK-NEXT: mov w0, wzr
; CHECK-NEXT: ldr x30, [sp], #16
; CHECK-NEXT: ret
define internal i1 @test3() {
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: callbr void asm sideeffect "", "!i"()
-; CHECK-NEXT: to label [[NORMAL:%.*]] [label %if.then2]
-; CHECK: normal:
-; CHECK-NEXT: br label [[IF_THEN2:%.*]]
+; CHECK-NEXT: to label [[IF_THEN2:%.*]] [label %if.then2]
; CHECK: if.end:
; CHECK-NEXT: [[CALL:%.*]] = call i32 @b()
; CHECK-NEXT: [[PHITMP:%.*]] = icmp ne i32 [[CALL]], 0
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -jump-threading -S | FileCheck %s
-; CHECK-ALL-LABEL: @func(
-
define i1 @func(i1 %arg, i32 %arg1, i1 %arg2) {
; CHECK-LABEL: @func(
; CHECK-NEXT: bb:
; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB7:%.*]], label [[BB4:%.*]]
; CHECK: bb4:
; CHECK-NEXT: callbr void asm sideeffect "", "!i"()
-; CHECK-NEXT: to label [[BB5:%.*]] [label %bb7.thr_comm]
-; CHECK: bb5:
-; CHECK-NEXT: br label [[BB7_THR_COMM:%.*]]
+; CHECK-NEXT: to label [[BB7_THR_COMM:%.*]] [label %bb7.thr_comm]
; CHECK: bb7.thr_comm:
; CHECK-NEXT: [[I91:%.*]] = xor i1 [[ARG2:%.*]], [[ARG]]
; CHECK-NEXT: br i1 [[I91]], label [[BB11:%.*]], label [[BB11]]
ret void
}
-; TODO: Can fold to a duplicate callbr destination.
define void @callbr_can_fold_to_duplicate_dest1() {
; CHECK-LABEL: @callbr_can_fold_to_duplicate_dest1(
; CHECK-NEXT: entry:
; CHECK-NEXT: callbr void asm sideeffect "", "!i"()
-; CHECK-NEXT: to label [[BB2:%.*]] [label %common.ret]
+; CHECK-NEXT: to label [[COMMON_RET:%.*]] [label %common.ret]
; CHECK: common.ret:
; CHECK-NEXT: ret void
-; CHECK: bb2:
-; CHECK-NEXT: br label [[COMMON_RET:%.*]]
;
entry:
callbr void asm sideeffect "", "!i"()
ret void
}
-; TODO: Can fold to a duplicate callbr destination.
define void @callbr_can_fold_to_duplicate_dest2() {
; CHECK-LABEL: @callbr_can_fold_to_duplicate_dest2(
; CHECK-NEXT: entry:
; CHECK-NEXT: callbr void asm sideeffect "", "!i,!i"()
-; CHECK-NEXT: to label [[COMMON_RET:%.*]] [label [[BB2:%.*]], label %bb3]
+; CHECK-NEXT: to label [[COMMON_RET:%.*]] [label [[COMMON_RET]], label %common.ret]
; CHECK: common.ret:
; CHECK-NEXT: ret void
-; CHECK: bb2:
-; CHECK-NEXT: br label [[COMMON_RET]]
-; CHECK: bb3:
-; CHECK-NEXT: br label [[COMMON_RET]]
;
entry:
callbr void asm sideeffect "", "!i,!i"()
; CHECK-LABEL: @callbr(
; CHECK-NEXT: entry:
; CHECK-NEXT: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
-; CHECK-NEXT: to label [[IF_END:%.*]] [label %target]
-; CHECK: target:
-; CHECK-NEXT: br label [[IF_END]]
+; CHECK-NEXT: to label [[IF_END:%.*]] [label %if.end]
; CHECK: if.end:
; CHECK-NEXT: ret void
;