blob: ebe67b8a8d49b8146aafa78baa2d141d92395f71 [file] [log] [blame]
// RUN: %target-sil-opt -enforce-exclusivity=checked -enable-sil-verify-all %s -licm | %FileCheck %s
sil_stage canonical
import Builtin
import Swift
struct X {
@_hasStorage var i: Int64 { get set }
init(i: Int64)
init()
}
var globalX: X
sil_global hidden @globalX : $X
var globalY: X
sil_global hidden @globalY : $X
sil hidden_external [global_init] @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
// public func hoist_access_with_conflict() {
// Tests Hoisting of begin/end access when there's a "sandwiched" unidentified access
//
// CHECK-LABEL: sil @hoist_access_with_conflict : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: [[BEGIN:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*X
// CHECK-NEXT: br bb1
// CHECK: apply
// CHECK: load
// CHECK: cond_br
// CHECK: bb2
// CHECK: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'hoist_access_with_conflict'
sil @hoist_access_with_conflict : $@convention(thin) () -> () {
bb0:
%0 = global_addr @globalX: $*X
%u0 = function_ref @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%u3 = begin_access [read] [dynamic] %0 : $*X
%u1 = apply %u0() : $@convention(thin) () -> Builtin.RawPointer
%u4 = load %u3 : $*X
end_access %u3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func dont_hoist_access_with_conflict() {
// Tests *not* hoisting begin/end access when there's an unidentified access not protected by them
//
// CHECK-LABEL: sil @dont_hoist_access_with_conflict : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: br bb1
// CHECK: apply
// CHECK-NEXT: [[BEGIN:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*X
// CHECK-NEXT: load
// CHECK-NEXT: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'dont_hoist_access_with_conflict'
sil @dont_hoist_access_with_conflict : $@convention(thin) () -> () {
bb0:
%0 = global_addr @globalX: $*X
%u0 = function_ref @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%u1 = apply %u0() : $@convention(thin) () -> Builtin.RawPointer
%u3 = begin_access [read] [dynamic] %0 : $*X
%u4 = load %u3 : $*X
end_access %u3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func hoist_access_with_may_release() {
// Tests Hoisting of begin/end access when there's a "sandwiched" MayRelease instruction
//
// CHECK-LABEL: sil @hoist_access_with_may_release : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: [[BEGIN:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*X
// CHECK-NEXT: br bb1
// CHECK: apply
// CHECK: load
// CHECK: cond_br
// CHECK: bb2
// CHECK: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'hoist_access_with_may_release'
sil @hoist_access_with_may_release : $@convention(thin) () -> () {
bb0:
%alloc = alloc_box ${ var Int32 }, var, name "y"
%0 = global_addr @globalX: $*X
%u0 = function_ref @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%u3 = begin_access [read] [dynamic] %0 : $*X
%u1 = apply %u0() : $@convention(thin) () -> Builtin.RawPointer
%u4 = load %u3 : $*X
strong_release %alloc : ${ var Int32 }
end_access %u3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func dont_hoist_access_with_may_release() {
// Tests *not* hoisting begin/end access when there's a MayRelease not protected by them
//
// CHECK-LABEL: sil @dont_hoist_access_with_may_release : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: br bb1
// CHECK: [[BEGIN:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*X
// CHECK-NEXT: apply
// CHECK-NEXT: load
// CHECK-NEXT: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'dont_hoist_access_with_may_release'
sil @dont_hoist_access_with_may_release : $@convention(thin) () -> () {
bb0:
%alloc = alloc_box ${ var Int32 }, var, name "y"
%0 = global_addr @globalX: $*X
%u0 = function_ref @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%u3 = begin_access [read] [dynamic] %0 : $*X
%u1 = apply %u0() : $@convention(thin) () -> Builtin.RawPointer
%u4 = load %u3 : $*X
end_access %u3 : $*X
strong_release %alloc : ${ var Int32 }
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func hoist_access_static() {
// Tests Hoisting of begin/end access when there's a static access
//
// CHECK-LABEL: sil @hoist_access_static : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: [[BEGIN:%.*]] = begin_access [read] [static] [[GLOBAL]] : $*X
// CHECK-NEXT: br bb1
// CHECK: apply
// CHECK: load
// CHECK: cond_br
// CHECK: bb2
// CHECK: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'hoist_access_static'
sil @hoist_access_static : $@convention(thin) () -> () {
bb0:
%0 = global_addr @globalX: $*X
%u0 = function_ref @globalAddressor : $@convention(thin) () -> Builtin.RawPointer
br bb1
bb1:
%u3 = begin_access [read] [static] %0 : $*X
%u1 = apply %u0() : $@convention(thin) () -> Builtin.RawPointer
%u4 = load %u3 : $*X
end_access %u3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func hoist_access_static_and_dynamic() {
// Tests Hoisting of begin/end access when there's a static and distinct dynamic access
//
// CHECK-LABEL: sil @hoist_access_static_and_dynamic : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: [[GLOBALY:%.*]] = global_addr @globalY : $*X
// CHECK: [[BEGIN:%.*]] = begin_access [read] [static] [[GLOBAL]] : $*X
// CHECK: [[BEGINY:%.*]] = begin_access [read] [dynamic] [[GLOBALY]] : $*X
// CHECK-NEXT: br bb1
// CHECK: load
// CHECK: load
// CHECK: cond_br
// CHECK: bb2
// CHECK: end_access [[BEGINY]]
// CHECK: end_access [[BEGIN]]
// CHECK-LABEL: } // end sil function 'hoist_access_static_and_dynamic'
sil @hoist_access_static_and_dynamic : $@convention(thin) () -> () {
bb0:
%0 = global_addr @globalX: $*X
%1 = global_addr @globalY: $*X
br bb1
bb1:
%x3 = begin_access [read] [static] %0 : $*X
%x4 = load %x3 : $*X
end_access %x3 : $*X
%y3 = begin_access [read] [dynamic] %1 : $*X
%y4 = load %y3 : $*X
end_access %y3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}
// public func dont_hoist_access_static_and_dynamic() {
// Tests bailing out when there's a static and non-distinct dynamic access
//
// CHECK-LABEL: sil @dont_hoist_access_static_and_dynamic : $@convention(thin) () -> () {
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
// CHECK: [[GLOBALX:%.*]] = global_addr @globalX : $*X
// CHECK-NEXT: br bb1
// CHECK: [[BEGIN:%.*]] = begin_access [read] [static] [[GLOBAL]] : $*X
// CHECK-NEXT: load
// CHECK: end_access [[BEGIN]]
// CHECK: [[BEGINX:%.*]] = begin_access [read] [dynamic] [[GLOBALX]] : $*X
// CHECK-NEXT: load
// CHECK: end_access [[BEGINX]]
// CHECK: cond_br
// CHECK: bb2
// CHECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function 'dont_hoist_access_static_and_dynamic'
sil @dont_hoist_access_static_and_dynamic : $@convention(thin) () -> () {
bb0:
%0 = global_addr @globalX: $*X
%1 = global_addr @globalX: $*X
br bb1
bb1:
%x3 = begin_access [read] [static] %0 : $*X
%x4 = load %x3 : $*X
end_access %x3 : $*X
%y3 = begin_access [read] [dynamic] %1 : $*X
%y4 = load %y3 : $*X
end_access %y3 : $*X
cond_br undef, bb1, bb2
bb2:
%10 = tuple ()
return %10 : $()
}