Skip to content

Commit 056132c

Browse files
committed
[move-function] Add a new pass that propagates debug_value [moved] into coroutine func-lets.
NOTE: debug_value [moved] appearing in the source code implies a _move was used. So this will not effect current stable swift code. This is just a first version of this that I am using to commit/bring up tests for IRGen supporting a full dataflow version of this patch. Big picture is that there is a bunch of work that is done in the LLVM level in the coroutine splitter to work around communicating live variables in the various coroutine func-lets. This logic is all done with debug.declare and we would need to update that logic in the coroutine splitter to handle debug.addr. Rather than do this, after some conversation, AdrianP and I realized that we could get the same effect of a debug.declare by just redeclaring the current live set of debug_value after each possible coroutine funclet start. To do this in full generality, we need a full dataflow but just to bring this up we initially perform a dominance propagation algorithm of the following sort: 1. We walk the CFG along successors. By doing this we guarantee that we visit blocks after their dominators. 2. When we visit a block, we walk the block from start->end. During this walk: a. We grab a new block state from the centralized block->blockState map. This state is a [SILDebugVariable : DebugValueInst]. b. If we see a debug_value, we map blockState[debug_value.getDbgVar()] = debug_value. This ensures that when we get to the bottom of the block, we have pairs of SILDebugVariable + last debug_value on it. c. If we see any coroutine funclet boundaries, we clone the current tracked set of our block state and then walk up the dom tree dumping in each block any debug_value with a SILDebugVariable that we have not already dumped. This is maintained by using a visited set of SILDebugVariable for each funclet boundary. The end result is that at the beginning of each funclet we will basically declare the debug info for an addr. This is insufficient of course for moves that are in conditional control flow, e.x.: ``` let x = Klass() if boolValue { await asyncCall() let _ = _move(x) } ``` but this at least lets me begin to write tests for this in lldb using straight line code and work out the rest of the issues in CodeGen using those tests.
1 parent 965f32d commit 056132c

File tree

10 files changed

+565
-7
lines changed

10 files changed

+565
-7
lines changed

include/swift/SIL/SILDebugInfoExpression.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Decl.h"
2121
#include "llvm/ADT/APInt.h"
2222
#include "llvm/ADT/ArrayRef.h"
23+
#include "llvm/ADT/Hashing.h"
2324
#include "llvm/ADT/Optional.h"
2425
#include "llvm/ADT/iterator_range.h"
2526
#include "llvm/Support/raw_ostream.h"
@@ -109,6 +110,12 @@ struct SILDIExprElement {
109110
}
110111
};
111112

113+
/// Returns the hashcode for the di expr element.
114+
inline llvm::hash_code hash_value(const SILDIExprElement &elt) {
115+
return llvm::hash_combine(elt.getKind(), elt.getAsDecl(), elt.getAsDecl(),
116+
elt.getAsConstInt());
117+
}
118+
112119
/// For a given SILDIExprOperator, provides information
113120
/// like its textual name and operand types.
114121
struct SILDIExprInfo {
@@ -273,5 +280,11 @@ class SILDebugInfoExpression {
273280
SILDIExprOperator::Fragment;
274281
}
275282
};
283+
284+
/// Returns the hashcode for the di expr element.
285+
inline llvm::hash_code hash_value(const SILDebugInfoExpression &elt) {
286+
return llvm::hash_combine_range(elt.element_begin(), elt.element_end());
287+
}
288+
276289
} // end namespace swift
277290
#endif

