Skip to content

Commit b90b326

Browse files
authored
Merge pull request #70039 from eeckstein/fix-let-property-lowering
LetPropertyLowering: handle `store_borrow` and re-borrows
2 parents 2c43c27 + 6aaf200 commit b90b326

File tree

5 files changed

+98
-16
lines changed

5 files changed

+98
-16
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LetPropertyLowering.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ private func constructLetInitRegion(
135135
// root-class initializer).
136136
initRegion.insert(markUninitialized)
137137

138-
var beginBorrows = Stack<BeginBorrowInst>(context)
139-
defer { beginBorrows.deinitialize() }
138+
var borrows = Stack<BorrowIntroducingInstruction>(context)
139+
defer { borrows.deinitialize() }
140140

141141
for inst in markUninitialized.parentFunction.instructions {
142142
switch inst {
@@ -161,8 +161,13 @@ private func constructLetInitRegion(
161161
// Include let-field partial de-initializations in the region.
162162
initRegion.insert(inst)
163163

164-
case let beginBorrow as BeginBorrowInst:
165-
beginBorrows.append(beginBorrow)
164+
case let beginBorrow as BeginBorrowInst
165+
where beginBorrow.borrowedValue.referenceRoot == markUninitialized:
166+
borrows.append(beginBorrow)
167+
168+
case let storeBorrow as StoreBorrowInst
169+
where storeBorrow.source.referenceRoot == markUninitialized:
170+
borrows.append(storeBorrow)
166171

167172
default:
168173
break
@@ -171,8 +176,8 @@ private func constructLetInitRegion(
171176

172177
// Extend the region to whole borrow scopes to avoid that we insert an `end_init_let_ref` in the
173178
// middle of a borrow scope.
174-
for beginBorrow in beginBorrows where initRegion.contains(beginBorrow) {
175-
initRegion.insert(contentsOf: beginBorrow.endBorrows)
179+
for borrow in borrows where initRegion.contains(borrow) {
180+
initRegion.insert(borrowScopeOf: borrow, context)
176181
}
177182
}
178183

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,3 +532,25 @@ extension GlobalVariable {
532532
}
533533
}
534534
}
535+
536+
extension InstructionRange {
537+
/// Adds the instruction range of a borrow-scope by transitively visiting all (potential) re-borrows.
538+
mutating func insert(borrowScopeOf borrow: BorrowIntroducingInstruction, _ context: some Context) {
539+
var worklist = ValueWorklist(context)
540+
defer { worklist.deinitialize() }
541+
542+
worklist.pushIfNotVisited(borrow)
543+
while let value = worklist.pop() {
544+
for use in value.uses {
545+
switch use.instruction {
546+
case let endBorrow as EndBorrowInst:
547+
self.insert(endBorrow)
548+
case let branch as BranchInst:
549+
worklist.pushIfNotVisited(branch.getArgument(for: use))
550+
default:
551+
break
552+
}
553+
}
554+
}
555+
}
556+
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ extension UnaryInstruction {
234234
final public class UnimplementedInstruction : Instruction {
235235
}
236236

237-
public protocol StoringInstruction : AnyObject {
237+
public protocol StoringInstruction : Instruction {
238238
var operands: OperandArray { get }
239239
}
240240

@@ -270,6 +270,8 @@ final public class StoreInst : Instruction, StoringInstruction {
270270
final public class StoreWeakInst : Instruction, StoringInstruction { }
271271
final public class StoreUnownedInst : Instruction, StoringInstruction { }
272272

273+
final public class StoreBorrowInst : SingleValueInstruction, StoringInstruction, BorrowIntroducingInstruction { }
274+
273275
final public class AssignInst : Instruction, StoringInstruction {
274276
// must match with enum class swift::AssignOwnershipQualifier
275277
public enum AssignOwnership: Int {
@@ -495,6 +497,9 @@ extension LoadInstruction {
495497
public var address: Value { operand.value }
496498
}
497499

500+
/// Instructions, beginning a borrow-scope which must be ended by `end_borrow`.
501+
public protocol BorrowIntroducingInstruction : SingleValueInstruction {}
502+
498503
final public class LoadInst : SingleValueInstruction, LoadInstruction {
499504
// must match with enum class LoadOwnershipQualifier
500505
public enum LoadOwnership: Int {
@@ -507,7 +512,7 @@ final public class LoadInst : SingleValueInstruction, LoadInstruction {
507512

508513
final public class LoadWeakInst : SingleValueInstruction, LoadInstruction {}
509514
final public class LoadUnownedInst : SingleValueInstruction, LoadInstruction {}
510-
final public class LoadBorrowInst : SingleValueInstruction, LoadInstruction {}
515+
final public class LoadBorrowInst : SingleValueInstruction, LoadInstruction, BorrowIntroducingInstruction {}
511516

512517
final public class BuiltinInst : SingleValueInstruction {
513518
public typealias ID = BridgedInstruction.BuiltinValueKind
@@ -872,16 +877,9 @@ extension BeginAccessInst : ScopedInstruction {
872877
}
873878
}
874879

875-
final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction {
880+
final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction, BorrowIntroducingInstruction {
876881
public var borrowedValue: Value { operand.value }
877882

878-
public typealias EndBorrowSequence = LazyMapSequence<LazyFilterSequence<LazyMapSequence<UseList, EndBorrowInst?>>,
879-
EndBorrowInst>
880-
881-
public var endBorrows: EndBorrowSequence {
882-
uses.lazy.compactMap({ $0.instruction as? EndBorrowInst })
883-
}
884-
885883
public var isLexical: Bool { bridged.BeginBorrow_isLexical() }
886884
public var hasPointerEscape: Bool { bridged.BeginBorrow_hasPointerEscape() }
887885
}

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public func registerSILClasses() {
4141
register(StoreInst.self)
4242
register(StoreWeakInst.self)
4343
register(StoreUnownedInst.self)
44+
register(StoreBorrowInst.self)
4445
register(AssignInst.self)
4546
register(CopyAddrInst.self)
4647
register(EndAccessInst.self)

test/SILOptimizer/let-property-lowering.sil

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,59 @@ bb3:
254254
return %2 : $C
255255
}
256256

257+
// CHECK-LABEL: sil [ossa] @test_store_borrow :
258+
// CHECK: bb1:
259+
// CHECK-NEXT: end_borrow
260+
// CHECK-NEXT: end_init_let_ref %2
261+
// CHECK: bb2:
262+
// CHECK: end_borrow {{%[0-9]}} : $*C
263+
// CHECK: [[B:%.*]] = begin_borrow %2
264+
// CHECK: end_borrow [[B]] : $C
265+
// CHECK-NEXT: end_init_let_ref %2
266+
// CHECK: } // end sil function 'test_store_borrow'
267+
sil [ossa] @test_store_borrow : $@convention(thin) (@owned C, Int) -> @owned C {
268+
bb0(%0 : @owned $C, %1 : $Int):
269+
%2 = mark_uninitialized [rootself] %0 : $C
270+
%3 = begin_borrow %2 : $C
271+
%4 = ref_element_addr %3 : $C, #C.a
272+
store %1 to [trivial] %4 : $*Int
273+
end_borrow %3 : $C
274+
%10 = alloc_stack $C
275+
%11 = store_borrow %2 to %10 : $*C
276+
cond_br undef, bb1, bb2
277+
bb1:
278+
end_borrow %11 : $*C
279+
dealloc_stack %10 : $*C
280+
return %2 : $C
281+
bb2:
282+
end_borrow %11 : $*C
283+
%17 = begin_borrow %2 : $C
284+
%18 = ref_element_addr %17 : $C, #C.a
285+
%19 = begin_access [deinit] [static] %18 : $*Int
286+
destroy_addr %19 : $*Int
287+
end_access %19 : $*Int
288+
end_borrow %17 : $C
289+
unreachable
290+
}
291+
292+
// CHECK-LABEL: sil [ossa] @test_reborrow :
293+
// CHECK: bb1([[A:%.*]] : @reborrow @guaranteed $C):
294+
// CHECK: end_borrow [[A]]
295+
// CHECK-NEXT: end_init_let_ref %2
296+
// CHECK: } // end sil function 'test_reborrow'
297+
sil [ossa] @test_reborrow : $@convention(thin) (@owned C, Int) -> @owned C {
298+
bb0(%0 : @owned $C, %1 : $Int):
299+
%2 = mark_uninitialized [rootself] %0 : $C
300+
%3 = begin_borrow %2 : $C
301+
%4 = ref_element_addr %3 : $C, #C.a
302+
store %1 to [trivial] %4 : $*Int
303+
br bb1(%3 : $C)
304+
bb1(%3a : @reborrow @guaranteed $C):
305+
end_borrow %3a : $C
306+
%7 = begin_borrow %2 : $C
307+
%8 = ref_element_addr %7 : $C, #C.a
308+
%9 = load [trivial] %8 : $*Int
309+
end_borrow %7 : $C
310+
return %2 : $C
311+
}
312+

0 commit comments

Comments
 (0)