Skip to content

Commit 08d411a

Browse files
committed
CopyToBorrowOptimization: need to update borrowed-from instructions when changes are made
When ownership is changed from owned to guaranteed, the enclosing values of a guaranteed value can change. Fixes a SIL verifier error.
1 parent 0cbf356 commit 08d411a

File tree

2 files changed

+41
-10
lines changed

2 files changed

+41
-10
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CopyToBorrowOptimization.swift

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,49 +53,60 @@ let copyToBorrowOptimization = FunctionPass(name: "copy-to-borrow-optimization")
5353
return
5454
}
5555

56+
var changed = false
57+
5658
for inst in function.instructions {
5759
switch inst {
5860
case let load as LoadInst:
59-
optimize(load: load, context)
61+
if optimize(load: load, context) {
62+
changed = true
63+
}
6064
case let copy as CopyValueInst:
61-
optimize(copy: copy, context)
65+
if optimize(copy: copy, context) {
66+
changed = true
67+
}
6268
default:
6369
break
6470
}
6571
}
72+
73+
if changed {
74+
updateBorrowedFrom(in: function, context)
75+
}
6676
}
6777

68-
private func optimize(load: LoadInst, _ context: FunctionPassContext) {
78+
private func optimize(load: LoadInst, _ context: FunctionPassContext) -> Bool {
6979
if load.loadOwnership != .copy {
70-
return
80+
return false
7181
}
7282

7383
var collectedUses = Uses(context)
7484
defer { collectedUses.deinitialize() }
7585
if !collectedUses.collectUses(of: load) {
76-
return
86+
return false
7787
}
7888

7989
if mayWrite(toAddressOf: load,
8090
within: collectedUses.destroys,
8191
usersInDeadEndBlocks: collectedUses.usersInDeadEndBlocks,
8292
context)
8393
{
84-
return
94+
return false
8595
}
8696

8797
load.replaceWithLoadBorrow(collectedUses: collectedUses)
98+
return true
8899
}
89100

90-
private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) {
101+
private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) -> Bool {
91102
if copy.fromValue.ownership != .guaranteed {
92-
return
103+
return false
93104
}
94105

95106
var collectedUses = Uses(context)
96107
defer { collectedUses.deinitialize() }
97108
if !collectedUses.collectUses(of: copy) {
98-
return
109+
return false
99110
}
100111

101112
var liverange = InstructionRange(begin: copy, context)
@@ -104,10 +115,11 @@ private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) {
104115
liverange.insert(contentsOf: collectedUses.usersInDeadEndBlocks)
105116

106117
if !liverange.isFullyContainedIn(borrowScopeOf: copy.fromValue.lookThroughForwardingInstructions) {
107-
return
118+
return false
108119
}
109120

110121
remove(copy: copy, collectedUses: collectedUses, liverange: liverange)
122+
return true
111123
}
112124

113125
private struct Uses {

test/SILOptimizer/copy-to-borrow-optimization.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,3 +2275,22 @@ bb1(%6 : @guaranteed $MyArrayStorageBase):
22752275
%13 = tuple ()
22762276
return %13
22772277
}
2278+
2279+
// CHECK-LABEL: sil [ossa] @test_updating_borrowed_from :
2280+
// CHECK: borrowed {{.*}} from (%0)
2281+
// CHECK-LABEL: } // end sil function 'test_updating_borrowed_from'
2282+
sil [ossa] @test_updating_borrowed_from : $@convention(thin) (@guaranteed NonTrivialStruct) -> () {
2283+
bb0(%0 : @guaranteed $NonTrivialStruct):
2284+
%1 = destructure_struct %0 : $NonTrivialStruct
2285+
%2 = copy_value %1 : $Klass
2286+
%3 = begin_borrow %2 : $Klass
2287+
br bb1(%3 : $Klass)
2288+
2289+
bb1(%5 : @reborrow $Klass):
2290+
%6 = borrowed %5 : $Klass from (%2 : $Klass)
2291+
end_borrow %6 : $Klass
2292+
destroy_value %2 : $Klass
2293+
%9 = tuple ()
2294+
return %9 : $()
2295+
}
2296+

0 commit comments

Comments
 (0)