Files
swift-mirror/validation-test/SILOptimizer/rdar172670647.swift
Meghana Gupta 8b3f775673 COWOpts: Don't look through struct_extract/destructure_struct for multi-field structs
`LifetimeDependenceScopeFixup` can insert `end_cow_mutation_addr` on a struct address containing multiple COW fields, `SimplifyEndCOWMutationAddr` lowers it to an `end_cow_mutation` on the struct.

`skipStructAndExtract()` in COWOpts was unconditionally looking through `struct_extract` and `destructure_struct` instructions when tracing from `begin_cow_mutation` back to `end_cow_mutation`.

COWOpts would then trace from a `begin_cow_mutation` on one field, through `struct_extract`, to the `end_cow_mutation` on the `struct` that was placed for a different field's mutation. This caused COWOpts to incorrectly conclude the
buffer was uniquely referenced and fold the uniqueness check to true, breaking COW semantics.

The fix restricts `skipStructAndExtract` to only look through `struct_extract` and `destructure_struct` when the struct type has exactly one stored property.

Resolves rdar://172670647
2026-03-24 13:10:33 -07:00

40 lines
698 B
Swift

// RUN: %target-run-simple-swift(-O)
// REQUIRES: executable_test
struct S {
var c: ContiguousArray<Int>
var a: ContiguousArray<UInt64>
var b: ContiguousArray<UInt64>
init(n: Int) {
c = .init(repeating: 0, count: n)
a = .init(repeating: 0, count: n)
b = .init(repeating: 0, count: n)
}
mutating func bump(n: Int) {
do {
var s = a.mutableSpan
for i in 0 ..< n { s[i] &+= 1 }
}
do {
var s = b.mutableSpan
for i in 0 ..< n { s[i] &+= 1 }
}
}
}
@inline(never)
func run() -> (UInt64, UInt64) {
var x = S(n: 3)
let snapshot = Array(x.b)
x.bump(n: 3)
return (x.b[0], snapshot[0])
}
let (a, b) = run()
precondition(a != b)