18
18
#define SWIFT_SIL_SILBITFIELD_H
19
19
20
20
#include " swift/SIL/SILFunction.h"
21
+ #include " llvm/ADT/SmallVector.h"
21
22
22
23
namespace swift {
23
24
24
25
// / Utility to add a custom bitfield to a function's basic blocks.
25
26
// /
26
27
// / This can be used by transforms to store temporary flags or tiny values per
27
28
// / basic block.
28
- // / It is very efficient: no memory allocation is needed, no hash set or map is
29
- // / needed for lookup and there is no initialization cost (in contrast to
30
- // / BasicBlockData which needs to iterate over all blocks at initialization).
29
+ // / The memory managed is a 32 bit field within each basic block (\see
30
+ // / BasicBlock::customBits) and thus is very efficient: no memory allocation is
31
+ // / needed, no hash set or map is needed for lookup and there is no
32
+ // / initialization cost (in contrast to BasicBlockData which needs to iterate
33
+ // / over all blocks at initialization).
31
34
// /
32
- // / Restrictions :
35
+ // / Invariants :
33
36
// / * BasicBlockBitfield instances must be allocated and deallocated
34
- // / following a strict stack discipline. This means, it's fine to use them as
35
- // / (or in) local variables in transformations. But it's e.g. not possible to
36
- // / store a BasicBlockBitfield in an Analysis.
37
+ // / following a strict stack discipline, because bit-positions in
38
+ // / BasicBlock::customBits are "allocated" and "freed" with a stack-allocation
39
+ // / algorithm. This means, it's fine to use a BasicBlockBitfield as (or in)
40
+ // / local variables, e.g. in transformations. But it's not possible to store
41
+ // / a BasicBlockBitfield in an Analysis.
37
42
// / * The total number of bits which are alive at the same time must not exceed
38
- // / 32.
43
+ // / 32 (the size of BasicBlock::customBits) .
39
44
class BasicBlockBitfield {
40
45
// / The bitfield is "added" to the blocks of this function.
41
46
SILFunction *function;
@@ -89,6 +94,7 @@ class BasicBlockBitfield {
89
94
SILFunction *getFunction () const { return function; }
90
95
91
96
unsigned get (SILBasicBlock *block) const {
97
+ assert (block->getParent () == function);
92
98
if (bitfieldID > block->lastInitializedBitfieldID ) {
93
99
// The bitfield is not initialized yet in this block.
94
100
return 0 ;
@@ -97,6 +103,7 @@ class BasicBlockBitfield {
97
103
}
98
104
99
105
void set (SILBasicBlock *block, unsigned value) {
106
+ assert (block->getParent () == function);
100
107
assert (((value << startBit) & ~mask) == 0 &&
101
108
" value too large for BasicBlockBitfield" );
102
109
unsigned clearMask = mask;
@@ -136,7 +143,9 @@ class BasicBlockFlag {
136
143
137
144
bool get (SILBasicBlock *block) const { return (bool )bit.get (block); }
138
145
139
- void set (SILBasicBlock *block) { bit.set (block, 1 ); }
146
+ void set (SILBasicBlock *block, bool value = true ) {
147
+ bit.set (block, (unsigned )value);
148
+ }
140
149
void reset (SILBasicBlock *block) { bit.set (block, 0 ); }
141
150
142
151
// / Sets the flag and returns the old value.
@@ -161,7 +170,45 @@ class BasicBlockSet {
161
170
// / Returns true if \p block was not contained in the set before inserting.
162
171
bool insert (SILBasicBlock *block) { return !flag.testAndSet (block); }
163
172
164
- void remove (SILBasicBlock *block) { flag.reset (block); }
173
+ void erase (SILBasicBlock *block) { flag.reset (block); }
174
+ };
175
+
176
+ // / An implementation of `llvm::SetVector<SILBasicBlock *,
177
+ // / SmallVector<SILBasicBlock *, N>,
178
+ // / BasicBlockSet>`.
179
+ // /
180
+ // / Unfortunately it's not possible to use `llvm::SetVector` directly because
181
+ // / the BasicBlockSet constructor needs a `SILFunction` argument.
182
+ // /
183
+ // / Note: This class does not provide a `remove` method intentinally, because
184
+ // / it would have a O(n) complexity.
185
+ template <unsigned N> class BasicBlockSetVector {
186
+ using Vector = llvm::SmallVector<SILBasicBlock *, N>;
187
+
188
+ Vector vector;
189
+ BasicBlockSet set;
190
+
191
+ public:
192
+ using iterator = typename Vector::const_iterator;
193
+
194
+ BasicBlockSetVector (SILFunction *function) : set(function) {}
195
+
196
+ iterator begin () const { return vector.begin (); }
197
+ iterator end () const { return vector.end (); }
198
+
199
+ unsigned size () const { return vector.size (); }
200
+ bool empty () const { return vector.empty (); }
201
+
202
+ bool contains (SILBasicBlock *block) const { return set.contains (block); }
203
+
204
+ // / Returns true if \p block was not contained in the set before inserting.
205
+ bool insert (SILBasicBlock *block) {
206
+ if (set.insert (block)) {
207
+ vector.push_back (block);
208
+ return true ;
209
+ }
210
+ return false ;
211
+ }
165
212
};
166
213
167
214
} // namespace swift
0 commit comments