|
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