| // RUN: %target-sil-opt %s -aa=basic-aa -aa-dump -o /dev/null | FileCheck %s |
| |
| // REQUIRES: asserts |
| |
| import Builtin |
| import Swift |
| |
| // 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 |
| |
| // @local_storage cannot alias non @local_storage types. |
| // CHECK: PAIR #0. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #2. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #3. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #4. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #14. |
| // CHECK-NEXT: (0): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %14 = tuple () |
| // CHECK-NEXT: MayAlias |
| |
| // CHECK: PAIR #15. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #16. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #17. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #18. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #19. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %3 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.x |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #20. |
| // CHECK-NEXT: (1): %0 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup |
| // CHECK-NEXT: PartialAlias |
| |
| // CHECK: PAIR #50. |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %9 = struct_element_addr %7 : $*StructLvl2, #StructLvl2.tup |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #51. |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %10 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 0 |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #52. |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %11 = tuple_element_addr %9 : $*(Builtin.Int64, Builtin.Int32), 1 |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #53. |
| // CHECK-NEXT: (1): %1 = alloc_stack $StructLvl1 |
| // CHECK-NEXT: (0): %14 = tuple () |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #55. |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: (0): %3 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.x |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #56. |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: (0): %4 = struct_element_addr %2 : $*StructLvl2, #StructLvl2.tup |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #57. |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: (0): %5 = tuple_element_addr %4 : $*(Builtin.Int64, Builtin.Int32), 0 |
| // CHECK-NEXT: PartialAlias |
| // CHECK: PAIR #58. |
| // CHECK-NEXT: (0): %2 = struct_element_addr %0#1 : $*StructLvl1, #StructLvl1.sub |
| // CHECK-NEXT: (0): %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#1 : $*StructLvl1, #StructLvl1.sub |
| %3 = struct_element_addr %0#1 : $*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#1 : $*StructLvl1, #StructLvl1.sub |
| %8 = struct_element_addr %1#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#0 : $*@local_storage StructLvl1 |
| dealloc_stack %0#0 : $*@local_storage StructLvl1 |
| |
| %12 = tuple() |
| return %12 : $() |
| } |
| |
| // Function Arguments cannot alias with no alias arguments or with identified |
| // function locals. |
| // |
| // @args_dont_alias_with_identified_function_locals |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: (0): %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #2. |
| // CHECK-NEXT: (0): %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %2 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #3. |
| // CHECK-NEXT: (0): %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #4. |
| // CHECK-NEXT: (0): %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #5. |
| // CHECK-NEXT: (0): %0 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %5 = tuple () |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #7. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %2 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #8. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #9. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #12. |
| // CHECK-NEXT: (0): %2 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #13. |
| // CHECK-NEXT: (0): %2 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK-NEXT: (1): %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#0 : $*@local_storage 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. |
| |
| // @escapesource_functionlocal_test_readwrite_nonescaping_alloca |
| // Test %0 |
| |
| // CHECK: PAIR #1. |
| // CHECK: (0): %0 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #3. |
| // CHECK: (0): %0 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #5. |
| // CHECK: (0): %0 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #7. |
| // CHECK: (0): %0 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #10. |
| // CHECK: (0): %0 = argument of bb0 : $*Builtin.NativeObject |
| // CHECK: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK: NoAlias |
| |
| // Test %1 (the aliasing argument) |
| |
| // CHECK: PAIR #13. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #14. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #15. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #16. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #17. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #19. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #20. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %6 = load %0 : $*Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #22. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #23. |
| // CHECK-NEXT: (0): %1 = argument of bb0 : $Builtin.NativeObject |
| // CHECK-NEXT: (0): %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| // CHECK-NEXT: MayAlias |
| |
| // Test %2 |
| // CHECK: PAIR #38. |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #40. |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #41. |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: (0): %6 = load %0 : $*Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #43. |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK: NoAlias |
| // CHECK: PAIR #44. |
| // CHECK: (1): %2 = alloc_stack $Builtin.NativeObject |
| // CHECK: (0): %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| // CHECK: NoAlias |
| |
| // Test %3 (the escaping alloca). |
| |
| // CHECK: PAIR #49. |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #50. |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %6 = load %0 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #52. |
| // CHECK-NEXT: (0): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #57. |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #58. |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %6 = load %0 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #60. |
| // CHECK-NEXT: (1): %3 = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: NoAlias |
| |
| // Test %5 (the read write apply inst). |
| |
| // CHECK: PAIR #70. |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #71. |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: (0): %6 = load %0 : $*Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #72. |
| // CHECK-NEXT: (0): %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 #73. |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: MayAlias |
| // CHECK: PAIR #74. |
| // CHECK-NEXT: (0): %5 = apply %4() : $@convention(thin) () -> Builtin.NativeObject |
| // CHECK-NEXT: (0): %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| // CHECK-NEXT: MayAlias |
| |
| // Test %8 (the escaping load) |
| |
| // CHECK: PAIR #85. |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #86. |
| // CHECK-NEXT: (0): %8 = load %3#1 : $*Builtin.NativeObject |
| // CHECK-NEXT: (0): %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#1 : $*Builtin.NativeObject |
| %9 = apply %7(%8) : $@convention(thin) (Builtin.NativeObject) -> () |
| dealloc_stack %3#0 : $*@local_storage Builtin.NativeObject |
| dealloc_stack %2#0 : $*@local_storage Builtin.NativeObject |
| %12 = tuple () |
| return %12 : $() |
| } |
| |
| // CHECK-LABEL: @projections_from_the_same_source_with_the_same_projection_path_mustalias |
| // CHECK: PAIR #33. |
| // CHECK-NEXT: (0): %3 = tuple_element_addr %2 : $*(Builtin.Int64, Builtin.Int32), 1 |
| // CHECK-NEXT: (0): %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#1 : $*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#1 : $*StructLvl1, #StructLvl1.sub |
| %5 = struct_element_addr %4 : $*StructLvl2, #StructLvl2.tup |
| %6 = tuple_element_addr %5 : $*(Builtin.Int64, Builtin.Int32), 1 |
| dealloc_stack %0#0 : $*@local_storage 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): %0 = global_addr @sil_global1 : $*Builtin.Int32 |
| // CHECK-NEXT: (0): %0 = global_addr @sil_global1 : $*Builtin.Int32 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: (0): %0 = global_addr @sil_global1 : $*Builtin.Int32 |
| // CHECK-NEXT: (0): %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): %0 = global_addr @sil_global1 : $*Builtin.Int32 |
| // CHECK-NEXT: (0): %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): %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: (0): %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: (0): %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: (0): %1 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #2. |
| // CHECK-NEXT: (0): %0 = global_addr @sil_global3 : $*Int32 |
| // CHECK-NEXT: (0): %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: (0): %5 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.current |
| // CHECK-NEXT: (0): %7 = ref_element_addr %4 : $HalfOpenRange, #HalfOpenRange.end |
| // CHECK-NEXT: NoAlias |
| // CHECK: PAIR #64. |
| // CHECK-NEXT: (0): %9 = struct_element_addr %5 : $*Int32, #Int32._value |
| // CHECK-NEXT: (0): %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): %0 = alloc_ref $C // user: %1 |
| // CHECK-NEXT: (0): %0 = alloc_ref $C // user: %1 |
| // CHECK-NEXT: MustAlias |
| // CHECK: PAIR #1. |
| // CHECK-NEXT: (0): %0 = alloc_ref $C // user: %1 |
| // CHECK-NEXT: (0): %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: (0): %3 = ref_element_addr %0 : $C, #C.a |
| // CHECK-NEXT: (0): %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: (0): %1 = alloc_ref $X // user: %3 |
| // CHECK-NEXT: (0): %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 #5. |
| // CHECK-NEXT: (1): %0 = alloc_stack $C // users: %1, %2 |
| // CHECK-NEXT: (0): %1 = unchecked_addr_cast %0#1 : $*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#1 : $*C to $*Optional<C> |
| dealloc_stack %0#0 : $*@local_storage C |
| %2 = tuple() |
| return %2 : $() |
| } |