Skip to content

Commit 8507c5a

Browse files
committed
Avoid inserting end_cow_mutation_addr in some common cases
1 parent 0d0c1d5 commit 8507c5a

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,24 @@ private extension Type {
176176
}
177177
return false
178178
}
179+
180+
// Returns true if a type maybe Array/ArraySlice/ContiguousArray which are optimized COW types.
181+
// The standard library introduces builtins begin_cow_mutation/end_cow_mutation for such types which are then used to optimize uniqueness checks.
182+
func mayHaveOptimizedCOWType(in function: Function) -> Bool {
183+
// Trivial types cannot be Array/ArraySlice/ContiguousArray.
184+
if isTrivial(in: function) {
185+
return false
186+
}
187+
// Builtin types do not contain Array/ArraySlice/ContiguousArray.
188+
if isBuiltinType {
189+
return false
190+
}
191+
// ~Copyable types cannot contain Array/ArraySlice/ContiguousArray.
192+
if isMoveOnly {
193+
return false
194+
}
195+
return true
196+
}
179197
}
180198

181199
/// Insert end_cow_mutation_addr for lifetime dependent values that maybe of type MutableSpan and depend on a mutable address.
@@ -203,7 +221,8 @@ private func createEndCOWMutationIfNeeded(lifetimeDep: LifetimeDependence, _ con
203221
return
204222
}
205223

206-
guard lifetimeDep.dependentValue.type.mayHaveMutableSpan(in: lifetimeDep.dependentValue.parentFunction, context) else {
224+
guard lifetimeDep.dependentValue.type.mayHaveMutableSpan(in: lifetimeDep.dependentValue.parentFunction, context) &&
225+
lifetimeDep.parentValue.type.mayHaveOptimizedCOWType(in: lifetimeDep.dependentValue.parentFunction) else {
207226
return
208227
}
209228

test/SILOptimizer/mutable_span_bounds_check_tests.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,9 @@ public protocol P {
175175
mutating func mutate(_ other: Self)
176176
}
177177

178-
// TODO: Ensure end_cow_mutation_addr is not inserted within the loop
179-
// This happens because MutableSpan's subscript is implemented with unsafe addressors which introduce mark_dependence [unresolved].
180-
// This triggers lifetime-dependence-scope-fixup which unnecessarily inserts end_cow_mutation_addr due to the conservative analysis of `mayHaveMutableSpan` on generic types.
181-
// TODO: Improve `mayHaveMutableSpan` to avoid this.
182178
// CHECK-LABEL: sil @$s31mutable_span_bounds_check_tests0a1_B7_doubleyys11MutableSpanVyxGzAA1PRzlF :
183179
// CHECK-SIL: bb3({{.*}}):
184-
// TODO-CHECK-NOT: end_cow_mutation
180+
// CHECK-NOT: end_cow_mutation
185181
// CHECK-LABEL: } // end sil function '$s31mutable_span_bounds_check_tests0a1_B7_doubleyys11MutableSpanVyxGzAA1PRzlF'
186182
public func mutable_span_double<T: P>(_ ms: inout MutableSpan<T>) {
187183
for i in ms.indices {
@@ -225,6 +221,17 @@ extension Int : P {
225221
public func specializedCaller(_ array: inout Array<Int>) {
226222
var mut = array.mutableSpan
227223
mutable_span_double_bitwisecopyable(&mut)
224+
mutable_span_double(&mut)
225+
}
226+
227+
// CHECK-LABEL: sil @$s31mutable_span_bounds_check_tests07output_B9_init_allyys10OutputSpanVyxGz_xtAA1PRzlF :
228+
// CHECK-SIL: bb3({{.*}}):
229+
// CHECK-NOT: end_cow_mutation
230+
// CHECK-LABEL: } // end sil function '$s31mutable_span_bounds_check_tests07output_B9_init_allyys10OutputSpanVyxGz_xtAA1PRzlF'
231+
public func output_span_init_all<T: P>(_ os: inout OutputSpan<T>, _ value: T) {
232+
for i in os.indices {
233+
os[i] = value
234+
}
228235
}
229236

230237
// CHECK-LABEL: sil @$s31mutable_span_bounds_check_tests07output_B25_init_all_bitwisecopyableyys10OutputSpanVyxGz_xts15BitwiseCopyableRzAA1PRzlF :

0 commit comments

Comments
 (0)