@@ -155,14 +155,6 @@ class DeadEndBlocks;
155155// / not dominated by a def block, then liveness will include the entry block,
156156// / as if defined by a function argument
157157// /
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- // /
166158// / TODO: For efficiency, use BasicBlockBitfield rather than SmallDenseMap.
167159class PrunedLiveBlocks {
168160public:
@@ -181,210 +173,101 @@ class PrunedLiveBlocks {
181173 // / LiveOut blocks are live on at least one successor path. LiveOut blocks may
182174 // / or may not contain defs or uses.
183175 // /
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
187180 enum IsLive {
188181 Dead = 0 ,
189182 LiveWithin = 1 ,
190183 LiveOut = 3 ,
191184 };
192185
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-
246186private:
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;
254189
255190 // / 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 );
257195
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 );
260198
261199public:
262- PrunedLiveBlocks (unsigned numBitsToTrack ,
200+ PrunedLiveBlocks (SILFunction *function ,
263201 SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
264- : numBitsToTrack(numBitsToTrack ), discoveredBlocks(discoveredBlocks) {
202+ : liveBlocks(function, 2 ), discoveredBlocks(discoveredBlocks) {
265203 assert (!discoveredBlocks || discoveredBlocks->empty ());
266204 }
267205
268- unsigned getNumBitsToTrack () const { return numBitsToTrack ; }
206+ bool isInitialized () const { return initializedFlag ; }
269207
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 ;
275211 }
276212
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+ }
278219
279220 // / If the constructor was provided with a vector to populate, then this
280221 // / returns the list of all live blocks with no duplicates.
281222 ArrayRef<SILBasicBlock *> getDiscoveredBlocks () const {
282223 return *discoveredBlocks;
283224 }
284225
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);
292229 }
293230
294231 // / 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+
296235 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.
298240 if (liveness != Dead)
299241 return liveness;
300- computeScalarUseBlockLiveness (block, bitNo);
301- return getBlockLiveness (block, bitNo);
302- }
303242
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);
316245 }
317246
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);
333250 }
334251
335252 llvm::StringRef getStringRef (IsLive isLive) const ;
253+
336254 void print (llvm::raw_ostream &OS) const ;
255+
337256 void dump () const ;
338257
339258protected:
340- void markBlockLive (SILBasicBlock *bb, unsigned bitNo, IsLive isLive) {
259+ void markBlockLive (SILBasicBlock *bb, IsLive isLive) {
341260 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) {
351264 if (discoveredBlocks)
352265 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);
377266 }
378267 }
379268
380269private:
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);
388271};
389272
390273// / If inner borrows are 'Contained', then liveness is fully described by the
@@ -479,20 +362,23 @@ class PrunedLiveness {
479362 llvm::SmallMapVector<SILInstruction *, bool , 8 > users;
480363
481364public:
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) {}
484368
485- bool empty () const {
486- assert (!liveBlocks.empty () || users.empty ());
487- return liveBlocks.empty ();
488- }
369+ bool isInitialized () const { return liveBlocks.isInitialized (); }
489370
490- void clear () {
491- liveBlocks.clear ();
371+ bool empty () const { return users.empty (); }
372+
373+ void invalidate () {
374+ liveBlocks.invalidate ();
492375 users.clear ();
493376 }
494377
495- unsigned numLiveBlocks () const { return liveBlocks.numLiveBlocks (); }
378+ void initializeDiscoveredBlocks (
379+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks) {
380+ liveBlocks.initializeDiscoveredBlocks (discoveredBlocks);
381+ }
496382
497383 // / If the constructor was provided with a vector to populate, then this
498384 // / returns the list of all live blocks with no duplicates.
@@ -501,7 +387,7 @@ class PrunedLiveness {
501387 }
502388
503389 void initializeDefBlock (SILBasicBlock *defBB) {
504- liveBlocks.initializeDefBlock (defBB, 0 );
390+ liveBlocks.initializeDefBlock (defBB);
505391 }
506392
507393 // / For flexibility, \p lifetimeEnding is provided by the
@@ -526,7 +412,7 @@ class PrunedLiveness {
526412 void extendAcrossLiveness (PrunedLiveness &otherLiveness);
527413
528414 PrunedLiveBlocks::IsLive getBlockLiveness (SILBasicBlock *bb) const {
529- return liveBlocks.getBlockLiveness (bb, 0 );
415+ return liveBlocks.getBlockLiveness (bb);
530416 }
531417
532418 enum IsInterestingUser {
@@ -670,8 +556,9 @@ class PrunedLiveRange : public PrunedLiveness {
670556 return static_cast <const LivenessWithDefs &>(*this );
671557 }
672558
673- PrunedLiveRange (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
674- : PrunedLiveness(discoveredBlocks) {}
559+ PrunedLiveRange (SILFunction *function,
560+ SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
561+ : PrunedLiveness(function, discoveredBlocks) {}
675562
676563 LiveRangeSummary recursivelyUpdateForDef (SILValue initialDef,
677564 ValueSet &visited,
@@ -745,15 +632,16 @@ class SSAPrunedLiveness : public PrunedLiveRange<SSAPrunedLiveness> {
745632
746633public:
747634 SSAPrunedLiveness (
635+ SILFunction *function,
748636 SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
749- : PrunedLiveRange(discoveredBlocks) {}
637+ : PrunedLiveRange(function, discoveredBlocks) {}
750638
751639 SILValue getDef () const { return def; }
752640
753- void clear () {
641+ void invalidate () {
754642 def = SILValue ();
755643 defInst = nullptr ;
756- PrunedLiveRange::clear ();
644+ PrunedLiveRange::invalidate ();
757645 }
758646
759647 void initializeDef (SILValue def) {
@@ -815,11 +703,11 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
815703 MultiDefPrunedLiveness (
816704 SILFunction *function,
817705 SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
818- : PrunedLiveRange(discoveredBlocks), defs(function), defBlocks(function) {
819- }
706+ : PrunedLiveRange(function, discoveredBlocks), defs(function),
707+ defBlocks (function) { }
820708
821- void clear () {
822- llvm_unreachable ( " multi-def liveness cannot be reused " );
709+ void invalidate () {
710+ PrunedLiveRange::invalidate ( );
823711 }
824712
825713 void initializeDef (SILInstruction *defInst) {
@@ -886,14 +774,15 @@ class DiagnosticPrunedLiveness : public SSAPrunedLiveness {
886774
887775public:
888776 DiagnosticPrunedLiveness (
777+ SILFunction *function,
889778 SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ,
890779 SmallSetVector<SILInstruction *, 8 > *nonLifetimeEndingUsesInLiveOut =
891780 nullptr )
892- : SSAPrunedLiveness(discoveredBlocks),
781+ : SSAPrunedLiveness(function, discoveredBlocks),
893782 nonLifetimeEndingUsesInLiveOut (nonLifetimeEndingUsesInLiveOut) {}
894783
895- void clear () {
896- SSAPrunedLiveness::clear ();
784+ void invalidate () {
785+ SSAPrunedLiveness::invalidate ();
897786 if (nonLifetimeEndingUsesInLiveOut)
898787 nonLifetimeEndingUsesInLiveOut->clear ();
899788 }
0 commit comments