@@ -165,9 +165,9 @@ private func analyzeInstructions(
165
165
analyzedInstructions. loads. append ( loadInst)
166
166
case let storeInst as StoreInst :
167
167
switch storeInst. storeOwnership {
168
- case . assign, . initialize :
168
+ case . assign:
169
169
continue // TODO: Add support
170
- case . unqualified, . trivial:
170
+ case . unqualified, . trivial, . initialize :
171
171
break
172
172
}
173
173
analyzedInstructions. stores. append ( storeInst)
@@ -324,8 +324,7 @@ private func collectMovableInstructions(
324
324
case let loadInst as LoadInst :
325
325
// Avoid quadratic complexity in corner cases. Usually, this limit will not be exceeded.
326
326
if loadInstCounter * analyzedInstructions. loopSideEffects. count < 8000 ,
327
- !analyzedInstructions. loopSideEffectsMayWriteTo ( address: loadInst. operand. value, context. aliasAnalysis) ,
328
- loadInst. loadOwnership != . take, loadInst. loadOwnership != . copy { // TODO: Add support for take and copy loads.
327
+ !analyzedInstructions. loopSideEffectsMayWriteTo ( address: loadInst. operand. value, context. aliasAnalysis) {
329
328
movableInstructions. hoistUp. append ( loadInst)
330
329
}
331
330
@@ -334,9 +333,9 @@ private func collectMovableInstructions(
334
333
movableInstructions. loadsAndStores. append ( loadInst)
335
334
case let storeInst as StoreInst :
336
335
switch storeInst. storeOwnership {
337
- case . assign, . initialize :
336
+ case . assign:
338
337
continue // TODO: Add support
339
- case . unqualified, . trivial:
338
+ case . unqualified, . trivial, . initialize :
340
339
break
341
340
}
342
341
movableInstructions. loadsAndStores. append ( storeInst)
@@ -861,7 +860,12 @@ private extension Instruction {
861
860
if canHoistArraySemanticsCall ( to: terminator, context) {
862
861
hoistArraySemanticsCall ( before: terminator, context)
863
862
} else {
864
- move ( before: terminator, context)
863
+ if let loadCopyInst = self as? LoadInst , loadCopyInst. loadOwnership == . copy {
864
+ hoist ( loadCopyInst: loadCopyInst, outOf: loop, context)
865
+ return true
866
+ } else {
867
+ move ( before: terminator, context)
868
+ }
865
869
}
866
870
867
871
if let singleValueInst = self as? SingleValueInstruction ,
@@ -879,6 +883,31 @@ private extension Instruction {
879
883
return true
880
884
}
881
885
886
+ private func hoist( loadCopyInst: LoadInst , outOf loop: Loop , _ context: FunctionPassContext ) {
887
+ if loop. hasNoExitBlocks {
888
+ return
889
+ }
890
+
891
+ let preheaderBuilder = Builder ( before: loop. preheader!. terminator, context)
892
+ let preheaderLoadBorrow = preheaderBuilder. createLoadBorrow ( fromAddress: loadCopyInst. address)
893
+
894
+ let headerBuilder = Builder ( before: loadCopyInst, context)
895
+ let copyValue = headerBuilder. createCopyValue ( operand: preheaderLoadBorrow)
896
+ loadCopyInst. replace ( with: copyValue, context)
897
+
898
+ var createdEndBorrow : EndBorrowInst ?
899
+ for exitBlock in loop. exitBlocks {
900
+ assert ( exitBlock. hasSinglePredecessor, " Exiting edge should not be critical. " )
901
+
902
+ if let createdEndBorrow {
903
+ createdEndBorrow. copy ( before: exitBlock. instructions. first!, context)
904
+ } else {
905
+ let exitBlockBuilder = Builder ( before: exitBlock. instructions. first!, context)
906
+ createdEndBorrow = exitBlockBuilder. createEndBorrow ( of: preheaderLoadBorrow)
907
+ }
908
+ }
909
+ }
910
+
882
911
func sink( outOf loop: Loop , _ context: FunctionPassContext ) -> Bool {
883
912
let exitBlocks = loop. exitBlocks
884
913
var changed = false
0 commit comments