1818#define SWIFT_SIL_SILBITFIELD_H
1919
2020#include " swift/SIL/SILFunction.h"
21+ #include " llvm/ADT/SmallVector.h"
2122
2223namespace swift {
2324
2425// / Utility to add a custom bitfield to a function's basic blocks.
2526// /
2627// / This can be used by transforms to store temporary flags or tiny values per
2728// / 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).
3134// /
32- // / Restrictions :
35+ // / Invariants :
3336// / * 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.
3742// / * The total number of bits which are alive at the same time must not exceed
38- // / 32.
43+ // / 32 (the size of BasicBlock::customBits) .
3944class BasicBlockBitfield {
4045 // / The bitfield is "added" to the blocks of this function.
4146 SILFunction *function;
@@ -89,6 +94,7 @@ class BasicBlockBitfield {
8994 SILFunction *getFunction () const { return function; }
9095
9196 unsigned get (SILBasicBlock *block) const {
97+ assert (block->getParent () == function);
9298 if (bitfieldID > block->lastInitializedBitfieldID ) {
9399 // The bitfield is not initialized yet in this block.
94100 return 0 ;
@@ -97,6 +103,7 @@ class BasicBlockBitfield {
97103 }
98104
99105 void set (SILBasicBlock *block, unsigned value) {
106+ assert (block->getParent () == function);
100107 assert (((value << startBit) & ~mask) == 0 &&
101108 " value too large for BasicBlockBitfield" );
102109 unsigned clearMask = mask;
@@ -136,7 +143,9 @@ class BasicBlockFlag {
136143
137144 bool get (SILBasicBlock *block) const { return (bool )bit.get (block); }
138145
139- void set (SILBasicBlock *block) { bit.set (block, 1 ); }
146+ void set (SILBasicBlock *block, bool value = true ) {
147+ bit.set (block, (unsigned )value);
148+ }
140149 void reset (SILBasicBlock *block) { bit.set (block, 0 ); }
141150
142151 // / Sets the flag and returns the old value.
@@ -161,7 +170,45 @@ class BasicBlockSet {
161170 // / Returns true if \p block was not contained in the set before inserting.
162171 bool insert (SILBasicBlock *block) { return !flag.testAndSet (block); }
163172
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+ }
165212};
166213
167214} // namespace swift
0 commit comments