Skip to content

Commit 0c8ecb5

Browse files
authored
Revert "MultiDefPrunedLiveness: add support for arbitrary uses/defs."
1 parent eb63223 commit 0c8ecb5

File tree

6 files changed

+120
-171
lines changed

6 files changed

+120
-171
lines changed

include/swift/SIL/PrunedLiveness.h

+34-53
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class PrunedLiveBlocks {
190190
/// Optional vector of live blocks for clients that deterministically iterate.
191191
SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr;
192192

193+
/// Only a clean bitfield can be initialized.
194+
bool cleanFlag = true;
195+
193196
/// Once the first def has been initialized, uses can be added.
194197
bool initializedFlag = false;
195198

@@ -204,6 +207,7 @@ class PrunedLiveBlocks {
204207

205208
void invalidate() {
206209
initializedFlag = false;
210+
cleanFlag = false;
207211
}
208212

209213
void initializeDiscoveredBlocks(
@@ -225,21 +229,17 @@ class PrunedLiveBlocks {
225229
}
226230

227231
/// 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) {
233233
assert(isInitialized() && "at least one definition must be initialized");
234234

235235
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+
243243
computeUseBlockLiveness(block);
244244
return getBlockLiveness(block);
245245
}
@@ -348,7 +348,6 @@ struct LiveRangeSummary {
348348
/// necessarily include liveness up to destroy_value or end_borrow
349349
/// instructions.
350350
class PrunedLiveness {
351-
protected:
352351
PrunedLiveBlocks liveBlocks;
353352

354353
// Map all "interesting" user instructions in this def's live range to a flag
@@ -391,6 +390,27 @@ class PrunedLiveness {
391390
liveBlocks.initializeDefBlock(defBB);
392391
}
393392

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+
394414
PrunedLiveBlocks::IsLive getBlockLiveness(SILBasicBlock *bb) const {
395415
return liveBlocks.getBlockLiveness(bb);
396416
}
@@ -545,27 +565,6 @@ class PrunedLiveRange : public PrunedLiveness {
545565
SILValue value);
546566

547567
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-
569568
/// Update liveness for all direct uses of \p def. Transitively follows
570569
/// guaranteed forwards up to but not including guaranteed phis. If \p def is
571570
/// used by a guaranteed phi return InnerBorrowKind::Reborrowed.
@@ -661,9 +660,6 @@ class SSAPrunedLiveness : public PrunedLiveRange<SSAPrunedLiveness> {
661660
return def->getParentBlock() == block;
662661
}
663662

664-
/// In SSA, uses never occur before the single def.
665-
bool isUserBeforeDef(SILInstruction *user) const { return false; }
666-
667663
/// SSA implementation of computeBoundary.
668664
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
669665
PrunedLivenessBoundary &boundary) const;
@@ -715,7 +711,7 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
715711
}
716712

717713
void initializeDef(SILInstruction *defInst) {
718-
initializeDefNode(cast<SILNode>(defInst));
714+
initializeDefNode(defInst->asSILNode());
719715
}
720716

721717
void initializeDef(SILArgument *defArg) { initializeDefNode(defArg); }
@@ -737,25 +733,10 @@ class MultiDefPrunedLiveness : public PrunedLiveRange<MultiDefPrunedLiveness> {
737733
return defs.contains(cast<SILNode>(inst));
738734
}
739735

740-
bool isDef(SILArgument *arg) const {
741-
return defs.contains(arg);
742-
}
743-
744736
bool isDefBlock(SILBasicBlock *block) const {
745737
return defBlocks.contains(block);
746738
}
747739

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-
759740
/// Multi-Def implementation of computeBoundary.
760741
void findBoundariesInBlock(SILBasicBlock *block, bool isLiveOut,
761742
PrunedLivenessBoundary &boundary) const;

include/swift/SIL/ScopedAddressUtils.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ struct ScopedAddressValue {
119119
///
120120
/// Valid for any type of liveness, SSA or MultiDef, that may be used by a
121121
/// scoped address.
122-
AddressUseKind updateTransitiveLiveness(SSAPrunedLiveness &liveness) const;
122+
AddressUseKind updateTransitiveLiveness(PrunedLiveness &liveness) const;
123123

124124
/// Create appropriate scope ending instruction at \p insertPt.
125125
void createScopeEnd(SILBasicBlock::iterator insertPt, SILLocation loc) const;

lib/SIL/Utils/OSSALifetimeCompletion.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
///
1616
/// Interior liveness handles the following cases naturally:
1717
///
18-
/// When completing the lifetime of the initial value, %v1, transitively
19-
/// include all uses of dominated reborrows as, such as %phi1 in this example:
18+
/// When completing the lifetime if the initial value, %v1, transitively
19+
/// include all dominated reborrows. %phi1 in this example:
2020
///
2121
/// %v1 = ...
2222
/// cond_br bb1, bb2
@@ -31,8 +31,8 @@
3131
/// end_borrow %phi1
3232
/// %k1 = destroy_value %v1 // must be below end_borrow %phi1
3333
///
34-
/// When completing the lifetime for a phi (%phi2) transitively include all
35-
/// uses of inner adjacent reborrows, such as %phi1 in this example:
34+
/// When completing the lifetime for a (%phi2) transitively include all inner
35+
/// adjacent reborrows (%phi1):
3636
///
3737
/// bb1:
3838
/// %v1 = ...

0 commit comments

Comments
 (0)