mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
5533 lines
237 KiB
Plaintext
5533 lines
237 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-copy-propagation=requested-passes-only -enable-objc-interop -enforce-exclusivity=none -enable-sil-verify-all %s -update-borrowed-from -sil-combine -wmo | %FileCheck %s
|
|
// RUN: %target-sil-opt -sil-print-types -enable-copy-propagation=requested-passes-only -enable-objc-interop -enforce-exclusivity=none -enable-sil-verify-all %s -update-borrowed-from -sil-combine -generic-specializer | %FileCheck %s --check-prefix=CHECK_FORWARDING_OWNERSHIP_KIND
|
|
//
|
|
// FIXME: check copy-propagation output instead once it is the default mode
|
|
// RUN: %target-sil-opt -sil-print-types -enable-objc-interop -enforce-exclusivity=none -enable-sil-verify-all %s -update-borrowed-from -sil-combine -enable-copy-propagation -enable-lexical-lifetimes=false | %FileCheck %s --check-prefix=CHECK_COPYPROP
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
// Declare this SIL to be canonical because some tests break raw SIL
|
|
// conventions. e.g. address-type block args. -enforce-exclusivity=none is also
|
|
// required to allow address-type block args in canonical SIL.
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
class Klass {}
|
|
|
|
sil @use_klass_guaranteed : $@convention(thin) (@guaranteed Klass) -> ()
|
|
|
|
class RawBuffer {}
|
|
class HeapBufferStorage<T, U> : RawBuffer {}
|
|
|
|
enum FakeOptional<T> {
|
|
case none
|
|
case some(T)
|
|
}
|
|
sil @use_fakeoptional_nativeobject_guaranteed : $@convention(thin) (@guaranteed FakeOptional<Builtin.NativeObject>) -> ()
|
|
|
|
struct StringData {
|
|
var size: Builtin.Word
|
|
}
|
|
|
|
struct PointerStorage {
|
|
var ptr: FakeOptional<Builtin.NativeObject>
|
|
}
|
|
|
|
class B { }
|
|
class E : B { }
|
|
|
|
sil @use_b_guaranteed : $@convention(thin) (@guaranteed B) -> ()
|
|
sil @usearray_error : $@convention(thin) (@guaranteed Array<Error>) -> ()
|
|
|
|
enum AddressOnlyEnum {
|
|
case Loadable(Builtin.Int32)
|
|
case AddressOnly(Any)
|
|
}
|
|
|
|
enum NonTrivialLoadableEnum {
|
|
case noPayload
|
|
case trivialPayload(Builtin.Int32)
|
|
case nonTrivialPayload(Builtin.NativeObject)
|
|
}
|
|
|
|
protocol FakeProtocol {
|
|
func requirement()
|
|
}
|
|
|
|
struct MyInt {
|
|
var value: Builtin.Int32
|
|
}
|
|
|
|
struct NativeObjectStruct {
|
|
var ele : Builtin.NativeObject
|
|
}
|
|
|
|
struct MyContiguousArrayBody {
|
|
@_hasStorage var count: Builtin.Int64 { get }
|
|
init(count: Builtin.Int64)
|
|
}
|
|
|
|
class MyContiguousArrayStorage {
|
|
@_hasStorage var body: MyContiguousArrayBody { get }
|
|
@objc deinit
|
|
}
|
|
|
|
struct MyContiguousArray {
|
|
@_hasStorage var storage: MyContiguousArrayStorage { get set }
|
|
init(storage: MyContiguousArrayStorage)
|
|
}
|
|
|
|
sil [global_init] @global_init_fun : $@convention(thin) () -> Builtin.RawPointer
|
|
|
|
sil [ossa] @user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
sil [ossa] @use_nativeobject_owned : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
sil [ossa] @use_nativeobject_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
sil [ossa] @get_owned_klass : $@convention(thin) () -> (@owned Klass)
|
|
sil @use_anyobject_guaranteed : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
sil @use_generic_obj_guaranteed : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
|
|
sil [ossa] @unknown : $@convention(thin) () -> ()
|
|
sil [ossa] @get_myint : $@convention(thin) () -> (MyInt)
|
|
sil [ossa] @use_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
sil [ossa] @useC : $@convention(thin) (@guaranteed C) -> ()
|
|
|
|
enum KlassNativeObjEither {
|
|
case lhs(Klass)
|
|
case rhs(Builtin.NativeObject)
|
|
}
|
|
|
|
struct MoveOnlyStruct: ~Copyable {
|
|
var value: MyInt
|
|
}
|
|
|
|
//////////////////////
|
|
// Simple DCE Tests //
|
|
//////////////////////
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_inst_elimination_one_bb
|
|
// CHECK-NOT: integer_literal $Builtin.Int64, 24
|
|
sil [ossa] @dead_inst_elimination_one_bb : $@convention(thin) () -> () {
|
|
%0 = integer_literal $Builtin.Int64, 24
|
|
%1 = tuple()
|
|
return %1 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_inst_elimination_diamond
|
|
// CHECK: bb0
|
|
// CHECK-NOT: integer_literal $Builtin.Int64, 24
|
|
// CHECK: bb1
|
|
// CHECK-NOT: integer_literal $Builtin.Int64, 48
|
|
sil [ossa] @dead_inst_elimination_diamond : $@convention(thin) (Builtin.Int1) -> () {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%1 = integer_literal $Builtin.Int64, 24
|
|
cond_br %0, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = integer_literal $Builtin.Int64, 48
|
|
br bb3
|
|
|
|
bb2:
|
|
%3 = integer_literal $Builtin.Int64, 96
|
|
br bb3
|
|
|
|
bb3:
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
sil [ossa] @random_counter : $@convention(thin) () -> Builtin.Int1
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_inst_elimination_loop
|
|
// CHECK: bb0
|
|
// CHECK-NOT: integer_literal
|
|
// CHECK: bb1
|
|
// CHECK: function_ref
|
|
// CHECK: apply
|
|
// CHECK-NOT: integer_literal
|
|
// CHECK: bb2
|
|
// CHECK-NOT: integer_literal
|
|
// CHECK: tuple
|
|
// CHECK: return
|
|
sil [ossa] @dead_inst_elimination_loop : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = integer_literal $Builtin.Int64, 24
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = function_ref @random_counter : $@convention(thin) () -> Builtin.Int1
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.Int1
|
|
%4 = integer_literal $Builtin.Int64, 48
|
|
cond_br %3, bb1a, bb2
|
|
|
|
bb1a:
|
|
br bb1
|
|
|
|
bb2:
|
|
%5 = integer_literal $Builtin.Int64, 59
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
// For now until the proper unreachable pruning code is committed for
|
|
// SILCombine, we should not dce dead instructions in unreachable code.
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_inst_elimination_ignore_unreachable
|
|
// CHECK: bb0
|
|
// CHECK-NOT: integer_literal $Builtin.Int64, 24
|
|
// CHECK: bb1
|
|
// CHECK: integer_literal $Builtin.Int64, 48
|
|
sil [ossa] @dead_inst_elimination_ignore_unreachable : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int64, 24
|
|
br bb2
|
|
|
|
bb1:
|
|
%1 = integer_literal $Builtin.Int64, 48
|
|
br bb2
|
|
|
|
bb2:
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
// Other DCE Tests taken from diagnose_unreachable.sil //
|
|
//////////////////////////////////////////////////////////
|
|
|
|
sil [ossa] @exit : $@convention(thin) () -> Never {
|
|
bb0:
|
|
br bb1
|
|
bb1:
|
|
br bb1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @removeTriviallyDeadInstructions :
|
|
// CHECK: store
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'removeTriviallyDeadInstructions'
|
|
sil [ossa] @removeTriviallyDeadInstructions : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
|
|
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
|
|
store %0 to [init] %1a : $*B
|
|
%3 = load [copy] %1a : $*B
|
|
%5 = unchecked_ref_cast %3 : $B to $Builtin.NativeObject
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <B>
|
|
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
|
|
%10 = apply %9() : $@convention(thin) () -> Never
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @removeTriviallyDeadCrossBasicBlocks
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: cond_br
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: }
|
|
sil [ossa] @removeTriviallyDeadCrossBasicBlocks : $@convention(thin) (@owned B, Builtin.Int1) -> () {
|
|
bb0(%0 : @owned $B, %1: $Builtin.Int1):
|
|
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
|
|
cond_br %1, bb1, bb2a
|
|
|
|
bb1:
|
|
br bb2
|
|
|
|
bb2a:
|
|
br bb2
|
|
|
|
bb2:
|
|
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
|
|
%10 = apply %9() : $@convention(thin) () -> Never
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_use_of_alloc_stack
|
|
// CHECK: bb
|
|
// CHECK: alloc_stack
|
|
// CHECK: dealloc_stack
|
|
// CHECK: }
|
|
sil [ossa] @dead_use_of_alloc_stack : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = alloc_stack $((), (), ())
|
|
%2 = tuple_element_addr %1 : $*((), (), ()), 0
|
|
fix_lifetime %2
|
|
dealloc_stack %1 : $*((), (), ())
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @tuple_extract
|
|
// CHECK: bb
|
|
// CHECK-NEXT: return %0
|
|
sil [ossa] @tuple_extract : $@convention(thin) (Int64) -> Int64 {
|
|
bb0(%0 : $Int64):
|
|
%1 = tuple (%0 : $Int64, %0 : $Int64)
|
|
%2 = tuple_extract %1 : $(Int64, Int64), 0
|
|
return %2 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_not_fold_integer_literal
|
|
// CHECK: bb
|
|
// CHECK: cond_br
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: br bb
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: br bb
|
|
sil [ossa] @do_not_fold_integer_literal : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
cond_br %0, bb1, bb3
|
|
|
|
bb1:
|
|
%1 = integer_literal $Builtin.Int1, 0
|
|
br bb2(%1 : $Builtin.Int1)
|
|
|
|
bb3:
|
|
%2 = integer_literal $Builtin.Int1, -1
|
|
br bb2(%2 : $Builtin.Int1)
|
|
|
|
bb2(%3 : $Builtin.Int1):
|
|
return %3 : $Builtin.Int1
|
|
}
|
|
|
|
enum BoolLike { case true_, false_ }
|
|
|
|
// CHECK-LABEL: sil [ossa] @fold_enum :
|
|
// CHECK: bb
|
|
// CHECK: switch_enum
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NOT: enum
|
|
// CHECK-NEXT: br bb
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NOT: enum
|
|
// CHECK-NEXT: br bb
|
|
sil [ossa] @fold_enum : $@convention(thin) (BoolLike) -> BoolLike {
|
|
bb0(%0 : $BoolLike):
|
|
switch_enum %0 : $BoolLike, case #BoolLike.true_!enumelt: bb1, case #BoolLike.false_!enumelt: bb2
|
|
|
|
bb1:
|
|
%1 = enum $BoolLike, #BoolLike.true_!enumelt
|
|
br bb3(%1 : $BoolLike)
|
|
|
|
bb2:
|
|
%2 = enum $BoolLike, #BoolLike.false_!enumelt
|
|
br bb3(%2 : $BoolLike)
|
|
|
|
bb3(%3 : $BoolLike):
|
|
return %3 : $BoolLike
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @do_not_fold_enum
|
|
// CHECK: bb
|
|
// CHECK: switch_enum
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NEXT: enum
|
|
// CHECK-NEXT: br bb
|
|
// CHECK: {{^bb}}
|
|
// CHECK-NEXT: enum
|
|
// CHECK-NEXT: br bb
|
|
sil [ossa] @do_not_fold_enum : $@convention(thin) (BoolLike) -> BoolLike {
|
|
bb0(%0 : $BoolLike):
|
|
switch_enum %0 : $BoolLike, case #BoolLike.true_!enumelt: bb1, case #BoolLike.false_!enumelt: bb2
|
|
|
|
bb1:
|
|
%1 = enum $BoolLike, #BoolLike.false_!enumelt
|
|
br bb3(%1 : $BoolLike)
|
|
|
|
bb2:
|
|
%2 = enum $BoolLike, #BoolLike.true_!enumelt
|
|
br bb3(%2 : $BoolLike)
|
|
|
|
bb3(%3 : $BoolLike):
|
|
return %3 : $BoolLike
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @struct_extract_load_to_load_struct_element_addr :
|
|
// CHECK: bb0([[IN:%[0-9]+]] : $*UInt8):
|
|
// CHECK-NEXT: [[IN_GEP:%[0-9]+]] = struct_element_addr [[IN]] : $*UInt8, #UInt8._value
|
|
// CHECK-NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
|
|
// CHECK-NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK-NEXT: [[UINT8:%.*]] = struct $UInt8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK-NEXT: store [[UINT8]] to [trivial] [[IN]] : $*UInt8
|
|
// CHECK-NEXT: return [[IN_LOADED]] : $Builtin.Int8
|
|
// CHECK: } // end sil function 'struct_extract_load_to_load_struct_element_addr'
|
|
sil [ossa] @struct_extract_load_to_load_struct_element_addr : $@convention(thin) (@inout UInt8) -> (Builtin.Int8) {
|
|
bb0(%0 : $*UInt8):
|
|
%1 = load [trivial] %0 : $*UInt8
|
|
%2 = integer_literal $Builtin.Int8, 1
|
|
%3 = struct_element_addr %0 : $*UInt8, #UInt8._value
|
|
store %2 to [trivial] %3 : $*Builtin.Int8
|
|
%5 = struct_extract %1 : $UInt8, #UInt8._value
|
|
return %5 : $Builtin.Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @tuple_extract_load_to_load_tuple_element_addr :
|
|
// CHECK: bb0([[IN:%[0-9]+]] : $*(Builtin.Int8, Builtin.Int8)):
|
|
// CHECK-NEXT: [[IN_GEP:%[0-9]+]] = tuple_element_addr [[IN]] : $*(Builtin.Int8, Builtin.Int8), 0
|
|
// CHECK-NEXT: [[IN_LOADED:%[0-9]+]] = load [trivial] [[IN_GEP]] : $*Builtin.Int8
|
|
// CHECK-NEXT: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK-NEXT: [[IN_STORE_GEP:%[0-9]+]] = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
|
|
// CHECK-NEXT: store [[LITERAL]] to [trivial] [[IN_STORE_GEP]] : $*Builtin.Int8
|
|
// CHECK-NEXT: return [[IN_LOADED]] : $Builtin.Int8
|
|
// CHECK: } // end sil function 'tuple_extract_load_to_load_tuple_element_addr'
|
|
sil [ossa] @tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> (Builtin.Int8) {
|
|
bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
|
|
%1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
|
|
%2 = integer_literal $Builtin.Int8, 1
|
|
%3 = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
|
|
store %2 to [trivial] %3 : $*Builtin.Int8
|
|
%5 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int8), 0
|
|
return %5 : $Builtin.Int8
|
|
}
|
|
|
|
// Do not perform the optimization of the input load has multiple uses.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @multiple_use_struct_extract_load_to_load_struct_element_addr
|
|
// CHECK: bb0([[IN:%[0-9]+]] : $*UInt8):
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: struct
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: struct_extract
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @multiple_use_struct_extract_load_to_load_struct_element_addr : $@convention(thin) (@inout UInt8) -> (UInt8, Builtin.Int8) {
|
|
bb0(%0 : $*UInt8):
|
|
%1 = load [trivial] %0 : $*UInt8
|
|
%2 = integer_literal $Builtin.Int8, 1
|
|
%3 = struct_element_addr %0 : $*UInt8, #UInt8._value
|
|
store %2 to [trivial] %3 : $*Builtin.Int8
|
|
%5 = struct_extract %1 : $UInt8, #UInt8._value
|
|
%6 = tuple (%1 : $UInt8, %5 : $Builtin.Int8)
|
|
return %6 : $(UInt8, Builtin.Int8)
|
|
}
|
|
|
|
// Do not perform the optimization of the input load has multiple uses.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @multiple_use_tuple_extract_load_to_load_tuple_element_addr
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: tuple_extract
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @multiple_use_tuple_extract_load_to_load_tuple_element_addr : $@convention(thin) (@inout (Builtin.Int8, Builtin.Int8)) -> ((Builtin.Int8, Builtin.Int8), Builtin.Int8) {
|
|
bb0(%0 : $*(Builtin.Int8, Builtin.Int8)):
|
|
%1 = load [trivial] %0 : $*(Builtin.Int8, Builtin.Int8)
|
|
%2 = integer_literal $Builtin.Int8, 1
|
|
%3 = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
|
|
store %2 to [trivial] %3 : $*Builtin.Int8
|
|
%5 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int8), 0
|
|
%6 = tuple (%1 : $(Builtin.Int8, Builtin.Int8), %5 : $Builtin.Int8)
|
|
return %6 : $((Builtin.Int8, Builtin.Int8), Builtin.Int8)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @optimize_load_first_char_from_string_literal
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 97
|
|
// CHECK-NEXT: return %0
|
|
sil [ossa] @optimize_load_first_char_from_string_literal : $@convention(thin) () -> Builtin.Int8 {
|
|
bb0:
|
|
%0 = string_literal utf8 "abc123a"
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%2 = struct_element_addr %1 : $*UInt8, #UInt8._value
|
|
%3 = load [trivial] %2 : $*Builtin.Int8
|
|
return %3 : $Builtin.Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @optimize_load_from_string_literal
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: %0 = integer_literal $Builtin.Int8, 49
|
|
// CHECK-NEXT: return %0
|
|
sil [ossa] @optimize_load_from_string_literal : $@convention(thin) () -> Builtin.Int8 {
|
|
bb0:
|
|
%0 = string_literal utf8 "abc123a"
|
|
%1 = integer_literal $Builtin.Word, 3
|
|
%2 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%3 = index_addr %2 : $*UInt8, %1 : $Builtin.Word
|
|
%4 = struct_element_addr %3 : $*UInt8, #UInt8._value
|
|
%5 = load [trivial] %4 : $*Builtin.Int8
|
|
return %5 : $Builtin.Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @optimize_nested_index_addr
|
|
// CHECK: bb0(%0 : $Builtin.RawPointer):
|
|
// CHECK-NEXT: %1 = pointer_to_address %0
|
|
// CHECK-NEXT: %2 = integer_literal $Builtin.Word, 10
|
|
// CHECK-NEXT: %3 = index_addr %1 : $*UInt8, %2
|
|
// CHECK-NEXT: %4 = address_to_pointer %3
|
|
// CHECK-NEXT: return %4
|
|
sil [ossa] @optimize_nested_index_addr : $@convention(thin) (Builtin.RawPointer) -> Builtin.RawPointer {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = integer_literal $Builtin.Word, 3
|
|
%2 = integer_literal $Builtin.Word, 7
|
|
%3 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%4 = index_addr %3 : $*UInt8, %1 : $Builtin.Word
|
|
%5 = index_addr %4 : $*UInt8, %2 : $Builtin.Word
|
|
%6 = address_to_pointer %5 : $*UInt8 to $Builtin.RawPointer
|
|
return %6 : $Builtin.RawPointer
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @destroy_value_test
|
|
// CHECK: bb0({{%[0-9]+}} : $Builtin.Int8, [[RELEASE_TARGET:%[0-9]+]] : @owned $Builtin.NativeObject):
|
|
// CHECK-NEXT: destroy_value [[RELEASE_TARGET]] : $Builtin.NativeObject
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @destroy_value_test : $@convention(thin) (Builtin.Int8, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $Builtin.Int8, %1 : @owned $Builtin.NativeObject):
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @retain_value_test
|
|
// CHECK: bb0([[TRIVIAL_TARGET:%[0-9]+]] : $Builtin.Int8, [[REFCOUNT_TARGET:%[0-9]+]] : @guaranteed $Builtin.NativeObject):
|
|
// CHECK-NEXT: [[RC:%.*]] = copy_value [[REFCOUNT_TARGET]] : $Builtin.NativeObject
|
|
// CHECK-NEXT: tuple ([[TRIVIAL_TARGET]] : $Builtin.Int8, [[RC]] : $Builtin.NativeObject)
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @retain_value_test : $@convention(thin) (Builtin.Int8, @guaranteed Builtin.NativeObject) -> @owned (Builtin.Int8, Builtin.NativeObject) {
|
|
bb0(%0 : $Builtin.Int8, %1 : @guaranteed $Builtin.NativeObject):
|
|
%1a = copy_value %1 : $Builtin.NativeObject
|
|
%4 = tuple(%0 : $Builtin.Int8, %1a : $Builtin.NativeObject)
|
|
return %4 : $(Builtin.Int8, Builtin.NativeObject)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @a2p_p2a_test
|
|
// CHECK: bb0([[ADR:%[0-9]+]] : $*Builtin.Word, [[RAWPTR:%[0-9]+]] : $Builtin.RawPointer):
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @a2p_p2a_test : $@convention(thin) (@inout Builtin.Word, Builtin.RawPointer) -> (Builtin.Word, Builtin.RawPointer) {
|
|
bb0(%0 : $*Builtin.Word, %1 : $Builtin.RawPointer):
|
|
%2 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer
|
|
%3 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%4 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%5 = address_to_pointer %3 : $*Builtin.Word to $Builtin.RawPointer
|
|
%6 = load [trivial] %4 : $*Builtin.Word
|
|
%7 = tuple(%6 : $Builtin.Word, %5 : $Builtin.RawPointer)
|
|
return %7 : $(Builtin.Word, Builtin.RawPointer)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @a2p_p2a_reinterpret_cast_word_raw_pointer1
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: unchecked_addr_cast
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'a2p_p2a_reinterpret_cast_word_raw_pointer1'
|
|
sil [ossa] @a2p_p2a_reinterpret_cast_word_raw_pointer1 : $@convention(thin) (@inout Builtin.Word, Builtin.RawPointer) -> Int32 {
|
|
bb0(%0 : $*Builtin.Word, %1 : $Builtin.RawPointer):
|
|
%2 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer
|
|
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int32
|
|
%4 = load [trivial] %3 : $*Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
sil @useInt : $@convention(thin) (Int32) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @a2p_p2a_reinterpret_cast_word_raw_pointer2
|
|
// CHECK: unchecked_addr_cast
|
|
// CHECK: } // end sil function 'a2p_p2a_reinterpret_cast_word_raw_pointer2'
|
|
sil [ossa] @a2p_p2a_reinterpret_cast_word_raw_pointer2 : $@convention(thin) (@owned ContiguousArray<UInt16>) -> () {
|
|
bb0(%0 : @owned $ContiguousArray<UInt16>):
|
|
%1 = begin_borrow %0 : $ContiguousArray<UInt16>
|
|
%2 = struct_extract %1 : $ContiguousArray<UInt16>, #ContiguousArray._buffer
|
|
%3 = struct_extract %2 : $_ContiguousArrayBuffer<UInt16>, #_ContiguousArrayBuffer._storage
|
|
%4 = ref_tail_addr %3 : $__ContiguousArrayStorageBase, $UInt16
|
|
%5 = address_to_pointer %4 : $*UInt16 to $Builtin.RawPointer
|
|
br bb1
|
|
|
|
bb1:
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*Int32
|
|
%7 = load [trivial] %6 : $*Int32
|
|
%8 = function_ref @useInt : $@convention(thin) (Int32) -> ()
|
|
%9 = apply %8(%7) : $@convention(thin) (Int32) -> ()
|
|
end_borrow %1 : $ContiguousArray<UInt16>
|
|
destroy_value %0 : $ContiguousArray<UInt16>
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @sil_extract_of_string
|
|
//
|
|
// Make sure we only forward the first field of the string_literal
|
|
// instead of the whole string literal. Otherwise we run into arity
|
|
// issues.
|
|
sil [ossa] @sil_extract_of_string : $@convention(thin) () -> Builtin.Word {
|
|
%0 = string_literal utf8 ""
|
|
%l1 = integer_literal $Builtin.Word, 0
|
|
%1 = struct $StringData (%l1 : $Builtin.Word)
|
|
%2 = struct_extract %1 : $StringData, #StringData.size
|
|
return %2 : $Builtin.Word
|
|
}
|
|
|
|
class C {}
|
|
|
|
enum U {
|
|
init()
|
|
case X
|
|
case Y(Builtin.Int64)
|
|
case Z(C)
|
|
}
|
|
|
|
// RefToRawPointer pointer consumption.
|
|
//
|
|
// (ref_to_raw_pointer (unchecked_ref_cast x))
|
|
// -> (ref_to_raw_pointer x)
|
|
// CHECK-LABEL: sil [ossa] @ref_to_raw_pointer_unchecked_ref_cast_composition : $@convention(thin) (@guaranteed C) -> Builtin.RawPointer
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: ref_to_raw_pointer
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @ref_to_raw_pointer_unchecked_ref_cast_composition : $@convention(thin) (@guaranteed C) -> Builtin.RawPointer {
|
|
bb0(%0 : @guaranteed $C):
|
|
%1 = unchecked_ref_cast %0 : $C to $Builtin.NativeObject
|
|
%2 = ref_to_raw_pointer %1 : $Builtin.NativeObject to $Builtin.RawPointer
|
|
return %2 : $Builtin.RawPointer
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @downcast_upcast_roundtrip :
|
|
// CHECK-NOT: upcast
|
|
// CHECK-NOT: unconditional_checked_cast
|
|
// CHECK: } // end sil function 'downcast_upcast_roundtrip'
|
|
sil [ossa] @downcast_upcast_roundtrip : $@convention(thin) <T_0_0, T_0_1> (@owned HeapBufferStorage<T_0_0, T_0_1>) -> @owned HeapBufferStorage<T_0_0, T_0_1> {
|
|
bb0(%0 : @owned $HeapBufferStorage<T_0_0, T_0_1>):
|
|
%2 = upcast %0 : $HeapBufferStorage<T_0_0, T_0_1> to $RawBuffer // user: %3
|
|
%3 = unconditional_checked_cast %2 : $RawBuffer to HeapBufferStorage<T_0_0, T_0_1>
|
|
return %3 : $HeapBufferStorage<T_0_0, T_0_1>
|
|
}
|
|
|
|
class Derived : C {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_unconditional_checked_cast :
|
|
// CHECK-NOT: unconditional_checked_cast
|
|
// CHECK: destroy_value %0
|
|
// CHECK: } // end sil function 'dead_unconditional_checked_cast'
|
|
sil [ossa] @dead_unconditional_checked_cast : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
%1 = unconditional_checked_cast %0 : $C to Derived
|
|
destroy_value %1 : $Derived
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cond_fail_applied_to_zero_removal :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_fail
|
|
// CHECK-NEXT: tuple ()
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'cond_fail_applied_to_zero_removal'
|
|
sil [ossa] @cond_fail_applied_to_zero_removal : $@convention(thin) (Builtin.Int1) -> () {
|
|
bb0(%0 : $Builtin.Int1):
|
|
cond_fail %0 : $Builtin.Int1
|
|
%1 = integer_literal $Builtin.Int1, 0
|
|
cond_fail %1 : $Builtin.Int1
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_unchecked_ref_cast_round_trip :
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_unchecked_ref_cast_round_trip'
|
|
sil [ossa] @unchecked_ref_cast_unchecked_ref_cast_round_trip : $@convention(thin) <T_0_0, T_0_1> (@owned HeapBufferStorage<T_0_0, T_0_1>) -> @owned HeapBufferStorage<T_0_0, T_0_1> {
|
|
bb0(%0 : @owned $HeapBufferStorage<T_0_0, T_0_1>):
|
|
%1 = unchecked_ref_cast %0 : $HeapBufferStorage<T_0_0, T_0_1> to $Builtin.NativeObject
|
|
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $HeapBufferStorage<T_0_0, T_0_1>
|
|
return %2 : $HeapBufferStorage<T_0_0, T_0_1>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @raw_pointer_to_ref_ref_to_raw_pointer_round_trip
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @raw_pointer_to_ref_ref_to_raw_pointer_round_trip : $@convention(thin) (Builtin.RawPointer) -> Builtin.RawPointer {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = raw_pointer_to_ref %0 : $Builtin.RawPointer to $C
|
|
%2 = ref_to_raw_pointer %1 : $C to $Builtin.RawPointer
|
|
return %2 : $Builtin.RawPointer
|
|
}
|
|
|
|
sil [ossa] @test_closure : $@convention(thin) (@guaranteed C) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_closure_elimination :
|
|
// CHECK-NOT: function_ref
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: } // end sil function 'dead_closure_elimination'
|
|
sil [ossa] @dead_closure_elimination : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
%1 = function_ref @test_closure : $@convention(thin) (@guaranteed C) -> ()
|
|
%2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (@guaranteed C) -> ()
|
|
cond_br undef, bb1, bb2a
|
|
|
|
bb1:
|
|
%2a = copy_value %2 : $@callee_guaranteed () -> ()
|
|
destroy_value %2a : $@callee_guaranteed () -> ()
|
|
br bb2
|
|
|
|
bb2a:
|
|
br bb2
|
|
|
|
bb2:
|
|
destroy_value %2 : $@callee_guaranteed () -> ()
|
|
%5 = tuple()
|
|
return %5 : $()
|
|
}
|
|
|
|
////////////////////////////////////////////
|
|
// Load Proj To GEP Load Canonicalization //
|
|
////////////////////////////////////////////
|
|
|
|
struct Y {
|
|
var int : Builtin.Int64
|
|
var ptr : Builtin.NativeObject
|
|
var tup : (Builtin.Int32, Builtin.Int1)
|
|
}
|
|
|
|
struct X {
|
|
var y : Y
|
|
var t : (Builtin.NativeObject, Y)
|
|
}
|
|
|
|
sil [ossa] @mix1 : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
sil [ossa] @mix2 : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_proj_to_gep_load_canonicalization_no_rep_no_other_use_test : $@convention(thin) (@inout X) -> ()
|
|
// CHECK-NOT: struct_extract
|
|
// CHECK-NOT: tuple_extract
|
|
sil [ossa] @load_proj_to_gep_load_canonicalization_no_rep_no_other_use_test : $@convention(thin) (@inout X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = load_borrow %0 : $*X
|
|
%2 = struct_extract %1 : $X, #X.y
|
|
%3 = struct_extract %2 : $Y, #Y.int
|
|
%4 = struct_extract %2 : $Y, #Y.ptr
|
|
%5 = struct_extract %2 : $Y, #Y.tup
|
|
%6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1
|
|
%8 = struct_extract %1 : $X, #X.t
|
|
%9 = tuple_extract %8 : $(Builtin.NativeObject, Y), 0
|
|
%10 = tuple_extract %8 : $(Builtin.NativeObject, Y), 1
|
|
%11 = struct_extract %10 : $Y, #Y.int
|
|
%12 = struct_extract %10 : $Y, #Y.ptr
|
|
%13 = struct_extract %10 : $Y, #Y.tup
|
|
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%15 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 1
|
|
%16 = function_ref @mix1 : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
apply %16(%3, %4, %6, %7) : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
%17 = function_ref @mix2 : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
apply %17(%9, %11, %12, %14, %15) : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
end_borrow %1 : $X
|
|
%18 = tuple()
|
|
return %18 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_proj_to_gep_load_canonicalization_with_rep_no_other_use_test : $@convention(thin) (@inout X) -> ()
|
|
// CHECK-NOT: struct_extract
|
|
// CHECK-NOT: tuple_extract
|
|
// CHECK: apply {{%[0-9]+}}([[ARG1:%[0-9]+]], [[ARG2:%[0-9]+]], [[ARG3:%[0-9]+]], [[ARG4:%[0-9]+]]
|
|
// CHECK-NEXT: apply {{%[0-9]+}}([[ARG1]], [[ARG2]], [[ARG3]], [[ARG4]]
|
|
// CHECK-NOT: struct_extract
|
|
// CHECK-NOT: tuple_extract
|
|
sil [ossa] @load_proj_to_gep_load_canonicalization_with_rep_no_other_use_test : $@convention(thin) (@inout X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = load_borrow %0 : $*X
|
|
%2 = struct_extract %1 : $X, #X.y
|
|
%3 = struct_extract %2 : $Y, #Y.int
|
|
%4 = struct_extract %2 : $Y, #Y.ptr
|
|
%5 = struct_extract %2 : $Y, #Y.tup
|
|
%6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1
|
|
%16 = function_ref @mix1 : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
apply %16(%3, %4, %6, %7) : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
%19 = struct_extract %2 : $Y, #Y.int
|
|
%20 = struct_extract %2 : $Y, #Y.ptr
|
|
%21 = struct_extract %2 : $Y, #Y.tup
|
|
%22 = tuple_extract %21 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%23 = tuple_extract %21 : $(Builtin.Int32, Builtin.Int1), 1
|
|
apply %16(%19, %20, %22, %23) : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
end_borrow %1 : $X
|
|
%18 = tuple()
|
|
return %18 : $()
|
|
}
|
|
|
|
sil [ossa] @disrupting_use : $@convention(thin) (@guaranteed Y) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_proj_to_gep_load_canonicalization_no_rep_with_disrupting_use_test : $@convention(thin) (@inout X) -> ()
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: tuple_element_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: struct_extract
|
|
// CHECK-NEXT: struct_extract
|
|
// CHECK-NEXT: struct_extract
|
|
// CHECK-NEXT: tuple_extract
|
|
// CHECK-NEXT: tuple_extract
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: end_borrow
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @load_proj_to_gep_load_canonicalization_no_rep_with_disrupting_use_test : $@convention(thin) (@inout X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = load_borrow %0 : $*X
|
|
%2 = struct_extract %1 : $X, #X.y
|
|
%3 = struct_extract %2 : $Y, #Y.int
|
|
%4 = struct_extract %2 : $Y, #Y.ptr
|
|
%5 = struct_extract %2 : $Y, #Y.tup
|
|
%6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1
|
|
%8 = struct_extract %1 : $X, #X.t
|
|
%9 = tuple_extract %8 : $(Builtin.NativeObject, Y), 0
|
|
%10 = tuple_extract %8 : $(Builtin.NativeObject, Y), 1
|
|
%11 = struct_extract %10 : $Y, #Y.int
|
|
%12 = struct_extract %10 : $Y, #Y.ptr
|
|
%13 = struct_extract %10 : $Y, #Y.tup
|
|
%14 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 0
|
|
%15 = tuple_extract %13 : $(Builtin.Int32, Builtin.Int1), 1
|
|
%16 = function_ref @mix1 : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
apply %16(%3, %4, %6, %7) : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
%17 = function_ref @mix2 : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
apply %17(%9, %11, %12, %14, %15) : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.Int32, Builtin.Int1) -> ()
|
|
%18 = function_ref @disrupting_use : $@convention(thin) (@guaranteed Y) -> ()
|
|
apply %18(%10) : $@convention(thin) (@guaranteed Y) -> ()
|
|
end_borrow %1 : $X
|
|
%19 = tuple()
|
|
return %19 : $()
|
|
}
|
|
|
|
sil [ossa] @unbalanced_closure : $@convention(thin) (@guaranteed B) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @partial_apply_unbalanced_retain_release :
|
|
// CHECK: bb0
|
|
// CHECK-NOT: partial_apply
|
|
// Check that the arguments of the closure are released after its last use
|
|
// CHECK-NEXT: destroy_value %0 : $B
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'partial_apply_unbalanced_retain_release'
|
|
sil [ossa] @partial_apply_unbalanced_retain_release : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = function_ref @unbalanced_closure : $@convention(thin) (@guaranteed B) -> ()
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (@guaranteed B) -> ()
|
|
%2a = copy_value %2 : $@callee_owned () -> ()
|
|
destroy_value %2 : $@callee_owned () -> ()
|
|
destroy_value %2a : $@callee_owned () -> ()
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
class C1 {}
|
|
class C2 : C1 {}
|
|
class C3 : C2 {}
|
|
|
|
sil @use_c2_owned : $@convention(thin) (@owned C2) -> ()
|
|
sil @use_c2_guaranteed : $@convention(thin) (@guaranteed C2) -> ()
|
|
sil @use_c2_unowned : $@convention(thin) (C2) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_owned :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: upcast
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_owned'
|
|
sil [ossa] @upcast_upcast_merge_owned : $@convention(thin) (@owned C3) -> @owned C1 {
|
|
bb0(%0 : @owned $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%2 = upcast %1 : $C2 to $C1
|
|
return %2 : $C1
|
|
}
|
|
|
|
// We sink in this case the original upcast into bb2 before its use.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_owned_different_bb :
|
|
// CHECK: bb0([[ARG0:%.*]] : @owned $C3,
|
|
// CHECK-NEXT: cond_br undef, bb1, bb2
|
|
//
|
|
// CHECK: bb1:
|
|
// CHECK: upcast [[ARG0]] : $C3 to $C1
|
|
// CHECK: br bb3(
|
|
//
|
|
// CHECK: bb2:
|
|
// CHECK: [[ARG0_CAST:%.*]] = upcast [[ARG0]] : $C3 to $C2
|
|
// CHECK: apply {{%.*}}([[ARG0_CAST]])
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_owned_different_bb'
|
|
sil [ossa] @upcast_upcast_merge_owned_different_bb : $@convention(thin) (@owned C3, @guaranteed C1) -> @owned C1 {
|
|
bb0(%0 : @owned $C3, %0a : @guaranteed $C1):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = upcast %1 : $C2 to $C1
|
|
br bb3(%2 : $C1)
|
|
|
|
bb2:
|
|
%0aCopy = copy_value %0a : $C1
|
|
%useC2Owned = function_ref @use_c2_owned : $@convention(thin) (@owned C2) -> ()
|
|
apply %useC2Owned(%1) : $@convention(thin) (@owned C2) -> ()
|
|
br bb3(%0aCopy : $C1)
|
|
|
|
bb3(%result : @owned $C1):
|
|
return %result : $C1
|
|
}
|
|
|
|
// In this case, we only have a destroy_value,s o we just put it on %0 and
|
|
// eliminate it, implying we should have a single upcast.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_owned_different_bb_1 :
|
|
// CHECK: upcast
|
|
// CHECK-NOT: upcast
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_owned_different_bb_1'
|
|
sil [ossa] @upcast_upcast_merge_owned_different_bb_1 : $@convention(thin) (@owned C3, @guaranteed C1) -> @owned C1 {
|
|
bb0(%0 : @owned $C3, %0a : @guaranteed $C1):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = upcast %1 : $C2 to $C1
|
|
br bb3(%2 : $C1)
|
|
|
|
bb2:
|
|
%0aCopy = copy_value %0a : $C1
|
|
destroy_value %1 : $C2
|
|
br bb3(%0aCopy : $C1)
|
|
|
|
bb3(%result : @owned $C1):
|
|
return %result : $C1
|
|
}
|
|
|
|
|
|
// We can't eliminate the first upcast, so we do not perform this opt and break
|
|
// up the forwarding chain. This would be a less canonical representation since
|
|
// it has unneeded ARC traffic.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_no_erase_owned :
|
|
// CHECK: bb0([[ARG:%.*]] : @owned $C3):
|
|
// CHECK: [[ARG_UPCAST:%.*]] = upcast [[ARG]]
|
|
// CHECK: upcast [[ARG_UPCAST]]
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_no_erase_owned'
|
|
sil [ossa] @upcast_upcast_merge_no_erase_owned : $@convention(thin) (@owned C3) -> @owned C1 {
|
|
bb0(%0 : @owned $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%f = function_ref @use_c2_guaranteed : $@convention(thin) (@guaranteed C2) -> ()
|
|
apply %f(%1) : $@convention(thin) (@guaranteed C2) -> ()
|
|
%2 = upcast %1 : $C2 to $C1
|
|
return %2 : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_guaranteed :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: upcast
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_guaranteed'
|
|
sil [ossa] @upcast_upcast_merge_guaranteed : $@convention(thin) (@guaranteed C3) -> @owned C1 {
|
|
bb0(%0 : @guaranteed $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%2 = upcast %1 : $C2 to $C1
|
|
%3 = copy_value %2 : $C1
|
|
return %3 : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_guaranteed_loop :
|
|
// CHECK: bb0
|
|
// CHECK: upcast
|
|
// CHECK-NOT: upcast
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_guaranteed_loop'
|
|
sil [ossa] @upcast_upcast_merge_guaranteed_loop : $@convention(thin) (@guaranteed C3, @owned C1) -> @owned C1 {
|
|
bb0(%0 : @guaranteed $C3, %0b : @owned $C1):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
br bb1
|
|
|
|
bb1:
|
|
br bb2(%0b : $C1)
|
|
|
|
bb2(%2a : @owned $C1):
|
|
cond_br undef, bb3, bb4
|
|
|
|
bb3:
|
|
%3 = upcast %1 : $C2 to $C1
|
|
%4 = copy_value %3 : $C1
|
|
destroy_value %2a : $C1
|
|
br bb2(%4 : $C1)
|
|
|
|
bb4:
|
|
return %2a : $C1
|
|
}
|
|
|
|
// We can't eliminate the first upcast, so we RAUW but have to do a copy.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_no_erase_guaranteed :
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $C3):
|
|
// CHECK: [[OLD_UPCAST:%.*]] = upcast [[ARG]]
|
|
// CHECK: [[FUNC:%.*]] = function_ref @use_c2_guaranteed : $@convention(thin) (@guaranteed C2) -> ()
|
|
// CHECK: apply [[FUNC]]([[OLD_UPCAST]])
|
|
// CHECK: [[RESULT:%.*]] = upcast [[ARG]]
|
|
// CHECK: [[RESULT_COPY:%.*]] = copy_value [[RESULT]]
|
|
// CHECK: return [[RESULT_COPY]]
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_no_erase_guaranteed'
|
|
sil [ossa] @upcast_upcast_merge_no_erase_guaranteed : $@convention(thin) (@guaranteed C3) -> @owned C1 {
|
|
bb0(%0 : @guaranteed $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%f = function_ref @use_c2_guaranteed : $@convention(thin) (@guaranteed C2) -> ()
|
|
apply %f(%1) : $@convention(thin) (@guaranteed C2) -> ()
|
|
%2 = upcast %1 : $C2 to $C1
|
|
%3 = copy_value %2 : $C1
|
|
return %3 : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_unowned :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: upcast
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_unowned'
|
|
sil [ossa] @upcast_upcast_merge_unowned : $@convention(thin) (C3) -> @owned C1 {
|
|
bb0(%0 : @unowned $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%2 = upcast %1 : $C2 to $C1
|
|
%3 = copy_value %2 : $C1
|
|
return %3 : $C1
|
|
}
|
|
|
|
// We can't eliminate the first upcast.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @upcast_upcast_merge_no_erase_unowned :
|
|
// CHECK: bb0([[ARG:%.*]] : @unowned $C3):
|
|
// CHECK: [[OLD_UPCAST:%.*]] = upcast [[ARG]]
|
|
// CHECK: [[FUNC:%.*]] = function_ref @use_c2_unowned : $@convention(thin) (C2) -> ()
|
|
// CHECK: apply [[FUNC]]([[OLD_UPCAST]])
|
|
// CHECK: [[RESULT:%.*]] = upcast [[ARG]]
|
|
// CHECK: [[RESULT_COPY:%.*]] = copy_value [[RESULT]]
|
|
// CHECK: return [[RESULT_COPY]]
|
|
// CHECK: } // end sil function 'upcast_upcast_merge_no_erase_unowned'
|
|
sil [ossa] @upcast_upcast_merge_no_erase_unowned : $@convention(thin) (C3) -> @owned C1 {
|
|
bb0(%0 : @unowned $C3):
|
|
%1 = upcast %0 : $C3 to $C2
|
|
%f = function_ref @use_c2_unowned : $@convention(thin) (C2) -> ()
|
|
apply %f(%1) : $@convention(thin) (C2) -> ()
|
|
%2 = upcast %1 : $C2 to $C1
|
|
%3 = copy_value %2 : $C1
|
|
return %3 : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_upcast
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @dead_upcast : $@convention(thin) (@guaranteed C2) -> @owned C2 {
|
|
bb0(%0 : @guaranteed $C2):
|
|
%1 = upcast %0 : $C2 to $C1
|
|
%0a = copy_value %0 : $C2
|
|
return %0a : $C2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_unchecked_ref_cast
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @dead_unchecked_ref_cast : $@convention(thin) (@guaranteed C1) -> @owned C1 {
|
|
bb0(%0 : @guaranteed $C1):
|
|
%1 = unchecked_ref_cast %0 : $C1 to $C2
|
|
%0a = copy_value %0 : $C1
|
|
return %0a : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_end_cow_mutation :
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: destroy_value %0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dead_end_cow_mutation'
|
|
sil [ossa] @dead_end_cow_mutation : $@convention(thin) (@owned C1) -> () {
|
|
bb0(%0 : @owned $C1):
|
|
%1 = end_cow_mutation %0 : $C1
|
|
destroy_value %1 : $C1
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @end_cow_mutation_of_cast :
|
|
// CHECK: %1 = end_cow_mutation %0
|
|
// CHECK-NEXT: %2 = upcast %1
|
|
// CHECK-NEXT: return %2
|
|
// CHECK: } // end sil function 'end_cow_mutation_of_cast'
|
|
sil [ossa] @end_cow_mutation_of_cast : $@convention(thin) (@owned C2) -> @owned C1 {
|
|
bb0(%0 : @owned $C2):
|
|
%1 = upcast %0 : $C2 to $C1
|
|
%2 = end_cow_mutation %1 : $C1
|
|
return %2 : $C1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @end_cow_mutation_of_cast2 :
|
|
// CHECK: %1 = end_cow_mutation [keep_unique] %0
|
|
// CHECK-NEXT: %2 = upcast %1
|
|
// CHECK-NEXT: return %2
|
|
// CHECK: } // end sil function 'end_cow_mutation_of_cast2'
|
|
sil [ossa] @end_cow_mutation_of_cast2 : $@convention(thin) (@owned C2) -> @owned C1 {
|
|
bb0(%0 : @owned $C2):
|
|
%1 = upcast %0 : $C2 to $C1
|
|
%2 = end_cow_mutation [keep_unique] %1 : $C1
|
|
return %2 : $C1
|
|
}
|
|
|
|
struct XS {
|
|
var m: Int
|
|
var k: Float
|
|
init(x: XS)
|
|
}
|
|
|
|
// CHECK-LABEL: strc_from_extr
|
|
// CHECK-NOT: struct_extract
|
|
// CHECK-NOT: struct
|
|
// CHECK: return
|
|
sil [ossa] @strc_from_extr : $@convention(thin) (XS, @thin XS.Type) -> XS {
|
|
bb0(%0 : $XS, %1 : $@thin XS.Type):
|
|
%2 = struct_extract %0 : $XS, #XS.m
|
|
%3 = struct_extract %0 : $XS, #XS.k
|
|
%4 = struct $XS (%2 : $Int, %3 : $Float)
|
|
return %4 : $XS
|
|
}
|
|
|
|
// CHECK-LABEL: tup_from_extr_tup
|
|
// CHECK-NOT: tuple_extract
|
|
// CHECK-NOT: tuple
|
|
// CHECK: return
|
|
sil [ossa] @tup_from_extr_tup : $@convention(thin) () -> (Int, Int) {
|
|
bb0:
|
|
// function_ref x
|
|
%0 = function_ref @tup_from_extr_tup : $@convention(thin) () -> (Int, Int) // user: %1
|
|
%1 = apply %0() : $@convention(thin) () -> (Int, Int) // users: %2, %3
|
|
%2 = tuple_extract %1 : $(Int, Int), 0 // user: %4
|
|
%3 = tuple_extract %1 : $(Int, Int), 1 // user: %4
|
|
%4 = tuple (%2 : $Int, %3 : $Int) // user: %5
|
|
return %4 : $(Int, Int) // id: %5
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @apply_and_pa_merge :
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: [[C:%.*]] = function_ref @some_closure
|
|
// CHECK: [[P:%.*]] = function_ref @print_a_number
|
|
// CHECK: [[R1:%.*]] = apply [[C]](
|
|
// CHECK: = apply [[P]]([[R1]]
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'apply_and_pa_merge'
|
|
sil [ossa] @apply_and_pa_merge : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = function_ref @some_closure : $@convention(thin) (Int) -> Int // user: %2
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (Int) -> Int // users: %4, %5, %7
|
|
%3 = function_ref @print_a_number : $@convention(thin) (Int) -> () // user: %6
|
|
%2a = copy_value %2 : $@callee_owned () -> Int // id: %4
|
|
%5 = apply %2a() : $@callee_owned () -> Int // user: %6
|
|
%6 = apply %3(%5) : $@convention(thin) (Int) -> ()
|
|
destroy_value %2 : $@callee_owned () -> Int // id: %7
|
|
%8 = tuple () // user: %9
|
|
return %8 : $() // id: %9
|
|
}
|
|
|
|
sil [ossa] @some_closure : $@convention(thin) (Int) -> Int
|
|
sil [ossa] @print_a_number : $@convention(thin) (Int) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @applied
|
|
sil [ossa] @applied : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
// CHECK: return
|
|
return %0 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @combine_partial_apply_with_apply :
|
|
// CHECK: [[APPLIED:%.*]] = function_ref @applied
|
|
// CHECK: [[THICK:%.*]] = thin_to_thick_function [[APPLIED]]
|
|
// CHECK: [[REABSTRACT:%.*]] = function_ref @reabstract
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: [[TMP:%.*]] = alloc_stack $Builtin.Int32
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: apply [[REABSTRACT]]([[TMP]], %0, [[THICK]])
|
|
// CHECK-NOT: destroy_value
|
|
// CHECK-NOT: tuple
|
|
// CHECK: [[RESULT:%.*]] = load [trivial] [[TMP]]
|
|
// CHECK: dealloc_stack [[TMP]]
|
|
// CHECK: return [[RESULT]]
|
|
// CHECK: } // end sil function 'combine_partial_apply_with_apply'
|
|
sil [ossa] @combine_partial_apply_with_apply : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%2 = function_ref @applied : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
|
|
%3 = thin_to_thick_function %2 : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 to $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
%4 = function_ref @reabstract : $@convention(thin) (Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> Builtin.Int32) -> @out Builtin.Int32
|
|
%5 = partial_apply %4(%3) : $@convention(thin) (Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> Builtin.Int32) -> @out Builtin.Int32
|
|
%6 = alloc_stack $Builtin.Int32
|
|
%5a = copy_value %5 : $@callee_owned (Builtin.Int32) -> @out Builtin.Int32
|
|
%8 = apply %5a(%6, %0) : $@callee_owned (Builtin.Int32) -> @out Builtin.Int32
|
|
destroy_value %5 : $@callee_owned (Builtin.Int32) -> @out Builtin.Int32
|
|
%10 = tuple ()
|
|
%11 = load [trivial] %6 : $*Builtin.Int32
|
|
dealloc_stack %6 : $*Builtin.Int32
|
|
return %11 : $Builtin.Int32
|
|
}
|
|
|
|
// TODO: What is this testing?
|
|
//
|
|
// CHECK-LABEL: sil shared [transparent] [ossa] @reabstract :
|
|
// CHECK: return
|
|
sil shared [ossa] [transparent] @reabstract : $@convention(thin) (Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> Builtin.Int32) -> @out Builtin.Int32 {
|
|
bb0(%0 : $*Builtin.Int32, %1 : $Builtin.Int32, %2 : @owned $@callee_owned (Builtin.Int32) -> Builtin.Int32):
|
|
%3 = apply %2(%1) : $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
store %3 to [trivial] %0 : $*Builtin.Int32
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @generic_is_objc :
|
|
// CHECK: [[TYPE:%[a-zA-Z0-9]+]] = metatype $@thick [[ARCH:[a-zA-Z]+]].Type
|
|
// CHECK: builtin "canBeClass"<[[ARCH]]>([[TYPE]] : $@thick [[ARCH]].Type)
|
|
// CHECK: } // end sil function 'generic_is_objc'
|
|
sil [ossa] @generic_is_objc : $@convention(thin) <T> (@in T) -> Int8 {
|
|
bb0(%0 : $*T):
|
|
%1 = metatype $@thick T.Type // user: %3
|
|
%3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8 // user: %4
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8) // user: %6
|
|
destroy_addr %0 : $*T // id: %5
|
|
return %4 : $Int8 // id: %6
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @is_int_objc :
|
|
// CHECK-NOT: builtin "canBeClass"
|
|
// CHECK-NOT: apply
|
|
// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 0
|
|
// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK: return [[RESULT]] : $Int8
|
|
// CHECK: } // end sil function 'is_int_objc'
|
|
sil [ossa] @is_int_objc : $@convention(thin) (Int) -> Int8 {
|
|
bb0(%0 : $Int):
|
|
%1 = metatype $@thick Int.Type // user: %3
|
|
%3 = builtin "canBeClass"<Int>(%1 : $@thick Int.Type) : $Builtin.Int8 // user: %4
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8) // user: %5
|
|
return %4 : $Int8 // id: %5
|
|
}
|
|
|
|
// An archetype with a trivial layout constraint can never be a class.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @is_trivial_layout_constraint_class :
|
|
// CHECK-NOT: builtin "canBeClass"
|
|
// CHECK-NOT: apply
|
|
// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 0
|
|
// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK: return [[RESULT]] : $Int8
|
|
// CHECK: } // end sil function 'is_trivial_layout_constraint_class'
|
|
sil [ossa] @is_trivial_layout_constraint_class : $@convention(thin) <T where T: _Trivial> (@in T) -> Int8 {
|
|
bb0(%0 : $*T):
|
|
%1 = metatype $@thick T.Type
|
|
%3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8)
|
|
return %4 : $Int8
|
|
}
|
|
|
|
// An archetype with a _Class layout constraint is always a class.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @is_class_layout_constraint_class
|
|
// CHECK-NOT: builtin "canBeClass"
|
|
// CHECK-NOT: apply
|
|
// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK: return [[RESULT]] : $Int8
|
|
// CHECK: } // end sil function 'is_class_layout_constraint_class'
|
|
sil [ossa] @is_class_layout_constraint_class : $@convention(thin) <T where T: _Class> (@in T) -> Int8 {
|
|
bb0(%0 : $*T):
|
|
%1 = metatype $@thick T.Type
|
|
%3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8)
|
|
destroy_addr %0 : $*T
|
|
return %4 : $Int8
|
|
}
|
|
|
|
// An archetype with a _NativeClass layout constraint is always a class.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @is_native_class_layout_constraint_class :
|
|
// CHECK-NOT: builtin "canBeClass"
|
|
// CHECK-NOT: apply
|
|
// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK: return [[RESULT]] : $Int8
|
|
// CHECK: } // end sil function 'is_native_class_layout_constraint_class'
|
|
sil [ossa] @is_native_class_layout_constraint_class : $@convention(thin) <T where T: _NativeClass> (@in T) -> Int8 {
|
|
bb0(%0 : $*T):
|
|
%1 = metatype $@thick T.Type
|
|
%3 = builtin "canBeClass"<T>(%1 : $@thick T.Type) : $Builtin.Int8
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8)
|
|
destroy_addr %0 : $*T
|
|
return %4 : $Int8
|
|
}
|
|
|
|
@objc class MyClass {
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @is_objc_class_objc :
|
|
// CHECK-NOT: builtin "canBeClass"
|
|
// CHECK: [[LITERAL:%[a-zA-Z0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK: [[RESULT:%[a-zA-Z0-9]+]] = struct $Int8 ([[LITERAL]] : $Builtin.Int8)
|
|
// CHECK: return [[RESULT]] : $Int8
|
|
// CHECK: } // end sil function 'is_objc_class_objc'
|
|
sil [ossa] @is_objc_class_objc : $@convention(thin) (@owned MyClass) -> Int8 {
|
|
bb0(%0 : @owned $MyClass):
|
|
%1 = metatype $@thick MyClass.Type // user: %3
|
|
%3 = builtin "canBeClass"<MyClass>(%1 : $@thick MyClass.Type) : $Builtin.Int8 // user: %4
|
|
%4 = struct $Int8 (%3 : $Builtin.Int8) // user: %6
|
|
destroy_value %0 : $MyClass // id: %5
|
|
return %4 : $Int8 // id: %6
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @constant_expect_hint :
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: [[INT1:%[0-9]+]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK-NEXT: [[INT2:%[0-9]+]] = integer_literal $Builtin.Int32, 5
|
|
// CHECK-NEXT: [[INT3:%[0-9]+]] = integer_literal $Builtin.Int64, 32
|
|
// CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ([[INT1]] : $Builtin.Int1, [[INT2]] : $Builtin.Int32, [[INT3]] : $Builtin.Int64)
|
|
// CHECK-NEXT: return [[TUPLE]]
|
|
// CHECK-NEXT: } // end sil function 'constant_expect_hint'
|
|
sil [ossa] @constant_expect_hint : $@convention(thin) () -> (Builtin.Int1, Builtin.Int32, Builtin.Int64) {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int1, 0
|
|
%1 = integer_literal $Builtin.Int32, 5
|
|
%2 = integer_literal $Builtin.Int64, 32
|
|
|
|
%3 = integer_literal $Builtin.Int1, 1
|
|
%4 = integer_literal $Builtin.Int32, 400
|
|
%5 = integer_literal $Builtin.Int64, 5000
|
|
|
|
%9 = builtin "int_expect_Int1"(%0 : $Builtin.Int1, %3 : $Builtin.Int1) : $Builtin.Int1
|
|
%10 = builtin "int_expect_Int32"(%1 : $Builtin.Int32, %4 : $Builtin.Int32) : $Builtin.Int32
|
|
%11 = builtin "int_expect_Int64"(%2 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int64
|
|
|
|
%12 = tuple (%9 : $Builtin.Int1, %10 : $Builtin.Int32, %11 : $Builtin.Int64)
|
|
return %12 : $(Builtin.Int1, Builtin.Int32, Builtin.Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: @_TF6expect3fooFSiSi :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function '_TF6expect3fooFSiSi'
|
|
sil [ossa] @_TF6expect3fooFSiSi : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%5 = integer_literal $Builtin.Int1, -1
|
|
%9 = builtin "xor_Int1"(%0 : $Builtin.Int1, %5 : $Builtin.Int1) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2 // id: %10
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_promotion_of_concrete_types
|
|
// CHECK: bb0([[INT_PTR:%[0-9]+]]
|
|
// CHECK-NEXT: [[ALLOCA1:%[0-9]+]] = alloc_stack $FakeOptional<Builtin.Int1>
|
|
// CHECK-NEXT: [[ENUM1:%[0-9]+]] = enum $FakeOptional<Builtin.Int1>, #FakeOptional.none!enumelt
|
|
// CHECK-NEXT: store [[ENUM1]] to [trivial] [[ALLOCA1]]
|
|
// CHECK-NEXT: [[ALLOCA2:%[0-9]+]] = alloc_stack $FakeOptional<Builtin.Int1>
|
|
// CHECK-NEXT: [[INT:%[0-9]+]] = load [trivial] [[INT_PTR]] : $*Builtin.Int1
|
|
// CHECK-NEXT: [[ENUM2:%[0-9]+]] = enum $FakeOptional<Builtin.Int1>, #FakeOptional.some!enumelt, [[INT]] : $Builtin.Int1
|
|
// CHECK-NEXT: store [[ENUM2]] to [trivial] [[ALLOCA2]] : $*FakeOptional<Builtin.Int1>
|
|
// CHECK-NEXT: [[RESULT1:%[0-9]+]] = load [trivial] [[ALLOCA1]]
|
|
// CHECK-NEXT: [[RESULT2:%[0-9]+]] = load [trivial] [[ALLOCA2]]
|
|
// CHECK-NEXT: [[RESULT:%[0-9]+]] = tuple ([[RESULT1]] : $FakeOptional<Builtin.Int1>, [[RESULT2]] : $FakeOptional<Builtin.Int1>)
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
sil [ossa] @enum_promotion_of_concrete_types : $@convention(thin) (@in Builtin.Int1) -> (FakeOptional<Builtin.Int1>, FakeOptional<Builtin.Int1>) {
|
|
bb0(%0 : $*Builtin.Int1):
|
|
%1 = alloc_stack $FakeOptional<Builtin.Int1>
|
|
inject_enum_addr %1 : $*FakeOptional<Builtin.Int1>, #FakeOptional.none!enumelt
|
|
|
|
%2 = integer_literal $Builtin.Int1, 1
|
|
%3 = alloc_stack $FakeOptional<Builtin.Int1>
|
|
%4 = init_enum_data_addr %3 : $*FakeOptional<Builtin.Int1>, #FakeOptional.some!enumelt
|
|
%5 = load [trivial] %0 : $*Builtin.Int1
|
|
store %5 to [trivial] %4 : $*Builtin.Int1
|
|
inject_enum_addr %3 : $*FakeOptional<Builtin.Int1>, #FakeOptional.some!enumelt
|
|
|
|
%6 = load [trivial] %1 : $*FakeOptional<Builtin.Int1>
|
|
%7 = load [trivial] %3 : $*FakeOptional<Builtin.Int1>
|
|
|
|
%8 = tuple(%6 : $FakeOptional<Builtin.Int1>, %7 : $FakeOptional<Builtin.Int1>)
|
|
|
|
dealloc_stack %3 : $*FakeOptional<Builtin.Int1>
|
|
dealloc_stack %1 : $*FakeOptional<Builtin.Int1>
|
|
return %8 : $(FakeOptional<Builtin.Int1>, FakeOptional<Builtin.Int1>)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_promotion_case2
|
|
// CHECK: bb0([[B_PTR:%[0-9]+]]
|
|
// CHECK-NEXT: [[ALLOCA:%[0-9]+]] = alloc_stack $FakeOptional<B>
|
|
// CHECK-NEXT: [[B_PTR_COPY_FOR_ENUM:%.*]] = copy_value [[B_PTR]]
|
|
// CHECK-NEXT: [[ENUM:%[0-9]+]] = enum $FakeOptional<B>, #FakeOptional.some!enumelt, [[B_PTR_COPY_FOR_ENUM]] : $B
|
|
// CHECK-NEXT: store [[ENUM]] to [init] [[ALLOCA]]
|
|
// CHECK-NEXT: [[RESULT:%[0-9]+]] = load [take] [[ALLOCA]]
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: br bb1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: // function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy_value [[B_PTR]]
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
// CHECK: } // end sil function 'enum_promotion_case2'
|
|
sil [ossa] @enum_promotion_case2 : $@convention(thin) (@owned B) -> @owned FakeOptional<B> {
|
|
bb0(%0 : @owned $B):
|
|
%2 = alloc_stack $FakeOptional<B>
|
|
%3 = init_enum_data_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%0a = copy_value %0 : $B
|
|
store %0a to [init] %3 : $*B
|
|
|
|
// This instruction between the store and the inject_enum_addr should not prevent
|
|
// the optimization.
|
|
%0b = copy_value %0 : $B
|
|
|
|
inject_enum_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%7 = load [take] %2 : $*FakeOptional<B>
|
|
dealloc_stack %2 : $*FakeOptional<B>
|
|
destroy_value %0 : $B
|
|
br bb1
|
|
|
|
bb1:
|
|
%f3 = function_ref @use_b_guaranteed : $@convention(thin) (@guaranteed B) -> ()
|
|
apply %f3(%0b) : $@convention(thin) (@guaranteed B) -> ()
|
|
destroy_value %0b : $B
|
|
return %7 : $FakeOptional<B>
|
|
}
|
|
|
|
// Negative test corresponding to the previous test.
|
|
// CHECK-LABEL: sil [ossa] @no_enum_promotion_of_non_concrete_types
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: alloc_stack $FakeOptional<T>
|
|
// CHECK-NEXT: inject_enum_addr {{%[0-9]+}} : $*FakeOptional<T>, #FakeOptional.none!enumelt
|
|
// CHECK-NEXT: alloc_stack $FakeOptional<T>
|
|
// CHECK-NEXT: init_enum_data_addr {{%[0-9]+}} : $*FakeOptional<T>, #FakeOptional.some!enumelt
|
|
// CHECK-NEXT: copy_addr
|
|
// CHECK-NEXT: inject_enum_addr
|
|
// CHECK-NEXT: cond_br
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: copy_addr
|
|
// CHECK-NEXT: destroy_addr
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: copy_addr
|
|
// CHECK-NEXT: destroy_addr
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb3
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @no_enum_promotion_of_non_concrete_types : $@convention(thin) <T> (@inout T, Builtin.Int1) -> @out FakeOptional<T> {
|
|
bb0(%0 : $*FakeOptional<T>, %1 : $*T, %2 : $Builtin.Int1):
|
|
%3 = alloc_stack $FakeOptional<T>
|
|
inject_enum_addr %3 : $*FakeOptional<T>, #FakeOptional.none!enumelt
|
|
%4 = alloc_stack $FakeOptional<T>
|
|
%5 = init_enum_data_addr %4 : $*FakeOptional<T>, #FakeOptional.some!enumelt
|
|
copy_addr %1 to [init] %5 : $*T
|
|
inject_enum_addr %4 : $*FakeOptional<T>, #FakeOptional.some!enumelt
|
|
cond_br %2, bb1, bb2
|
|
|
|
bb1:
|
|
copy_addr [take] %3 to [init] %0 : $*FakeOptional<T>
|
|
destroy_addr %4 : $*FakeOptional<T>
|
|
br bb3
|
|
|
|
bb2:
|
|
copy_addr [take] %4 to [init] %0 : $*FakeOptional<T>
|
|
destroy_addr %3 : $*FakeOptional<T>
|
|
br bb3
|
|
|
|
bb3:
|
|
%7 = tuple()
|
|
dealloc_stack %4 : $*FakeOptional<T>
|
|
dealloc_stack %3 : $*FakeOptional<T>
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_round_trip : $@convention(thin) (@owned B) -> @owned B {
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_round_trip'
|
|
sil [ossa] @unchecked_ref_cast_round_trip : $@convention(thin) (@owned B) -> @owned B {
|
|
bb0(%0 : @owned $B):
|
|
%1 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
|
|
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $B
|
|
return %2 : $B
|
|
}
|
|
|
|
// (upcast X2->X (ref-to-object-pointer-inst (object-pointer-to-ref-inst x) typeof(x))) -> x
|
|
// CHECK-LABEL: sil [ossa] @upcast_unchecked_ref_cast_round_trip1 : $@convention(thin) (@owned E) -> @owned E {
|
|
// CHECK-NOT: upcast
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'upcast_unchecked_ref_cast_round_trip1'
|
|
sil [ossa] @upcast_unchecked_ref_cast_round_trip1 : $@convention(thin) (@owned E) -> @owned E {
|
|
bb0(%0 : @owned $E):
|
|
%1 = upcast %0 : $E to $B
|
|
%2 = unchecked_ref_cast %1 : $B to $Builtin.NativeObject
|
|
%3 = unchecked_ref_cast %2 : $Builtin.NativeObject to $E
|
|
return %3 : $E
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_unchecked_ref_cast_round_trip2 :
|
|
// CHECK-NOT: upcast
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-LABEL: } // end sil function 'upcast_unchecked_ref_cast_round_trip2'
|
|
sil [ossa] @upcast_unchecked_ref_cast_round_trip2 : $@convention(method) (@owned E) -> () {
|
|
bb0(%0 : @owned $E):
|
|
%1 = upcast %0 : $E to $B
|
|
debug_value %1 : $B
|
|
%2 = unchecked_ref_cast %1 : $B to $Builtin.NativeObject
|
|
%3 = struct $NativeObjectStruct (%2 : $Builtin.NativeObject)
|
|
destroy_value %3 : $NativeObjectStruct
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_enum_data_of_enum : $@convention(thin) () -> Builtin.Int1 {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'unchecked_enum_data_of_enum'
|
|
sil [ossa] @unchecked_enum_data_of_enum : $@convention(thin) () -> Builtin.Int1 {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int1, 0
|
|
%1 = enum $FakeOptional<Builtin.Int1>, #FakeOptional.some!enumelt, %0 : $Builtin.Int1
|
|
%2 = unchecked_enum_data %1 : $FakeOptional<Builtin.Int1>, #FakeOptional.some!enumelt
|
|
return %2 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_addr_cast_formation : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
|
|
// CHECK: bb0([[INPUT_PTR:%[0-9]+]] : $*Builtin.NativeObject):
|
|
// CHECK-NEXT: [[ADDR_CAST:%[0-9]+]] = unchecked_addr_cast [[INPUT_PTR]] : $*Builtin.NativeObject to $*Builtin.Word
|
|
// CHECK-NEXT: [[RETURN_VALUE:%[0-9]+]] = load [trivial] [[ADDR_CAST]] : $*Builtin.Word
|
|
// CHECK-NEXT: return [[RETURN_VALUE]]
|
|
// CHECK: } // end sil function 'unchecked_addr_cast_formation'
|
|
sil [ossa] @unchecked_addr_cast_formation : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
|
|
bb0(%0 : $*Builtin.NativeObject):
|
|
%1 = address_to_pointer %0 : $*Builtin.NativeObject to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%3 = load [trivial] %2 : $*Builtin.Word
|
|
return %3 : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_addr_cast_forwarding : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
|
|
// CHECK: bb0([[INPUT_PTR:%[0-9]+]] : $*Builtin.NativeObject):
|
|
// CHECK-NEXT: [[ADDR_CAST:%[0-9]+]] = unchecked_addr_cast [[INPUT_PTR]] : $*Builtin.NativeObject to $*Builtin.Word
|
|
// CHECK-NEXT: debug_value [[ADDR_CAST]]
|
|
// CHECK-NEXT: [[RETURN_VALUE:%[0-9]+]] = load [trivial] [[ADDR_CAST]] : $*Builtin.Word
|
|
// CHECK-NEXT: return [[RETURN_VALUE]]
|
|
// CHECK: } // end sil function 'unchecked_addr_cast_forwarding'
|
|
sil [ossa] @unchecked_addr_cast_forwarding : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
|
|
bb0(%0 : $*Builtin.NativeObject):
|
|
%1 = unchecked_addr_cast %0 : $*Builtin.NativeObject to $*Builtin.RawPointer
|
|
%2 = unchecked_addr_cast %1 : $*Builtin.RawPointer to $*Builtin.Word
|
|
debug_value %2 : $*Builtin.Word // should not prevent the optimization
|
|
%3 = load [trivial] %2 : $*Builtin.Word
|
|
return %3 : $Builtin.Word
|
|
}
|
|
|
|
class F : E {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_forwarding : $@convention(thin) (@owned B) -> @owned F {
|
|
// CHECK: bb0([[INPUT_REF:%[0-9]+]] : @owned $B):
|
|
// CHECK-NEXT: [[CAST_REF:%[0-9]+]] = unchecked_ref_cast [[INPUT_REF]] : $B to $F
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @unchecked_ref_cast_forwarding : $@convention(thin) (@owned B) -> @owned F {
|
|
bb0(%0 : @owned $B):
|
|
%1 = unchecked_ref_cast %0 : $B to $E
|
|
%2 = unchecked_ref_cast %1 : $E to $F
|
|
return %2 : $F
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_formation_owned : $@convention(thin) (@owned B) -> @owned F {
|
|
// CHECK: bb0([[INPUT_REF:%[0-9]+]] : @owned $B):
|
|
// CHECK: ref_to_raw_pointer
|
|
// CHECK: raw_pointer_to_ref
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_formation_owned'
|
|
sil [ossa] @unchecked_ref_cast_formation_owned : $@convention(thin) (@owned B) -> @owned F {
|
|
bb0(%0 : @owned $B):
|
|
%1 = ref_to_raw_pointer %0 : $B to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $F
|
|
%3 = copy_value %2 : $F
|
|
destroy_value %0 : $B
|
|
return %3 : $F
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_formation_guaranteed : $@convention(thin) (@guaranteed B) -> @owned F {
|
|
// CHECK: bb0([[INPUT_REF:%[0-9]+]] : @guaranteed $B):
|
|
// CHECK: ref_to_raw_pointer
|
|
// CHECK: raw_pointer_to_ref
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_formation_guaranteed'
|
|
sil [ossa] @unchecked_ref_cast_formation_guaranteed : $@convention(thin) (@guaranteed B) -> @owned F {
|
|
bb0(%0 : @guaranteed $B):
|
|
%1 = ref_to_raw_pointer %0 : $B to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $F
|
|
%3 = copy_value %2 : $F
|
|
return %3 : $F
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_formation_unowned : $@convention(thin) (B) -> F {
|
|
// CHECK: bb0([[INPUT_REF:%[0-9]+]] :
|
|
// CHECK: ref_to_raw_pointer
|
|
// CHECK: raw_pointer_to_ref
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_formation_unowned'
|
|
sil [ossa] @unchecked_ref_cast_formation_unowned : $@convention(thin) (B) -> F {
|
|
bb0(%0 : @unowned $B):
|
|
%1 = ref_to_raw_pointer %0 : $B to $Builtin.RawPointer
|
|
%2 = raw_pointer_to_ref %1 : $Builtin.RawPointer to $F
|
|
return %2 : $F
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_unchecked_ref_cast_roundtrip : $@convention(thin) (@owned B) -> @owned B {
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-NOT: upcast
|
|
// CHECK: } // end sil function 'upcast_unchecked_ref_cast_roundtrip'
|
|
sil [ossa] @upcast_unchecked_ref_cast_roundtrip : $@convention(thin) (@owned B) -> @owned B {
|
|
bb0(%0 : @owned $B):
|
|
%1 = unchecked_ref_cast %0 : $B to $E
|
|
%2 = upcast %1 : $E to $B
|
|
return %2 : $B
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_upcast_roundtrip : $@convention(thin) (@owned E) -> @owned E {
|
|
// CHECK-NOT: upcast
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_upcast_roundtrip'
|
|
sil [ossa] @unchecked_ref_cast_upcast_roundtrip : $@convention(thin) (@owned E) -> @owned E {
|
|
bb0(%0 : @owned $E):
|
|
%1 = upcast %0 : $E to $B
|
|
%2 = unchecked_ref_cast %1 : $B to $E
|
|
return %2 : $E
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_open_existential_ref : $@convention(thin) (@owned AnyObject) -> @owned AnyObject {
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'unchecked_ref_cast_open_existential_ref'
|
|
sil [ossa] @unchecked_ref_cast_open_existential_ref : $@convention(thin) (@owned AnyObject) -> @owned AnyObject {
|
|
bb0(%0 : @owned $AnyObject):
|
|
%1 = open_existential_ref %0 : $AnyObject to $@opened("F06A1466-8414-11E5-81D5-685B35C48C83", AnyObject) Self
|
|
%2 = unchecked_ref_cast %1 : $@opened("F06A1466-8414-11E5-81D5-685B35C48C83", AnyObject) Self to $AnyObject
|
|
return %2 : $AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ref_cast_upcast_combine : $@convention(thin) (@owned E) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @unchecked_ref_cast_upcast_combine : $@convention(thin) (@owned E) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $E):
|
|
%1 = upcast %0 : $E to $B
|
|
%2 = unchecked_ref_cast %1 : $B to $Builtin.NativeObject
|
|
return %2 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_promotion : $@convention(thin) (@inout FakeOptional<B>) -> @owned B {
|
|
// CHECK: bb0(%0 : $*FakeOptional<B>):
|
|
// CHECK-NEXT: [[BORROW:%.*]] = load_borrow
|
|
// CHECK-NEXT: switch_enum [[BORROW]]
|
|
// CHECK: bb1([[GUARANTEED:%.*]] : @guaranteed
|
|
// CHECK-NEXT: end_borrow [[BORROW]]
|
|
// CHECK-NEXT: load [copy]
|
|
// CHECK-NEXT: unchecked_enum_data
|
|
// CHECK-NEXT: return
|
|
// CHECK: } /
|
|
sil [ossa] @unchecked_take_enum_data_addr_promotion : $@convention(thin) (@inout FakeOptional<B>) -> @owned B {
|
|
bb0(%0 : $*FakeOptional<B>):
|
|
switch_enum_addr %0 : $*FakeOptional<B>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1:
|
|
%2 = unchecked_take_enum_data_addr %0 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
debug_value %2 : $*B // should not prevent the optimization
|
|
%3 = load [copy] %2 : $*B
|
|
return %3 : $B
|
|
|
|
bb2:
|
|
unreachable
|
|
}
|
|
|
|
sil [ossa] @weird_function : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_function_simplification : $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> () {
|
|
// CHECK: bb0([[ADDR:%[0-9]+]] : $*B, [[REF:%[0-9]+]] : @guaranteed $B, [[NA:%[0-9]+]] : $Builtin.Int1):
|
|
// CHECK-NEXT: function_ref weird_function
|
|
// CHECK-NEXT: [[FUN:%[0-9]+]] = function_ref @weird_function : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> ()
|
|
// CHECK-NEXT: [[ADDR_CAST:%[0-9]+]] = unchecked_addr_cast %0 : $*B to $*E
|
|
// CHECK-NEXT: [[REF_CAST:%[0-9]+]] = unchecked_ref_cast %1 : $B to $E
|
|
// CHECK-NEXT: apply [[FUN]]([[ADDR_CAST]], [[REF_CAST]], [[NA]])
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @convert_function_simplification : $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> () {
|
|
bb0(%0 : $*B, %1 : @guaranteed $B, %2 : $Builtin.Int1):
|
|
%3 = function_ref @weird_function : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> ()
|
|
%4 = convert_function %3 : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> () to $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> ()
|
|
%5 = apply %4(%0, %1, %2) : $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> ()
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
// Check that convert_function simplifications are not applied in certain cases.
|
|
@objc class MyNSObj { }
|
|
|
|
class AnotherClass : MyNSObj { }
|
|
|
|
sil [ossa] @MyNSObj_self : $@convention(method) (@guaranteed MyNSObj) -> @owned MyNSObj
|
|
|
|
sil shared [ossa] [transparent] [serialized] [reabstraction_thunk] @reabstraction_thunk1 : $@convention(thin) (@in (), @owned @callee_owned () -> @owned AnotherClass) -> @out AnotherClass {
|
|
bb0(%0 : $*AnotherClass, %1 : $*(), %2 : @owned $@callee_owned () -> @owned AnotherClass):
|
|
%3 = apply %2() : $@callee_owned () -> @owned AnotherClass
|
|
store %3 to [init] %0 : $*AnotherClass
|
|
%5 = tuple ()
|
|
return %5 : $()
|
|
}
|
|
|
|
// @nonobjc curry thunk of MyNSObj.self()
|
|
sil shared [ossa] [serialized] [thunk] @curry_thunk_for_MyNSObj_self : $@convention(thin) (@owned MyNSObj) -> @owned @callee_owned () -> @owned MyNSObj {
|
|
bb0(%0 : @owned $MyNSObj):
|
|
// function_ref @nonobjc MyNSObj.self()
|
|
%1 = function_ref @MyNSObj_self : $@convention(method) (@guaranteed MyNSObj) -> @owned MyNSObj
|
|
%2 = partial_apply %1(%0) : $@convention(method) (@guaranteed MyNSObj) -> @owned MyNSObj
|
|
return %2 : $@callee_owned () -> @owned MyNSObj
|
|
}
|
|
|
|
// Check that convert_function is eliminated if the result type of the converted function is different from the apply result type.
|
|
// CHECK-LABEL: sil {{.*}} @peephole_convert_function_result_change : $@convention(thin) (@in AnotherClass) -> @out @callee_owned (@in ()) -> @out AnotherClass {
|
|
// CHECK: [[F1:%[0-9]+]] = function_ref @curry_thunk_for_MyNSObj_self
|
|
// CHECK: [[APPLY:%[0-9]+]] = apply [[F1]]
|
|
// CHECK: [[CONV_RESULT:%[0-9]+]] = convert_function [[APPLY]]
|
|
// CHECK: [[FUN:%[0-9]+]] = function_ref @reabstraction_thunk1
|
|
// CHECK: [[CF:%[0-9]+]] = partial_apply [[FUN]]([[CONV_RESULT]])
|
|
// CHECK: // end sil function 'peephole_convert_function_result_change'
|
|
sil shared [ossa] [transparent] [reabstraction_thunk] @peephole_convert_function_result_change : $@convention(thin) (@in AnotherClass) -> @out @callee_owned (@in ()) -> @out AnotherClass {
|
|
bb0(%0 : $*@callee_owned (@in ()) -> @out AnotherClass, %1 : $*AnotherClass):
|
|
// function_ref @nonobjc curry thunk of MyNSObj.self()
|
|
%2 = function_ref @curry_thunk_for_MyNSObj_self : $@convention(thin) (@owned MyNSObj) -> @owned @callee_owned () -> @owned MyNSObj
|
|
%3 = convert_function %2 : $@convention(thin) (@owned MyNSObj) -> @owned @callee_owned () -> @owned MyNSObj to $@convention(thin) (@owned AnotherClass) -> @owned @callee_owned () -> @owned AnotherClass
|
|
%5 = load [take] %1 : $*AnotherClass
|
|
%6 = apply %3(%5) : $@convention(thin) (@owned AnotherClass) -> @owned @callee_owned () -> @owned AnotherClass
|
|
// function_ref thunk for @callee_owned () -> (@owned AnotherClass)
|
|
%7 = function_ref @reabstraction_thunk1 : $@convention(thin) (@in (), @owned @callee_owned () -> @owned AnotherClass) -> @out AnotherClass
|
|
%8 = partial_apply %7(%6) : $@convention(thin) (@in (), @owned @callee_owned () -> @owned AnotherClass) -> @out AnotherClass
|
|
store %8 to [init] %0 : $*@callee_owned (@in ()) -> @out AnotherClass
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
} // end sil function 'peephole_convert_function_result_change'
|
|
|
|
sil @convertible_result_with_error : $@convention(thin) () -> (@owned AnotherClass, @error Error)
|
|
|
|
// CHECK-LABEL: sil [ossa] @peephole_convert_function_result_change_with_error : {{.*}} {
|
|
// CHECK-NOT: convert_function
|
|
// CHECK-LABEL: } // end sil function 'peephole_convert_function_result_change_with_error'
|
|
sil [ossa] @peephole_convert_function_result_change_with_error : $@convention(thin) () -> () {
|
|
entry:
|
|
%f = function_ref @convertible_result_with_error : $@convention(thin) () -> (@owned AnotherClass, @error Error)
|
|
%c = convert_function %f : $@convention(thin) () -> (@owned AnotherClass, @error Error) to $@convention(thin) () -> (@owned MyNSObj, @error Error)
|
|
try_apply %c() : $@convention(thin) () -> (@owned MyNSObj, @error Error), normal success, error failure
|
|
|
|
success(%r : $MyNSObj):
|
|
destroy_value %r : $MyNSObj
|
|
br exit
|
|
|
|
failure(%e : $Error):
|
|
destroy_value %e : $Error
|
|
br exit
|
|
|
|
exit:
|
|
return undef : $()
|
|
}
|
|
|
|
sil @convertible_indirect_result : $@convention(thin) (@guaranteed MyNSObj) -> @out AnotherClass
|
|
|
|
// CHECK-LABEL: sil [ossa] @peephole_convert_function_indirect_result :
|
|
// CHECK: bb0([[A:%.*]] : @guaranteed $AnotherClass):
|
|
// CHECK: [[F:%.*]] = function_ref @convertible_indirect_result :
|
|
// CHECK: [[B:%.*]] = alloc_stack $MyNSObj
|
|
// CHECK: [[B_CONV:%.*]] = unchecked_addr_cast [[B]]
|
|
// CHECK: [[A_CONV:%.*]] = upcast [[A]]
|
|
// CHECK: apply [[F]]([[B_CONV]], [[A_CONV]])
|
|
sil [ossa] @peephole_convert_function_indirect_result : $@convention(thin) (@guaranteed AnotherClass) -> @owned MyNSObj {
|
|
entry(%a : @guaranteed $AnotherClass):
|
|
%f = function_ref @convertible_indirect_result : $@convention(thin) (@guaranteed MyNSObj) -> @out AnotherClass
|
|
%c = convert_function %f : $@convention(thin) (@guaranteed MyNSObj) -> @out AnotherClass to $@convention(thin) (@guaranteed AnotherClass) -> @out MyNSObj
|
|
%b = alloc_stack $*MyNSObj
|
|
apply %c(%b, %a) : $@convention(thin) (@guaranteed AnotherClass) -> @out MyNSObj
|
|
%r = load [take] %b : $*MyNSObj
|
|
dealloc_stack %b : $*MyNSObj
|
|
return %r : $MyNSObj
|
|
}
|
|
|
|
sil @convertible_owned_aggregate_input : $@convention(thin) (@owned (MyNSObj, MyNSObj)) -> @owned (AnotherClass, AnotherClass)
|
|
|
|
// CHECK-LABEL: sil [ossa] @peephole_convert_owned_aggregate_input_result :
|
|
// CHECK: bb0([[A:%.*]] : @owned $(AnotherClass, AnotherClass)):
|
|
// CHECK: [[F:%.*]] = function_ref @convertible_owned_aggregate_input :
|
|
// CHECK: [[A_CONV:%.*]] = unchecked_value_cast [[A]]
|
|
// CHECK: [[R:%.*]] = apply [[F]]([[A_CONV]])
|
|
// CHECK: [[R_CONV:%.*]] = unchecked_value_cast [[R]]
|
|
// CHECK: return [[R_CONV]]
|
|
sil [ossa] @peephole_convert_owned_aggregate_input_result : $@convention(thin) (@owned (AnotherClass, AnotherClass)) -> @owned (MyNSObj, MyNSObj) {
|
|
entry(%a : @owned $(AnotherClass, AnotherClass)):
|
|
%f = function_ref @convertible_owned_aggregate_input : $@convention(thin) (@owned (MyNSObj, MyNSObj)) -> @owned (AnotherClass, AnotherClass)
|
|
%c = convert_function %f : $@convention(thin) (@owned (MyNSObj, MyNSObj)) -> @owned (AnotherClass, AnotherClass) to $@convention(thin) (@owned (AnotherClass, AnotherClass)) -> @owned (MyNSObj, MyNSObj)
|
|
%r = apply %c(%a) : $@convention(thin) (@owned (AnotherClass, AnotherClass)) -> @owned (MyNSObj, MyNSObj)
|
|
return %r : $(MyNSObj, MyNSObj)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @upcast_formation : $@convention(thin) (@inout E, @owned E, @inout B) -> @owned B {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: upcast
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: upcast
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'upcast_formation'
|
|
sil [ossa] @upcast_formation : $@convention(thin) (@inout E, @owned E, @inout B) -> @owned B {
|
|
bb0(%0 : $*E, %1 : @owned $E, %2 : $*B):
|
|
%3 = unchecked_addr_cast %0 : $*E to $*B
|
|
%4 = unchecked_ref_cast %1 : $E to $B
|
|
%5 = load [copy] %3 : $*B
|
|
store %5 to [assign] %2 : $*B
|
|
return %4 : $B
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_form_upcast_when_casts_are_identity : $@convention(thin) (@inout E, @owned E, @inout E) -> @owned E {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dont_form_upcast_when_casts_are_identity'
|
|
sil [ossa] @dont_form_upcast_when_casts_are_identity : $@convention(thin) (@inout E, @owned E, @inout E) -> @owned E {
|
|
bb0(%0 : $*E, %1 : @owned $E, %2 : $*E):
|
|
%3 = unchecked_addr_cast %0 : $*E to $*E
|
|
%4 = unchecked_ref_cast %1 : $E to $E
|
|
%5 = load [copy] %3 : $*E
|
|
store %5 to [assign] %2 : $*E
|
|
return %4 : $E
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: pointer_to_address
|
|
// CHECK-NEXT: index_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @indexrawpointer_to_indexaddr : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3 : $@thick Int8.Type) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4 : $Builtin.Word, %1 : $Builtin.Word, %6 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7 : $(Builtin.Word, Builtin.Int1), 0
|
|
%9 = index_raw_pointer %0 : $Builtin.RawPointer, %8 : $Builtin.Word
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*Int8
|
|
%11 = load [trivial] %10 : $*Int8
|
|
return %11 : $Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_strideof : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: pointer_to_address
|
|
// CHECK-NEXT: index_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_strideof'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_strideof : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3 : $@thick Int8.Type) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4 : $Builtin.Word, %1 : $Builtin.Word, %6 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7 : $(Builtin.Word, Builtin.Int1), 0
|
|
%9 = index_raw_pointer %0 : $Builtin.RawPointer, %8 : $Builtin.Word
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*Int8
|
|
%11 = load [trivial] %10 : $*Int8
|
|
return %11 : $Int8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_mismatched_metatype : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int32 {
|
|
// CHECK-NOT: index_addr
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_mismatched_metatype'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_mismatched_metatype : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int32 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3 : $@thick Int8.Type) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4 : $Builtin.Word, %1 : $Builtin.Word, %6 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7 : $(Builtin.Word, Builtin.Int1), 0
|
|
%9 = index_raw_pointer %0 : $Builtin.RawPointer, %8 : $Builtin.Word
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*Int32
|
|
%11 = load [trivial] %10 : $*Int32
|
|
return %11 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_with_casts : $@convention(thin) (Builtin.RawPointer, Builtin.Int64) -> Int32
|
|
// CHECK: pointer_to_address
|
|
// CHECK-NEXT: builtin "truncOrBitCast_Int64_Word"
|
|
// CHECK-NEXT: index_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_with_casts'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_with_casts : $@convention(thin) (Builtin.RawPointer, Builtin.Int64) -> Int32 {
|
|
bb0(%0 : $Builtin.RawPointer, %1: $Builtin.Int64):
|
|
%2 = integer_literal $Builtin.Int1, -1
|
|
%3 = metatype $@thick Int32.Type
|
|
%4 = builtin "strideof"<Int32>(%3 : $@thick Int32.Type) : $Builtin.Word
|
|
%5 = builtin "zextOrBitCast_Word_Int64"(%4 : $Builtin.Word) : $Builtin.Int64
|
|
%6 = builtin "smul_with_overflow_Int64"(%1 : $Builtin.Int64, %5 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%7 = tuple_extract %6 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%8 = builtin "truncOrBitCast_Int64_Word"(%7 : $Builtin.Int64) : $Builtin.Word
|
|
%9 = index_raw_pointer %0 : $Builtin.RawPointer, %8 : $Builtin.Word
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*Int32
|
|
%11 = load [trivial] %10 : $*Int32
|
|
return %11 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @max_int_ult : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK-NOT: builtin "cmp_ult_Int32"
|
|
// CHECK: integer_literal $Builtin.Int1, 0
|
|
sil [ossa] @max_int_ult : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%minint = integer_literal $Builtin.Int32, -1
|
|
%cmp = builtin "cmp_ult_Int32"(%minint : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1
|
|
cond_br %cmp, bb1, bb2
|
|
|
|
bb1:
|
|
%badret = integer_literal $Builtin.Int32, 0
|
|
br bb3(%badret : $Builtin.Int32)
|
|
|
|
bb2:
|
|
%goodret = integer_literal $Builtin.Int32, 1
|
|
br bb3(%goodret : $Builtin.Int32)
|
|
|
|
bb3(%ret : $Builtin.Int32):
|
|
return %ret : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @max_int_ule : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
|
|
// CHECK: builtin "cmp_ule_Int32"
|
|
// CHECK-NOT: integer_literal $Builtin.Int1, 0
|
|
sil [ossa] @max_int_ule : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%minint = integer_literal $Builtin.Int32, -1
|
|
%cmp = builtin "cmp_ule_Int32"(%minint : $Builtin.Int32, %0 : $Builtin.Int32) : $Builtin.Int1
|
|
cond_br %cmp, bb1, bb2
|
|
|
|
bb1:
|
|
%badret = integer_literal $Builtin.Int32, 0
|
|
br bb3(%badret : $Builtin.Int32)
|
|
|
|
bb2:
|
|
%goodret = integer_literal $Builtin.Int32, 1
|
|
br bb3(%goodret : $Builtin.Int32)
|
|
|
|
bb3(%ret : $Builtin.Int32):
|
|
return %ret : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @trunc_of_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int32
|
|
// CHECK-NOT: builtin "zextOrBitCast_Int16_Int64"
|
|
// CHECK-NOT: builtin "truncOrBitCast_Int64_Int32"
|
|
// CHECK: builtin "zextOrBitCast_Int16_Int32"
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @trunc_of_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int32 {
|
|
bb0(%0 : $Builtin.Int16):
|
|
%zext = builtin "zextOrBitCast_Int16_Int64"(%0 : $Builtin.Int16) : $Builtin.Int64
|
|
%trunc = builtin "truncOrBitCast_Int64_Int32"(%zext : $Builtin.Int64) : $Builtin.Int32
|
|
return %trunc : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @zext_of_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int64
|
|
// CHECK-NOT: builtin "zextOrBitCast_Int16_Int32"
|
|
// CHECK-NOT: builtin "zextOrBitCast_Int32_Int64"
|
|
// CHECK: builtin "zextOrBitCast_Int16_Int64"
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @zext_of_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int64 {
|
|
bb0(%0 : $Builtin.Int16):
|
|
%zext1 = builtin "zextOrBitCast_Int16_Int32"(%0 : $Builtin.Int16) : $Builtin.Int32
|
|
%zext2 = builtin "zextOrBitCast_Int32_Int64"(%zext1 : $Builtin.Int32) : $Builtin.Int64
|
|
return %zext2 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @trunc_of_zext_then_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int16
|
|
// CHECK-NOT: builtin "zextOrBitCast_Int16_Int64"
|
|
// CHECK-NOT: builtin "truncOrBitCast_Int64_Int32"
|
|
// CHECK-NOT: builtin "zextOrBitCast_Int32_Int64"
|
|
// CHECK-NOT: builtin "truncOrBitCast_Int64_Int16"
|
|
// CHECK: return
|
|
sil [ossa] @trunc_of_zext_then_zext : $@convention(thin) (Builtin.Int16) -> Builtin.Int16 {
|
|
bb0(%0 : $Builtin.Int16):
|
|
%zext = builtin "zextOrBitCast_Int16_Int64"(%0 : $Builtin.Int16) : $Builtin.Int64
|
|
%trunc = builtin "truncOrBitCast_Int64_Int32"(%zext : $Builtin.Int64) : $Builtin.Int32
|
|
%zext2 = builtin "zextOrBitCast_Int32_Int64"(%trunc : $Builtin.Int32) : $Builtin.Int64
|
|
%trunc2 = builtin "truncOrBitCast_Int64_Int16"(%zext2 : $Builtin.Int64) : $Builtin.Int16
|
|
return %trunc2 : $Builtin.Int16
|
|
}
|
|
|
|
sil [ossa] @eliminate_dead_thin_to_thick_function_fun : $@convention(thin) () -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @eliminate_dead_thin_to_thick_function : $@convention(thin) () -> () {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'eliminate_dead_thin_to_thick_function'
|
|
sil [ossa] @eliminate_dead_thin_to_thick_function : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @eliminate_dead_thin_to_thick_function_fun : $@convention(thin) () -> ()
|
|
%1 = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
%2 = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
%3 = tuple()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @eliminate_thin_to_thick_apply : $@convention(thin) () -> () {
|
|
// CHECK: bb0
|
|
// CHECK: function_ref @eliminate_dead_thin_to_thick_function_fun
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'eliminate_thin_to_thick_apply'
|
|
sil [ossa] @eliminate_thin_to_thick_apply : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @eliminate_dead_thin_to_thick_function_fun : $@convention(thin) () -> ()
|
|
%1 = thin_to_thick_function %0 : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
|
|
%2 = apply %1() : $@callee_guaranteed () -> ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_unchecked_take_enum_data_addr :
|
|
// CHECK: bb0(%0 : $*AddressOnlyEnum):
|
|
// CHECK-NEXT: destroy_addr %0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'dead_unchecked_take_enum_data_addr'
|
|
sil [ossa] @dead_unchecked_take_enum_data_addr : $@convention(thin) (@in AddressOnlyEnum) -> () {
|
|
bb0(%0 : $*AddressOnlyEnum):
|
|
%1 = unchecked_take_enum_data_addr %0 : $*AddressOnlyEnum, #AddressOnlyEnum.Loadable!enumelt
|
|
destroy_addr %1 : $*Builtin.Int32
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil [ossa] @partial_apply_arg_fun : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
sil [ossa] @partial_apply_generic_func : $@convention(thin) <T> () -> () {
|
|
bb0:
|
|
%0 = tuple()
|
|
return %0 : $()
|
|
}
|
|
|
|
sil [ossa] @partial_apply_nothing : $@convention(thin) () -> () {
|
|
%0 = tuple()
|
|
return %0 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @partial_apply_without_subs_or_args_is_thin_to_thick :
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: function_ref partial_apply_nothing
|
|
// CHECK-NEXT: function_ref @partial_apply_nothing
|
|
// CHECK-NEXT: thin_to_thick_function
|
|
// CHECK-NEXT: function_ref partial_apply_arg_fun
|
|
// CHECK-NEXT: function_ref @partial_apply_arg_fun
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: partial_apply
|
|
// CHECK-NEXT: function_ref partial_apply_generic_func
|
|
// CHECK-NEXT: function_ref @partial_apply_generic_func
|
|
// CHECK-NEXT: partial_apply
|
|
// CHECK: } // end sil function 'partial_apply_without_subs_or_args_is_thin_to_thick'
|
|
sil [ossa] @partial_apply_without_subs_or_args_is_thin_to_thick : $@convention(thin) () -> @owned (@callee_owned () -> (), @callee_owned (Builtin.Int32) -> (), @callee_owned () -> ()) {
|
|
bb0:
|
|
%0 = function_ref @partial_apply_nothing : $@convention(thin) () -> ()
|
|
%1 = partial_apply %0() : $@convention(thin) () -> ()
|
|
%2 = function_ref @partial_apply_arg_fun : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> ()
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
%4 = partial_apply %2(%3) : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> ()
|
|
%5 = function_ref @partial_apply_generic_func : $@convention(thin) <T> () -> ()
|
|
%6 = partial_apply %5<Builtin.Int32>() : $@convention(thin) <T> () -> ()
|
|
%7 = tuple(%1 : $@callee_owned () -> (), %4 : $@callee_owned (Builtin.Int32) -> (), %6 : $@callee_owned () -> ())
|
|
return %7 : $(@callee_owned () -> (), @callee_owned (Builtin.Int32) -> (), @callee_owned () -> ())
|
|
}
|
|
|
|
// Global initializers might have side-effects. We cannot delete such unused
|
|
// calls.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @not_dead_global_init_call : $@convention(thin) () -> () {
|
|
// CHECK: bb0:
|
|
// CHECK: [[FUN:%.*]] = function_ref
|
|
// CHECK-NEXT: apply [[FUN]]()
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'not_dead_global_init_call'
|
|
sil [ossa] @not_dead_global_init_call : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @global_init_fun : $@convention(thin) () -> Builtin.RawPointer
|
|
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @sub_pointers : $@convention(thin) (Builtin.RawPointer) -> Builtin.Word
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'sub_pointers'
|
|
sil [ossa] @sub_pointers : $@convention(thin) (Builtin.RawPointer) -> Builtin.Word {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = integer_literal $Builtin.Word, 0
|
|
%23 = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word
|
|
%26 = builtin "ptrtoint_Word"(%23 : $Builtin.RawPointer) : $Builtin.Word
|
|
%27 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word
|
|
%28 = builtin "sub_Word"(%26 : $Builtin.Word, %27 : $Builtin.Word) : $Builtin.Word
|
|
return %28 : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @sub_same_value : $@convention(thin) (Builtin.RawPointer) -> Builtin.Word
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: integer_literal
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'sub_same_value'
|
|
sil [ossa] @sub_same_value : $@convention(thin) (Builtin.RawPointer) -> Builtin.Word {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%27 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word
|
|
%28 = builtin "sub_Word"(%27 : $Builtin.Word, %27 : $Builtin.Word) : $Builtin.Word
|
|
return %28 : $Builtin.Word
|
|
}
|
|
|
|
sil [ossa] @generic_call_with_indirect_result : $@convention(thin) <T> (@in T) -> @out T
|
|
sil [ossa] @generic_call_without_indirect_result : $@convention(thin) <T> (@in T) -> Bool
|
|
sil [ossa] @generic_call_with_direct_result : $@convention(thin) <T> (T) -> T
|
|
|
|
// CHECK-LABEL: sil [ossa] @generic_partialapply : $@convention(thin)
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: } // end sil function 'generic_partialapply'
|
|
sil [ossa] @generic_partialapply : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%a : $Builtin.Int32):
|
|
%0 = function_ref @generic_call_with_indirect_result : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%1 = function_ref @generic_call_without_indirect_result : $@convention(thin) <τ_0_0> (@in τ_0_0) -> Bool
|
|
%2 = partial_apply %0<Builtin.Int32>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
|
|
%3 = alloc_stack $Builtin.Int32
|
|
%4 = alloc_stack $Builtin.Int32
|
|
store %a to [trivial] %3 : $*Builtin.Int32
|
|
store %a to [trivial] %4 : $*Builtin.Int32
|
|
%5 = apply %2(%3, %4) : $@callee_owned (@in Builtin.Int32) -> @out Builtin.Int32
|
|
%6 = partial_apply %1<Builtin.Int32>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> Bool
|
|
%7 = apply %6(%3) : $@callee_owned (@in Builtin.Int32) -> Bool
|
|
%8 = integer_literal $Builtin.Int32, 0
|
|
%9 = function_ref @generic_call_with_direct_result : $@convention(thin) <τ_0_0> (τ_0_0) -> τ_0_0
|
|
%10 = partial_apply %9<Builtin.Int32>() : $@convention(thin) <τ_0_0> (τ_0_0) -> τ_0_0
|
|
%11 = apply %10(%8) : $@callee_owned (Builtin.Int32) -> Builtin.Int32
|
|
%12 = partial_apply %9<Builtin.Int32>(%8) : $@convention(thin) <τ_0_0> (τ_0_0) -> τ_0_0
|
|
%13 = apply %12() : $@callee_owned () -> Builtin.Int32
|
|
dealloc_stack %4 : $*Builtin.Int32
|
|
dealloc_stack %3 : $*Builtin.Int32
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @bitcast_round_trips : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Builtin.NativeObject, Builtin.RawPointer) {
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-NOT: unchecked_trivial_bit_cast
|
|
// CHECK: } // end sil function 'bitcast_round_trips'
|
|
sil [ossa] @bitcast_round_trips : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Builtin.NativeObject, Builtin.RawPointer) {
|
|
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
|
|
%2 = unchecked_ref_cast %0 : $Builtin.NativeObject to $Optional<Builtin.NativeObject>
|
|
%3 = unchecked_ref_cast %2 : $Optional<Builtin.NativeObject> to $Builtin.NativeObject
|
|
%4 = unchecked_trivial_bit_cast %1 : $Builtin.RawPointer to $Builtin.Word
|
|
%5 = unchecked_trivial_bit_cast %4 : $Builtin.Word to $Builtin.RawPointer
|
|
%6 = tuple(%3 : $Builtin.NativeObject, %5 : $Builtin.RawPointer)
|
|
return %6 : $(Builtin.NativeObject, Builtin.RawPointer)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @bitcast_combines : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (B, Optional<Builtin.Word>) {
|
|
// CHECK: unchecked_ref_cast
|
|
// CHECK-NOT: unchecked_bit_cast
|
|
// CHECK: unchecked_trivial_bit_cast
|
|
// CHECK-NOT: unchecked_trivial_bit_cast
|
|
// CHECK: } // end sil function 'bitcast_combines'
|
|
sil [ossa] @bitcast_combines : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (B, Optional<Builtin.Word>) {
|
|
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
|
|
%2 = unchecked_ref_cast %0 : $Builtin.NativeObject to $Optional<Builtin.NativeObject>
|
|
%3 = unchecked_ref_cast %2 : $Optional<Builtin.NativeObject> to $B
|
|
%4 = unchecked_trivial_bit_cast %1 : $Builtin.RawPointer to $Builtin.Word
|
|
%5 = unchecked_trivial_bit_cast %4 : $Builtin.Word to $Optional<Builtin.Word>
|
|
%6 = tuple(%3 : $B, %5 : $Optional<Builtin.Word>)
|
|
return %6 : $(B, Optional<Builtin.Word>)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @bitwise_combines_owned : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: unchecked_bitwise_cast
|
|
// CHECK-NEXT: unchecked_trivial_bit_cast
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NOT: unchecked_bitwise_cast
|
|
// CHECK-NOT: unchecked_ownership_conversion
|
|
// CHECK: } // end sil function 'bitwise_combines_owned'
|
|
sil [ossa] @bitwise_combines_owned : $@convention(thin) (@owned Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
|
|
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.RawPointer):
|
|
// combine
|
|
%2 = unchecked_bitwise_cast %1 : $Builtin.RawPointer to $Builtin.Word
|
|
%3 = unchecked_bitwise_cast %2 : $Builtin.Word to $Optional<Builtin.NativeObject>
|
|
|
|
// promote trivial
|
|
%4 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Builtin.RawPointer
|
|
|
|
// promote ref
|
|
%5 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Optional<Builtin.NativeObject>
|
|
|
|
destroy_value %0 : $Builtin.NativeObject
|
|
|
|
%6 = tuple(%3 : $Optional<Builtin.NativeObject>, %4 : $Builtin.RawPointer, %5 : $Optional<Builtin.NativeObject>)
|
|
%6a = copy_value %6 : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
|
|
return %6a : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @bitwise_combines_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: unchecked_bitwise_cast
|
|
// CHECK-NEXT: unchecked_trivial_bit_cast
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NOT: unchecked_bitwise_cast
|
|
// CHECK-NOT: unchecked_ownership_conversion
|
|
// CHECK: } // end sil function 'bitwise_combines_guaranteed'
|
|
sil [ossa] @bitwise_combines_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, Builtin.RawPointer) -> @owned (Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>) {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : $Builtin.RawPointer):
|
|
// combine
|
|
%2 = unchecked_bitwise_cast %1 : $Builtin.RawPointer to $Builtin.Word
|
|
%3 = unchecked_bitwise_cast %2 : $Builtin.Word to $Optional<Builtin.NativeObject>
|
|
|
|
// promote trivial
|
|
%4 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Builtin.RawPointer
|
|
|
|
// promote ref
|
|
%5 = unchecked_bitwise_cast %0 : $Builtin.NativeObject to $Optional<Builtin.NativeObject>
|
|
|
|
%6 = tuple(%3 : $Optional<Builtin.NativeObject>, %4 : $Builtin.RawPointer, %5 : $Optional<Builtin.NativeObject>)
|
|
%6a = copy_value %6 : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
|
|
return %6a : $(Optional<Builtin.NativeObject>, Builtin.RawPointer, Optional<Builtin.NativeObject>)
|
|
}
|
|
|
|
// CHECK-LABEL: @remove_pointer_compare_to_zero :
|
|
// CHECK-NOT: apply
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'remove_pointer_compare_to_zero'
|
|
sil [ossa] @remove_pointer_compare_to_zero : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = string_literal utf8 "ss"
|
|
%2 = integer_literal $Builtin.Word, 0
|
|
%4 = builtin "inttoptr_Word"(%2 : $Builtin.Word) : $Builtin.RawPointer
|
|
%6 = builtin "cmp_eq_RawPointer"(%1 : $Builtin.RawPointer, %4 : $Builtin.RawPointer) : $Builtin.Int1
|
|
cond_fail %6 : $Builtin.Int1
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @remove_pointer_compare_to_zero_NE :
|
|
// CHECK-NOT: apply
|
|
// CHECK: cond_fail
|
|
// CHECK: unreachable
|
|
// CHECK: } // end sil function 'remove_pointer_compare_to_zero_NE'
|
|
sil [ossa] @remove_pointer_compare_to_zero_NE : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%1 = string_literal utf8 "ss"
|
|
%2 = integer_literal $Builtin.Word, 0
|
|
%4 = builtin "inttoptr_Word"(%2 : $Builtin.Word) : $Builtin.RawPointer
|
|
%6 = builtin "cmp_ne_RawPointer"(%1 : $Builtin.RawPointer, %4 : $Builtin.RawPointer) : $Builtin.Int1
|
|
cond_fail %6 : $Builtin.Int1
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @remove_pointer_compare_to_zero_arith :
|
|
// CHECK-NOT: apply
|
|
// CHECK-NOT: cond_fail
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'remove_pointer_compare_to_zero_arith'
|
|
sil [ossa] @remove_pointer_compare_to_zero_arith : $@convention(thin) (Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.Word):
|
|
%1 = string_literal utf8 "ss"
|
|
%2 = integer_literal $Builtin.Word, 0
|
|
%3 = integer_literal $Builtin.Word, 4
|
|
%4 = integer_literal $Builtin.Int1, -1
|
|
%6 = builtin "smul_with_overflow_Word"(%0 : $Builtin.Word, %2 : $Builtin.Word, %4 : $Builtin.Int1) : $(Builtin.Word, Builtin.Int1)
|
|
%7 = tuple_extract %6 : $(Builtin.Word, Builtin.Int1), 0
|
|
%9 = builtin "inttoptr_Word"(%7 : $Builtin.Word) : $Builtin.RawPointer
|
|
%11 = builtin "cmp_eq_RawPointer"(%1 : $Builtin.RawPointer, %9 : $Builtin.RawPointer) : $Builtin.Int1
|
|
cond_fail %11 : $Builtin.Int1
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @nonnil :
|
|
// CHECK: bb0
|
|
// CHECK-NOT: select_enum
|
|
// CHECK: [[ONE:%[^ ]+]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK: return [[ONE]]
|
|
// CHECK: } // end sil function 'nonnil'
|
|
sil [ossa] @nonnil : $@convention(thin) () -> Builtin.Int1 {
|
|
bb0:
|
|
%1 = integer_literal $Builtin.Int32, 8
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32)
|
|
%3 = enum $Optional<Int32>, #Optional.some!enumelt, %2 : $Int32
|
|
%t = integer_literal $Builtin.Int1, -1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
%5 = select_enum %3 : $Optional<Int32>, case #Optional.some!enumelt: %t, case #Optional.none!enumelt: %f : $Builtin.Int1
|
|
return %5 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @isnil :
|
|
// CHECK: bb0
|
|
// CHECK-NOT: select_enum
|
|
// CHECK: [[ZERO:%[^ ]+]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK: return [[ZERO]]
|
|
// CHECK: } // end sil function 'isnil'
|
|
sil [ossa] @isnil : $@convention(thin) () -> Builtin.Int1 {
|
|
bb0:
|
|
%1 = enum $Optional<Int>, #Optional.none!enumelt
|
|
%t = integer_literal $Builtin.Int1, -1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
%5 = select_enum %1 : $Optional<Int>, case #Optional.some!enumelt: %t, case #Optional.none!enumelt: %f : $Builtin.Int1
|
|
return %5 : $Builtin.Int1
|
|
}
|
|
|
|
class ZZZ {
|
|
@objc deinit
|
|
init()
|
|
}
|
|
|
|
struct SSS {
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_delete_readonly_owned :
|
|
// CHECK: bb0(%0 : @owned $ZZZ):
|
|
// CHECK-NEXT: destroy_value %0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'test_delete_readonly_owned'
|
|
sil [ossa] @test_delete_readonly_owned : $@convention(thin) (@owned ZZZ) -> () {
|
|
bb0(%0 : @owned $ZZZ):
|
|
%2 = function_ref @read_only_owned : $@convention(thin) (@owned ZZZ) -> () // user: %4
|
|
%4 = apply %2(%0) : $@convention(thin) (@owned ZZZ) -> ()
|
|
%6 = tuple () // user: %7
|
|
return %6 : $() // id: %7
|
|
}
|
|
|
|
sil [readonly] @read_only_owned : $@convention(thin) (@owned ZZZ) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_delete_readonly_guaranteed :
|
|
// CHECK: bb0(%0 : @guaranteed $ZZZ):
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'test_delete_readonly_guaranteed'
|
|
sil [ossa] @test_delete_readonly_guaranteed : $@convention(thin) (@guaranteed ZZZ) -> () {
|
|
bb0(%0 : @guaranteed $ZZZ):
|
|
%2 = function_ref @read_only_guaranteed : $@convention(thin) (@guaranteed ZZZ) -> () // user: %4
|
|
%4 = apply %2(%0) : $@convention(thin) (@guaranteed ZZZ) -> ()
|
|
%6 = tuple () // user: %7
|
|
return %6 : $() // id: %7
|
|
}
|
|
|
|
sil [readonly] @read_only_guaranteed : $@convention(thin) (@guaranteed ZZZ) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_delete_readonly_in :
|
|
// CHECK: bb0(%0 : $*SSS):
|
|
// CHECK-NEXT: destroy_addr %0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'test_delete_readonly_in'
|
|
sil [ossa] @test_delete_readonly_in : $@convention(thin) (@in SSS) -> () {
|
|
bb0(%0 : $*SSS):
|
|
%2 = function_ref @read_only_in : $@convention(thin) (@in SSS) -> () // user: %4
|
|
%4 = apply %2(%0) : $@convention(thin) (@in SSS) -> ()
|
|
%6 = tuple () // user: %7
|
|
return %6 : $() // id: %7
|
|
}
|
|
|
|
sil [readonly] @read_only_in : $@convention(thin) (@in SSS) -> ()
|
|
|
|
struct MyError : Error {
|
|
}
|
|
|
|
sil [readonly] @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
|
|
sil [readonly] @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
sil [ossa] @returns_param : $@convention(thin) (@owned B) -> @owned B
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_readonly_insert_release_after_arc_uses_simple :
|
|
// CHECK: copy_value
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'delete_readonly_insert_release_after_arc_uses_simple'
|
|
sil [ossa] @delete_readonly_insert_release_after_arc_uses_simple : $@convention(thin) (@owned B) -> @owned B {
|
|
bb0(%0 : @owned $B):
|
|
%fu = function_ref @returns_param : $@convention(thin) (@owned B) -> @owned B
|
|
%0a = copy_value %0 : $B
|
|
%ru = apply %fu(%0a) : $@convention(thin) (@owned B) -> @owned B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%0b = copy_value %0 : $B
|
|
%r = apply %f(%0b) : $@convention(thin) (@owned B) -> @owned B
|
|
%rua = copy_value %ru : $B // This is actually %0
|
|
destroy_value %ru : $B
|
|
destroy_value %rua : $B
|
|
destroy_value %r : $B
|
|
return %0 : $B
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_readonly_insert_release_after_arc_uses_multibb
|
|
// CHECK: apply
|
|
// CHECK-NEXT: cond_br
|
|
//
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: br bb3(
|
|
//
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: br bb3(
|
|
//
|
|
// CHECK: bb3(
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'delete_readonly_insert_release_after_arc_uses_multibb'
|
|
sil [ossa] @delete_readonly_insert_release_after_arc_uses_multibb : $@convention(thin) (@owned B) -> @owned B {
|
|
bb0(%0 : @owned $B):
|
|
%fu = function_ref @returns_param : $@convention(thin) (@owned B) -> @owned B
|
|
%0a = copy_value %0 : $B
|
|
%ru = apply %fu(%0) : $@convention(thin) (@owned B) -> @owned B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%r = apply %f(%0a) : $@convention(thin) (@owned B) -> @owned B
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%rua = copy_value %ru : $B // This is actually %0
|
|
destroy_value %r : $B
|
|
br bb3(%rua : $B)
|
|
|
|
bb2:
|
|
%rub = copy_value %ru : $B // This is actually %0
|
|
destroy_value %r : $B
|
|
br bb3(%rub : $B)
|
|
|
|
bb3(%ruOut : @owned $B):
|
|
destroy_value %ru : $B
|
|
return %ruOut : $B
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_delete_readonly_function_dealloc_ref_simple :
|
|
// CHECK: apply
|
|
// CHECK-NEXT: dealloc_ref
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'dont_delete_readonly_function_dealloc_ref_simple'
|
|
sil [ossa] @dont_delete_readonly_function_dealloc_ref_simple : $@convention(thin) () -> () {
|
|
bb0:
|
|
%3 = alloc_ref [stack] $B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%3a = copy_value %3 : $B
|
|
%r = apply %f(%3a) : $@convention(thin) (@owned B) -> @owned B
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
destroy_value %r : $B
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_delete_readonly_function_dealloc_ref_multibb :
|
|
// CHECK: apply
|
|
// CHECK: dealloc_stack_ref
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK: dealloc_stack_ref
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'dont_delete_readonly_function_dealloc_ref_multibb'
|
|
sil [ossa] @dont_delete_readonly_function_dealloc_ref_multibb : $@convention(thin) () -> () {
|
|
bb0:
|
|
%3 = alloc_ref [stack] $B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%3a = copy_value %3 : $B
|
|
%r = apply %f(%3a) : $@convention(thin) (@owned B) -> @owned B
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
destroy_value %r : $B
|
|
br bb3
|
|
|
|
bb2:
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
destroy_value %r : $B
|
|
br bb3
|
|
|
|
bb3:
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_readonly_function_dealloc_ref_simple :
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'delete_readonly_function_dealloc_ref_simple'
|
|
sil [ossa] @delete_readonly_function_dealloc_ref_simple : $@convention(thin) () -> () {
|
|
bb0:
|
|
%3 = alloc_ref [stack] $B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%3a = copy_value %3 : $B
|
|
%r = apply %f(%3a) : $@convention(thin) (@owned B) -> @owned B
|
|
destroy_value %r : $B
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_readonly_function_dealloc_ref_multibb :
|
|
// CHECK-NOT: apply
|
|
// CHECK: } // end sil function 'delete_readonly_function_dealloc_ref_multibb'
|
|
sil [ossa] @delete_readonly_function_dealloc_ref_multibb : $@convention(thin) () -> () {
|
|
bb0:
|
|
%3 = alloc_ref [stack] $B
|
|
%f = function_ref @readonly_owned : $@convention(thin) (@owned B) -> @owned B
|
|
%3a = copy_value %3 : $B
|
|
%r = apply %f(%3a) : $@convention(thin) (@owned B) -> @owned B
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_value %r : $B
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
br bb3
|
|
|
|
bb2:
|
|
destroy_value %r : $B
|
|
dealloc_ref %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
br bb3
|
|
|
|
bb3:
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_delete_readonly_try_apply :
|
|
// CHECK: bb0(%0 : @owned $ZZZ):
|
|
// CHECK-NEXT: [[IL:%[0-9]+]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK-NEXT: cond_br [[IL]], bb1, bb2
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: destroy_value %0
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: destroy_value %0
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb3:
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'test_delete_readonly_try_apply'
|
|
sil [ossa] @test_delete_readonly_try_apply : $@convention(thin) (@owned ZZZ) -> () {
|
|
bb0(%0 : @owned $ZZZ):
|
|
%2 = function_ref @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
try_apply %2(%0) : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : @owned $ZZZ):
|
|
destroy_value %4 : $ZZZ
|
|
br bb3
|
|
|
|
bb2(%8 : @owned $Error):
|
|
destroy_value %8 : $Error
|
|
br bb3
|
|
|
|
bb3:
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_dont_delete_readonly_try_apply1 :
|
|
// CHECK: try_apply %{{[0-9]+}}(%0)
|
|
// CHECK: } // end sil function 'test_dont_delete_readonly_try_apply1'
|
|
sil [ossa] @test_dont_delete_readonly_try_apply1 : $@convention(thin) (@owned ZZZ) -> () {
|
|
bb0(%0 : @owned $ZZZ):
|
|
%2 = function_ref @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
try_apply %2(%0) : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : @owned $ZZZ):
|
|
destroy_value %4 : $ZZZ
|
|
br bb3
|
|
|
|
bb2(%8 : @owned $Error):
|
|
// Additional instructions in error block.
|
|
%u = function_ref @unknown : $@convention(thin) () -> ()
|
|
%r = apply %u() : $@convention(thin) () -> ()
|
|
destroy_value %8 : $Error
|
|
br bb3
|
|
|
|
bb3:
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_dont_delete_readonly_try_apply2 :
|
|
// CHECK: try_apply %{{[0-9]+}}(%0)
|
|
// CHECK: } // end sil function 'test_dont_delete_readonly_try_apply2'
|
|
sil [ossa] @test_dont_delete_readonly_try_apply2 : $@convention(thin) (@owned ZZZ) -> () {
|
|
bb0(%0 : @owned $ZZZ):
|
|
%2 = function_ref @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
try_apply %2(%0) : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : @owned $ZZZ):
|
|
// Additional instructions in normal return block.
|
|
%u = function_ref @unknown : $@convention(thin) () -> ()
|
|
%r = apply %u() : $@convention(thin) () -> ()
|
|
destroy_value %4 : $ZZZ
|
|
br bb3
|
|
|
|
bb2(%8 : @owned $Error):
|
|
destroy_value %8 : $Error
|
|
br bb3
|
|
|
|
bb3:
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_dont_delete_readonly_try_apply3 :
|
|
// CHECK: try_apply %{{[0-9]+}}(%0)
|
|
// CHECK: } // end sil function 'test_dont_delete_readonly_try_apply3'
|
|
sil [ossa] @test_dont_delete_readonly_try_apply3 : $@convention(thin) (@owned ZZZ) -> () {
|
|
bb0(%0 : @owned $ZZZ):
|
|
%2 = function_ref @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
try_apply %2(%0) : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : @owned $ZZZ):
|
|
destroy_value %4 : $ZZZ
|
|
br bb3
|
|
|
|
bb2(%8 : @owned $Error):
|
|
destroy_value %8 : $Error
|
|
// Normal and error block don't have a common successor block.
|
|
br bb4
|
|
|
|
bb3:
|
|
%u = function_ref @unknown : $@convention(thin) () -> ()
|
|
%r = apply %u() : $@convention(thin) () -> ()
|
|
br bb4
|
|
|
|
bb4:
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_dont_delete_readonly_try_apply4 :
|
|
// CHECK: try_apply
|
|
// CHECK: } // end sil function 'test_dont_delete_readonly_try_apply4'
|
|
sil [ossa] @test_dont_delete_readonly_try_apply4 : $@convention(thin) (@owned ZZZ, @owned ZZZ) -> @owned ZZZ {
|
|
bb0(%0 : @owned $ZZZ, %1 : @owned $ZZZ):
|
|
%2 = function_ref @readonly_throwing : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error)
|
|
%0a = copy_value %0 : $ZZZ
|
|
try_apply %2(%0) : $@convention(thin) (@owned ZZZ) -> (@owned ZZZ, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%4 : @owned $ZZZ):
|
|
destroy_value %4 : $ZZZ
|
|
destroy_value %1 : $ZZZ
|
|
br bb3(%0a : $ZZZ)
|
|
|
|
bb2(%8 : @owned $Error):
|
|
destroy_value %8 : $Error
|
|
destroy_value %0a : $ZZZ
|
|
// Normal and error block don't use the same block arguments for the common successor.
|
|
br bb3(%1 : $ZZZ)
|
|
|
|
bb3(%a : @owned $ZZZ):
|
|
return %a : $ZZZ
|
|
}
|
|
|
|
struct FakeInt16 {
|
|
var val : Builtin.Int16
|
|
}
|
|
|
|
struct FakeInt32 {
|
|
var val : Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @loadable_switchenumaddr_promotion : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
|
|
// CHECK-NOT: switch_enum_addr
|
|
// CHECK: load
|
|
// CHECK-NEXT: switch_enum
|
|
// CHECK-NOT: switch_enum_addr
|
|
// CHECK: } // end sil function 'loadable_switchenumaddr_promotion'
|
|
sil [ossa] @loadable_switchenumaddr_promotion : $@convention(thin) (@in FakeOptional<Builtin.RawPointer>) -> () {
|
|
bb0(%0 : $*FakeOptional<Builtin.RawPointer>):
|
|
switch_enum_addr %0 : $*FakeOptional<Builtin.RawPointer>, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2
|
|
|
|
bb1:
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
// We do not perform this optimization in SILCombine in OSSA since we would be
|
|
// deleting an edge from the CFG.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @resilient_enum_case_propagation :
|
|
// CHECK: switch_enum_addr
|
|
// CHECK: } // end sil function 'resilient_enum_case_propagation'
|
|
sil [ossa] @resilient_enum_case_propagation : $@convention(thin) () -> Builtin.Int64 {
|
|
bb0:
|
|
%0 = alloc_stack $FloatingPointRoundingRule
|
|
inject_enum_addr %0 : $*FloatingPointRoundingRule, #FloatingPointRoundingRule.toNearestOrEven!enumelt
|
|
%2 = alloc_stack $FloatingPointRoundingRule
|
|
copy_addr %0 to [init] %2 : $*FloatingPointRoundingRule
|
|
destroy_addr %0 : $*FloatingPointRoundingRule
|
|
switch_enum_addr %2 : $*FloatingPointRoundingRule, case #FloatingPointRoundingRule.toNearestOrAwayFromZero!enumelt: bb1, default bb2
|
|
|
|
bb1:
|
|
%6 = integer_literal $Builtin.Int64, 1
|
|
br bb3(%6 : $Builtin.Int64)
|
|
|
|
bb2:
|
|
destroy_addr %2 : $*FloatingPointRoundingRule
|
|
%9 = integer_literal $Builtin.Int64, 0
|
|
br bb3(%9 : $Builtin.Int64)
|
|
|
|
bb3(%11 : $Builtin.Int64):
|
|
dealloc_stack %2 : $*FloatingPointRoundingRule
|
|
dealloc_stack %0 : $*FloatingPointRoundingRule
|
|
return %11 : $Builtin.Int64
|
|
}
|
|
|
|
|
|
@objc(XX) protocol XX {
|
|
}
|
|
|
|
class XXImpl : XX {
|
|
@objc deinit
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unowned_round_trips : $@convention(thin) (@guaranteed B, @guaranteed @sil_unowned B, @guaranteed AnyObject, @sil_unmanaged AnyObject) -> (B, @sil_unowned B, AnyObject, @sil_unmanaged AnyObject) {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'unowned_round_trips'
|
|
sil [ossa] @unowned_round_trips : $@convention(thin) (@guaranteed B, @guaranteed @sil_unowned B, @guaranteed AnyObject, @sil_unmanaged AnyObject) -> (B, @sil_unowned B, AnyObject, @sil_unmanaged AnyObject) {
|
|
bb0(%0 : @guaranteed $B, %1 : @guaranteed $@sil_unowned B, %2 : @guaranteed $AnyObject, %3 : $@sil_unmanaged AnyObject):
|
|
%4 = ref_to_unowned %0 : $B to $@sil_unowned B
|
|
%5 = unowned_to_ref %4 : $@sil_unowned B to $B
|
|
%6 = unowned_to_ref %1 : $@sil_unowned B to $B
|
|
%7 = ref_to_unowned %6 : $B to $@sil_unowned B
|
|
|
|
%8 = ref_to_unmanaged %2 : $AnyObject to $@sil_unmanaged AnyObject
|
|
%9 = unmanaged_to_ref %8 : $@sil_unmanaged AnyObject to $AnyObject
|
|
%10 = unmanaged_to_ref %3 : $@sil_unmanaged AnyObject to $AnyObject
|
|
%11 = ref_to_unmanaged %10 : $AnyObject to $@sil_unmanaged AnyObject
|
|
|
|
%9999 = tuple(%5 : $B, %7 : $@sil_unowned B, %9 : $AnyObject, %11 : $@sil_unmanaged AnyObject)
|
|
return %9999 : $(B, @sil_unowned B, AnyObject, @sil_unmanaged AnyObject)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast :
|
|
// CHECK: bb0([[Ref:%.*]] : @guaranteed $MyClass):
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: unchecked_ref_cast [[Ref]]
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast : $@convention(thin) (@guaranteed MyClass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @guaranteed $MyClass):
|
|
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("2CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%3 = unchecked_ref_cast %2 : $@opened("2CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
%3a = copy_value %3 : $Builtin.NativeObject
|
|
return %3a : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned :
|
|
// CHECK: bb0([[Ref:%.*]] : @owned $MyClass):
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: unchecked_ref_cast [[Ref]]
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned : $@convention(thin) (@owned MyClass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $MyClass):
|
|
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("3CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%3 = unchecked_ref_cast %2 : $@opened("3CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_1 :
|
|
// CHECK: bb0([[Ref:%.*]] : @owned $MyClass):
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: unchecked_ref_cast [[Ref]]
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_1'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_1 : $@convention(thin) (@owned MyClass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $MyClass):
|
|
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("4CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%3 = unchecked_ref_cast %2 : $@opened("4CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_2 :
|
|
// CHECK: bb0([[Ref:%.*]] : @owned $MyClass):
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: unchecked_ref_cast [[Ref]]
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_2'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_diff_blocks_2 : $@convention(thin) (@owned MyClass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $MyClass):
|
|
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("5CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
br bb2
|
|
|
|
bb2:
|
|
%3 = unchecked_ref_cast %2 : $@opened("5CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_fail :
|
|
// CHECK: bb0(
|
|
// CHECK: init_existential_ref
|
|
// CHECK: open_existential_ref
|
|
// CHECK: unchecked_ref_cast
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned_fail'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned_fail : $@convention(thin) (@owned Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = init_existential_ref %0 : $Klass : $Klass, $AnyObject
|
|
%f = function_ref @use_anyobject_guaranteed : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("6CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%3 = unchecked_ref_cast %2 : $@opened("6CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned3 :
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned3'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned3 : $@convention(thin) (@owned Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = init_existential_ref %0 : $Klass : $Klass, $AnyObject
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%f = function_ref @use_generic_obj_guaranteed : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
|
|
apply %f<@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self>(%2) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
|
|
%3 = unchecked_ref_cast %2 : $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned4 :
|
|
// CHECK: apply {{.*}}<Klass>
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_unchecked_ref_cast_owned4'
|
|
sil [ossa] @collapse_existential_pack_unpack_unchecked_ref_cast_owned4 : $@convention(thin) (@owned Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = init_existential_ref %0 : $Klass : $Klass, $AnyObject
|
|
%f1 = function_ref @use_anyobject_guaranteed : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
apply %f1(%1) : $@convention(thin) (@guaranteed AnyObject) -> ()
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%f2 = function_ref @use_generic_obj_guaranteed : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
|
|
apply %f2<@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self>(%2) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
|
|
%3 = unchecked_ref_cast %2 : $@opened("7CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_existential_pack_unpack_ref_to_raw_pointer
|
|
// CHECK: bb0([[Ref:%.*]] : @guaranteed $MyClass):
|
|
// CHECK-NOT: init_existential_ref
|
|
// CHECK-NOT: open_existential_ref
|
|
// CHECK: ref_to_raw_pointer [[Ref]]
|
|
// CHECK: } // end sil function 'collapse_existential_pack_unpack_ref_to_raw_pointer'
|
|
sil [ossa] @collapse_existential_pack_unpack_ref_to_raw_pointer : $@convention(thin) (@guaranteed MyClass) -> () {
|
|
bb0(%0 : @guaranteed $MyClass):
|
|
%1 = init_existential_ref %0 : $MyClass : $MyClass, $AnyObject
|
|
%2 = open_existential_ref %1 : $AnyObject to $@opened("8CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self
|
|
%3 = ref_to_raw_pointer %2 : $@opened("8CAE06CE-5F10-11E4-AF13-C82A1428F987", AnyObject) Self to $Builtin.RawPointer
|
|
%4 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%5 = integer_literal $Builtin.Word, 5
|
|
store %5 to [trivial] %4 : $*Builtin.Word
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_fixlifetime_address :
|
|
// CHECK: [[Stck:%.*]] = alloc_stack
|
|
// CHECK-NOT: fix_lifetime [[Stck]]#1
|
|
// CHECK: [[StckVal:%.*]] = load_borrow [[Stck]]
|
|
// CHECK: fix_lifetime [[StckVal]]
|
|
// CHECK: } // end sil function 'load_fixlifetime_address'
|
|
sil [ossa] @load_fixlifetime_address : $@convention(thin) (@owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = alloc_stack $Builtin.NativeObject
|
|
store %0 to [init] %1: $*Builtin.NativeObject
|
|
fix_lifetime %1 : $*Builtin.NativeObject
|
|
destroy_addr %1 : $*Builtin.NativeObject
|
|
dealloc_stack %1 : $*Builtin.NativeObject
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @collapse_to_unchecked_trivial_bit_cast :
|
|
// CHECK: bb0([[Ref:%.*]] : @guaranteed $Optional<MyClass>):
|
|
// CHECK: unchecked_trivial_bit_cast [[Ref]]
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-NOT: ref_to_raw_pointer
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'collapse_to_unchecked_trivial_bit_cast'
|
|
// (ref_to_raw_pointer (unchecked_ref_cast x)) -> (unchecked_trivial_bit_cast x)
|
|
sil [ossa] @collapse_to_unchecked_trivial_bit_cast : $@convention(thin) (@guaranteed Optional<MyClass>) -> Builtin.RawPointer {
|
|
bb0(%0 : @guaranteed $Optional<MyClass>):
|
|
%1 = unchecked_ref_cast %0 : $Optional<MyClass> to $Builtin.NativeObject
|
|
%2 = ref_to_raw_pointer %1 : $Builtin.NativeObject to $Builtin.RawPointer
|
|
return %2 : $Builtin.RawPointer
|
|
}
|
|
|
|
struct GenContainer<T> {
|
|
}
|
|
|
|
sil public_external [serialized] @materializeForSetClosure : $@convention(thin) <T> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenContainer<T>, @thick GenContainer<T>.Type) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*GenContainer<T>, %3 : $@thick GenContainer<T>.Type):
|
|
unreachable
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_dead_code_after_cond_fail :
|
|
// CHECK: [[Ref:%.*]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK-NEXT: cond_fail [[Ref]]
|
|
// CHECK-NEXT: unreachable
|
|
// CHECK: } // end sil function 'remove_dead_code_after_cond_fail'
|
|
sil [ossa] @remove_dead_code_after_cond_fail : $@convention(thin) () -> (Int32) {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int32, -2
|
|
%1 = integer_literal $Builtin.Int1, -1
|
|
cond_fail %1 : $Builtin.Int1
|
|
%3 = struct $Int32 (%0 : $Builtin.Int32)
|
|
return %3 : $Int32
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_remove_code_after_cond_fail
|
|
// CHECK: bb0([[Cond:%.*]] : $Builtin.Int1):
|
|
// CHECK-NEXT: [[Ref:%.*]] = integer_literal $Builtin.Int32, -2
|
|
// CHECK-NEXT: cond_fail [[Cond]]
|
|
// CHECK-NEXT: [[Ret:%.*]] = struct $Int32 ([[Ref]] : $Builtin.Int32)
|
|
// CHECK-NEXT: return [[Ret]]
|
|
// CHECK: } // end sil function 'dont_remove_code_after_cond_fail'
|
|
sil [ossa] @dont_remove_code_after_cond_fail : $@convention(thin) (Builtin.Int1) -> (Int32) {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%1 = integer_literal $Builtin.Int32, -2
|
|
cond_fail %0 : $Builtin.Int1
|
|
%3 = struct $Int32 (%1 : $Builtin.Int32)
|
|
return %3 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @builtin_array_opt_index_raw_pointer_to_index_addr :
|
|
// CHECK: [[MT:%.*]] = metatype $@thick Int32.Type
|
|
// CHECK: [[ONE:%.*]] = integer_literal $Builtin.Word, 1
|
|
// CHECK: [[PTA1:%.*]] = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int32
|
|
// CHECK: [[CAST1:%.*]] = builtin "truncOrBitCast_Int64_Word"(%0 : $Builtin.Int64)
|
|
// CHECK: [[IAD1:%.*]] = index_addr [[PTA1]] : $*Int32, [[CAST1]] : $Builtin.Word
|
|
// CHECK: [[ATP1:%.*]] = address_to_pointer [[IAD1]] : $*Int32 to $Builtin.RawPointer
|
|
// CHECK: [[PTA2:%.*]] = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Int32
|
|
// CHECK: [[CAST2:%.*]] = builtin "truncOrBitCast_Int64_Word"(%0 : $Builtin.Int64)
|
|
// CHECK: [[IAD2:%.*]] = index_addr [[PTA2]] : $*Int32, [[CAST2]] : $Builtin.Word
|
|
// CHECK: [[ATP2:%.*]] = address_to_pointer [[IAD2]] : $*Int32 to $Builtin.RawPointer
|
|
// CHECK: builtin "takeArrayFrontToBack"<Int32>([[MT]] : $@thick Int32.Type, [[ATP1]] : $Builtin.RawPointer, [[ATP2]] : $Builtin.RawPointer, [[ONE]] : $Builtin.Word) : $()
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'builtin_array_opt_index_raw_pointer_to_index_addr'
|
|
|
|
sil [ossa] @builtin_array_opt_index_raw_pointer_to_index_addr : $@convention(thin) (Builtin.Int64, Builtin.RawPointer, Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.Int64, %1 : $Builtin.RawPointer, %2 : $Builtin.RawPointer):
|
|
%4 = metatype $@thick Int32.Type
|
|
%5 = integer_literal $Builtin.Word, 1
|
|
%6 = integer_literal $Builtin.Int1, 0
|
|
%7 = builtin "strideof"<Int32>(%4 : $@thick Int32.Type) : $Builtin.Word
|
|
%14 = builtin "zextOrBitCast_Word_Int64"(%7 : $Builtin.Word) : $Builtin.Int64
|
|
%8 = builtin "smul_with_overflow_Word"(%14 : $Builtin.Int64, %0 : $Builtin.Int64, %6 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%15 = builtin "truncOrBitCast_Int64_Word"(%9 : $Builtin.Int64) : $Builtin.Word
|
|
%10 = index_raw_pointer %1 : $Builtin.RawPointer, %15 : $Builtin.Word
|
|
%11 = index_raw_pointer %2 : $Builtin.RawPointer, %15 : $Builtin.Word
|
|
%12 = builtin "takeArrayFrontToBack"<Int32>(%4 : $@thick Int32.Type, %10 : $Builtin.RawPointer, %11 : $Builtin.RawPointer, %5 : $Builtin.Word) : $()
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
// Make sure we do not crash here. This ensures that when checking for
|
|
// tuple_extract, we check if we have an argument or not.
|
|
sil [ossa] @builtin_array_opt_index_raw_pointer_to_index_addr_no_crash : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.Word {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%2 = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word
|
|
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%4 = load [trivial] %3 : $*Builtin.Word
|
|
return %4 : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cmp_zext_peephole :
|
|
// CHECK: bb0([[Arg1:%.*]] : $Builtin.Word, [[Arg2:%.*]] : $Builtin.Word):
|
|
// CHECK: [[ZA1:%.*]] = builtin "zextOrBitCast_Word_Int64"([[Arg1]] : $Builtin.Word) : $Builtin.Int64
|
|
// CHECK: [[ZA2:%.*]] = builtin "zextOrBitCast_Word_Int64"([[Arg2]] : $Builtin.Word) : $Builtin.Int64
|
|
// CHECK: builtin "cmp_eq_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_ne_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_ule_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_ult_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_uge_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_ugt_Word"([[Arg1]] : $Builtin.Word, [[Arg2]] : $Builtin.Word)
|
|
// CHECK: builtin "cmp_sle_Int64"([[ZA1]] : $Builtin.Int64, [[ZA2]] : $Builtin.Int64)
|
|
// CHECK: builtin "cmp_slt_Int64"([[ZA1]] : $Builtin.Int64, [[ZA2]] : $Builtin.Int64)
|
|
// CHECK: builtin "cmp_sge_Int64"([[ZA1]] : $Builtin.Int64, [[ZA2]] : $Builtin.Int64)
|
|
// CHECK: builtin "cmp_sgt_Int64"([[ZA1]] : $Builtin.Int64, [[ZA2]] : $Builtin.Int64)
|
|
// CHECK: } // end sil function 'cmp_zext_peephole'
|
|
sil [ossa] @cmp_zext_peephole : $@convention(thin) (Builtin.Word, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.Word, %1 : $Builtin.Word):
|
|
%2 = builtin "zextOrBitCast_Word_Int64"(%0 : $Builtin.Word) : $Builtin.Int64
|
|
%3 = builtin "zextOrBitCast_Word_Int64"(%1 : $Builtin.Word) : $Builtin.Int64
|
|
|
|
%4 = builtin "cmp_eq_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %4 : $Builtin.Int1
|
|
|
|
%6 = builtin "cmp_ne_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %6 : $Builtin.Int1
|
|
|
|
%8 = builtin "cmp_ule_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %8 : $Builtin.Int1
|
|
|
|
%10 = builtin "cmp_ult_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %10 : $Builtin.Int1
|
|
|
|
%12 = builtin "cmp_uge_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %12 : $Builtin.Int1
|
|
|
|
%14 = builtin "cmp_ugt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %14 : $Builtin.Int1
|
|
|
|
%16 = builtin "cmp_sle_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %16 : $Builtin.Int1
|
|
|
|
%18 = builtin "cmp_slt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %18 : $Builtin.Int1
|
|
|
|
%20 = builtin "cmp_sge_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %20 : $Builtin.Int1
|
|
|
|
%22 = builtin "cmp_sgt_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_fail %22 : $Builtin.Int1
|
|
|
|
%24 = tuple()
|
|
return %24 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_ref_dynamic_with_metatype :
|
|
// CHECK: bb0
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK-NEXT: alloc_ref $B
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_with_metatype'
|
|
sil [ossa] @alloc_ref_dynamic_with_metatype : $() -> () {
|
|
%1 = metatype $@thick B.Type
|
|
%2 = alloc_ref_dynamic %1 : $@thick B.Type, $B
|
|
destroy_value %2 : $B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK: sil [ossa] @alloc_ref_dynamic_with_metatype_generic :
|
|
// CHECK: metatype
|
|
// CHECK: upcast
|
|
// CHECK: alloc_ref_dynamic
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_with_metatype_generic'
|
|
sil [ossa] @alloc_ref_dynamic_with_metatype_generic : $<T where T : B>() -> () {
|
|
%1 = metatype $@thick T.Type
|
|
%2 = upcast %1 : $@thick T.Type to $@thick B.Type
|
|
%3 = alloc_ref_dynamic %2 : $@thick B.Type, $B
|
|
destroy_value %3 : $B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_ref_dynamic_with_upcast_metatype :
|
|
// CHECK: bb0
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK-NEXT: [[R:%[0-9]+]] = alloc_ref $E
|
|
// CHECK-NEXT: [[C:%[0-9]+]] = upcast [[R]] : $E to $B
|
|
// CHECK-NEXT: return [[C]]
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_with_upcast_metatype'
|
|
sil [ossa] @alloc_ref_dynamic_with_upcast_metatype : $@convention(thin) () -> @owned B {
|
|
%1 = metatype $@thick E.Type
|
|
%2 = upcast %1 : $@thick E.Type to $@thick B.Type
|
|
%3 = alloc_ref_dynamic %2 : $@thick B.Type, $B
|
|
return %3 : $B
|
|
}
|
|
|
|
// CHECK-LABEL: @alloc_ref_dynamic_after_successful_checked_cast_br :
|
|
// CHECK: checked_cast_br
|
|
// CHECK: bb1
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK: alloc_ref $B
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_after_successful_checked_cast_br'
|
|
sil [ossa] @alloc_ref_dynamic_after_successful_checked_cast_br : $(@thick B.Type) -> Builtin.Int32 {
|
|
bb0(%1 : $@thick B.Type):
|
|
checked_cast_br [exact] @thick B.Type in %1 : $@thick B.Type to B.Type, bb1, bb2
|
|
|
|
bb1(%2 : $@thick B.Type):
|
|
%3 = alloc_ref_dynamic %2 : $@thick B.Type, $B
|
|
destroy_value %3 : $B
|
|
%4 = integer_literal $Builtin.Int32, 1
|
|
br bb3 (%4 : $Builtin.Int32)
|
|
|
|
bb2(%2a : $@thick B.Type):
|
|
%5 = integer_literal $Builtin.Int32, 2
|
|
br bb3 (%5 : $Builtin.Int32)
|
|
|
|
bb3 (%10: $Builtin.Int32):
|
|
return %10 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @alloc_ref_dynamic_upcast_after_successful_checked_cast_br
|
|
// CHECK: checked_cast_br
|
|
// CHECK: bb1
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK: [[R:%[0-9]+]] = alloc_ref $E
|
|
// CHECK-NEXT: destroy_value [[R]]
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_upcast_after_successful_checked_cast_br'
|
|
sil [ossa] @alloc_ref_dynamic_upcast_after_successful_checked_cast_br : $(@thick B.Type) -> Builtin.Int32 {
|
|
bb0(%1 : $@thick B.Type):
|
|
checked_cast_br [exact] @thick B.Type in %1 : $@thick B.Type to E.Type, bb1, bb2
|
|
|
|
bb1(%2 : $@thick E.Type):
|
|
%3 = upcast %2 : $@thick E.Type to $@thick B.Type
|
|
%4 = alloc_ref_dynamic %3 : $@thick B.Type, $B
|
|
destroy_value %4 : $B
|
|
%5 = integer_literal $Builtin.Int32, 1
|
|
br bb3 (%5 : $Builtin.Int32)
|
|
|
|
bb2(%2a : $@thick B.Type):
|
|
%6 = integer_literal $Builtin.Int32, 2
|
|
br bb3 (%6 : $Builtin.Int32)
|
|
|
|
bb3 (%10: $Builtin.Int32):
|
|
return %10 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_ref_dynamic_stack_with_metatype :
|
|
// CHECK: bb0:
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK-NEXT: alloc_ref [stack] $B
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: dealloc_stack_ref
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_stack_with_metatype'
|
|
sil [ossa] @alloc_ref_dynamic_stack_with_metatype : $() -> () {
|
|
%1 = metatype $@thick B.Type
|
|
%2 = alloc_ref_dynamic [stack] %1 : $@thick B.Type, $B
|
|
destroy_value %2 : $B
|
|
dealloc_stack_ref %2 : $B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @alloc_ref_dynamic_stack_with_upcast_metatype :
|
|
// CHECK: alloc_ref_dynamic [stack]
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_stack_with_upcast_metatype'
|
|
sil [ossa] @alloc_ref_dynamic_stack_with_upcast_metatype : $() -> () {
|
|
%1 = metatype $@thick E.Type
|
|
%2 = upcast %1 : $@thick E.Type to $@thick B.Type
|
|
%3 = alloc_ref_dynamic [stack] %2 : $@thick B.Type, $B
|
|
destroy_value %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @alloc_ref_dynamic_stack_after_successful_checked_cast_br :
|
|
// CHECK: checked_cast_br
|
|
// CHECK: bb1
|
|
// CHECK-NOT: alloc_ref_dynamic
|
|
// CHECK: alloc_ref [stack] $B
|
|
// CHECK: } // end sil function 'alloc_ref_dynamic_stack_after_successful_checked_cast_br'
|
|
sil [ossa] @alloc_ref_dynamic_stack_after_successful_checked_cast_br : $(@thick B.Type) -> Builtin.Int32 {
|
|
bb0(%1 : $@thick B.Type):
|
|
checked_cast_br [exact] @thick B.Type in %1 : $@thick B.Type to B.Type, bb1, bb2
|
|
|
|
bb1(%2 : $@thick B.Type):
|
|
%3 = alloc_ref_dynamic [stack] %2 : $@thick B.Type, $B
|
|
destroy_value %3 : $B
|
|
dealloc_stack_ref %3 : $B
|
|
%4 = integer_literal $Builtin.Int32, 1
|
|
br bb3 (%4 : $Builtin.Int32)
|
|
|
|
bb2(%2a : $@thick B.Type):
|
|
%5 = integer_literal $Builtin.Int32, 2
|
|
br bb3 (%5 : $Builtin.Int32)
|
|
|
|
bb3 (%10: $Builtin.Int32):
|
|
return %10 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_dead_alloc_stack
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @delete_dead_alloc_stack : $(@inout B) -> () {
|
|
bb0(%0 : $*B):
|
|
%1 = alloc_stack $B
|
|
copy_addr %0 to [init] %1 : $*B
|
|
destroy_addr %1 : $*B
|
|
dealloc_stack %1 : $*B
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @delete_dead_alloc_stack2
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: destroy_addr %0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
sil [ossa] @delete_dead_alloc_stack2 : $(@in B) -> () {
|
|
bb0(%0 : $*B):
|
|
%1 = alloc_stack $B
|
|
copy_addr [take] %0 to [init] %1 : $*B
|
|
destroy_addr %1 : $*B
|
|
dealloc_stack %1 : $*B
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
sil [ossa] @use_b : $@convention(thin) (@inout B) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_delete_dead_alloc_stack :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: alloc_stack
|
|
// CHECK-NEXT: copy_addr
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'dont_delete_dead_alloc_stack'
|
|
sil [ossa] @dont_delete_dead_alloc_stack : $(@inout B) -> () {
|
|
bb0(%0 : $*B):
|
|
%1 = alloc_stack $B
|
|
copy_addr %0 to [init] %1 : $*B
|
|
%2 = function_ref @use_b : $@convention(thin) (@inout B) -> ()
|
|
%3 = apply %2(%1) : $@convention(thin) (@inout B) -> ()
|
|
destroy_addr %1 : $*B
|
|
dealloc_stack %1 : $*B
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
protocol someProtocol {
|
|
var i: Int { get }
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @witness_archetype
|
|
// XHECK: bb0
|
|
// XHECK-NEXT: alloc_stack $T
|
|
// XHECK-NEXT: copy_addr
|
|
// XHECK-NEXT: destroy_addr
|
|
// XHECK-NEXT: [[T0:%.*]] = witness_method $T
|
|
// XHECK-NEXT: apply [[T0]]<T>
|
|
// XHECK: return
|
|
sil [ossa] @witness_archetype : $@convention(thin) <T where T : someProtocol> (@in T) -> () {
|
|
bb0(%0 : $*T):
|
|
%3 = alloc_stack $someProtocol // users: %4, %7, %10, %13, %15
|
|
%4 = init_existential_addr %3 : $*someProtocol, $T // user: %5
|
|
copy_addr %0 to [init] %4 : $*T // id: %5
|
|
destroy_addr %0 : $*T // id: %6
|
|
%7 = open_existential_addr immutable_access %3 : $*someProtocol to $*@opened("105977B0-D8EB-11E4-AC00-3C0754644993", someProtocol) Self // users: %8, %9
|
|
%8 = witness_method $@opened("105977B0-D8EB-11E4-AC00-3C0754644993", someProtocol) Self, #someProtocol.i!getter, %7 : $*@opened("105977B0-D8EB-11E4-AC00-3C0754644993", someProtocol) Self : $@convention(witness_method: someProtocol) <τ_0_0 where τ_0_0 : someProtocol> (@in_guaranteed τ_0_0) -> Int // user: %9
|
|
%9 = apply %8<@opened("105977B0-D8EB-11E4-AC00-3C0754644993", someProtocol) Self>(%7) : $@convention(witness_method: someProtocol) <τ_0_0 where τ_0_0 : someProtocol> (@in_guaranteed τ_0_0) -> Int
|
|
destroy_addr %3 : $*someProtocol // id: %13
|
|
dealloc_stack %3 : $*someProtocol // id: %15
|
|
%16 = tuple () // user: %17
|
|
return %16 : $() // id: %17
|
|
}
|
|
|
|
protocol P {
|
|
}
|
|
|
|
protocol Q : P {
|
|
}
|
|
|
|
struct T : Q {
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @silcombine_checked_cast_addr_br_on_metatype_into_checked_cast_br_on_metatype
|
|
// CHECK: bb0:
|
|
// CHECK: metatype $@thick T.Type
|
|
// CHECK-NOT: checked_cast_addr_br
|
|
// CHECK: checked_cast_br
|
|
// CHECK: bb1(%[[ARG:[0-9]+]] : $@thick any Q.Type)
|
|
// CHECK: store %[[ARG]] to {{.*}} : $*@thick any Q.Type
|
|
// CHECK: }
|
|
sil [ossa] @silcombine_checked_cast_addr_br_on_metatype_into_checked_cast_br_on_metatype : $@convention(thin) () -> Bool {
|
|
bb0:
|
|
%1 = metatype $@thick T.Type
|
|
%2 = init_existential_metatype %1 : $@thick T.Type, $@thick P.Type
|
|
%3 = alloc_stack $@thick P.Type
|
|
store %2 to [trivial] %3 : $*@thick P.Type
|
|
%5 = alloc_stack $@thick Q.Type
|
|
checked_cast_addr_br take_always P.Type in %3 : $*@thick P.Type to Q.Type in %5 : $*@thick Q.Type, bb1, bb3
|
|
|
|
bb1:
|
|
%7 = integer_literal $Builtin.Int1, -1
|
|
br bb2(%7 : $Builtin.Int1)
|
|
|
|
bb2(%9 : $Builtin.Int1):
|
|
dealloc_stack %5 : $*@thick Q.Type
|
|
dealloc_stack %3 : $*@thick P.Type
|
|
%12 = struct $Bool (%9 : $Builtin.Int1)
|
|
return %12 : $Bool
|
|
|
|
bb3:
|
|
%14 = integer_literal $Builtin.Int1, 0
|
|
br bb2(%14 : $Builtin.Int1)
|
|
}
|
|
|
|
// Make sure we do not crash on this and remove everything
|
|
// CHECK-LABEL: sil [ossa] @partial_apply_retain_removal : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'partial_apply_retain_removal'
|
|
sil [ossa] @partial_apply_retain_removal : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @owned $Builtin.NativeObject):
|
|
%1 = function_ref @user : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
%0a = copy_value %0 : $Builtin.NativeObject
|
|
%2 = partial_apply %1(%0a) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
destroy_value %2 : $@callee_owned @convention(thick) () -> ()
|
|
return %0 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_cmp_xor_canonicalization :
|
|
// CHECK:bb0([[ARG:%.*]] : $Builtin.Int1
|
|
// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK: [[FALSE:%.*]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK: [[EQ:%.*]] = builtin "cmp_eq_Int1"([[ARG]] : $Builtin.Int1, [[FALSE]]
|
|
// CHECK: [[NOT:%.*]] = builtin "xor_Int1"([[EQ]] : $Builtin.Int1, [[TRUE]] : $Builtin.Int1)
|
|
// CHECK: return [[NOT]]
|
|
// CHECK: } // end sil function 'test_cmp_xor_canonicalization'
|
|
sil [ossa] @test_cmp_xor_canonicalization : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%1 = integer_literal $Builtin.Int1, -1
|
|
%2 = builtin "cmp_eq_Int1"(%0 : $Builtin.Int1, %1 : $Builtin.Int1) : $Builtin.Int1
|
|
return %2 : $Builtin.Int1
|
|
}
|
|
|
|
struct NStruct {
|
|
var a:Int
|
|
var b:Int
|
|
}
|
|
|
|
final class NClass {
|
|
init(news: NStruct)
|
|
var s: NStruct
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @narrow_load_with_debug_value :
|
|
// CHECK: bb0(%0 : @guaranteed $NClass):
|
|
// CHECK: debug_value %0
|
|
// CHECK: [[C:%[0-9]+]] = ref_element_addr %0
|
|
// CHECK: [[S:%[0-9]+]] = struct_element_addr [[C]]
|
|
// CHECK: [[R:%[0-9]+]] = load [trivial] [[S]]
|
|
// CHECK: return [[R]]
|
|
// CHECK: } // end sil function 'narrow_load_with_debug_value'
|
|
sil [ossa] @narrow_load_with_debug_value : $@convention(thin) (@guaranteed NClass) -> Int {
|
|
bb0(%0 : @guaranteed $NClass):
|
|
debug_value %0 : $NClass, let, name "c" // id: %1
|
|
%2 = ref_element_addr %0 : $NClass, #NClass.s // user: %3
|
|
%3 = load [trivial] %2 : $*NStruct // users: %4, %5
|
|
debug_value %3 : $NStruct, let, name "xx" // id: %4
|
|
%5 = struct_extract %3 : $NStruct, #NStruct.a // user: %7
|
|
return %5 : $Int // id: %7
|
|
}
|
|
|
|
enum VendingMachineError: Error {
|
|
case InvalidSelection
|
|
case InsufficientFunds(required: Double)
|
|
case OutOfStock
|
|
}
|
|
|
|
// Check that we can delete exceptions if we can inline the `throw`
|
|
// block into the `try` block.
|
|
// CHECK-LABEL: @RemoveUnusedException
|
|
// CHECK-NOT: alloc_existential_box
|
|
// CHECK-NOT: enum $VendingMachineError
|
|
// CHECK: return
|
|
sil hidden [ossa] @RemoveUnusedException : $@convention(thin) (Int32) -> (Double, @error Error) {
|
|
bb0(%0 : $Int32):
|
|
debug_value %0 : $Int32, let, name "x" // id: %1
|
|
%2 = integer_literal $Builtin.Int32, 10 // user: %4
|
|
%3 = struct_extract %0 : $Int32, #Int32._value // user: %4
|
|
%4 = builtin "cmp_sgt_Int32"(%3 : $Builtin.Int32, %2 : $Builtin.Int32) : $Builtin.Int1 // user: %5
|
|
cond_br %4, bb1, bb2 // id: %5
|
|
|
|
bb1: // Preds: bb0
|
|
%6 = alloc_existential_box $Error, $VendingMachineError // users: %8, %9, %13
|
|
%6a = project_existential_box $VendingMachineError in %6 : $Error
|
|
%7 = enum $VendingMachineError, #VendingMachineError.OutOfStock!enumelt // user: %8
|
|
store %7 to [trivial] %6a : $*VendingMachineError // id: %8
|
|
debug_value %6 : $Error, let, name "error" // id: %9
|
|
%10 = float_literal $Builtin.FPIEEE80, 0x3FFF8000000000000000 // 1 // user: %11
|
|
%11 = builtin "fptrunc_FPIEEE80_FPIEEE64"(%10 : $Builtin.FPIEEE80) : $Builtin.FPIEEE64 // user: %12
|
|
%12 = struct $Double (%11 : $Builtin.FPIEEE64) // user: %14
|
|
destroy_value %6 : $Error // id: %13
|
|
br bb3(%12 : $Double) // id: %14
|
|
|
|
bb2: // Preds: bb0
|
|
%15 = float_literal $Builtin.FPIEEE80, 0x40008000000000000000 // 2 // user: %16
|
|
%16 = builtin "fptrunc_FPIEEE80_FPIEEE64"(%15 : $Builtin.FPIEEE80) : $Builtin.FPIEEE64 // user: %17
|
|
%17 = struct $Double (%16 : $Builtin.FPIEEE64) // user: %18
|
|
br bb3(%17 : $Double) // id: %18
|
|
|
|
bb3(%19 : $Double): // Preds: bb1 bb2
|
|
return %19 : $Double // id: %20
|
|
}
|
|
|
|
enum ErrorEnum: Error {
|
|
case errorCase(label: [Error])
|
|
case other
|
|
}
|
|
|
|
// In OSSA we can completely remove this test case from sil_combine.sil. I added
|
|
// a version afterwards that is too complicated for sil-combine that should show
|
|
// the behavior specified.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @insert_compensating_release_at_release_of_box :
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'insert_compensating_release_at_release_of_box'
|
|
sil [ossa] @insert_compensating_release_at_release_of_box : $@convention(method) (@in_guaranteed Array<Error>) -> () {
|
|
bb0(%0 : $*Array<Error>):
|
|
%20 = load [copy] %0 : $*Array<Error>
|
|
%22 = tuple $(label: Array<Error>) (%20)
|
|
%23 = enum $ErrorEnum, #ErrorEnum.errorCase!enumelt, %22 : $(label: Array<Error>)
|
|
%36 = alloc_existential_box $Error, $ErrorEnum
|
|
%37 = project_existential_box $ErrorEnum in %36 : $Error
|
|
store %23 to [init] %37 : $*ErrorEnum
|
|
destroy_value %36 : $Error
|
|
%52 = tuple ()
|
|
return %52 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @insert_compensating_release_at_release_of_box_2 :
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'insert_compensating_release_at_release_of_box_2'
|
|
sil [ossa] @insert_compensating_release_at_release_of_box_2 : $@convention(method) (@in_guaranteed Array<Error>) -> () {
|
|
bb0(%0 : $*Array<Error>):
|
|
%20 = load_borrow %0 : $*Array<Error>
|
|
%22 = tuple $(label: Array<Error>) (%20)
|
|
%23 = enum $ErrorEnum, #ErrorEnum.errorCase!enumelt, %22 : $(label: Array<Error>)
|
|
%23a = copy_value %23 : $ErrorEnum
|
|
end_borrow %20 : $Array<Error>
|
|
%36 = alloc_existential_box $Error, $ErrorEnum
|
|
%37 = project_existential_box $ErrorEnum in %36 : $Error
|
|
store %23a to [init] %37 : $*ErrorEnum
|
|
destroy_value %36 : $Error
|
|
%52 = tuple ()
|
|
return %52 : $()
|
|
}
|
|
|
|
|
|
struct TestError: Error {
|
|
var payload: AnyObject
|
|
}
|
|
|
|
struct OtherError: Error {
|
|
var payload: AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast :
|
|
// CHECK: bb0([[ERROR:%.*]] : @guaranteed
|
|
// CHECK: [[ERROR_COPY_2:%.*]] = copy_value [[ERROR]]
|
|
// CHECK: [[BOX:%.*]] = alloc_existential_box
|
|
// CHECK: [[ERROR_COPY_1:%.*]] = copy_value [[ERROR]]
|
|
// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error
|
|
// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]]
|
|
// CHECK: store [[BOX_COPY]] to [init] [[E]]
|
|
// CHECK: [[T:%[0-9]+]] = alloc_stack $TestError
|
|
// CHECK-NEXT: destroy_addr [[E]]
|
|
// CHECK-NEXT: store [[ERROR_COPY_2]] to [init] [[T]]
|
|
// CHECK-NEXT: struct_element_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast'
|
|
sil [ossa] @unconditional_existential_box_cast : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
sil [ossa] @unknown_use_of_TestError : $@convention(thin) (@inout TestError) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_unknown_user1
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_unknown_user1'
|
|
sil [ossa] @unconditional_existential_box_cast_unknown_user1 : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%u = function_ref @unknown_use_of_TestError : $@convention(thin) (@inout TestError) -> ()
|
|
%r = apply %u(%2) : $@convention(thin) (@inout TestError) -> ()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
sil [ossa] @unknown_use_of_box : $@convention(thin) (Error) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_unknown_user2
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_unknown_user2'
|
|
sil [ossa] @unconditional_existential_box_cast_unknown_user2 : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%u = function_ref @unknown_use_of_box : $@convention(thin) (Error) -> ()
|
|
%r = apply %u(%1) : $@convention(thin) (Error) -> ()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
sil [ossa] @unknown_use_of_Error : $@convention(thin) (@inout Error) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_unknown_user3
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_unknown_user3'
|
|
sil [ossa] @unconditional_existential_box_cast_unknown_user3 : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%u = function_ref @unknown_use_of_Error : $@convention(thin) (@inout Error) -> ()
|
|
%r = apply %u(%5) : $@convention(thin) (@inout Error) -> ()
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_multiple_stores1
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_multiple_stores1'
|
|
sil [ossa] @unconditional_existential_box_cast_multiple_stores1 : $@convention(thin) (@guaranteed TestError, @guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError, %0a : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0c = copy_value %0 : $TestError
|
|
store %0c to [init] %2 : $*TestError
|
|
%0ac = copy_value %0a : $TestError
|
|
store %0ac to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_multiple_stores2
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_multiple_stores2'
|
|
sil [ossa] @unconditional_existential_box_cast_multiple_stores2 : $@convention(thin) (@guaranteed TestError, @owned Error) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError, %0a : @owned $Error):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0c = copy_value %0 : $TestError
|
|
store %0c to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
store %1 to [init] %5 : $*Error
|
|
store %0a to [assign] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_wrong_type
|
|
// CHECK: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_wrong_type'
|
|
sil [ossa] @unconditional_existential_box_cast_wrong_type : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $OtherError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to OtherError in %7 : $*OtherError
|
|
%10 = struct_element_addr %7 : $*OtherError, #OtherError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*OtherError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unconditional_existential_box_cast_not_dominating :
|
|
// CHECK-NOT: unconditional_checked_cast_addr
|
|
// CHECK: } // end sil function 'unconditional_existential_box_cast_not_dominating'
|
|
sil [ossa] @unconditional_existential_box_cast_not_dominating : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
cond_br undef, bb1, bb2a
|
|
|
|
bb1:
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
br bb2
|
|
|
|
bb2a:
|
|
br bb2
|
|
|
|
bb2:
|
|
cond_br undef, bb3, bb4
|
|
|
|
bb3:
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
unconditional_checked_cast_addr Error in %5 : $*Error to TestError in %7 : $*TestError
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
|
|
bb4:
|
|
%20 = integer_literal $Builtin.Int1, -1
|
|
cond_fail %20 : $Builtin.Int1
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @conditional_existential_box_cast :
|
|
// CHECK: [[LIFETIME_EXTENDING_COPY:%.*]] = copy_value %0
|
|
// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error
|
|
// CHECK: [[T:%[0-9]+]] = alloc_stack $TestError
|
|
// CHECK: store [[LIFETIME_EXTENDING_COPY]] to [init] [[T]]
|
|
// CHECK-NEXT: [[I:%[0-9]+]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK-NEXT: cond_br [[I]], bb1, bb2
|
|
// CHECK: } // end sil function 'conditional_existential_box_cast'
|
|
sil [ossa] @conditional_existential_box_cast : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
checked_cast_addr_br copy_on_success Error in %5 : $*Error to TestError in %7 : $*TestError, bb1, bb2
|
|
|
|
bb1:
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
destroy_addr %5 : $*Error
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
|
|
bb2:
|
|
%20 = integer_literal $Builtin.Int1, -1
|
|
cond_fail %20 : $Builtin.Int1
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @taking_conditional_existential_box_cast :
|
|
// CHECK: [[LIFETIME_EXTENDING_COPY:%.*]] = copy_value %0
|
|
// CHECK: [[E:%[0-9]+]] = alloc_stack $any Error
|
|
// CHECK: [[T:%[0-9]+]] = alloc_stack $TestError
|
|
// CHECK: destroy_addr [[E]]
|
|
// CHECK-NEXT: store [[LIFETIME_EXTENDING_COPY]] to [init] [[T]]
|
|
// CHECK-NEXT: [[I:%[0-9]+]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK-NEXT: cond_br [[I]], bb1, bb2
|
|
// CHECK: } // end sil function 'taking_conditional_existential_box_cast'
|
|
sil [ossa] @taking_conditional_existential_box_cast : $@convention(thin) (@guaranteed TestError) -> @owned AnyObject {
|
|
bb0(%0 : @guaranteed $TestError):
|
|
%1 = alloc_existential_box $Error, $TestError
|
|
%2 = project_existential_box $TestError in %1 : $Error
|
|
%0a = copy_value %0 : $TestError
|
|
store %0a to [init] %2 : $*TestError
|
|
%4 = builtin "willThrow"(%1 : $Error) : $()
|
|
%5 = alloc_stack $Error
|
|
%1a = copy_value %1 : $Error
|
|
store %1a to [init] %5 : $*Error
|
|
%7 = alloc_stack $TestError
|
|
checked_cast_addr_br take_on_success Error in %5 : $*Error to TestError in %7 : $*TestError, bb1, bb2
|
|
|
|
bb1:
|
|
%10 = struct_element_addr %7 : $*TestError, #TestError.payload
|
|
%11 = load [take] %10 : $*AnyObject
|
|
destroy_value %1 : $Error
|
|
dealloc_stack %7 : $*TestError
|
|
dealloc_stack %5 : $*Error
|
|
return %11 : $AnyObject
|
|
|
|
bb2:
|
|
%20 = integer_literal $Builtin.Int1, -1
|
|
cond_fail %20 : $Builtin.Int1
|
|
unreachable
|
|
}
|
|
|
|
sil [reabstraction_thunk] @_TTRXFo_oSS_dSb_XFo_iSS_iSb_ : $@convention(thin) (@in String, @owned @callee_owned (@owned String) -> Bool) -> @out Bool
|
|
sil [reabstraction_thunk] @_TTRXFo_iSS_iSb_XFo_oSS_dSb_ : $@convention(thin) (@owned String, @owned @callee_owned (@in String) -> @out Bool) -> Bool
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_identity_reabstraction_thunks :
|
|
// CHECK: [[STK:%.*]] = alloc_stack $@callee_owned (@owned String) -> Bool
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: store %0 to [init] [[STK]]
|
|
// CHECK: [[LD:%.*]] = load [take] [[STK]]
|
|
// CHECK: destroy_value [[LD]]
|
|
// CHECK: dealloc_stack [[STK]]
|
|
// CHECK: } // end sil function 'remove_identity_reabstraction_thunks'
|
|
sil [ossa] @remove_identity_reabstraction_thunks : $@convention(thin) (@owned @callee_owned (@owned String) -> Bool) -> () {
|
|
bb0(%0 : @owned $@callee_owned (@owned String) -> Bool):
|
|
%1 = alloc_stack $@callee_owned (@owned String) -> Bool
|
|
// function_ref reabstraction thunk helper from @callee_owned (@owned Swift.String) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.String) -> (@out Swift.Bool)
|
|
%2 = function_ref @_TTRXFo_oSS_dSb_XFo_iSS_iSb_ : $@convention(thin) (@in String, @owned @callee_owned (@owned String) -> Bool) -> @out Bool
|
|
%3 = partial_apply %2(%0) : $@convention(thin) (@in String, @owned @callee_owned (@owned String) -> Bool) -> @out Bool
|
|
debug_value %3 : $@callee_owned (@in String) -> @out Bool
|
|
// function_ref reabstraction thunk helper from @callee_owned (@in Swift.String) -> (@out Swift.Bool) to @callee_owned (@owned Swift.String) -> (@unowned Swift.Bool)
|
|
%4 = function_ref @_TTRXFo_iSS_iSb_XFo_oSS_dSb_ : $@convention(thin) (@owned String, @owned @callee_owned (@in String) -> @out Bool) -> Bool
|
|
%5 = partial_apply %4(%3) : $@convention(thin) (@owned String, @owned @callee_owned (@in String) -> @out Bool) -> Bool
|
|
store %5 to [init] %1 : $*@callee_owned (@owned String) -> Bool
|
|
%6 = load [take] %1 : $*@callee_owned (@owned String) -> Bool
|
|
destroy_value %6 : $@callee_owned (@owned String) -> Bool
|
|
dealloc_stack %1 : $*@callee_owned (@owned String) -> Bool
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_unused_convert_function :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'remove_unused_convert_function'
|
|
sil [ossa] @remove_unused_convert_function : $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> () {
|
|
bb0(%0 : $*B, %1 : @guaranteed $B, %2 : $Builtin.Int1):
|
|
%3 = function_ref @weird_function : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> ()
|
|
%4 = convert_function %3 : $@convention(thin) (@inout E, @guaranteed E, Builtin.Int1) -> () to $@convention(thin) (@inout B, @guaranteed B, Builtin.Int1) -> ()
|
|
%7 = tuple()
|
|
return %7 : $()
|
|
}
|
|
|
|
// Make sure that we do not crash when determining if a value is not zero and
|
|
// has a value that cannot be stored in a UInt64. The specific issue is that we
|
|
// were using getZExtValue before which assumes that an APInt can be stored in a
|
|
// UInt64.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @large_int_zero_comparison : $@convention(thin) () -> Builtin.Int1 {
|
|
// CHECK: [[CMP_RESULT:%.*]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK: return [[CMP_RESULT]]
|
|
// CHECK: } // end sil function 'large_int_zero_comparison'
|
|
sil [ossa] @large_int_zero_comparison : $@convention(thin) () -> Builtin.Int1 {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int1024, 0
|
|
%1 = integer_literal $Builtin.Int1024, 0xFFFFFFFFFFFFFFFFFFFF
|
|
%2 = builtin "cmp_eq_Int1024"(%0 : $Builtin.Int1024, %1 : $Builtin.Int1024) : $Builtin.Int1
|
|
return %2 : $Builtin.Int1
|
|
}
|
|
|
|
sil [ossa] @callee : $@convention(thin) (Double, @in_guaranteed Int) -> ()
|
|
sil [ossa] @generic_callee : $@convention(thin) <T, U> (@in T, @in U) -> ()
|
|
sil [ossa] @noreturn_func : $@convention(thin) () -> Never
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_destroy_array :
|
|
// CHECK-NOT: destroyArray
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'remove_destroy_array'
|
|
sil [ossa] @remove_destroy_array : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%4 = metatype $@thick Int32.Type
|
|
%8 = builtin "destroyArray"<Int32>(%4 : $@thick Int32.Type, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
|
|
%90 = tuple ()
|
|
return %90 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_remove_destroy_array_of_nontrivial_type :
|
|
// CHECK: builtin "destroyArray"
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'dont_remove_destroy_array_of_nontrivial_type'
|
|
sil [ossa] @dont_remove_destroy_array_of_nontrivial_type : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%4 = metatype $@thick B.Type
|
|
%8 = builtin "destroyArray"<B>(%4 : $@thick B.Type, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
|
|
%90 = tuple ()
|
|
return %90 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_remove_destroy_array_of_generic_type :
|
|
// CHECK: builtin "destroyArray"
|
|
// CHECK: return
|
|
// CHECK: } // end sil function 'dont_remove_destroy_array_of_generic_type'
|
|
sil [ossa] @dont_remove_destroy_array_of_generic_type : $@convention(thin) <Memory> (Builtin.RawPointer, Builtin.Word) -> () {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%4 = metatype $@thick Memory.Type
|
|
%8 = builtin "destroyArray"<Memory>(%4 : $@thick Memory.Type, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
|
|
%90 = tuple ()
|
|
return %90 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_promotion_case3 :
|
|
// CHECK: bb0([[B_PTR:%[0-9]+]]
|
|
// CHECK-NEXT: [[ALLOCA:%[0-9]+]] = alloc_stack $FakeOptional<B>
|
|
// CHECK-NEXT: [[ENUM:%[0-9]+]] = enum $FakeOptional<B>, #FakeOptional.some!enumelt, [[B_PTR]] : $B
|
|
// CHECK-NEXT: store [[ENUM]] to [init] [[ALLOCA]]
|
|
// CHECK-NEXT: [[RESULT:%[0-9]+]] = load [take] [[ALLOCA]]
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
// CHECK: } // end sil function 'enum_promotion_case3'
|
|
sil [ossa] @enum_promotion_case3 : $@convention(thin) (@owned B) -> @owned FakeOptional<B> {
|
|
bb0(%0 : @owned $B):
|
|
%2 = alloc_stack $FakeOptional<B>
|
|
%3 = init_enum_data_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%0a = copy_value %0 : $B
|
|
store %0a to [init] %3 : $*B
|
|
|
|
// This instruction between the store and the inject_enum_addr should not prevent
|
|
// the optimization.
|
|
destroy_value %0 : $B
|
|
|
|
inject_enum_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%7 = load [take] %2 : $*FakeOptional<B>
|
|
dealloc_stack %2 : $*FakeOptional<B>
|
|
return %7 : $FakeOptional<B>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_promotion_case3a : $@convention(thin) (@owned B) -> @owned FakeOptional<B> {
|
|
// CHECK: } // end sil function 'enum_promotion_case3a'
|
|
sil [ossa] @enum_promotion_case3a : $@convention(thin) (@owned B) -> @owned FakeOptional<B> {
|
|
bb0(%0 : @owned $B):
|
|
%2 = alloc_stack $FakeOptional<B>
|
|
%3 = init_enum_data_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%0a = copy_value %0 : $B
|
|
store %0a to [init] %3 : $*B
|
|
|
|
// This instruction between the store and the inject_enum_addr should not prevent
|
|
// the optimization.
|
|
destroy_value %0 : $B
|
|
|
|
inject_enum_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%7 = load [copy] %2 : $*FakeOptional<B>
|
|
destroy_addr %2 : $*FakeOptional<B>
|
|
dealloc_stack %2 : $*FakeOptional<B>
|
|
return %7 : $FakeOptional<B>
|
|
}
|
|
|
|
sil [ossa] @init_enum : $@convention(thin) () -> @out B
|
|
|
|
|
|
// Localize the initialization of the enum payload to enable mem2reg for the enum.
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_promotion_case4
|
|
// CHECK: [[V1:%.*]] = alloc_stack $FakeOptional
|
|
// CHECK: [[V2:%.*]] = function_ref @init_enum
|
|
// CHECK: [[V3:%.*]] = alloc_stack $B
|
|
// CHECK: apply [[V2]]([[V3]])
|
|
// CHECK: [[V4:%.*]] = load [take] [[V3]]
|
|
// CHECK: [[V5:%.*]] = enum $FakeOptional<B>, #FakeOptional.some!enumelt, [[V4]]
|
|
// CHECK: store [[V5]] to [init] [[V1]]
|
|
|
|
sil [ossa] @enum_promotion_case4 : $@convention(thin) () -> @owned FakeOptional<B> {
|
|
bb0:
|
|
%2 = alloc_stack $FakeOptional<B>
|
|
%3 = init_enum_data_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%4 = function_ref @init_enum : $@convention(thin) () -> @out B
|
|
%5 = apply %4(%3) : $@convention(thin) () -> @out B
|
|
inject_enum_addr %2 : $*FakeOptional<B>, #FakeOptional.some!enumelt
|
|
%7 = load [take] %2 : $*FakeOptional<B>
|
|
dealloc_stack %2 : $*FakeOptional<B>
|
|
return %7 : $FakeOptional<B>
|
|
}
|
|
|
|
|
|
|
|
struct MyErrorType {}
|
|
|
|
protocol Socket {
|
|
static func newWithConfig() throws -> Builtin.Int32
|
|
}
|
|
|
|
class ClientSocket : Socket {
|
|
final class func newWithConfig() throws -> Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @static_existential : $@convention(thin) () -> (Builtin.Int32, @error MyErrorType) {
|
|
// CHECK:bb0:
|
|
// XHECK: [[META:%.*]] = metatype $@thick ClientSocket.Type
|
|
// XHECK: [[WM:%.*]] = witness_method $ClientSocket
|
|
// XHECK: try_apply [[WM]]<ClientSocket>([[META]])
|
|
// CHECK: } // end sil function 'static_existential'
|
|
sil [ossa] @static_existential : $@convention(thin) () -> (Builtin.Int32, @error MyErrorType) {
|
|
bb0:
|
|
%0 = metatype $@thick ClientSocket.Type
|
|
%1 = init_existential_metatype %0 : $@thick ClientSocket.Type, $@thick Socket.Type
|
|
%2 = open_existential_metatype %1 : $@thick Socket.Type to $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309913", Socket) Self).Type
|
|
%3 = witness_method $@opened("82105EE0-DCB0-11E5-865D-C8E0EB309913", Socket) Self, #Socket.newWithConfig, %2 : $@thick (@opened("82105EE0-DCB0-11E5-865D-C8E0EB309913", Socket) Self).Type : $@convention(witness_method: Socket) <τ_0_0 where τ_0_0 : Socket> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType)
|
|
try_apply %3<@opened("82105EE0-DCB0-11E5-865D-C8E0EB309913", Socket) Self>(%2) : $@convention(witness_method: Socket) <τ_0_0 where τ_0_0 : Socket> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType), normal bb1, error bb2
|
|
|
|
bb1(%4 : $Builtin.Int32):
|
|
return %4 : $Builtin.Int32
|
|
|
|
bb2(%5 : @owned $MyErrorType):
|
|
throw %5 : $MyErrorType
|
|
}
|
|
|
|
protocol PM {
|
|
var sum: Int { get nonmutating set }
|
|
func done()
|
|
}
|
|
|
|
extension PM {
|
|
func plus() -> Self
|
|
func minus()
|
|
}
|
|
|
|
|
|
public final class VV {
|
|
@_hasStorage final var m: PM { get set }
|
|
init()
|
|
deinit
|
|
}
|
|
|
|
sil [ossa] @plus : $@convention(method) <Self where Self : PM> (@in_guaranteed Self) -> @out Self
|
|
|
|
sil [ossa] @minus : $@convention(method) <Self where Self : PM> (@in_guaranteed Self) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @silcombine_dont_change_allocstack_for_opened_archetypes
|
|
// CHECK-NOT: alloc_stack{{.*}}opened
|
|
// CHECK: open_existential_addr immutable_access {{%[0-9]+}} : $*any PM to $*@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", any PM) Self
|
|
// CHECK: return
|
|
sil [ossa] @silcombine_dont_change_allocstack_for_opened_archetypes : $@convention(thin) (@owned VV) -> () {
|
|
bb0(%0 : @owned $VV):
|
|
%8 = alloc_stack $PM, let, name "x"
|
|
%0b = begin_borrow %0 : $VV
|
|
%9 = ref_element_addr %0b : $VV, #VV.m
|
|
%10 = alloc_stack $PM
|
|
copy_addr %9 to [init] %10 : $*PM
|
|
end_borrow %0b : $VV
|
|
%12 = open_existential_addr immutable_access %10 : $*PM to $*@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", PM) Self
|
|
%13 = init_existential_addr %8 : $*PM, $@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", PM) Self
|
|
%14 = function_ref @plus : $@convention(method) <τ_0_0 where τ_0_0 : PM> (@in_guaranteed τ_0_0) -> @out τ_0_0
|
|
%15 = apply %14<@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", PM) Self>(%13, %12) : $@convention(method) <τ_0_0 where τ_0_0 : PM> (@in_guaranteed τ_0_0) -> @out τ_0_0
|
|
destroy_addr %10 : $*PM
|
|
dealloc_stack %10 : $*PM
|
|
%20 = function_ref @minus : $@convention(method) <τ_0_0 where τ_0_0 : PM> (@in_guaranteed τ_0_0) -> ()
|
|
%21 = apply %20<@opened("090C3DB0-1C76-11E6-81C4-B8E856428C60", PM) Self>(%13) : $@convention(method) <τ_0_0 where τ_0_0 : PM> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %8 : $*PM
|
|
dealloc_stack %8 : $*PM
|
|
destroy_value %0 : $VV
|
|
%26 = tuple ()
|
|
return %26 : $()
|
|
}
|
|
|
|
sil [ossa] @any_to_object : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_crash_when_propagating_existentials
|
|
// CHECK: [[EM:%[0-9]+]] = init_existential_metatype %0
|
|
// CHECK: [[S:%[0-9]+]] = alloc_stack $C
|
|
// CHECK: [[M:%[0-9]+]] = open_existential_metatype [[EM]]
|
|
// CHECK: [[E:%[0-9]+]] = unchecked_addr_cast [[S]]
|
|
// CHECK: store [[M]] to [trivial] [[E]]
|
|
// CHECK: apply {{%[0-9]+}}<(@opened("5F99B72C-EC40-11EA-9534-8C8590A6A134", AnyObject) Self).Type>([[E]])
|
|
// CHECK: } // end sil function 'dont_crash_when_propagating_existentials'
|
|
sil [ossa] @dont_crash_when_propagating_existentials : $@convention(thin) () -> @owned AnyObject {
|
|
bb0:
|
|
%0 = metatype $@thick C.Type
|
|
%1 = init_existential_metatype %0 : $@thick C.Type, $@thick AnyObject.Type
|
|
%3 = alloc_stack $Any, let, name "object"
|
|
%4 = open_existential_metatype %1 : $@thick AnyObject.Type to $@thick (@opened("5F99B72C-EC40-11EA-9534-8C8590A6A134", AnyObject) Self).Type
|
|
%5 = init_existential_addr %3 : $*Any, $(@opened("5F99B72C-EC40-11EA-9534-8C8590A6A134", AnyObject) Self).Type
|
|
store %4 to [trivial] %5 : $*@thick (@opened("5F99B72C-EC40-11EA-9534-8C8590A6A134", AnyObject) Self).Type
|
|
%7 = open_existential_addr immutable_access %3 : $*Any to $*@opened("5F9F1B04-EC40-11EA-9534-8C8590A6A134", Any) Self
|
|
%8 = function_ref @any_to_object : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
|
|
%9 = apply %8<@opened("5F9F1B04-EC40-11EA-9534-8C8590A6A134", Any) Self>(%7) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
|
|
destroy_addr %3 : $*Any
|
|
dealloc_stack %3 : $*Any
|
|
return %9 : $AnyObject
|
|
}
|
|
|
|
// Int1_const == x -> x == Int1_const
|
|
// CHECK-LABEL: sil [ossa] @canonicalize_bool_eq_checks :
|
|
// CHECK: builtin "cmp_eq_Int1"(%0 : $Builtin.Int1, %1 :
|
|
// CHECK: } // end sil function 'canonicalize_bool_eq_checks'
|
|
sil [ossa] @canonicalize_bool_eq_checks : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%1 = integer_literal $Builtin.Int1, 0
|
|
%2 = builtin "cmp_eq_Int1"(%1 : $Builtin.Int1, %0 : $Builtin.Int1) : $Builtin.Int1
|
|
return %2 : $Builtin.Int1
|
|
}
|
|
|
|
// Int1_const != x -> x != Int1_const
|
|
// CHECK-LABEL: sil [ossa] @canonicalize_bool_ne_checks :
|
|
// CHECK: builtin "cmp_ne_Int1"(%0 : $Builtin.Int1, %1 :
|
|
// CHECK: } // end sil function 'canonicalize_bool_ne_checks'
|
|
sil [ossa] @canonicalize_bool_ne_checks : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%1 = integer_literal $Builtin.Int1, 0
|
|
%2 = builtin "cmp_ne_Int1"(%1 : $Builtin.Int1, %0 : $Builtin.Int1) : $Builtin.Int1
|
|
return %2 : $Builtin.Int1
|
|
}
|
|
|
|
// cond_br(xor(x, 1)), t_label, f_label -> cond_br x, f_label, t_label
|
|
// CHECK-LABEL: sil [ossa] @negate_branch_condition_xor1 :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function 'negate_branch_condition_xor1'
|
|
sil [ossa] @negate_branch_condition_xor1 : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%5 = integer_literal $Builtin.Int1, -1
|
|
%9 = builtin "xor_Int1"(%0 : $Builtin.Int1, %5 : $Builtin.Int1) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2 // id: %10
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// cond_br(xor(1, x)), t_label, f_label -> cond_br x, f_label, t_label
|
|
// CHECK-LABEL: sil [ossa] @negate_branch_condition_xor2 :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function 'negate_branch_condition_xor2'
|
|
sil [ossa] @negate_branch_condition_xor2 : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%5 = integer_literal $Builtin.Int1, -1
|
|
%9 = builtin "xor_Int1"(%5 : $Builtin.Int1, %0 : $Builtin.Int1) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2 // id: %10
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// cond_br(x == 0), t_label, f_label -> cond_br x, f_label, t_label
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @negate_branch_condition_eq_false :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function 'negate_branch_condition_eq_false'
|
|
sil [ossa] @negate_branch_condition_eq_false : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%5 = integer_literal $Builtin.Int1, 0
|
|
%9 = builtin "cmp_eq_Int1"(%0 : $Builtin.Int1, %5 : $Builtin.Int1) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2 // id: %10
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// cond_br(x != -1), t_label, f_label -> cond_br x, f_label, t_label
|
|
// CHECK-LABEL: sil [ossa] @negate_branch_condition_ne_true :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function 'negate_branch_condition_ne_true'
|
|
sil [ossa] @negate_branch_condition_ne_true : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%5 = integer_literal $Builtin.Int1, -1
|
|
%9 = builtin "cmp_ne_Int1"(%0 : $Builtin.Int1, %5 : $Builtin.Int1) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2 // id: %10
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_value_to_cond_br_1 :
|
|
// CHECK: bb0({{.*}}):
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
// CHECK: } // end sil function 'switch_value_to_cond_br_1'
|
|
sil [ossa] @switch_value_to_cond_br_1 : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%t1 = integer_literal $Builtin.Int1, -1
|
|
switch_value %0 : $Builtin.Int1, case %t1: bb1, default bb2
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_value_to_cond_br_2 :
|
|
// CHECK: bb0({{.*}}):
|
|
// CHECK-NEXT: cond_br %0, bb2, bb1
|
|
// CHECK: } // end sil function 'switch_value_to_cond_br_2'
|
|
sil [ossa] @switch_value_to_cond_br_2 : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%f1 = integer_literal $Builtin.Int1, 0
|
|
switch_value %0 : $Builtin.Int1, case %f1: bb1, default bb2
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @switch_value_to_cond_br_3 :
|
|
// CHECK: bb0({{.*}}):
|
|
// CHECK-NEXT: cond_br %0, bb1, bb2
|
|
// CHECK: } // end sil function 'switch_value_to_cond_br_3'
|
|
sil [ossa] @switch_value_to_cond_br_3 : $@convention(thin) (Builtin.Int1) -> Int32 {
|
|
bb0(%0 : $Builtin.Int1):
|
|
%t1 = integer_literal $Builtin.Int1, -1
|
|
%f1 = integer_literal $Builtin.Int1, 0
|
|
switch_value %0 : $Builtin.Int1, case %t1: bb1, case %f1: bb2
|
|
|
|
bb1: // Preds: bb0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
%2 = struct $Int32 (%1 : $Builtin.Int32) // user: %12
|
|
br bb3(%2 : $Int32) // id: %12
|
|
|
|
bb2: // Preds: bb0
|
|
%3 = integer_literal $Builtin.Int32, 1
|
|
%4 = struct $Int32 (%3 : $Builtin.Int32) // user: %12
|
|
br bb3(%4 : $Int32) // id: %15
|
|
|
|
bb3(%16 : $Int32): // Preds: bb1 bb2
|
|
return %16 : $Int32 // id: %17
|
|
}
|
|
|
|
protocol Prot0 : AnyObject {
|
|
static func newWithConfig() throws -> Builtin.Int32
|
|
}
|
|
|
|
|
|
protocol Prot1 : Prot0 {
|
|
@_nonoverride static func newWithConfig() throws -> Builtin.Int32
|
|
}
|
|
|
|
protocol Prot2 : Prot1 {
|
|
static func newWithConfig() throws -> Builtin.Int32
|
|
}
|
|
|
|
sil [ossa] @getMetaType : $@convention(thin) () -> @thick Prot2.Type
|
|
|
|
// CHECK-LABEL: sil [ossa] @meta_existential : $@convention(thin) () -> (Builtin.Int32, @error MyErrorType) {
|
|
// CHECK:bb0:
|
|
// XHECK: [[APPLY:%.*]] = apply {{%.*}}() : $@convention(thin) () -> @thick Prot2.Type
|
|
// XHECK: [[OE:%.*]] = open_existential_metatype [[APPLY]] : $@thick Prot2.Type to $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type
|
|
// XHECK: [[WM:%.*]] = witness_method $@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self, #Prot1.newWithConfig : <Self where Self : Prot1> (Self.Type) -> () throws -> Builtin.Int32, [[OE]] : $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType)
|
|
// XHECK: try_apply [[WM]]<@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self>([[OE]]) : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType)
|
|
// CHECK: } // end sil function 'meta_existential'
|
|
sil [ossa] @meta_existential : $@convention(thin) () -> (Builtin.Int32, @error MyErrorType) {
|
|
bb0:
|
|
%fref = function_ref @getMetaType : $@convention(thin) () -> @thick Prot2.Type
|
|
%apply = apply %fref() : $@convention(thin) () -> @thick Prot2.Type
|
|
%open = open_existential_metatype %apply : $@thick Prot2.Type to $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type
|
|
%1 = init_existential_metatype %open : $@thick (@opened("690DA5F6-B5EA-11E7-B144-685B3593C496", Prot1) Self).Type, $@thick Prot1.Type
|
|
%2 = open_existential_metatype %1 : $@thick Prot1.Type to $@thick (@opened("92105EE0-DCB0-11E5-865D-C8E0EB309913", Prot1) Self).Type
|
|
%3 = witness_method $@opened("92105EE0-DCB0-11E5-865D-C8E0EB309913", Prot1) Self, #Prot1.newWithConfig, %2 : $@thick (@opened("92105EE0-DCB0-11E5-865D-C8E0EB309913", Prot1) Self).Type : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType)
|
|
try_apply %3<@opened("92105EE0-DCB0-11E5-865D-C8E0EB309913", Prot1) Self>(%2) : $@convention(witness_method: Prot1) <τ_0_0 where τ_0_0 : Prot1> (@thick τ_0_0.Type) -> (Builtin.Int32, @error MyErrorType), normal bb1, error bb2
|
|
|
|
bb1(%4 : $Builtin.Int32):
|
|
return %4 : $Builtin.Int32
|
|
|
|
bb2(%5 : @owned $MyErrorType):
|
|
throw %5 : $MyErrorType
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @mark_dependence_base
|
|
// XHECK: bb0(
|
|
// XHECK-NOT: init_existential_ref
|
|
// XHECK-NOT: enum
|
|
// XHECK-NEXT: mark_dependence
|
|
// XHECK-NEXT: load
|
|
// XHECK: return
|
|
sil [ossa] @mark_dependence_base : $@convention(thin) (@inout Builtin.Int64, @owned B) -> Builtin.Int64 {
|
|
bb0(%0 : $*Builtin.Int64, %1 : @owned $B):
|
|
%x = init_existential_ref %1 : $B : $B, $AnyObject
|
|
%2 = enum $Optional<AnyObject>, #Optional.some!enumelt, %x : $AnyObject
|
|
%3 = mark_dependence %0 : $*Builtin.Int64 on %2 : $Optional<AnyObject>
|
|
%4 = load [trivial] %3 : $*Builtin.Int64
|
|
destroy_value %2 : $Optional<AnyObject>
|
|
return %4 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @mark_dependence_trivial_object_base :
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'mark_dependence_trivial_object_base'
|
|
sil [ossa] @mark_dependence_trivial_object_base : $@convention(thin) (@guaranteed B) -> @owned B {
|
|
bb0(%0 : @guaranteed $B):
|
|
%0a = copy_value %0 : $B
|
|
%1 = enum $Optional<Int>, #Optional.none!enumelt
|
|
%2 = mark_dependence %0a : $B on %1 : $Optional<Int>
|
|
return %2 : $B
|
|
}
|
|
|
|
// Check that a mark_dependence on an enum on a lexical value doesn't result in
|
|
// RAUWing the enum with the lexical value and extending the latter's lifetime.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @mark_dependence_base1_lexical1 : {{.*}} {
|
|
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*Builtin.Int64, [[INSTANCE:%[^,]+]] : @owned $B):
|
|
// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
|
|
// CHECK: [[OPTIONAL:%[^,]+]] = enum $FakeOptional<B>, #FakeOptional.some!enumelt, [[LIFETIME]]
|
|
// CHECK: [[DEPENDENT_ADDR:%[^,]+]] = mark_dependence [[ADDR]]
|
|
// CHECK: [[VALUE:%[^,]+]] = load [trivial] [[DEPENDENT_ADDR]]
|
|
// CHECK: return [[VALUE]]
|
|
// CHECK-LABEL: } // end sil function 'mark_dependence_base1_lexical1'
|
|
sil [ossa] @mark_dependence_base1_lexical1 : $@convention(thin) (@inout Builtin.Int64, @owned B) -> Builtin.Int64 {
|
|
bb0(%addr : $*Builtin.Int64, %instance : @owned $B):
|
|
%lifetime = move_value [lexical] %instance : $B
|
|
%optional = enum $FakeOptional<B>, #FakeOptional.some!enumelt, %lifetime : $B
|
|
%dependent_addr = mark_dependence %addr : $*Builtin.Int64 on %optional : $FakeOptional<B>
|
|
%value = load [trivial] %dependent_addr : $*Builtin.Int64
|
|
destroy_value %optional : $FakeOptional<B>
|
|
return %value : $Builtin.Int64
|
|
}
|
|
|
|
protocol _NSArrayCore {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @mark_dependence_base2
|
|
// XHECK: bb0(
|
|
// XHECK-NOT: open_existential_ref
|
|
// XHECK-NOT: enum
|
|
// XHECK-NEXT: mark_dependence
|
|
// XHECK-NEXT: load
|
|
// XHECK: return
|
|
sil [ossa] @mark_dependence_base2 : $@convention(thin) (@inout Builtin.Int64, @owned B) -> Builtin.Int64 {
|
|
bb0(%0 : $*Builtin.Int64, %1 : @owned $B):
|
|
%2 = init_existential_ref %1 : $B : $B, $AnyObject
|
|
%2a = begin_borrow %2 : $AnyObject
|
|
%3 = open_existential_ref %2a : $AnyObject to $@opened("B674783A-EF08-11E7-97D6-8C85900CB088", _NSArrayCore) Self
|
|
%5 = mark_dependence %0 : $*Builtin.Int64 on %3 : $@opened("B674783A-EF08-11E7-97D6-8C85900CB088", _NSArrayCore) Self
|
|
%4 = load [trivial] %5 : $*Builtin.Int64
|
|
end_borrow %2a : $AnyObject
|
|
destroy_value %2 : $AnyObject
|
|
return %4 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @mark_dependence_string_literal
|
|
// CHECK: %1 = string_literal utf8 "a"
|
|
// CHECK: %2 = struct $UnsafePointer<Int8> (%1 : $Builtin.RawPointer)
|
|
// CHECK: return %2
|
|
// CHECK: } // end sil function 'mark_dependence_string_literal'
|
|
sil [ossa] @mark_dependence_string_literal : $@convention(thin) (@guaranteed Builtin.NativeObject) -> UnsafePointer<Int8> {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject):
|
|
%1 = string_literal utf8 "a"
|
|
%2 = struct $UnsafePointer<Int8> (%1 : $Builtin.RawPointer)
|
|
%3 = mark_dependence %2 : $UnsafePointer<Int8> on %0 : $Builtin.NativeObject
|
|
return %3 : $UnsafePointer<Int8>
|
|
}
|
|
|
|
// Test to see if we can constant fold a classify_bridge_object on a Swift class
|
|
// to false.
|
|
// CHECK-LABEL: sil [ossa] @test_classify_fold :
|
|
// CHECK-NOT: classify_bridge_object
|
|
// CHECK: destroy_value
|
|
// CHECK: [[LITERAL:%.*]] = integer_literal $Builtin.Int1, 0
|
|
// CHECK: return [[LITERAL]]
|
|
// CHECK: } // end sil function 'test_classify_fold'
|
|
sil [ossa] @test_classify_fold : $@convention(thin) (@owned _ContiguousArrayStorage<B>) -> Builtin.Int1 {
|
|
bb0(%0 : @owned $_ContiguousArrayStorage<B>):
|
|
%1 = unchecked_ref_cast %0 : $_ContiguousArrayStorage<B> to $Builtin.BridgeObject
|
|
%2 = classify_bridge_object %1 : $Builtin.BridgeObject
|
|
%3 = tuple_extract %2 : $(Builtin.Int1, Builtin.Int1), 0
|
|
destroy_value %1 : $Builtin.BridgeObject
|
|
return %3 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @bridge_cast_noop_fold :
|
|
// CHECK: bb0(%0
|
|
// CHECK-NEXT: %1 = upcast %0
|
|
// CHECK-NEXT: return %1
|
|
// CHECK: } // end sil function 'bridge_cast_noop_fold'
|
|
sil [ossa] @bridge_cast_noop_fold : $@convention(thin) (@owned _ContiguousArrayStorage<B>) -> @owned __ContiguousArrayStorageBase {
|
|
bb0(%0 : @owned $_ContiguousArrayStorage<B>):
|
|
%1 = unchecked_ref_cast %0 : $_ContiguousArrayStorage<B> to $Builtin.BridgeObject
|
|
%2 = bridge_object_to_ref %1 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
|
|
return %2 : $__ContiguousArrayStorageBase
|
|
}
|
|
|
|
sil [ossa] @returnInt : $@convention(thin) () -> Builtin.Int32
|
|
|
|
// CHECK-LABEL: sil [ossa] @optimize_convert_escape_to_noescape :
|
|
// CHECK: [[FN:%.*]] = function_ref @returnInt
|
|
// CHECK: apply [[FN]]()
|
|
// CHECK: } // end sil function 'optimize_convert_escape_to_noescape'
|
|
sil [ossa] @optimize_convert_escape_to_noescape : $@convention(thin) () -> Builtin.Int32 {
|
|
bb0:
|
|
%0 = function_ref @returnInt : $@convention(thin) () -> Builtin.Int32
|
|
%1 = thin_to_thick_function %0 : $@convention(thin) () -> Builtin.Int32 to $@callee_guaranteed () -> Builtin.Int32
|
|
%2 = convert_escape_to_noescape %1 : $@callee_guaranteed () -> Builtin.Int32 to $@noescape @callee_guaranteed () -> Builtin.Int32
|
|
%4 = apply %2() : $@noescape @callee_guaranteed () -> Builtin.Int32
|
|
destroy_value %2 : $@noescape @callee_guaranteed () -> Builtin.Int32
|
|
return %4 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @optimize_stringObject_bit_operations :
|
|
// CHECK: bb0:
|
|
// CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 4611686018427387904
|
|
// CHECK-NEXT: return %0
|
|
// CHECK: } // end sil function 'optimize_stringObject_bit_operations'
|
|
sil [ossa] @optimize_stringObject_bit_operations : $@convention(thin) () -> Builtin.Int64 {
|
|
bb0:
|
|
%2 = string_literal utf8 "thequickbrownfoxjumpsoverthelazydogusingasmanycharacteraspossible123456789"
|
|
%5 = builtin "ptrtoint_Word"(%2 : $Builtin.RawPointer) : $Builtin.Word
|
|
%6 = builtin "zextOrBitCast_Word_Int64"(%5 : $Builtin.Word) : $Builtin.Int64
|
|
%9 = integer_literal $Builtin.Int64, 13835058055282163712
|
|
%10 = builtin "stringObjectOr_Int64"(%6 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int64
|
|
%11 = struct $UInt64 (%10 : $Builtin.Int64)
|
|
%12 = value_to_bridge_object %11 : $UInt64
|
|
%33 = unchecked_trivial_bit_cast %12 : $Builtin.BridgeObject to $UInt64
|
|
%34 = integer_literal $Builtin.Int64, 6917529027641081856
|
|
%35 = struct_extract %33 : $UInt64, #UInt64._value
|
|
%36 = builtin "and_Int64"(%35 : $Builtin.Int64, %34 : $Builtin.Int64) : $Builtin.Int64
|
|
return %36 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_optimize_stringObject_bit_operations1 :
|
|
// CHECK: builtin "stringObjectOr_Int64"
|
|
// CHECK: builtin "and_Int64"
|
|
// CHECK: } // end sil function 'dont_optimize_stringObject_bit_operations1'
|
|
sil [ossa] @dont_optimize_stringObject_bit_operations1 : $@convention(thin) (Builtin.RawPointer) -> Builtin.Int64 {
|
|
bb0(%2 : $Builtin.RawPointer):
|
|
%5 = builtin "ptrtoint_Word"(%2 : $Builtin.RawPointer) : $Builtin.Word
|
|
%6 = builtin "zextOrBitCast_Word_Int64"(%5 : $Builtin.Word) : $Builtin.Int64
|
|
%9 = integer_literal $Builtin.Int64, -9223372036854775808
|
|
%10 = builtin "stringObjectOr_Int64"(%6 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int64
|
|
%11 = struct $UInt64 (%10 : $Builtin.Int64)
|
|
%12 = value_to_bridge_object %11 : $UInt64
|
|
%33 = unchecked_trivial_bit_cast %12 : $Builtin.BridgeObject to $UInt64
|
|
%34 = integer_literal $Builtin.Int64, 4611686018427387904
|
|
%35 = struct_extract %33 : $UInt64, #UInt64._value
|
|
%36 = builtin "and_Int64"(%35 : $Builtin.Int64, %34 : $Builtin.Int64) : $Builtin.Int64
|
|
return %36 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_optimize_stringObject_bit_operations2 :
|
|
// CHECK: builtin "stringObjectOr_Int64"
|
|
// CHECK: builtin "and_Int64"
|
|
// CHECK: } // end sil function 'dont_optimize_stringObject_bit_operations2'
|
|
sil [ossa] @dont_optimize_stringObject_bit_operations2 : $@convention(thin) () -> Builtin.Int64 {
|
|
bb0:
|
|
%2 = string_literal utf8 "thequickbrownfoxjumpsoverthelazydogusingasmanycharacteraspossible123456789"
|
|
%5 = builtin "ptrtoint_Word"(%2 : $Builtin.RawPointer) : $Builtin.Word
|
|
%6 = builtin "zextOrBitCast_Word_Int64"(%5 : $Builtin.Word) : $Builtin.Int64
|
|
%9 = integer_literal $Builtin.Int64, 13835058055282163712
|
|
%10 = builtin "stringObjectOr_Int64"(%6 : $Builtin.Int64, %9 : $Builtin.Int64) : $Builtin.Int64
|
|
%11 = struct $UInt64 (%10 : $Builtin.Int64)
|
|
%12 = value_to_bridge_object %11 : $UInt64
|
|
%33 = unchecked_trivial_bit_cast %12 : $Builtin.BridgeObject to $UInt64
|
|
%34 = integer_literal $Builtin.Int64, 1152921504606846975
|
|
%35 = struct_extract %33 : $UInt64, #UInt64._value
|
|
%36 = builtin "and_Int64"(%35 : $Builtin.Int64, %34 : $Builtin.Int64) : $Builtin.Int64
|
|
return %36 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @conversion_to_and_from_bridge_object
|
|
// CHECK: bb0(%0 : $Builtin.Int64):
|
|
// CHECK-NEXT: return %0
|
|
// CHECK: } // end sil function 'conversion_to_and_from_bridge_object'
|
|
sil [ossa] @conversion_to_and_from_bridge_object : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64) {
|
|
bb0(%0 : $Builtin.Int64):
|
|
%1 = struct $UInt64 (%0 : $Builtin.Int64)
|
|
%2 = value_to_bridge_object %1 : $UInt64
|
|
%3 = bridge_object_to_word %2 : $Builtin.BridgeObject to $Builtin.Word
|
|
%4 = builtin "zextOrBitCast_Word_Int64"(%3 : $Builtin.Word) : $Builtin.Int64
|
|
return %4 : $Builtin.Int64
|
|
}
|
|
|
|
// <rdar://46746188> crash in swift_getObjCClassFromObject
|
|
// class TestDocument: NSPersistentDocument {
|
|
// override init() {
|
|
// super.init()
|
|
// }
|
|
// convenience init(type: String) throws {
|
|
// self.init()
|
|
// }
|
|
// }
|
|
// After inlining the __allocating_init, we have two uses of the value_metatype.
|
|
// The second use goes through a thick_to_objc_metatype. When SILCombine replaces
|
|
// thick_to_objc_metatype with value_metatype, it cannot extend the liverange
|
|
// of value_metatype's operand.
|
|
@objc class TestObjCInit {
|
|
init()
|
|
|
|
convenience init(type: String) throws
|
|
}
|
|
// CHECK-LABEL: sil hidden [thunk] [ossa] @objc_init_partial_dealloc : $@convention(objc_method) (@owned TestObjCInit) -> @owned Optional<TestObjCInit> {
|
|
// CHECK: bb0(%0 : @owned $TestObjCInit):
|
|
// CHECK: [[VMT2:%.*]] = value_metatype $@objc_metatype TestObjCInit.Type, %0 : $TestObjCInit
|
|
// CHECK: [[VMT:%.*]] = value_metatype $@thick TestObjCInit.Type, %0 : $TestObjCInit
|
|
// CHECK: dealloc_partial_ref %0 : $TestObjCInit, [[VMT]] : $@thick TestObjCInit.Type
|
|
// CHECK-NOT: value_metatype
|
|
// CHECK: [[O:%.*]] = alloc_ref_dynamic [objc] [[VMT2]] : $@objc_metatype TestObjCInit.Type, $TestObjCInit
|
|
// CHECK: [[M:%.*]] = objc_method [[O]] : $TestObjCInit, #TestObjCInit.init!initializer.foreign : (TestObjCInit.Type) -> () -> TestObjCInit, $@convention(objc_method) (@owned TestObjCInit) -> @owned TestObjCInit
|
|
// CHECK: apply [[M]]([[O]]) : $@convention(objc_method) (@owned TestObjCInit) -> @owned TestObjCInit
|
|
// CHECK-LABEL: } // end sil function 'objc_init_partial_dealloc'
|
|
sil hidden [thunk] [ossa] @objc_init_partial_dealloc : $@convention(objc_method) (@owned TestObjCInit) -> @owned Optional<TestObjCInit> {
|
|
bb0(%2 : @owned $TestObjCInit):
|
|
%8 = value_metatype $@thick TestObjCInit.Type, %2 : $TestObjCInit
|
|
dealloc_partial_ref %2 : $TestObjCInit, %8 : $@thick TestObjCInit.Type
|
|
%11 = thick_to_objc_metatype %8 : $@thick TestObjCInit.Type to $@objc_metatype TestObjCInit.Type
|
|
%12 = alloc_ref_dynamic [objc] %11 : $@objc_metatype TestObjCInit.Type, $TestObjCInit
|
|
%13 = objc_method %12 : $TestObjCInit, #TestObjCInit.init!initializer.foreign : (TestObjCInit.Type) -> () -> TestObjCInit, $@convention(objc_method) (@owned TestObjCInit) -> @owned TestObjCInit
|
|
%14 = apply %13(%12) : $@convention(objc_method) (@owned TestObjCInit) -> @owned TestObjCInit
|
|
%19 = enum $Optional<TestObjCInit>, #Optional.some!enumelt, %14 : $TestObjCInit
|
|
return %19 : $Optional<TestObjCInit>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @isConcrete_true : $@convention(thin) (@thin MyInt.Type) -> Builtin.Int1 {
|
|
// CHECK: bb0(%0 : $@thin MyInt.Type):
|
|
// CHECK: [[RESULT:%.*]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK: return [[RESULT]]
|
|
// CHECK: } // end sil function 'isConcrete_true'
|
|
sil [ossa] @isConcrete_true : $@convention(thin) (@thin MyInt.Type) -> Builtin.Int1 {
|
|
bb0(%0 : $@thin MyInt.Type):
|
|
%1 = builtin "isConcrete"(%0 : $@thin MyInt.Type) : $Builtin.Int1
|
|
return %1 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
|
|
// CHECK: bb0(%0 : $@thin T.Type):
|
|
// CHECK: [[RESULT:%.*]] = builtin "isConcrete"<T>(%0 : $@thin T.Type) : $Builtin.Int1
|
|
// CHECK: return [[RESULT]]
|
|
// CHECK: } // end sil function 'isConcrete_false'
|
|
sil [ossa] @isConcrete_false : $@convention(thin) <T> (@thin T.Type) -> Builtin.Int1 {
|
|
bb0(%0 : $@thin T.Type):
|
|
// FIXME: Explicit specialization is required here when it shouldn't be
|
|
%1 = builtin "isConcrete"<T>(%0 : $@thin T.Type) : $Builtin.Int1
|
|
return %1 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_function_substitution : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out ()) -> ()
|
|
// CHECK: bb0(%0 : @guaranteed $@callee_guaranteed () -> @out ()):
|
|
// CHECK-NOT: convert_function
|
|
// CHECK: } // end sil function 'convert_function_substitution'
|
|
sil [ossa] @convert_function_substitution : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out ()) -> () {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> @out ()):
|
|
%1 = convert_function %0 : $@callee_guaranteed () -> @out () to $@callee_guaranteed @substituted <A> () -> @out A for <()>
|
|
%2 = alloc_stack $()
|
|
apply %1(%2) : $@callee_guaranteed @substituted <A> () -> @out A for <()>
|
|
dealloc_stack %2 : $*()
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @convert_function_substitution_pa :
|
|
// CHECK-NOT: convert_function
|
|
// CHECK: } // end sil function 'convert_function_substitution_pa'
|
|
sil [ossa] @convert_function_substitution_pa : $@convention(thin) (@guaranteed @callee_guaranteed (@in Int, @in Int) -> @out (), @in Int, @in Int) -> @owned @callee_guaranteed () -> @out () {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed (@in Int, @in Int) -> @out (), %1 : $*Int, %1b : $*Int):
|
|
%2 = convert_function %0 : $@callee_guaranteed (@in Int, @in Int) -> @out () to $@callee_guaranteed @substituted <A, B, C> (@in A, @in B) -> @out C for <Int, Int, ()>
|
|
%2a = copy_value %2 : $@callee_guaranteed @substituted <A, B, C> (@in A, @in B) -> @out C for <Int, Int, ()>
|
|
%3 = partial_apply [callee_guaranteed] %2a(%1) : $@callee_guaranteed @substituted <A, B, C> (@in A, @in B) -> @out C for <Int, Int, ()>
|
|
%4 = partial_apply [callee_guaranteed] %3(%1b) : $@callee_guaranteed @substituted <A, B, C> (@in A) -> @out C for <Int, Int, ()>
|
|
%5 = convert_function %4 : $@callee_guaranteed @substituted <A, B, C> () -> @out C for <Int, Int, ()> to $@callee_guaranteed () -> @out ()
|
|
return %5 : $@callee_guaranteed () -> @out ()
|
|
|
|
}
|
|
|
|
// Test builtin "is_same_metatype" folding.
|
|
protocol SomeP {}
|
|
|
|
public enum SpecialEnum : SomeP {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testFoldBuiltinIsSameMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool {
|
|
// CHECK-NEXT: bb0(%0 : $@thick SpecialEnum.Type):
|
|
// CHECK-NEXT: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK-NEXT: struct $Bool ([[TRUE]] : $Builtin.Int1)
|
|
// CHECK-NEXT: return
|
|
// CHECK-LABEL: } // end sil function 'testFoldBuiltinIsSameMetatype'
|
|
sil [ossa] @testFoldBuiltinIsSameMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool {
|
|
bb0(%0 : $@thick SpecialEnum.Type):
|
|
%1 = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type
|
|
%3 = builtin "is_same_metatype"(%1 : $@thick Any.Type, %1 : $@thick Any.Type) : $Builtin.Int1
|
|
%4 = struct $Bool (%3 : $Builtin.Int1)
|
|
return %4 : $Bool
|
|
}
|
|
|
|
struct IntTuple {
|
|
@_hasStorage var t: (Int64, Int64)
|
|
}
|
|
|
|
sil_global [let] @initialized_let_global : $Int64 = {
|
|
%0 = integer_literal $Builtin.Int64, 27
|
|
%initval = struct $Int64 (%0 : $Builtin.Int64)
|
|
}
|
|
|
|
sil_global @initialized_var_global : $Int64 = {
|
|
%0 = integer_literal $Builtin.Int64, 27
|
|
%initval = struct $Int64 (%0 : $Builtin.Int64)
|
|
}
|
|
|
|
sil_global [let] @initialized_tuple_global : $IntTuple = {
|
|
%0 = integer_literal $Builtin.Int64, 27
|
|
%1 = integer_literal $Builtin.Int64, 28
|
|
%2 = struct $Int64 (%0 : $Builtin.Int64)
|
|
%3 = struct $Int64 (%1 : $Builtin.Int64)
|
|
%4 = tuple (%2 : $Int64, %3 : $Int64)
|
|
%initval = struct $IntTuple (%4 : $(Int64, Int64))
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_from_global_let
|
|
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int64, 27
|
|
// CHECK: [[R:%.*]] = struct $Int64 ([[I]] : $Builtin.Int64)
|
|
// CHECK: return [[R]]
|
|
// CHECK: } // end sil function 'load_from_global_let'
|
|
sil [ossa] @load_from_global_let : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @initialized_let_global : $*Int64
|
|
%1 = load [trivial] %0 : $*Int64
|
|
return %1 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_from_global_with_projections
|
|
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int64, 28
|
|
// CHECK: return [[I]]
|
|
// CHECK: } // end sil function 'load_from_global_with_projections'
|
|
sil [ossa] @load_from_global_with_projections : $@convention(thin) () -> Builtin.Int64 {
|
|
bb0:
|
|
%0 = global_addr @initialized_tuple_global : $*IntTuple
|
|
%1 = struct_element_addr %0 : $*IntTuple, #IntTuple.t
|
|
%2 = tuple_element_addr %1 : $*(Int64, Int64), 1
|
|
%3 = struct_element_addr %2 : $*Int64, #Int64._value
|
|
%4 = load [trivial] %3 : $*Builtin.Int64
|
|
return %4 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_from_global_without_projections
|
|
// CHECK-DAG: [[I1:%.*]] = integer_literal $Builtin.Int64, 27
|
|
// CHECK-DAG: [[I2:%.*]] = integer_literal $Builtin.Int64, 28
|
|
// CHECK-DAG: [[S1:%.*]] = struct $Int64 ([[I1]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[S2:%.*]] = struct $Int64 ([[I2]] : $Builtin.Int64)
|
|
// CHECK-DAG: [[T:%.*]] = tuple ([[S1]] : $Int64, [[S2]] : $Int64)
|
|
// CHECK-DAG: [[IT:%.*]] = struct $IntTuple ([[T]] : $(Int64, Int64))
|
|
// CHECK: return [[IT]]
|
|
// CHECK: } // end sil function 'load_from_global_without_projections'
|
|
sil [ossa] @load_from_global_without_projections : $@convention(thin) () -> IntTuple {
|
|
bb0:
|
|
%0 = global_addr @initialized_tuple_global : $*IntTuple
|
|
%1 = load [trivial] %0 : $*IntTuple
|
|
return %1 : $IntTuple
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @load_from_global_var
|
|
// CHECK: global_addr
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'load_from_global_var'
|
|
sil [ossa] @load_from_global_var : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @initialized_var_global : $*Int64
|
|
%1 = load [trivial] %0 : $*Int64
|
|
return %1 : $Int64
|
|
}
|
|
|
|
sil private [ossa] @somePrivateFunction : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int64, 27
|
|
%1 = struct $Int64 (%0 : $Builtin.Int64)
|
|
return %1 : $Int64
|
|
}
|
|
|
|
sil_global [let] @pointerToSomePrivateFunction : $@callee_guaranteed () -> Int64 = {
|
|
%0 = function_ref @somePrivateFunction: $@convention(thin) () -> Int64
|
|
%initval = thin_to_thick_function %0 : $@convention(thin) () -> Int64 to $@callee_guaranteed () -> Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [serialized] [ossa] @dontInlinePrivateFunctionRefIntoSerializedFunction
|
|
// CHECK: [[GA:%[0-9]+]] = global_addr
|
|
// CHECK: [[L:%[0-9]+]] = load [copy] [[GA]]
|
|
// CHECK: return [[L]]
|
|
// CHECK: } // end sil function 'dontInlinePrivateFunctionRefIntoSerializedFunction'
|
|
sil [serialized] [ossa] @dontInlinePrivateFunctionRefIntoSerializedFunction : $@convention(thin) () -> @owned @callee_guaranteed () -> Int64 {
|
|
bb0:
|
|
%0 = global_addr @pointerToSomePrivateFunction : $*@callee_guaranteed () -> Int64
|
|
%1 = load [copy] %0 : $*@callee_guaranteed () -> Int64
|
|
return %1 : $@callee_guaranteed () -> Int64
|
|
}
|
|
|
|
|
|
// Check for disabled optimization of unchecked_bitwise_cast to unchecked_ref_cast in ossa
|
|
// This test can be optimized when ossa is supported in the SILCombine for unchecked_bitwise_cast
|
|
// CHECK-LABEL: sil [ossa] @refcast :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: copy_value
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: return
|
|
// CHECK-LABEL: } // end sil function 'refcast'
|
|
sil [ossa] @refcast : $@convention(thin) (@owned Klass) -> @owned Optional<Klass> {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = unchecked_bitwise_cast %0 : $Klass to $Optional<Klass>
|
|
%2 = copy_value %1 : $Optional<Klass>
|
|
destroy_value %0 : $Klass
|
|
return %2 : $Optional<Klass>
|
|
}
|
|
|
|
// We do not sink if the forwarding inst is in the same block as the consuming use.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @sink_forwarding_owned_uses_no_sink_same_block : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK: } // end sil function 'sink_forwarding_owned_uses_no_sink_same_block'
|
|
sil [ossa] @sink_forwarding_owned_uses_no_sink_same_block : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0a : @owned $Klass, %0b : @guaranteed $Klass):
|
|
%1 = unchecked_ref_cast %0a : $Klass to $Builtin.NativeObject
|
|
%2 = function_ref @use_klass_guaranteed : $@convention(thin) (@guaranteed Klass) -> ()
|
|
apply %2(%0b) : $@convention(thin) (@guaranteed Klass) -> ()
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
// In this case, since we have different blocks, we sink.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: br bb1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'sink_forwarding_owned_uses_sink_diff_block_single_use'
|
|
sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0a : @owned $Klass, %0b : @guaranteed $Klass):
|
|
%1 = unchecked_ref_cast %0a : $Klass to $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use_noopt : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: br bb1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'sink_forwarding_owned_uses_sink_diff_block_single_use_noopt'
|
|
sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use_noopt : $@convention(thin) (@owned Klass, @guaranteed Klass) -> @owned Builtin.NativeObject {
|
|
bb0(%0a : @owned $Klass, %0b : @guaranteed $Klass):
|
|
%1 = unchecked_ref_cast %0a : $Klass to $Builtin.NativeObject
|
|
%f = function_ref @use_nativeobject_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
br bb1
|
|
|
|
bb1:
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
// In this case, since we have different blocks, we sink.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use_destroy : $@convention(thin) (@owned Klass, @guaranteed Klass) -> () {
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: cond_br undef, bb1, bb2
|
|
//
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: br bb3
|
|
//
|
|
// CHECK: bb2:
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: br bb3
|
|
//
|
|
// CHECK: bb3:
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-NEXT: return
|
|
// CHECK: } // end sil function 'sink_forwarding_owned_uses_sink_diff_block_single_use_destroy'
|
|
sil [ossa] @sink_forwarding_owned_uses_sink_diff_block_single_use_destroy : $@convention(thin) (@owned Klass, @guaranteed Klass) -> () {
|
|
bb0(%0a : @owned $Klass, %0b : @guaranteed $Klass):
|
|
%1 = unchecked_ref_cast %0a : $Klass to $Builtin.NativeObject
|
|
cond_br undef, bb1a, bb1b
|
|
|
|
bb1a:
|
|
%f = function_ref @use_nativeobject_owned : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
apply %f(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
br bb1
|
|
|
|
bb1b:
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
br bb1
|
|
|
|
bb1:
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that we eliminate copy_value on values with None ownership and
|
|
// preserve ownership.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @copy_value_of_none : $@convention(thin) () -> () {
|
|
// CHECK-NOT: copy_value
|
|
// CHECK: } // end sil function 'copy_value_of_none'
|
|
sil [ossa] @copy_value_of_none : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = enum $FakeOptional<Builtin.NativeObject>, #FakeOptional.none!enumelt
|
|
%1 = copy_value %0 : $FakeOptional<Builtin.NativeObject>
|
|
br bb1(%1 : $FakeOptional<Builtin.NativeObject>)
|
|
|
|
bb1(%2 : @owned $FakeOptional<Builtin.NativeObject>):
|
|
%f = function_ref @use_fakeoptional_nativeobject_guaranteed : $@convention(thin) (@guaranteed FakeOptional<Builtin.NativeObject>) -> ()
|
|
apply %f(%2) : $@convention(thin) (@guaranteed FakeOptional<Builtin.NativeObject>) -> ()
|
|
destroy_value %2 : $FakeOptional<Builtin.NativeObject>
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_useafterfree_debuginstdelete :
|
|
// CHECK-NOT: upcast
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-LABEL: } // end sil function 'test_useafterfree_debuginstdelete'
|
|
sil [ossa] @test_useafterfree_debuginstdelete : $@convention(method) (@owned E) -> () {
|
|
bb0(%0 : @owned $E):
|
|
%1 = upcast %0 : $E to $B
|
|
debug_value %1 : $B
|
|
%2 = unchecked_ref_cast %1 : $B to $Builtin.NativeObject
|
|
debug_value %2 : $Builtin.NativeObject
|
|
destroy_value %2 : $Builtin.NativeObject
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
// Make sure we optimize this and do not put the end_borrow on the
|
|
// unchecked_enum_data and thus have the verifier hit us.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_load_borrow : $@convention(thin) (@inout Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject {
|
|
// CHECK-NOT: unchecked_take_enum_data_addr
|
|
// CHECK: unchecked_enum_data
|
|
// CHECK-NOT: unchecked_take_enum_data_addr
|
|
// CHECK: } // end sil function 'unchecked_take_enum_data_addr_load_borrow'
|
|
sil [ossa] @unchecked_take_enum_data_addr_load_borrow : $@convention(thin) (@inout Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : $*Optional<Builtin.NativeObject>):
|
|
%1 = unchecked_take_enum_data_addr %0 : $*Optional<Builtin.NativeObject>, #Optional.some!enumelt
|
|
%2 = load_borrow %1 : $*Builtin.NativeObject
|
|
%3 = copy_value %2 : $Builtin.NativeObject
|
|
end_borrow %2 : $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_load_borrow_no_reborrow : $@convention(thin) (@inout Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject {
|
|
// CHECK: unchecked_take_enum_data_addr
|
|
// CHECK: } // end sil function 'unchecked_take_enum_data_addr_load_borrow_no_reborrow'
|
|
sil [ossa] @unchecked_take_enum_data_addr_load_borrow_no_reborrow : $@convention(thin) (@inout Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : $*Optional<Builtin.NativeObject>):
|
|
%1 = unchecked_take_enum_data_addr %0 : $*Optional<Builtin.NativeObject>, #Optional.some!enumelt
|
|
%2 = load_borrow %1 : $*Builtin.NativeObject
|
|
br bb1(%2 : $Builtin.NativeObject)
|
|
|
|
bb1(%2a : @guaranteed $Builtin.NativeObject):
|
|
%3 = copy_value %2a : $Builtin.NativeObject
|
|
end_borrow %2a : $Builtin.NativeObject
|
|
return %3 : $Builtin.NativeObject
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cowbuffer_reading_immutable_1 : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: ref_element_addr [immutable]
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: } // end sil function 'cowbuffer_reading_immutable_1'
|
|
sil [ossa] @cowbuffer_reading_immutable_1 : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
bb0(%0 : @guaranteed $_ContiguousArrayBuffer<Element>):
|
|
%3 = struct_extract %0 : $_ContiguousArrayBuffer<Element>, #_ContiguousArrayBuffer._storage
|
|
%4 = copy_value %3 : $__ContiguousArrayStorageBase
|
|
%5 = builtin "COWBufferForReading"<__ContiguousArrayStorageBase>(%4 : $__ContiguousArrayStorageBase) : $__ContiguousArrayStorageBase
|
|
%6 = begin_borrow %5 : $__ContiguousArrayStorageBase
|
|
%7 = ref_element_addr %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
// I am doing this to avoid exposing 32 vs 64 bit. It is evil and just for
|
|
// testing.
|
|
%7a = unchecked_addr_cast %7 : $*_ArrayBody to $*Builtin.Int32
|
|
%8 = load [trivial] %7a : $*Builtin.Int32
|
|
debug_value %8 : $Builtin.Int32, let, name "self", argno 1
|
|
%14 = struct $MyInt (%8 : $Builtin.Int32)
|
|
end_borrow %6 : $__ContiguousArrayStorageBase
|
|
destroy_value %5 : $__ContiguousArrayStorageBase
|
|
return %14 : $MyInt
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cowbuffer_reading_no_crash_derived_borrow : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: ref_element_addr [immutable]
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: ref_tail_addr [immutable]
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: } // end sil function 'cowbuffer_reading_no_crash_derived_borrow'
|
|
sil [ossa] @cowbuffer_reading_no_crash_derived_borrow : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
bb0(%0 : @guaranteed $_ContiguousArrayBuffer<Element>):
|
|
%3 = struct_extract %0 : $_ContiguousArrayBuffer<Element>, #_ContiguousArrayBuffer._storage
|
|
%4 = copy_value %3 : $__ContiguousArrayStorageBase
|
|
%5 = builtin "COWBufferForReading"<__ContiguousArrayStorageBase>(%4 : $__ContiguousArrayStorageBase) : $__ContiguousArrayStorageBase
|
|
%6 = begin_borrow %5 : $__ContiguousArrayStorageBase
|
|
%6b = begin_borrow %6 : $__ContiguousArrayStorageBase
|
|
%7 = ref_element_addr %6b : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
// This is evil! I am doing it just for this test to avoid platform 32 vs 64
|
|
// integer size issues.
|
|
%7a = unchecked_addr_cast %7 : $*_ArrayBody to $*Builtin.Int32
|
|
%8 = load [trivial] %7a : $*Builtin.Int32
|
|
debug_value %8 : $Builtin.Int32, let, name "self", argno 1
|
|
end_borrow %6b : $__ContiguousArrayStorageBase
|
|
%6c = begin_borrow %6 : $__ContiguousArrayStorageBase
|
|
%7b = ref_tail_addr %6c : $__ContiguousArrayStorageBase, $Element
|
|
// This is evil! I am doing it just for this test to avoid platform 32 vs 64
|
|
// integer size issues.
|
|
%7c = unchecked_addr_cast %7b : $*Element to $*Builtin.Int32
|
|
%12b = load [trivial] %7c : $*Builtin.Int32
|
|
end_borrow %6c : $__ContiguousArrayStorageBase
|
|
end_borrow %6 : $__ContiguousArrayStorageBase
|
|
destroy_value %5 : $__ContiguousArrayStorageBase
|
|
%12c = builtin "and_Int32"(%8 : $Builtin.Int32, %12b : $Builtin.Int32) : $Builtin.Int32
|
|
%14 = struct $MyInt (%12c : $Builtin.Int32)
|
|
return %14 : $MyInt
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cowbuffer_reading_no_lookthrough_reborrow : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
//
|
|
// After updating with borrowed-from instructions, the ref_element_addr's can all be promoted without looking through
|
|
// reborrows because they are reachable from the borrowed-from.
|
|
//
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: ref_element_addr [immutable]
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: ref_tail_addr [immutable] %
|
|
// CHECK-NOT: builtin "COWBufferForReading"
|
|
// CHECK: } // end sil function 'cowbuffer_reading_no_lookthrough_reborrow'
|
|
sil [ossa] @cowbuffer_reading_no_lookthrough_reborrow : $@convention(method) <Element> (@guaranteed _ContiguousArrayBuffer<Element>) -> MyInt {
|
|
bb0(%0 : @guaranteed $_ContiguousArrayBuffer<Element>):
|
|
%3 = struct_extract %0 : $_ContiguousArrayBuffer<Element>, #_ContiguousArrayBuffer._storage
|
|
%4 = copy_value %3 : $__ContiguousArrayStorageBase
|
|
%5 = builtin "COWBufferForReading"<__ContiguousArrayStorageBase>(%4 : $__ContiguousArrayStorageBase) : $__ContiguousArrayStorageBase
|
|
%6 = begin_borrow %5 : $__ContiguousArrayStorageBase
|
|
%6bb = begin_borrow %6 : $__ContiguousArrayStorageBase
|
|
br bb1(%6bb : $__ContiguousArrayStorageBase)
|
|
|
|
bb1(%6b : @guaranteed $__ContiguousArrayStorageBase):
|
|
%7 = ref_element_addr %6b : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
|
|
// This is evil! I am doing it just for this test to avoid platform 32 vs 32
|
|
// integer size issues.
|
|
%7a = unchecked_addr_cast %7 : $*_ArrayBody to $*Builtin.Int32
|
|
%8 = load [trivial] %7a : $*Builtin.Int32
|
|
debug_value %8 : $Builtin.Int32, let, name "self", argno 1
|
|
end_borrow %6b : $__ContiguousArrayStorageBase
|
|
%6cb = begin_borrow %6 : $__ContiguousArrayStorageBase
|
|
br bb2(%6cb : $__ContiguousArrayStorageBase)
|
|
|
|
bb2(%6c : @guaranteed $__ContiguousArrayStorageBase):
|
|
%7b = ref_tail_addr %6c : $__ContiguousArrayStorageBase, $Element
|
|
// This is evil! I am doing it just for this test to avoid platform 32 vs 32
|
|
// integer size issues.
|
|
%7c = unchecked_addr_cast %7b : $*Element to $*Builtin.Int32
|
|
%12b = load [trivial] %7c : $*Builtin.Int32
|
|
end_borrow %6c : $__ContiguousArrayStorageBase
|
|
end_borrow %6 : $__ContiguousArrayStorageBase
|
|
destroy_value %5 : $__ContiguousArrayStorageBase
|
|
%12c = builtin "and_Int32"(%8 : $Builtin.Int32, %12b : $Builtin.Int32) : $Builtin.Int32
|
|
%13 = builtin "assumeNonNegative_Int32"(%12c : $Builtin.Int32) : $Builtin.Int32
|
|
%14 = struct $MyInt (%13 : $Builtin.Int32)
|
|
return %14 : $MyInt
|
|
}
|
|
|
|
// Make sure that we hoist the unchecked_trivial_bit_cast up the def-use chain
|
|
// to before copy1 and make its operand copy1.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @unchecked_trivial_bit_cast_hoist_up_def_use_chain : $@convention(thin) (@guaranteed AnyObject) -> UInt {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: [[RESULT:%.*]] = unchecked_trivial_bit_cast [[ARG]]
|
|
// CHECK: cond_br undef, [[BB_UNREACHABLE:bb[0-9]*]], [[BB_RESULT:bb[0-9]*]]
|
|
//
|
|
// CHECK: [[BB_UNREACHABLE]]:
|
|
// CHECK-NEXT: unreachable
|
|
//
|
|
// CHECK: [[BB_RESULT]]:
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
// CHECK: } // end sil function 'unchecked_trivial_bit_cast_hoist_up_def_use_chain'
|
|
sil [ossa] @unchecked_trivial_bit_cast_hoist_up_def_use_chain : $@convention(thin) (@guaranteed AnyObject) -> UInt {
|
|
bb0(%0 : @guaranteed $AnyObject):
|
|
%copy1 = copy_value %0 : $AnyObject
|
|
%cast = unchecked_ref_cast %copy1 : $AnyObject to $Builtin.NativeObject
|
|
cond_br undef, bb3, bb4
|
|
|
|
bb3:
|
|
unreachable
|
|
|
|
bb4:
|
|
%2 = unchecked_trivial_bit_cast %cast : $Builtin.NativeObject to $UInt
|
|
destroy_value %cast : $Builtin.NativeObject
|
|
return %2 : $UInt
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_promotion_trivialpayload_nontrivial_enum : $@convention(thin) (@inout NonTrivialLoadableEnum) -> Builtin.Int32 {
|
|
// CHECK-NOT: unchecked_take_enum_data_addr
|
|
// CHECK: unchecked_enum_data
|
|
// CHECK-NOT: unchecked_take_enum_data_addr
|
|
// CHECK: } // end sil function 'unchecked_take_enum_data_addr_promotion_trivialpayload_nontrivial_enum'
|
|
sil [ossa] @unchecked_take_enum_data_addr_promotion_trivialpayload_nontrivial_enum : $@convention(thin) (@inout NonTrivialLoadableEnum) -> Builtin.Int32 {
|
|
bb0(%0 : $*NonTrivialLoadableEnum):
|
|
switch_enum_addr %0 : $*NonTrivialLoadableEnum, case #NonTrivialLoadableEnum.trivialPayload!enumelt: bb1, default bb2
|
|
|
|
bb1:
|
|
%2 = unchecked_take_enum_data_addr %0 : $*NonTrivialLoadableEnum, #NonTrivialLoadableEnum.trivialPayload!enumelt
|
|
%3 = load [trivial] %2 : $*Builtin.Int32
|
|
return %3 : $Builtin.Int32
|
|
|
|
bb2:
|
|
unreachable
|
|
}
|
|
|
|
// Make sure that when we promote the unchecked_take_enum_data_uses in bb1, bb2,
|
|
// we keep the loads in bb1, bb2 instead of hoisting them to the
|
|
// unchecked_take_enum_data_addr that we are optimizing.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @unchecked_take_enum_data_addr_promotion_host_load : $@convention(thin) (@inout FakeOptional<KlassNativeObjEither>) -> @owned KlassNativeObjEither {
|
|
// CHECK: bb0([[ARG:%.*]] : $*
|
|
// CHECK: [[LOADED_ARG:%.*]] = load_borrow [[ARG]]
|
|
// CHECK: [[FOR_SWITCH:%.*]] = unchecked_enum_data [[LOADED_ARG]]
|
|
// CHECK: switch_enum [[FOR_SWITCH]] :
|
|
//
|
|
// CHECK: bb1(
|
|
// CHECK-NEXT: end_borrow [[LOADED_ARG]]
|
|
// CHECK-NEXT: [[LOADED_ARG_2:%.*]] = load [copy] [[ARG]]
|
|
// CHECK-NEXT: [[LOADED_ARG_2_EXT:%.*]] = unchecked_enum_data [[LOADED_ARG_2]]
|
|
// CHECK-NEXT: br bb3([[LOADED_ARG_2_EXT]] :
|
|
//
|
|
// CHECK: bb2(
|
|
// CHECK-NEXT: end_borrow [[LOADED_ARG]]
|
|
// CHECK-NEXT: [[LOADED_ARG_3:%.*]] = load [take] [[ARG]]
|
|
// CHECK-NEXT: [[LOADED_ARG_3_EXT:%.*]] = unchecked_enum_data [[LOADED_ARG_3]]
|
|
// CHECK-NEXT: [[NONE:%.*]] = enum $FakeOptional<
|
|
// CHECK-NEXT: store [[NONE]] to [init] [[ARG]]
|
|
// CHECK-NEXT: br bb3([[LOADED_ARG_3_EXT]] :
|
|
//
|
|
// CHECK: bb3([[RESULT:%.*]] : @owned
|
|
// CHECK-NEXT: return [[RESULT]]
|
|
// CHECK: } // end sil function 'unchecked_take_enum_data_addr_promotion_host_load'
|
|
sil [ossa] @unchecked_take_enum_data_addr_promotion_host_load : $@convention(thin) (@inout FakeOptional<KlassNativeObjEither>) -> @owned KlassNativeObjEither {
|
|
bb0(%0 : $*FakeOptional<KlassNativeObjEither>):
|
|
%1 = unchecked_take_enum_data_addr %0 : $*FakeOptional<KlassNativeObjEither>, #FakeOptional.some!enumelt
|
|
switch_enum_addr %1 : $*KlassNativeObjEither, case #KlassNativeObjEither.lhs!enumelt: bb1, case #KlassNativeObjEither.rhs!enumelt: bb2
|
|
|
|
bb1:
|
|
%2 = load [copy] %1 : $*KlassNativeObjEither
|
|
br bb3(%2 : $KlassNativeObjEither)
|
|
|
|
bb2:
|
|
%3 = load [take] %1 : $*KlassNativeObjEither
|
|
%nil = enum $FakeOptional<KlassNativeObjEither>, #FakeOptional.none!enumelt
|
|
store %nil to [init] %0 : $*FakeOptional<KlassNativeObjEither>
|
|
br bb3(%3 : $KlassNativeObjEither)
|
|
|
|
bb3(%4 : @owned $KlassNativeObjEither):
|
|
return %4 : $KlassNativeObjEither
|
|
}
|
|
|
|
|
|
sil @convert_raw_pointer_to_nativeobject : $@convention(thin) (Builtin.RawPointer) -> @owned Builtin.NativeObject
|
|
|
|
// To eliminate the convert_function below we need to convert the try_apply to
|
|
// an apply. We do not delete edges like this in SILCombine with ownership and
|
|
// are trying to reduce it without ownership. So make sure we don't optimize
|
|
// this. This should be done in a different pass that handles CFG issues.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @do_not_eliminate_error_adding_convert_function_used_by_try_apply : $@convention(thin) (Builtin.RawPointer) -> @owned Builtin.NativeObject {
|
|
// CHECK: convert_function
|
|
// CHECK: try_apply
|
|
// CHECK: } // end sil function 'do_not_eliminate_error_adding_convert_function_used_by_try_apply'
|
|
sil [ossa] @do_not_eliminate_error_adding_convert_function_used_by_try_apply : $@convention(thin) (Builtin.RawPointer) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%f = function_ref @convert_raw_pointer_to_nativeobject : $@convention(thin) (Builtin.RawPointer) -> @owned Builtin.NativeObject
|
|
%t = thin_to_thick_function %f : $@convention(thin) (Builtin.RawPointer) -> @owned Builtin.NativeObject to $@noescape @callee_guaranteed (Builtin.RawPointer) -> @owned Builtin.NativeObject
|
|
%c = convert_function %t : $@noescape @callee_guaranteed (Builtin.RawPointer) -> @owned Builtin.NativeObject to $@noescape @callee_guaranteed (Builtin.RawPointer) -> (@owned Builtin.NativeObject, @error Error)
|
|
try_apply %c(%0) : $@noescape @callee_guaranteed (Builtin.RawPointer) -> (@owned Builtin.NativeObject, @error Error), normal bb1, error bb2
|
|
|
|
bb1(%result : @owned $Builtin.NativeObject):
|
|
return %result : $Builtin.NativeObject
|
|
|
|
bb2(%error : @owned $Error):
|
|
unreachable
|
|
}
|
|
|
|
sil [ossa] @takeKlass : $@convention(thin) (@owned Optional<Klass>) -> ()
|
|
|
|
// CHECK_FORWARDING_OWNERSHIP_KIND-LABEL: sil shared [ossa] @$s8refcast24main5KlassC_Tg5 :
|
|
// CHECK_FORWARDING_OWNERSHIP_KIND: unchecked_ref_cast %1 : $Klass to $Optional<Klass>, forwarding: @unowned
|
|
// CHECK_FORWARDING_OWNERSHIP_KIND-LABEL: } // end sil function '$s8refcast24main5KlassC_Tg5'
|
|
sil [ossa] @refcast2 : $@convention(thin) <T> (@in T, @owned Klass) -> () {
|
|
bb0(%0 : $*T, %1 : @owned $Klass):
|
|
destroy_addr %0 : $*T
|
|
%2 = unchecked_bitwise_cast %1 : $Klass to $Optional<Klass>
|
|
%3 = copy_value %2 : $Optional<Klass>
|
|
destroy_value %1 : $Klass
|
|
%func = function_ref @takeKlass : $@convention(thin) (@owned Optional<Klass>) -> ()
|
|
apply %func(%3) : $@convention(thin) (@owned Optional<Klass>) -> ()
|
|
%res = tuple ()
|
|
return %res : $()
|
|
}
|
|
|
|
sil [ossa] @caller : $@convention(thin) (@in Klass, @owned Klass) -> () {
|
|
bb0(%0 : $*Klass, %1 : @owned $Klass):
|
|
%f = function_ref @refcast2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned Klass) -> ()
|
|
%res = apply %f<Klass>(%0, %1) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned Klass) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
class KlassWithTailAllocatedElems {
|
|
var x : Builtin.NativeObject
|
|
init()
|
|
}
|
|
|
|
// Test conversion from address_to_pointer->pointer_to_address to
|
|
// unchecked_addr_cast when the base is an interior pointer (ref_tail_addr).
|
|
//
|
|
// RAW attempts to clone the ref_tail_addr and its access path to the
|
|
// load, which includes
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @unchecked_addr_cast_formation_handling_interior_pointer_rebase_of_cast : $@convention(thin) () -> Builtin.Word {
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK: [[TAIL_ADDR:%.*]] = ref_tail_addr
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK: [[CAST_RESULT:%.*]] = unchecked_addr_cast [[TAIL_ADDR]]
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK: load [trivial] [[CAST_RESULT]]
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK: } // end sil function 'unchecked_addr_cast_formation_handling_interior_pointer_rebase_of_cast'
|
|
sil [ossa] @unchecked_addr_cast_formation_handling_interior_pointer_rebase_of_cast : $@convention(thin) () -> Builtin.Word {
|
|
bb0:
|
|
%7 = integer_literal $Builtin.Word, 1
|
|
%8 = alloc_ref [tail_elems $(Builtin.NativeObject) * %7 : $Builtin.Word] $KlassWithTailAllocatedElems
|
|
%borrow = begin_borrow %8 : $KlassWithTailAllocatedElems
|
|
%addr = ref_tail_addr %borrow : $KlassWithTailAllocatedElems, $Builtin.NativeObject
|
|
%1 = address_to_pointer %addr : $*Builtin.NativeObject to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Builtin.Word
|
|
%3 = load [trivial] %2 : $*Builtin.Word
|
|
end_borrow %borrow : $KlassWithTailAllocatedElems
|
|
destroy_value %8 : $KlassWithTailAllocatedElems
|
|
return %3 : $Builtin.Word
|
|
}
|
|
|
|
struct Function {
|
|
var impl: (MyInt) -> Double
|
|
}
|
|
|
|
sil @negateFunction : $@convention(thin) (MyInt, @guaranteed Function) -> Double
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_borrow_struct_extract : $@convention(thin) (@guaranteed Function) -> Double {
|
|
// CHECK-NOT: struct_extract
|
|
// CHECK-NOT: struct $Function
|
|
// CHECK: } // end sil function 'test_borrow_struct_extract'
|
|
sil [ossa] @test_borrow_struct_extract : $@convention(thin) (@guaranteed Function) -> Double {
|
|
bb0(%0 : @guaranteed $Function):
|
|
%3 = function_ref @negateFunction : $@convention(thin) (MyInt, @guaranteed Function) -> Double
|
|
%4 = copy_value %0 : $Function
|
|
%5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (MyInt, @guaranteed Function) -> Double
|
|
%6 = struct $Function (%5 : $@callee_guaranteed (MyInt) -> Double)
|
|
%7 = integer_literal $Builtin.Int32, 0
|
|
%8 = struct $MyInt (%7 : $Builtin.Int32)
|
|
%9 = begin_borrow %6 : $Function
|
|
%12 = struct_extract %9 : $Function, #Function.impl
|
|
%13 = apply %12(%8) : $@callee_guaranteed (MyInt) -> Double
|
|
end_borrow %9 : $Function
|
|
destroy_value %6 : $Function
|
|
return %13 : $Double
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_borrow_tuple_extract : $@convention(thin) (@guaranteed Function) -> Double {
|
|
// CHECK-NOT: tuple_extract
|
|
// CHECK: } // end sil function 'test_borrow_tuple_extract'
|
|
sil [ossa] @test_borrow_tuple_extract : $@convention(thin) (@guaranteed Function) -> Double {
|
|
bb0(%0 : @guaranteed $Function):
|
|
%3 = function_ref @negateFunction : $@convention(thin) (MyInt, @guaranteed Function) -> Double
|
|
%4 = copy_value %0 : $Function
|
|
%5 = partial_apply [callee_guaranteed] %3(%4) : $@convention(thin) (MyInt, @guaranteed Function) -> Double
|
|
%7 = integer_literal $Builtin.Int32, 0
|
|
%8 = struct $MyInt (%7 : $Builtin.Int32)
|
|
%6 = tuple (%5 : $@callee_guaranteed (MyInt) -> Double, %7 : $Builtin.Int32)
|
|
%9 = begin_borrow %6 : $(@callee_guaranteed (MyInt) -> Double, Builtin.Int32)
|
|
%12 = tuple_extract %9 : $(@callee_guaranteed (MyInt) -> Double, Builtin.Int32), 0
|
|
%13 = apply %12(%8) : $@callee_guaranteed (MyInt) -> Double
|
|
end_borrow %9 : $(@callee_guaranteed (MyInt) -> Double, Builtin.Int32)
|
|
destroy_value %6 : $(@callee_guaranteed (MyInt) -> Double, Builtin.Int32)
|
|
return %13 : $Double
|
|
}
|
|
|
|
sil [reabstraction_thunk] @thunk : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_apply_opt1 :
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: } // end sil function 'test_partial_apply_apply_opt1'
|
|
sil [ossa] @test_partial_apply_apply_opt1 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () {
|
|
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass):
|
|
%c1 = copy_value %0 : $Klass
|
|
%c2 = copy_value %1 : $Klass
|
|
%f1 = function_ref @thunk : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
|
|
%p1 = partial_apply [callee_guaranteed] %f1(%c1, %c2) : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
|
|
%r = apply %p1() : $@callee_guaranteed () -> ()
|
|
destroy_value %p1 : $@callee_guaranteed () -> ()
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_partial_apply_apply_opt2 :
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: } // end sil function 'test_partial_apply_apply_opt2'
|
|
sil [ossa] @test_partial_apply_apply_opt2 : $@convention(thin) (@owned Klass, @owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass, %1 : @owned $Klass):
|
|
%c1 = copy_value %0 : $Klass
|
|
%c2 = copy_value %1 : $Klass
|
|
%f1 = function_ref @thunk : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
|
|
%p1 = partial_apply [callee_guaranteed] %f1(%c1, %c2) : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> ()
|
|
%r = apply %p1() : $@callee_guaranteed () -> ()
|
|
destroy_value %p1 : $@callee_guaranteed () -> ()
|
|
destroy_value %0 : $Klass
|
|
destroy_value %1 : $Klass
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testTransitiveAddressUse : $@convention(thin) (Builtin.Int64, @owned MyContiguousArrayStorage) -> () {
|
|
// CHECK: [[VAL:%.*]] = struct $MyContiguousArrayBody (%0 : $Builtin.Int64)
|
|
// CHECK: store [[VAL]] to [trivial] %{{.*}} : $*MyContiguousArrayBody
|
|
// CHECK-LABEL: } // end sil function 'testTransitiveAddressUse'
|
|
sil [ossa] @testTransitiveAddressUse : $@convention(thin) (Builtin.Int64, @owned MyContiguousArrayStorage) -> () {
|
|
bb0(%0 : $Builtin.Int64, %1 : @owned $MyContiguousArrayStorage):
|
|
%2 = struct $MyContiguousArray (%1 : $MyContiguousArrayStorage)
|
|
%3 = begin_borrow %2 : $MyContiguousArray
|
|
%4 = struct_extract %3 : $MyContiguousArray, #MyContiguousArray.storage
|
|
%5 = ref_element_addr %4 : $MyContiguousArrayStorage, #MyContiguousArrayStorage.body
|
|
%6 = struct_element_addr %5 : $*MyContiguousArrayBody, #MyContiguousArrayBody.count
|
|
store %0 to [trivial] %6 : $*Builtin.Int64
|
|
end_borrow %3 : $MyContiguousArray
|
|
destroy_value %2 : $MyContiguousArray
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
// Test Ownership RAUW when the replacement address requires an additional unchecked_addr_cast.
|
|
//
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @testAddrCast : $@convention(thin) (UnsafePointer<AnyObject>) -> @owned Optional<AnyObject> {
|
|
// CHECK: bb0(%0 : $UnsafePointer<AnyObject>):
|
|
// CHECK: [[A1:%.*]] = index_addr %{{.*}} : $*AnyObject, undef : $Builtin.Word
|
|
// CHECK: [[A2:%.*]] = unchecked_addr_cast [[A1]] : $*AnyObject to $*Optional<AnyObject>
|
|
// CHECK: load [copy] [[A2]] : $*Optional<AnyObject>
|
|
// CHECK-LABEL: } // end sil function 'testAddrCast'
|
|
sil [ossa] @testAddrCast : $@convention(thin) (UnsafePointer<AnyObject>) -> @owned Optional<AnyObject> {
|
|
bb0(%0 : $UnsafePointer<AnyObject>):
|
|
%1 = struct_extract %0 : $UnsafePointer<AnyObject>, #UnsafePointer._rawValue
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%3 = index_addr %2 : $*AnyObject, undef : $Builtin.Word
|
|
%4 = address_to_pointer %3 : $*AnyObject to $Builtin.RawPointer
|
|
%5 = pointer_to_address %4 : $Builtin.RawPointer to [strict] $*Optional<AnyObject>
|
|
%6 = load [copy] %5 : $*Optional<AnyObject>
|
|
return %6 : $Optional<AnyObject>
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_pointer_to_address : $@convention(thin) (@owned Klass, Builtin.Word) -> @owned AnyObject {
|
|
// CHECK: [[P:%.*]] = address_to_pointer
|
|
// CHECK: end_borrow
|
|
// CHECK: [[A:%.*]] = pointer_to_address [[P]]
|
|
// CHECK: [[I:%.*]] = index_addr [[A]]
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK: load [copy] [[I]]
|
|
// CHECK-LABEL: } // end sil function 'test_pointer_to_address'
|
|
sil [ossa] @test_pointer_to_address : $@convention(thin) (@owned Klass, Builtin.Word) -> @owned AnyObject {
|
|
bb0(%0 : @owned $Klass, %1 : $Builtin.Word):
|
|
%2 = begin_borrow %0 : $Klass
|
|
%3 = ref_tail_addr %2 : $Klass, $AnyObject
|
|
%4 = index_addr %3 : $*AnyObject, %1 : $Builtin.Word
|
|
%5 = address_to_pointer %4 : $*AnyObject to $Builtin.RawPointer
|
|
end_borrow %2 : $Klass
|
|
%7 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%8 = index_addr %7 : $*AnyObject, %1 : $Builtin.Word
|
|
%9 = address_to_pointer %8 : $*AnyObject to $Builtin.RawPointer
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%11 = load [copy] %10 : $*AnyObject
|
|
fix_lifetime %0 : $Klass
|
|
destroy_value %0 : $Klass
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// CHECK_COPYPROP-LABEL: sil [ossa] @test_pointer_to_address_copyprop : {{.*}} {
|
|
// CHECK_COPYPROP: [[P:%.*]] = address_to_pointer
|
|
// CHECK_COPYPROP: end_borrow
|
|
// CHECK_COPYPROP: [[A:%.*]] = pointer_to_address [[P]]
|
|
// CHECK_COPYPROP: [[I:%.*]] = index_addr [[A]]
|
|
// CHECK_COPYPROP-NOT: address_to_pointer
|
|
// CHECK_COPYPROP-NOT: pointer_to_address
|
|
// CHECK_COPYPROP: load [copy] [[I]]
|
|
// CHECK_COPYPROP-LABEL: } // end sil function 'test_pointer_to_address_copyprop'
|
|
sil [ossa] @test_pointer_to_address_copyprop : $@convention(thin) (Builtin.Word) -> @owned AnyObject {
|
|
bb0(%1 : $Builtin.Word):
|
|
%f = function_ref @get_owned_klass : $@convention(thin) () -> (@owned Klass)
|
|
%0 = apply %f() : $@convention(thin) () -> (@owned Klass)
|
|
%2 = begin_borrow %0 : $Klass
|
|
%3 = ref_tail_addr %2 : $Klass, $AnyObject
|
|
%4 = index_addr %3 : $*AnyObject, %1 : $Builtin.Word
|
|
%5 = address_to_pointer %4 : $*AnyObject to $Builtin.RawPointer
|
|
end_borrow %2 : $Klass
|
|
%7 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%8 = index_addr %7 : $*AnyObject, %1 : $Builtin.Word
|
|
%9 = address_to_pointer %8 : $*AnyObject to $Builtin.RawPointer
|
|
%10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*AnyObject
|
|
%11 = load [copy] %10 : $*AnyObject
|
|
fix_lifetime %0 : $Klass
|
|
destroy_value %0 : $Klass
|
|
return %11 : $AnyObject
|
|
}
|
|
|
|
// Test that DCE during SILCombine does not remove traps.
|
|
// Tests isReadOnlyConstantEvaluable().
|
|
sil hidden [noinline] [_semantics "programtermination_point"] @trapWrapper : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = builtin "int_trap"() : $Never
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testTrap : $@convention(thin) () -> () {
|
|
// CHECK: apply
|
|
// CHECK-LABEL: } // end sil function 'testTrap'
|
|
sil [ossa] @testTrap : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @trapWrapper : $@convention(thin) () -> ()
|
|
%1 = apply %0() : $@convention(thin) () -> ()
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_moveonly_singlestoreopt :
|
|
// CHECK: struct_element_addr
|
|
// CHECK-LABEL: } // end sil function 'test_moveonly_singlestoreopt'
|
|
sil [ossa] @test_moveonly_singlestoreopt : $@convention(method) (@inout MoveOnlyStruct) -> () {
|
|
bb0(%0 : $*MoveOnlyStruct):
|
|
%1 = struct_element_addr %0 : $*MoveOnlyStruct, #MoveOnlyStruct.value
|
|
%2 = function_ref @get_myint : $@convention(thin) () -> MyInt
|
|
%3 = apply %2() : $@convention(thin) () -> MyInt
|
|
store %3 to [trivial] %1 : $*MyInt
|
|
%16 = tuple ()
|
|
return %16 : $()
|
|
}
|
|
|
|
sil @originalClosure : $@convention(thin) (@owned Klass) -> ()
|
|
sil @useNoEscapeClosure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_mark_dependence_ossa_silcombine1 :
|
|
// [[ENUM:%.*]] = enum
|
|
// [[MDI:%.*]] = mark_dependence {{.*}} on [[ENUM]]
|
|
// CHECK-LABEL: } // end sil function 'test_mark_dependence_ossa_silcombine1'
|
|
sil [ossa] @test_mark_dependence_ossa_silcombine1 : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = function_ref @originalClosure : $@convention(thin) (@owned Klass) -> ()
|
|
%2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (@owned Klass) -> ()
|
|
%3 = convert_escape_to_noescape %2 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
%4 = enum $Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt, %2 : $@callee_guaranteed () -> ()
|
|
%5 = begin_borrow %4 : $Optional<@callee_guaranteed () -> ()>
|
|
%6 = mark_dependence %3 : $@noescape @callee_guaranteed () -> () on %5 : $Optional<@callee_guaranteed () -> ()>
|
|
%7 = function_ref @useNoEscapeClosure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%8 = apply %7(%6) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %6 : $@noescape @callee_guaranteed () -> ()
|
|
end_borrow %5 : $Optional<@callee_guaranteed () -> ()>
|
|
destroy_value %4 : $Optional<@callee_guaranteed () -> ()>
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_mark_dependence_ossa_silcombine2 :
|
|
// [[ENUM:%.*]] = enum
|
|
// [[MDI:%.*]] = mark_dependence {{.*}} on [[ENUM]]
|
|
// CHECK-LABEL: } // end sil function 'test_mark_dependence_ossa_silcombine2'
|
|
sil [ossa] @test_mark_dependence_ossa_silcombine2 : $@convention(thin) (@owned Klass) -> () {
|
|
bb0(%0 : @owned $Klass):
|
|
%1 = function_ref @originalClosure : $@convention(thin) (@owned Klass) -> ()
|
|
%2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (@owned Klass) -> ()
|
|
%3 = convert_escape_to_noescape %2 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
%4 = enum $Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt, %2 : $@callee_guaranteed () -> ()
|
|
%5 = begin_borrow %4 : $Optional<@callee_guaranteed () -> ()>
|
|
%6 = mark_dependence %3 : $@noescape @callee_guaranteed () -> () on %5 : $Optional<@callee_guaranteed () -> ()>
|
|
%7 = function_ref @useNoEscapeClosure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%8 = apply %7(%6) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %6 : $@noescape @callee_guaranteed () -> ()
|
|
br bb1(%4 : $Optional<@callee_guaranteed () -> ()>, %5 : $Optional<@callee_guaranteed () -> ()>)
|
|
|
|
bb1(%10 : @owned $Optional<@callee_guaranteed () -> ()>, %11 : @guaranteed $Optional<@callee_guaranteed () -> ()>):
|
|
end_borrow %11 : $Optional<@callee_guaranteed () -> ()>
|
|
destroy_value %10 : $Optional<@callee_guaranteed () -> ()>
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @not_dead_mark_dependence_addr :
|
|
// CHECK: mark_dependence_addr %0 : $*B on %1
|
|
// CHECK-LABEL: } // end sil function 'not_dead_mark_dependence_addr'
|
|
sil [ossa] @not_dead_mark_dependence_addr : $@convention(thin) (@inout B, @in_guaranteed B) -> @owned B {
|
|
bb0(%0 : $*B, %1 : $*B):
|
|
mark_dependence_addr %0 on %1
|
|
%3 = load [copy] %0
|
|
return %3
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_borrow_of_thin_function :
|
|
// CHECK: [[F:%.*]] = function_ref @unknown
|
|
// CHECK: [[T:%.*]] = thin_to_thick_function [[F]]
|
|
// CHECK-NOT: begin_borrow
|
|
// CHECK: apply %{{[0-9]+}}([[T]])
|
|
// CHECK: apply %0()
|
|
// CHECK-LABEL: } // end sil function 'remove_borrow_of_thin_function'
|
|
sil [ossa] @remove_borrow_of_thin_function : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @unknown : $@convention(thin) () -> ()
|
|
%1 = thin_to_thick_function %0 to $@callee_guaranteed () -> ()
|
|
%2 = begin_borrow %1
|
|
%3 = function_ref @use_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
%4 = apply %3(%2) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
%5 = apply %2(): $@callee_guaranteed () -> ()
|
|
end_borrow %2
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @remove_borrow_of_owned :
|
|
// CHECK-NOT: begin_borrow
|
|
// CHECK: apply %1(%0)
|
|
// CHECK-NEXT: destroy_value %0
|
|
// CHECK: } // end sil function 'remove_borrow_of_owned'
|
|
sil [ossa] @remove_borrow_of_owned : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
%1 = begin_borrow %0 : $C
|
|
%2 = function_ref @useC : $@convention(thin) (@guaranteed C) -> ()
|
|
%3 = apply %2(%1) : $@convention(thin) (@guaranteed C) -> ()
|
|
end_borrow %1 : $C
|
|
destroy_value %0: $C
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
private protocol Pr: AnyObject {
|
|
}
|
|
|
|
private class Cr: Pr {
|
|
}
|
|
|
|
sil @use_pr : $@convention(thin) <τ_0_0 where τ_0_0 : Pr> (@in τ_0_0) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @existential_consumed_too_early1 :
|
|
// CHECK: apply {{.*}}<@opened
|
|
// CHECK: } // end sil function 'existential_consumed_too_early1'
|
|
sil [ossa] @existential_consumed_too_early1 : $@convention(thin) (@owned Pr) -> () {
|
|
bb0(%0 : @owned $Pr):
|
|
%2 = open_existential_ref %0 to $@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self
|
|
%3 = alloc_stack $@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self
|
|
store %2 to [init] %3
|
|
%5 = function_ref @use_pr : $@convention(thin) <τ_0_0 where τ_0_0 : Pr> (@in τ_0_0) -> ()
|
|
%6 = apply %5<@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self>(%3) : $@convention(thin) <τ_0_0 where τ_0_0 : Pr> (@in τ_0_0) -> ()
|
|
dealloc_stack %3
|
|
%8 = tuple ()
|
|
return %8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @existential_consumed_too_early2 :
|
|
// CHECK: apply {{.*}}<@opened
|
|
// CHECK: } // end sil function 'existential_consumed_too_early2'
|
|
sil [ossa] @existential_consumed_too_early2 : $@convention(thin) (@owned Cr) -> () {
|
|
bb0(%0 : @owned $Cr):
|
|
%1 = init_existential_ref %0 : $Cr : $Cr, $any Pr
|
|
%2 = open_existential_ref %1 to $@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self
|
|
%3 = alloc_stack $@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self
|
|
store %2 to [init] %3
|
|
%5 = function_ref @use_pr : $@convention(thin) <τ_0_0 where τ_0_0 : Pr> (@in τ_0_0) -> ()
|
|
%6 = apply %5<@opened("5554ACAA-0F2B-11F0-86AA-0EA13E3AABB1", any Pr) Self>(%3) : $@convention(thin) <τ_0_0 where τ_0_0 : Pr> (@in τ_0_0) -> ()
|
|
dealloc_stack %3
|
|
%8 = tuple ()
|
|
return %8
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @init_existential_with_debug_value :
|
|
// CHECK: return %0
|
|
// CHECK: } // end sil function 'init_existential_with_debug_value'
|
|
sil [ossa] @init_existential_with_debug_value : $@convention(thin) (@owned Cr) -> @owned Cr {
|
|
bb0(%1 : @owned $Cr):
|
|
%5 = init_existential_ref %1 : $Cr : $Cr, $any Pr
|
|
debug_value %5, let, name "interactor", argno 2
|
|
%48 = open_existential_ref %5 to $@opened("F9D78C78-0FCD-11F0-9F91-0EA13E3AABB1", any Pr) Self
|
|
%49 = unchecked_ref_cast %48 to $Cr
|
|
return %49
|
|
}
|
|
|
|
enum NT {
|
|
case inline(InlineArray<1, Int>)
|
|
case klass(Klass)
|
|
}
|
|
|
|
sil @get_inlinearray : $@convention(thin) () -> @out InlineArray<1, Int>
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @testTrivialPayloadInNonTrivialEnum :
|
|
// CHECK-NOT: inject_enum_addr
|
|
// CHECK-LABEL: } // end sil function 'testTrivialPayloadInNonTrivialEnum'
|
|
sil shared [ossa] @testTrivialPayloadInNonTrivialEnum : $@convention(thin) () -> @owned NT {
|
|
bb0:
|
|
%0 = alloc_stack $NT
|
|
%1 = init_enum_data_addr %0, #NT.inline!enumelt
|
|
%3 = function_ref @get_inlinearray : $@convention(thin) () -> @out InlineArray<1, Int>
|
|
%4 = apply %3(%1) : $@convention(thin) () -> @out InlineArray<1, Int>
|
|
inject_enum_addr %0, #NT.inline!enumelt
|
|
%6 = load [take] %0
|
|
dealloc_stack %0
|
|
return %6
|
|
}
|
|
|