@@ -219,8 +219,13 @@ struct OwnershipKind {
219219 return OwnershipKind::None;
220220 return *this ;
221221 }
222+
223+ // / Convert this ownership kind to a StringRef.
224+ StringRef asString () const ;
222225};
223226
227+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os, const OwnershipKind &kind);
228+
224229// / A value representing the specific ownership semantics that a SILValue may
225230// / have.
226231struct ValueOwnershipKind {
@@ -566,150 +571,50 @@ inline bool ValueOwnershipKind::isCompatibleWith(SILValue other) const {
566571 return isCompatibleWith (other.getOwnershipKind ());
567572}
568573
569- // / A map from a ValueOwnershipKind that an operand can accept to a
570- // / UseLifetimeConstraint that describes the effect that the operand's use has
571- // / on the underlying value. If a ValueOwnershipKind is not in this map then
572- // / matching an operand with the value results in an ill formed program.
573- // /
574- // / So for instance, a map could specify that if a value is used as an owned
575- // / parameter, then the use implies that the original value is destroyed at that
576- // / point. In contrast, if the value is used as a guaranteed parameter, then the
577- // / liveness constraint just requires that the value remains alive at the use
578- // / point.
579- struct OperandOwnershipKindMap {
580- // One bit for if a value exists and if the value exists, what the
581- // ownership constraint is. These are stored as pairs.
582- //
583- // NOTE: We are burning 1 bit per unset value. But this is without
584- // matter since we are always going to need less bits than 64, so we
585- // should always have a small case SmallBitVector, so there is no
586- // difference in size.
587- static constexpr unsigned NUM_DATA_BITS =
588- 2 * (unsigned (OwnershipKind::LastValueOwnershipKind) + 1 );
589-
590- // / A bit vector representing our "map". Given a ValueOwnershipKind k, if the
591- // / operand can accept k, the unsigned(k)*2 bit will be set to true. Assuming
592- // / that bit is set, the unsigned(k)*2+1 bit is set to the use lifetime
593- // / constraint provided by the value.
594- SmallBitVector data;
595-
596- OperandOwnershipKindMap () : data(NUM_DATA_BITS) {}
597- OperandOwnershipKindMap (ValueOwnershipKind kind,
598- UseLifetimeConstraint constraint)
599- : data(NUM_DATA_BITS) {
600- add (kind, constraint);
601- }
574+ class OwnershipConstraint {
575+ OwnershipKind ownershipKind;
576+ UseLifetimeConstraint lifetimeConstraint;
602577
603- // / Return the OperandOwnershipKindMap that tests for compatibility with
604- // / ValueOwnershipKind kind. This means that it will accept a element whose
605- // / ownership is OwnershipKind::None.
606- static OperandOwnershipKindMap
607- compatibilityMap (ValueOwnershipKind kind, UseLifetimeConstraint constraint ) {
608- OperandOwnershipKindMap set;
609- set. addCompatibilityConstraint (kind, constraint);
610- return set ;
578+ public:
579+ OwnershipConstraint (OwnershipKind inputOwnershipKind,
580+ UseLifetimeConstraint inputLifetimeConstraint)
581+ : ownershipKind(inputOwnershipKind),
582+ lifetimeConstraint (inputLifetimeConstraint ) {
583+ assert ((ownershipKind != OwnershipKind::None ||
584+ lifetimeConstraint == UseLifetimeConstraint::NonLifetimeEnding) &&
585+ " ValueOwnershipKind::None can never have their lifetime ended " ) ;
611586 }
612587
613- // / Return a map that is compatible with any and all ValueOwnershipKinds
614- // / except for \p kind.
615- static OperandOwnershipKindMap
616- compatibleWithAllExcept (ValueOwnershipKind kind) {
617- OperandOwnershipKindMap map;
618- unsigned index = 0 ;
619- unsigned end = unsigned (OwnershipKind::LastValueOwnershipKind) + 1 ;
620- for (; index != end; ++index) {
621- if (ValueOwnershipKind (index) == kind) {
622- continue ;
623- }
624- map.add (ValueOwnershipKind (index),
625- UseLifetimeConstraint::NonLifetimeEnding);
626- }
627- return map;
588+ OwnershipKind getPreferredKind () const {
589+ return ownershipKind;
628590 }
629591
630- // / Create a map that has compatibility constraints for each of the
631- // / ValueOwnershipKind, UseLifetimeConstraints in \p args.
632- static OperandOwnershipKindMap
633- compatibilityMap (std::initializer_list<
634- std::pair<ValueOwnershipKind, UseLifetimeConstraint>>
635- args) {
636- OperandOwnershipKindMap map;
637- for (auto &p : args) {
638- map.addCompatibilityConstraint (p.first , p.second );
639- }
640- return map;
592+ bool isLifetimeEnding () const {
593+ return lifetimeConstraint == UseLifetimeConstraint::LifetimeEnding;
641594 }
642595
643- // / Return a map that states that an operand can take any ownership with each
644- // / ownership having a must be live constraint.
645- static OperandOwnershipKindMap allLive () {
646- OperandOwnershipKindMap map;
647- unsigned index = 0 ;
648- unsigned end = unsigned (OwnershipKind::LastValueOwnershipKind) + 1 ;
649- while (index != end) {
650- map.add (ValueOwnershipKind (index),
651- UseLifetimeConstraint::NonLifetimeEnding);
652- ++index;
653- }
654- return map;
596+ UseLifetimeConstraint getLifetimeConstraint () const {
597+ return lifetimeConstraint;
655598 }
656599
657- // / Specify that the operand associated with this set can accept a value with
658- // / ValueOwnershipKind \p kind. The value provided by the operand will have a
659- // / new ownership enforced constraint defined by \p constraint.
660- void add (ValueOwnershipKind kind, UseLifetimeConstraint constraint) {
661- unsigned index = unsigned (kind);
662- unsigned kindOffset = index * 2 ;
663- unsigned constraintOffset = index * 2 + 1 ;
664-
665- // If we have already put this kind into the map, we require the constraint
666- // offset to be the same, i.e. we only allow for a kind to be added twice if
667- // the constraint is idempotent. We assert otherwise.
668- assert ((!data[kindOffset] || UseLifetimeConstraint (bool (
669- data[constraintOffset])) == constraint) &&
670- " Adding kind twice to the map with different constraints?!" );
671- data[kindOffset] = true ;
672- data[constraintOffset] = bool (constraint);
600+ static OwnershipConstraint anyValueAcceptingConstraint () {
601+ return {OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding};
673602 }
674603
675- void addCompatibilityConstraint (ValueOwnershipKind kind,
676- UseLifetimeConstraint constraint) {
677- add (OwnershipKind::None, UseLifetimeConstraint::NonLifetimeEnding);
678- add (kind, constraint);
679- }
604+ bool satisfiedBy (const Operand *use) const ;
680605
681- bool canAcceptKind (ValueOwnershipKind kind) const {
682- unsigned index = unsigned (kind);
683- unsigned kindOffset = index * 2 ;
684- return data[kindOffset];
606+ bool satisfiesConstraint (ValueOwnershipKind testKind) const {
607+ return ownershipKind.join (testKind) == testKind;
685608 }
686609
687- UseLifetimeConstraint getLifetimeConstraint (ValueOwnershipKind kind ) const ;
688-
689- void print (llvm::raw_ostream &os) const ;
690- SWIFT_DEBUG_DUMP;
610+ bool operator ==( const OwnershipConstraint &other ) const {
611+ return ownershipKind == other. ownershipKind &&
612+ isLifetimeEnding () == other. isLifetimeEnding () ;
613+ }
691614};
692615
693- inline llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
694- OperandOwnershipKindMap map) {
695- map.print (os);
696- return os;
697- }
698-
699- // Out of line to work around lack of forward declaration for operator <<.
700- inline UseLifetimeConstraint
701- OperandOwnershipKindMap::getLifetimeConstraint (ValueOwnershipKind kind) const {
702- #ifndef NDEBUG
703- if (!canAcceptKind (kind)) {
704- llvm::errs () << " Can not lookup lifetime constraint: " << kind
705- << " . Not in map!\n "
706- << *this ;
707- llvm_unreachable (" standard error assertion" );
708- }
709- #endif
710- unsigned constraintOffset = unsigned (kind) * 2 + 1 ;
711- return UseLifetimeConstraint (data[constraintOffset]);
712- }
616+ llvm::raw_ostream &operator <<(llvm::raw_ostream &os,
617+ OwnershipConstraint constraint);
713618
714619// / A formal SIL reference to a value, suitable for use as a stored
715620// / operand.
@@ -788,24 +693,25 @@ class Operand {
788693 // / Return which operand this is in the operand list of the using instruction.
789694 unsigned getOperandNumber () const ;
790695
791- // / Return the static map of ValueOwnershipKinds that this operand can
792- // / potentially have to the UseLifetimeConstraint associated with that
793- // / ownership kind
696+ // / Return the ownership constraint that restricts what types of values this
697+ // / Operand can contain. Returns none if the operand is a type dependent
698+ // / operand.
794699 // /
795700 // / NOTE: This is implemented in OperandOwnership.cpp.
796- OperandOwnershipKindMap getOwnershipKindMap () const ;
701+ Optional<OwnershipConstraint> getOwnershipConstraint () const ;
702+
703+ // / Returns true if changing the operand to use a value with the given
704+ // / ownership kind would not cause the operand to violate the operand's
705+ // / ownership constraints. Returns false otherwise.
706+ bool canAcceptKind (ValueOwnershipKind kind) const ;
707+
708+ // / Returns true if this operand and its value satisfy the operand's
709+ // / operand constraint.
710+ bool satisfiesConstraints () const ;
797711
798712 // / Returns true if this operand acts as a use that consumes its associated
799713 // / value.
800- bool isLifetimeEnding () const {
801- // Type dependent uses can never be consuming and do not have valid
802- // ownership maps since they do not participate in the ownership system.
803- if (isTypeDependent ())
804- return false ;
805- auto map = getOwnershipKindMap ();
806- auto constraint = map.getLifetimeConstraint (get ().getOwnershipKind ());
807- return constraint == UseLifetimeConstraint::LifetimeEnding;
808- }
714+ bool isLifetimeEnding () const ;
809715
810716 SILBasicBlock *getParentBlock () const ;
811717 SILFunction *getParentFunction () const ;
0 commit comments