@@ -40,7 +40,8 @@ class SILInstruction;
4040class SILLocation ;
4141class DeadEndBlocks ;
4242class ValueBaseUseIterator ;
43- class ValueUseIterator ;
43+ class ConsumingUseIterator ;
44+ class NonConsumingUseIterator ;
4445class SILValue ;
4546
4647// / An enumeration which contains values for all the concrete ValueBase
@@ -263,10 +264,20 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
263264
264265 using use_iterator = ValueBaseUseIterator;
265266 using use_range = iterator_range<use_iterator>;
267+ using consuming_use_iterator = ConsumingUseIterator;
268+ using consuming_use_range = iterator_range<consuming_use_iterator>;
269+ using non_consuming_use_iterator = NonConsumingUseIterator;
270+ using non_consuming_use_range = iterator_range<non_consuming_use_iterator>;
266271
267272 inline use_iterator use_begin () const ;
268273 inline use_iterator use_end () const ;
269274
275+ inline consuming_use_iterator consuming_use_begin () const ;
276+ inline consuming_use_iterator consuming_use_end () const ;
277+
278+ inline non_consuming_use_iterator non_consuming_use_begin () const ;
279+ inline non_consuming_use_iterator non_consuming_use_end () const ;
280+
270281 // / Returns a range of all uses, which is useful for iterating over all uses.
271282 // / To ignore debug-info instructions use swift::getNonDebugUses instead
272283 // / (see comment in DebugUtils.h).
@@ -285,6 +296,12 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
285296 // / and it has a single consuming user. Returns .none otherwise.
286297 inline Operand *getSingleConsumingUse () const ;
287298
299+ // / Returns a range of all consuming uses
300+ inline consuming_use_range getConsumingUses () const ;
301+
302+ // / Returns a range of all non consuming uses
303+ inline non_consuming_use_range getNonConsumingUses () const ;
304+
288305 template <class T >
289306 inline T *getSingleUserOfType () const ;
290307
@@ -711,8 +728,10 @@ class Operand {
711728 TheValue->FirstUse = this ;
712729 }
713730
731+ friend class ValueBase ;
714732 friend class ValueBaseUseIterator ;
715- friend class ValueUseIterator ;
733+ friend class ConsumingUseIterator ;
734+ friend class NonConsumingUseIterator ;
716735 template <unsigned N> friend class FixedOperandList ;
717736 friend class TrailingOperandsList ;
718737};
@@ -729,6 +748,7 @@ using OperandValueArrayRef = ArrayRefView<Operand, SILValue, getSILValueType>;
729748// / An iterator over all uses of a ValueBase.
730749class ValueBaseUseIterator : public std ::iterator<std::forward_iterator_tag,
731750 Operand*, ptrdiff_t > {
751+ protected:
732752 Operand *Cur;
733753public:
734754 ValueBaseUseIterator () = default ;
@@ -770,6 +790,74 @@ inline ValueBase::use_iterator ValueBase::use_end() const {
770790inline iterator_range<ValueBase::use_iterator> ValueBase::getUses () const {
771791 return { use_begin (), use_end () };
772792}
793+
794+ class ConsumingUseIterator : public ValueBaseUseIterator {
795+ public:
796+ explicit ConsumingUseIterator (Operand *cur) : ValueBaseUseIterator(cur) {}
797+ ConsumingUseIterator &operator ++() {
798+ assert (Cur && " incrementing past end()!" );
799+ assert (Cur->isConsumingUse ());
800+ while ((Cur = Cur->NextUse )) {
801+ if (Cur->isConsumingUse ())
802+ break ;
803+ }
804+ return *this ;
805+ }
806+
807+ ConsumingUseIterator operator ++(int unused) {
808+ ConsumingUseIterator copy = *this ;
809+ ++*this ;
810+ return copy;
811+ }
812+ };
813+
814+ inline ValueBase::consuming_use_iterator
815+ ValueBase::consuming_use_begin () const {
816+ auto cur = FirstUse;
817+ while (cur && !cur->isConsumingUse ()) {
818+ cur = cur->NextUse ;
819+ }
820+ return ValueBase::consuming_use_iterator (cur);
821+ }
822+
823+ inline ValueBase::consuming_use_iterator ValueBase::consuming_use_end () const {
824+ return ValueBase::consuming_use_iterator (nullptr );
825+ }
826+
827+ class NonConsumingUseIterator : public ValueBaseUseIterator {
828+ public:
829+ explicit NonConsumingUseIterator (Operand *cur) : ValueBaseUseIterator(cur) {}
830+ NonConsumingUseIterator &operator ++() {
831+ assert (Cur && " incrementing past end()!" );
832+ assert (!Cur->isConsumingUse ());
833+ while ((Cur = Cur->NextUse )) {
834+ if (!Cur->isConsumingUse ())
835+ break ;
836+ }
837+ return *this ;
838+ }
839+
840+ NonConsumingUseIterator operator ++(int unused) {
841+ NonConsumingUseIterator copy = *this ;
842+ ++*this ;
843+ return copy;
844+ }
845+ };
846+
847+ inline ValueBase::non_consuming_use_iterator
848+ ValueBase::non_consuming_use_begin () const {
849+ auto cur = FirstUse;
850+ while (cur && cur->isConsumingUse ()) {
851+ cur = cur->NextUse ;
852+ }
853+ return ValueBase::non_consuming_use_iterator (cur);
854+ }
855+
856+ inline ValueBase::non_consuming_use_iterator
857+ ValueBase::non_consuming_use_end () const {
858+ return ValueBase::non_consuming_use_iterator (nullptr );
859+ }
860+
773861inline bool ValueBase::hasOneUse () const {
774862 auto I = use_begin (), E = use_end ();
775863 if (I == E) return false ;
@@ -806,6 +894,15 @@ inline Operand *ValueBase::getSingleConsumingUse() const {
806894 return result;
807895}
808896
897+ inline ValueBase::consuming_use_range ValueBase::getConsumingUses () const {
898+ return {consuming_use_begin (), consuming_use_end ()};
899+ }
900+
901+ inline ValueBase::non_consuming_use_range
902+ ValueBase::getNonConsumingUses () const {
903+ return {non_consuming_use_begin (), non_consuming_use_end ()};
904+ }
905+
809906inline bool ValueBase::hasTwoUses () const {
810907 auto iter = use_begin (), end = use_end ();
811908 for (unsigned i = 0 ; i < 2 ; ++i) {
0 commit comments