12
12
//
13
13
// This file defines efficient data structures for working with Nodes.
14
14
//
15
- // TODO: Add an InstructionWorklist similar to BasicBlockWorklist.
16
- //
17
15
// ===----------------------------------------------------------------------===//
18
16
19
17
#ifndef SWIFT_SIL_NODEDATASTRUCTURES_H
@@ -29,7 +27,7 @@ namespace swift {
29
27
// / NodeSet>`.
30
28
// /
31
29
// / Unfortunately it's not possible to use `llvm::SetVector` directly because
32
- // / the ValueSet and StackList constructors needs a `SILFunction` argument.
30
+ // / the NodeSet and StackList constructors needs a `SILFunction` argument.
33
31
// /
34
32
// / Note: This class does not provide a `remove` method intentionally, because
35
33
// / it would have a O(n) complexity.
@@ -63,6 +61,112 @@ class NodeSetVector {
63
61
}
64
62
};
65
63
64
+ // / An implementation of `llvm::SetVector<SILInstruction *,
65
+ // / StackList<SILInstruction *>,
66
+ // / InstructionSet>`.
67
+ // /
68
+ // / Unfortunately it's not possible to use `llvm::SetVector` directly because
69
+ // / the InstructionSet and StackList constructors needs a `SILFunction`
70
+ // / argument.
71
+ // /
72
+ // / Note: This class does not provide a `remove` method intentionally, because
73
+ // / it would have a O(n) complexity.
74
+ class InstructionSetVector {
75
+ StackList<SILInstruction *> vector;
76
+ InstructionSet set;
77
+
78
+ public:
79
+ using iterator = typename StackList<SILInstruction *>::iterator;
80
+
81
+ InstructionSetVector (SILFunction *function)
82
+ : vector(function), set(function) {}
83
+
84
+ iterator begin () const { return vector.begin (); }
85
+ iterator end () const { return vector.end (); }
86
+
87
+ llvm::iterator_range<iterator> getRange () const {
88
+ return llvm::make_range (begin (), end ());
89
+ }
90
+
91
+ bool empty () const { return vector.empty (); }
92
+
93
+ bool contains (SILInstruction *instruction) const {
94
+ return set.contains (instruction);
95
+ }
96
+
97
+ // / Returns true if \p instruction was not contained in the set before
98
+ // / inserting.
99
+ bool insert (SILInstruction *instruction) {
100
+ if (set.insert (instruction)) {
101
+ vector.push_back (instruction);
102
+ return true ;
103
+ }
104
+ return false ;
105
+ }
106
+ };
107
+
108
+ // / A utility for processing instructions in a worklist.
109
+ // /
110
+ // / It is basically a combination of an instruction vector and an instruction
111
+ // / set. It can be used for typical worklist-processing algorithms.
112
+ class InstructionWorklist {
113
+ StackList<SILInstruction *> worklist;
114
+ InstructionSet visited;
115
+
116
+ public:
117
+ // / Construct an empty worklist.
118
+ InstructionWorklist (SILFunction *function)
119
+ : worklist(function), visited(function) {}
120
+
121
+ // / Initialize the worklist with \p initialBlock.
122
+ InstructionWorklist (SILInstruction *initialInstruction)
123
+ : InstructionWorklist(initialInstruction->getFunction ()) {
124
+ push (initialInstruction);
125
+ }
126
+
127
+ // / Pops the last added element from the worklist or returns null, if the
128
+ // / worklist is empty.
129
+ SILInstruction *pop () {
130
+ if (worklist.empty ())
131
+ return nullptr ;
132
+ return worklist.pop_back_val ();
133
+ }
134
+
135
+ // / Pushes \p instruction onto the worklist if \p instruction has never been
136
+ // / push before.
137
+ bool pushIfNotVisited (SILInstruction *instruction) {
138
+ if (visited.insert (instruction)) {
139
+ worklist.push_back (instruction);
140
+ return true ;
141
+ }
142
+ return false ;
143
+ }
144
+
145
+ // / Like `pushIfNotVisited`, but requires that \p instruction has never been
146
+ // / on the worklist before.
147
+ void push (SILInstruction *instruction) {
148
+ assert (!visited.contains (instruction));
149
+ visited.insert (instruction);
150
+ worklist.push_back (instruction);
151
+ }
152
+
153
+ // / Like `pop`, but marks the returned instruction as "unvisited". This means,
154
+ // / that the instruction can be pushed onto the worklist again.
155
+ SILInstruction *popAndForget () {
156
+ if (worklist.empty ())
157
+ return nullptr ;
158
+ SILInstruction *instruction = worklist.pop_back_val ();
159
+ visited.erase (instruction);
160
+ return instruction;
161
+ }
162
+
163
+ // / Returns true if \p instruction was visited, i.e. has been added to the
164
+ // / worklist.
165
+ bool isVisited (SILInstruction *instruction) const {
166
+ return visited.contains (instruction);
167
+ }
168
+ };
169
+
66
170
// / An implementation of `llvm::SetVector<SILValue,
67
171
// / StackList<SILValue>,
68
172
// / ValueSet>`.
@@ -102,6 +206,64 @@ class ValueSetVector {
102
206
}
103
207
};
104
208
209
+ // / A utility for processing values in a worklist.
210
+ // /
211
+ // / It is basically a combination of a value vector and a value set. It can be
212
+ // / used for typical worklist-processing algorithms.
213
+ class ValueWorklist {
214
+ StackList<SILValue> worklist;
215
+ ValueSet visited;
216
+
217
+ public:
218
+ // / Construct an empty worklist.
219
+ ValueWorklist (SILFunction *function)
220
+ : worklist(function), visited(function) {}
221
+
222
+ // / Initialize the worklist with \p initialValue.
223
+ ValueWorklist (SILValue initialValue)
224
+ : ValueWorklist(initialValue->getFunction ()) {
225
+ push (initialValue);
226
+ }
227
+
228
+ // / Pops the last added element from the worklist or returns null, if the
229
+ // / worklist is empty.
230
+ SILValue pop () {
231
+ if (worklist.empty ())
232
+ return nullptr ;
233
+ return worklist.pop_back_val ();
234
+ }
235
+
236
+ // / Pushes \p value onto the worklist if \p value has never been push before.
237
+ bool pushIfNotVisited (SILValue value) {
238
+ if (visited.insert (value)) {
239
+ worklist.push_back (value);
240
+ return true ;
241
+ }
242
+ return false ;
243
+ }
244
+
245
+ // / Like `pushIfNotVisited`, but requires that \p value has never been on the
246
+ // / worklist before.
247
+ void push (SILValue value) {
248
+ assert (!visited.contains (value));
249
+ visited.insert (value);
250
+ worklist.push_back (value);
251
+ }
252
+
253
+ // / Like `pop`, but marks the returned value as "unvisited". This means, that
254
+ // / the value can be pushed onto the worklist again.
255
+ SILValue popAndForget () {
256
+ if (worklist.empty ())
257
+ return nullptr ;
258
+ SILValue value = worklist.pop_back_val ();
259
+ visited.erase (value);
260
+ return value;
261
+ }
262
+
263
+ // / Returns true if \p value was visited, i.e. has been added to the worklist.
264
+ bool isVisited (SILValue value) const { return visited.contains (value); }
265
+ };
266
+
105
267
} // namespace swift
106
268
107
269
#endif
0 commit comments