Skip to content

Commit 387f700

Browse files
committed
Revert "TempRValueElimination: handle store instructions to the temporary stack location."
This reverts commit 5d24a26.
1 parent 5d1327d commit 387f700

File tree

7 files changed

+43
-239
lines changed

7 files changed

+43
-239
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/TempRValueElimination.swift

Lines changed: 30 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -38,51 +38,18 @@ let tempRValueElimination = FunctionPass(name: "temp-rvalue-elimination") {
3838
(function: Function, context: FunctionPassContext) in
3939

4040
for inst in function.instructions {
41-
switch inst {
42-
case let copy as CopyAddrInst:
43-
if copy.source == copy.destination {
44-
// Remove identity copies which may have been created by an earlier iteration, where another `copy_addr`
45-
// copied the `alloc_stack` back to the source location.
46-
context.erase(instruction: copy)
47-
} else {
48-
tryEliminate(copy: copy, context)
49-
}
50-
case let store as StoreInst:
51-
// Also handle `load`-`store` pairs which are basically the same thing as a `copy_addr`.
52-
if let load = store.source as? LoadInst, load.uses.isSingleUse, load.parentBlock == store.parentBlock {
53-
tryEliminate(copy: store, context)
54-
}
55-
default:
56-
break
41+
if let copyAddr = inst as? CopyAddrInst {
42+
tryEliminate(copy: copyAddr, context)
5743
}
5844
}
5945
}
6046

61-
private protocol CopyLikeInstruction: Instruction {
62-
var sourceAddress: Value { get }
63-
var destinationAddress: Value { get }
64-
var isTakeOfSource: Bool { get }
65-
var isInitializationOfDestination: Bool { get }
66-
var loadingInstruction: Instruction { get }
67-
}
68-
69-
extension CopyAddrInst: CopyLikeInstruction {
70-
var sourceAddress: Value { source }
71-
var destinationAddress: Value { destination }
72-
var loadingInstruction: Instruction { self }
73-
}
74-
75-
// A `store` which has a `load` as source operand. This is basically the same as a `copy_addr`.
76-
extension StoreInst: CopyLikeInstruction {
77-
var sourceAddress: Value { load.address }
78-
var destinationAddress: Value { destination }
79-
var isTakeOfSource: Bool { load.loadOwnership == .take }
80-
var isInitializationOfDestination: Bool { storeOwnership != .assign }
81-
var loadingInstruction: Instruction { load }
82-
private var load: LoadInst { source as! LoadInst }
83-
}
84-
85-
private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassContext) {
47+
private func tryEliminate(copy: CopyAddrInst, _ context: FunctionPassContext) {
48+
// Remove identity copies which may have been created by an earlier iteration, where another `copy_addr`
49+
// copied the `alloc_stack` back to the source location.
50+
if copy.source == copy.destination {
51+
context.erase(instruction: copy)
52+
}
8653

8754
guard let (allocStack, lastUseOfAllocStack) = getRemovableAllocStackDestination(of: copy, context) else {
8855
return
@@ -94,7 +61,7 @@ private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassCont
9461

9562
if needToInsertDestroy(copy: copy, lastUseOfAllocStack: lastUseOfAllocStack) {
9663
Builder.insert(after: lastUseOfAllocStack, context) { builder in
97-
builder.createDestroyAddr(address: copy.sourceAddress)
64+
builder.createDestroyAddr(address: copy.source)
9865
}
9966
}
10067

@@ -109,25 +76,25 @@ private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassCont
10976
assert(cai == lastUseOfAllocStack && cai.source == allocStack)
11077
cai.set(isTakeOfSource: false, context)
11178
}
112-
use.set(to: copy.sourceAddress, context)
79+
use.set(to: copy.source, context)
11380
case let load as LoadInst:
11481
if load.loadOwnership == .take, !copy.isTakeOfSource {
11582
// If the original copy is not taking its source, a `load` from the `allocStack` must
11683
// not take its source either.
11784
assert(load == lastUseOfAllocStack)
11885
load.set(ownership: .copy, context)
11986
}
120-
use.set(to: copy.sourceAddress, context);
87+
use.set(to: copy.source, context);
12188

12289
default:
12390
// Note that no operations that may be handled by this default clause can destroy the `allocStack`.
12491
// This includes operations that load the value from memory and release it or cast the address
12592
// before destroying it.
126-
use.set(to: copy.sourceAddress, context);
93+
use.set(to: copy.source, context);
12794
}
12895
}
12996
context.erase(instruction: allocStack)
130-
context.erase(instructionIncludingAllUsers: copy.loadingInstruction)
97+
context.erase(instruction: copy)
13198
}
13299

