mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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.
This commit is contained in:
@@ -53,27 +53,37 @@ let copyToBorrowOptimization = FunctionPass(name: "copy-to-borrow-optimization")
|
||||
return
|
||||
}
|
||||
|
||||
var changed = false
|
||||
|
||||
for inst in function.instructions {
|
||||
switch inst {
|
||||
case let load as LoadInst:
|
||||
optimize(load: load, context)
|
||||
if optimize(load: load, context) {
|
||||
changed = true
|
||||
}
|
||||
case let copy as CopyValueInst:
|
||||
optimize(copy: copy, context)
|
||||
if optimize(copy: copy, context) {
|
||||
changed = true
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
updateBorrowedFrom(in: function, context)
|
||||
}
|
||||
}
|
||||
|
||||
private func optimize(load: LoadInst, _ context: FunctionPassContext) {
|
||||
private func optimize(load: LoadInst, _ context: FunctionPassContext) -> Bool {
|
||||
if load.loadOwnership != .copy {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
var collectedUses = Uses(context)
|
||||
defer { collectedUses.deinitialize() }
|
||||
if !collectedUses.collectUses(of: load) {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
if mayWrite(toAddressOf: load,
|
||||
@@ -81,21 +91,22 @@ private func optimize(load: LoadInst, _ context: FunctionPassContext) {
|
||||
usersInDeadEndBlocks: collectedUses.usersInDeadEndBlocks,
|
||||
context)
|
||||
{
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
load.replaceWithLoadBorrow(collectedUses: collectedUses)
|
||||
return true
|
||||
}
|
||||
|
||||
private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) {
|
||||
private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) -> Bool {
|
||||
if copy.fromValue.ownership != .guaranteed {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
var collectedUses = Uses(context)
|
||||
defer { collectedUses.deinitialize() }
|
||||
if !collectedUses.collectUses(of: copy) {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
var liverange = InstructionRange(begin: copy, context)
|
||||
@@ -104,10 +115,11 @@ private func optimize(copy: CopyValueInst, _ context: FunctionPassContext) {
|
||||
liverange.insert(contentsOf: collectedUses.usersInDeadEndBlocks)
|
||||
|
||||
if !liverange.isFullyContainedIn(borrowScopeOf: copy.fromValue.lookThroughForwardingInstructions) {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
remove(copy: copy, collectedUses: collectedUses, liverange: liverange)
|
||||
return true
|
||||
}
|
||||
|
||||
private struct Uses {
|
||||
|
||||
@@ -2275,3 +2275,22 @@ bb1(%6 : @guaranteed $MyArrayStorageBase):
|
||||
%13 = tuple ()
|
||||
return %13
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_updating_borrowed_from :
|
||||
// CHECK: borrowed {{.*}} from (%0)
|
||||
// CHECK-LABEL: } // end sil function 'test_updating_borrowed_from'
|
||||
sil [ossa] @test_updating_borrowed_from : $@convention(thin) (@guaranteed NonTrivialStruct) -> () {
|
||||
bb0(%0 : @guaranteed $NonTrivialStruct):
|
||||
%1 = destructure_struct %0 : $NonTrivialStruct
|
||||
%2 = copy_value %1 : $Klass
|
||||
%3 = begin_borrow %2 : $Klass
|
||||
br bb1(%3 : $Klass)
|
||||
|
||||
bb1(%5 : @reborrow $Klass):
|
||||
%6 = borrowed %5 : $Klass from (%2 : $Klass)
|
||||
end_borrow %6 : $Klass
|
||||
destroy_value %2 : $Klass
|
||||
%9 = tuple ()
|
||||
return %9 : $()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user