|
17 | 17 | #ifndef SWIFT_SIL_BASICBLOCKBITS_H
|
18 | 18 | #define SWIFT_SIL_BASICBLOCKBITS_H
|
19 | 19 |
|
20 |
| -#include "swift/SIL/SILFunction.h" |
21 |
| -#include "llvm/ADT/SmallVector.h" |
| 20 | +#include "swift/SIL/SILBitfield.h" |
22 | 21 |
|
23 | 22 | namespace swift {
|
24 | 23 |
|
25 | 24 | /// Utility to add a custom bitfield to a function's basic blocks.
|
26 | 25 | ///
|
27 | 26 | /// This can be used by transforms to store temporary flags or tiny values per
|
28 | 27 | /// basic block.
|
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 |
| 28 | +/// The bits are stored in a 32 bit field within each basic block (\see |
| 29 | +/// SILBasicBlock::customBits) which is very efficient: no memory allocation |
| 30 | +/// is needed, no hash set or map is needed for lookup and there is no |
32 | 31 | /// initialization cost (in contrast to BasicBlockData which needs to iterate
|
33 | 32 | /// over all blocks at initialization).
|
34 | 33 | ///
|
35 | 34 | /// Invariants:
|
36 | 35 | /// * BasicBlockBitfield instances must be allocated and deallocated
|
37 | 36 | /// following a strict stack discipline, because bit-positions in
|
38 |
| -/// BasicBlock::customBits are "allocated" and "freed" with a stack-allocation |
| 37 | +/// SILBasicBlock::customBits are "allocated" and "freed" with a stack-allocation |
39 | 38 | /// algorithm. This means, it's fine to use a BasicBlockBitfield as (or in)
|
40 | 39 | /// local variables, e.g. in transformations. But it's not possible to store
|
41 | 40 | /// a BasicBlockBitfield in an Analysis.
|
42 | 41 | /// * The total number of bits which are alive at the same time must not exceed
|
43 |
| -/// 32 (the size of BasicBlock::customBits). |
44 |
| -class BasicBlockBitfield { |
45 |
| - /// The bitfield is "added" to the blocks of this function. |
46 |
| - SILFunction *function; |
47 |
| - |
48 |
| - /// A single linked list of currently alive BasicBlockBitfields (oldest is |
49 |
| - /// last, newest is first). |
50 |
| - /// The head of the list is function->lastAllocatedBitfield. |
51 |
| - BasicBlockBitfield *parent; |
52 |
| - |
53 |
| - /// Initialized with the monotonically increasing currentBitfieldID of the |
54 |
| - /// function. |
55 |
| - /// Used to check if the bitfield in a block is initialized. |
56 |
| - /// If a block's lastInitializedBitfieldID is less than this ID, it means |
57 |
| - /// that the bits of that block are not initialized yet. |
58 |
| - /// See also: SILBasicBlock::lastInitializedBitfieldID, |
59 |
| - /// SILFunction::currentBitfieldID |
60 |
| - unsigned bitfieldID; |
61 |
| - |
62 |
| - short startBit; |
63 |
| - short endBit; |
64 |
| - uint32_t mask; |
| 42 | +/// 32 (the size of SILBasicBlock::customBits). |
| 43 | +class BasicBlockBitfield : public SILBitfield<BasicBlockBitfield, SILBasicBlock> { |
| 44 | + template <class, class> friend class SILBitfield; |
| 45 | + |
| 46 | + BasicBlockBitfield *insertInto(SILFunction *function) { |
| 47 | + BasicBlockBitfield *oldParent = function->newestAliveBlockBitfield; |
| 48 | + function->newestAliveBlockBitfield = this; |
| 49 | + return oldParent; |
| 50 | + } |
65 | 51 |
|
66 | 52 | public:
|
67 | 53 | BasicBlockBitfield(SILFunction *function, int size) :
|
68 |
| - function(function), |
69 |
| - parent(function->newestAliveBitfield), |
70 |
| - bitfieldID(function->currentBitfieldID), |
71 |
| - startBit(parent ? parent->endBit : 0), |
72 |
| - endBit(startBit + size), |
73 |
| - mask(0xffffffffu >> (32 - size) << startBit) { |
74 |
| - assert(size > 0 && "bit field size must be > 0"); |
75 |
| - assert(endBit <= 32 && "too many/large bit fields allocated in function"); |
76 |
| - assert((!parent || bitfieldID > parent->bitfieldID) && |
77 |
| - "BasicBlockBitfield indices are not in order"); |
78 |
| - function->newestAliveBitfield = this; |
79 |
| - ++function->currentBitfieldID; |
80 |
| - assert(function->currentBitfieldID != 0 && "currentBitfieldID overflow"); |
81 |
| - } |
| 54 | + SILBitfield(function, size, insertInto(function)) {} |
82 | 55 |
|
83 | 56 | ~BasicBlockBitfield() {
|
84 |
| - assert(function->newestAliveBitfield == this && |
| 57 | + assert(function->newestAliveBlockBitfield == this && |
85 | 58 | "BasicBlockBitfield destructed too early");
|
86 |
| - function->newestAliveBitfield = parent; |
87 |
| - } |
88 |
| - |
89 |
| - BasicBlockBitfield(const BasicBlockBitfield &) = delete; |
90 |
| - BasicBlockBitfield(BasicBlockBitfield &&) = delete; |
91 |
| - BasicBlockBitfield &operator=(const BasicBlockBitfield &) = delete; |
92 |
| - BasicBlockBitfield &operator=(BasicBlockBitfield &&) = delete; |
93 |
| - |
94 |
| - SILFunction *getFunction() const { return function; } |
95 |
| - |
96 |
| - unsigned get(SILBasicBlock *block) const { |
97 |
| - assert(block->getParent() == function); |
98 |
| - if (bitfieldID > block->lastInitializedBitfieldID) { |
99 |
| - // The bitfield is not initialized yet in this block. |
100 |
| - return 0; |
101 |
| - } |
102 |
| - return (block->customBits & mask) >> startBit; |
103 |
| - } |
104 |
| - |
105 |
| - void set(SILBasicBlock *block, unsigned value) { |
106 |
| - assert(block->getParent() == function); |
107 |
| - assert(((value << startBit) & ~mask) == 0 && |
108 |
| - "value too large for BasicBlockBitfield"); |
109 |
| - unsigned clearMask = mask; |
110 |
| - if (bitfieldID > block->lastInitializedBitfieldID) { |
111 |
| - |
112 |
| - // The bitfield is not initialized yet in this block. |
113 |
| - // Initialize the bitfield, and also initialize all parent bitfields, |
114 |
| - // which are not initialized, yet. Example: |
115 |
| - // |
116 |
| - // This field Last initialized field |
117 |
| - // | | |
118 |
| - // V V |
119 |
| - // EE DDD C BB AAA |
120 |
| - // |
121 |
| - // block->lastInitializedBitfieldID == AAA.bitfieldID |
122 |
| - // -> we have to initialize the fields: BB, C, DDD and EE |
123 |
| - // |
124 |
| - BasicBlockBitfield *bf = parent; |
125 |
| - while (bf && bf->bitfieldID > block->lastInitializedBitfieldID) { |
126 |
| - clearMask |= bf->mask; |
127 |
| - bf = bf->parent; |
128 |
| - } |
129 |
| - block->lastInitializedBitfieldID = bitfieldID; |
130 |
| - } |
131 |
| - block->customBits = (block->customBits & ~clearMask) | (value << startBit); |
| 59 | + function->newestAliveBlockBitfield = parent; |
132 | 60 | }
|
133 | 61 | };
|
134 | 62 |
|
|
0 commit comments