mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
271 lines
5.6 KiB
LLVM
271 lines
5.6 KiB
LLVM
;
|
|
; This file is distributed under the MIT License. See LICENSE.md for details.
|
|
;
|
|
|
|
; RUN: %revngopt %s -enforce-single-exit -S -o - | FileCheck %s
|
|
|
|
; function tags metadata needed for all the tests
|
|
declare !revng.tags !0 void @scope_closer(ptr)
|
|
declare !revng.tags !1 void @goto_block()
|
|
!0 = !{!"marker", !"scope-closer"}
|
|
!1 = !{!"marker", !"goto-block"}
|
|
|
|
; two trivial exits test
|
|
|
|
define void @f() {
|
|
block_a:
|
|
br i1 undef, label %block_b, label %block_c
|
|
|
|
block_b:
|
|
ret void
|
|
|
|
block_c:
|
|
br i1 undef, label %block_b, label %block_d
|
|
|
|
block_d:
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @f
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_c
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_d
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@f, %block_b))
|
|
; CHECK-NEXT: ret void
|
|
|
|
; one trivial, one non-trivial exit test
|
|
|
|
define void @g() {
|
|
block_a:
|
|
br i1 undef, label %block_b, label %block_c
|
|
|
|
block_b:
|
|
ret void
|
|
|
|
block_c:
|
|
br label %block_d
|
|
|
|
block_d:
|
|
br label %block_c
|
|
}
|
|
|
|
; CHECK-LABEL: define void @g
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_c
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: br label %block_d
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@g, %block_b))
|
|
; CHECK-NEXT: br label %block_c
|
|
|
|
; one trivial, one non-trivial exit (self loop) test
|
|
|
|
define void @h() {
|
|
block_a:
|
|
br i1 undef, label %block_b, label %block_c
|
|
|
|
block_b:
|
|
ret void
|
|
|
|
block_c:
|
|
br label %block_c
|
|
}
|
|
|
|
; CHECK-LABEL: define void @h
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_c
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@h, %block_b))
|
|
; CHECK-NEXT: br label %block_c
|
|
|
|
; two trivial exit, with one scope_closer edge already present test
|
|
|
|
define void @i() {
|
|
block_a:
|
|
br i1 undef, label %block_b, label %block_c
|
|
|
|
block_b:
|
|
ret void
|
|
|
|
block_c:
|
|
call void @scope_closer(ptr blockaddress(@i, %block_b))
|
|
br label %block_d
|
|
|
|
block_d:
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @i
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_c
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@i, %block_b))
|
|
; CHECK-NEXT: br label %block_d
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@i, %block_b))
|
|
; CHECK-NEXT: ret void
|
|
|
|
; SCC composed by a `scope_closer` edge test
|
|
|
|
define void @l() {
|
|
block_a:
|
|
br i1 undef, label %block_c, label %block_b
|
|
|
|
block_b:
|
|
br i1 undef, label %block_e, label %block_d
|
|
|
|
block_c:
|
|
call void @scope_closer(ptr blockaddress(@l, %block_d))
|
|
unreachable
|
|
|
|
block_d:
|
|
br label %block_c
|
|
|
|
block_e:
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @l
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_c, label %block_b
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: br i1 undef, label %block_e, label %block_d
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@l, %block_d))
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@l, %block_e))
|
|
; CHECK-NEXT: br label %block_c
|
|
; CHECK: block_e:
|
|
; CHECK-NEXT: ret void
|
|
|
|
; no trivial exit, one non-trivial exit
|
|
|
|
define void @m() {
|
|
block_a:
|
|
br label %block_b
|
|
|
|
block_b:
|
|
br label %block_c
|
|
|
|
block_c:
|
|
br label %block_b
|
|
}
|
|
|
|
; CHECK-LABEL: define void @m
|
|
; CHECK: new_entry_block:
|
|
; CHECK-NEXT: br i1 true, label %block_a, label %sink_block
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br label %block_b
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: br label %block_c
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@m, %sink_block))
|
|
; CHECK-NEXT: br label %block_b
|
|
; CHECK: sink_block:
|
|
; CHECK-NEXT: unreachable
|
|
|
|
; two trivial exits
|
|
|
|
define void @n() {
|
|
block_a:
|
|
br i1 true, label %block_b, label %block_d
|
|
|
|
block_b:
|
|
br label %block_c
|
|
|
|
block_c:
|
|
br label %block_b
|
|
|
|
block_d:
|
|
br label %block_e
|
|
|
|
block_e:
|
|
br label %block_d
|
|
}
|
|
|
|
; CHECK-LABEL: define void @n
|
|
; CHECK: new_entry_block:
|
|
; CHECK-NEXT: br i1 true, label %block_a, label %sink_block
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 true, label %block_b, label %block_d
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: br label %block_c
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@n, %sink_block))
|
|
; CHECK-NEXT: br label %block_b
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: br label %block_e
|
|
; CHECK: block_e:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@n, %sink_block))
|
|
; CHECK-NEXT: br label %block_d
|
|
; CHECK: sink_block:
|
|
; CHECK-NEXT: unreachable
|
|
|
|
; one trivial exit, no modification test
|
|
|
|
define void @o() {
|
|
block_a:
|
|
br i1 undef, label %block_b, label %block_c
|
|
|
|
block_b:
|
|
br label %block_d
|
|
|
|
block_c:
|
|
br label %block_d
|
|
|
|
block_d:
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @o
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_c
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: br label %block_d
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: br label %block_d
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: ret void
|
|
|
|
; two nested sccs
|
|
|
|
define void @p() {
|
|
block_a:
|
|
br label %block_b
|
|
|
|
block_b:
|
|
br label %block_c
|
|
|
|
block_c:
|
|
br i1 undef, label %block_b, label %block_d
|
|
|
|
block_d:
|
|
br label %block_b
|
|
}
|
|
|
|
; CHECK-LABEL: define void @p
|
|
; CHECK: new_entry_block:
|
|
; CHECK-NEXT: br i1 true, label %block_a, label %sink_block
|
|
; CHECK: block_a:
|
|
; CHECK-NEXT: br label %block_b
|
|
; CHECK: block_b:
|
|
; CHECK-NEXT: br label %block_c
|
|
; CHECK: block_c:
|
|
; CHECK-NEXT: br i1 undef, label %block_b, label %block_d
|
|
; CHECK: block_d:
|
|
; CHECK-NEXT: call void @scope_closer(ptr blockaddress(@p, %sink_block))
|
|
; CHECK-NEXT: br label %block_b
|
|
; CHECK: sink_block:
|
|
; CHECK-NEXT: unreachable
|