@@ -237,6 +237,90 @@ class SelectEnumOperation {
237
237
}
238
238
};
239
239
240
+ class ForwardingOperation {
241
+ SILInstruction *forwardingInst = nullptr ;
242
+
243
+ public:
244
+ explicit ForwardingOperation (SILInstruction *inst);
245
+
246
+ operator bool () const { return bool (forwardingInst); }
247
+ const SILInstruction *operator ->() const { return forwardingInst; }
248
+ SILInstruction *operator ->() { return forwardingInst; }
249
+ const SILInstruction *operator *() const { return forwardingInst; }
250
+ SILInstruction *operator *() { return forwardingInst; }
251
+
252
+ ValueOwnershipKind getForwardingOwnershipKind ();
253
+ bool preservesOwnership ();
254
+
255
+ // FIXME: Find a better name. Even unary instructions like struct_extract
256
+ // forward "all" operands.
257
+ bool canForwardAllOperands () const {
258
+ switch (forwardingInst->getKind ()) {
259
+ case SILInstructionKind::StructInst:
260
+ case SILInstructionKind::TupleInst:
261
+ case SILInstructionKind::LinearFunctionInst:
262
+ case SILInstructionKind::DifferentiableFunctionInst:
263
+ return true ;
264
+ default :
265
+ return false ;
266
+ }
267
+ }
268
+
269
+ // FIXME: Find a better name. Even instructions that forward all operands can
270
+ // forward the first operand.
271
+ bool canForwardFirstOperandOnly () const {
272
+ return !canForwardAllOperands () && forwardingInst->getNumRealOperands () > 0 ;
273
+ }
274
+
275
+ ArrayRef<Operand> getForwardedOperands () const {
276
+ if (canForwardAllOperands ()) {
277
+ return forwardingInst->getAllOperands ();
278
+ }
279
+ if (canForwardFirstOperandOnly ()) {
280
+ return forwardingInst->getOperandRef (0 );
281
+ }
282
+ return {};
283
+ }
284
+
285
+ MutableArrayRef<Operand> getForwardedOperands () {
286
+ if (canForwardAllOperands ()) {
287
+ return forwardingInst->getAllOperands ();
288
+ }
289
+ if (canForwardFirstOperandOnly ()) {
290
+ return forwardingInst->getOperandRef (0 );
291
+ }
292
+ return {};
293
+ }
294
+
295
+ bool canForwardOwnedCompatibleValuesOnly () {
296
+ switch (forwardingInst->getKind ()) {
297
+ case SILInstructionKind::MarkUninitializedInst:
298
+ return true ;
299
+ default :
300
+ return false ;
301
+ }
302
+ }
303
+
304
+ bool canForwardGuaranteedCompatibleValuesOnly () {
305
+ switch (forwardingInst->getKind ()) {
306
+ case SILInstructionKind::TupleExtractInst:
307
+ case SILInstructionKind::StructExtractInst:
308
+ case SILInstructionKind::DifferentiableFunctionExtractInst:
309
+ case SILInstructionKind::LinearFunctionExtractInst:
310
+ return true ;
311
+ default :
312
+ return false ;
313
+ }
314
+ }
315
+
316
+ // / Return true if the forwarded value has the same representation. If true,
317
+ // / then the result can be mapped to the same storage without a move or copy.
318
+ bool hasSameRepresentation () const ;
319
+
320
+ // / Return true if the forwarded value is address-only either before or after
321
+ // / forwarding.
322
+ bool isAddressOnly () const ;
323
+ };
240
324
} // end namespace swift
241
325
242
326
#endif
0 commit comments