| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enforce-exclusivity=none -module-name Swift %s -aa-kind=basic-aa -aa-dump -o /dev/null | %FileCheck %s |
| |
| // REQUIRES: asserts |
| |
| // 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<T> { |
| 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: MustAlias |
| 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: |
| %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: MustAlias |
| // 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): |
| %2 = tuple() |
| return %2 : $() |
| } |
| |
| // Address Arguments may alias if they are arguments to a BB besides the first. |
| // |
| // FIXME: Once we support looking through PHIs, we will allow for must alias here. |
| // |
| // CHECK-LABEL: @address_args_may_alias_in_non_first_bb |
| // CHECK-NOT: NoAlias |
| sil @address_args_may_alias_in_non_first_bb : $@convention(thin) (@inout Builtin.NativeObject) -> () { |
| bb0(%0 : $*Builtin.NativeObject): |
| br bb1(%0 : $*Builtin.NativeObject, %0 : $*Builtin.NativeObject) |
| |
| bb1(%1 : $*Builtin.NativeObject, %2 : $*Builtin.NativeObject): |
| %3 = tuple() |
| return %3 : $() |
| } |
| |
| // Assume that inout arguments alias to preserve memory safety. |
| // |
| // CHECK-LABEL: @inout_args_may_alias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: %0 = argument of bb0 |
| // CHECK-NEXT: %1 = argument of bb0 |
| // CHECK-NEXT: MayAlias |
| sil @inout_args_may_alias: $@convention(thin) (@inout Builtin.NativeObject, @inout Builtin.NativeObject) -> () { |
| bb0(%0 : $*Builtin.NativeObject, %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: MustAlias |
| // 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: PartialAlias |
| // CHECK: PAIR #3. |
| // CHECK-NEXT: %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %3 = struct_element_addr %0 : $*StructLvl1, #StructLvl1.x |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #4. |
| // CHECK-NEXT: %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup |
| // CHECK-NEXT: PartialAlias |
| |
| // CHECK: PAIR #12. |
| // CHECK-NEXT: %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %14 = tuple () |
| // CHECK-NEXT: MayAlias |
| |
| // CHECK: PAIR #21. |
| // CHECK-NEXT: %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %9 = struct_element_addr %7 : $*StructLvl2, #StructLvl2.tup |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #22. |
| // CHECK-NEXT: %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %10 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 0 |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #23. |
| // CHECK-NEXT: %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: %11 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 1 |
| // CHECK-NEXT: PartialAlias |
| // 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: PartialAlias |
| // 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: PartialAlias |
| // 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: PartialAlias |
| 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 |
| |
| 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 #4. |
| // CHECK-NEXT: %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: %5 = tuple () |
| // CHECK-NEXT: MayAlias |
| // 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 |
| %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: MustAlias |
| // 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 #18. |
| // CHECK-NEXT: %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: %8 = load %3 : $*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: MayAlias |
| |
| // 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 |
| // CHECK: PAIR #28. |
| // CHECK-NEXT: %2 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| // CHECK-NEXT: MayAlias |
| |
| // 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 |
| // CHECK: PAIR #35. |
| // CHECK-NEXT: %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: %8 = load %3 : $*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: MustAlias |
| // 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: MayAlias |
| // CHECK: PAIR #48. |
| // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #49. |
| // CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| // CHECK-NEXT: MayAlias |
| |
| // Test %8 (the escaping load) |
| |
| // CHECK: PAIR #60. |
| // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject |
| // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #61. |
| // CHECK-NEXT: %8 = load %3 : $*Builtin.NativeObject |
| // CHECK-NEXT: %9 = apply %7(%8) : $@convention(thin) (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 |
| %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: MustAlias |
| 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 |
| 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: MustAlias |
| // 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 |
| %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 |
| %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: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: %1 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #2. |
| // CHECK-NEXT: %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: %2 = struct_element_addr %1 : $*Int32, #Int32._value |
| // CHECK-NEXT: PartialAlias |
| 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 { |
| @sil_stored final var a: Int { get set } |
| @sil_stored 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{{.*}} // user: %1 |
| // CHECK-NEXT: %0 = alloc_ref $C{{.*}} // user: %1 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: %0 = alloc_ref $C{{.*}} // user: %1 |
| // CHECK-NEXT: %1 = ref_element_addr %0 : $C, #C.a |
| // CHECK-NEXT: PartialAlias |
| sil @ref_element_addr_and_object_itself : $@convention(thin) () -> () { |
| bb0: |
| %0 = alloc_ref $C |
| %1 = ref_element_addr %0 : $C, #C.a |
| %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 |
| return %2 : $Int |
| } |
| |
| // CHECK-LABEL: @non_escaping_local_object_does_not_alias_with_unknown |
| // CHECK: PAIR #7. |
| // CHECK-NEXT: %1 = alloc_ref $X{{.*}} // user: %3 |
| // CHECK-NEXT: %3 = apply %2(%1) : $@convention(thin) (X) -> X |
| // CHECK-NEXT: NoAlias |
| sil @non_escaping_local_object_does_not_alias_with_unknown : $@convention(thin) (X) -> () { |
| bb0(%0 : $X): |
| %1 = alloc_ref $X |
| |
| %f = function_ref @not_escaping : $@convention(thin) (X) -> X |
| %2 = apply %f(%1) : $@convention(thin) (X) -> X |
| |
| %12 = tuple() |
| return %12 : $() |
| } |
| |
| 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{{.*}} // users: %2, %1 |
| // CHECK-NEXT: %1 = unchecked_addr_cast %0 : $*C to $*Optional<C> |
| // CHECK-NEXT: MayAlias |
| sil @alloc_stack_and_addr_cast : $@convention(thin) () -> () { |
| bb0: |
| %0 = alloc_stack $C |
| %1 = unchecked_addr_cast %0 : $*C to $*Optional<C> |
| dealloc_stack %0 : $*C |
| %2 = tuple() |
| return %2 : $() |
| } |