Skip to content

Commit 537ea4b

Browse files
committed
Update BitwiseCopyable versions of subscript for MutableSpan and OutputSpan
Also move all bounds checking within @_semantics annotated function for MutableSpan and OutputSpan Eliminating unsafe addressors for BitwiseCopyable to get better bounds optimizations in SIL
1 parent 2365d12 commit 537ea4b

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

stdlib/public/core/Span/MutableSpan.swift

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,38 @@ extension MutableSpan where Element: BitwiseCopyable {
170170
}
171171
}
172172

173+
@available(SwiftCompatibilitySpan 5.0, *)
174+
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
175+
extension MutableSpan where Element: BitwiseCopyable {
176+
@_alwaysEmitIntoClient
177+
public subscript(_ position: Index) -> Element {
178+
get {
179+
_checkIndex(position)
180+
return unsafe self[unchecked: position]
181+
}
182+
@lifetime(self: copy self)
183+
set {
184+
_checkIndex(position)
185+
self[unchecked: position] = newValue
186+
}
187+
}
188+
189+
@unsafe
190+
@_alwaysEmitIntoClient
191+
public subscript(unchecked position: Index) -> Element {
192+
get {
193+
let elementOffset = position &* MemoryLayout<Element>.stride
194+
let address = unsafe _start().advanced(by: elementOffset)
195+
return unsafe address.loadUnaligned(as: Element.self)
196+
}
197+
@lifetime(self: copy self)
198+
set {
199+
let elementOffset = position &* MemoryLayout<Element>.stride
200+
_start().storeBytes(of: newValue, toByteOffset: elementOffset, as: Element.self)
201+
}
202+
}
203+
}
204+
173205
@available(SwiftCompatibilitySpan 5.0, *)
174206
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
175207
extension Span where Element: ~Copyable {
@@ -236,6 +268,7 @@ extension MutableSpan where Element: ~Copyable {
236268
extension MutableSpan where Element: ~Copyable {
237269

238270
@_alwaysEmitIntoClient
271+
@_semantics("fixed_storage.get_count")
239272
public var count: Int { _assumeNonNegative(_count) }
240273

241274
@_alwaysEmitIntoClient
@@ -279,7 +312,13 @@ extension MutableSpan where Element: BitwiseCopyable {
279312
@available(SwiftCompatibilitySpan 5.0, *)
280313
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
281314
extension MutableSpan where Element: ~Copyable {
282-
315+
// SILOptimizer looks for fixed_storage.check_index semantics for bounds check optimizations.
316+
@_semantics("fixed_storage.check_index")
317+
@inline(__always)
318+
@_alwaysEmitIntoClient
319+
internal func _checkIndex(_ position: Index) {
320+
_precondition(indices.contains(position), "index out of bounds")
321+
}
283322
/// Accesses the element at the specified position in the `MutableSpan`.
284323
///
285324
/// - Parameter position: The offset of the element to access. `position`
@@ -289,12 +328,12 @@ extension MutableSpan where Element: ~Copyable {
289328
@_alwaysEmitIntoClient
290329
public subscript(_ position: Index) -> Element {
291330
unsafeAddress {
292-
_precondition(indices.contains(position), "index out of bounds")
331+
_checkIndex(position)
293332
return unsafe UnsafePointer(_unsafeAddressOfElement(unchecked: position))
294333
}
295334
@lifetime(self: copy self)
296335
unsafeMutableAddress {
297-
_precondition(indices.contains(position), "index out of bounds")
336+
_checkIndex(position)
298337
return unsafe _unsafeAddressOfElement(unchecked: position)
299338
}
300339
}

stdlib/public/core/Span/OutputSpan.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ extension OutputSpan where Element: ~Copyable {
193193
unsafe Range(_uncheckedBounds: (0, _count))
194194
}
195195

196+
// SILOptimizer looks for fixed_storage.check_index semantics for bounds check optimizations.
197+
@_semantics("fixed_storage.check_index")
198+
@inline(__always)
199+
@_alwaysEmitIntoClient
200+
internal func _checkIndex(_ index: Index) {
201+
_precondition(indices.contains(index), "Index out of bounds")
202+
}
203+
196204
/// Accesses the element at the specified position.
197205
///
198206
/// - Parameter index: A valid index into this span.
@@ -201,12 +209,12 @@ extension OutputSpan where Element: ~Copyable {
201209
@_alwaysEmitIntoClient
202210
public subscript(_ index: Index) -> Element {
203211
unsafeAddress {
204-
_precondition(indices.contains(index), "index out of bounds")
212+
_checkIndex(index)
205213
return unsafe UnsafePointer(_unsafeAddressOfElement(unchecked: index))
206214
}
207215
@lifetime(self: copy self)
208216
unsafeMutableAddress {
209-
_precondition(indices.contains(index), "index out of bounds")
217+
_checkIndex(index)
210218
return unsafe _unsafeAddressOfElement(unchecked: index)
211219
}
212220
}

stdlib/public/core/Span/Span.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ extension Span where Element: ~Copyable {
414414
@available(SwiftCompatibilitySpan 5.0, *)
415415
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
416416
extension Span where Element: ~Copyable {
417+
// SILOptimizer looks for fixed_storage.check_index semantics for bounds check optimizations.
417418
@_semantics("fixed_storage.check_index")
418419
@inline(__always)
419420
@_alwaysEmitIntoClient

0 commit comments

Comments
 (0)