Skip to content

Commit 827c30f

Browse files
authored
Merge pull request #85482 from meg-gupta/reduceendcowmutation
Avoid inserting end_cow_mutation_addr in some common cases
2 parents 7f2f3ea + 404173d commit 827c30f

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ let lifetimeDependenceScopeFixupPass = FunctionPass(
142142

143143
private extension Type {
144144
func mayHaveMutableSpan(in function: Function, _ context: FunctionPassContext) -> Bool {
145+
// Escapable and Copyable types cannot have MutableSpan
146+
if isEscapable || !isMoveOnly {
147+
return false
148+
}
145149
if hasArchetype {
146150
return true
147151
}
@@ -176,6 +180,24 @@ private extension Type {
176180
}
177181
return false
178182
}
183+
184+
// Returns true if a type maybe Array/ArraySlice/ContiguousArray which are optimized COW types.
185+
// The standard library introduces builtins begin_cow_mutation/end_cow_mutation for such types which are then used to optimize uniqueness checks.
186+
func mayHaveOptimizedCOWType(in function: Function) -> Bool {
187+
// Trivial types cannot be Array/ArraySlice/ContiguousArray.
188+
if isTrivial(in: function) {
189+
return false
190+
}
191+
// Builtin types do not contain Array/ArraySlice/ContiguousArray.
192+
if isBuiltinType {
193+
return false
194+
}
195+
// ~Copyable types cannot contain Array/ArraySlice/ContiguousArray.
196+
if isMoveOnly {
197+
return false
198+
}
199+
return true
200+
}
179201
}
180202

181203
/// Insert end_cow_mutation_addr for lifetime dependent values that maybe of type MutableSpan and depend on a mutable address.
@@ -203,7 +225,8 @@ private func createEndCOWMutationIfNeeded(lifetimeDep: LifetimeDependence, _ con
203225
return
204226
}
205227

206-
guard lifetimeDep.dependentValue.type.mayHaveMutableSpan(in: lifetimeDep.dependentValue.parentFunction, context) else {
228+
guard lifetimeDep.dependentValue.type.mayHaveMutableSpan(in: lifetimeDep.dependentValue.parentFunction, context) &&
229+
lifetimeDep.parentValue.type.mayHaveOptimizedCOWType(in: lifetimeDep.dependentValue.parentFunction) else {
207230
return
208231
}
209232

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-frontend -O -emit-sil %s -disable-availability-checking | %FileCheck %s --check-prefix=CHECK-SIL
2+
3+
public protocol P {
4+
mutating func mutate(_ other: Self)
5+
}
6+
7+
// CHECK-SIL-LABEL: sil @$s38mutable_span_stdlib_bounds_check_tests0a1_B7_doubleyys11MutableSpanVyxGzAA1PRzlF :
8+
// CHECK-SIL: bb3({{.*}}):
9+
// CHECK-SIL-NOT: end_cow_mutation
10+
// CHECK-SIL-NOT: cond_fail "index out of bounds"
11+
// CHECK-SIL-LABEL: } // end sil function '$s38mutable_span_stdlib_bounds_check_tests0a1_B7_doubleyys11MutableSpanVyxGzAA1PRzlF'
12+
public func mutable_span_double<T: P>(_ ms: inout MutableSpan<T>) {
13+
for i in ms.indices {
14+
ms[i].mutate(ms[i])
15+
}
16+
}
17+
18+
extension Int : P {
19+
public mutating func mutate(_ other: Int) {
20+
self += other
21+
}
22+
}
23+
24+
// CHECK-SIL-LABEL: sil @$s38mutable_span_stdlib_bounds_check_tests17specializedCalleryySaySiGzF : $@convention(thin) (@inout Array<Int>) -> () {
25+
// CHECK-SIL-NOT: cond_fail "index out of bounds"
26+
// CHECK-SIL-LABEL: } // end sil function '$s38mutable_span_stdlib_bounds_check_tests17specializedCalleryySaySiGzF'
27+
public func specializedCaller(_ array: inout Array<Int>) {
28+
var mut = array.mutableSpan
29+
mutable_span_double(&mut)
30+
}
31+

0 commit comments

Comments
 (0)