Skip to content

Commit f47757a

Browse files
committed
[CanonicalizeOSSALifetime] Extend Onone lifetimes.
To improve the debugging experience of values whose lifetimes are canonicalized without compromising the semantics expressed in the source language, when canonicalizing OSSA lifetimes at Onone, lengthen lifetimes as much as possible without incurring copies that would be eliminated at O. rdar://99618502
1 parent 2c5ee0f commit f47757a

File tree

8 files changed

+1057
-69
lines changed

8 files changed

+1057
-69
lines changed

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void diagnoseRequiredCopyOfMoveOnly(Operand *use,
130130
///
131131
/// This result remains valid during copy rewriting. The only instructions
132132
/// referenced it contains are consumes that cannot be deleted.
133-
class CanonicalOSSAConsumeInfo {
133+
class CanonicalOSSAConsumeInfo final {
134134
/// Map blocks on the lifetime boundary to the last consuming instruction.
135135
llvm::SmallDenseMap<SILBasicBlock *, SILInstruction *, 4> finalBlockConsumes;
136136

@@ -159,6 +159,10 @@ class CanonicalOSSAConsumeInfo {
159159
return false;
160160
}
161161

162+
CanonicalOSSAConsumeInfo() {}
163+
CanonicalOSSAConsumeInfo(CanonicalOSSAConsumeInfo const &) = delete;
164+
CanonicalOSSAConsumeInfo &
165+
operator=(CanonicalOSSAConsumeInfo const &) = delete;
162166
SWIFT_ASSERT_ONLY_DECL(void dump() const LLVM_ATTRIBUTE_USED);
163167
};
164168

@@ -169,7 +173,7 @@ class CanonicalOSSAConsumeInfo {
169173
///
170174
/// TODO: Move all the private per-definition members into an implementation
171175
/// class in the .cpp file.
172-
class CanonicalizeOSSALifetime {
176+
class CanonicalizeOSSALifetime final {
173177
public:
174178
/// Find the original definition of a potentially copied value. \p copiedValue
175179
/// must be an owned value. It is usually a copy but may also be a destroy.
@@ -205,6 +209,10 @@ class CanonicalizeOSSALifetime {
205209
/// liveness may be pruned during canonicalization.
206210
bool pruneDebugMode;
207211

212+
/// If true, lifetimes will not be shortened except when necessary to avoid
213+
/// copies.
214+
bool maximizeLifetime;
215+
208216
/// If true and we are processing a value of move_only type, emit a diagnostic
209217
/// when-ever we need to insert a copy_value.
210218
std::function<void(Operand *)> moveOnlyCopyValueNotification;
@@ -240,6 +248,9 @@ class CanonicalizeOSSALifetime {
240248
/// Visited set for general def-use traversal that prevents revisiting values.
241249
GraphNodeWorklist<SILValue, 8> defUseWorklist;
242250

251+
/// The blocks that were discovered by PrunedLiveness.
252+
SmallVector<SILBasicBlock *, 32> discoveredBlocks;
253+
243254
/// Pruned liveness for the extended live range including copies. For this
244255
/// purpose, only consuming instructions are considered "lifetime
245256
/// ending". end_borrows do not end a liverange that may include owned copies.
@@ -248,7 +259,7 @@ class CanonicalizeOSSALifetime {
248259
/// The destroys of the value. These are not uses, but need to be recorded so
249260
/// that we know when the last use in a consuming block is (without having to
250261
/// repeatedly do use-def walks from destroys).
251-
SmallPtrSet<SILInstruction *, 8> destroys;
262+
SmallPtrSetVector<SILInstruction *, 8> destroys;
252263

253264
/// Information about consuming instructions discovered in this canonical OSSA
254265
/// lifetime.
@@ -286,15 +297,17 @@ class CanonicalizeOSSALifetime {
286297
}
287298

288299
CanonicalizeOSSALifetime(
289-
bool pruneDebugMode, NonLocalAccessBlockAnalysis *accessBlockAnalysis,
290-
DominanceInfo *domTree, InstructionDeleter &deleter,
300+
bool pruneDebugMode, bool maximizeLifetime,
301+
NonLocalAccessBlockAnalysis *accessBlockAnalysis, DominanceInfo *domTree,
302+
InstructionDeleter &deleter,
291303
std::function<void(Operand *)> moveOnlyCopyValueNotification = nullptr,
292304
std::function<void(Operand *)> moveOnlyFinalConsumingUse = nullptr)
293-
: pruneDebugMode(pruneDebugMode),
305+
: pruneDebugMode(pruneDebugMode), maximizeLifetime(maximizeLifetime),
294306
moveOnlyCopyValueNotification(moveOnlyCopyValueNotification),
295307
moveOnlyFinalConsumingUse(moveOnlyFinalConsumingUse),
296308
accessBlockAnalysis(accessBlockAnalysis), domTree(domTree),
297-
deleter(deleter) {}
309+
deleter(deleter),
310+
liveness(maximizeLifetime ? &discoveredBlocks : nullptr) {}
298311

299312
SILValue getCurrentDef() const { return liveness.getDef(); }
300313

@@ -313,6 +326,7 @@ class CanonicalizeOSSALifetime {
313326
consumingBlocks.clear();
314327
debugValues.clear();
315328
liveness.clear();
329+
discoveredBlocks.clear();
316330
}
317331

318332
/// Top-Level API: rewrites copies and destroys within \p def's extended
@@ -331,7 +345,7 @@ class CanonicalizeOSSALifetime {
331345

332346
InstModCallbacks &getCallbacks() { return deleter.getCallbacks(); }
333347

334-
protected:
348+
private:
335349
void recordDebugValue(DebugValueInst *dvi) { debugValues.insert(dvi); }
336350

337351
void recordConsumingUse(Operand *use) {
@@ -343,9 +357,14 @@ class CanonicalizeOSSALifetime {
343357

344358
void extendLivenessThroughOverlappingAccess();
345359

346-
void findExtendedBoundary(PrunedLivenessBoundary &boundary);
360+
void findOriginalBoundary(PrunedLivenessBoundary &boundary);
361+
362+
void findExtendedBoundary(PrunedLivenessBoundary const &originalBoundary,
363+
PrunedLivenessBoundary &boundary);
364+
365+
void extendUnconsumedLiveness(PrunedLivenessBoundary const &boundary);
347366

348-
void insertDestroysOnBoundary(PrunedLivenessBoundary &boundary);
367+
void insertDestroysOnBoundary(PrunedLivenessBoundary const &boundary);
349368

350369
void rewriteCopies();
351370
};

lib/SILOptimizer/Mandatory/MoveOnlyAddressChecker.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,9 @@ struct MoveOnlyChecker {
746746
instToDelete->eraseFromParent();
747747
})),
748748
canonicalizer(
749-
false /*pruneDebugMode*/, accessBlockAnalysis, domTree, deleter,
749+
false /*pruneDebugMode*/,
750+
!fn->shouldOptimize() /*maximizeLifetime*/, accessBlockAnalysis,
751+
domTree, deleter,
750752
[&](Operand *use) { consumingUsesNeedingCopy.push_back(use); },
751753
[&](Operand *use) { finalConsumingUses.push_back(use); }) {}
752754

lib/SILOptimizer/Mandatory/MoveOnlyObjectChecker.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,9 @@ bool MoveOnlyChecker::check(NonLocalAccessBlockAnalysis *accessBlockAnalysis,
401401
};
402402

403403
CanonicalizeOSSALifetime canonicalizer(
404-
false /*pruneDebugMode*/, accessBlockAnalysis, domTree, deleter,
405-
foundConsumingUseNeedingCopy, foundConsumingUseNotNeedingCopy);
404+
false /*pruneDebugMode*/, !fn->shouldOptimize() /*maximizeLifetime*/,
405+
accessBlockAnalysis, domTree, deleter, foundConsumingUseNeedingCopy,
406+
foundConsumingUseNotNeedingCopy);
406407
auto moveIntroducers = llvm::makeArrayRef(moveIntroducersToProcess.begin(),
407408
moveIntroducersToProcess.end());
408409
SmallPtrSet<MarkMustCheckInst *, 4> valuesWithDiagnostics;

lib/SILOptimizer/SILCombiner/SILCombine.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,10 @@ void SILCombiner::canonicalizeOSSALifetimes(SILInstruction *currentInst) {
350350
InstructionDeleter deleter(std::move(canonicalizeCallbacks));
351351

352352
DominanceInfo *domTree = DA->get(&Builder.getFunction());
353-
CanonicalizeOSSALifetime canonicalizer(false /*prune debug*/, NLABA, domTree,
354-
deleter);
353+
CanonicalizeOSSALifetime canonicalizer(
354+
false /*prune debug*/,
355+
!parentTransform->getFunction()->shouldOptimize() /*maximizeLifetime*/,
356+
NLABA, domTree, deleter);
355357
CanonicalizeBorrowScope borrowCanonicalizer(deleter);
356358

357359
while (!defsToCanonicalize.empty()) {

lib/SILOptimizer/Transforms/CopyPropagation.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ static bool sinkOwnedForward(SILInstruction *ownedForward,
373373
namespace {
374374

375375
class CopyPropagation : public SILFunctionTransform {
376-
/// True if debug_value instructions should be pruned.
376+
/// If true, debug_value instructions should be pruned.
377377
bool pruneDebug;
378378
/// True if all values should be canonicalized.
379379
bool canonicalizeAll;
@@ -437,8 +437,9 @@ void CopyPropagation::run() {
437437

438438
// canonicalizer performs all modifications through deleter's callbacks, so we
439439
// don't need to explicitly check for changes.
440-
CanonicalizeOSSALifetime canonicalizer(pruneDebug, accessBlockAnalysis,
441-
domTree, deleter);
440+
CanonicalizeOSSALifetime canonicalizer(
441+
pruneDebug, /*maximizeLifetime=*/!getFunction()->shouldOptimize(),
442+
accessBlockAnalysis, domTree, deleter);
442443

443444
// NOTE: We assume that the function is in reverse post order so visiting the
444445
// blocks and pushing begin_borrows as we see them and then popping them

0 commit comments

Comments
 (0)