Skip to content

Commit 5ea2d13

Browse files
committed
Improve the performance of IRGenDebugInfo
This commit changes how inline information is stored in SILDebugScope from a tree to a linear chain of inlined call sites (similar to what LLVM is using). This makes creating inlined SILDebugScopes slightly more expensive, but makes lowering SILDebugScopes into LLVM metadata much faster because entire inlined-at chains can now be cached. This means that SIL is no longer preserve the inlining history (i.e., ((a was inlined into b) was inlined into c) is represented the same as (a was inlined into (b was inlined into c)), but this information was not used by anyone. On my late 2012 i7 iMac, this saves about 4 seconds when compiling the RelWithDebInfo x86_64 swift standard library — or 40% of IRGen time. rdar://problem/28311051
1 parent 3e28874 commit 5ea2d13

File tree

11 files changed

+197
-181
lines changed

11 files changed

+197
-181
lines changed

include/swift/SIL/SILDebugScope.h

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -46,82 +46,28 @@ class SILDebugScope : public SILAllocated<SILDebugScope> {
4646
/// An optional chain of inlined call sites.
4747
///
4848
/// If this scope is inlined, this points to a special "scope" that
49-
/// holds only the location of the call site. The parent scope will be
50-
/// the scope of the inlined call site.
51-
///
52-
/// Note that compared to the inlinedAt chain in llvm::DILocation
53-
/// SILDebugScope represents an inline tree.
49+
/// holds the location of the call site.
5450
const SILDebugScope *InlinedCallSite;
5551

5652
SILDebugScope(SILLocation Loc, SILFunction *SILFn,
5753
const SILDebugScope *ParentScope = nullptr,
58-
const SILDebugScope *InlinedCallSite = nullptr)
59-
: Loc(Loc), InlinedCallSite(InlinedCallSite) {
60-
if (ParentScope)
61-
Parent = ParentScope;
62-
else {
63-
assert(SILFn && "no parent provided");
64-
Parent = SILFn;
65-
}
66-
}
54+
const SILDebugScope *InlinedCallSite = nullptr);
6755

6856
/// Create a scope for an artificial function.
69-
SILDebugScope(SILLocation Loc)
70-
: Loc(Loc), InlinedCallSite(nullptr) {}
71-
72-
/// Create an inlined version of CalleeScope.
73-
SILDebugScope(const SILDebugScope *CallSiteScope,
74-
const SILDebugScope *CalleeScope)
75-
: Loc(CalleeScope->Loc), Parent(CalleeScope),
76-
InlinedCallSite(CallSiteScope) {
77-
assert(CallSiteScope && CalleeScope);
78-
if (InlinedCallSite)
79-
assert(!InlinedCallSite->InlinedCallSite &&
80-
"a call site scope cannot have an inlined call site");
81-
}
57+
SILDebugScope(SILLocation Loc);
8258

8359
/// Return the function this scope originated from before being inlined.
84-
SILFunction *getInlinedFunction() const {
85-
if (Parent.isNull())
86-
return nullptr;
60+
SILFunction *getInlinedFunction() const;
8761

88-
const SILDebugScope *Scope = this;
89-
while (Scope->Parent.is<const SILDebugScope *>())
90-
Scope = Scope->Parent.get<const SILDebugScope *>();
91-
assert(Scope->Parent.is<SILFunction *>() && "orphaned scope");
92-
return Scope->Parent.get<SILFunction *>();
93-
}
94-
95-
/// Return this scope without inline information.
96-
const SILDebugScope *getInlinedScope() const {
97-
return InlinedCallSite ? Parent.get<const SILDebugScope*>() : this;
98-
}
99-
10062
/// Return the parent function of this scope. If the scope was
10163
/// inlined this recursively returns the function it was inlined
10264
/// into.
103-
SILFunction *getParentFunction() const {
104-
if (InlinedCallSite)
105-
return InlinedCallSite->Parent.get<const SILDebugScope *>()
106-
->getParentFunction();
107-
if (auto *ParentScope = Parent.dyn_cast<const SILDebugScope *>())
108-
return ParentScope->getParentFunction();
109-
return Parent.get<SILFunction *>();
110-
}
111-
112-
typedef SmallVector<const SILDebugScope *, 8> InlineScopeList;
113-
static void flatten(const SILDebugScope *DS, InlineScopeList &List);
114-
115-
// Return a flattened representation of the inline scope tree that
116-
// is equivalent to the reversed inlined-at chain.
117-
InlineScopeList flattenedInlineTree() const {
118-
InlineScopeList List;
119-
flatten(this, List);
120-
return List;
121-
}
65+
SILFunction *getParentFunction() const;
12266

67+
#ifndef NDEBUG
12368
void dump(SourceManager &SM, llvm::raw_ostream &OS = llvm::errs(),
12469
unsigned Indent = 0) const;
70+
#endif
12571
};
12672

12773
#ifndef NDEBUG

include/swift/SIL/SILLocation.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,12 @@ class SILLocation {
410410
SourceLoc getSourceLoc() const;
411411
SourceLoc getStartSourceLoc() const;
412412
SourceLoc getEndSourceLoc() const;
413-
414413
SourceRange getSourceRange() const {
415-
return { getStartSourceLoc(), getEndSourceLoc() };
414+
return {getStartSourceLoc(), getEndSourceLoc()};
415+
}
416+
DebugLoc getDebugInfoLoc() const {
417+
assert(isDebugInfoLoc());
418+
return Loc.DebugInfoLoc;
416419
}
417420

418421
/// Fingerprint a DebugLoc for use in a DenseMap.

include/swift/SILOptimizer/Utils/SILInliner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class SILInliner : public TypeSubstCloner<SILInliner> {
5151
CloneCollector::CallbackType Callback = nullptr)
5252
: TypeSubstCloner<SILInliner>(To, From, ApplySubs,
5353
OpenedArchetypesTracker, true),
54-
IKind(IKind), CalleeEntryBB(nullptr), CallSiteScope(nullptr),
54+
IKind(IKind), CalleeEntryBB(nullptr),
5555
Callback(Callback) {
5656
}
5757

@@ -114,7 +114,7 @@ class SILInliner : public TypeSubstCloner<SILInliner> {
114114
/// Alternatively, it can be the SIL file location of the call site (in case
115115
/// of SIL-to-SIL transformations).
116116
Optional<SILLocation> Loc;
117-
const SILDebugScope *CallSiteScope;
117+
const SILDebugScope *CallSiteScope = nullptr;
118118
SILFunction *CalleeFunction;
119119
llvm::SmallDenseMap<const SILDebugScope *,
120120
const SILDebugScope *> InlinedScopeCache;

0 commit comments

Comments
 (0)