1212//
1313// This file defines efficient data structures for working with Nodes.
1414//
15- // TODO: Add an InstructionWorklist similar to BasicBlockWorklist.
16- //
1715// ===----------------------------------------------------------------------===//
1816
1917#ifndef SWIFT_SIL_NODEDATASTRUCTURES_H
@@ -29,7 +27,7 @@ namespace swift {
2927// / NodeSet>`.
3028// /
3129// / 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.
3331// /
3432// / Note: This class does not provide a `remove` method intentionally, because
3533// / it would have a O(n) complexity.
@@ -63,6 +61,112 @@ class NodeSetVector {
6361 }
6462};
6563
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+
66170// / An implementation of `llvm::SetVector<SILValue,
67171// / StackList<SILValue>,
68172// / ValueSet>`.
@@ -102,6 +206,64 @@ class ValueSetVector {
102206 }
103207};
104208
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+
105267} // namespace swift
106268
107269#endif
0 commit comments