include/swift/SIL/SILDebugVariable.h

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,23 @@ namespace swift {
2323

2424
class AllocationInst;
2525

26+
/// Holds common debug information about local variables and function
27+
/// arguments that are needed by DebugValueInst, AllocStackInst,
28+
/// and AllocBoxInst.
29+
struct SILDebugVariable;
30+
inline llvm::hash_code hash_value(const SILDebugVariable &P);
31+
2632
/// Holds common debug information about local variables and function
2733
/// arguments that are needed by DebugValueInst, AllocStackInst,
2834
/// and AllocBoxInst.
2935
struct SILDebugVariable {
36+
friend llvm::hash_code hash_value(const SILDebugVariable &P);
37+
3038
StringRef Name;
3139
unsigned ArgNo : 16;
3240
unsigned Constant : 1;
3341
unsigned Implicit : 1;
42+
unsigned isDenseMapSingleton : 2;
3443
Optional<SILType> Type;
3544
Optional<SILLocation> Loc;
3645
const SILDebugScope *Scope;
@@ -40,26 +49,41 @@ struct SILDebugVariable {
4049
SILDebugVariable(const SILDebugVariable &) = default;
4150
SILDebugVariable &operator=(const SILDebugVariable &) = default;
4251

52+
enum class IsDenseMapSingleton { No, IsEmpty, IsTombstone };
53+
SILDebugVariable(IsDenseMapSingleton inputIsDenseMapSingleton)
54+
: SILDebugVariable() {
55+
assert(inputIsDenseMapSingleton != IsDenseMapSingleton::No &&
56+
"Should only pass IsEmpty or IsTombstone");
57+
isDenseMapSingleton = unsigned(inputIsDenseMapSingleton);
58+
}
59+
4360
SILDebugVariable()
44-
: ArgNo(0), Constant(false), Implicit(false), Scope(nullptr) {}
61+
: ArgNo(0), Constant(false), Implicit(false), isDenseMapSingleton(0),
62+
Scope(nullptr) {}
4563
SILDebugVariable(bool Constant, uint16_t ArgNo)
46-
: ArgNo(ArgNo), Constant(Constant), Implicit(false), Scope(nullptr) {}
64+
: ArgNo(ArgNo), Constant(Constant), Implicit(false),
65+
isDenseMapSingleton(0), Scope(nullptr) {}
4766
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo,
4867
bool IsImplicit = false, Optional<SILType> AuxType = {},
4968
Optional<SILLocation> DeclLoc = {},
5069
const SILDebugScope *DeclScope = nullptr,
5170
llvm::ArrayRef<SILDIExprElement> ExprElements = {})
5271
: Name(Name), ArgNo(ArgNo), Constant(Constant), Implicit(IsImplicit),
53-
Type(AuxType), Loc(DeclLoc), Scope(DeclScope), DIExpr(ExprElements) {}
72+
isDenseMapSingleton(0), Type(AuxType), Loc(DeclLoc), Scope(DeclScope),
73+
DIExpr(ExprElements) {}
5474

5575
/// Created from either AllocStack or AllocBox instruction
5676
static Optional<SILDebugVariable>
5777
createFromAllocation(const AllocationInst *AI);
5878

59-
bool operator==(const SILDebugVariable &V) {
79+
// We're not comparing DIExpr here because strictly speaking,
80+
// DIExpr is not part of the debug variable. We simply piggyback
81+
// it in this class so that's it's easier to carry DIExpr around.
82+
bool operator==(const SILDebugVariable &V) const {
6083
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name &&
6184
Implicit == V.Implicit && Type == V.Type && Loc == V.Loc &&
62-
Scope == V.Scope && DIExpr == V.DIExpr;
85+
Scope == V.Scope && isDenseMapSingleton == V.isDenseMapSingleton &&
86+
DIExpr == V.DIExpr;
6387
}
6488

6589
SILDebugVariable withoutDIExpr() const {
@@ -73,6 +97,13 @@ struct SILDebugVariable {
7397
bool isVar() const { return Name.size() && !Constant; }
7498
};
7599

100+
/// Returns the hashcode for the new projection path.
101+
inline llvm::hash_code hash_value(const SILDebugVariable &P) {
102+
return llvm::hash_combine(P.ArgNo, P.Constant, P.Name, P.Implicit,
103+
P.isDenseMapSingleton, P.Type, P.Loc, P.Scope,
104+
P.DIExpr);
105+
}
106+
76107
} // namespace swift
77108

78109
#endif

include/swift/SIL/SILInstruction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9863,6 +9863,19 @@ struct ilist_traits<::swift::SILInstruction> :
98639863
void createNode(const SILInstruction &);
98649864
};
98659865

9866+
template <>
9867+
struct DenseMapInfo<swift::SILDebugVariable> {
9868+
using KeyTy = swift::SILDebugVariable;
9869+
static inline KeyTy getEmptyKey() {
9870+
return KeyTy(KeyTy::IsDenseMapSingleton::IsEmpty);
9871+
}
9872+
static inline KeyTy getTombstoneKey() {
9873+
return KeyTy(KeyTy::IsDenseMapSingleton::IsTombstone);
9874+
}
9875+
static unsigned getHashValue(const KeyTy &Val) { return hash_value(Val); }
9876+
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { return LHS == RHS; }
9877+
};
9878+
98669879
} // end llvm namespace
98679880

98689881
#endif

include/swift/SIL/SILLocation.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ class SILLocation {
7272
return line == rhs.line && column == rhs.column &&
7373
filename.equals(rhs.filename);
7474
}
75+
7576
void dump() const;
7677
void print(raw_ostream &OS) const;
78+
friend llvm::hash_code hash_value(const FilenameAndLocation &);
7779
};
7880

7981
protected:
@@ -431,8 +433,19 @@ class SILLocation {
431433
}
432434

433435
inline bool operator!=(const SILLocation &R) const { return !(*this == R); }
436+
437+
friend llvm::hash_code hash_value(const SILLocation &);
434438
};
435439

440+
inline llvm::hash_code hash_value(const SILLocation &R) {
441+
return llvm::hash_combine(R.kindAndFlags.packedKindAndFlags,
442+
*R.storage.filePositionLoc);
443+
}
444+
445+
inline llvm::hash_code hash_value(const SILLocation::FilenameAndLocation &R) {
446+
return llvm::hash_combine(R.line, R.column, R.filename);
447+
}
448+
436449
/// Allowed on any instruction.
437450
class RegularLocation : public SILLocation {
438451
public:

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ PASS(MoveKillsCopyableAddressesChecker, "sil-move-kills-copyable-addresses-check
436436
PASS(MoveFunctionCanonicalization, "sil-move-function-canon",
437437
"Pass that canonicalizes certain parts of the IR before we perform move "
438438
"function checking.")
439+
PASS(DebugInfoCanonicalizer, "sil-onone-debuginfo-canonicalizer",
440+
"Canonicalize debug info at -Onone by propagating debug info into coroutine funclets")
439441
PASS(PruneVTables, "prune-vtables",
440442
"Mark class methods that do not require vtable dispatch")
441443
PASS_RANGE(AllPasses, AADumper, PruneVTables)

lib/SILOptimizer/Mandatory/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ target_sources(swiftSILOptimizer PRIVATE
55
CapturePromotion.cpp
66
ClosureLifetimeFixup.cpp
77
ConstantPropagation.cpp
8+
DebugInfoCanonicalizer.cpp
89
DefiniteInitialization.cpp
910
DIMemoryUseCollector.cpp
1011
DataflowDiagnostics.cpp

0 commit comments

Comments
 (0)