mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Which consists of * removing redundant `address_to_pointer`-`pointer_to_address` pairs * optimize `index_raw_pointer` of a manually computed stride to `index_addr` * remove or increase the alignment based on a "assumeAlignment" builtin This is a big code cleanup but also has some functional differences for the `address_to_pointer`-`pointer_to_address` pair removal: * It's not done if the resulting SIL would result in a (detectable) use-after-dealloc_stack memory lifetime failure. * It's not done if `copy_value`s must be inserted or borrow-scopes must be extended to comply with ownership rules (this was the task of the OwnershipRAUWHelper). Inserting copies is bad anyway. Extending borrow-scopes would only be required if the original lifetime of the pointer extends a borrow scope - which shouldn't happen in save code. Therefore this is a very rare case which is not worth handling.
272 lines
10 KiB
Plaintext
272 lines
10 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -onone-simplification -simplify-instruction=pointer_to_address | %FileCheck %s
|
|
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
class C {}
|
|
|
|
// CHECK-LABEL: sil @remove_conversion :
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK: [[L:%.*]] = load %0
|
|
// CHECK: return [[L]]
|
|
// CHECK: } // end sil function 'remove_conversion'
|
|
sil @remove_conversion : $@convention(thin) (@in Int) -> Int {
|
|
bb0(%0 : $*Int):
|
|
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Int
|
|
%3 = load %2 : $*Int
|
|
return %3 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil @mismatching_type :
|
|
// CHECK: %1 = unchecked_addr_cast %0
|
|
// CHECK: %2 = load %1
|
|
// CHECK: return %2
|
|
// CHECK: } // end sil function 'mismatching_type'
|
|
sil @mismatching_type : $@convention(thin) (@in Int) -> Bool {
|
|
bb0(%0 : $*Int):
|
|
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*Bool
|
|
%3 = load %2 : $*Bool
|
|
return %3 : $Bool
|
|
}
|
|
|
|
// CHECK-LABEL: sil @no_strict :
|
|
// CHECK: address_to_pointer
|
|
// CHECK: [[A:%.*]] = pointer_to_address
|
|
// CHECK: [[L:%.*]] = load [[A]]
|
|
// CHECK: return [[L]]
|
|
// CHECK: } // end sil function 'no_strict'
|
|
sil @no_strict : $@convention(thin) (@in Int) -> Int {
|
|
bb0(%0 : $*Int):
|
|
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to $*Int
|
|
%3 = load %2 : $*Int
|
|
return %3 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @borrow_escape :
|
|
// CHECK: address_to_pointer
|
|
// CHECK: [[A:%.*]] = pointer_to_address
|
|
// CHECK: [[L:%.*]] = load [trivial] [[A]]
|
|
// CHECK: return [[L]]
|
|
// CHECK: } // end sil function 'borrow_escape'
|
|
sil [ossa] @borrow_escape : $@convention(thin) (@guaranteed C) -> Int {
|
|
bb0(%0 : @guaranteed $C):
|
|
%1 = begin_borrow %0 : $C
|
|
%2 = ref_tail_addr %1: $C, $Int
|
|
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
|
|
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int
|
|
end_borrow %1 : $C
|
|
%6 = load [trivial] %5 : $*Int
|
|
return %6 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @borrow_no_escape :
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK: } // end sil function 'borrow_no_escape'
|
|
sil [ossa] @borrow_no_escape : $@convention(thin) (@guaranteed C) -> Int {
|
|
bb0(%0 : @guaranteed $C):
|
|
%1 = begin_borrow %0 : $C
|
|
%2 = ref_tail_addr %1: $C, $Int
|
|
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
|
|
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int
|
|
%6 = load [trivial] %5 : $*Int
|
|
end_borrow %1 : $C
|
|
return %6 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @stack_escape :
|
|
// CHECK: address_to_pointer
|
|
// CHECK: %4 = pointer_to_address
|
|
// CHECK: load [trivial] %4
|
|
// CHECK: } // end sil function 'stack_escape'
|
|
sil [ossa] @stack_escape : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_stack $Int
|
|
store %0 to [trivial] %1
|
|
%3 = address_to_pointer %1 to $Builtin.RawPointer
|
|
%4 = pointer_to_address %3 to [strict] $*Int
|
|
dealloc_stack %1
|
|
%6 = load [trivial] %4 : $*Int
|
|
return %6 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @stack_no_escape :
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK: load [trivial] %1
|
|
// CHECK: } // end sil function 'stack_no_escape'
|
|
sil [ossa] @stack_no_escape : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
%1 = alloc_stack $Int
|
|
store %0 to [trivial] %1
|
|
%3 = address_to_pointer %1 to $Builtin.RawPointer
|
|
%4 = pointer_to_address %3 to [strict] $*Int
|
|
%6 = load [trivial] %4 : $*Int
|
|
dealloc_stack %1
|
|
return %6 : $Int
|
|
}
|
|
|
|
sil @createC : $@convention(thin) () -> @owned C
|
|
|
|
// CHECK-LABEL: sil @non_ossa_local_ownership :
|
|
// CHECK: [[A:%.*]] = ref_tail_addr
|
|
// CHECK-NOT: address_to_pointer
|
|
// CHECK-NOT: pointer_to_address
|
|
// CHECK: [[L:%.*]] = load [[A]]
|
|
// CHECK: return [[L]]
|
|
// CHECK: } // end sil function 'non_ossa_local_ownership'
|
|
sil @non_ossa_local_ownership : $@convention(thin) () -> Int {
|
|
bb0:
|
|
%f = function_ref @createC : $@convention(thin) () -> @owned C
|
|
%0 = apply %f() : $@convention(thin) () -> @owned C
|
|
%2 = ref_tail_addr %0: $C, $Int
|
|
%3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
|
|
%5 = pointer_to_address %3 : $Builtin.RawPointer to [strict] $*Int
|
|
%6 = load %5 : $*Int
|
|
strong_release %0 : $C
|
|
return %6 : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @const_alignemnt :
|
|
// CHECK: pointer_to_address %1 to [align=8] $*T
|
|
// CHECK: } // end sil function 'const_alignemnt'
|
|
sil [ossa] @const_alignemnt : $@convention(thin) <T> (Builtin.RawPointer, @thick T.Type) -> @out T {
|
|
bb0(%0 : $*T, %1 : $Builtin.RawPointer, %2 : $@thick T.Type):
|
|
%3 = integer_literal $Builtin.Word, 8
|
|
%4 = builtin "assumeAlignment"(%1, %3) : $Builtin.RawPointer
|
|
%5 = pointer_to_address %4 to [align=1] $*T
|
|
copy_addr %5 to [init] %0
|
|
%10 = tuple ()
|
|
return %10
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @zero_alignemnt :
|
|
// CHECK: pointer_to_address %1 to $*T
|
|
// CHECK: } // end sil function 'zero_alignemnt'
|
|
sil [ossa] @zero_alignemnt : $@convention(thin) <T> (Builtin.RawPointer, @thick T.Type) -> @out T {
|
|
bb0(%0 : $*T, %1 : $Builtin.RawPointer, %2 : $@thick T.Type):
|
|
%3 = integer_literal $Builtin.Word, 0
|
|
%4 = builtin "assumeAlignment"(%1, %3) : $Builtin.RawPointer
|
|
%5 = pointer_to_address %4 to [align=1] $*T
|
|
copy_addr %5 to [init] %0
|
|
%10 = tuple ()
|
|
return %10
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @type_alignment :
|
|
// CHECK: pointer_to_address %1 to $*T
|
|
// CHECK: } // end sil function 'type_alignment'
|
|
sil [ossa] @type_alignment : $@convention(thin) <T> (Builtin.RawPointer, @thick T.Type) -> @out T {
|
|
bb0(%0 : $*T, %1 : $Builtin.RawPointer, %2 : $@thick T.Type):
|
|
%3 = metatype $@thick T.Type
|
|
%4 = builtin "alignof"<T>(%3) : $Builtin.Word
|
|
%5 = builtin "sextOrBitCast_Word_Int64"(%4) : $Builtin.Int64
|
|
%6 = builtin "truncOrBitCast_Int64_Word"(%5) : $Builtin.Word
|
|
%7 = builtin "assumeAlignment"(%1, %6) : $Builtin.RawPointer
|
|
%8 = pointer_to_address %7 to [align=1] $*T
|
|
copy_addr %8 to [init] %0
|
|
%10 = tuple ()
|
|
return %10
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr :
|
|
// CHECK: %2 = pointer_to_address %0
|
|
// CHECK-NEXT: %3 = index_addr %2, %1
|
|
// CHECK-NEXT: load [trivial] %3
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr'
|
|
sil [ossa] @indexrawpointer_to_indexaddr : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4, %1, %6) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7, 0
|
|
%9 = index_raw_pointer %0, %8
|
|
%10 = pointer_to_address %9 to [strict] $*Int8
|
|
%11 = load [trivial] %10
|
|
return %11
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_strideof :
|
|
// CHECK: %2 = pointer_to_address %0
|
|
// CHECK-NEXT: %3 = index_addr %2, %1
|
|
// CHECK-NEXT: load [trivial] %3
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_strideof'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_strideof : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int8 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4, %1, %6) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7, 0
|
|
%9 = index_raw_pointer %0, %8
|
|
%10 = pointer_to_address %9 to [strict] $*Int8
|
|
%11 = load [trivial] %10
|
|
return %11
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_mismatched_metatype :
|
|
// CHECK-NOT: index_addr
|
|
// CHECK: index_raw_pointer
|
|
// CHECK-NOT: index_addr
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_mismatched_metatype'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_mismatched_metatype : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Int32 {
|
|
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
|
|
%3 = metatype $@thick Int8.Type
|
|
%4 = builtin "strideof"<Int8>(%3) : $Builtin.Word
|
|
%6 = integer_literal $Builtin.Int1, -1
|
|
%7 = builtin "smul_with_overflow_Word"(%4, %1, %6) : $(Builtin.Word, Builtin.Int1)
|
|
%8 = tuple_extract %7, 0
|
|
%9 = index_raw_pointer %0, %8
|
|
%10 = pointer_to_address %9 to [strict] $*Int32
|
|
%11 = load [trivial] %10
|
|
return %11
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @indexrawpointer_to_indexaddr_with_casts :
|
|
// CHECK: %2 = pointer_to_address %0
|
|
// CHECK-NEXT: %3 = builtin "truncOrBitCast_Int64_Word"(%1)
|
|
// CHECK-NEXT: %4 = index_addr %2, %3
|
|
// CHECK-NEXT: load [trivial] %4
|
|
// CHECK: } // end sil function 'indexrawpointer_to_indexaddr_with_casts'
|
|
sil [ossa] @indexrawpointer_to_indexaddr_with_casts : $@convention(thin) (Builtin.RawPointer, Builtin.Int64) -> Int32 {
|
|
bb0(%0 : $Builtin.RawPointer, %1: $Builtin.Int64):
|
|
%2 = integer_literal $Builtin.Int1, -1
|
|
%3 = metatype $@thick Int32.Type
|
|
%4 = builtin "strideof"<Int32>(%3) : $Builtin.Word
|
|
%5 = builtin "zextOrBitCast_Word_Int64"(%4) : $Builtin.Int64
|
|
%6 = builtin "smul_with_overflow_Int64"(%1, %5, %2) : $(Builtin.Int64, Builtin.Int1)
|
|
%7 = tuple_extract %6, 0
|
|
%8 = builtin "truncOrBitCast_Int64_Word"(%7) : $Builtin.Word
|
|
%9 = index_raw_pointer %0, %8
|
|
%10 = pointer_to_address %9 to [strict] $*Int32
|
|
%11 = load [trivial] %10
|
|
return %11
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @unchecked_ownership_conversion :
|
|
// CHECK: %4 = ref_tail_addr
|
|
// CHECK-NEXT: %5 = load [trivial] %4
|
|
// CHECK: } // end sil function 'unchecked_ownership_conversion'
|
|
sil [ossa] @unchecked_ownership_conversion : $@convention(thin) (Unmanaged<C>) -> Int {
|
|
bb0(%0 : $Unmanaged<C>):
|
|
%1 = struct_extract %0, #Unmanaged._value
|
|
%2 = unmanaged_to_ref %1 to $C
|
|
%3 = unchecked_ownership_conversion %2, @unowned to @guaranteed
|
|
%4 = ref_tail_addr %3, $*Int
|
|
%5 = address_to_pointer %4 to $Builtin.RawPointer
|
|
%6 = pointer_to_address %5 to [strict] $*Int
|
|
%7 = load [trivial] %6
|
|
end_borrow %3
|
|
return %7
|
|
}
|