Skip to content

Commit 4f09d29

Browse files
committed
Optimizer: add simplification for begin_borrow
Try to replace a begin_borrow with its owned operand. This is either possible if the borrowed value (or a forwarded value if it) is copied: ``` %1 = begin_borrow %0 %2 = struct_extract %1 // a chain of forwarding instructions %3 = copy_value %1 // ... uses of %3 end_borrow %1 ``` -> ``` %1 = copy_value %0 %3 = destructure_struct %0 // owned version of the forwarding instructions // ... uses of %3 ``` Or if the borrowed value is destroyed immediately after the borrow scope: ``` %1 = begin_borrow %0 %2 = struct_extract %1 // a chain of forwarding instructions // ... uses of %2 end_borrow %1 destroy_value %1 // the only other use of %0 beside begin_borrow ``` -> ``` %2 = destructure_struct %0 // owned version of the forwarding instructions // ... uses of %2 destroy_value %2 ```
1 parent 1f85ee1 commit 4f09d29

File tree

5 files changed

+556
-28
lines changed

5 files changed

+556
-28
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
swift_compiler_sources(Optimizer
1010
SimplifyApply.swift
11+
SimplifyBeginBorrow.swift
1112
SimplifyBeginCOWMutation.swift
1213
SimplifyBranch.swift
1314
SimplifyBuiltin.swift
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
//===--- SimplifyBeginBorrow.swift ----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension BeginBorrowInst : OnoneSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
if borrowedValue.ownership == .owned,
18+
// We need to keep lexical lifetimes in place.
19+
!isLexical
20+
{
21+
tryReplaceBorrowWithOwnedOperand(beginBorrow: self, context)
22+
}
23+
}
24+
}
25+
26+
private func tryReplaceBorrowWithOwnedOperand(beginBorrow: BeginBorrowInst, _ context: SimplifyContext) {
27+
// The last value of a (potentially empty) forwarding chain, beginning at the `begin_borrow`.
28+
let forwardedValue = beginBorrow.lookThroughSingleForwardingUses()
29+
if forwardedValue.allUsesCanBeConvertedToOwned {
30+
if tryReplaceCopy(of: forwardedValue, withCopiedOperandOf: beginBorrow, context) {
31+
return
32+
}
33+
if beginBorrow.borrowedValue.isDestroyed(after: beginBorrow) {
34+
convertAllUsesToOwned(of: beginBorrow, context)
35+
}
36+
}
37+
}
38+
39+
/// Replace
40+
/// ```
41+
/// %1 = begin_borrow %0
42+
/// %2 = struct_extract %1 // a chain of forwarding instructions
43+
/// %3 = copy_value %1
44+
/// // ... uses of %3
45+
/// end_borrow %1
46+
/// ```
47+
/// with
48+
/// ```
49+
/// %1 = copy_value %0
50+
/// %3 = destructure_struct %0 // owned version of the forwarding instructions
51+
/// // ... uses of %3
52+
/// ```
53+
private func tryReplaceCopy(
54+
of forwardedValue: Value,
55+
withCopiedOperandOf beginBorrow: BeginBorrowInst,
56+
_ context: SimplifyContext
57+
) -> Bool {
58+
guard let singleUser = forwardedValue.uses.ignoreUsers(ofType: EndBorrowInst.self).singleUse?.instruction,
59+
let copy = singleUser as? CopyValueInst,
60+
copy.parentBlock == beginBorrow.parentBlock else {
61+
return false
62+
}
63+
let builder = Builder(before: beginBorrow, context)
64+
let copiedOperand = builder.createCopyValue(operand: beginBorrow.borrowedValue)
65+
let forwardedOwnedValue = replace(guaranteedValue: beginBorrow, withOwnedValue: copiedOperand, context)
66+
copy.uses.replaceAll(with: forwardedOwnedValue, context)
67+
context.erase(instruction: copy)
68+
context.erase(instructionIncludingAllUsers: beginBorrow)
69+
return true
70+
}
71+
72+
/// Replace
73+
/// ```
74+
/// %1 = begin_borrow %0
75+
/// %2 = struct_extract %1 // a chain of forwarding instructions
76+
/// // ... uses of %2
77+
/// end_borrow %1
78+
/// destroy_value %1 // the only other use of %0 beside begin_borrow
79+
/// ```
80+
/// with
81+
/// ```
82+
/// %2 = destructure_struct %0 // owned version of the forwarding instructions
83+
/// // ... uses of %2
84+
/// destroy_value %2
85+
/// ```
86+
private func convertAllUsesToOwned(of beginBorrow: BeginBorrowInst, _ context: SimplifyContext) {
87+
let forwardedOwnedValue = replace(guaranteedValue: beginBorrow, withOwnedValue: beginBorrow.borrowedValue, context)
88+
beginBorrow.borrowedValue.replaceAllDestroys(with: forwardedOwnedValue, context)
89+
context.erase(instructionIncludingAllUsers: beginBorrow)
90+
}
91+
92+
private extension Value {
93+
/// Returns the last value of a (potentially empty) forwarding chain.
94+
/// For example, returns %3 for the following def-use chain:
95+
/// ```
96+
/// %1 = struct_extract %self, #someField
97+
/// %2 = tuple_extract %1, 0
98+
/// %3 = struct $S(%2) // %3 has no forwarding users
99+
/// ```
100+
/// Returns self if this value has no uses which are ForwardingInstructions.
101+
func lookThroughSingleForwardingUses() -> Value {
102+
if let singleUse = uses.ignoreUsers(ofType: EndBorrowInst.self).singleUse,
103+
let fwdInst = singleUse.instruction as? (SingleValueInstruction & ForwardingInstruction),
104+
fwdInst.canConvertToOwned,
105+
fwdInst.isSingleForwardedOperand(singleUse),
106+
fwdInst.parentBlock == parentBlock
107+
{
108+
return fwdInst.lookThroughSingleForwardingUses()
109+
}
110+
return self
111+
}
112+
113+
var allUsesCanBeConvertedToOwned: Bool {
114+
let relevantUses = uses.ignoreUsers(ofType: EndBorrowInst.self)
115+
return relevantUses.allSatisfy { $0.canAccept(ownership: .owned) }
116+
}
117+
118+
func isDestroyed(after nonDestroyUser: Instruction) -> Bool {
119+
uses.getSingleUser(notOfType: DestroyValueInst.self) == nonDestroyUser
120+
}
121+
122+
func replaceAllDestroys(with replacement: Value, _ context: SimplifyContext) {
123+
uses.filterUsers(ofType: DestroyValueInst.self).replaceAll(with: replacement, context)
124+
}
125+
}
126+
127+
private extension ForwardingInstruction {
128+
func isSingleForwardedOperand(_ operand: Operand) -> Bool {
129+
switch self {
130+
case is StructInst, is TupleInst:
131+
// TODO: we could move that logic to StructInst/TupleInst.singleForwardedOperand.
132+
return operands.lazy.map({ $0.value.type }).hasSingleNonTrivialElement(at: operand.index, in: parentFunction)
133+
default:
134+
if let sfo = singleForwardedOperand {
135+
return sfo == operand
136+
}
137+
return false
138+
}
139+
}
140+
}
141+
142+
/// Replaces a guaranteed value with an owned value.
143+
///
144+
/// If the `guaranteedValue`'s use is a ForwardingInstruction (or forwarding instruction chain),
145+
/// it is converted to an owned version of the forwarding instruction (or instruction chain).
146+
///
147+
/// Returns the last owned value in a forwarding-chain or `ownedValue` if `guaranteedValue` has
148+
/// no forwarding uses.
149+
private func replace(guaranteedValue: Value, withOwnedValue ownedValue: Value, _ context: SimplifyContext) -> Value {
150+
var result = ownedValue
151+
var numForwardingUses = 0
152+
for use in guaranteedValue.uses {
153+
154+
switch use.instruction {
155+
case let tei as TupleExtractInst:
156+
numForwardingUses += 1
157+
let dti = Builder(before: tei, context).createDestructureTuple(tuple: ownedValue)
158+
result = replace(guaranteedValue: tei, withOwnedValue: dti.results[tei.fieldIndex], context)
159+
context.erase(instruction: tei)
160+
case let sei as StructExtractInst:
161+
numForwardingUses += 1
162+
let dsi = Builder(before: sei, context).createDestructureStruct(struct: ownedValue)
163+
result = replace(guaranteedValue: sei, withOwnedValue: dsi.results[sei.fieldIndex], context)
164+
context.erase(instruction: sei)
165+
case let fwdInst as (SingleValueInstruction & ForwardingInstruction) where
166+
fwdInst.isSingleForwardedOperand(use):
167+
// Other forwarding instructions beside tuple_extract and struct_extract
168+
numForwardingUses += 1
169+
use.set(to: ownedValue, context)
170+
fwdInst.setForwardingOwnership(to: .owned, context)
171+
result = replace(guaranteedValue: fwdInst, withOwnedValue: fwdInst, context)
172+
case is EndBorrowInst:
173+
break
174+
default:
175+
precondition(use.canAccept(ownership: .owned))
176+
use.set(to: ownedValue, context)
177+
}
178+
}
179+
precondition(numForwardingUses <= 1, "guaranteed value must not have multiple forwarding uses")
180+
return result
181+
}
182+
183+
private extension ForwardingInstruction {
184+
var canConvertToOwned: Bool {
185+
switch self {
186+
case let si as StructExtractInst:
187+
if si.struct.type.isMoveOnly {
188+
// We cannot easily convert a struct_extract to a destructure_struct of a move-only type, because
189+
// the deinit would get lost.
190+
return false
191+
}
192+
let structFields = si.struct.type.getNominalFields(in: parentFunction)
193+
return structFields.hasSingleNonTrivialElement(at: si.fieldIndex, in: parentFunction)
194+
case let ti as TupleExtractInst:
195+
return ti.tuple.type.tupleElements.hasSingleNonTrivialElement(at: ti.fieldIndex, in: parentFunction)
196+
default:
197+
return canForwardOwnedValues
198+
}
199+
}
200+
}
201+
202+
private extension Collection where Element == Type {
203+
func hasSingleNonTrivialElement(at nonTrivialElementIndex: Int, in function: Function) -> Bool {
204+
for (elementIdx, elementTy) in self.enumerated() {
205+
if elementTy.isTrivial(in: function) != (elementIdx != nonTrivialElementIndex) {
206+
return false
207+
}
208+
}
209+
return true
210+
}
211+
}

