mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1410 lines
51 KiB
Plaintext
1410 lines
51 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -allocbox-to-stack -enable-copy-propagation=requested-passes-only | %FileCheck %s
|
|
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
|
|
struct Int {
|
|
var _value: Builtin.Int64
|
|
}
|
|
|
|
struct Bool {
|
|
var _value: Builtin.Int1
|
|
}
|
|
|
|
protocol Error {}
|
|
|
|
class C {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @simple_promotion
|
|
sil [ossa] @simple_promotion : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
return %3 : $Int
|
|
// CHECK: alloc_stack
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: return
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @double_project_box
|
|
sil [ossa] @double_project_box : $@convention(thin) (Int) -> (Int, Int) {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = load [trivial] %1a : $*Int
|
|
|
|
%1b = project_box %1 : ${ var Int }, 0
|
|
%3b = load [trivial] %1b : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple (%3 : $Int, %3b : $Int)
|
|
return %r : $(Int, Int)
|
|
|
|
// CHECK: alloc_stack
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK-NOT: project_box
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: return
|
|
}
|
|
// CHECK-LABEL: sil [ossa] @init_var
|
|
sil [ossa] @init_var : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
return %3 : $Int
|
|
|
|
// CHECK: %1 = alloc_stack
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK: dealloc_stack %1 : $*Int
|
|
// CHECK: return
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @multi_destroy_value
|
|
sil [ossa] @multi_destroy_value : $@convention(thin) () -> Int {
|
|
bb0:
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = mark_uninitialized [rootself] %1 : ${ var Int }
|
|
%2 = project_box %1a : ${ var Int }, 0
|
|
%3 = load [trivial] %2 : $*Int
|
|
%x = copy_value %1a : ${ var Int }
|
|
destroy_value %1a : ${ var Int }
|
|
br bb1
|
|
|
|
bb1:
|
|
destroy_value %x : ${ var Int }
|
|
return %3 : $Int
|
|
|
|
// CHECK: %0 = alloc_stack
|
|
// CHECK: bb1:
|
|
// CHECK: dealloc_stack %0 : $*Int
|
|
// CHECK: return
|
|
}
|
|
|
|
struct TestStruct {
|
|
var Elt : Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @struct_tuple_element_addr
|
|
sil [ossa] @struct_tuple_element_addr : $@convention(thin) (Int) -> Int {
|
|
bb1(%0 : $Int):
|
|
// CHECK-DAG: [[STRUCT:%.*]] = alloc_stack $TestStruct
|
|
// CHECK-DAG: [[TUPLE:%.*]] = alloc_stack $(Int, Int)
|
|
%1 = alloc_box ${ var TestStruct }
|
|
%1a = project_box %1 : ${ var TestStruct }, 0
|
|
%a = alloc_box ${ var (Int, Int) }
|
|
%aa = project_box %a : ${ var (Int, Int) }, 0
|
|
|
|
%2 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
|
|
store %0 to [trivial] %2 : $*Int
|
|
|
|
%b = tuple_element_addr %aa : $*(Int, Int), 0
|
|
store %0 to [trivial] %b : $*Int
|
|
|
|
%6 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
|
|
%7 = load [trivial] %6 : $*Int
|
|
destroy_value %a : ${ var (Int, Int) }
|
|
destroy_value %1 : ${ var TestStruct }
|
|
|
|
return %7 : $Int
|
|
|
|
// CHECK-DAG: dealloc_stack [[STRUCT]]
|
|
// CHECK-DAG: dealloc_stack [[TUPLE]]
|
|
// CHECK: return
|
|
}
|
|
|
|
sil [ossa] @callee : $@convention(thin) (@inout Int) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @inout_nocapture
|
|
sil [ossa] @inout_nocapture : $@convention(thin) () -> Int {
|
|
bb0:
|
|
// CHECK: alloc_stack
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
%6 = function_ref @callee : $@convention(thin) (@inout Int) -> ()
|
|
%7 = apply %6(%1a) : $@convention(thin) (@inout Int) -> ()
|
|
%8 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%10 = address_to_pointer %1a : $*Int to $Builtin.RawPointer
|
|
%11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int
|
|
%12 = load [trivial] %11 : $*Int
|
|
return %8 : $Int
|
|
// CHECK: return
|
|
}
|
|
|
|
protocol P {
|
|
}
|
|
|
|
sil [ossa] @returns_protocol : $@convention(thin) () -> @out P
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_indirect_return
|
|
sil [ossa] @test_indirect_return : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: alloc_stack
|
|
%1 = function_ref @returns_protocol : $@convention(thin) () -> @out P
|
|
%2 = alloc_box ${ var P }
|
|
%2a = project_box %2 : ${ var P }, 0
|
|
%3 = apply %1(%2a) : $@convention(thin) () -> @out P
|
|
destroy_value %2 : ${ var P }
|
|
%0 = tuple ()
|
|
return %0 : $()
|
|
// CHECK: return
|
|
}
|
|
|
|
class SomeClass {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @class_promotion
|
|
sil [ossa] @class_promotion : $@convention(thin) (@owned SomeClass) -> @owned SomeClass {
|
|
bb0(%0 : @owned $SomeClass):
|
|
%1 = alloc_box ${ var SomeClass }
|
|
%1a = project_box %1 : ${ var SomeClass }, 0
|
|
store %0 to [init] %1a : $*SomeClass
|
|
%3 = load [copy] %1a : $*SomeClass
|
|
destroy_value %1 : ${ var SomeClass }
|
|
return %3 : $SomeClass
|
|
|
|
// CHECK: %1 = alloc_stack
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK: destroy_addr {{.*}} : $*SomeClass
|
|
// CHECK: return
|
|
}
|
|
|
|
protocol LogicValue {
|
|
func getLogicValue() -> Bool
|
|
}
|
|
|
|
// CHECK-LABEL: @protocols
|
|
sil [ossa] @protocols : $@convention(thin) (@in LogicValue, @thin Bool.Type) -> Bool {
|
|
bb0(%0 : $*LogicValue, %1 : $@thin Bool.Type):
|
|
%2 = alloc_box ${ var LogicValue }
|
|
%2a = project_box %2 : ${ var LogicValue }, 0
|
|
// CHECK: %2 = alloc_stack $any LogicValue
|
|
copy_addr [take] %0 to [init] %2a : $*LogicValue
|
|
%6 = open_existential_addr mutable_access %2a : $*LogicValue to $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self
|
|
%7 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self, #LogicValue.getLogicValue, %6 : $*@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self : $@convention(witness_method: LogicValue) <T: LogicValue> (@in_guaranteed T) -> Bool
|
|
%8 = apply %7<@opened("01234567-89ab-cdef-0123-000000000000", LogicValue) Self>(%6) : $@convention(witness_method: LogicValue) <T: LogicValue> (@in_guaranteed T) -> Bool
|
|
destroy_value %2 : ${ var LogicValue }
|
|
// CHECK: destroy_addr %2 : $*any LogicValue
|
|
// CHECK-NEXT: dealloc_stack %2 : $*any LogicValue
|
|
// CHECK-NEXT: return
|
|
return %8 : $Bool
|
|
}
|
|
|
|
|
|
// Generics test, which is address-only.
|
|
class Generic<T> {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dealloc_box_test
|
|
sil [ossa] @dealloc_box_test : $@convention(thin) <T> () -> () {
|
|
bb0: // CHECK-NEXT: bb0:
|
|
// CHECK-NEXT: alloc_stack
|
|
%1 = alloc_box $<τ_0_0> { var Generic<τ_0_0> } <T>
|
|
dealloc_box %1 : $<τ_0_0> { var Generic<τ_0_0> } <T>
|
|
|
|
%0 = tuple () // CHECK: tuple ()
|
|
return %0 : $()
|
|
// CHECK: return
|
|
}
|
|
|
|
|
|
enum SomeUnion {
|
|
case x(Int)
|
|
case y(SomeClass)
|
|
}
|
|
|
|
|
|
|
|
sil [ossa] @$s1t9SomeUnionO1yfMS0_FCS_9SomeClassS0_ : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion
|
|
sil [ossa] @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass
|
|
|
|
// CHECK-LABEL: sil [ossa] @union_test
|
|
sil [ossa] @union_test : $@convention(thin) () -> () {
|
|
bb0:
|
|
// CHECK: [[UNION:%.*]] = alloc_stack
|
|
%1 = alloc_box ${ var SomeUnion }
|
|
%1a = project_box %1 : ${ var SomeUnion }, 0
|
|
%2 = function_ref @$s1t9SomeUnionO1yfMS0_FCS_9SomeClassS0_ : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion // user: %7
|
|
%3 = metatype $@thin SomeUnion.Type
|
|
%4 = function_ref @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass // user: %6
|
|
%5 = metatype $@thick SomeClass.Type
|
|
%6 = apply %4(%5) : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass
|
|
%7 = apply %2(%6, %3) : $@convention(thin) (@owned SomeClass, @thin SomeUnion.Type) -> @owned SomeUnion
|
|
store %7 to [init] %1a : $*SomeUnion
|
|
destroy_value %1 : ${ var SomeUnion }
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
// CHECK: dealloc_stack [[UNION]]
|
|
// CHECK: [[T0:%.*]] = tuple ()
|
|
// CHECK-NEXT: return [[T0]] : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @multiple_destroy_test
|
|
sil [ossa] @multiple_destroy_test : $@convention(thin) (Bool) -> Bool {
|
|
bb0(%0 : $Bool):
|
|
%1 = alloc_box ${ var Bool }
|
|
%1a = project_box %1 : ${ var Bool }, 0
|
|
store %0 to [trivial] %1a : $*Bool
|
|
%2 = copy_value %1 : ${ var Bool }
|
|
%3 = copy_value %1 : ${ var Bool }
|
|
%5 = tuple ()
|
|
%6 = load [trivial] %1a : $*Bool
|
|
destroy_value %3 : ${ var Bool }
|
|
destroy_value %2 : ${ var Bool }
|
|
destroy_value %1 : ${ var Bool }
|
|
return %6 : $Bool
|
|
|
|
// CHECK: alloc_stack $Bool
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return
|
|
}
|
|
|
|
// Make sure that we can promote this box and dealloc_stack
|
|
// on each path.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @box_reachable_from_destroy_test
|
|
sil [ossa] @box_reachable_from_destroy_test : $@convention(thin) () -> () {
|
|
bb0:
|
|
br bb1
|
|
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: alloc_stack
|
|
bb1:
|
|
%1 = alloc_box ${ var Bool }
|
|
cond_br undef, bb2, bb3
|
|
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: dealloc_stack
|
|
bb2:
|
|
destroy_value %1 : ${ var Bool }
|
|
br bb1
|
|
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: dealloc_stack
|
|
bb3:
|
|
destroy_value %1 : ${ var Bool }
|
|
%2 = tuple ()
|
|
// CHECK: return
|
|
return %2 : $()
|
|
}
|
|
|
|
|
|
|
|
sil [ossa] @useSomeClass : $@convention(thin) (@owned SomeClass) -> ()
|
|
|
|
|
|
// <rdar://problem/16382973> DI misses destroy_addr because allocbox_to_stack isn't preserving mark_uninitialized invariants
|
|
// When allocbox_to_stack promotes the box, it should rewrite the multiple
|
|
// destroy_values into destroy_addr/dealloc_stack pairs. However, it needs to
|
|
// make sure to use the MUI result for the destroy addr.
|
|
|
|
public protocol My_Incrementable { }
|
|
|
|
extension Int : My_Incrementable { }
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_mui
|
|
sil [ossa] @test_mui : $@convention(thin) (Builtin.Int1) -> () {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%2 = alloc_box ${ var SomeClass }
|
|
%2a = mark_uninitialized [var] %2 : ${ var SomeClass }
|
|
%3 = project_box %2a : ${ var SomeClass }, 0
|
|
// CHECK: [[STACK:%[0-9]+]] = alloc_stack
|
|
// CHECK: [[MUI:%[0-9]+]] = mark_uninitialized
|
|
cond_br %0, bb1, bb3
|
|
|
|
bb1:
|
|
%7 = function_ref @$s1t9SomeClassCCfMS0_FT_S0_ : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass // user: %6
|
|
%8 = metatype $@thick SomeClass.Type
|
|
%9 = apply %7(%8) : $@convention(thin) (@thick SomeClass.Type) -> @owned SomeClass
|
|
|
|
assign %9 to %3 : $*SomeClass
|
|
%11 = function_ref @useSomeClass : $@convention(thin) (@owned SomeClass) -> ()
|
|
%12 = load [copy] %3 : $*SomeClass
|
|
%14 = apply %11(%12) : $@convention(thin) (@owned SomeClass) -> ()
|
|
|
|
destroy_value %2a : ${ var SomeClass }
|
|
// CHECK: destroy_addr [[MUI]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK]]
|
|
br bb2
|
|
|
|
// CHECK: bb2
|
|
bb2:
|
|
%17 = tuple ()
|
|
// CHECK: return
|
|
return %17 : $()
|
|
|
|
bb3:
|
|
destroy_value %2a : ${ var SomeClass }
|
|
// CHECK: destroy_addr [[MUI]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK]]
|
|
br bb2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s6struct5apply1fS2iyc_tF
|
|
// struct.apply (f : () -> Swift.Int) -> Swift.Int
|
|
sil [ossa] @$s6struct5apply1fS2iyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> Int {
|
|
bb0(%0 : @owned $@callee_owned () -> Int):
|
|
debug_value %0 : $@callee_owned () -> Int, let, name "f" // id: %1
|
|
%1 = copy_value %0 : $@callee_owned () -> Int // id: %2
|
|
%3 = apply %1() : $@callee_owned () -> Int // user: %5
|
|
destroy_value %0 : $@callee_owned () -> Int // id: %4
|
|
return %3 : $Int // id: %5
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s6struct6escape1fSiycSiyc_tF
|
|
// struct.escape (f : () -> Swift.Int) -> () -> Swift.Int
|
|
sil [ossa] @$s6struct6escape1fSiycSiyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int {
|
|
bb0(%0 : @owned $@callee_owned () -> Int):
|
|
debug_value %0 : $@callee_owned () -> Int, let, name "f" // id: %1
|
|
return %0 : $@callee_owned () -> Int // id: %2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s6struct8useStack1tySi_tF
|
|
// struct.useStack (t : Swift.Int) -> ()
|
|
sil [ossa] @$s6struct8useStack1tySi_tF : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
debug_value %0 : $Int, let, name "t" // id: %1
|
|
// CHECK: alloc_stack
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>, var, name "s" // users: %3, %6, %7, %7, %9
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to [trivial] %2a : $*Int // id: %3
|
|
// function_ref struct.apply (f : () -> Swift.Int) -> Swift.Int
|
|
%4 = function_ref @$s6struct5apply1fS2iyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> Int // user: %8
|
|
// CHECK: [[FUNC:%[a-zA-Z0-9]+]] = function_ref @$s6struct8useStack1tySi_tFSiycfU_Tf0s_n
|
|
// function_ref struct.(useStack (t : Swift.Int) -> ()).(closure #1)
|
|
%5 = function_ref @$s6struct8useStack1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int // user: %7
|
|
%6 = copy_value %2 : $<τ_0_0> { var τ_0_0 } <Int> // id: %6
|
|
// CHECK: [[PA:%[a-zA-Z0-9]+]] = partial_apply [[FUNC]]
|
|
%7 = partial_apply %5(%6) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int // user: %8
|
|
%8 = apply %4(%7) : $@convention(thin) (@owned @callee_owned () -> Int) -> Int
|
|
destroy_value %2 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
%10 = tuple () // user: %11
|
|
return %10 : $() // id: %11
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_Tf0s_n
|
|
// CHECK-LABEL: sil private [transparent] [_semantics "sil.optimizer.delete_if_unused"] [ossa] @$s6struct8useStack1tySi_tFSiycfU_
|
|
// struct.(useStack (t : Swift.Int) -> ()).(closure #1)
|
|
sil private [transparent] [ossa] @$s6struct8useStack1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int {
|
|
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <Int>):
|
|
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
// function_ref Swift.++ @postfix <A : Swift._Incrementable>(x : @inout A) -> A
|
|
%2 = function_ref @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 // user: %4
|
|
%3 = alloc_stack $Int // users: %4, %5, %6
|
|
%4 = apply %2<Int>(%3, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0
|
|
%5 = load [trivial] %3 : $*Int // user: %8
|
|
dealloc_stack %3 : $*Int // id: %6
|
|
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Int> // id: %7
|
|
return %5 : $Int // id: %8
|
|
}
|
|
|
|
// Swift.++ @postfix <A : Swift._Incrementable>(x : @inout A) -> A
|
|
sil [transparent] @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s6struct6useBox1tySi_tF
|
|
// struct.useBox (t : Swift.Int) -> ()
|
|
sil [ossa] @$s6struct6useBox1tySi_tF : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
debug_value %0 : $Int, let, name "t" // id: %1
|
|
// CHECK: alloc_box
|
|
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>, var, name "s" // users: %3, %6, %7, %7, %10
|
|
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to [trivial] %2a : $*Int // id: %3
|
|
// function_ref struct.escape (f : () -> Swift.Int) -> () -> Swift.Int
|
|
%4 = function_ref @$s6struct6escape1fSiycSiyc_tF : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int // user: %8
|
|
// function_ref struct.(useBox (t : Swift.Int) -> ()).(closure #1)
|
|
%5 = function_ref @$s6struct6useBox1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int // user: %7
|
|
%6 = copy_value %2 : $<τ_0_0> { var τ_0_0 } <Int> // id: %6
|
|
%7 = partial_apply %5(%6) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int // user: %8
|
|
%8 = apply %4(%7) : $@convention(thin) (@owned @callee_owned () -> Int) -> @owned @callee_owned () -> Int // user: %9
|
|
%9 = apply %8() : $@callee_owned () -> Int
|
|
destroy_value %2 : $<τ_0_0> { var τ_0_0 } <Int> // id: %10
|
|
%11 = tuple () // user: %12
|
|
return %11 : $() // id: %12
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s6struct6useBox1tySi_tFSiycfU_
|
|
// struct.(useBox (t : Swift.Int) -> ()).(closure #1)
|
|
sil private [ossa] @$s6struct6useBox1tySi_tFSiycfU_ : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int {
|
|
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <Int>):
|
|
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
// function_ref Swift.++ @postfix <A : Swift._Incrementable>(x : @inout A) -> A
|
|
%2 = function_ref @_TFsoP2ppUs14_Incrementable__FT1xRQ__Q_ : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0 // user: %4
|
|
%3 = alloc_stack $Int // users: %4, %5, %6
|
|
%4 = apply %2<Int>(%3, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : My_Incrementable> (@inout τ_0_0) -> @out τ_0_0
|
|
%5 = load [trivial] %3 : $*Int // user: %8
|
|
dealloc_stack %3 : $*Int // id: %6
|
|
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Int> // id: %7
|
|
return %5 : $Int // id: %8
|
|
}
|
|
|
|
// CHECK-LABEL: sil @closure
|
|
sil @closure : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @no_final_destroy
|
|
sil [ossa] @no_final_destroy : $@convention(thin) (Int) -> Bool {
|
|
bb0(%0 : $Int):
|
|
// This is not destroyed, but the unreachable makes the verifier not trip.
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
// function_ref main.(newFoo (Swift.Int) -> Swift.Bool).(modify #1) (())()
|
|
%3 = function_ref @closure : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
|
|
%4 = copy_value %1 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
%5 = partial_apply %3(%4) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
|
|
%6 = copy_value %5 : $@callee_owned () -> ()
|
|
apply %6() : $@callee_owned () -> ()
|
|
destroy_value %5 : $@callee_owned () -> ()
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_copy_and_borrow_of_closure
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: alloc_stack
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: } // end sil function 'test_copy_and_borrow_of_closure'
|
|
sil [ossa] @test_copy_and_borrow_of_closure : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
// This is not destroyed, but the unreachable makes the verifier not trip.
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = function_ref @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
|
|
%4 = copy_value %1 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
%5 = partial_apply %3(%4) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> ()
|
|
%6 = begin_borrow %5 : $@callee_owned () -> ()
|
|
%7 = copy_value %6 : $@callee_owned () -> ()
|
|
apply %7() : $@callee_owned () -> ()
|
|
end_borrow %6 : $@callee_owned () -> ()
|
|
destroy_value %5 : $@callee_owned () -> ()
|
|
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <Int>
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil [ossa] @closure3 : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> () {
|
|
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <Int>):
|
|
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Int> // id: %7
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil [ossa] @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> () {
|
|
bb0(%0 : @guaranteed ${ var SomeClass }):
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil [ossa] @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @finalReleaseWithBorrow
|
|
// CHECK: [[S:%[0-9]+]] = alloc_stack {{.*}}$SomeClass
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK: [[F:%[0-9]+]] = function_ref @useClosure
|
|
// CHECK: apply [[F]]
|
|
// CHECK: destroy_addr [[S]]
|
|
// CHECK: } // end sil function 'finalReleaseWithBorrow'
|
|
sil [ossa] @finalReleaseWithBorrow : $@convention(thin) (@owned SomeClass) -> () {
|
|
bb0(%0 : @owned $SomeClass):
|
|
%1 = alloc_box $ { var SomeClass }
|
|
%2 = begin_borrow %1 : ${ var SomeClass }
|
|
%1a = project_box %2 : ${ var SomeClass }, 0
|
|
store %0 to [init] %1a : $*SomeClass
|
|
%3 = function_ref @closureWithBoxArg : $@convention(thin) (@guaranteed { var SomeClass }) -> ()
|
|
%4 = copy_value %2 : ${ var SomeClass }
|
|
%5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (@guaranteed { var SomeClass }) -> ()
|
|
end_borrow %2 : ${ var SomeClass }
|
|
destroy_value %1 : ${ var SomeClass }
|
|
%6 = function_ref @useClosure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
apply %6(%5) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %5 : $@callee_guaranteed () -> ()
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> ()
|
|
sil [transparent] [serialized] [ossa] @mightApply : $@convention(thin) <U where U : P> (@owned @callee_owned () -> @out U) -> () {
|
|
// CHECK: bb0
|
|
bb0(%0 : @owned $@callee_owned () -> @out U):
|
|
debug_value %0 : $@callee_owned () -> @out U
|
|
%1 = copy_value %0 : $@callee_owned () -> @out U
|
|
%3 = alloc_stack $U
|
|
%4 = apply %1(%3) : $@callee_owned () -> @out U
|
|
destroy_addr %3 : $*U
|
|
dealloc_stack %3 : $*U
|
|
destroy_value %0 : $@callee_owned () -> @out U
|
|
%8 = tuple ()
|
|
// CHECK: return
|
|
return %8 : $()
|
|
}
|
|
|
|
sil [transparent] [serialized] [ossa] @mightApplyGuaranteed : $@convention(thin) <U where U : P> (@guaranteed @callee_guaranteed () -> @out U) -> () {
|
|
// CHECK: bb0
|
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> @out U):
|
|
debug_value %0 : $@callee_guaranteed () -> @out U
|
|
%3 = alloc_stack $U
|
|
%4 = apply %0(%3) : $@callee_guaranteed () -> @out U
|
|
destroy_addr %3 : $*U
|
|
dealloc_stack %3 : $*U
|
|
%8 = tuple ()
|
|
// CHECK: return
|
|
return %8 : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @callWithAutoclosure
|
|
sil [ossa] @callWithAutoclosure : $@convention(thin) <T where T : P> (@in T) -> () {
|
|
// CHECK: bb0
|
|
bb0(%0 : $*T):
|
|
// CHECK: debug_value {{.*}} expr op_deref
|
|
debug_value %0 : $*T, expr op_deref
|
|
// CHECK: function_ref @mightApply
|
|
%2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
%3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
|
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
// CHECK: copy_addr %0 to [init] [[STACK]] : $*T
|
|
copy_addr %0 to [init] %4a : $*T
|
|
// CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n
|
|
// CHECK: partial_apply [[CLOSURE]]<T>([[STACK]])
|
|
%6 = partial_apply %3<T>(%4) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
%7 = apply %2<T>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
// CHECK: destroy_addr [[STACK]] : $*T
|
|
// CHECK: dealloc_stack [[STACK]] : $*T
|
|
destroy_addr %0 : $*T
|
|
%9 = tuple ()
|
|
// CHECK: return
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @callWithAutoclosure_2 : $@convention(thin) <T where T : P> (@in T) -> () {
|
|
sil [ossa] @callWithAutoclosure_2 : $@convention(thin) <T where T : P> (@in T) -> () {
|
|
// CHECK: bb0
|
|
bb0(%0 : $*T):
|
|
// CHECK: debug_value {{.*}} expr op_deref
|
|
debug_value %0 : $*T, expr op_deref
|
|
// CHECK: function_ref @mightApply
|
|
%2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
%3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: [[STACK:%[0-9a-zA-Z_]+]] = alloc_stack $T
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
|
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
%4copy = copy_value %4 : $<τ_0_0> { var τ_0_0 } <T>
|
|
// CHECK: copy_addr %0 to [init] [[STACK]] : $*T
|
|
copy_addr %0 to [init] %4a : $*T
|
|
// CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n
|
|
// CHECK: partial_apply [[CLOSURE]]<T>([[STACK]])
|
|
%6 = partial_apply %3<T>(%4copy) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
%7 = apply %2<T>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
// CHECK: destroy_addr [[STACK]] : $*T
|
|
// CHECK: dealloc_stack [[STACK]] : $*T
|
|
destroy_addr %0 : $*T
|
|
destroy_value %4 : $<τ_0_0> { var τ_0_0 } <T>
|
|
%9 = tuple ()
|
|
// CHECK: return
|
|
return %9 : $()
|
|
}
|
|
// CHECK: } // end sil function 'callWithAutoclosure_2'
|
|
|
|
// CHECK-LABEL: sil [ossa] @callWithAutoclosure_3 : $@convention(thin) <T where T : P> (@in T) -> () {
|
|
sil [ossa] @callWithAutoclosure_3 : $@convention(thin) <T where T : P> (@in T) -> () {
|
|
// CHECK: bb0
|
|
bb0(%0 : $*T):
|
|
// CHECK: debug_value {{.*}} expr op_deref
|
|
debug_value %0 : $*T, expr op_deref
|
|
// CHECK: function_ref @mightApply
|
|
%2 = function_ref @mightApply : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
%3 = function_ref @closure_to_specialize : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
// CHECK-NOT: alloc_box
|
|
// CHECK: [[STACK_UNMARKED:%[0-9a-zA-Z_]+]] = alloc_stack $T
|
|
// CHECK: [[STACK:%.*]] = mark_uninitialized [var] [[STACK_UNMARKED]]
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
|
%4c = mark_uninitialized [var] %4 : $<τ_0_0> { var τ_0_0 } <T>
|
|
%4a = project_box %4c : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
%4copy = copy_value %4c : $<τ_0_0> { var τ_0_0 } <T>
|
|
// CHECK: copy_addr %0 to [init] [[STACK]] : $*T
|
|
copy_addr %0 to [init] %4a : $*T
|
|
// CHECK: [[CLOSURE:%[0-9a-zA-Z]+]] = function_ref @$s21closure_to_specializeTf0ns_n
|
|
// CHECK: partial_apply [[CLOSURE]]<T>([[STACK]])
|
|
%6 = partial_apply %3<T>(%4copy) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
|
|
%7 = apply %2<T>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned @callee_owned () -> @out τ_0_0) -> ()
|
|
// CHECK: destroy_addr [[STACK]] : $*T
|
|
// CHECK: dealloc_stack [[STACK_UNMARKED]] : $*T
|
|
destroy_addr %0 : $*T
|
|
destroy_value %4c : $<τ_0_0> { var τ_0_0 } <T>
|
|
%9 = tuple ()
|
|
// CHECK: return
|
|
return %9 : $()
|
|
}
|
|
// CHECK: } // end sil function 'callWithAutoclosure_3'
|
|
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s21closure_to_specializeTf0ns_n : $@convention(thin) <T where T : P> (@inout_aliasable T) -> @out T
|
|
sil shared [ossa] @closure_to_specialize : $@convention(thin) <T where T : P> (@owned <τ_0_0> { var τ_0_0 } <T>) -> @out T {
|
|
// CHECK: bb0
|
|
bb0(%0 : $*T, %1 : @owned $<τ_0_0> { var τ_0_0 } <T>):
|
|
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
// CHECK-NEXT: copy_addr
|
|
copy_addr %2 to [init] %0 : $*T
|
|
// CHECK-NOT: destroy_value
|
|
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <T>
|
|
%5 = tuple ()
|
|
// CHECK: return
|
|
return %5 : $()
|
|
}
|
|
|
|
protocol Count {
|
|
var count: Int { get }
|
|
}
|
|
|
|
struct Q : Count {
|
|
var count: Int { get }
|
|
init()
|
|
}
|
|
|
|
struct S<T : Count> {
|
|
@_hasStorage var t: T
|
|
var count: Int { get }
|
|
func test(i: Int) -> Bool
|
|
init(t: T)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @inner
|
|
sil [noinline] [ossa] @inner : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : @owned $@callee_owned () -> Bool):
|
|
debug_value %0 : $@callee_owned () -> Bool
|
|
%1 = copy_value %0 : $@callee_owned () -> Bool
|
|
%3 = apply %1() : $@callee_owned () -> Bool
|
|
destroy_value %0 : $@callee_owned () -> Bool
|
|
// CHECK: return
|
|
return %3 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @outer
|
|
sil [noinline] [ossa] @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : @owned $@callee_owned () -> Bool):
|
|
debug_value %0 : $@callee_owned () -> Bool
|
|
%1 = copy_value %0 : $@callee_owned () -> Bool
|
|
%3 = apply %1() : $@callee_owned () -> Bool
|
|
destroy_value %0 : $@callee_owned () -> Bool
|
|
// CHECK: return
|
|
return %3 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil @get
|
|
sil @get : $@convention(method) <T where T : Count> (@in S<T>) -> Int
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @specialized
|
|
sil shared [ossa] @specialized : $@convention(method) (Int, @in S<Q>) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : $Int, %1 : $*S<Q>):
|
|
debug_value %0 : $Int
|
|
debug_value %1 : $*S<Q>, expr op_deref
|
|
%4 = function_ref @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
%5 = function_ref @closure1 : $@convention(thin) <T where T : Count> (Int, @owned <τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>) -> Bool
|
|
%6 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <Q>
|
|
%6a = project_box %6 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <Q>, 0
|
|
copy_addr %1 to [init] %6a : $*S<Q>
|
|
%8 = partial_apply %5<Q>(%0, %6) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool
|
|
%9 = apply %4(%8) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
destroy_addr %1 : $*S<Q>
|
|
// CHECK: return
|
|
return %9 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unspecialized
|
|
sil [ossa] @unspecialized : $@convention(method) <T where T : Count> (Int, @in S<T>) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : $Int, %1 : $*S<T>):
|
|
debug_value %0 : $Int
|
|
debug_value %1 : $*S<T>, expr op_deref
|
|
%4 = function_ref @outer : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
%5 = function_ref @closure1 : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool
|
|
%6 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
%6a = project_box %6 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>, 0
|
|
copy_addr %1 to [init] %6a : $*S<T>
|
|
%8 = partial_apply %5<T>(%0, %6) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool
|
|
%9 = apply %4(%8) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
destroy_addr %1 : $*S<T>
|
|
// CHECK: return
|
|
return %9 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [_semantics "sil.optimizer.delete_if_unused"] [ossa] @closure1
|
|
sil shared [ossa] @closure1 : $@convention(thin) <T where T : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <T>) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : $Int, %1 : @owned $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>):
|
|
%2 = project_box %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>, 0
|
|
%3 = function_ref @inner : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
%4 = function_ref @closure2 : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool
|
|
%5 = alloc_box $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
%5a = project_box %5 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>, 0
|
|
copy_addr %2 to [init] %5a : $*S<T>
|
|
%7 = partial_apply %4<T>(%0, %5) : $@convention(thin) <τ_0_0 where τ_0_0 : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <τ_0_0>) -> Bool
|
|
%8 = apply %3(%7) : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
|
|
destroy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
// CHECK: return
|
|
return %8 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s8closure2Tf0ns_n
|
|
// CHECK: bb0
|
|
// CHECK: return
|
|
// CHECK-NOT: bb1
|
|
|
|
// CHECK-LABEL: sil shared [_semantics "sil.optimizer.delete_if_unused"] [ossa] @closure2
|
|
sil shared [ossa] @closure2 : $@convention(thin) <T where T : Count> (Int, @owned <τ_0_0 : Count> { var S<τ_0_0> } <T>) -> Bool {
|
|
// CHECK: bb0
|
|
bb0(%0 : $Int, %1 : @owned $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>):
|
|
%2 = project_box %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>, 0
|
|
%3 = function_ref @binary : $@convention(thin) (Int, Int) -> Bool
|
|
%4 = alloc_stack $S<T>
|
|
copy_addr %2 to [init] %4 : $*S<T>
|
|
%6 = function_ref @get : $@convention(method) <τ_0_0 where τ_0_0 : Count> (@in S<τ_0_0>) -> Int
|
|
%7 = apply %6<T>(%4) : $@convention(method) <τ_0_0 where τ_0_0 : Count> (@in S<τ_0_0>) -> Int
|
|
%8 = apply %3(%0, %7) : $@convention(thin) (Int, Int) -> Bool
|
|
%9 = copy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
%10 = project_box %9 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>, 0
|
|
copy_addr %10 to [init] %4 : $*S<T>
|
|
destroy_value %9 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
destroy_addr %4 : $*S<T>
|
|
dealloc_stack %4 : $*S<T>
|
|
destroy_value %1 : $<τ_0_0 where τ_0_0 : Count> { var S<τ_0_0> } <T>
|
|
// CHECK: return
|
|
return %8 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil [transparent] [serialized] @binary
|
|
sil [transparent] [serialized] @binary : $@convention(thin) (Int, Int) -> Bool
|
|
|
|
// CHECK-LABEL: sil [ossa] @destroy_stack_value_after_closure
|
|
sil [ossa] @destroy_stack_value_after_closure : $@convention(thin) <T> (@in T) -> @out T {
|
|
// CHECK: bb0
|
|
bb0(%0 : $*T, %1 : $*T):
|
|
// CHECK: [[STACK:%.*]] = alloc_stack
|
|
// CHECK: copy_addr %1 to [init] [[STACK]]
|
|
// CHECK: [[APPLIED:%.*]] = function_ref
|
|
%3 = function_ref @applied : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> ()
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
|
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
copy_addr %1 to [init] %4a : $*T
|
|
// CHECK: [[PARTIAL:%.*]] = partial_apply [[APPLIED]]<T>([[STACK]])
|
|
%6 = partial_apply %3<T>(%4) : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> ()
|
|
// CHECK: debug_value [[PARTIAL]]
|
|
debug_value %6 : $@callee_owned () -> ()
|
|
// CHECK: [[COPIED_PARTIAL:%.*]] = copy_value [[PARTIAL]]
|
|
%7 = copy_value %6 : $@callee_owned () -> ()
|
|
// CHECK: apply [[COPIED_PARTIAL]]() : $@callee_owned () -> ()
|
|
%9 = apply %7() : $@callee_owned () -> ()
|
|
copy_addr %1 to [init] %0 : $*T
|
|
// CHECK: destroy_value [[PARTIAL]]
|
|
destroy_value %6 : $@callee_owned () -> ()
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: destroy_addr %1
|
|
destroy_addr %1 : $*T
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
sil [ossa] @applied : $@convention(thin) <T> (@owned <τ_0_0> { var τ_0_0 } <T>) -> () {
|
|
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <T>):
|
|
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
%2 = function_ref @consume : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
%3 = alloc_stack $T
|
|
copy_addr %1 to [init] %3 : $*T
|
|
%5 = apply %2<T>(%3) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
|
|
dealloc_stack %3 : $*T
|
|
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <T>
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
sil hidden [noinline] @consume : $@convention(thin) <T> (@in T) -> () {
|
|
bb0(%0 : $*T):
|
|
debug_value %0 : $*T, expr op_deref
|
|
destroy_addr %0 : $*T
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
class ThrowBaseClass {
|
|
required init() throws
|
|
init(noFail: ())
|
|
}
|
|
|
|
class ThrowDerivedClass : ThrowBaseClass {
|
|
//final init(failBeforeFullInitialization: Int) throws
|
|
}
|
|
|
|
sil [ossa] @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error)
|
|
sil [ossa] @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error)
|
|
|
|
sil hidden [ossa] @try_apply_during_chaining_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error) {
|
|
// %0 // users: %11, %5
|
|
// %1 // user: %7
|
|
bb0(%0 : $Int, %1 : @owned $ThrowDerivedClass):
|
|
%2 = alloc_box ${ var ThrowDerivedClass }, let, name "self"
|
|
%3 = mark_uninitialized [delegatingself] %2 : ${ var ThrowDerivedClass }
|
|
%4 = project_box %3 : ${ var ThrowDerivedClass }, 0
|
|
store %1 to [init] %4 : $*ThrowDerivedClass
|
|
%8 = load [take] %4 : $*ThrowDerivedClass
|
|
%9 = function_ref @fake_throwing_init : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error)
|
|
%10 = function_ref @throwing_unwrap : $@convention(thin) (Int) -> (Int, @error any Error)
|
|
try_apply %10(%0) : $@convention(thin) (Int) -> (Int, @error any Error), normal bb1, error bb3
|
|
|
|
// %12 // user: %13
|
|
bb1(%12 : $Int): // Preds: bb0
|
|
try_apply %9(%12, %8) : $@convention(method) (Int, @owned ThrowDerivedClass) -> (@owned ThrowDerivedClass, @error any Error), normal bb2, error bb4
|
|
|
|
// %14 // user: %15
|
|
bb2(%14 : @owned $ThrowDerivedClass): // Preds: bb1
|
|
store %14 to [init] %4 : $*ThrowDerivedClass
|
|
%16 = load [copy] %4 : $*ThrowDerivedClass
|
|
destroy_value %3 : ${ var ThrowDerivedClass }
|
|
return %16 : $ThrowDerivedClass
|
|
|
|
// %20 // user: %22
|
|
bb3(%20 : @owned $Error): // Preds: bb0
|
|
destroy_value %8 : $ThrowDerivedClass
|
|
br bb5(%20 : $Error)
|
|
|
|
// %23 // user: %24
|
|
bb4(%23 : @owned $Error): // Preds: bb1
|
|
br bb5(%23 : $Error)
|
|
|
|
// %25 // user: %27
|
|
bb5(%25 : @owned $Error): // Preds: bb4 bb3
|
|
destroy_value %3 : ${ var ThrowDerivedClass }
|
|
throw %25 : $Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @deal_with_wrong_nesting
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK1]]
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: [[STACK2:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: dealloc_stack [[STACK2]]
|
|
// CHECK-NEXT: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK1]]
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @deal_with_wrong_nesting : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%as1 = alloc_stack $Bool
|
|
%1 = alloc_box ${ var Int }
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_value %1 : ${ var Int }
|
|
dealloc_stack %as1 : $*Bool
|
|
br bb3
|
|
|
|
bb2:
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
dealloc_stack %as1 : $*Bool
|
|
%3 = load [trivial] %1a : $*Int
|
|
%as2 = alloc_stack $Bool
|
|
destroy_value %1 : ${ var Int }
|
|
dealloc_stack %as2 : $*Bool
|
|
br bb3
|
|
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @wrong_nesting_with_alloc_ref
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[REF:%[0-9]+]] = alloc_ref [stack] $SomeClass
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: dealloc_stack_ref [[REF]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @wrong_nesting_with_alloc_ref : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%as1 = alloc_ref [stack] $SomeClass
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
store %0 to [trivial] %1a : $*Int
|
|
dealloc_ref %as1 : $SomeClass
|
|
dealloc_stack_ref %as1 : $SomeClass
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nesting_and_unreachable1
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: dealloc_stack [[STACK2]]
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK1]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @nesting_and_unreachable1 : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%as1 = alloc_stack $Bool
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%as2 = alloc_stack $Bool
|
|
dealloc_stack %as2 : $*Bool
|
|
unreachable
|
|
|
|
bb2:
|
|
store %0 to [trivial] %1a : $*Int
|
|
dealloc_stack %as1 : $*Bool
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nesting_and_unreachable2
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[STACK1:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: [[STACK2:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK-NEXT: dealloc_stack [[STACK2]]
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: dealloc_stack [[STACK1]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @nesting_and_unreachable2 : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%as1 = alloc_stack $Bool
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%as2 = alloc_stack $Bool
|
|
destroy_value %1 : ${ var Int }
|
|
dealloc_stack %as2 : $*Bool
|
|
unreachable
|
|
|
|
bb2:
|
|
store %0 to [trivial] %1a : $*Int
|
|
dealloc_stack %as1 : $*Bool
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nesting_and_unreachable3
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK-NEXT: [[STACK:%[0-9]+]] = alloc_stack $Bool
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[STACK]]
|
|
// CHECK-NEXT: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @nesting_and_unreachable3 : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%as1 = alloc_stack $Bool
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_value %1 : ${ var Int }
|
|
unreachable
|
|
|
|
bb2:
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = load [trivial] %1a : $*Int
|
|
dealloc_stack %as1 : $*Bool
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nesting_and_unreachable4
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @nesting_and_unreachable4 : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
unreachable
|
|
|
|
bb2:
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nesting_and_unreachable5
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK-NEXT: [[BOX:%[0-9]+]] = alloc_stack $Int
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: {{.*}} = alloc_stack $Bool
|
|
// CHECK-NEXT: {{.*}} = alloc_stack $Bool
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: bb2:
|
|
// CHECK: store
|
|
// CHECK: dealloc_stack [[BOX]]
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @nesting_and_unreachable5 : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_box ${ var Int }
|
|
%1a = project_box %1 : ${ var Int }, 0
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%as1 = alloc_stack $Bool
|
|
%as2 = alloc_stack $Bool
|
|
unreachable
|
|
|
|
bb2:
|
|
store %0 to [trivial] %1a : $*Int
|
|
%3 = load [trivial] %1a : $*Int
|
|
destroy_value %1 : ${ var Int }
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// Test that
|
|
// begin_access [read], copy_addr, end_access, destroy_addr
|
|
// is folded into
|
|
// begin_access [deinit], copy_addr [take], end_access
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @deinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $T, var, name "x"
|
|
// CHECK: copy_addr %2 to [init] [[STK]] : $*T
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T
|
|
// CHECK: copy_addr [[READ]] to [init] %0 : $*T
|
|
// CHECK: end_access [[READ]] : $*T
|
|
// CHECK: [[READ:%.*]] = begin_access [deinit] [static] [[STK]] : $*T
|
|
// CHECK: copy_addr [take] [[READ]] to [init] %1 : $*T
|
|
// CHECK: end_access [[READ]] : $*T
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK: dealloc_stack [[STK]] : $*T
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'deinit_access'
|
|
sil [ossa] @deinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>, var, name "x"
|
|
%5 = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
copy_addr %2 to [init] %5 : $*T
|
|
%7 = begin_access [read] [static] %5 : $*T
|
|
copy_addr %7 to [init] %0 : $*T
|
|
end_access %7 : $*T
|
|
%10 = begin_access [read] [static] %5 : $*T
|
|
copy_addr %10 to [init] %1 : $*T
|
|
end_access %10 : $*T
|
|
destroy_value %4 : $<τ_0_0> { var τ_0_0 } <T>
|
|
destroy_addr %2 : $*T
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
// Test that
|
|
// begin_access [read], <other access>, copy_addr, end_access, destroy_addr
|
|
// is *not* folded into
|
|
// begin_access [deinit], copy_addr [take], end_access
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @nodeinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $T, var, name "x"
|
|
// CHECK: copy_addr %2 to [init] [[STK]] : $*T
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T
|
|
// CHECK: copy_addr [[READ]] to [init] %0 : $*T
|
|
// CHECK: end_access [[READ]] : $*T
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*T
|
|
// CHECK: [[INNER:%.*]] = begin_access [read] [static] [[READ]] : $*T
|
|
// CHECK: end_access [[INNER]] : $*T
|
|
// CHECK: copy_addr [[READ]] to [init] %1 : $*T
|
|
// CHECK: end_access [[READ]] : $*T
|
|
// CHECK: destroy_addr [[STK]] : $*T
|
|
// CHECK: dealloc_stack [[STK]] : $*T
|
|
// CHECK: destroy_addr %2 : $*T
|
|
// CHECK: return %{{.*}} : $()
|
|
// CHECK-LABEL: } // end sil function 'nodeinit_access'
|
|
sil [ossa] @nodeinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
|
|
bb0(%0 : $*T, %1 : $*T, %2 : $*T):
|
|
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>, var, name "x"
|
|
%5 = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
|
|
copy_addr %2 to [init] %5 : $*T
|
|
%7 = begin_access [read] [static] %5 : $*T
|
|
copy_addr %7 to [init] %0 : $*T
|
|
end_access %7 : $*T
|
|
%10 = begin_access [read] [static] %5 : $*T
|
|
%innerAccess = begin_access [read] [static] %10 : $*T
|
|
end_access %innerAccess : $*T
|
|
copy_addr %10 to [init] %1 : $*T
|
|
end_access %10 : $*T
|
|
destroy_value %4 : $<τ_0_0> { var τ_0_0 } <T>
|
|
destroy_addr %2 : $*T
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
sil @getC : $@convention(thin) () -> (@owned C)
|
|
|
|
// CHECK-LABEL: sil [ossa] @leak_to_inf_loop_1 : {{.*}} {
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'leak_to_inf_loop_1'
|
|
sil [ossa] @leak_to_inf_loop_1 : $@convention(thin) (@owned C) -> () {
|
|
entry(%c : @owned $C):
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
store %c to [init] %c_addr
|
|
%copy = copy_value %box
|
|
destroy_value %box
|
|
br loop
|
|
|
|
loop:
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%c2 = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
%c_old = load [take] %c_addr
|
|
store %c2 to [init] %c_addr
|
|
destroy_value %c_old
|
|
br loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @leak_to_inf_loop_2 : {{.*}} {
|
|
// CHECK: cond_br undef, [[EXIT:bb[0-9]+]], [[TO_LOOP:bb[0-9]+]]
|
|
// CHECK: [[EXIT]]
|
|
// CHECK: destroy_addr
|
|
// CHECK: dealloc_stack
|
|
// CHECK: [[TO_LOOP]]
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'leak_to_inf_loop_2'
|
|
sil [ossa] @leak_to_inf_loop_2 : $@convention(thin) (@owned C) -> () {
|
|
entry(%c : @owned $C):
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
store %c to [init] %c_addr
|
|
%copy = copy_value %box
|
|
destroy_value %box
|
|
cond_br undef, exit, to_loop
|
|
|
|
exit:
|
|
destroy_value %copy
|
|
return undef : $()
|
|
|
|
to_loop:
|
|
%copy2 = copy_value %copy
|
|
destroy_value %copy
|
|
br loop
|
|
|
|
loop:
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%c2 = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
%c_old = load [take] %c_addr
|
|
store %c2 to [init] %c_addr
|
|
destroy_value %c_old
|
|
br loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @leak_to_inf_loop_3 : {{.*}} {
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'leak_to_inf_loop_3'
|
|
sil [ossa] @leak_to_inf_loop_3 : $@convention(thin) (@owned C) -> () {
|
|
entry(%c : @owned $C):
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
store %c to [init] %c_addr
|
|
br to_loop
|
|
|
|
to_loop:
|
|
%copy = copy_value %box
|
|
destroy_value %box
|
|
br loop
|
|
|
|
loop:
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%c2 = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
%c_old = load [take] %c_addr
|
|
store %c2 to [init] %c_addr
|
|
destroy_value %c_old
|
|
br loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dealloc_box_before_loop
|
|
// CHECK: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'dealloc_box_before_loop'
|
|
sil [ossa] @dealloc_box_before_loop : $@convention(thin) (@owned C) -> () {
|
|
entry(%c : @owned $C):
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
store %c to [init] %c_addr
|
|
cond_br undef, exit, to_loop
|
|
|
|
exit:
|
|
destroy_value %box
|
|
return undef : $()
|
|
|
|
to_loop:
|
|
dealloc_box %box
|
|
br loop
|
|
|
|
loop:
|
|
br loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_box_in_deadend_loop
|
|
// CHECK: alloc_stack
|
|
// CHECK: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'alloc_box_in_deadend_loop'
|
|
sil [ossa] @alloc_box_in_deadend_loop : $@convention(thin) () -> () {
|
|
entry:
|
|
br loop
|
|
|
|
loop:
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%c = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %c to [init] %c_addr
|
|
destroy_value %box
|
|
br loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_box_in_exiting_loop
|
|
// CHECK: br [[EXITING_LOOP:bb[0-9]+]]
|
|
// CHECK: [[EXITING_LOOP]]:
|
|
// CHECK: alloc_stack
|
|
// CHECK: cond_br undef, [[EXIT:bb[0-9]+]], [[LATCH:bb[0-9]+]]
|
|
// CHECK: [[LATCH]]:
|
|
// CHECK: cond_br undef, [[BACKEDGE:bb[0-9]+]], [[INFINITE_LOOP:bb[0-9]+]]
|
|
// CHECK: [[BACKEDGE]]:
|
|
// CHECK: dealloc_stack
|
|
// CHECK: br [[EXITING_LOOP]]
|
|
// CHECK: [[EXIT]]:
|
|
// CHECK: dealloc_stack
|
|
// CHECK: [[INFINITE_LOOP]]:
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'alloc_box_in_exiting_loop'
|
|
sil [ossa] @alloc_box_in_exiting_loop : $@convention(thin) () -> () {
|
|
entry:
|
|
br exiting_loop
|
|
|
|
exiting_loop:
|
|
%box = alloc_box ${ var C }
|
|
%c_addr = project_box %box, 0
|
|
%getC = function_ref @getC : $@convention(thin) () -> (@owned C)
|
|
%c = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %c to [init] %c_addr
|
|
cond_br undef, exit, latch
|
|
|
|
latch:
|
|
cond_br undef, backedge, to_infinite_loop
|
|
|
|
backedge:
|
|
destroy_value %box
|
|
br exiting_loop
|
|
|
|
exit:
|
|
destroy_value %box
|
|
return undef : $()
|
|
|
|
to_infinite_loop:
|
|
br infinite_loop
|
|
|
|
infinite_loop:
|
|
%c2 = apply %getC() : $@convention(thin) () -> (@owned C)
|
|
store %c2 to [assign] %c_addr
|
|
%copy = copy_value %box
|
|
destroy_value %copy
|
|
br infinite_loop
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_box_in_deadend_loop_with_another_deadend
|
|
// CHECK: br [[LOOP:bb[0-9]+]]
|
|
// CHECK: [[LOOP]]:
|
|
// CHECK: alloc_stack
|
|
// CHECK: cond_br undef, [[BACKEDGE:bb[0-9]+]], [[DIE:bb[0-9]+]]
|
|
// CHECK: [[BACKEDGE]]:
|
|
// CHECK: dealloc_stack
|
|
// CHECK: br [[LOOP]]
|
|
// CHECK: [[DIE]]:
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'alloc_box_in_deadend_loop_with_another_deadend'
|
|
sil [ossa] @alloc_box_in_deadend_loop_with_another_deadend : $@convention(thin) () -> () {
|
|
entry:
|
|
br loop
|
|
|
|
loop:
|
|
%box = alloc_box ${ var C }
|
|
cond_br undef, backedge, die
|
|
|
|
backedge:
|
|
destroy_value %box
|
|
br loop
|
|
|
|
die:
|
|
%copy = copy_value %box
|
|
destroy_value %copy
|
|
unreachable
|
|
}
|