llvm-project/llvm/test/Transforms/SimplifyCFG/callbr-destinations.ll
Nick Desaulniers 094190c2f5 [llvm][CallBrPrepare] add llvm.callbr.landingpad intrinsic
Insert a new intrinsic call after splitting critical edges, and verify
it. Later commits will update the SSA values to use this new value along
indirect branches rather than the callbr's value, and have SelectionDAG
consume this new value.

Part 2b of
https://discourse.llvm.org/t/rfc-syncing-asm-goto-with-outputs-with-gcc/65453/8.

Reviewed By: efriedma, jyknight

Differential Revision: https://reviews.llvm.org/D139883
2023-02-16 17:58:33 -08:00

107 lines
3.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -passes="simplifycfg<sink-common-insts>" \
; RUN: -simplifycfg-require-and-preserve-domtree=1 | FileCheck %s
define void @callbr_duplicate_dest() {
; CHECK-LABEL: @callbr_duplicate_dest(
; CHECK-NEXT: entry:
; CHECK-NEXT: callbr void asm sideeffect "", "!i"()
; CHECK-NEXT: to label [[BB:%.*]] [label %bb]
; CHECK: bb:
; CHECK-NEXT: ret void
;
entry:
callbr void asm sideeffect "", "!i"()
to label %bb [label %bb]
bb:
ret void
}
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 [[COMMON_RET:%.*]] [label %common.ret]
; CHECK: common.ret:
; CHECK-NEXT: ret void
;
entry:
callbr void asm sideeffect "", "!i"()
to label %bb2 [label %bb1]
bb1:
ret void
bb2:
ret void
}
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 [[COMMON_RET]], label %common.ret]
; CHECK: common.ret:
; CHECK-NEXT: ret void
;
entry:
callbr void asm sideeffect "", "!i,!i"()
to label %bb1 [label %bb2, label %bb3]
bb1:
ret void
bb2:
ret void
bb3:
ret void
}
; Validate that callbr landingpad intrinsics do not get merged (via the
; IntrNoMerge attribute).
define i32 @callbr_landingpad_nomerge() {
; CHECK-LABEL: @callbr_landingpad_nomerge(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[OUT:%.*]] = callbr i32 asm "# $0", "=r,!i"()
; CHECK-NEXT: to label [[DIRECT:%.*]] [label %entry.indirect_crit_edge]
; CHECK: entry.indirect_crit_edge:
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT]])
; CHECK-NEXT: br label [[COMMON_RET:%.*]]
; CHECK: direct:
; CHECK-NEXT: [[OUT2:%.*]] = callbr i32 asm "# $0", "=r,!i"()
; CHECK-NEXT: to label [[COMMON_RET]] [label %direct.indirect_crit_edge]
; CHECK: direct.indirect_crit_edge:
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.callbr.landingpad.i32(i32 [[OUT2]])
; CHECK-NEXT: br label [[COMMON_RET]]
; CHECK: common.ret:
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[DIRECT]] ], [ [[TMP0]], [[ENTRY_INDIRECT_CRIT_EDGE:%.*]] ], [ [[TMP1]], [[DIRECT_INDIRECT_CRIT_EDGE:%.*]] ]
; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
;
entry:
%out = callbr i32 asm "# $0", "=r,!i"()
to label %direct [label %entry.indirect_crit_edge]
entry.indirect_crit_edge:
%0 = call i32 @llvm.callbr.landingpad.i32(i32 %out)
br label %indirect
direct:
%out2 = callbr i32 asm "# $0", "=r,!i"()
to label %direct2 [label %direct.indirect_crit_edge]
direct.indirect_crit_edge:
%1 = call i32 @llvm.callbr.landingpad.i32(i32 %out2)
br label %indirect
direct2:
ret i32 0
indirect:
%out3 = phi i32 [ %0, %entry.indirect_crit_edge ], [ %1, %direct.indirect_crit_edge ]
ret i32 %out3
}
declare i32 @llvm.callbr.landingpad.i32(i32)