// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -update-borrowed-from -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 } %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } , 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 } %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 } // 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 { bb0(%0 : @owned $<τ_0_0> { var τ_0_0 } ): %1 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 0 %2 = project_box %0 : $<τ_0_0> { var τ_0_0 } , 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 } 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: pointer_to_address // CHECK: pointer_to_address // 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 %3 = unchecked_addr_cast %1: $*OpaquePointer to $*UnsafeMutablePointer %4 = struct_element_addr %2 : $*UnsafeMutablePointer, #UnsafeMutablePointer._rawValue %5 = load [trivial] %4 : $*Builtin.RawPointer %6 = struct_element_addr %3 : $*UnsafeMutablePointer, #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 // 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) { bb0(%0 : @guaranteed $Array): %f1 = function_ref @getCount : $@convention(method) (@guaranteed Array) -> Int %c1 = apply %f1(%0) : $@convention(method) (@guaranteed Array) -> Int %c2 = apply %f1(%0) : $@convention(method) (@guaranteed Array) -> 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(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)() -> () 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, 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) (@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(%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(%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(%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(%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(%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(%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)() -> () 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)() -> () 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)() -> () 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: pointer_to_address // CHECK: pointer_to_address // 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 switch_enum %3 : $Optional, 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, #Optional.some!enumelt, %10 : $Int64 store %12 to [trivial] %2 : $*Optional 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, #Optional.none!enumelt %5 = struct $StructWithLazyProperty (%4 : $Optional) 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 switch_enum %3 : $Optional, 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, #Optional.some!enumelt, %10 : $Int64 store %12 to %2 : $*Optional 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 switch_enum %3 : $Optional, 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, #Optional.some!enumelt, %10 : $Int64 store %12 to [trivial] %2 : $*Optional 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 } // CHECK-LABEL: sil [ossa] @type_value_test : {{.*}} { // CHECK: type_value // CHECK-NOT: type_value // CHECK-LABEL: } // end sil function 'type_value_test' sil [ossa] @type_value_test : $@convention(thin) (@in_guaranteed InlineArray, Int) -> () { bb0(%0 : $*InlineArray, %1 : $Int): %2 = integer_literal $Builtin.Int64, 0 %3 = type_value $Int for N %4 = struct_extract %1, #Int._value %5 = struct_extract %3, #Int._value %6 = builtin "cmp_slt_Int64"(%4, %2) : $Builtin.Int1 cond_fail %6, "Index out of bounds" %8 = integer_literal $Builtin.Int64, 0 %9 = type_value $Int for N %10 = struct_extract %1, #Int._value %11 = struct_extract %9, #Int._value %12 = builtin "cmp_slt_Int64"(%10, %8) : $Builtin.Int1 cond_fail %12, "Index out of bounds" %14 = tuple () return %14 } struct Pair {} // CHECK-LABEL: sil [ossa] @dont_cse_different_type_values : {{.*}} { // CHECK: type_value // CHECK: type_value // CHECK-LABEL: } // end sil function 'dont_cse_different_type_values' sil [ossa] @dont_cse_different_type_values : $@convention(method) (Pair) -> (Int, Int) { [global: ] bb0(%0 : $Pair): %2 = type_value $Int for x %3 = type_value $Int for y %4 = tuple (%2, %3) return %4 }