@@ -190,6 +190,9 @@ class PrunedLiveBlocks {
190
190
// / Optional vector of live blocks for clients that deterministically iterate.
191
191
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ;
192
192
193
+ // / Only a clean bitfield can be initialized.
194
+ bool cleanFlag = true ;
195
+
193
196
// / Once the first def has been initialized, uses can be added.
194
197
bool initializedFlag = false ;
195
198
@@ -204,6 +207,7 @@ class PrunedLiveBlocks {
204
207
205
208
void invalidate () {
206
209
initializedFlag = false ;
210
+ cleanFlag = false ;
207
211
}
208
212
209
213
void initializeDiscoveredBlocks (
@@ -225,21 +229,17 @@ class PrunedLiveBlocks {
225
229
}
226
230
227
231
// / Update this liveness result for a single use.
228
- // /
229
- // / \p isUseBeforeDef is true if \p user occures before the first def in this
230
- // / block. This indicates "liveness holes" inside the block, causing liveness
231
- // / to propagate to predecessors.
232
- IsLive updateForUse (SILInstruction *user, bool isUseBeforeDef) {
232
+ IsLive updateForUse (SILInstruction *user) {
233
233
assert (isInitialized () && " at least one definition must be initialized" );
234
234
235
235
auto *block = user->getParent ();
236
- if (!isUseBeforeDef) {
237
- auto liveness = getBlockLiveness (block);
238
- // If a block is already marked live, it must either "kill" liveness, or
239
- // liveness was already propagated to its predecessors .
240
- if (liveness != Dead)
241
- return liveness;
242
- }
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 .
240
+ if (liveness != Dead)
241
+ return liveness;
242
+
243
243
computeUseBlockLiveness (block);
244
244
return getBlockLiveness (block);
245
245
}
@@ -348,7 +348,6 @@ struct LiveRangeSummary {
348
348
// / necessarily include liveness up to destroy_value or end_borrow
349
349
// / instructions.
350
350
class PrunedLiveness {
351
- protected:
352
351
PrunedLiveBlocks liveBlocks;
353
352
354
353
// Map all "interesting" user instructions in this def's live range to a flag
@@ -391,6 +390,27 @@ class PrunedLiveness {
391
390
liveBlocks.initializeDefBlock (defBB);
392
391
}
393
392
393
+ // / For flexibility, \p lifetimeEnding is provided by the
394
+ // / caller. PrunedLiveness makes no assumptions about the def-use
395
+ // / relationships that generate liveness. For example, use->isLifetimeEnding()
396
+ // / cannot distinguish the end of the borrow scope that defines this extended
397
+ // / live range vs. a nested borrow scope within the extended live range.
398
+ void updateForUse (SILInstruction *user, bool lifetimeEnding);
399
+
400
+ // / Updates the liveness for a whole borrow scope, beginning at \p op.
401
+ // / Returns false if this cannot be done. This assumes that nested OSSA
402
+ // / lifetimes are complete.
403
+ InnerBorrowKind updateForBorrowingOperand (Operand *operand);
404
+
405
+ // / Update liveness for an interior pointer use. These are normally handled
406
+ // / like an instantaneous use. But if \p operand "borrows" a value for the
407
+ // / duration of a scoped address (store_borrow), then update liveness for the
408
+ // / entire scope. This assumes that nested OSSA lifetimes are complete.
409
+ AddressUseKind checkAndUpdateInteriorPointer (Operand *operand);
410
+
411
+ // / Update this liveness to extend across the given liveness.
412
+ void extendAcrossLiveness (PrunedLiveness &otherLiveness);
413
+
394
414
PrunedLiveBlocks::IsLive getBlockLiveness (SILBasicBlock *bb) const {
395
415
return liveBlocks.getBlockLiveness (bb);
396
416
}
@@ -545,27 +565,6 @@ class PrunedLiveRange : public PrunedLiveness {
545
565
SILValue value);
546
566
547
567
public:
548
- // / For flexibility, \p lifetimeEnding is provided by the
549
- // / caller. PrunedLiveness makes no assumptions about the def-use
550
- // / relationships that generate liveness. For example, use->isLifetimeEnding()
551
- // / cannot distinguish the end of the borrow scope that defines this extended
552
- // / live range vs. a nested borrow scope within the extended live range.
553
- void updateForUse (SILInstruction *user, bool lifetimeEnding);
554
-
555
- // / Updates the liveness for a whole borrow scope, beginning at \p op.
556
- // / Returns false if this cannot be done. This assumes that nested OSSA
557
- // / lifetimes are complete.
558
- InnerBorrowKind updateForBorrowingOperand (Operand *operand);
559
-
560
- // / Update liveness for an interior pointer use. These are normally handled
561
- // / like an instantaneous use. But if \p operand "borrows" a value for the
562
- // / duration of a scoped address (store_borrow), then update liveness for the
563
- // / entire scope. This assumes that nested OSSA lifetimes are complete.
564
- AddressUseKind checkAndUpdateInteriorPointer (Operand *operand);
565
-
566
- // / Update this liveness to extend across the given liveness.
567
- void extendAcrossLiveness (PrunedLiveness &otherLiveness);
568
-
569
568
// / Update liveness for all direct uses of \p def. Transitively follows
570
569
// / guaranteed forwards up to but not including guaranteed phis. If \p def is
571
570
// / used by a guaranteed phi return InnerBorrowKind::Reborrowed.
@@ -661,9 +660,6 @@ class SSAPrunedLiveness : public PrunedLiveRange<SSAPrunedLiveness> {
661
660
return def->getParentBlock () == block;
662
661
}
663
662
664
- // / In SSA, uses never occur before the single def.
665
- bool isUserBeforeDef (SILInstruction *user) const { return false ; }
666
-
667
663
// / SSA implementation of computeBoundary.
668
664
void findBoundariesInBlock (SILBasicBlock *block, bool isLiveOut,
669
665
PrunedLivenessBoundary &boundary) const ;
@@ -715,7 +711,7 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
715
711
}
716
712
717
713
void initializeDef (SILInstruction *defInst) {
718
- initializeDefNode (cast<SILNode>(defInst ));
714
+ initializeDefNode (defInst-> asSILNode ( ));
719
715
}
720
716
721
717
void initializeDef (SILArgument *defArg) { initializeDefNode (defArg); }
@@ -737,25 +733,10 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
737
733
return defs.contains (cast<SILNode>(inst));
738
734
}
739
735
740
- bool isDef (SILArgument *arg) const {
741
- return defs.contains (arg);
742
- }
743
-
744
736
bool isDefBlock (SILBasicBlock *block) const {
745
737
return defBlocks.contains (block);
746
738
}
747
739
748
- // / Return true if \p user occurs before the first def in the same basic
749
- // / block. In classical liveness dataflow terms, gen/kill conditions over all
750
- // / users in 'bb' are:
751
- // /
752
- // / Gen(bb) |= !isDefBlock(bb) || isUserBeforeDef(bb)
753
- // / Kill(bb) &= isDefBlock(bb) && !isUserBeforeDef(bb)
754
- // /
755
- // / If 'bb' has no users, it is neither a Gen nor Kill. Otherwise, Gen and
756
- // / Kill are complements.
757
- bool isUserBeforeDef (SILInstruction *user) const ;
758
-
759
740
// / Multi-Def implementation of computeBoundary.
760
741
void findBoundariesInBlock (SILBasicBlock *block, bool isLiveOut,
761
742
PrunedLivenessBoundary &boundary) const ;
0 commit comments