@@ -757,12 +757,45 @@ struct OperandOwnership {
757
757
llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
758
758
const OperandOwnership &operandOwnership);
759
759
760
- // / Defined inline so the switch is eliminated for constant OperandOwnership.
760
+ // / Map OperandOwnership to the OwnershipConstraint used in OSSA validation.
761
+ // /
762
+ // / Each OperandOwnership kind maps directly to a fixed OwnershipConstraint. Any
763
+ // / value that can be legally passed to this operand must have an ownership kind
764
+ // / permitted by this constraint. A constraint permits an ownership kind if,
765
+ // / when it is applied to that ownership kind via a lattice join, it returns the
766
+ // / same ownership kind, indicating that no restriction exists.
767
+ // /
768
+ // / Consequently, OperandOwnership kinds that are allowed to take either Owned
769
+ // / or Guaranteed values map to an OwnershipKind::Any constraint.
770
+ // /
771
+ // / Unowned values are more restricted than then Owned or Guaranteed values in
772
+ // / terms of their valid uses, which helps limit the situations where the
773
+ // / implementation needs to consider this special case. This additional
774
+ // / restriction is validated by `canAcceptUnownedValue`.
775
+ // /
776
+ // / Forwarding instructions that produce Owned or Guaranteed values always
777
+ // / forward an operand of the same ownership kind. Each case has a distinct
778
+ // / OperandOwnership (ForwardingConsume and ForwardingBorrow), which enforces a
779
+ // / specific constraint on the operand's ownership. Forwarding instructions that
780
+ // / produce an Unowned value, however, may forward an operand of any
781
+ // / ownership. Therefore, ForwardingUnowned is mapped to OwnershipKind::Any.
782
+ // /
783
+ // / This design yields the following advantages:
784
+ // /
785
+ // / 1. Keeping the verification of Unowned in a separate utility avoids
786
+ // / the need to add an extra OwnedOrGuaranteed state to the OwnershipKind
787
+ // / lattice. That state would be meaningless as a representation of value
788
+ // / ownership, would serve no purpose as a data flow state, and would make
789
+ // / the basic definition of ownership less approachable to developers.
761
790
// /
762
- // / Here, an Any ownership constraint is used to allow either Owned or
763
- // / Guaranteed values. However, enforcement of Unowned values is more
764
- // / strict. This is handled by separate logic in canAcceptUnownedValue() to
765
- // / avoid complicating the OwnershipKind lattice.
791
+ // / 2. Owned or Guaranteed values can be passed to instructions that want to
792
+ // / produce an unowned result from a parent operand. This simplifies the IR
793
+ // / and makes RAUWing Unowned values with Owned or Guaranteed values much
794
+ // / easier since it does not need to introduce operations that convert those
795
+ // / values to Unowned. This significantly simplifies the implementation of
796
+ // / OSSA utilities.
797
+ // /
798
+ // / Defined inline so the switch is eliminated for constant OperandOwnership.
766
799
inline OwnershipConstraint OperandOwnership::getOwnershipConstraint () {
767
800
switch (value) {
768
801
case OperandOwnership::TrivialUse:
@@ -788,6 +821,31 @@ inline OwnershipConstraint OperandOwnership::getOwnershipConstraint() {
788
821
}
789
822
}
790
823
824
+ // / Return true if this use can accept Unowned values.
825
+ // /
826
+ // / This extra restriction is applied on top of the OwnershipConstraint to limit
827
+ // / the spread of Unowned values.
828
+ inline bool canAcceptUnownedValue (OperandOwnership operandOwnership) {
829
+ switch (operandOwnership) {
830
+ case OperandOwnership::NonUse:
831
+ case OperandOwnership::UnownedInstantaneousUse:
832
+ case OperandOwnership::ForwardingUnowned:
833
+ case OperandOwnership::PointerEscape:
834
+ case OperandOwnership::BitwiseEscape:
835
+ return true ;
836
+ case OperandOwnership::TrivialUse:
837
+ case OperandOwnership::InstantaneousUse:
838
+ case OperandOwnership::Borrow:
839
+ case OperandOwnership::DestroyingConsume:
840
+ case OperandOwnership::ForwardingConsume:
841
+ case OperandOwnership::InteriorPointer:
842
+ case OperandOwnership::ForwardingBorrow:
843
+ case OperandOwnership::EndBorrow:
844
+ case OperandOwnership::Reborrow:
845
+ return false ;
846
+ }
847
+ }
848
+
791
849
// / Return the OperandOwnership for a forwarded operand when the forwarded
792
850
// / result has this ValueOwnershipKind. \p allowUnowned is true for a subset
793
851
// / of forwarding operations that are allowed to propagate Unowned values.
0 commit comments