mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
CSE relies on OSSA RAUW for lifetime extension when replacing a redundant instruction. OSSA RAUW however does not handle lifetime extension for escaped base values. Values escape from ownership via pointer escape, bitwise escape, forwarding unowned operations and have none or unowned ownership. For all such values do not look through ownership instructions while determining equality. It is possible to CSE such values with equivalent operands, because the operand use guarantees lifetime of the base operand.
1338 lines
59 KiB
Plaintext
1338 lines
59 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -cse | %FileCheck %s
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class B {
|
|
func foo()
|
|
}
|
|
class E : B { }
|
|
|
|
class C {}
|
|
class D : C { }
|
|
|
|
class Ping {
|
|
func ping() -> Ping
|
|
}
|
|
|
|
//////////////////////
|
|
// Simple DCE Tests //
|
|
//////////////////////
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_inst_elimination_one_bb :
|
|
// CHECK-NOT: integer_literal $Builtin.Int64, 24
|
|
// CHECK-LABEL: } // end sil function 'dead_inst_elimination_one_bb'
|
|
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
|
|
// CHECK-LABEL: } // end sil function 'dead_inst_elimination_diamond'
|
|
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-LABEL: } // end sil function 'dead_inst_elimination_loop'
|
|
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, bb2, bb3
|
|
|
|
bb2:
|
|
br bb1
|
|
|
|
bb3:
|
|
%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
|
|
// CHECK-LABEL: } // end sil function 'dead_inst_elimination_ignore_unreachable'
|
|
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: unchecked_ref_cast
|
|
// CHECK-NOT: unchecked_bitwise_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 %1 : $<τ_0_0> { var τ_0_0 } <B>
|
|
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
|
|
%10 = apply %9() : $@convention(thin) () -> Never
|
|
%6 = unchecked_bitwise_cast %5 : $Builtin.NativeObject to $B
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
%11 = tuple()
|
|
return %11 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @removeTriviallyDeadCrossBasicBlocks :
|
|
// CHECK: cond_br
|
|
// CHECK-NOT: unchecked_ref_cast
|
|
// CHECK-LABEL: } // end sil function 'removeTriviallyDeadCrossBasicBlocks'
|
|
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, bb2
|
|
bb1:
|
|
br bb3
|
|
bb2:
|
|
br bb3
|
|
bb3:
|
|
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
|
|
%10 = apply %9() : $@convention(thin) () -> Never
|
|
%21 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B
|
|
destroy_value %21 : $B
|
|
%32 = tuple ()
|
|
return %32 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dead_use_of_alloc_stack :
|
|
// CHECK: bb
|
|
// CHECK: alloc_stack
|
|
// CHECK: dealloc_stack
|
|
// CHECK-LABEL: } // end sil function 'dead_use_of_alloc_stack'
|
|
sil [ossa] @dead_use_of_alloc_stack : $@convention(thin) () -> () {
|
|
bb0:
|
|
%1 = alloc_stack $((), (), ())
|
|
%2 = tuple_element_addr %1 : $*((), (), ()), 0
|
|
dealloc_stack %1 : $*((), (), ())
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @tuple_extract :
|
|
// CHECK: bb
|
|
// CHECK-LABEL: } // end sil function 'tuple_extract'
|
|
sil [ossa] @tuple_extract : $@convention(thin) (Int64) -> Int64 {
|
|
bb0(%0 : $Int64):
|
|
%1 = tuple (%0 : $Int64, %0 : $Int64)
|
|
return %0 : $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
|
|
// CHECK-LABEL: } // end sil function 'do_not_fold_integer_literal'
|
|
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
|
|
// CHECK-LABEL: } // end sil function 'fold_enum'
|
|
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
|
|
// CHECK-LABEL: } // end sil function 'do_not_fold_enum'
|
|
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
|
|
}
|
|
|
|
///////////////
|
|
// CSE Tests //
|
|
///////////////
|
|
|
|
// Test simple instruction value numbering and usage of an available value in a single bb.
|
|
//
|
|
// Specifically we make sure that we only replace Int8 literals with
|
|
// Int8 literals with the same value. Anything else is outside of scope for cse.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test0 :
|
|
// CHECK: [[TARGET:%[0-9]+]] = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: [[DECOY1:%[0-9]+]] = integer_literal $Builtin.Int16, 8
|
|
// CHECK-NEXT: [[DECOY2:%[0-9]+]] = integer_literal $Builtin.Int8, 1
|
|
// CHECK-NEXT: tuple ([[TARGET]] : $Builtin.Int8, [[TARGET]] : $Builtin.Int8, [[DECOY1]] : $Builtin.Int16, [[DECOY2]] : $Builtin.Int8)
|
|
// CHECK-LABEL: } // end sil function 'test0'
|
|
sil [ossa] @test0 : $@convention(thin) () -> (Builtin.Int8, Builtin.Int8, Builtin.Int16,
|
|
Builtin.Int8) {
|
|
%0 = integer_literal $Builtin.Int8, 8
|
|
%1 = integer_literal $Builtin.Int8, 8
|
|
%2 = integer_literal $Builtin.Int16, 8
|
|
%3 = integer_literal $Builtin.Int8, 1
|
|
%4 = tuple(%0 : $Builtin.Int8, %1 : $Builtin.Int8, %2 : $Builtin.Int16, %3 : $Builtin.Int8)
|
|
return %4 : $(Builtin.Int8, Builtin.Int8, Builtin.Int16, Builtin.Int8)
|
|
}
|
|
|
|
// Make sure that we can replace cse values in different basic blocks
|
|
// assuming nothing has changed.
|
|
|
|
// CHECK-LABEL: sil [ossa] @test1 :
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: [[TARGET:%[0-9]+]] = integer_literal $Builtin.Int8, 8
|
|
// CHECK-NEXT: cond_br undef, bb1, bb2
|
|
// CHECK: bb1
|
|
// CHECK-NEXT: br bb3([[TARGET]] : $Builtin.Int8)
|
|
// CHECK: bb2
|
|
// CHECK-NEXT: [[DECOY:%[0-9]+]] = integer_literal $Builtin.Int8, 16
|
|
// CHECK-NEXT: br bb3([[DECOY]] : $Builtin.Int8)
|
|
// CHECK: bb3([[PHI:%[0-9]+]] : $Builtin.Int8):
|
|
// CHECK-NEXT: tuple ([[TARGET]] : $Builtin.Int8, [[PHI]] : $Builtin.Int8, [[TARGET]] : $Builtin.Int8)
|
|
// CHECK-LABEL: } // end sil function 'test1'
|
|
sil [ossa] @test1 : $@convention(thin) () -> (Builtin.Int8, Builtin.Int8, Builtin.Int8) {
|
|
bb0:
|
|
%0 = integer_literal $Builtin.Int8, 8
|
|
%1 = integer_literal $Builtin.Int8, 8
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%2 = integer_literal $Builtin.Int8, 8
|
|
br bb3(%2 : $Builtin.Int8)
|
|
|
|
bb2:
|
|
%3 = integer_literal $Builtin.Int8, 16
|
|
br bb3(%3 : $Builtin.Int8)
|
|
|
|
bb3(%4 : $Builtin.Int8):
|
|
%5 = tuple(%0 : $Builtin.Int8, %4 : $Builtin.Int8, %1 : $Builtin.Int8)
|
|
return %5 : $(Builtin.Int8, Builtin.Int8, Builtin.Int8)
|
|
}
|
|
|
|
sil [ossa] @evil : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @functionrefinst :
|
|
// CHECK: bb0
|
|
// CHECK: function_ref @evil : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
// CHECK-NOT: function_ref @evil : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
// CHECK-LABEL: } // end sil function 'functionrefinst'
|
|
sil [ossa] @functionrefinst : $@convention(thin) (@inout Builtin.Int8) -> () {
|
|
bb0(%0 : $*Builtin.Int8):
|
|
%1 = function_ref @evil : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
apply %1(%0) : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
%2 = function_ref @evil : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
apply %2(%0) : $@convention(thin) (@inout Builtin.Int8) -> ()
|
|
%3 = tuple()
|
|
return %3 : $()
|
|
}
|
|
|
|
sil_global @global_target : $Builtin.Int64
|
|
|
|
// CHECK-LABEL: sil [ossa] @globaladdr_inst :
|
|
// CHECK-NOT: global_addr
|
|
// CHECK: global_addr @global_target
|
|
// CHECK-NOT: global_addr
|
|
// CHECK-LABEL: } // end sil function 'globaladdr_inst'
|
|
sil [ossa] @globaladdr_inst : $@convention(thin) () -> (Builtin.Int64) {
|
|
%0 = global_addr @global_target : $*Builtin.Int64
|
|
%1 = global_addr @global_target : $*Builtin.Int64
|
|
%2 = load [trivial] %0 : $*Builtin.Int64
|
|
%3 = load [trivial] %1 : $*Builtin.Int64
|
|
%5 = integer_literal $Builtin.Int1, 0
|
|
%6 = builtin "sadd_with_overflow_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64, %5 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%7 = tuple_extract %6 : $(Builtin.Int64, Builtin.Int1), 0
|
|
return %7 : $(Builtin.Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @floatliteral :
|
|
// CHECK: float_literal $Builtin.FPIEEE32, 0x3F800000
|
|
// CHECK-NOT: float_literal $Builtin.FPIEEE32, 0x3F800000
|
|
// CHECK-LABEL: } // end sil function 'floatliteral'
|
|
sil [ossa] @floatliteral : $@convention(thin) () -> (Builtin.FPIEEE32) {
|
|
%0 = float_literal $Builtin.FPIEEE32, 0x3F800000
|
|
%1 = float_literal $Builtin.FPIEEE32, 0x3F800000
|
|
%4 = builtin "fadd_FPIEEE32"(%0 : $Builtin.FPIEEE32, %1 : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
|
|
return %4 : $(Builtin.FPIEEE32)
|
|
}
|
|
|
|
sil [ossa] @string_use : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type, Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> ()
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @stringliteral :
|
|
// CHECK: [[TARGET:%[0-9]+]] = string_literal utf8 "First"
|
|
// CHECK: [[LEN:%[0-9]+]] = integer_literal $Builtin.Word, 5
|
|
// CHECK: [[ASCII:%[0-9]+]] = integer_literal $Builtin.Int1, -1
|
|
// CHECK-NOT: string_literal "First"
|
|
// CHECK: apply {{%[0-9]+}}([[TARGET]], [[LEN]], [[ASCII]], {{%[0-9]+}}, [[TARGET]], [[LEN]], [[ASCII]], {{%[0-9]+}})
|
|
// CHECK-LABEL: } // end sil function 'stringliteral'
|
|
sil [ossa] @stringliteral : $@convention(thin) () -> () {
|
|
%0 = string_literal utf8 "First"
|
|
%1 = string_literal utf8 "First"
|
|
%2 = metatype $@thin String.Type
|
|
%l1 = integer_literal $Builtin.Word, 5
|
|
%l2 = integer_literal $Builtin.Word, 5
|
|
%a1 = integer_literal $Builtin.Int1, 1
|
|
%a2 = integer_literal $Builtin.Int1, 1
|
|
%3 = function_ref @string_use : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type, Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> ()
|
|
apply %3 (%0, %l1, %a1, %2, %1, %l2, %a2, %2): $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type, Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> ()
|
|
%4 = tuple()
|
|
return %4 : $()
|
|
}
|
|
|
|
struct Interval {
|
|
var start: Builtin.Int32
|
|
var end: Builtin.Int32
|
|
}
|
|
struct FakeInterval {
|
|
var start: Builtin.Int32
|
|
var end: Builtin.Int32
|
|
}
|
|
|
|
sil @print_interval : $@convention(thin) (Interval) -> ()
|
|
sil @print_fake_interval : $@convention(thin) (FakeInterval) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @structliteral :
|
|
// CHECK: [[TARGET:%[0-9]+]] = struct $Interval ([[IN1:%[0-9]+]] : $Builtin.Int32, [[IN2:%[0-9]+]] : $Builtin.Int32)
|
|
// CHECK-NOT: struct $Interval ([[IN1]] : $Builtin.Int32, [[IN2]] : $Builtin.Int32)
|
|
// CHECK: [[DECOY:%[0-9]+]] = struct $FakeInterval ([[IN1]] : $Builtin.Int32, [[IN2]] : $Builtin.Int32)
|
|
// CHECK: [[PRINT_INTERVAL_FUN:%[0-9]+]] = function_ref @print_interval
|
|
// CHECK: apply [[PRINT_INTERVAL_FUN]]([[TARGET]])
|
|
// CHECK: apply [[PRINT_INTERVAL_FUN]]([[TARGET]])
|
|
// CHECK: [[PRINT_FAKEINTERVAL_FUN:%[0-9]+]] = function_ref @print_fake_interval
|
|
// CHECK: apply [[PRINT_FAKEINTERVAL_FUN]]([[DECOY]])
|
|
// CHECK-LABEL: } // end sil function 'structliteral'
|
|
sil [ossa] @structliteral : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
%2 = struct $Interval (%0 : $Builtin.Int32, %1 : $Builtin.Int32)
|
|
%3 = struct $Interval (%0 : $Builtin.Int32, %1 : $Builtin.Int32)
|
|
%4 = struct $FakeInterval (%0 : $Builtin.Int32, %1 : $Builtin.Int32)
|
|
%5 = function_ref @print_interval : $@convention(thin) (Interval) -> ()
|
|
apply %5 (%2) : $@convention(thin) (Interval) -> ()
|
|
apply %5 (%3) : $@convention(thin) (Interval) -> ()
|
|
%6 = function_ref @print_fake_interval : $@convention(thin) (FakeInterval) -> ()
|
|
apply %6 (%4) : $@convention(thin) (FakeInterval) -> ()
|
|
%9 = tuple()
|
|
return %9 : $()
|
|
}
|
|
|
|
sil [ossa] @sadd_with_address : $@convention(thin) (@inout Builtin.Int32, @inout Builtin.Int32) -> (Builtin.Int32)
|
|
|
|
// CHECK-LABEL: sil [ossa] @structelementaddr_test :
|
|
// CHECK: struct_element_addr {{%[0-9]+}} : $*Interval, #Interval.start
|
|
// CHECK-NOT: struct_element_addr {{%[0-9]+}} : $*Interval, #Interval.start
|
|
// CHECK-LABEL: } // end sil function 'structelementaddr_test'
|
|
sil [ossa] @structelementaddr_test : $@convention(thin) (@inout Interval) -> (Builtin.Int32) {
|
|
bb0(%0 : $*Interval):
|
|
%1 = struct_element_addr %0 : $*Interval, #Interval.start
|
|
%2 = struct_element_addr %0 : $*Interval, #Interval.start
|
|
%3 = function_ref @sadd_with_address : $@convention(thin) (@inout Builtin.Int32, @inout Builtin.Int32) -> (Builtin.Int32)
|
|
%4 = apply %3(%1, %2) : $@convention(thin) (@inout Builtin.Int32, @inout Builtin.Int32) -> (Builtin.Int32)
|
|
return %4 : $(Builtin.Int32)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @project_box_test :
|
|
// CHECK: project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>
|
|
// CHECK-NOT: project_box
|
|
// CHECK-LABEL: } // end sil function 'project_box_test'
|
|
sil [ossa] @project_box_test : $(@owned <τ_0_0> { var τ_0_0 } <Builtin.Int32>) -> Builtin.Int32 {
|
|
bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } <Builtin.Int32>):
|
|
%1 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, 0
|
|
%2 = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, 0
|
|
%3 = function_ref @sadd_with_address : $@convention(thin) (@inout Builtin.Int32, @inout Builtin.Int32) -> (Builtin.Int32)
|
|
%4 = apply %3(%1, %2) : $@convention(thin) (@inout Builtin.Int32, @inout Builtin.Int32) -> (Builtin.Int32)
|
|
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>
|
|
return %4 : $(Builtin.Int32)
|
|
}
|
|
|
|
sil [ossa] @tuple_function : $@convention(thin) ((Builtin.Int32, Builtin.Int32), (Builtin.Int32, Builtin.Int32)) -> (Builtin.Int32)
|
|
|
|
// CHECK-LABEL: sil [ossa] @tuple_test :
|
|
// CHECK: tuple ({{%[0-9]+}} : $Builtin.Int32, {{%[0-9]+}} : $Builtin.Int32)
|
|
// CHECK-NOT: tuple ({{%[0-9]+}} : $Builtin.Int32, {{%[0-9]+}} : $Builtin.Int32)
|
|
// CHECK-LABEL: } // end sil function 'tuple_test'
|
|
sil [ossa] @tuple_test : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> (Builtin.Int32) {
|
|
bb0(%0 : $Builtin.Int32, %1 : $Builtin.Int32):
|
|
%2 = tuple(%0 : $Builtin.Int32, %1 : $Builtin.Int32)
|
|
%3 = tuple(%0 : $Builtin.Int32, %1 : $Builtin.Int32)
|
|
%4 = function_ref @tuple_function : $@convention(thin) ((Builtin.Int32, Builtin.Int32), (Builtin.Int32, Builtin.Int32)) -> (Builtin.Int32)
|
|
%5 = apply %4(%2, %3) : $@convention(thin) ((Builtin.Int32, Builtin.Int32), (Builtin.Int32, Builtin.Int32)) -> (Builtin.Int32)
|
|
return %5 : $(Builtin.Int32)
|
|
}
|
|
|
|
sil [ossa] @generate_tuple : $@convention(thin) () -> ((Builtin.Int32, Builtin.Int32))
|
|
|
|
// CHECK-LABEL: sil [ossa] @tupleextract_test :
|
|
// CHECK: tuple_extract {{%[0-9]}} : $(Builtin.Int32, Builtin.Int32), 0
|
|
// CHECK-NOT: tuple_extract {{%[0-9]}} : $(Builtin.Int32, Builtin.Int32), 0
|
|
// CHECK-LABEL: } // end sil function 'tupleextract_test'
|
|
sil [ossa] @tupleextract_test : $@convention(thin) () -> (Builtin.Int32) {
|
|
%0 = function_ref @generate_tuple : $@convention(thin) () -> ((Builtin.Int32, Builtin.Int32))
|
|
%1 = apply %0() : $@convention(thin) () -> ((Builtin.Int32, Builtin.Int32))
|
|
%2 = tuple_extract %1 : $(Builtin.Int32, Builtin.Int32), 0
|
|
%3 = tuple_extract %1 : $(Builtin.Int32, Builtin.Int32), 0
|
|
%5 = integer_literal $Builtin.Int1, 0
|
|
%6 = builtin "sadd_with_overflow_Int32" (%2 : $Builtin.Int32, %3 : $Builtin.Int32, %5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
|
|
%7 = tuple_extract %6 : $(Builtin.Int32, Builtin.Int1), 0
|
|
return %7 : $(Builtin.Int32)
|
|
}
|
|
|
|
sil [ossa] @init_tuple_addr : $@convention(thin) () -> @out (Builtin.Int32, Builtin.Int32)
|
|
|
|
// CHECK-LABEL: sil [ossa] @tupleelementaddr_test :
|
|
// CHECK: tuple_element_addr {{%[0-9]}} : $*(Builtin.Int32, Builtin.Int32), 0
|
|
// CHECK-NOT: tuple_element_addr {{%[0-9]}} : $*(Builtin.Int32, Builtin.Int32), 0
|
|
// CHECK-LABEL: } // end sil function 'tupleelementaddr_test'
|
|
sil [ossa] @tupleelementaddr_test : $@convention(thin) () -> (Builtin.Int32) {
|
|
%0 = alloc_stack $(Builtin.Int32, Builtin.Int32)
|
|
%1 = function_ref @init_tuple_addr : $@convention(thin) () -> (@out (Builtin.Int32, Builtin.Int32))
|
|
apply %1(%0) : $@convention(thin) () -> (@out (Builtin.Int32, Builtin.Int32))
|
|
%2 = tuple_element_addr %0 : $*(Builtin.Int32, Builtin.Int32), 0
|
|
%3 = tuple_element_addr %0 : $*(Builtin.Int32, Builtin.Int32), 0
|
|
%5 = integer_literal $Builtin.Int1, 0
|
|
%6 = load [trivial] %2 : $*Builtin.Int32
|
|
%7 = load [trivial] %3 : $*Builtin.Int32
|
|
%8 = builtin "sadd_with_overflow_Int32" (%6 : $Builtin.Int32, %7 : $Builtin.Int32, %5 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
|
|
%9 = tuple_extract %8 : $(Builtin.Int32, Builtin.Int1), 0
|
|
dealloc_stack %0 : $* (Builtin.Int32, Builtin.Int32)
|
|
return %9 : $(Builtin.Int32)
|
|
}
|
|
|
|
sil [ossa] @metatype_user : $@convention(thin) (@thin String.Type) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @metatype_test :
|
|
// CHECK: [[TARGET:%[0-9]+]] = metatype $@thin String.Type
|
|
// CHECK-NOT: {{%[0-9]+}} = metatype $@thin String.Type
|
|
// CHECK: apply {{%[0-9]+}}([[TARGET]])
|
|
// CHECK: apply {{%[0-9]+}}([[TARGET]])
|
|
// CHECK-LABEL: } // end sil function 'metatype_test'
|
|
sil [ossa] @metatype_test : $@convention(thin) () -> () {
|
|
%0 = metatype $@thin String.Type
|
|
%1 = metatype $@thin String.Type
|
|
%2 = function_ref @metatype_user : $@convention(thin) (@thin String.Type) -> ()
|
|
apply %2(%0) : $@convention(thin) (@thin String.Type) -> ()
|
|
apply %2(%1) : $@convention(thin) (@thin String.Type) -> ()
|
|
%3 = tuple()
|
|
return %3 : $()
|
|
}
|
|
|
|
struct StringData {
|
|
var size: Builtin.Word
|
|
}
|
|
|
|
// 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.
|
|
// CHECK-LABEL: } // end sil function 'sil_extract_of_string'
|
|
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
|
|
}
|
|
|
|
sil [ossa] @helper : $@convention(thin) (Builtin.RawPointer, Builtin.RawPointer) -> Builtin.Word
|
|
sil [ossa] @helper2 : $@convention(thin) (UInt8, UInt8) -> Builtin.Word
|
|
|
|
// CHECK-LABEL: sil [ossa] @sil_string_different_encodings :
|
|
// CHECK: [[T0:%.*]] = function_ref @helper
|
|
// CHECK-NEXT: apply [[T0]](%0, %1)
|
|
// CHECK-LABEL: } // end sil function 'sil_string_different_encodings'
|
|
sil [ossa] @sil_string_different_encodings : $@convention(thin) () -> Builtin.Word {
|
|
%0 = string_literal utf8 "help"
|
|
%1 = string_literal objc_selector "help"
|
|
%2 = function_ref @helper : $@convention(thin) (Builtin.RawPointer, Builtin.RawPointer) -> Builtin.Word
|
|
%3 = apply %2(%0, %1) : $@convention(thin) (Builtin.RawPointer, Builtin.RawPointer) -> Builtin.Word
|
|
return %3 : $Builtin.Word
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @raw_idx_cse :
|
|
// CHECK: integer_literal
|
|
// CHECK-NEXT: index_raw_pointer
|
|
// CHECK-NEXT: pointer_to_address
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-LABEL: } // end sil function 'raw_idx_cse'
|
|
sil [ossa] @raw_idx_cse: $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%X = function_ref @helper2 : $@convention(thin) (UInt8, UInt8) -> Builtin.Word
|
|
%1 = integer_literal $Builtin.Word, 5
|
|
%2 = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word
|
|
%3 = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word
|
|
%4 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%6 = load [trivial] %4 : $*UInt8
|
|
%7 = load [trivial] %5 : $*UInt8
|
|
%8 = apply %X(%6, %7) : $@convention(thin) (UInt8, UInt8) -> Builtin.Word
|
|
%Y = tuple()
|
|
return %Y : $()
|
|
}
|
|
|
|
enum FakeOptional {
|
|
case none
|
|
case some(Builtin.Int32)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @enum_cse : $@convention(thin) () -> () {
|
|
// CHECK: bb0
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: [[FUNC:%[0-9]+]] = function_ref @unknown_fake_optional_user : $@convention(thin) (FakeOptional) -> ()
|
|
// CHECK-NEXT: [[NONE:%[0-9]+]] = enum $FakeOptional, #FakeOptional.none!enumelt
|
|
// CHECK-NEXT: apply [[FUNC]]([[NONE]]) : $@convention(thin) (FakeOptional) -> ()
|
|
// CHECK-NEXT: apply [[FUNC]]([[NONE]]) : $@convention(thin) (FakeOptional) -> ()
|
|
// CHECK-NEXT: [[INTEGER:%[0-9]+]] = integer_literal $Builtin.Int32, 0
|
|
// CHECK-NEXT: [[SOME:%[0-9]+]] = enum $FakeOptional, #FakeOptional.some!enumelt, [[INTEGER]] : $Builtin.Int32
|
|
// CHECK-NEXT: apply [[FUNC]]([[SOME]]) : $@convention(thin) (FakeOptional) -> ()
|
|
// CHECK-NEXT: apply [[FUNC]]([[SOME]]) : $@convention(thin) (FakeOptional) -> ()
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-LABEL: } // end sil function 'enum_cse'
|
|
sil [ossa] @unknown_fake_optional_user : $@convention(thin) (FakeOptional) -> ()
|
|
sil [ossa] @enum_cse : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @unknown_fake_optional_user : $@convention(thin) (FakeOptional) -> ()
|
|
%1 = enum $FakeOptional, #FakeOptional.none!enumelt
|
|
%2 = enum $FakeOptional, #FakeOptional.none!enumelt
|
|
apply %0(%1) : $@convention(thin) (FakeOptional) -> ()
|
|
apply %0(%2) : $@convention(thin) (FakeOptional) -> ()
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
%4 = enum $FakeOptional, #FakeOptional.some!enumelt, %3 : $Builtin.Int32
|
|
%5 = enum $FakeOptional, #FakeOptional.some!enumelt, %3 : $Builtin.Int32
|
|
apply %0(%4) : $@convention(thin) (FakeOptional) -> ()
|
|
apply %0(%5) : $@convention(thin) (FakeOptional) -> ()
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
sil [ossa] @int32_user : $@convention(thin) (Builtin.Int32) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_enum_data_cse : $@convention(thin) (FakeOptional) -> () {
|
|
// CHECK: bb0([[INPUT_ENUM:%[0-9]+]] : $FakeOptional):
|
|
// CHECK-NEXT: function_ref
|
|
// CHECK-NEXT: [[FUNC:%[0-9]+]] = function_ref @int32_user : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: [[INT:%[0-9]+]] = unchecked_enum_data [[INPUT_ENUM]] : $FakeOptional, #FakeOptional.some!enumelt
|
|
// CHECK-NEXT: apply [[FUNC]]([[INT]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: apply [[FUNC]]([[INT]]) : $@convention(thin) (Builtin.Int32) -> ()
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-LABEL: } // end sil function 'unchecked_enum_data_cse'
|
|
sil [ossa] @unchecked_enum_data_cse : $@convention(thin) (FakeOptional) -> () {
|
|
bb0(%0 : $FakeOptional):
|
|
%1 = function_ref @int32_user : $@convention(thin) (Builtin.Int32) -> ()
|
|
%2 = unchecked_enum_data %0 : $FakeOptional, #FakeOptional.some!enumelt
|
|
%3 = unchecked_enum_data %0 : $FakeOptional, #FakeOptional.some!enumelt
|
|
apply %1(%2) : $@convention(thin) (Builtin.Int32) -> ()
|
|
apply %1(%3) : $@convention(thin) (Builtin.Int32) -> ()
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test2cse :
|
|
// CHECK: ref_to_raw_pointer
|
|
// CHECK-NOT: ref_to_raw_pointer
|
|
// CHECK: function_ref
|
|
// CHECK: apply
|
|
// CHECK-LABEL: } // end sil function 'test2cse'
|
|
sil [ossa] @test2cse : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
%1 = ref_to_raw_pointer %0 : $C to $Builtin.RawPointer
|
|
%2 = ref_to_raw_pointer %0 : $C to $Builtin.RawPointer
|
|
%4 = function_ref @helper : $@convention(thin) (Builtin.RawPointer, Builtin.RawPointer) -> Builtin.Word
|
|
%5 = apply %4(%1, %2) : $@convention(thin) (Builtin.RawPointer, Builtin.RawPointer) -> Builtin.Word
|
|
destroy_value %0 : $C
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
sil [ossa] @helperCD : $@convention(thin) (@owned C, @owned C) -> Builtin.Word
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_index_addr_inst :
|
|
// CHECK: bb0(
|
|
// CHECK-NEXT: index_addr
|
|
// CHECK-NEXT: address_to_pointer
|
|
// CHECK-NEXT: tuple
|
|
// CHECK-LABEL: } // end sil function 'cse_index_addr_inst'
|
|
sil [ossa] @cse_index_addr_inst : $@convention(thin) (@in D, Builtin.Word) -> (Builtin.RawPointer, Builtin.RawPointer) {
|
|
bb0(%0 : $*D, %1 : $Builtin.Word):
|
|
%2 = index_addr %0 : $*D, %1 : $Builtin.Word
|
|
%3 = index_addr %0 : $*D, %1 : $Builtin.Word
|
|
%4 = address_to_pointer %2 : $*D to $Builtin.RawPointer
|
|
%5 = address_to_pointer %3 : $*D to $Builtin.RawPointer
|
|
%6 = tuple(%4 : $Builtin.RawPointer, %5 : $Builtin.RawPointer)
|
|
return %6 : $(Builtin.RawPointer, Builtin.RawPointer)
|
|
}
|
|
|
|
|
|
sil [ossa] [readnone] @readnonefun : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_readnone :
|
|
// CHECK: bb0
|
|
// CHECK: function_ref @readnonefun
|
|
// CHECK: apply
|
|
// CHECK-NOT: function_ref @readnonefun
|
|
// CHECK-NOT: apply
|
|
// CHECK-LABEL: } // end sil function 'cse_readnone'
|
|
sil [ossa] @cse_readnone : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64 {
|
|
bb0(%0 : $*Builtin.Int8):
|
|
%1 = function_ref @readnonefun : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64
|
|
%3 = apply %1(%0) : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64
|
|
%2 = function_ref @readnonefun : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64
|
|
%4 = apply %2(%0) : $@convention(thin) (@inout Builtin.Int8) -> Builtin.Int64
|
|
return %4 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_raw_pointer_to_ref :
|
|
// CHECK: raw_pointer_to_ref
|
|
// CHECK-NOT: raw_pointer_to_ref
|
|
// CHECK: tuple
|
|
// CHECK-LABEL: } // end sil function 'cse_raw_pointer_to_ref'
|
|
sil [ossa] @cse_raw_pointer_to_ref : $@convention(thin) (Builtin.RawPointer) -> (C, C) {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = raw_pointer_to_ref %0 : $Builtin.RawPointer to $C
|
|
%2 = raw_pointer_to_ref %0 : $Builtin.RawPointer to $C
|
|
%6 = tuple(%1: $C, %2: $C)
|
|
return %6 : $(C, C)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_unchecked_addr_cast :
|
|
// CHECK: unchecked_addr_cast
|
|
// CHECK-NOT: unchecked_addr_cast
|
|
// CHECK: struct_element_addr
|
|
// CHECK: tuple
|
|
// CHECK-LABEL: } // end sil function 'cse_unchecked_addr_cast'
|
|
sil [ossa] @cse_unchecked_addr_cast : $@convention(thin) () -> (Builtin.RawPointer, Builtin.RawPointer) {
|
|
bb0:
|
|
%1 = alloc_stack $OpaquePointer
|
|
%2 = unchecked_addr_cast %1: $*OpaquePointer to $*UnsafeMutablePointer<AnyObject>
|
|
%3 = unchecked_addr_cast %1: $*OpaquePointer to $*UnsafeMutablePointer<AnyObject>
|
|
%4 = struct_element_addr %2 : $*UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
%5 = load [trivial] %4 : $*Builtin.RawPointer
|
|
%6 = struct_element_addr %3 : $*UnsafeMutablePointer<AnyObject>, #UnsafeMutablePointer._rawValue
|
|
%7 = load [trivial] %6 : $*Builtin.RawPointer
|
|
%8 = tuple (%5: $Builtin.RawPointer, %7: $Builtin.RawPointer)
|
|
dealloc_stack %1 : $*OpaquePointer
|
|
return %8: $(Builtin.RawPointer, Builtin.RawPointer)
|
|
}
|
|
|
|
enum Enum1 {
|
|
case Case1
|
|
case Case2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_select_enum :
|
|
// CHECK: select_enum
|
|
// CHECK-NOT: select_enum
|
|
// CHECK: tuple
|
|
// CHECK-LABEL: } // end sil function 'cse_select_enum'
|
|
sil [ossa] @cse_select_enum : $@convention(thin) (@guaranteed Enum1) -> (Builtin.Int1, Builtin.Int1) {
|
|
bb0(%0 : $Enum1):
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
%1 = select_enum %0 : $Enum1, case #Enum1.Case1!enumelt: %t, case #Enum1.Case2!enumelt: %f : $Builtin.Int1
|
|
%2 = select_enum %0 : $Enum1, case #Enum1.Case1!enumelt: %t, case #Enum1.Case2!enumelt: %f : $Builtin.Int1
|
|
%3 = tuple (%1: $Builtin.Int1, %2: $Builtin.Int1)
|
|
return %3: $(Builtin.Int1, Builtin.Int1)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_bridge_object_to_word :
|
|
// CHECK: [[REF:%[0-9]+]] = bridge_object_to_word
|
|
// CHECK-NOT: bridge_object_to_word
|
|
// CHECK: tuple ([[REF]] : $Builtin.Word, [[REF]] : $Builtin.Word)
|
|
// CHECK-LABEL: } // end sil function 'cse_bridge_object_to_word'
|
|
sil [ossa] @cse_bridge_object_to_word : $@convention(thin) (@owned Builtin.BridgeObject) -> (Builtin.Word, Builtin.Word) {
|
|
bb0(%0 : @owned $Builtin.BridgeObject):
|
|
%1 = bridge_object_to_word %0 : $Builtin.BridgeObject to $Builtin.Word
|
|
%2 = bridge_object_to_word %0 : $Builtin.BridgeObject to $Builtin.Word
|
|
%3 = tuple (%1 : $Builtin.Word, %2 : $Builtin.Word)
|
|
destroy_value %0 : $Builtin.BridgeObject
|
|
return %3 : $(Builtin.Word, Builtin.Word)
|
|
}
|
|
|
|
sil [ossa] [_semantics "array.get_count"] @getCount : $@convention(method) (@guaranteed Array<Int>) -> Int
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_cse_get_count_on_low_level_sil :
|
|
// CHECK: [[R1:%[0-9]+]] = apply
|
|
// CHECK: [[R2:%[0-9]+]] = apply
|
|
// CHECK: tuple ([[R1]] : $Int, [[R2]] : $Int)
|
|
// CHECK-LABEL: } // end sil function 'dont_cse_get_count_on_low_level_sil'
|
|
sil [ossa] @dont_cse_get_count_on_low_level_sil : $@convention(thin) (@guaranteed Array<Int>) -> (Int, Int) {
|
|
bb0(%0 : @guaranteed $Array<Int>):
|
|
%f1 = function_ref @getCount : $@convention(method) (@guaranteed Array<Int>) -> Int
|
|
%c1 = apply %f1(%0) : $@convention(method) (@guaranteed Array<Int>) -> Int
|
|
%c2 = apply %f1(%0) : $@convention(method) (@guaranteed Array<Int>) -> Int
|
|
%r1 = tuple (%c1 : $Int, %c2 : $Int)
|
|
return %r1 : $(Int, Int)
|
|
}
|
|
|
|
|
|
sil [ossa] @_TFC4main4Ping4pingfS0_FT_S0_ : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
sil [ossa] @_TFC4main4PingD : $@convention(method) (@owned Ping) -> ()
|
|
sil [ossa] @_TFC4main4PingcfMS0_FT_S0_ : $@convention(method) (@owned Ping) -> @owned Ping
|
|
|
|
// CHECK-LABEL: sil [ossa] @_TF4main4ringFCS_4PingT_ :
|
|
// CHECK: bb0(%0 : @owned $Ping):
|
|
// CHECK-NEXT: class_method
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-LABEL: } // end sil function '_TF4main4ringFCS_4PingT_'
|
|
sil [ossa] @_TF4main4ringFCS_4PingT_ : $@convention(thin) (@owned Ping) -> () {
|
|
bb0(%0 : @owned $Ping):
|
|
%1 = class_method %0 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%2 = class_method %0 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%3 = class_method %0 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%4 = class_method %0 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%5 = class_method %0 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%6 = apply %1(%0) : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%7 = apply %2(%0) : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%8 = apply %3(%0) : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%9 = apply %4(%0) : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
destroy_value %6 : $Ping
|
|
destroy_value %7 : $Ping
|
|
destroy_value %8 : $Ping
|
|
destroy_value %9 : $Ping
|
|
destroy_value %0 : $Ping
|
|
%10 = tuple ()
|
|
return %10 : $()
|
|
}
|
|
|
|
sil_vtable Ping {
|
|
#Ping.ping: @_TFC4main4Ping4pingfS0_FT_S0_ // main.Ping.ping (main.Ping)() -> main.Ping
|
|
#Ping.deinit!deallocator: @_TFC4main4PingD // main.Ping.__deallocating_deinit
|
|
#Ping.init!initializer: @_TFC4main4PingcfMS0_FT_S0_ // main.Ping.init (main.Ping.Type)() -> main.Ping
|
|
}
|
|
|
|
protocol Reachable {
|
|
func reach()
|
|
}
|
|
|
|
class T : Reachable {
|
|
func reach()
|
|
deinit
|
|
init()
|
|
}
|
|
|
|
func foo<T : Reachable>(x: T, a: Int)
|
|
|
|
// p.T.reach (p.T)() -> ()
|
|
sil hidden [ossa] @_TFC1p1T5reachfS0_FT_T_ : $@convention(method) (@guaranteed T) -> () {
|
|
bb0(%0 : @guaranteed $T):
|
|
debug_value %0 : $T, let, name "self"
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// p.T.__deallocating_deinit
|
|
sil hidden [ossa] @_TFC1p1TD : $@convention(method) (@owned T) -> () {
|
|
bb0(%0 : @owned $T):
|
|
debug_value %0 : $T, let, name "self"
|
|
destroy_value %0 : $T
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// p.T.deinit
|
|
sil hidden [ossa] @_TFC1p1Td : $@convention(method) (@guaranteed T) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : @guaranteed $T):
|
|
debug_value %0 : $T, let, name "self"
|
|
%copy = copy_value %0 : $T
|
|
%2 = unchecked_ref_cast %copy : $T to $Builtin.NativeObject
|
|
return %2 : $Builtin.NativeObject
|
|
}
|
|
|
|
// p.T.init (p.T.Type)() -> p.T
|
|
sil hidden [ossa] @_TFC1p1TcfMS0_FT_S0_ : $@convention(method) (@owned T) -> @owned T {
|
|
bb0(%0 : @owned $T):
|
|
debug_value %0 : $T, let, name "self"
|
|
return %0 : $T
|
|
}
|
|
|
|
// protocol witness for p.Reachable.reach <A where A: p.Reachable> (A)() -> () in conformance p.T : p.Reachable in p
|
|
sil hidden [ossa] [transparent] [thunk] @_TTWC1p1TS_9ReachableS_FS1_5reachuRq_S1__fq_FT_T_ : $@convention(witness_method: Reachable) (@in_guaranteed T) -> () {
|
|
bb0(%0 : $*T):
|
|
%1 = load [copy] %0 : $*T
|
|
%3 = class_method %1 : $T, #T.reach : (T) -> () -> (), $@convention(method) (@guaranteed T) -> ()
|
|
%4 = apply %3(%1) : $@convention(method) (@guaranteed T) -> ()
|
|
destroy_value %1 : $T
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @_TF1p3foouRq_S_9Reachable_FTq_1aSi_T_ :
|
|
// CHECK: bb0(%0 : $*T, %1 : $Int):
|
|
// CHECK-NEXT: witness_method
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy_addr
|
|
// CHECK-NEXT: tuple
|
|
// p.foo <A where A: p.Reachable> (A, a : Swift.Int) -> ()
|
|
// CHECK-LABEL: } // end sil function '_TF1p3foouRq_S_9Reachable_FTq_1aSi_T_'
|
|
sil hidden [ossa] @_TF1p3foouRq_S_9Reachable_FTq_1aSi_T_ : $@convention(thin) <T where T : Reachable> (@in T, Int) -> () {
|
|
bb0(%0 : $*T, %1 : $Int):
|
|
%4 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%5 = apply %4<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%6 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%7 = apply %6<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%8 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%9 = apply %8<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%10 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%11 = apply %10<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%12 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%13 = apply %12<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%14 = witness_method $T, #Reachable.reach : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
%15 = apply %14<T>(%0) : $@convention(witness_method: Reachable) <τ_0_0 where τ_0_0 : Reachable> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %0 : $*T
|
|
%17 = tuple ()
|
|
return %17 : $()
|
|
}
|
|
|
|
sil_vtable T {
|
|
#T.reach: @_TFC1p1T5reachfS0_FT_T_ // p.T.reach (p.T)() -> ()
|
|
#T.deinit!deallocator: @_TFC1p1TD // p.T.__deallocating_deinit
|
|
#T.init!initializer: @_TFC1p1TcfMS0_FT_S0_ // p.T.init (p.T.Type)() -> p.T
|
|
}
|
|
|
|
sil_witness_table hidden T: Reachable module p {
|
|
method #Reachable.reach: @_TTWC1p1TS_9ReachableS_FS1_5reachuRq_S1__fq_FT_T_ // protocol witness for p.Reachable.reach <A where A: p.Reachable> (A)() -> () in conformance p.T : p.Reachable in p
|
|
}
|
|
|
|
protocol Flyable {
|
|
func fly()
|
|
}
|
|
|
|
struct Airplane : Flyable {
|
|
func fly()
|
|
init()
|
|
}
|
|
|
|
func trytofly(a: Flyable)
|
|
|
|
// p2.Airplane.fly (p2.Airplane)() -> ()
|
|
sil hidden [ossa] @_TFV2p28Airplane3flyfS0_FT_T_ : $@convention(method) (Airplane) -> () {
|
|
bb0(%0 : $Airplane):
|
|
debug_value %0 : $Airplane, let, name "self"
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
// protocol witness for p2.Flyable.fly <A where A: p2.Flyable> (A)() -> () in conformance p2.Airplane : p2.Flyable in p2
|
|
sil hidden [ossa] [transparent] [thunk] @_TTWV2p28AirplaneS_7FlyableS_FS1_3flyuRq_S1__fq_FT_T_ : $@convention(witness_method: Flyable) (@in_guaranteed Airplane) -> () {
|
|
bb0(%0 : $*Airplane):
|
|
%1 = alloc_stack $Airplane
|
|
copy_addr %0 to [init] %1 : $*Airplane
|
|
%3 = struct $Airplane ()
|
|
// function_ref p2.Airplane.fly (p2.Airplane)() -> ()
|
|
%4 = function_ref @_TFV2p28Airplane3flyfS0_FT_T_ : $@convention(method) (Airplane) -> ()
|
|
%5 = apply %4(%3) : $@convention(method) (Airplane) -> ()
|
|
dealloc_stack %1 : $*Airplane
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @_TF2p28trytoflyFPS_7Flyable_T_ :
|
|
// CHECK: bb0(%0 : $*any Flyable):
|
|
// CHECK-NEXT: open_existential_addr
|
|
// CHECK-NEXT: witness_method
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: open_existential_addr
|
|
// CHECK-NEXT: witness_method
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: open_existential_addr
|
|
// CHECK-NEXT: witness_method
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: destroy_addr
|
|
// CHECK-NEXT: tuple
|
|
// p2.trytofly (p2.Flyable) -> ()
|
|
// CHECK-LABEL: } // end sil function '_TF2p28trytoflyFPS_7Flyable_T_'
|
|
sil hidden [ossa] @_TF2p28trytoflyFPS_7Flyable_T_ : $@convention(thin) (@in Flyable) -> () {
|
|
bb0(%0 : $*Flyable):
|
|
%2 = open_existential_addr immutable_access %0 : $*Flyable to $*@opened("D8A4A5D8-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self
|
|
%3 = witness_method $@opened("D8A4A5D8-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self, #Flyable.fly, %2 : $*@opened("D8A4A5D8-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%4 = apply %3<@opened("D8A4A5D8-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self>(%2) : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%5 = open_existential_addr immutable_access %0 : $*Flyable to $*@opened("D8A4B49C-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self
|
|
%6 = witness_method $@opened("D8A4B49C-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self, #Flyable.fly, %5 : $*@opened("D8A4B49C-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%7 = apply %6<@opened("D8A4B49C-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self>(%5) : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%8 = open_existential_addr immutable_access %0 : $*Flyable to $*@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self
|
|
%9 = witness_method $@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self, #Flyable.fly, %8 : $*@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%10 = apply %9<@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self>(%8) : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%11 = witness_method $@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self, #Flyable.fly, %8 : $*@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
%12 = apply %9<@opened("D8A4BCB2-4C44-11E5-BA43-AC87A3294C0A", Flyable) Self>(%8) : $@convention(witness_method: Flyable) <τ_0_0 where τ_0_0 : Flyable> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %0 : $*Flyable
|
|
%13 = tuple ()
|
|
return %13 : $()
|
|
}
|
|
|
|
sil_witness_table hidden Airplane: Flyable module p2 {
|
|
method #Flyable.fly: @_TTWV2p28AirplaneS_7FlyableS_FS1_3flyuRq_S1__fq_FT_T_ // protocol witness for p2.Flyable.fly <A where A: p2.Flyable> (A)() -> () in conformance p2.Airplane : p2.Flyable in p2
|
|
}
|
|
|
|
|
|
protocol Pingable { func ping() }
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @CSE_Existential_Simple :
|
|
// CHECK: open_existential_addr immutable_access %0 : $*any Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable)
|
|
// CHECK: witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self, #Pingable.ping : {{.*}}, %2
|
|
// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2)
|
|
// CHECK: open_existential_addr immutable_access
|
|
// CHECK: witness_method
|
|
// CHECK: apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", any Pingable) Self>(%2)
|
|
// CHECK-LABEL: } // end sil function 'CSE_Existential_Simple'
|
|
sil hidden [ossa] @CSE_Existential_Simple : $@convention(thin) (@in Pingable) -> () {
|
|
bb0(%0 : $*Pingable):
|
|
debug_value %0 : $*Pingable, expr op_deref // let x
|
|
%2 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self
|
|
%3 = witness_method $@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self, #Pingable.ping, %2 : $*@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
%4 = apply %3<@opened("1E467EB8-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%2) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
%5 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("1E4687DC-D5C5-11E5-8C0E-A82066121073", Pingable) Self
|
|
%6 = witness_method $@opened("1E4687DC-D5C5-11E5-8C0E-A82066121073", Pingable) Self, #Pingable.ping, %5 : $*@opened("1E4687DC-D5C5-11E5-8C0E-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
%7 = apply %6<@opened("1E4687DC-D5C5-11E5-8C0E-A82066121073", Pingable) Self>(%5) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %0 : $*Pingable
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @CSE_Existential_Calls_With_Control_Flow :
|
|
sil hidden [ossa] @CSE_Existential_Calls_With_Control_Flow : $@convention(thin) (@in Pingable, Int) -> () {
|
|
bb0(%0 : $*Pingable, %1 : $Int):
|
|
debug_value %0 : $*Pingable, expr op_deref // let x
|
|
debug_value %1 : $Int // let y
|
|
%4 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self
|
|
%5 = witness_method $@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %4 : $*@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
|
|
// CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4)
|
|
%6 = apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", Pingable) Self>(%4) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
%7 = integer_literal $Builtin.Int64, 3
|
|
%8 = integer_literal $Builtin.Int64, 3
|
|
%9 = builtin "cmp_sgt_Int64"(%8 : $Builtin.Int64, %7 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_br %9, bb1, bb2
|
|
|
|
bb1:
|
|
%11 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self
|
|
%12 = witness_method $@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %11 : $*@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
|
|
// CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4)
|
|
%13 = apply %12<@opened("75F1F3AC-D6CB-11E5-9470-A82066121073", Pingable) Self>(%11) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%15 = open_existential_addr immutable_access %0 : $*Pingable to $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self
|
|
%16 = witness_method $@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self, #Pingable.ping, %15 : $*@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
|
|
// CHECK: apply %5<@opened("75F1B81A-D6CB-11E5-9470-A82066121073", any Pingable) Self>(%4)
|
|
%17 = apply %16<@opened("75F1F5C8-D6CB-11E5-9470-A82066121073", Pingable) Self>(%15) : $@convention(witness_method: Pingable) <τ_0_0 where τ_0_0 : Pingable> (@in_guaranteed τ_0_0) -> ()
|
|
destroy_addr %0 : $*Pingable
|
|
%19 = tuple ()
|
|
|
|
return %19 : $()
|
|
}
|
|
// CHECK-LABEL: } // end sil function 'CSE_Existential_Calls_With_Control_Flow'
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_mark_dependence :
|
|
// CHECK: mark_dependence
|
|
// CHECK-NOT: mark_dependence
|
|
// CHECK-LABEL: } // end sil function 'cse_mark_dependence'
|
|
sil [ossa] @cse_mark_dependence : $@convention(thin) (@inout Builtin.Int64, @guaranteed Builtin.NativeObject) -> (Builtin.Int64, Builtin.Int64) {
|
|
bb0(%0 : $*Builtin.Int64, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = mark_dependence %0 : $*Builtin.Int64 on %1 : $Builtin.NativeObject
|
|
%3 = mark_dependence %0 : $*Builtin.Int64 on %1 : $Builtin.NativeObject
|
|
%4 = load [trivial] %2 : $*Builtin.Int64
|
|
%5 = load [trivial] %3 : $*Builtin.Int64
|
|
%6 = tuple(%4 : $Builtin.Int64, %5 : $Builtin.Int64)
|
|
return %6 : $(Builtin.Int64, Builtin.Int64)
|
|
}
|
|
|
|
protocol Proto : class {
|
|
func doThis()
|
|
func doThat()
|
|
}
|
|
|
|
// Check that we don't CSE open_existential_ref if they are not completely equal.
|
|
// CHECK-LABEL: sil [ossa] @dont_cse_open_existential_ref :
|
|
// CHECK: open_existential_ref
|
|
// CHECK: open_existential_ref
|
|
// CHECK-LABEL: } // end sil function 'dont_cse_open_existential_ref'
|
|
sil [ossa] @dont_cse_open_existential_ref : $@convention(thin) (@guaranteed Proto & Ping) -> @owned Ping {
|
|
bb0(%0 : @guaranteed $Proto & Ping):
|
|
%4 = open_existential_ref %0 : $Proto & Ping to $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self
|
|
%5 = witness_method $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self, #Proto.doThis, %4 : $@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self : $@convention(witness_method: Proto) <τ_0_0 where τ_0_0 : Proto> (@guaranteed τ_0_0) -> ()
|
|
%6 = apply %5<@opened("1B68354A-4796-11E6-B7DF-B8E856428C60", Proto) Self>(%4) : $@convention(witness_method: Proto) <τ_0_0 where τ_0_0 : Proto> (@guaranteed τ_0_0) -> ()
|
|
%9 = open_existential_ref %0 : $Proto & Ping to $@opened("3C038746-BE69-11E7-A5C1-685B35C48C83", Proto & Ping) Self
|
|
%10 = upcast %9 : $@opened("3C038746-BE69-11E7-A5C1-685B35C48C83", Proto & Ping) Self to $Ping
|
|
%11 = class_method %10 : $Ping, #Ping.ping : (Ping) -> () -> Ping, $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
%12 = apply %11(%10) : $@convention(method) (@guaranteed Ping) -> @owned Ping
|
|
return %12 : $Ping
|
|
}
|
|
|
|
sil [ossa] [global_init] @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_global_init :
|
|
// CHECK: [[P:%[0-9]+]] = apply
|
|
// CHECK: [[A:%[0-9]+]] = pointer_to_address [[P]]
|
|
// CHECK: begin_access [modify] [dynamic] [no_nested_conflict] [[A]]
|
|
// CHECK: begin_access [read] [dynamic] [no_nested_conflict] [[A]]
|
|
// CHECK: // end sil function 'cse_global_init'
|
|
sil [ossa] @cse_global_init : $@convention(thin) () -> Int64 {
|
|
bb0:
|
|
%2 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = apply %2() : $@convention(thin) () -> Builtin.RawPointer
|
|
%4 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int64
|
|
%5 = integer_literal $Builtin.Int64, 42
|
|
%6 = struct $Int64 (%5 : $Builtin.Int64)
|
|
%7 = begin_access [modify] [dynamic] [no_nested_conflict] %4 : $*Int64
|
|
store %6 to [trivial] %7 : $*Int64
|
|
end_access %7 : $*Int64
|
|
%10 = function_ref @$s4test10testGlobalSivau : $@convention(thin) () -> Builtin.RawPointer
|
|
%11 = apply %10() : $@convention(thin) () -> Builtin.RawPointer
|
|
%12 = pointer_to_address %11 : $Builtin.RawPointer to [strict] $*Int64
|
|
%33 = begin_access [read] [dynamic] [no_nested_conflict] %12 : $*Int64
|
|
%35 = load [trivial] %33 : $*Int64
|
|
end_access %33 : $*Int64
|
|
return %35 : $Int64
|
|
}
|
|
|
|
// Test init_existential_metatype combining.
|
|
protocol SomeP {}
|
|
|
|
public enum SpecialEnum : SomeP {}
|
|
|
|
// CHECK-LABEL: sil [ossa] @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool {
|
|
// CHECK: [[EMT:%.*]] = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick any Any.Type
|
|
// CHECK-NOT: init_existential_metatype
|
|
// CHECK: builtin "is_same_metatype"([[EMT]] : $@thick any Any.Type, [[EMT]] : $@thick any Any.Type) : $Builtin.Int1
|
|
// CHECK-LABEL: } // end sil function 'testCSEInitExistentialMetatype'
|
|
sil [ossa] @testCSEInitExistentialMetatype : $@convention(thin) (@thick SpecialEnum.Type) -> Bool {
|
|
bb0(%0 : $@thick SpecialEnum.Type):
|
|
%1 = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type
|
|
%2 = init_existential_metatype %0 : $@thick SpecialEnum.Type, $@thick Any.Type
|
|
%3 = builtin "is_same_metatype"(%1 : $@thick Any.Type, %2 : $@thick Any.Type) : $Builtin.Int1
|
|
%4 = struct $Bool (%3 : $Builtin.Int1)
|
|
return %4 : $Bool
|
|
}
|
|
|
|
struct StructWithLazyProperty {
|
|
var lazyProperty: Int64 { mutating get set }
|
|
@_hasStorage @_hasInitialValue var lazyPropertyStorage : Int64? { get set }
|
|
}
|
|
|
|
sil private [ossa] [lazy_getter] [noinline] @lazy_getter : $@convention(method) (@inout StructWithLazyProperty) -> Int64 {
|
|
bb0(%0 : $*StructWithLazyProperty):
|
|
%2 = struct_element_addr %0 : $*StructWithLazyProperty, #StructWithLazyProperty.lazyPropertyStorage
|
|
%3 = load [trivial] %2 : $*Optional<Int64>
|
|
switch_enum %3 : $Optional<Int64>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%5 : $Int64):
|
|
br bb3(%5 : $Int64)
|
|
|
|
bb2:
|
|
%9 = integer_literal $Builtin.Int64, 27
|
|
%10 = struct $Int64 (%9 : $Builtin.Int64)
|
|
%12 = enum $Optional<Int64>, #Optional.some!enumelt, %10 : $Int64
|
|
store %12 to [trivial] %2 : $*Optional<Int64>
|
|
br bb3(%10 : $Int64)
|
|
|
|
bb3(%15 : $Int64):
|
|
return %15 : $Int64
|
|
}
|
|
|
|
sil [ossa] @take_int : $@convention(thin) (Int64) -> ()
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_cse_lazy_property_of_overwritten_struct : $@convention(thin) () -> () {
|
|
// CHECK: [[GETTER:%[0-9]+]] = function_ref @lazy_getter
|
|
// CHECK: apply [[GETTER]]
|
|
// CHECK: apply [[GETTER]]
|
|
// CHECK: } // end sil function 'dont_cse_lazy_property_of_overwritten_struct'
|
|
sil [ossa] @dont_cse_lazy_property_of_overwritten_struct : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $StructWithLazyProperty
|
|
%4 = enum $Optional<Int64>, #Optional.none!enumelt
|
|
%5 = struct $StructWithLazyProperty (%4 : $Optional<Int64>)
|
|
store %5 to [trivial] %0 : $*StructWithLazyProperty
|
|
%7 = function_ref @lazy_getter : $@convention(method) (@inout StructWithLazyProperty) -> Int64
|
|
%8 = apply %7(%0) : $@convention(method) (@inout StructWithLazyProperty) -> Int64
|
|
%9 = function_ref @take_int : $@convention(thin) (Int64) -> ()
|
|
%10 = apply %9(%8) : $@convention(thin) (Int64) -> ()
|
|
store %5 to [trivial] %0 : $*StructWithLazyProperty
|
|
%18 = apply %7(%0) : $@convention(method) (@inout StructWithLazyProperty) -> Int64
|
|
%20 = apply %9(%18) : $@convention(thin) (Int64) -> ()
|
|
dealloc_stack %0 : $*StructWithLazyProperty
|
|
%22 = tuple ()
|
|
return %22 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @cse_mark_dependence2 :
|
|
// CHECK: mark_dependence
|
|
// CHECK: mark_dependence
|
|
// CHECK-LABEL: } // end sil function 'cse_mark_dependence2'
|
|
sil [ossa] @cse_mark_dependence2 : $@convention(thin) (@inout Builtin.Int64, @guaranteed Builtin.NativeObject) -> (Builtin.Int64, Builtin.Int64) {
|
|
bb0(%0 : $*Builtin.Int64, %1 : @guaranteed $Builtin.NativeObject):
|
|
%2 = mark_dependence %0 : $*Builtin.Int64 on %1 : $Builtin.NativeObject
|
|
%copy = copy_value %1 : $Builtin.NativeObject
|
|
%3 = mark_dependence %0 : $*Builtin.Int64 on %copy : $Builtin.NativeObject
|
|
%4 = load [trivial] %2 : $*Builtin.Int64
|
|
%5 = load [trivial] %3 : $*Builtin.Int64
|
|
%6 = tuple(%4 : $Builtin.Int64, %5 : $Builtin.Int64)
|
|
destroy_value %copy : $Builtin.NativeObject
|
|
return %6 : $(Builtin.Int64, Builtin.Int64)
|
|
}
|
|
|
|
final class LazyKlass {
|
|
final var lazyProperty: Int64 { get set }
|
|
@_hasStorage @_hasInitialValue final var lazyPropertyStorage : Int64? { get set }
|
|
init()
|
|
}
|
|
|
|
sil private [lazy_getter] [noinline] @lazy_class_getter_nonossa : $@convention(method) (@guaranteed LazyKlass) -> Int64 {
|
|
bb0(%0 : $LazyKlass):
|
|
%2 = ref_element_addr %0 : $LazyKlass, #LazyKlass.lazyPropertyStorage
|
|
%3 = load %2 : $*Optional<Int64>
|
|
switch_enum %3 : $Optional<Int64>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%5 : $Int64):
|
|
br bb3(%5 : $Int64)
|
|
|
|
bb2:
|
|
%9 = integer_literal $Builtin.Int64, 27
|
|
%10 = struct $Int64 (%9 : $Builtin.Int64)
|
|
%12 = enum $Optional<Int64>, #Optional.some!enumelt, %10 : $Int64
|
|
store %12 to %2 : $*Optional<Int64>
|
|
br bb3(%10 : $Int64)
|
|
|
|
bb3(%15 : $Int64):
|
|
return %15 : $Int64
|
|
}
|
|
|
|
sil private [lazy_getter] [noinline] [ossa] @lazy_class_getter_ossa : $@convention(method) (@guaranteed LazyKlass) -> Int64 {
|
|
bb0(%0 : @guaranteed $LazyKlass):
|
|
%2 = ref_element_addr %0 : $LazyKlass, #LazyKlass.lazyPropertyStorage
|
|
%3 = load [trivial] %2 : $*Optional<Int64>
|
|
switch_enum %3 : $Optional<Int64>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%5 : $Int64):
|
|
br bb3(%5 : $Int64)
|
|
|
|
bb2:
|
|
%9 = integer_literal $Builtin.Int64, 27
|
|
%10 = struct $Int64 (%9 : $Builtin.Int64)
|
|
%12 = enum $Optional<Int64>, #Optional.some!enumelt, %10 : $Int64
|
|
store %12 to [trivial] %2 : $*Optional<Int64>
|
|
br bb3(%10 : $Int64)
|
|
|
|
bb3(%15 : $Int64):
|
|
return %15 : $Int64
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_cse_nonossa_getter :
|
|
// CHECK: [[GETTER:%[0-9]+]] = function_ref @lazy_class_getter_nonossa
|
|
// CHECK: apply [[GETTER]]
|
|
// CHECK: apply [[GETTER]]
|
|
// CHECK: } // end sil function 'dont_cse_nonossa_getter'
|
|
sil [ossa] @dont_cse_nonossa_getter : $@convention(thin) (@guaranteed LazyKlass) -> (Int64, Int64) {
|
|
bb0(%0 : @guaranteed $LazyKlass):
|
|
%getter = function_ref @lazy_class_getter_nonossa : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%call1 = apply %getter(%0) : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%call2 = apply %getter(%0) : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%res = tuple (%call1 : $Int64, %call2 : $Int64)
|
|
return %res : $(Int64, Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: sil @cse_ossa_getter :
|
|
// CHECK: [[GETTER:%[0-9]+]] = function_ref @lazy_class_getter_ossa
|
|
// CHECK: apply [[GETTER]]
|
|
// CHECK-NOT: apply [[GETTER]]
|
|
// CHECK: } // end sil function 'cse_ossa_getter'
|
|
sil @cse_ossa_getter : $@convention(thin) (@guaranteed LazyKlass) -> (Int64, Int64) {
|
|
bb0(%0 : $LazyKlass):
|
|
%1 = function_ref @lazy_class_getter_ossa : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%2 = apply %1(%0) : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%3 = apply %1(%0) : $@convention(method) (@guaranteed LazyKlass) -> Int64
|
|
%4 = tuple (%2 : $Int64, %3 : $Int64)
|
|
return %4 : $(Int64, Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_end_lifetime :
|
|
// CHECK: upcast
|
|
// CHECK-NOT: upcast
|
|
// CHECK: } // end sil function 'test_end_lifetime'
|
|
sil [ossa] @test_end_lifetime : $@convention(method) (@owned E) -> () {
|
|
bb0(%0 : @owned $E):
|
|
%copy = copy_value %0 : $E
|
|
%u1 = upcast %0 : $E to $B
|
|
%f = objc_method %u1 : $B, #B.foo!foreign : (B) -> () -> (), $@convention(objc_method) (B) -> ()
|
|
%c1 = apply %f(%u1) : $@convention(objc_method) (B) -> ()
|
|
end_lifetime %u1 : $B
|
|
%u2 = upcast %copy : $E to $B
|
|
%c2 = apply %f(%u2) : $@convention(objc_method) (B) -> ()
|
|
end_lifetime %u2 : $B
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil [ossa] @get_owned_c : $@convention(thin) () -> (@owned C)
|
|
sil [ossa] @get_owned_s : $@convention(thin) () -> (@owned S)
|
|
sil [ossa] @take_guaranteed_c : $@convention(thin) (@guaranteed C) -> ()
|
|
|
|
struct S {
|
|
var c : C
|
|
}
|
|
|
|
// The RAUW utility doesn't properly handle reborrows yet. Until it does, don't
|
|
// replace in the face of non-dominated reborrows.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @dont_rauw_guaranteed_with_nondominated_reborrow : {{.*}} {
|
|
// CHECK: struct_extract
|
|
// CHECK: struct_extract
|
|
// CHECK: struct_extract
|
|
// CHECK-LABEL: } // end sil function 'dont_rauw_guaranteed_with_nondominated_reborrow'
|
|
sil [ossa] @dont_rauw_guaranteed_with_nondominated_reborrow : $@convention(thin) (@owned S) -> (@owned C) {
|
|
entry(%instance : @owned $S):
|
|
cond_br undef, left, right
|
|
|
|
left:
|
|
%guaranteed_s_left = begin_borrow %instance : $S
|
|
%new = struct_extract %guaranteed_s_left : $S, #S.c
|
|
%old = struct_extract %guaranteed_s_left : $S, #S.c
|
|
%take_guaranteed_c = function_ref @take_guaranteed_c : $@convention(thin) (@guaranteed C) -> ()
|
|
apply %take_guaranteed_c(%new) : $@convention(thin) (@guaranteed C) -> ()
|
|
br exit(%old : $C, %guaranteed_s_left : $S, %instance : $S)
|
|
|
|
right:
|
|
destroy_value %instance : $S
|
|
%get_owned_s = function_ref @get_owned_s : $@convention(thin) () -> (@owned S)
|
|
%owned_s = apply %get_owned_s() : $@convention(thin) () -> (@owned S)
|
|
%guaranteed_s = begin_borrow %owned_s : $S
|
|
%projection = struct_extract %guaranteed_s : $S, #S.c
|
|
br exit(%projection : $C, %guaranteed_s : $S, %owned_s : $S)
|
|
|
|
exit(%proj : @guaranteed $C, %borrow : @guaranteed $S, %owned_s_2 : @owned $S):
|
|
%copy = copy_value %proj : $C
|
|
end_borrow %borrow : $S
|
|
destroy_value %owned_s_2 : $S
|
|
return %copy : $C
|
|
}
|
|
|