test/SILOptimizer/OSLogMandatoryOptTest.swift

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ func testSimpleInterpolation() {
4646

4747
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
4848
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
49-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
49+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
5050
// We need to wade through some borrows and copy values here.
51-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
52-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
5351
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
5452
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
5553
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -92,9 +90,7 @@ func testInterpolationWithFormatOptions() {
9290

9391
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
9492
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
95-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
96-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
97-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
93+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
9894
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
9995
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
10096
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -139,9 +135,7 @@ func testInterpolationWithFormatOptionsAndPrivacy() {
139135

140136
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
141137
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
142-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
143-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
144-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
138+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
145139
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
146140
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
147141
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -192,10 +186,8 @@ func testInterpolationWithMultipleArguments() {
192186

193187
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
194188
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
195-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
189+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
196190
// CHECK-DAG: [[ARGSARRAYADDR]] = alloc_stack $Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>
197-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
198-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
199191
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
200192
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
201193
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -242,9 +234,7 @@ func testLogMessageWithoutData() {
242234

243235
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
244236
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
245-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to {{.*}}
246-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
247-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[ARGSARRAY:%[0-9]+]]
237+
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY:%[0-9]+]] to {{.*}}
248238
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
249239
// CHECK-DAG: [[ARRAYINITRES]] = apply [[ARRAYINIT:%[0-9]+]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARRAYSIZE:%[0-9]+]])
250240
// CHECK-DAG: [[ARRAYINIT]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF
@@ -314,9 +304,7 @@ func testMessageWithTooManyArguments() {
314304

315305
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
316306
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
317-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
318-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
319-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
307+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
320308
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
321309
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
322310
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -398,9 +386,7 @@ func testDynamicStringArguments() {
398386

399387
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
400388
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
401-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
402-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
403-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
389+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
404390
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
405391
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
406392
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -450,9 +436,7 @@ func testNSObjectInterpolation() {
450436

451437
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
452438
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
453-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
454-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
455-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
439+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
456440
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
457441
// CHECK-DAG: [[FINARR]] = apply {{.*}}<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
458442
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]
@@ -497,9 +481,7 @@ func testDoubleInterpolation() {
497481

498482
// CHECK-DAG: [[FOREACH:%[0-9]+]] = function_ref @$sSTsE7forEachyyy7ElementQzKXEKF
499483
// CHECK-DAG: try_apply [[FOREACH]]<Array<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>>({{%.*}}, [[SB:%[0-9]+]])
500-
// CHECK-DAG: [[SB]] = store_borrow [[ARGSARRAY3:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
501-
// CHECK-DAG: [[ARGSARRAY3]] = copy_value [[ARGSARRAY4:%[0-9]+]]
502-
// CHECK-DAG: [[ARGSARRAY4]] = begin_borrow [[FINARR:%[0-9]+]]
484+
// CHECK-DAG: [[SB]] = store_borrow [[FINARR:%[0-9]+]] to [[ARGSARRAYADDR:%[0-9]+]]
503485
// CHECK-DAG: [[FINARRFUNC:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
504486
// CHECK-DAG: [[FINARR]] = apply [[FINARRFUNC]]<(inout UnsafeMutablePointer<UInt8>, inout Optional<UnsafeMutablePointer<NSObject>>, inout Optional<UnsafeMutablePointer<Any>>) -> ()>([[ARGSARRAY:%[0-9]+]])
505487
// CHECK-DAG: ([[ARGSARRAY]], {{%.*}}) = destructure_tuple [[ARRAYINITRES:%[0-9]+]]

test/SILOptimizer/lexical_lifetime_elim.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %target-swift-frontend -emit-sil -O -parse-as-library -enable-copy-propagation=false -Xllvm -sil-print-all -module-name=main %s 2>&1 | %FileCheck %s
22
// RUN: %target-swift-frontend -emit-sil -O -parse-as-library -enable-lexical-lifetimes=false -Xllvm -sil-print-all -module-name=main %s 2>&1 | %FileCheck %s
33

4+
// REQUIRES: swift_in_compiler
5+
46
@inline(never)
57
func takeGuaranteed(_ a: AnyObject) -> AnyObject {
68
return a
@@ -35,7 +37,7 @@ func getOwned() -> AnyObject
3537
// The first round of SemanticARCOpts must eliminate the borrow scope
3638
// that was only needed for a lexical lifetime.
3739

38-
// CHECK-LABEL: *** SIL function after {{.*}} (semantic-arc-opts)
40+
// CHECK-LABEL: *** SIL function after {{.*}} (onone-simplification)
3941
// CHECK-LABEL: // testLexical()
4042
// CHECK: [[A:%.*]] = apply %{{.*}}()
4143
// CHECK: apply %{{.*}}([[A]])

0 commit comments

Comments
 (0)