@@ -115,6 +115,11 @@ class DeadEndBlocks;
115
115
// / which the def block's predecessors incorrectly remain dead. This situation
116
116
// / could be handled by adding an updateForUseBeforeFirstDef() API.
117
117
// /
118
+ // / We allow for multiple bits of liveness information to be tracked by
119
+ // / internally using a SmallBitVector. We default to only tracking a single
120
+ // / bit. The multiple bit tracking is useful when tracking state for multiple
121
+ // / fields of the same root value.
122
+ // /
118
123
// / TODO: This can be made space-efficient if all clients can maintain a block
119
124
// / numbering so liveness info can be represented as bitsets across the blocks.
120
125
class PrunedLiveBlocks {
@@ -136,19 +141,24 @@ class PrunedLiveBlocks {
136
141
enum IsLive { Dead, LiveWithin, LiveOut };
137
142
138
143
private:
139
- // Map all blocks in which current def is live to a flag indicating whether
140
- // the value is also liveout of the block.
141
- llvm::SmallDenseMap<SILBasicBlock *, bool , 4 > liveBlocks;
144
+ // / Map all blocks in which current def is live to a SmallBitVector indicating
145
+ // / whether the value represented by said bit is also liveout of the block.
146
+ llvm::SmallDenseMap<SILBasicBlock *, SmallBitVector, 4 > liveBlocks;
147
+
148
+ // / Number of bits of liveness to track. By default 1. Used to track multiple
149
+ // / liveness bits.
150
+ unsigned numBitsToTrack;
142
151
143
- // Optional vector of live blocks for clients that deterministically iterate.
152
+ // / Optional vector of live blocks for clients that deterministically iterate.
144
153
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks;
145
154
146
- // Once the first use has been seen, no definitions can be added.
155
+ // / Once the first use has been seen, no definitions can be added.
147
156
SWIFT_ASSERT_ONLY_DECL (bool seenUse = false );
148
157
149
158
public:
150
- PrunedLiveBlocks (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
151
- : discoveredBlocks(discoveredBlocks) {
159
+ PrunedLiveBlocks (unsigned numBitsToTrack,
160
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
161
+ : numBitsToTrack(numBitsToTrack), discoveredBlocks(discoveredBlocks) {
152
162
assert (!discoveredBlocks || discoveredBlocks->empty ());
153
163
}
154
164
@@ -167,36 +177,38 @@ class PrunedLiveBlocks {
167
177
return *discoveredBlocks;
168
178
}
169
179
170
- void initializeDefBlock (SILBasicBlock *defBB) {
171
- markBlockLive (defBB, LiveWithin);
180
+ void initializeDefBlock (SILBasicBlock *defBB, unsigned bitNo ) {
181
+ markBlockLive (defBB, LiveWithin, bitNo );
172
182
}
173
183
174
184
// / Update this liveness result for a single use.
175
- IsLive updateForUse (SILInstruction *user);
185
+ IsLive updateForUse (SILInstruction *user, unsigned bitNo );
176
186
177
- IsLive getBlockLiveness (SILBasicBlock *bb) const {
187
+ IsLive getBlockLiveness (SILBasicBlock *bb, unsigned bitNo ) const {
178
188
auto liveBlockIter = liveBlocks.find (bb);
179
189
if (liveBlockIter == liveBlocks.end ())
180
190
return Dead;
181
- return liveBlockIter->second ? LiveOut : LiveWithin;
191
+ assert (liveBlockIter->second .size () == 1 );
192
+ return liveBlockIter->second [bitNo] ? LiveOut : LiveWithin;
182
193
}
183
194
184
195
protected:
185
- void markBlockLive (SILBasicBlock *bb, IsLive isLive) {
196
+ void markBlockLive (SILBasicBlock *bb, IsLive isLive, unsigned bitNo ) {
186
197
assert (isLive != Dead && " erasing live blocks isn't implemented." );
187
198
bool isLiveOut = (isLive == LiveOut);
188
199
auto iterAndInserted =
189
- liveBlocks.insert (std::make_pair (bb, isLiveOut ));
200
+ liveBlocks.insert (std::make_pair (bb, SmallBitVector (numBitsToTrack) ));
190
201
if (iterAndInserted.second ) {
202
+ iterAndInserted.first ->getSecond ()[bitNo] = isLiveOut;
191
203
if (discoveredBlocks)
192
204
discoveredBlocks->push_back (bb);
193
205
} else if (isLiveOut) {
194
206
// Update the existing entry to be live-out.
195
- iterAndInserted.first ->getSecond () = true ;
207
+ iterAndInserted.first ->getSecond ()[bitNo] = true ;
196
208
}
197
209
}
198
210
199
- void computeUseBlockLiveness (SILBasicBlock *userBB);
211
+ void computeUseBlockLiveness (SILBasicBlock *userBB, unsigned bitNo );
200
212
};
201
213
202
214
// / PrunedLiveness tracks PrunedLiveBlocks along with "interesting" use
@@ -252,7 +264,7 @@ class PrunedLiveness {
252
264
PrunedLiveness (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ,
253
265
SmallSetVector<SILInstruction *, 8 >
254
266
*nonLifetimeEndingUsesInLiveOut = nullptr )
255
- : liveBlocks(discoveredBlocks),
267
+ : liveBlocks(1 /* num bits */ , discoveredBlocks),
256
268
nonLifetimeEndingUsesInLiveOut (nonLifetimeEndingUsesInLiveOut) {}
257
269
258
270
bool empty () const {
@@ -317,7 +329,7 @@ class PrunedLiveness {
317
329
}
318
330
319
331
void initializeDefBlock (SILBasicBlock *defBB) {
320
- liveBlocks.initializeDefBlock (defBB);
332
+ liveBlocks.initializeDefBlock (defBB, 0 );
321
333
}
322
334
323
335
// / For flexibility, \p lifetimeEnding is provided by the
@@ -335,7 +347,7 @@ class PrunedLiveness {
335
347
void extendAcrossLiveness (PrunedLiveness &otherLiveness);
336
348
337
349
PrunedLiveBlocks::IsLive getBlockLiveness (SILBasicBlock *bb) const {
338
- return liveBlocks.getBlockLiveness (bb);
350
+ return liveBlocks.getBlockLiveness (bb, 0 );
339
351
}
340
352
341
353
enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse };
0 commit comments