mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Type annotations for instruction operands are omitted, e.g. ``` %3 = struct $S(%1, %2) ``` Operand types are redundant anyway and were only used for sanity checking in the SIL parser. But: operand types _are_ printed if the definition of the operand value was not printed yet. This happens: * if the block with the definition appears after the block where the operand's instruction is located * if a block or instruction is printed in isolation, e.g. in a debugger The old behavior can be restored with `-Xllvm -sil-print-types`. This option is added to many existing test files which check for operand types in their check-lines.
115 lines
6.6 KiB
Plaintext
115 lines
6.6 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types %s -compute-escape-effects -compute-side-effects -temp-rvalue-opt -enable-sil-verify-all -wmo | %FileCheck %s
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
// TempRValue iteratively uses EscapeAnalysis and deletes
|
|
// instructions. Make sure that the connection graph remains valid
|
|
// <rdar://57290845>.
|
|
//
|
|
// This test requires -wmo so EscapeAnalysis can find all
|
|
// implementations of SomeProtocol.foo. Otherwise the existential
|
|
// address appears to escape. As an alternative, we could be more
|
|
// aggressive about considering address-type argument not to escape,
|
|
// but that would require some limiting address_to_pointer to never
|
|
// occur on an exclusive address argument.
|
|
|
|
import Swift
|
|
|
|
sil_stage canonical
|
|
|
|
protocol SomeProtocol {
|
|
func foo()
|
|
}
|
|
struct SomeInstance : SomeProtocol {
|
|
func foo()
|
|
}
|
|
class SomeClass {
|
|
var someProperty: SomeProtocol
|
|
}
|
|
struct SomeStruct {
|
|
var someRef: SomeClass
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testTempRvalueEscapeAnalysisUpdate : $@convention(thin) (@in_guaranteed any SomeProtocol, @guaranteed SomeClass) -> () {
|
|
// CHECK: bb0(%0 : $*any SomeProtocol, %1 : $SomeClass):
|
|
// CHECK: alloc_ref $SomeClass
|
|
// CHECK: alloc_stack $SomeStruct
|
|
// CHECK-NOT: alloc_stack $any SomeProtocol
|
|
// CHECK-NOT: copy_addr
|
|
// CHECK: init_existential_addr %{{.*}} : $*any SomeProtocol, $SomeInstance
|
|
// CHECK: [[OPEN1:%.*]] = open_existential_addr immutable_access %0 : $*any SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001122", any SomeProtocol) Self
|
|
// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001122", any SomeProtocol) Self>([[OPEN1]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK-NOT: alloc_stack $any SomeProtocol
|
|
// CHECK-NOT: copy_addr
|
|
// CHECK: [[OPEN2:%.*]] = open_existential_addr immutable_access %{{.*}} : $*any SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001123", any SomeProtocol) Self
|
|
// CHECK: apply %{{.*}}<@opened("6419340C-0B14-11EA-9897-ACDE48001123", any SomeProtocol) Self>([[OPEN2]]) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
// CHECK-NOT: destroy_addr
|
|
// CHECK-LABEL: } // end sil function 'testTempRvalueEscapeAnalysisUpdate'
|
|
sil @testTempRvalueEscapeAnalysisUpdate : $@convention(thin) (@in_guaranteed SomeProtocol, @guaranteed SomeClass) -> () {
|
|
bb0(%0 : $*SomeProtocol, %1 : $SomeClass):
|
|
// First create a uniquely identified protocol value. This way
|
|
// EscapeAnalysis canPointToSameMemory will kick in later. It can't
|
|
// be an exclusive argument, or AliasAnalysis will filter it before
|
|
// querying EscapeAnalysis.
|
|
%localRef = alloc_ref $SomeClass
|
|
%localPropAdr = ref_element_addr %localRef : $SomeClass, #SomeClass.someProperty
|
|
copy_addr %0 to [init] %localPropAdr : $*SomeProtocol
|
|
%stk0 = alloc_stack $SomeStruct
|
|
%stk0Ref = struct_element_addr %stk0 : $*SomeStruct, #SomeStruct.someRef
|
|
store %localRef to %stk0Ref : $*SomeClass
|
|
%indirectRef = load %stk0Ref : $*SomeClass
|
|
%indirectLocalPropAdr = ref_element_addr %indirectRef : $SomeClass, #SomeClass.someProperty
|
|
|
|
%propAdr1 = ref_element_addr %1 : $SomeClass, #SomeClass.someProperty
|
|
// TempRValue tries to kick in on this copy, but there is an
|
|
// interfering write that can't be handled by AliasAnalysis without
|
|
// consulting EscapingAnalysis. MemoryBehavior drops down to
|
|
// EscapeAnalysis for only a few special instructions, like
|
|
// init_existential_addr.
|
|
%stkAdr1 = alloc_stack $SomeProtocol
|
|
copy_addr %0 to [init] %stkAdr1 : $*SomeProtocol
|
|
%instanceAdr = init_existential_addr %indirectLocalPropAdr : $*SomeProtocol, $SomeInstance
|
|
%openadr1 = open_existential_addr immutable_access %stkAdr1 : $*SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self
|
|
%witness1 = witness_method $@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self, #SomeProtocol.foo : <Self where Self : SomeProtocol> (Self) -> () -> (), %openadr1 : $*@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
%call1 = apply %witness1<@opened("6419340C-0B14-11EA-9897-ACDE48001122", SomeProtocol) Self>(%openadr1) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %stkAdr1 : $*SomeProtocol
|
|
|
|
// TempRValue optimization kicks in here. The open_existential_addr
|
|
// creates a content node that refers back to the dead stack
|
|
// location.
|
|
%stkAdr2 = alloc_stack $SomeProtocol
|
|
copy_addr %propAdr1 to [init] %stkAdr2 : $*SomeProtocol
|
|
%openadr2 = open_existential_addr immutable_access %stkAdr2 : $*SomeProtocol to $*@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self
|
|
%witness2 = witness_method $@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self, #SomeProtocol.foo : <Self where Self : SomeProtocol> (Self) -> () -> (), %openadr2 : $*@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
%call2 = apply %witness2<@opened("6419340C-0B14-11EA-9897-ACDE48001123", SomeProtocol) Self>(%openadr2) : $@convention(witness_method: SomeProtocol) <τ_0_0 where τ_0_0 : SomeProtocol> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %stkAdr2 : $*SomeProtocol
|
|
|
|
dealloc_stack %stkAdr2 : $*SomeProtocol
|
|
dealloc_stack %stkAdr1 : $*SomeProtocol
|
|
dealloc_stack %stk0 : $*SomeStruct
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
sil hidden @$s26escape_analysis_invalidate12SomeInstanceV3fooyyF : $@convention(method) (SomeInstance) -> () {
|
|
bb0(%0 : $SomeInstance):
|
|
debug_value %0 : $SomeInstance, let, name "self", argno 1 // id: %1
|
|
%2 = tuple () // user: %3
|
|
return %2 : $() // id: %3
|
|
}
|
|
|
|
sil private [transparent] [thunk] @$s26escape_analysis_invalidate12SomeInstanceVAA0A8ProtocolA2aDP3fooyyFTW : $@convention(witness_method: SomeProtocol) (@in_guaranteed SomeInstance) -> () {
|
|
bb0(%0 : $*SomeInstance):
|
|
%1 = load %0 : $*SomeInstance
|
|
// function_ref SomeInstance.foo()
|
|
%2 = function_ref @$s26escape_analysis_invalidate12SomeInstanceV3fooyyF : $@convention(method) (SomeInstance) -> ()
|
|
%3 = apply %2(%1) : $@convention(method) (SomeInstance) -> ()
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
sil_witness_table hidden SomeInstance: SomeProtocol module t {
|
|
method #SomeProtocol.foo: <Self where Self : SomeProtocol> (Self) -> () -> () : @$s26escape_analysis_invalidate12SomeInstanceVAA0A8ProtocolA2aDP3fooyyFTW // protocol witness for SomeProtocol.foo() in conformance SomeInstance
|
|
}
|