@@ -155,14 +155,6 @@ class DeadEndBlocks;
155
155
// / not dominated by a def block, then liveness will include the entry block,
156
156
// / as if defined by a function argument
157
157
// /
158
- // / We allow for multiple bits of liveness information to be tracked by
159
- // / internally using a SmallBitVector. The multiple bit tracking is useful when
160
- // / tracking state for multiple fields of the same root value. To do this, we
161
- // / actually track 2 bits per actual needed bit so we can represent 3 Dead,
162
- // / LiveOut, LiveWithin. This was previously unnecessary since we could just
163
- // / represent dead by not having liveness state for a block. With multiple bits
164
- // / possible this is no longer true.
165
- // /
166
158
// / TODO: For efficiency, use BasicBlockBitfield rather than SmallDenseMap.
167
159
class PrunedLiveBlocks {
168
160
public:
@@ -181,210 +173,101 @@ class PrunedLiveBlocks {
181
173
// / LiveOut blocks are live on at least one successor path. LiveOut blocks may
182
174
// / or may not contain defs or uses.
183
175
// /
184
- // / NOTE: The values below for Dead, LiveWithin, LiveOut were picked to ensure
185
- // / that given a 2 bit representation of the value, a value is Dead if the
186
- // / first bit is 0 and is LiveOut if the second bit is set.
176
+ // / NOTE: The values below for Dead, LiveWithin, LiveOut were picked to
177
+ // / establish a lattice such that:
178
+ // / - Dead is the initial state (zero bitfield)
179
+ // / - Merging liveness information is a bitwise-or
187
180
enum IsLive {
188
181
Dead = 0 ,
189
182
LiveWithin = 1 ,
190
183
LiveOut = 3 ,
191
184
};
192
185
193
- // / A bit vector that stores information about liveness. This is composed
194
- // / with SmallBitVector since it contains two bits per liveness so that it
195
- // / can represent 3 states, Dead, LiveWithin, LiveOut. We take advantage of
196
- // / their numeric values to make testing easier \see documentation on IsLive.
197
- class LivenessSmallBitVector {
198
- SmallBitVector bits;
199
-
200
- public:
201
- LivenessSmallBitVector () : bits() {}
202
-
203
- void init (unsigned numBits) {
204
- assert (bits.size () == 0 );
205
- assert (numBits != 0 );
206
- bits.resize (numBits * 2 );
207
- }
208
-
209
- unsigned size () const { return bits.size () / 2 ; }
210
-
211
- IsLive getLiveness (unsigned bitNo) const {
212
- if (!bits[bitNo * 2 ])
213
- return IsLive::Dead;
214
- return bits[bitNo * 2 + 1 ] ? LiveOut : LiveWithin;
215
- }
216
-
217
- // / Returns the liveness in \p resultingFoundLiveness. We only return the
218
- // / bits for endBitNo - startBitNo.
219
- void getLiveness (unsigned startBitNo, unsigned endBitNo,
220
- SmallVectorImpl<IsLive> &resultingFoundLiveness) const {
221
- unsigned actualStartBitNo = startBitNo * 2 ;
222
- unsigned actualEndBitNo = endBitNo * 2 ;
223
-
224
- for (unsigned i = actualStartBitNo, e = actualEndBitNo; i != e; i += 2 ) {
225
- if (!bits[i]) {
226
- resultingFoundLiveness.push_back (Dead);
227
- continue ;
228
- }
229
-
230
- resultingFoundLiveness.push_back (bits[i + 1 ] ? LiveOut : LiveWithin);
231
- }
232
- }
233
-
234
- void setLiveness (unsigned startBitNo, unsigned endBitNo, IsLive isLive) {
235
- for (unsigned i = startBitNo * 2 , e = endBitNo * 2 ; i != e; i += 2 ) {
236
- bits[i] = isLive & 1 ;
237
- bits[i + 1 ] = isLive & 2 ;
238
- }
239
- }
240
-
241
- void setLiveness (unsigned bitNo, IsLive isLive) {
242
- setLiveness (bitNo, bitNo + 1 , isLive);
243
- }
244
- };
245
-
246
186
private:
247
- // / Map all blocks in which current def is live to a SmallBitVector indicating
248
- // / whether the value represented by said bit is also liveout of the block.
249
- llvm::SmallDenseMap<SILBasicBlock *, LivenessSmallBitVector, 4 > liveBlocks;
250
-
251
- // / Number of bits of liveness to track. By default 1. Used to track multiple
252
- // / liveness bits.
253
- unsigned numBitsToTrack;
187
+ // / Map all blocks to an IsLive state.
188
+ BasicBlockBitfield liveBlocks;
254
189
255
190
// / Optional vector of live blocks for clients that deterministically iterate.
256
- SmallVectorImpl<SILBasicBlock *> *discoveredBlocks;
191
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ;
192
+
193
+ // / Only a clean bitfield can be initialized.
194
+ SWIFT_ASSERT_ONLY_DECL (bool cleanFlag = true );
257
195
258
- // / Once the first use has been seen, no definitions can be added.
259
- SWIFT_ASSERT_ONLY_DECL (bool seenUse = false );
196
+ // / Once the first def has been initialized, uses can be added.
197
+ SWIFT_ASSERT_ONLY_DECL (bool initializedFlag = false );
260
198
261
199
public:
262
- PrunedLiveBlocks (unsigned numBitsToTrack ,
200
+ PrunedLiveBlocks (SILFunction *function ,
263
201
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
264
- : numBitsToTrack(numBitsToTrack ), discoveredBlocks(discoveredBlocks) {
202
+ : liveBlocks(function, 2 ), discoveredBlocks(discoveredBlocks) {
265
203
assert (!discoveredBlocks || discoveredBlocks->empty ());
266
204
}
267
205
268
- unsigned getNumBitsToTrack () const { return numBitsToTrack ; }
206
+ bool isInitialized () const { return initializedFlag ; }
269
207
270
- bool empty () const { return liveBlocks.empty (); }
271
-
272
- void clear () {
273
- liveBlocks.clear ();
274
- SWIFT_ASSERT_ONLY (seenUse = false );
208
+ void invalidate () {
209
+ initializedFlag = false ;
210
+ cleanFlag = false ;
275
211
}
276
212
277
- unsigned numLiveBlocks () const { return liveBlocks.size (); }
213
+ void initializeDiscoveredBlocks (
214
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks) {
215
+ assert (!isInitialized () && " cannot reinitialize after blocks are live" );
216
+
217
+ this ->discoveredBlocks = discoveredBlocks;
218
+ }
278
219
279
220
// / If the constructor was provided with a vector to populate, then this
280
221
// / returns the list of all live blocks with no duplicates.
281
222
ArrayRef<SILBasicBlock *> getDiscoveredBlocks () const {
282
223
return *discoveredBlocks;
283
224
}
284
225
285
- void initializeDefBlock (SILBasicBlock *defBB, unsigned bitNo) {
286
- markBlockLive (defBB, bitNo, LiveWithin);
287
- }
288
-
289
- void initializeDefBlock (SILBasicBlock *defBB, unsigned startBitNo,
290
- unsigned endBitNo) {
291
- markBlockLive (defBB, startBitNo, endBitNo, LiveWithin);
226
+ void initializeDefBlock (SILBasicBlock *defBB) {
227
+ initializedFlag = true ;
228
+ markBlockLive (defBB, LiveWithin);
292
229
}
293
230
294
231
// / Update this liveness result for a single use.
295
- IsLive updateForUse (SILInstruction *user, unsigned bitNo) {
232
+ IsLive updateForUse (SILInstruction *user) {
233
+ assert (isInitialized () && " at least one definition must be initialized" );
234
+
296
235
auto *block = user->getParent ();
297
- auto liveness = getBlockLiveness (block, bitNo);
236
+ auto liveness = getBlockLiveness (block);
237
+ // If a block is already marked live, assume that liveness was propagated to
238
+ // its predecessors. This assumes that uses will never be added above a def
239
+ // in the same block.
298
240
if (liveness != Dead)
299
241
return liveness;
300
- computeScalarUseBlockLiveness (block, bitNo);
301
- return getBlockLiveness (block, bitNo);
302
- }
303
242
304
- // / Update this range of liveness results for a single use.
305
- void updateForUse (SILInstruction *user, unsigned startBitNo,
306
- unsigned endBitNo,
307
- SmallVectorImpl<IsLive> &resultingLiveness);
308
-
309
- IsLive getBlockLiveness (SILBasicBlock *bb, unsigned bitNo) const {
310
- auto liveBlockIter = liveBlocks.find (bb);
311
- if (liveBlockIter == liveBlocks.end ()) {
312
- return Dead;
313
- }
314
-
315
- return liveBlockIter->second .getLiveness (bitNo);
243
+ computeUseBlockLiveness (block);
244
+ return getBlockLiveness (block);
316
245
}
317
246
318
- // / FIXME: This API should directly return the live bitset. The live bitset
319
- // / type should have an api for querying and iterating over the live fields.
320
- void getBlockLiveness (SILBasicBlock *bb, unsigned startBitNo,
321
- unsigned endBitNo,
322
- SmallVectorImpl<IsLive> &foundLivenessInfo) const {
323
- auto liveBlockIter = liveBlocks.find (bb);
324
- if (liveBlockIter == liveBlocks.end ()) {
325
- for (unsigned i : range (endBitNo - startBitNo)) {
326
- (void )i;
327
- foundLivenessInfo.push_back (Dead);
328
- }
329
- return ;
330
- }
331
-
332
- liveBlockIter->second .getLiveness (startBitNo, endBitNo, foundLivenessInfo);
247
+ IsLive getBlockLiveness (SILBasicBlock *bb) const {
248
+ assert (isInitialized ());
249
+ return (IsLive)liveBlocks.get (bb);
333
250
}
334
251
335
252
llvm::StringRef getStringRef (IsLive isLive) const ;
253
+
336
254
void print (llvm::raw_ostream &OS) const ;
255
+
337
256
void dump () const ;
338
257
339
258
protected:
340
- void markBlockLive (SILBasicBlock *bb, unsigned bitNo, IsLive isLive) {
259
+ void markBlockLive (SILBasicBlock *bb, IsLive isLive) {
341
260
assert (isLive != Dead && " erasing live blocks isn't implemented." );
342
- auto iterAndInserted =
343
- liveBlocks.insert (std::make_pair (bb, LivenessSmallBitVector ()));
344
- if (iterAndInserted.second ) {
345
- // We initialize the size of the small bit vector here rather than in
346
- // liveBlocks.insert above to prevent us from allocating upon failure if
347
- // we have more than SmallBitVector's small size number of bits.
348
- auto &insertedBV = iterAndInserted.first ->getSecond ();
349
- insertedBV.init (numBitsToTrack);
350
- insertedBV.setLiveness (bitNo, bitNo + 1 , isLive);
261
+ auto state = (IsLive)liveBlocks.get (bb);
262
+ liveBlocks.set (bb, state | isLive);
263
+ if (state == IsLive::Dead) {
351
264
if (discoveredBlocks)
352
265
discoveredBlocks->push_back (bb);
353
- } else {
354
- // If we are dead, always update to the new liveness.
355
- switch (iterAndInserted.first ->getSecond ().getLiveness (bitNo)) {
356
- case Dead:
357
- iterAndInserted.first ->getSecond ().setLiveness (bitNo, bitNo + 1 ,
358
- isLive);
359
- break ;
360
- case LiveWithin:
361
- if (isLive == LiveOut) {
362
- // Update the existing entry to be live-out.
363
- iterAndInserted.first ->getSecond ().setLiveness (bitNo, bitNo + 1 ,
364
- LiveOut);
365
- }
366
- break ;
367
- case LiveOut:
368
- break ;
369
- }
370
- }
371
- }
372
-
373
- void markBlockLive (SILBasicBlock *bb, unsigned startBitNo, unsigned endBitNo,
374
- IsLive isLive) {
375
- for (unsigned index : range (startBitNo, endBitNo)) {
376
- markBlockLive (bb, index, isLive);
377
266
}
378
267
}
379
268
380
269
private:
381
- // / A helper routine that as a fast path handles the scalar case. We do not
382
- // / handle the mult-bit case today since the way the code is written today
383
- // / assumes we process a bit at a time.
384
- // /
385
- // / TODO: Make a multi-bit query for efficiency reasons.
386
- void computeScalarUseBlockLiveness (SILBasicBlock *userBB,
387
- unsigned startBitNo);
270
+ void computeUseBlockLiveness (SILBasicBlock *userBB);
388
271
};
389
272
390
273
// / If inner borrows are 'Contained', then liveness is fully described by the
@@ -479,20 +362,23 @@ class PrunedLiveness {
479
362
llvm::SmallMapVector<SILInstruction *, bool , 8 > users;
480
363
481
364
public:
482
- PrunedLiveness (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
483
- : liveBlocks(1 /* num bits*/ , discoveredBlocks) {}
365
+ PrunedLiveness (SILFunction *function,
366
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
367
+ : liveBlocks(function, discoveredBlocks) {}
484
368
485
- bool empty () const {
486
- assert (!liveBlocks.empty () || users.empty ());
487
- return liveBlocks.empty ();
488
- }
369
+ bool isInitialized () const { return liveBlocks.isInitialized (); }
489
370
490
- void clear () {
491
- liveBlocks.clear ();
371
+ bool empty () const { return users.empty (); }
372
+
373
+ void invalidate () {
374
+ liveBlocks.invalidate ();
492
375
users.clear ();
493
376
}
494
377
495
- unsigned numLiveBlocks () const { return liveBlocks.numLiveBlocks (); }
378
+ void initializeDiscoveredBlocks (
379
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks) {
380
+ liveBlocks.initializeDiscoveredBlocks (discoveredBlocks);
381
+ }
496
382
497
383
// / If the constructor was provided with a vector to populate, then this
498
384
// / returns the list of all live blocks with no duplicates.
@@ -501,7 +387,7 @@ class PrunedLiveness {
501
387
}
502
388
503
389
void initializeDefBlock (SILBasicBlock *defBB) {
504
- liveBlocks.initializeDefBlock (defBB, 0 );
390
+ liveBlocks.initializeDefBlock (defBB);
505
391
}
506
392
507
393
// / For flexibility, \p lifetimeEnding is provided by the
@@ -526,7 +412,7 @@ class PrunedLiveness {
526
412
void extendAcrossLiveness (PrunedLiveness &otherLiveness);
527
413
528
414
PrunedLiveBlocks::IsLive getBlockLiveness (SILBasicBlock *bb) const {
529
- return liveBlocks.getBlockLiveness (bb, 0 );
415
+ return liveBlocks.getBlockLiveness (bb);
530
416
}
531
417
532
418
enum IsInterestingUser {
@@ -670,8 +556,9 @@ class PrunedLiveRange : public PrunedLiveness {
670
556
return static_cast <const LivenessWithDefs &>(*this );
671
557
}
672
558
673
- PrunedLiveRange (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
674
- : PrunedLiveness(discoveredBlocks) {}
559
+ PrunedLiveRange (SILFunction *function,
560
+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
561
+ : PrunedLiveness(function, discoveredBlocks) {}
675
562
676
563
LiveRangeSummary recursivelyUpdateForDef (SILValue initialDef,
677
564
ValueSet &visited,
@@ -745,15 +632,16 @@ class SSAPrunedLiveness : public PrunedLiveRange<SSAPrunedLiveness> {
745
632
746
633
public:
747
634
SSAPrunedLiveness (
635
+ SILFunction *function,
748
636
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
749
- : PrunedLiveRange(discoveredBlocks) {}
637
+ : PrunedLiveRange(function, discoveredBlocks) {}
750
638
751
639
SILValue getDef () const { return def; }
752
640
753
- void clear () {
641
+ void invalidate () {
754
642
def = SILValue ();
755
643
defInst = nullptr ;
756
- PrunedLiveRange::clear ();
644
+ PrunedLiveRange::invalidate ();
757
645
}
758
646
759
647
void initializeDef (SILValue def) {
@@ -815,11 +703,11 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
815
703
MultiDefPrunedLiveness (
816
704
SILFunction *function,
817
705
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
818
- : PrunedLiveRange(discoveredBlocks), defs(function), defBlocks(function) {
819
- }
706
+ : PrunedLiveRange(function, discoveredBlocks), defs(function),
707
+ defBlocks (function) { }
820
708
821
- void clear () {
822
- llvm_unreachable ( " multi-def liveness cannot be reused " );
709
+ void invalidate () {
710
+ PrunedLiveRange::invalidate ( );
823
711
}
824
712
825
713
void initializeDef (SILInstruction *defInst) {
@@ -886,14 +774,15 @@ class DiagnosticPrunedLiveness : public SSAPrunedLiveness {
886
774
887
775
public:
888
776
DiagnosticPrunedLiveness (
777
+ SILFunction *function,
889
778
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ,
890
779
SmallSetVector<SILInstruction *, 8 > *nonLifetimeEndingUsesInLiveOut =
891
780
nullptr )
892
- : SSAPrunedLiveness(discoveredBlocks),
781
+ : SSAPrunedLiveness(function, discoveredBlocks),
893
782
nonLifetimeEndingUsesInLiveOut (nonLifetimeEndingUsesInLiveOut) {}
894
783
895
- void clear () {
896
- SSAPrunedLiveness::clear ();
784
+ void invalidate () {
785
+ SSAPrunedLiveness::invalidate ();
897
786
if (nonLifetimeEndingUsesInLiveOut)
898
787
nonLifetimeEndingUsesInLiveOut->clear ();
899
788
}
0 commit comments