Skip to content

Commit 12c0198

Browse files
authored
Merge pull request #59184 from gottesmm/release/5.7-movedbginfo
[release/5.7][move-function] Remaining _move changes for 5.7
2 parents e16b83f + 006b4d7 commit 12c0198

12 files changed

+1230
-34
lines changed

include/swift/SIL/DebugUtils.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,24 +237,26 @@ bool hasNonTrivialNonDebugTransitiveUsers(
237237
/// operators to access functionality from the underlying instruction when
238238
/// needed.
239239
struct DebugVarCarryingInst {
240-
enum class Kind {
240+
enum class Kind : uint8_t {
241241
Invalid = 0,
242242
DebugValue,
243243
AllocStack,
244244
AllocBox,
245245
};
246246

247-
Kind kind;
248247
SILInstruction *inst;
248+
Kind kind;
249+
uintptr_t spareBits : (sizeof(uintptr_t) - sizeof(Kind)) * 8;
249250

250-
DebugVarCarryingInst() : kind(Kind::Invalid), inst(nullptr) {}
251+
DebugVarCarryingInst() : inst(nullptr), kind(Kind::Invalid), spareBits(0) {}
251252
DebugVarCarryingInst(DebugValueInst *dvi)
252-
: kind(Kind::DebugValue), inst(dvi) {}
253+
: inst(dvi), kind(Kind::DebugValue), spareBits(0) {}
253254
DebugVarCarryingInst(AllocStackInst *asi)
254-
: kind(Kind::AllocStack), inst(asi) {}
255-
DebugVarCarryingInst(AllocBoxInst *abi) : kind(Kind::AllocBox), inst(abi) {}
255+
: inst(asi), kind(Kind::AllocStack), spareBits(0) {}
256+
DebugVarCarryingInst(AllocBoxInst *abi)
257+
: inst(abi), kind(Kind::AllocBox), spareBits(0) {}
256258
DebugVarCarryingInst(SILInstruction *newInst)
257-
: kind(Kind::Invalid), inst(nullptr) {
259+
: inst(nullptr), kind(Kind::Invalid), spareBits(0) {
258260
switch (newInst->getKind()) {
259261
default:
260262
return;
@@ -280,6 +282,15 @@ struct DebugVarCarryingInst {
280282
/// '->'. This keeps the wrapper light weight.
281283
SILInstruction *operator->() const { return inst; }
282284

285+
bool operator==(const DebugVarCarryingInst &other) const {
286+
return kind == other.kind && inst == other.inst &&
287+
spareBits == other.spareBits;
288+
}
289+
290+
bool operator!=(const DebugVarCarryingInst &other) const {
291+
return !(*this == other);
292+
}
293+
283294
/// Add support for this struct in `if` statement.
284295
explicit operator bool() const { return bool(kind); }
285296

@@ -351,7 +362,8 @@ struct DebugVarCarryingInst {
351362
case Kind::AllocStack:
352363
return cast<AllocStackInst>(inst)->getWasMoved();
353364
case Kind::AllocBox:
354-
llvm_unreachable("Not implemented");
365+
// We do not support moving alloc box today, so we always return false.
366+
return false;
355367
}
356368
}
357369

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ PASS(MoveFunctionCanonicalization, "sil-move-function-canon",
440440
"function checking.")
441441
PASS(DebugInfoCanonicalizer, "sil-onone-debuginfo-canonicalizer",
442442
"Canonicalize debug info at -Onone by propagating debug info into coroutine funclets")
443+
PASS(MovedAsyncVarDebugInfoPropagator, "sil-moved-async-var-dbginfo-propagator",
444+
"Propagate debug info from moved async vars after coroutine funclet boundaries")
443445
PASS(PruneVTables, "prune-vtables",
444446
"Mark class methods that do not require vtable dispatch")
445447
PASS_RANGE(AllPasses, AADumper, PruneVTables)

lib/SILOptimizer/Mandatory/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ target_sources(swiftSILOptimizer PRIVATE
2121
LexicalLifetimeEliminator.cpp
2222
LowerHopToActor.cpp
2323
MandatoryInlining.cpp
24+
MovedAsyncVarDebugInfoPropagator.cpp
2425
MoveFunctionCanonicalization.cpp
2526
MoveKillsCopyableAddressesChecker.cpp
2627
MoveKillsCopyableValuesChecker.cpp

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,10 @@ bool GatherLexicalLifetimeUseVisitor::visitUse(Operand *op,
13631363
if (isa<DeallocStackInst>(op->getUser()))
13641364
return true;
13651365

1366+
// Ignore end_access.
1367+
if (isa<EndAccessInst>(op->getUser()))
1368+
return true;
1369+
13661370
LLVM_DEBUG(llvm::dbgs() << "Found liveness use: " << *op->getUser());
13671371
useState.livenessUses.insert(op->getUser());
13681372

@@ -1507,6 +1511,24 @@ bool DataflowState::cleanupAllDestroyAddr(
15071511
SILBuilderWithScope builder(iter);
15081512
auto *dvi = builder.createDestroyAddr(
15091513
RegularLocation::getAutoGeneratedLocation(), address);
1514+
// Create a debug_value undef if we have debug info to stop the async dbg
1515+
// info propagation from creating debug info for an already destroyed
1516+
// value. We use a separate builder since we need to control the debug
1517+
// scope/location to get llvm to do the right thing.
1518+
if (addressDebugInst) {
1519+
if (auto varInfo = addressDebugInst.getVarInfo()) {
1520+
// We need to always insert /after/ the reinit since the value will
1521+
// not be defined before the value.
1522+
SILBuilderWithScope dbgValueInsertBuilder(dvi);
1523+
dbgValueInsertBuilder.setCurrentDebugScope(
1524+
addressDebugInst->getDebugScope());
1525+
dbgValueInsertBuilder.createDebugValue(
1526+
addressDebugInst.inst->getLoc(),
1527+
SILUndef::get(address->getType(), dvi->getModule()), *varInfo,
1528+
false,
1529+
/*was moved*/ true);
1530+
}
1531+
}
15101532
useState.destroys.insert(dvi);
15111533
continue;
15121534
}

lib/SILOptimizer/Mandatory/MoveKillsCopyableValuesChecker.cpp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,22 @@ bool CheckerLivenessInfo::compute() {
133133
break;
134134
case OperandOwnership::Borrow: {
135135
if (auto *bbi = dyn_cast<BeginBorrowInst>(user)) {
136-
// Only add borrows to liveness if the borrow isn't lexical. If it is
137-
// a lexical borrow, we have created an entirely new source level
138-
// binding that should be tracked separately.
139-
if (!bbi->isLexical()) {
136+
// If we have a lexical begin_borrow, we are going to check its uses
137+
// separately and emit diagnostics for it. So we just need to add the
138+
// liveness of the begin_borrow.
139+
//
140+
// NOTE: We know that semantically the use lexical lifetime must have
141+
// a separate lifetime from the base lexical lifetime that we are
142+
// processing. We do not want to include those uses as transitive uses
143+
// of our base lexical lifetime. We just want to treat the formation
144+
// of the new variable as a use. Thus we only include the begin_borrow
145+
// itself as the use.
146+
if (bbi->isLexical()) {
147+
liveness.updateForUse(bbi, false /*lifetime ending*/);
148+
} else {
149+
// Otherwise, try to update liveness for a borrowing operand
150+
// use. This will make it so that we add the end_borrows of the
151+
// liveness use. If we have a reborrow here, we will bail.
140152
bool failed = !liveness.updateForBorrowingOperand(use);
141153
if (failed)
142154
return false;
@@ -351,24 +363,32 @@ bool MoveKillsCopyableValuesChecker::check() {
351363
SmallSetVector<SILValue, 32> valuesToCheck;
352364

353365
for (auto *arg : fn->getEntryBlock()->getSILFunctionArguments()) {
354-
if (arg->getOwnershipKind() == OwnershipKind::Owned)
366+
if (arg->getOwnershipKind() == OwnershipKind::Owned) {
367+
LLVM_DEBUG(llvm::dbgs() << "Found owned arg to check: " << *arg);
355368
valuesToCheck.insert(arg);
369+
}
356370
}
357371

358372
for (auto &block : *fn) {
359373
for (auto &ii : block) {
360374
if (auto *bbi = dyn_cast<BeginBorrowInst>(&ii)) {
361-
if (bbi->isLexical())
375+
if (bbi->isLexical()) {
376+
LLVM_DEBUG(llvm::dbgs()
377+
<< "Found lexical lifetime to check: " << *bbi);
362378
valuesToCheck.insert(bbi);
379+
}
363380
continue;
364381
}
365382
}
366383
}
367384

368-
if (valuesToCheck.empty())
385+
if (valuesToCheck.empty()) {
386+
LLVM_DEBUG(llvm::dbgs() << "No values to check! Exiting early!\n");
369387
return false;
388+
}
370389

371-
LLVM_DEBUG(llvm::dbgs() << "Visiting Function: " << fn->getName() << "\n");
390+
LLVM_DEBUG(llvm::dbgs()
391+
<< "Found at least one value to check, performing checking.\n");
372392
auto valuesToProcess =
373393
llvm::makeArrayRef(valuesToCheck.begin(), valuesToCheck.end());
374394
auto &mod = fn->getModule();
@@ -475,6 +495,9 @@ class MoveKillsCopyableValuesCheckerPass : public SILFunctionTransform {
475495
assert(fn->getModule().getStage() == SILStage::Raw &&
476496
"Should only run on Raw SIL");
477497

498+
LLVM_DEBUG(llvm::dbgs() << "*** Checking moved values in fn: "
499+
<< getFunction()->getName() << '\n');
500+
478501
MoveKillsCopyableValuesChecker checker(getFunction());
479502

480503
// If we already had dominance or loop info generated, update them when

0 commit comments

Comments
 (0)