@@ -85,6 +85,17 @@ bool swift::isOwnedForwardingInstruction(SILInstruction *inst) {
85
85
}
86
86
}
87
87
88
+ bool swift::isOwnedForwardingValue (SILValue value) {
89
+ switch (value->getKind ()) {
90
+ // Phi arguments always forward ownership.
91
+ case ValueKind::SILPhiArgument:
92
+ return true ;
93
+ default :
94
+ return isOwnedForwardingValueKind (
95
+ value->getKindOfRepresentativeSILNodeInObject ());
96
+ }
97
+ }
98
+
88
99
bool swift::isGuaranteedForwardingValue (SILValue value) {
89
100
// If we have an argument from a transforming terminator, we can forward
90
101
// guaranteed.
@@ -95,6 +106,7 @@ bool swift::isGuaranteedForwardingValue(SILValue value) {
95
106
}
96
107
}
97
108
}
109
+
98
110
return isGuaranteedForwardingValueKind (
99
111
value->getKindOfRepresentativeSILNodeInObject ());
100
112
}
@@ -443,6 +455,49 @@ bool BorrowScopeIntroducingValue::visitInteriorPointerOperands(
443
455
return true ;
444
456
}
445
457
458
+ // ===----------------------------------------------------------------------===//
459
+ // Owned Value Introducers
460
+ // ===----------------------------------------------------------------------===//
461
+
462
+ void OwnedValueIntroducerKind::print (llvm::raw_ostream &os) const {
463
+ switch (value) {
464
+ case OwnedValueIntroducerKind::Apply:
465
+ os << " Apply" ;
466
+ return ;
467
+ case OwnedValueIntroducerKind::BeginApply:
468
+ os << " BeginApply" ;
469
+ return ;
470
+ case OwnedValueIntroducerKind::TryApply:
471
+ os << " TryApply" ;
472
+ return ;
473
+ case OwnedValueIntroducerKind::Copy:
474
+ os << " Copy" ;
475
+ return ;
476
+ case OwnedValueIntroducerKind::LoadCopy:
477
+ os << " LoadCopy" ;
478
+ return ;
479
+ case OwnedValueIntroducerKind::LoadTake:
480
+ os << " LoadTake" ;
481
+ return ;
482
+ case OwnedValueIntroducerKind::Phi:
483
+ os << " Phi" ;
484
+ return ;
485
+ case OwnedValueIntroducerKind::FunctionArgument:
486
+ os << " FunctionArgument" ;
487
+ return ;
488
+ case OwnedValueIntroducerKind::PartialApplyInit:
489
+ os << " PartialApplyInit" ;
490
+ return ;
491
+ case OwnedValueIntroducerKind::AllocBoxInit:
492
+ os << " AllocBoxInit" ;
493
+ return ;
494
+ case OwnedValueIntroducerKind::AllocRefInit:
495
+ os << " AllocRefInit" ;
496
+ return ;
497
+ }
498
+ llvm_unreachable (" Covered switch isn't covered" );
499
+ }
500
+
446
501
// ===----------------------------------------------------------------------===//
447
502
// Introducer Searching Routines
448
503
// ===----------------------------------------------------------------------===//
@@ -546,3 +601,103 @@ swift::getSingleBorrowIntroducingValue(SILValue inputValue) {
546
601
547
602
llvm_unreachable (" Should never hit this" );
548
603
}
604
+
605
+ bool swift::getAllOwnedValueIntroducers (
606
+ SILValue inputValue, SmallVectorImpl<OwnedValueIntroducer> &out) {
607
+ if (inputValue.getOwnershipKind () != ValueOwnershipKind::Owned)
608
+ return false ;
609
+
610
+ SmallVector<SILValue, 32 > worklist;
611
+ worklist.emplace_back (inputValue);
612
+
613
+ while (!worklist.empty ()) {
614
+ SILValue value = worklist.pop_back_val ();
615
+
616
+ // First check if v is an introducer. If so, stash it and continue.
617
+ if (auto introducer = OwnedValueIntroducer::get (value)) {
618
+ out.push_back (*introducer);
619
+ continue ;
620
+ }
621
+
622
+ // If v produces .none ownership, then we can ignore it. It is important
623
+ // that we put this before checking for guaranteed forwarding instructions,
624
+ // since we want to ignore guaranteed forwarding instructions that in this
625
+ // specific case produce a .none value.
626
+ if (value.getOwnershipKind () == ValueOwnershipKind::None)
627
+ continue ;
628
+
629
+ // Otherwise if v is an ownership forwarding value, add its defining
630
+ // instruction
631
+ if (isOwnedForwardingValue (value)) {
632
+ if (auto *i = value->getDefiningInstruction ()) {
633
+ llvm::copy (i->getOperandValues (true /* skip type dependent ops*/ ),
634
+ std::back_inserter (worklist));
635
+ continue ;
636
+ }
637
+
638
+ // Otherwise, we should have a block argument that is defined by a single
639
+ // predecessor terminator.
640
+ auto *arg = cast<SILPhiArgument>(value);
641
+ auto *termInst = arg->getSingleTerminator ();
642
+ assert (termInst && termInst->isTransformationTerminator ());
643
+ assert (termInst->getNumOperands () == 1 &&
644
+ " Transforming terminators should always have a single operand" );
645
+ worklist.push_back (termInst->getAllOperands ()[0 ].get ());
646
+ continue ;
647
+ }
648
+
649
+ // Otherwise, this is an introducer we do not understand. Bail and return
650
+ // false.
651
+ return false ;
652
+ }
653
+
654
+ return true ;
655
+ }
656
+
657
+ Optional<OwnedValueIntroducer>
658
+ swift::getSingleOwnedValueIntroducer (SILValue inputValue) {
659
+ if (inputValue.getOwnershipKind () != ValueOwnershipKind::Owned)
660
+ return None;
661
+
662
+ SILValue currentValue = inputValue;
663
+ while (true ) {
664
+ // First check if our initial value is an introducer. If we have one, just
665
+ // return it.
666
+ if (auto introducer = OwnedValueIntroducer::get (currentValue)) {
667
+ return introducer;
668
+ }
669
+
670
+ // Otherwise if v is an ownership forwarding value, add its defining
671
+ // instruction
672
+ if (isOwnedForwardingValue (currentValue)) {
673
+ if (auto *i = currentValue->getDefiningInstruction ()) {
674
+ auto instOps = i->getOperandValues (true /* ignore type dependent ops*/ );
675
+ // If we have multiple incoming values, return .None. We can't handle
676
+ // this.
677
+ auto begin = instOps.begin ();
678
+ if (std::next (begin) != instOps.end ()) {
679
+ return None;
680
+ }
681
+ // Otherwise, set currentOp to the single operand and continue.
682
+ currentValue = *begin;
683
+ continue ;
684
+ }
685
+
686
+ // Otherwise, we should have a block argument that is defined by a single
687
+ // predecessor terminator.
688
+ auto *arg = cast<SILPhiArgument>(currentValue);
689
+ auto *termInst = arg->getSingleTerminator ();
690
+ assert (termInst && termInst->isTransformationTerminator ());
691
+ assert (termInst->getNumOperands () == 1 &&
692
+ " Transformation terminators should only have single operands" );
693
+ currentValue = termInst->getAllOperands ()[0 ].get ();
694
+ continue ;
695
+ }
696
+
697
+ // Otherwise, this is an introducer we do not understand. Bail and return
698
+ // None.
699
+ return None;
700
+ }
701
+
702
+ llvm_unreachable (" Should never hit this" );
703
+ }
0 commit comments