Skip to content

Commit 058d22b

Browse files
committed
Fix LifetimeDependenceScopeFixup for loops.
Handle situations in which the uses of the new scope are inside a loop so the new range has no end instructions.
1 parent f3cf529 commit 058d22b

File tree

2 files changed

+60
-12
lines changed

2 files changed

+60
-12
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ private func extendAccessScope(beginAccess: BeginAccessInst, range: inout Instru
149149
if !requiresExtension {
150150
return nil
151151
}
152-
assert(!range.ends.isEmpty)
153-
154152
// Create new end_access at the end of extended uses
155153
var dependsOnCaller = false
156154
for end in range.ends {
@@ -167,6 +165,11 @@ private func extendAccessScope(beginAccess: BeginAccessInst, range: inout Instru
167165
range.insert(endAccess)
168166
}
169167
}
168+
for exitInst in range.exits {
169+
let location = exitInst.location.autoGenerated
170+
let endAccess = Builder(before: exitInst, location: location, context).createEndAccess(beginAccess: beginAccess)
171+
range.insert(endAccess)
172+
}
170173
// Delete original end_access instructions
171174
for endAccess in endAcceses {
172175
context.erase(instruction: endAccess)

test/SILOptimizer/lifetime_dependence/lifetime_dependence_mutate.swift

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,83 @@
88
// REQUIRES: asserts
99
// REQUIRES: swift_in_compiler
1010

11-
struct MBV : ~Escapable, ~Copyable {
12-
let p: UnsafeMutableRawPointer
13-
let c: Int
11+
struct MutableSpan : ~Escapable, ~Copyable {
12+
let base: UnsafeMutableRawPointer
13+
let count: Int
1414

1515
init(_ p: UnsafeMutableRawPointer, _ c: Int) -> dependsOn(p) Self {
16-
self.p = p
17-
self.c = c
16+
self.base = p
17+
self.count = c
1818
}
1919

2020
subscript(position: Int) -> Int {
2121
get {
2222
let offset = position * MemoryLayout<Int>.stride
23-
return p.loadUnaligned(fromByteOffset: offset, as: Int.self)
23+
return base.loadUnaligned(fromByteOffset: offset, as: Int.self)
2424
}
2525
nonmutating set(newValue) {
2626
let offset = position * MemoryLayout<Int>.stride
27-
p.storeBytes(of: newValue, toByteOffset: offset,
27+
base.storeBytes(of: newValue, toByteOffset: offset,
2828
as: Int.self)
2929
}
3030
}
31+
32+
struct Iter: ~Escapable {
33+
var base: UnsafeMutableRawPointer
34+
var count: Int
35+
36+
init(base: UnsafeMutableRawPointer, count: Int) -> dependsOn(base) Self {
37+
self.base = base
38+
self.count = count
39+
}
40+
41+
mutating func next() -> Int? {
42+
guard count > 0 else { return nil }
43+
count -= 1
44+
let n = base.load(as: Int.self)
45+
base = base + MemoryLayout<Int>.stride
46+
return n
47+
}
48+
}
49+
50+
var iterator: Iter { Iter(base: base, count: count) }
51+
}
52+
53+
extension Array where Element == Int {
54+
// TODO: comment out dependsOn(scoped)
55+
mutating func mutspan() -> /* dependsOn(scoped self) */ MutableSpan {
56+
/* not the real implementation */
57+
let p = self.withUnsafeMutableBufferPointer { $0.baseAddress! }
58+
return MutableSpan(p, count)
59+
}
3160
}
3261

3362
struct NC : ~Copyable {
3463
let p: UnsafeMutableRawPointer
3564
let c: Int
3665

3766
// Requires a mutable borrow.
38-
mutating func getMBV() -> dependsOn(self) MBV {
39-
MBV(p, c)
67+
mutating func getMutableSpan() -> dependsOn(self) MutableSpan {
68+
MutableSpan(p, c)
4069
}
4170
}
4271

4372
func mbv_set_element(nc: inout NC, e: Int) {
44-
nc.getMBV()[3] = e
73+
nc.getMutableSpan()[3] = e
74+
}
75+
76+
func test_mutate_iterate() {
77+
var array = [1,2,3]
78+
// mutable 'array' access
79+
let mutatingSpan = array.mutspan()
80+
var iterator = mutatingSpan.iterator
81+
var i = 0
82+
while let n = iterator.next() {
83+
_ = n
84+
if i < mutatingSpan.count {
85+
mutatingSpan[i+1] = mutatingSpan[i]
86+
i += 1
87+
}
88+
}
89+
// end mutable 'array' access
4590
}

0 commit comments

Comments
 (0)