@@ -58,6 +58,14 @@ bool isOwnedForwardingValueKind(SILNodeKind kind);
58
58
// / forward guaranteed ownership.
59
59
bool isOwnedForwardingInstruction (SILInstruction *inst);
60
60
61
+ // / Does this value 'forward' owned ownership, but may not be able to forward
62
+ // / guaranteed ownership.
63
+ // /
64
+ // / This will be either a multiple value instruction resuilt, a single value
65
+ // / instruction that forwards or an argument that forwards the ownership from a
66
+ // / previous terminator.
67
+ bool isOwnedForwardingValue (SILValue value);
68
+
61
69
struct BorrowScopeOperandKind {
62
70
enum Kind {
63
71
BeginBorrow,
@@ -371,13 +379,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
371
379
bool getAllBorrowIntroducingValues (
372
380
SILValue value, SmallVectorImpl<BorrowScopeIntroducingValue> &out);
373
381
374
- // / Look up the def-use graph starting at \p inputOperand and see if
375
- // / we can find a single BorrowScopeIntroducingValue for \p
376
- // / inputOperand. Returns None if there are multiple such introducers
377
- // / or if while processing we find a user we do not understand.
378
- Optional<BorrowScopeIntroducingValue>
379
- getSingleBorrowIntroducingValue (SILValue value);
380
-
381
382
// / Look up through the def-use chain of \p inputValue, looking for an initial
382
383
// / "borrow" introducing value. If at any point, we find two introducers or we
383
384
// / find a point in the chain we do not understand, we bail and return false. If
@@ -467,6 +468,164 @@ struct InteriorPointerOperand {
467
468
: operand(op), kind(kind) {}
468
469
};
469
470
471
+ struct OwnedValueIntroducerKind {
472
+ enum Kind {
473
+ // / An owned value that is a result of an Apply.
474
+ Apply,
475
+
476
+ // / An owned value returned as a result of applying a begin_apply.
477
+ BeginApply,
478
+
479
+ // / An owned value that is an argument that is in one of the successor
480
+ // / blocks of a try_apply. This represents in a sense the try applies
481
+ // / result.
482
+ TryApply,
483
+
484
+ // / An owned value produced as a result of performing a copy_value on some
485
+ // / other value.
486
+ Copy,
487
+
488
+ // / An owned value produced as a result of performing a load [copy] on a
489
+ // / memory location.
490
+ LoadCopy,
491
+
492
+ // / An owned value produced as a result of performing a load [take] from a
493
+ // / memory location.
494
+ LoadTake,
495
+
496
+ // / An owned value that is a result of a true phi argument.
497
+ // /
498
+ // / A true phi argument here is defined as an SIL phi argument that only has
499
+ // / branch predecessors.
500
+ Phi,
501
+
502
+ // / An owned value that is a function argument.
503
+ FunctionArgument,
504
+
505
+ // / An owned value that is a new partial_apply that has been formed.
506
+ PartialApplyInit,
507
+
508
+ // / An owned value from the formation of a new alloc_box.
509
+ AllocBoxInit,
510
+
511
+ // / An owned value from the formataion of a new alloc_ref.
512
+ AllocRefInit,
513
+ };
514
+
515
+ static Optional<OwnedValueIntroducerKind> get (SILValue value) {
516
+ if (value.getOwnershipKind () != ValueOwnershipKind::Owned)
517
+ return None;
518
+
519
+ switch (value->getKind ()) {
520
+ default :
521
+ return None;
522
+ case ValueKind::ApplyInst:
523
+ return OwnedValueIntroducerKind (Apply);
524
+ case ValueKind::BeginApplyResult:
525
+ return OwnedValueIntroducerKind (BeginApply);
526
+ case ValueKind::SILPhiArgument: {
527
+ auto *phiArg = cast<SILPhiArgument>(value);
528
+ if (dyn_cast_or_null<TryApplyInst>(phiArg->getSingleTerminator ())) {
529
+ return OwnedValueIntroducerKind (TryApply);
530
+ }
531
+ if (llvm::all_of (phiArg->getParent ()->getPredecessorBlocks (),
532
+ [](SILBasicBlock *block) {
533
+ return isa<BranchInst>(block->getTerminator ());
534
+ })) {
535
+ return OwnedValueIntroducerKind (Phi);
536
+ }
537
+ return None;
538
+ }
539
+ case ValueKind::SILFunctionArgument:
540
+ return OwnedValueIntroducerKind (FunctionArgument);
541
+ case ValueKind::CopyValueInst:
542
+ return OwnedValueIntroducerKind (Copy);
543
+ case ValueKind::LoadInst: {
544
+ auto qual = cast<LoadInst>(value)->getOwnershipQualifier ();
545
+ if (qual == LoadOwnershipQualifier::Take)
546
+ return OwnedValueIntroducerKind (LoadTake);
547
+ if (qual == LoadOwnershipQualifier::Copy)
548
+ return OwnedValueIntroducerKind (LoadCopy);
549
+ return None;
550
+ }
551
+ case ValueKind::PartialApplyInst:
552
+ return OwnedValueIntroducerKind (PartialApplyInit);
553
+ case ValueKind::AllocBoxInst:
554
+ return OwnedValueIntroducerKind (AllocBoxInit);
555
+ case ValueKind::AllocRefInst:
556
+ return OwnedValueIntroducerKind (AllocRefInit);
557
+ }
558
+ llvm_unreachable (" Default should have caught this" );
559
+ }
560
+
561
+ Kind value;
562
+
563
+ OwnedValueIntroducerKind (Kind newValue) : value(newValue) {}
564
+ OwnedValueIntroducerKind (const OwnedValueIntroducerKind &other)
565
+ : value(other.value) {}
566
+ operator Kind () const { return value; }
567
+
568
+ void print (llvm::raw_ostream &os) const ;
569
+ SWIFT_DEBUG_DUMP { print (llvm::dbgs ()); }
570
+ };
571
+
572
+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
573
+ OwnedValueIntroducerKind kind);
574
+
575
+ // / A higher level construct for working with values that introduce a new
576
+ // / "owned" value.
577
+ // /
578
+ // / An owned "introducer" is a value that signals in a SIL program the begin of
579
+ // / a new semantic @owned ownership construct that is live without respect to
580
+ // / any other values in the function. This introducer value is then either used
581
+ // / directly, forwarded then used, and then finally destroyed.
582
+ // /
583
+ // / NOTE: Previous incarnations of this concept used terms like "RC-identity".
584
+ struct OwnedValueIntroducer {
585
+ // / The actual underlying value that introduces the new owned value.
586
+ SILValue value;
587
+
588
+ // / The kind of "introducer" that we use to classify any of various possible
589
+ // / underlying introducing values.
590
+ OwnedValueIntroducerKind kind;
591
+
592
+ // / If a value is an owned value introducer we can recognize, return
593
+ // / .some(OwnedValueIntroducer). Otherwise, return None.
594
+ static Optional<OwnedValueIntroducer> get (SILValue value) {
595
+ auto kind = OwnedValueIntroducerKind::get (value);
596
+ if (!kind)
597
+ return None;
598
+ return OwnedValueIntroducer (value, *kind);
599
+ }
600
+
601
+ bool operator ==(const OwnedValueIntroducer &other) const {
602
+ return value == other.value ;
603
+ }
604
+
605
+ bool operator !=(const OwnedValueIntroducer &other) const {
606
+ return !(*this == other);
607
+ }
608
+
609
+ bool operator <(const OwnedValueIntroducer &other) const {
610
+ return value < other.value ;
611
+ }
612
+
613
+ private:
614
+ OwnedValueIntroducer (SILValue value, OwnedValueIntroducerKind kind)
615
+ : value(value), kind(kind) {}
616
+ };
617
+
618
+ // / Look up the def-use graph starting at use \p inputOperand, recording any
619
+ // / values that act as "owned" introducers.
620
+ // /
621
+ // / NOTE: This may return multiple owned introducers in cases where there are
622
+ // / phi-like nodes in the IR like any true phi block arguments or aggregate
623
+ // / literal instructions (struct, tuple, enum, etc.).
624
+ bool getAllOwnedValueIntroducers (SILValue value,
625
+ SmallVectorImpl<OwnedValueIntroducer> &out);
626
+
627
+ Optional<OwnedValueIntroducer> getSingleOwnedValueIntroducer (SILValue value);
628
+
470
629
} // namespace swift
471
630
472
631
#endif
0 commit comments