@@ -146,6 +146,99 @@ extension Instruction {
146
146
}
147
147
}
148
148
149
+ extension StoreInst {
150
+ func trySplit( _ context: FunctionPassContext ) {
151
+ let builder = Builder ( after: self , context)
152
+ let type = source. type
153
+ if type. isStruct {
154
+ if type. nominal. isStructWithUnreferenceableStorage {
155
+ return
156
+ }
157
+ if parentFunction. hasOwnership && source. ownership != . none {
158
+ let destructure = builder. createDestructureStruct ( struct: source)
159
+ for (fieldIdx, fieldValue) in destructure. results. enumerated ( ) {
160
+ let destFieldAddr = builder. createStructElementAddr ( structAddress: destination, fieldIndex: fieldIdx)
161
+ builder. createStore ( source: fieldValue, destination: destFieldAddr, ownership: splitOwnership ( for: fieldValue) )
162
+ }
163
+ } else {
164
+ for idx in 0 ..< type. getNominalFields ( in: parentFunction) . count {
165
+ let srcField = builder. createStructExtract ( struct: source, fieldIndex: idx)
166
+ let fieldAddr = builder. createStructElementAddr ( structAddress: destination, fieldIndex: idx)
167
+ builder. createStore ( source: srcField, destination: fieldAddr, ownership: splitOwnership ( for: srcField) )
168
+ }
169
+ }
170
+ } else if type. isTuple {
171
+ if parentFunction. hasOwnership && source. ownership != . none {
172
+ let destructure = builder. createDestructureTuple ( tuple: source)
173
+ for (elementIdx, elementValue) in destructure. results. enumerated ( ) {
174
+ let elementAddr = builder. createTupleElementAddr ( tupleAddress: destination, elementIndex: elementIdx)
175
+ builder. createStore ( source: elementValue, destination: elementAddr, ownership: splitOwnership ( for: elementValue) )
176
+ }
177
+ } else {
178
+ for idx in 0 ..< type. tupleElements. count {
179
+ let srcField = builder. createTupleExtract ( tuple: source, elementIndex: idx)
180
+ let destFieldAddr = builder. createTupleElementAddr ( tupleAddress: destination, elementIndex: idx)
181
+ builder. createStore ( source: srcField, destination: destFieldAddr, ownership: splitOwnership ( for: srcField) )
182
+ }
183
+ }
184
+ } else {
185
+ return
186
+ }
187
+ context. erase ( instruction: self )
188
+ }
189
+
190
+ private func splitOwnership( for fieldValue: Value ) -> StoreOwnership {
191
+ switch self . storeOwnership {
192
+ case . trivial, . unqualified:
193
+ return self . storeOwnership
194
+ case . assign, . initialize:
195
+ return fieldValue. type. isTrivial ( in: parentFunction) ? . trivial : self . storeOwnership
196
+ }
197
+ }
198
+ }
199
+
200
+ extension LoadInst {
201
+ func trySplit( _ context: FunctionPassContext ) {
202
+ var elements = [ Value] ( )
203
+ let builder = Builder ( before: self , context)
204
+ if type. isStruct {
205
+ if type. nominal. isStructWithUnreferenceableStorage {
206
+ return
207
+ }
208
+ for idx in 0 ..< type. getNominalFields ( in: parentFunction) . count {
209
+ let fieldAddr = builder. createStructElementAddr ( structAddress: address, fieldIndex: idx)
210
+ let splitLoad = builder. createLoad ( fromAddress: fieldAddr, ownership: self . splitOwnership ( for: fieldAddr) )
211
+ elements. append ( splitLoad)
212
+ }
213
+ let newStruct = builder. createStruct ( type: self . type, elements: elements)
214
+ self . uses. replaceAll ( with: newStruct, context)
215
+ } else if type. isTuple {
216
+ var elements = [ Value] ( )
217
+ let builder = Builder ( before: self , context)
218
+ for idx in 0 ..< type. tupleElements. count {
219
+ let fieldAddr = builder. createTupleElementAddr ( tupleAddress: address, elementIndex: idx)
220
+ let splitLoad = builder. createLoad ( fromAddress: fieldAddr, ownership: self . splitOwnership ( for: fieldAddr) )
221
+ elements. append ( splitLoad)
222
+ }
223
+ let newTuple = builder. createTuple ( type: self . type, elements: elements)
224
+ self . uses. replaceAll ( with: newTuple, context)
225
+ } else {
226
+ return
227
+ }
228
+ context. erase ( instruction: self )
229
+ }
230
+
231
+ private func splitOwnership( for fieldValue: Value ) -> LoadOwnership {
232
+ switch self . loadOwnership {
233
+ case . trivial, . unqualified:
234
+ return self . loadOwnership
235
+ case . copy, . take:
236
+ return fieldValue. type. isTrivial ( in: parentFunction) ? . trivial : self . loadOwnership
237
+ }
238
+ }
239
+ }
240
+
241
+
149
242
extension UseList {
150
243
var singleNonDebugUse : Operand ? {
151
244
var singleUse : Operand ?
0 commit comments