// RUN: %target-sil-opt %s -dump-alias-info -o /dev/null | %FileCheck %s // REQUIRES: asserts // REQUIRES: swift_in_compiler // Declare this SIL to be canonical because some tests break raw SIL // conventions. e.g. address-type block args. -enforce-exclusivity=none is also // required to allow address-type block args in canonical SIL. sil_stage canonical import Builtin struct Int { var _value: Builtin.Int64 } struct Int32 { var _value: Builtin.Int32 } enum Optional { case none case some(T) } // CHECK-LABEL: @index_addr_inst_with_unknown_index // CHECK: PAIR #16. // CHECK-NEXT: %3 = index_addr %2 : $*Int, %1 : $Builtin.Word // CHECK-NEXT: %4 = index_addr %2 : $*Int, %1 : $Builtin.Word // CHECK-NEXT: MayAlias sil @index_addr_inst_with_unknown_index : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> () { bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word): %212 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int %214 = index_addr %212 : $*Int, %1 : $Builtin.Word %2114 = index_addr %212 : $*Int, %1 : $Builtin.Word br bb1 bb1: %3 = tuple() return %3 : $() } // CHECK-LABEL: @index_addr_inst_with_same_constant_index // CHECK: PAIR #16. // CHECK-NEXT: %3 = index_addr %2 : $*Int, %1 : $Builtin.Word // CHECK-NEXT: %4 = index_addr %2 : $*Int, %1 : $Builtin.Word // CHECK-NEXT: MayAlias sil @index_addr_inst_with_same_constant_index : $@convention(thin) (Builtin.RawPointer) -> () { bb0(%0 : $Builtin.RawPointer): %6 = integer_literal $Builtin.Word, 2 %212 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int %214 = index_addr %212 : $*Int, %6 : $Builtin.Word %2114 = index_addr %212 : $*Int, %6 : $Builtin.Word br bb1 bb1: %3 = tuple() return %3 : $() } // CHECK-LABEL: @index_addr_inst_with_different_constant_index // CHECK: PAIR #23. // CHECK-NEXT: %4 = index_addr %3 : $*Int, %1 : $Builtin.Word // CHECK-NEXT: %5 = index_addr %3 : $*Int, %2 : $Builtin.Word // CHECK-NEXT: NoAlias sil @index_addr_inst_with_different_constant_index : $@convention(thin) (Builtin.RawPointer) -> () { bb0(%0 : $Builtin.RawPointer): %6 = integer_literal $Builtin.Word, 2 %7 = integer_literal $Builtin.Word, 3 %212 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Int %214 = index_addr %212 : $*Int, %6 : $Builtin.Word %2114 = index_addr %212 : $*Int, %7 : $Builtin.Word br bb1 bb1: fix_lifetime %214 : $*Int fix_lifetime %2114 : $*Int %3 = tuple() return %3 : $() } // Address Arguments don't alias if they are arguments to the first BB. // // CHECK-LABEL: @address_args_dont_alias_in_first_bb // CHECK: PAIR #0. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #1. // CHECK-NEXT: %0 = argument of bb0 // CHECK-NEXT: %1 = argument of bb0 // CHECK-NEXT: NoAlias sil @address_args_dont_alias_in_first_bb : $@convention(thin) (@in Builtin.NativeObject, @in Builtin.NativeObject) -> () { bb0(%0 : $*Builtin.NativeObject, %1 : $*Builtin.NativeObject): fix_lifetime %0 : $*Builtin.NativeObject fix_lifetime %1 : $*Builtin.NativeObject %2 = tuple() return %2 : $() } // CHECK-LABEL: @inout_args_may_not_alias // CHECK: PAIR #1. // CHECK-NEXT: %0 = argument of bb0 // CHECK-NEXT: %1 = argument of bb0 // CHECK-NEXT: NoAlias sil @inout_args_may_not_alias: $@convention(thin) (@inout Builtin.NativeObject, @inout Builtin.NativeObject) -> () { bb0(%0 : $*Builtin.NativeObject, %1 : $*Builtin.NativeObject): fix_lifetime %0 : $*Builtin.NativeObject fix_lifetime %1 : $*Builtin.NativeObject %2 = tuple() return %2 : $() } struct StructLvl2 { var tup : (Builtin.Int64, Builtin.Int32) } struct StructLvl1 { var sub : StructLvl2 var x : Builtin.Int64 } // Two values with different underlying alloc_stack cannot alias. // // CHECK-LABEL: @different_alloc_stack_dont_alias // cannot alias non types. // CHECK: PAIR #0. // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: MayAlias // CHECK: PAIR #1. // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: %1 = alloc_stack $StructLvl1 // CHECK-NEXT: NoAlias // CHECK: PAIR #2. // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub // CHECK-NEXT: MayAlias // CHECK: PAIR #3. // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: %3 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.x // CHECK-NEXT: MayAlias // CHECK: PAIR #4. // CHECK-NEXT: %0 = alloc_stack $StructLvl1 // CHECK-NEXT: %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup // CHECK-NEXT: MayAlias // CHECK: PAIR #21. // CHECK-NEXT: %1 = alloc_stack $StructLvl1 // CHECK-NEXT: %9 = struct_element_addr %7 : $*StructLvl2, #StructLvl2.tup // CHECK-NEXT: MayAlias // CHECK: PAIR #22. // CHECK-NEXT: %1 = alloc_stack $StructLvl1 // CHECK-NEXT: %10 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 0 // CHECK-NEXT: MayAlias // CHECK: PAIR #23. // CHECK-NEXT: %1 = alloc_stack $StructLvl1 // CHECK-NEXT: %11 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 1 // CHECK-NEXT: MayAlias // CHECK: PAIR #26. // CHECK-NEXT: %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub // CHECK-NEXT: %3 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.x // CHECK-NEXT: NoAlias // CHECK: PAIR #27. // CHECK-NEXT: %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub // CHECK-NEXT: %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup // CHECK-NEXT: MayAlias // CHECK: PAIR #28. // CHECK-NEXT: %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub // CHECK-NEXT: %5 = tuple_element_addr %4 : $*(Builtin.Int64, Builtin.Int32), 0 // CHECK-NEXT: MayAlias // CHECK: PAIR #29. // CHECK-NEXT: %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub // CHECK-NEXT: %6 = tuple_element_addr %4 : $*(Builtin.Int64, Builtin.Int32), 1 // CHECK-NEXT: MayAlias sil @different_alloc_stack_dont_alias : $@convention(thin) () -> () { %0 = alloc_stack $StructLvl1 %1 = alloc_stack $StructLvl1 %2 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub %3 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.x %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup %5 = tuple_element_addr %4 : $*(Builtin.Int64, Builtin.Int32), 0 %6 = tuple_element_addr %4 : $*(Builtin.Int64, Builtin.Int32), 1 %7 = struct_element_addr %1 : $*StructLvl1, #StructLvl1.sub %8 = struct_element_addr %1 : $*StructLvl1, #StructLvl1.x %9 = struct_element_addr %7 : $*StructLvl2, #StructLvl2.tup %10 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 0 %11 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 1 fix_lifetime %2 : $*StructLvl2 fix_lifetime %3 : $*Builtin.Int64 fix_lifetime %5 : $*Builtin.Int64 fix_lifetime %6 : $*Builtin.Int32 fix_lifetime %8 : $*Builtin.Int64 fix_lifetime %10 : $*Builtin.Int64 fix_lifetime %11 : $*Builtin.Int32 dealloc_stack %1 : $*StructLvl1 dealloc_stack %0 : $*StructLvl1 %12 = tuple() return %12 : $() } // Function Arguments cannot alias with no alias arguments or with identified // function locals. // // CHECK-LABEL: @args_dont_alias_with_identified_function_locals // CHECK: PAIR #1. // CHECK-NEXT: %0 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #2. // CHECK-NEXT: %0 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %2 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #3. // CHECK-NEXT: %0 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #6. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %2 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #7. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #10. // CHECK-NEXT: %2 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias sil @args_dont_alias_with_identified_function_locals : $@convention(thin) (Builtin.NativeObject, Builtin.NativeObject, @in Builtin.NativeObject) -> () { bb0(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject, %2 : $*Builtin.NativeObject): %3 = alloc_stack $Builtin.NativeObject dealloc_stack %3 : $*Builtin.NativeObject fix_lifetime %0 : $Builtin.NativeObject fix_lifetime %1 : $Builtin.NativeObject fix_lifetime %2 : $*Builtin.NativeObject %4 = tuple() return %4 : $() } sil @create_native_object : $@convention(thin) () -> (Builtin.NativeObject) sil @use_native_object : $@convention(thin) (Builtin.NativeObject) -> () // For this test, we care about the following results: // %1, %3, %5, %7, %8, %9 // Check every alias query involving those. // CHECK-LABEL: @escapesource_functionlocal_test_escapesource_nonescapinglocal // Test %0 // CHECK: PAIR #1. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #2. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #3. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #5. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #8. // CHECK-NEXT: %0 = argument of bb0 : $*Builtin.NativeObject // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // Test %1 (the aliasing argument) // CHECK: PAIR #11. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #12. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #13. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #15. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #16. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %6 = load %0 : $*Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #19. // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject // CHECK-NEXT: %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () // CHECK-NEXT: NoAlias // Test %2 // CHECK: PAIR #22. // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #24. // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #25. // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %6 = load %0 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #27. // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // Test %3 (the escaping alloca). // CHECK: PAIR #32. // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: NoAlias // CHECK: PAIR #33. // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject // CHECK-NEXT: %6 = load %0 : $*Builtin.NativeObject // CHECK-NEXT: NoAlias // Test %5 (the read write apply inst). // CHECK: PAIR #45. // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #46. // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: %6 = load %0 : $*Builtin.NativeObject // CHECK-NEXT: MayAlias // CHECK: PAIR #47. // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: function_ref use_native_object // CHECK-NEXT: %7 = function_ref @use_native_object : $@convention(thin) (Builtin.NativeObject) -> () // CHECK-NEXT: NoAlias // CHECK: PAIR #49. // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject // CHECK-NEXT: %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () // CHECK-NEXT: NoAlias // Test %8 (the escaping load) // CHECK: PAIR #60. // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject // CHECK-NEXT: MayAlias sil @escapesource_functionlocal_test_escapesource_nonescapinglocal : $@convention(thin) (@in Builtin.NativeObject, Builtin.NativeObject) -> () { bb0(%0 : $*Builtin.NativeObject, %1 : $Builtin.NativeObject): %2 = alloc_stack $Builtin.NativeObject %3 = alloc_stack $Builtin.NativeObject %4 = function_ref @create_native_object : $@convention(thin) () -> Builtin.NativeObject %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject %6 = load %0 : $*Builtin.NativeObject %7 = function_ref @use_native_object : $@convention(thin) (Builtin.NativeObject) -> () %8 = load %3 : $*Builtin.NativeObject %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () dealloc_stack %3 : $*Builtin.NativeObject dealloc_stack %2 : $*Builtin.NativeObject fix_lifetime %1 : $Builtin.NativeObject fix_lifetime %5 : $Builtin.NativeObject fix_lifetime %6 : $Builtin.NativeObject fix_lifetime %9 : $() %12 = tuple () return %12 : $() } // CHECK-LABEL: @projections_from_the_same_source_with_the_same_projection_path_mustalias // CHECK: PAIR #24. // CHECK-NEXT: %3 = tuple_element_addr %2 : $*(Builtin.Int64, Builtin.Int32), 1 // CHECK-NEXT: %6 = tuple_element_addr %5 : $*(Builtin.Int64, Builtin.Int32), 1 // CHECK-NEXT: MayAlias sil @projections_from_the_same_source_with_the_same_projection_path_mustalias : $@convention(thin) () -> () { %0 = alloc_stack $StructLvl1 %1 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub %2 = struct_element_addr %1 : $*StructLvl2, #StructLvl2.tup %3 = tuple_element_addr %2 : $*(Builtin.Int64, Builtin.Int32), 1 %4 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.sub %5 = struct_element_addr %4 : $*StructLvl2, #StructLvl2.tup %6 = tuple_element_addr %5 : $*(Builtin.Int64, Builtin.Int32), 1 fix_lifetime %3: $*Builtin.Int32 fix_lifetime %6: $*Builtin.Int32 dealloc_stack %0 : $*StructLvl1 %7 = tuple() return %7 : $() } sil_global public @sil_global1 : $Builtin.Int32 sil_global public @sil_global2 : $Builtin.Int32 class X { } // CHECK-LABEL: @globals_dont_alias // CHECK: PAIR #0. // CHECK-NEXT: %0 = global_addr @sil_global1 : $*Builtin.Int32 // CHECK-NEXT: %0 = global_addr @sil_global1 : $*Builtin.Int32 // CHECK-NEXT: MayAlias // CHECK: PAIR #1. // CHECK-NEXT: %0 = global_addr @sil_global1 : $*Builtin.Int32 // CHECK-NEXT: %1 = global_addr @sil_global2 : $*Builtin.Int32 // CHECK-NEXT: NoAlias sil @globals_dont_alias : $@convention(thin) () -> () { %0 = global_addr @sil_global1 : $*Builtin.Int32 %1 = global_addr @sil_global2 : $*Builtin.Int32 fix_lifetime %0 : $*Builtin.Int32 fix_lifetime %1 : $*Builtin.Int32 %4 = tuple() return %4 : $() } // CHECK-LABEL: @globals_and_allocs_dont_alias // CHECK: PAIR #1. // CHECK-NEXT: %0 = global_addr @sil_global1 : $*Builtin.Int32 // CHECK-NEXT: %1 = alloc_ref $X // CHECK-NEXT: NoAlias sil @globals_and_allocs_dont_alias : $@convention(thin) () -> () { %0 = global_addr @sil_global1 : $*Builtin.Int32 %1 = alloc_ref $X fix_lifetime %0 : $*Builtin.Int32 fix_lifetime %1 : $X %4 = tuple() return %4 : $() } sil_global @sil_global3 : $Int32 // CHECK-LABEL: @globals_alias // CHECK: PAIR #0. // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 // CHECK-NEXT: MayAlias // CHECK: PAIR #1. // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 // CHECK-NEXT: %1 = global_addr @sil_global3 : $*Int32 // CHECK-NEXT: MayAlias // CHECK: PAIR #2. // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 // CHECK-NEXT: %2 = struct_element_addr %1 : $*Int32, #Int32._value // CHECK-NEXT: MayAlias sil @globals_alias : $@convention(thin) () -> () { %0 = global_addr @sil_global3 : $*Int32 %1 = global_addr @sil_global3 : $*Int32 %2 = struct_element_addr %1 : $*Int32, #Int32._value %4 = tuple() return %4 : $() } class HalfOpenRange { final var current: Int32 final let end: Int32 init(start: Int32, end: Int32) } // CHECK-LABEL: @different_fields // CHECK: PAIR #51. // CHECK-NEXT: %5 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.current // CHECK-NEXT: %7 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.end // CHECK-NEXT: NoAlias // CHECK: PAIR #64. // CHECK-NEXT: %9 = struct_element_addr %5 : $*Int32, #Int32._value // CHECK-NEXT: %10 = struct_element_addr %7 : $*Int32, #Int32._value // CHECK-NEXT: NoAlias sil @different_fields : $@convention(thin) () -> () { %0 = integer_literal $Builtin.Int32, 0 %1 = struct $Int32 (%0 : $Builtin.Int32) %2 = integer_literal $Builtin.Int32, 10 %3 = struct $Int32 (%2 : $Builtin.Int32) %4 = alloc_ref $HalfOpenRange %5 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.current store %1 to %5 : $*Int32 %7 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.end store %3 to %7 : $*Int32 %9 = struct_element_addr %5 : $*Int32, #Int32._value %10 = struct_element_addr %7 : $*Int32, #Int32._value %11 = load %9 : $*Builtin.Int32 %12 = load %10 : $*Builtin.Int32 %13 = tuple() return %13 : $() } public final class C { @_hasStorage final var a: Int { get set } @_hasStorage final var b: Int { get set } deinit init() } // CHECK-LABEL: @ref_element_addr_and_object_itself // CHECK: PAIR #0. // CHECK-NEXT: %0 = alloc_ref $C{{.*}} // CHECK-NEXT: %0 = alloc_ref $C{{.*}} // CHECK-NEXT: MayAlias // CHECK: PAIR #1. // CHECK-NEXT: %0 = alloc_ref $C{{.*}} // CHECK-NEXT: %1 = ref_element_addr %0 : $C, #C.a // CHECK-NEXT: MayAlias sil @ref_element_addr_and_object_itself : $@convention(thin) () -> () { bb0: %0 = alloc_ref $C %1 = ref_element_addr %0 : $C, #C.a fix_lifetime %1 : $*Int %2 = tuple() return %2 : $() } // CHECK-LABEL: @different_fields_of_different_refs // CHECK: PAIR #13. // CHECK-NEXT: %3 = ref_element_addr %0 : $C, #C.a // CHECK-NEXT: %4 = ref_element_addr %1 : $C, #C.b // CHECK-NEXT: NoAlias sil @different_fields_of_different_refs : $@convention(thin) (@owned C, @owned C, Int) -> Int { bb0(%0 : $C, %1 : $C, %2 : $Int): %6 = ref_element_addr %0 : $C, #C.a %8 = ref_element_addr %1 : $C, #C.b fix_lifetime %6 : $*Int fix_lifetime %8 : $*Int return %2 : $Int } sil @not_escaping: $@convention(thin) (X) -> X { bb0(%0 : $X): %1 = alloc_ref $X return %1 : $X } // CHECK-LABEL: @alloc_stack_and_addr_cast // CHECK: PAIR #1. // CHECK-NEXT: %0 = alloc_stack $C{{.*}} // CHECK-NEXT: %1 = unchecked_addr_cast %0 : $*C to $*Optional // CHECK-NEXT: MayAlias sil @alloc_stack_and_addr_cast : $@convention(thin) () -> () { bb0: %0 = alloc_stack $C %1 = unchecked_addr_cast %0 : $*C to $*Optional fix_lifetime %1 : $*Optional dealloc_stack %0 : $*C %2 = tuple() return %2 : $() } struct TwoInts { var a: Int var b: Int } struct StructWithOptional { var i: Optional } // CHECK-LABEL: @init_enum_data_addr // CHECK: PAIR #3. // CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional // CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional, #Optional.some!enumelt // CHECK-NEXT: NoAlias // CHECK: PAIR #4. // CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional // CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a // CHECK-NEXT: NoAlias // CHECK: PAIR #5. // CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional // CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b // CHECK-NEXT: NoAlias // CHECK: PAIR #14. // CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i // CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional, #Optional.some!enumelt // CHECK-NEXT: MayAlias // CHECK: PAIR #15. // CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i // CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a // CHECK-NEXT: MayAlias // CHECK: PAIR #16. // CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i // CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b // CHECK-NEXT: MayAlias // CHECK: PAIR #19. // CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional, #Optional.some!enumelt // CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a // CHECK-NEXT: MayAlias // CHECK: PAIR #20. // CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional, #Optional.some!enumelt // CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b // CHECK-NEXT: MayAlias // CHECK: PAIR #23. // CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a // CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b // CHECK-NEXT: NoAlias sil @init_enum_data_addr : $@convention(thin) (@in_guaranteed StructWithOptional) -> () { bb0(%0 : $*StructWithOptional): %1 = alloc_stack $StructWithOptional %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i %3 = init_enum_data_addr %2 : $*Optional, #Optional.some!enumelt %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b fix_lifetime %0 : $*StructWithOptional fix_lifetime %4 : $*Int fix_lifetime %5 : $*Int dealloc_stack %1 : $*StructWithOptional %6 = tuple () return %6 : $() } protocol P {} struct S : P { var i: Int } // CHECK-LABEL: @init_existential_addr // CHECK: PAIR #3. // CHECK-NEXT: %0 = argument of bb0 : $any P // CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: NoAlias // CHECK: PAIR #12. // CHECK-NEXT: %2 = alloc_stack $any P // CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: MayAlias // CHECK: PAIR #13. // CHECK-NEXT: %2 = alloc_stack $any P // CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i // CHECK-NEXT: MayAlias // CHECK: PAIR #16. // CHECK-NEXT: %3 = init_existential_addr %2 : $*any P, $S // CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i // CHECK-NEXT: MayAlias sil @init_existential_addr : $@convention(thin) (P) -> () { bb0(%0 : $P): %1 = alloc_stack $S %2 = alloc_stack $P %3 = init_existential_addr %2 : $*P, $S %4 = struct_element_addr %3 : $*S, #S.i fix_lifetime %0 : $P fix_lifetime %4 : $*Int dealloc_stack %2 : $*P dealloc_stack %1 : $*S %6 = tuple () return %6 : $() } // CHECK-LABEL: @testCowMutation // CHECK: PAIR #23. // CHECK-NEXT: %4 = ref_tail_addr %0 : $X, $Int32 // CHECK-NEXT: %5 = ref_tail_addr %3 : $X, $Int32 // CHECK-NEXT: MayAlias sil @testCowMutation : $@convention(thin) () -> () { bb0: %0 = alloc_ref $X (%1, %2) = begin_cow_mutation %0 : $X %3 = end_cow_mutation %2 : $X %4 = ref_tail_addr %0 : $X, $Int32 %5 = ref_tail_addr %3 : $X, $Int32 fix_lifetime %4 : $*Int32 fix_lifetime %5 : $*Int32 %99 = tuple () return %99 : $() } class GenericClass { var x : T } // CHECK-LABEL: @test_generic_class // CHECK: PAIR #10. // CHECK-NEXT: %2 = ref_element_addr %0 : $GenericClass, #GenericClass.x // CHECK-NEXT: %3 = ref_element_addr %1 : $GenericClass, #GenericClass.x // CHECK-NEXT: MayAlias sil [ossa] @test_generic_class : $@convention(thin) (@guaranteed GenericClass, @guaranteed GenericClass) -> () { bb0(%0 : @guaranteed $GenericClass, %1 : @guaranteed $GenericClass): %2 = ref_element_addr %0 : $GenericClass, #GenericClass.x %3 = ref_element_addr %1 : $GenericClass, #GenericClass.x fix_lifetime %2 : $*T fix_lifetime %3 : $*Int %9999 = tuple() return %9999 : $() } // CHECK-LABEL: @test_bound_generic_class // CHECK: PAIR #10. // CHECK-NEXT: %2 = ref_element_addr %0 : $GenericClass, #GenericClass.x // CHECK-NEXT: %3 = ref_element_addr %1 : $GenericClass, #GenericClass.x // CHECK-NEXT: NoAlias sil [ossa] @test_bound_generic_class : $@convention(thin) (@guaranteed GenericClass, @guaranteed GenericClass) -> () { bb0(%0 : @guaranteed $GenericClass, %1 : @guaranteed $GenericClass): %2 = ref_element_addr %0 : $GenericClass, #GenericClass.x %3 = ref_element_addr %1 : $GenericClass, #GenericClass.x fix_lifetime %2 : $*Int32 fix_lifetime %3 : $*Int %9999 = tuple() return %9999 : $() } // CHECK-LABEL: @test_store_borrow // CHECK: PAIR #7. // CHECK-NEXT: %1 = alloc_stack $X // CHECK-NEXT: %2 = store_borrow %0 to %1 : $*X // CHECK-NEXT: MayAlias // CHECK: PAIR #13. // CHECK-NEXT: %2 = store_borrow %0 to %1 : $*X // CHECK-NEXT: %4 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*X // CHECK-NEXT: MayAlias sil [ossa] @test_store_borrow : $@convention(thin) (@guaranteed X) -> () { bb0(%0 : @guaranteed $X): %1 = alloc_stack $X %2 = store_borrow %0 to %1 : $*X %3 = address_to_pointer %2 : $*X to $Builtin.RawPointer %4 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*X fix_lifetime %4 : $*X end_borrow %2 : $*X dealloc_stack %1 : $*X %7 = tuple () return %7 : $() }