blob: e213d44c30559cb84423241e45f2da4815788dbf [file] [log] [blame]
// RUN: %target-sil-opt -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 {
@_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{{.*}} // 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 : $()
}