133100
/// Checks if the `copy` is copying into an `alloc_stack` which is removable:
@@ -138,17 +105,17 @@ private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassCont
138105
/// %lastUseOfAllocStack = load %allocStack
139106
/// ```
140107
private func getRemovableAllocStackDestination(
141-
of copy: CopyLikeInstruction, _ context: FunctionPassContext
108+
of copy: CopyAddrInst, _ context: FunctionPassContext
142109
) -> (allocStack: AllocStackInst, lastUseOfAllocStack: Instruction)? {
143110
guard copy.isInitializationOfDestination,
144-
let allocStack = copy.destinationAddress as? AllocStackInst
111+
let allocStack = copy.destination as? AllocStackInst
145112
else {
146113
return nil
147114
}
148115

149116
// If the `allocStack` is lexical we can eliminate it if the source of the copy is lexical and
150117
// it is live for longer than the `allocStack`.
151-
if allocStack.isLexical && !copy.sourceAddress.accessBase.storageIsLexical {
118+
if allocStack.isLexical && !copy.source.accessBase.storageIsLexical {
152119
return nil
153120
}
154121

@@ -182,7 +149,7 @@ private func getRemovableAllocStackDestination(
182149
if copy.isTakeOfSource,
183150
lastUseOfAllocStack != copy,
184151
!(lastUseOfAllocStack is DestroyAddrInst),
185-
lastUseOfAllocStack.mayWrite(toAddress: copy.sourceAddress, context.aliasAnalysis)
152+
lastUseOfAllocStack.mayWrite(toAddress: copy.source, context.aliasAnalysis)
186153
{
187154
return nil
188155
}
@@ -201,7 +168,7 @@ private func getRemovableAllocStackDestination(
201168

202169
/// We need to insert a final destroy if the original `copy` is taking the source but the
203170
/// `lastUseOfAllocStack` is not taking the `alloc_stack`.
204-
private func needToInsertDestroy(copy: CopyLikeInstruction, lastUseOfAllocStack: Instruction) -> Bool {
171+
private func needToInsertDestroy(copy: CopyAddrInst, lastUseOfAllocStack: Instruction) -> Bool {
205172
if !copy.isTakeOfSource {
206173
return false
207174
}
@@ -210,13 +177,13 @@ private func needToInsertDestroy(copy: CopyLikeInstruction, lastUseOfAllocStack:
210177
return true
211178
case let cai as CopyAddrInst:
212179
if cai.isTakeOfSource {
213-
assert(cai.source == copy.destinationAddress, "copy_addr must be not take a projected address")
180+
assert(cai.source == copy.destination, "copy_addr must be not take a projected address")
214181
return false
215182
}
216183
return true
217184
case let li as LoadInst:
218185
if li.loadOwnership == .take {
219-
assert(li.address == copy.destinationAddress, "load must be not take a projected address")
186+
assert(li.address == copy.destination, "load must be not take a projected address")
220187
return false
221188
}
222189
return true
@@ -280,9 +247,7 @@ private extension AllocStackInst {
280247
/// ```
281248
/// We must not replace %temp with %a after the `end_access`. Instead we try to move the `end_access`
282249
/// after the last use.
283-
private func extendAccessScopes(beyond lastUse: Instruction, copy: CopyLikeInstruction,
284-
_ context: FunctionPassContext) -> Bool
285-
{
250+
private func extendAccessScopes(beyond lastUse: Instruction, copy: CopyAddrInst, _ context: FunctionPassContext) -> Bool {
286251
var endAccessToMove: EndAccessInst? = nil
287252

288253
for inst in InstructionList(first: copy.next) {
@@ -292,7 +257,7 @@ private func extendAccessScopes(beyond lastUse: Instruction, copy: CopyLikeInstr
292257
if endAccessToMove != nil {
293258
return false
294259
}
295-
if context.aliasAnalysis.mayAlias(copy.sourceAddress, endAccess.beginAccess.address),
260+
if context.aliasAnalysis.mayAlias(copy.source, endAccess.beginAccess.address),
296261
// There cannot be any aliasing modifying accesses within the liverange of the `alloc_stack`,
297262
// because we would have cought this in `getLastUseWhileSourceIsNotModified`.
298263
// But there are cases where `aliasAnalysis.mayAlias` is less precise than `Instruction.mayWrite`.
@@ -336,7 +301,7 @@ private func extendAccessScopes(beyond lastUse: Instruction, copy: CopyLikeInstr
336301
///
337302
/// Unfortunately, we cannot simply use the destroy points as the lifetime end, because they can be in a
338303
/// different basic block. Instead we look for the last non-destroy, non-dealloc use.
339-
private func getLastUseWhileSourceIsNotModified(of copy: CopyLikeInstruction,
304+
private func getLastUseWhileSourceIsNotModified(of copy: CopyAddrInst,
340305
uses: InstructionSetWithCount,
341306
_ context: FunctionPassContext) -> Instruction?
342307
{
@@ -348,7 +313,7 @@ private func getLastUseWhileSourceIsNotModified(of copy: CopyLikeInstruction,
348313

349314
// We already checked that the useful lifetime of the `alloc_stack` ends in the same block as the `copy`.
350315
// Therefore we can limit our search to the instructions of this block.
351-
for inst in InstructionList(first: copy.loadingInstruction.next) {
316+
for inst in InstructionList(first: copy.next) {
352317
if uses.contains(inst) {
353318
numUsesFound += 1
354319
}
@@ -362,7 +327,7 @@ private func getLastUseWhileSourceIsNotModified(of copy: CopyLikeInstruction,
362327
// could occur _before_ the read of the `alloc_stack`.
363328
switch inst {
364329
case is FullApplySite, is YieldInst:
365-
if inst.mayWrite(toAddress: copy.sourceAddress, aliasAnalysis) {
330+
if inst.mayWrite(toAddress: copy.source, aliasAnalysis) {
366331
return nil
367332
}
368333
return inst
@@ -371,7 +336,7 @@ private func getLastUseWhileSourceIsNotModified(of copy: CopyLikeInstruction,
371336
}
372337
}
373338

374-
if inst.mayWrite(toAddress: copy.sourceAddress, aliasAnalysis) {
339+
if inst.mayWrite(toAddress: copy.source, aliasAnalysis) {
375340
return nil
376341
}
377342
}
@@ -383,9 +348,9 @@ private func getLastUseWhileSourceIsNotModified(of copy: CopyLikeInstruction,
383348
/// Collects all uses of the `alloc_stack`.
384349
private struct UseCollector : AddressDefUseWalker {
385350
private(set) var uses: InstructionSetWithCount
386-
private let copy: CopyLikeInstruction
351+
private let copy: CopyAddrInst
387352

388-
init(copy: CopyLikeInstruction, _ context: FunctionPassContext) {
353+
init(copy: CopyAddrInst, _ context: FunctionPassContext) {
389354
self.uses = InstructionSetWithCount(context)
390355
self.copy = copy
391356
}
@@ -502,7 +467,7 @@ private struct UseCollector : AddressDefUseWalker {
502467
if load.loadOwnership == .take,
503468
// Only accept `load [take]` if it takes the whole `alloc_stack`. A `load [take]` from
504469
// a projection would destroy only a part of the `alloc_stack` and we don't handle this.
505-
load.address != copy.destinationAddress
470+
load.address != copy.destination
506471
{
507472
return .abortWalk
508473
}
@@ -529,7 +494,7 @@ private struct UseCollector : AddressDefUseWalker {
529494
return .abortWalk
530495
}
531496
// As with `load [take]`, only accept `copy_addr [take]` if it takes the whole `alloc_stack`.
532-
if copyFromStack.isTakeOfSource && copyFromStack.source != copy.destinationAddress {
497+
if copyFromStack.isTakeOfSource && copyFromStack.source != copy.destination {
533498
return .abortWalk
534499
}
535500
uses.insert(copyFromStack)

test/SILOptimizer/globalopt_resilience.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ public func cannotConvertToValueUse() {
3737
}
3838

3939
// CHECK-LABEL: sil @$s4test23cannotConvertToValueUseyyF : $@convention(thin) () -> ()
40-
// CHECK: [[GA:%.*]] = global_addr @$s4test15ResilientStructV9staticValACvpZ
40+
// CHECK: [[INT:%.*]] = integer_literal $Builtin.Int{{32|64}}, 27
41+
// CHECK: [[S1:%.*]] = struct $Int ([[INT]] : $Builtin.Int{{32|64}})
42+
// CHECK: [[S2:%.*]] = struct $ResilientStruct ([[S1]] : $Int)
43+
// CHECK: [[TMP:%.*]] = alloc_stack $ResilientStruct
44+
// CHECK: store [[S2]] to [[TMP]] : $*ResilientStruct
4145
// CHECK: [[METHOD:%.*]] = function_ref @$s4test15ResilientStructV6methodyyF : $@convention(method) (@in_guaranteed ResilientStruct) -> ()
42-
// CHECK: apply [[METHOD]]([[GA]]) : $@convention(method) (@in_guaranteed ResilientStruct) -> ()
46+
// CHECK: apply [[METHOD]]([[TMP]]) : $@convention(method) (@in_guaranteed ResilientStruct) -> ()
4347
// CHECK: [[RESULT:%.*]] = tuple ()
4448
// CHECK: return [[RESULT]] : $()
4549

test/SILOptimizer/inline_arrays.swift

Lines changed: 0 additions & 35 deletions
This file was deleted.

test/SILOptimizer/pre_specialize_layouts.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public func usePrespecializedEntryPoints(wrapperStruct: ReferenceWrapperStruct,
189189
// OPT: [[A1:%.*]] = unchecked_ref_cast [[P1]] : $SomeClass to $AnyObject
190190
// OPT: [[R3:%.*]] = apply [[F1]]([[A1]]) : $@convention(thin) (@guaranteed AnyObject) -> @owned AnyObject
191191
// OPT: store [[R3]] to [[R2]] : $*AnyObject
192+
// OPT: [[A2:%.*]] = load [[R1]] : $*SomeClass
192193
// OPT: [[F2:%.*]] = function_ref @$s22pre_specialize_layouts7consumeyyxlF0a20_specialized_module_C09SomeClassC_Ttg5 : $@convention(thin) () -> ()
193194
// OPT: apply [[F2]]() : $@convention(thin) () -> ()
194195
// OPT: dealloc_stack [[R1]] : $*SomeClass

test/SILOptimizer/specialize_opaque_type_archetypes.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,12 @@ struct PAEM : P4EM {
421421
// CHECK: apply [[F]]([[V]])
422422

423423
// CHECK-64-LABEL: sil hidden @$s1A2PAV4testyyF : $@convention(method) (PA) -> ()
424-
// CHECK-64: [[V:%.*]] = integer_literal $Builtin.Int64, 5
425-
// CHECK-64-DAG: [[I:%.*]] = struct $Int64 ([[V]] : $Builtin.Int64)
426-
// CHECK-64-DAG: [[F:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
427-
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
428-
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
429-
// CHECK-64: } // end sil function '$s1A2PAV4testyyF'
424+
// CHECK-64: [[V:%.*]] = integer_literal $Builtin.Int64, 5
425+
// CHECK-64: [[I:%.*]] = struct $Int64 ([[V]] : $Builtin.Int64)
426+
// CHECK-64: [[F:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
427+
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
428+
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
429+
430430
@inline(never)
431431
func testIt<T>(cl: (Int64) throws -> T) {
432432
do {

test/SILOptimizer/temp_rvalue_opt.sil

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -827,18 +827,3 @@ bb0:
827827
return %12
828828
}
829829

830-
// CHECK-LABEL: sil @store_to_temp :
831-
// CHECK: %1 = load %0
832-
// CHECK-NEXT: return %1
833-
// CHECK-LABEL: } // end sil function 'store_to_temp'
834-
sil @store_to_temp : $@convention(thin) (@in_guaranteed Klass) -> @owned Klass {
835-
bb0(%0 : $*Klass):
836-
%1 = load %0
837-
%2 = alloc_stack $Klass
838-
store %1 to %2
839-
%4 = load %2
840-
destroy_addr %2
841-
dealloc_stack %2
842-
return %4
843-
}
844-

0 commit comments

Comments
 (0)