Skip to content

Commit fa952d3

Browse files
authored
Merge pull request swiftlang#22338 from atrick/speedup-ubp-subscript
Remove useless optional unwrap from Unsafe[Raw]BufferPointer subscript.
2 parents 38e5c8a + a557976 commit fa952d3

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,18 +270,19 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
270270
get {
271271
_debugPrecondition(i >= 0)
272272
_debugPrecondition(i < endIndex)
273-
return _position![i]
273+
return _position._unsafelyUnwrappedUnchecked[i]
274274
}
275275
%if Mutable:
276276
nonmutating _modify {
277277
_debugPrecondition(i >= 0)
278278
_debugPrecondition(i < endIndex)
279-
yield &_position![i]
279+
yield &_position._unsafelyUnwrappedUnchecked[i]
280280
}
281281
%end
282282
}
283283

284284
// Skip all debug and runtime checks
285+
285286
@inlinable // unsafe-performance
286287
internal subscript(_unchecked i: Int) -> Element {
287288
get {

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
185185
get {
186186
_debugPrecondition(i >= 0)
187187
_debugPrecondition(i < endIndex)
188-
return _position!.load(fromByteOffset: i, as: UInt8.self)
188+
return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self)
189189
}
190190
% if mutable:
191191
nonmutating set {
192192
_debugPrecondition(i >= 0)
193193
_debugPrecondition(i < endIndex)
194-
_position!.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self)
194+
_position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self)
195195
}
196196
% end # mutable
197197
}

test/SILOptimizer/unsafebufferpointer.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,52 @@ public func testCount(_ x: UnsafeBufferPointer<UInt>) -> Int {
4545
return x.count
4646
}
4747

48+
// Within the loop, there should be no extra checks.
49+
// CHECK-LABEL: define {{.*}} float {{.*}}testSubscript
50+
// The only unconditional branch is into the loop.
51+
// CHECK: br label %[[LOOP:[0-9]+]]
52+
//
53+
// For some reason, LLVM lays out the exit before the loop.
54+
// CHECK: .loopexit: ; preds = %[[LOOP]]
55+
// CHECK: ret float
56+
//
57+
// CHECK: ; <label>:[[LOOP]]:
58+
// CHECK: phi float [ 0.000000e+00
59+
// CHECK: add nuw i64 %{{.*}}, 1
60+
// CHECK: load float, float*
61+
// CHECK: fadd float
62+
// CHECK: [[CMP:%[0-9]+]] = icmp eq i64 %{{.*}}, %{{.*}}
63+
// CHECK: br i1 [[CMP]], label %.loopexit, label %[[LOOP]]
64+
public func testSubscript(_ ubp: UnsafeBufferPointer<Float>) -> Float {
65+
var sum: Float = 0
66+
for i in 0 ..< ubp.count {
67+
sum += ubp[i]
68+
}
69+
return sum
70+
}
71+
72+
// Within the loop, there should be no extra checks.
73+
// CHECK-LABEL: define {{.*}} i64 {{.*}}testSubscript
74+
// The only unconditional branch is into the loop.
75+
// CHECK: br label %[[LOOP:[0-9]+]]
76+
//
77+
// For some reason, LLVM lays out the exit before the loop.
78+
// CHECK: [[RET:.*]]: ; preds = %[[LOOP]], %entry
79+
// CHECK: ret i64
80+
//
81+
// CHECK: ; <label>:[[LOOP]]:
82+
// CHECK: phi i64 [ 0
83+
// CHECK: phi i64 [ 0
84+
// CHECK: add nuw i64 %{{.*}}, 1
85+
// CHECK: load i8, i8*
86+
// CHECK: zext i8 %{{.*}} to i64
87+
// CHECK: add i64
88+
// CHECK: [[CMP:%[0-9]+]] = icmp eq i64 %{{.*}}, %{{.*}}
89+
// CHECK: br i1 [[CMP]], label %[[RET]], label %[[LOOP]]
90+
public func testSubscript(_ ubp: UnsafeRawBufferPointer) -> Int {
91+
var sum: Int = 0
92+
for i in 0 ..< ubp.count {
93+
sum &+= Int(ubp[i])
94+
}
95+
return sum
96+
}

0 commit comments

Comments
 (0)