@@ -88,8 +88,10 @@ class Use {
88
88
: LLVMUse(LLVMUse), User(User), Ctx(&Ctx) {}
89
89
Use () : LLVMUse(nullptr ), Ctx(nullptr ) {}
90
90
91
+ friend class Value ; // For constructor
91
92
friend class User ; // For constructor
92
93
friend class OperandUseIterator ; // For constructor
94
+ friend class UserUseIterator ; // For accessing members
93
95
94
96
public:
95
97
operator Value *() const { return get (); }
@@ -137,6 +139,31 @@ class OperandUseIterator {
137
139
}
138
140
};
139
141
142
+ // / Returns user edge when dereferenced.
143
+ class UserUseIterator {
144
+ Use Use;
145
+ // / Don't let the user create a non-empty UserUseIterator.
146
+ UserUseIterator (const class Use &Use) : Use(Use) {}
147
+ friend class Value ; // For constructor
148
+
149
+ public:
150
+ using difference_type = std::ptrdiff_t ;
151
+ using value_type = class Use ;
152
+ using pointer = value_type *;
153
+ using reference = value_type &;
154
+ using iterator_category = std::input_iterator_tag;
155
+
156
+ UserUseIterator () = default ;
157
+ value_type operator *() const { return Use; }
158
+ UserUseIterator &operator ++();
159
+ bool operator ==(const UserUseIterator &Other) const {
160
+ return Use == Other.Use ;
161
+ }
162
+ bool operator !=(const UserUseIterator &Other) const {
163
+ return !(*this == Other);
164
+ }
165
+ };
166
+
140
167
// / A SandboxIR Value has users. This is the base class.
141
168
class Value {
142
169
public:
@@ -188,9 +215,77 @@ class Value {
188
215
virtual ~Value () = default ;
189
216
ClassID getSubclassID () const { return SubclassID; }
190
217
218
+ using use_iterator = UserUseIterator;
219
+ using const_use_iterator = UserUseIterator;
220
+
221
+ use_iterator use_begin ();
222
+ const_use_iterator use_begin () const {
223
+ return const_cast <Value *>(this )->use_begin ();
224
+ }
225
+ use_iterator use_end () { return use_iterator (Use (nullptr , nullptr , Ctx)); }
226
+ const_use_iterator use_end () const {
227
+ return const_cast <Value *>(this )->use_end ();
228
+ }
229
+
230
+ iterator_range<use_iterator> uses () {
231
+ return make_range<use_iterator>(use_begin (), use_end ());
232
+ }
233
+ iterator_range<const_use_iterator> uses () const {
234
+ return make_range<const_use_iterator>(use_begin (), use_end ());
235
+ }
236
+
237
+ // / Helper for mapped_iterator.
238
+ struct UseToUser {
239
+ User *operator ()(const Use &Use) const { return &*Use.getUser (); }
240
+ };
241
+
242
+ using user_iterator = mapped_iterator<sandboxir::UserUseIterator, UseToUser>;
243
+ using const_user_iterator = user_iterator;
244
+
245
+ user_iterator user_begin ();
246
+ user_iterator user_end () {
247
+ return user_iterator (Use (nullptr , nullptr , Ctx), UseToUser ());
248
+ }
249
+ const_user_iterator user_begin () const {
250
+ return const_cast <Value *>(this )->user_begin ();
251
+ }
252
+ const_user_iterator user_end () const {
253
+ return const_cast <Value *>(this )->user_end ();
254
+ }
255
+
256
+ iterator_range<user_iterator> users () {
257
+ return make_range<user_iterator>(user_begin (), user_end ());
258
+ }
259
+ iterator_range<const_user_iterator> users () const {
260
+ return make_range<const_user_iterator>(user_begin (), user_end ());
261
+ }
262
+ // / \Returns the number of user edges (not necessarily to unique users).
263
+ // / WARNING: This is a linear-time operation.
264
+ unsigned getNumUses () const ;
265
+ // / Return true if this value has N uses or more.
266
+ // / This is logically equivalent to getNumUses() >= N.
267
+ // / WARNING: This can be expensive, as it is linear to the number of users.
268
+ bool hasNUsesOrMore (unsigned Num) const {
269
+ unsigned Cnt = 0 ;
270
+ for (auto It = use_begin (), ItE = use_end (); It != ItE; ++It) {
271
+ if (++Cnt >= Num)
272
+ return true ;
273
+ }
274
+ return false ;
275
+ }
276
+ // / Return true if this Value has exactly N uses.
277
+ bool hasNUses (unsigned Num) const {
278
+ unsigned Cnt = 0 ;
279
+ for (auto It = use_begin (), ItE = use_end (); It != ItE; ++It) {
280
+ if (++Cnt > Num)
281
+ return false ;
282
+ }
283
+ return Cnt == Num;
284
+ }
285
+
191
286
Type *getType () const { return Val->getType (); }
192
287
193
- Context &getContext () const ;
288
+ Context &getContext () const { return Ctx; }
194
289
#ifndef NDEBUG
195
290
// / Should crash if there is something wrong with the instruction.
196
291
virtual void verify () const = 0;
0 commit comments