Skip to content

Commit 8c528e3

Browse files
committed
[Coro] Prebuild a global debug info set and share it between all coroutine clones
Summary: CoroCloner, by calling into CloneFunctionInto, does a lot of repeated work priming DIFinder and building a list of global debug info metadata. For programs compiled with full debug info this gets very expensive. This diff builds the data once and shares it between all clones. Anecdata for a sample cpp source file compiled with full debug info: | | Baseline | IdentityMD set | Prebuilt GlobalDI (cur.) | |-----------------+----------+----------------+--------------------------| | CoroSplitPass | 306ms | 221ms | 68ms | | CoroCloner | 101ms | 72ms | 0.5ms | | CollectGlobalDI | - | - | 63ms | |-----------------+----------+----------------+--------------------------| | Speed up | 1x | 1.4x | 4.5x | Note that CollectGlobalDI happens once *per coroutine* rather than per clone. Test Plan: ninja check-llvm-unit ninja check-llvm Compiled a sample internal source file, checked time trace output for scope timings.
1 parent 8b2edb1 commit 8c528e3

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "llvm/IR/CallingConv.h"
4242
#include "llvm/IR/Constants.h"
4343
#include "llvm/IR/DataLayout.h"
44+
#include "llvm/IR/DebugInfo.h"
4445
#include "llvm/IR/DerivedTypes.h"
4546
#include "llvm/IR/Dominators.h"
4647
#include "llvm/IR/Function.h"
@@ -83,6 +84,23 @@ using namespace llvm;
8384

8485
namespace {
8586

87+
/// Collect (a known) subset of global debug info metadata potentially used by
88+
/// the function \p F.
89+
///
90+
/// This metadata set can be used to avoid cloning debug info not owned by \p F
91+
/// and is shared among all potential clones \p F.
92+
void collectGlobalDebugInfo(Function &F, MetadataSetTy &GlobalDebugInfo) {
93+
TimeTraceScope FunctionScope("CollectGlobalDebugInfo");
94+
95+
DebugInfoFinder DIFinder;
96+
DISubprogram *SPClonedWithinModule = ProcessSubprogramAttachment(
97+
F, CloneFunctionChangeType::LocalChangesOnly, DIFinder);
98+
99+
FindDebugInfoToIdentityMap(GlobalDebugInfo,
100+
CloneFunctionChangeType::LocalChangesOnly,
101+
DIFinder, SPClonedWithinModule);
102+
}
103+
86104
/// A little helper class for building
87105
class CoroCloner {
88106
public:
@@ -119,21 +137,26 @@ class CoroCloner {
119137

120138
TargetTransformInfo &TTI;
121139

140+
const MetadataSetTy &GlobalDebugInfo;
141+
122142
/// Create a cloner for a switch lowering.
123143
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
124-
Kind FKind, TargetTransformInfo &TTI)
144+
Kind FKind, TargetTransformInfo &TTI,
145+
const MetadataSetTy &GlobalDebugInfo)
125146
: OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind),
126-
Builder(OrigF.getContext()), TTI(TTI) {
147+
Builder(OrigF.getContext()), TTI(TTI),
148+
GlobalDebugInfo(GlobalDebugInfo) {
127149
assert(Shape.ABI == coro::ABI::Switch);
128150
}
129151

130152
/// Create a cloner for a continuation lowering.
131153
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
132154
Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
133-
TargetTransformInfo &TTI)
155+
TargetTransformInfo &TTI, const MetadataSetTy &GlobalDebugInfo)
134156
: OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
135157
FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
136-
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) {
158+
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI),
159+
GlobalDebugInfo(GlobalDebugInfo) {
137160
assert(Shape.ABI == coro::ABI::Retcon ||
138161
Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async);
139162
assert(NewF && "need existing function for continuation");
@@ -144,10 +167,11 @@ class CoroCloner {
144167
/// Create a clone for a switch lowering.
145168
static Function *createClone(Function &OrigF, const Twine &Suffix,
146169
coro::Shape &Shape, Kind FKind,
147-
TargetTransformInfo &TTI) {
170+
TargetTransformInfo &TTI,
171+
const MetadataSetTy &GlobalDebugInfo) {
148172
TimeTraceScope FunctionScope("CoroCloner");
149173

150-
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);
174+
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI, GlobalDebugInfo);
151175
Cloner.create();
152176
return Cloner.getFunction();
153177
}
@@ -156,10 +180,12 @@ class CoroCloner {
156180
static Function *createClone(Function &OrigF, const Twine &Suffix,
157181
coro::Shape &Shape, Function *NewF,
158182
AnyCoroSuspendInst *ActiveSuspend,
159-
TargetTransformInfo &TTI) {
183+
TargetTransformInfo &TTI,
184+
const MetadataSetTy &GlobalDebugInfo) {
160185
TimeTraceScope FunctionScope("CoroCloner");
161186

162-
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
187+
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI,
188+
GlobalDebugInfo);
163189
Cloner.create();
164190
return Cloner.getFunction();
165191
}
@@ -1015,8 +1041,11 @@ void CoroCloner::create() {
10151041
auto savedLinkage = NewF->getLinkage();
10161042
NewF->setLinkage(llvm::GlobalValue::ExternalLinkage);
10171043

1018-
CloneFunctionInto(NewF, &OrigF, VMap,
1019-
CloneFunctionChangeType::LocalChangesOnly, Returns);
1044+
CloneFunctionAttributesInto(NewF, &OrigF, VMap, false);
1045+
CloneFunctionMetadataInto(NewF, &OrigF, VMap, RF_None, nullptr, nullptr,
1046+
&GlobalDebugInfo);
1047+
CloneFunctionBodyInto(NewF, &OrigF, VMap, RF_None, Returns, "", nullptr,
1048+
nullptr, nullptr, &GlobalDebugInfo);
10201049

10211050
auto &Context = NewF->getContext();
10221051

@@ -1490,16 +1519,22 @@ struct SwitchCoroutineSplitter {
14901519
TargetTransformInfo &TTI) {
14911520
assert(Shape.ABI == coro::ABI::Switch);
14921521

1522+
MetadataSetTy GlobalDebugInfo;
1523+
collectGlobalDebugInfo(F, GlobalDebugInfo);
1524+
14931525
// Create a resume clone by cloning the body of the original function,
14941526
// setting new entry block and replacing coro.suspend an appropriate value
14951527
// to force resume or cleanup pass for every suspend point.
14961528
createResumeEntryBlock(F, Shape);
1497-
auto *ResumeClone = CoroCloner::createClone(
1498-
F, ".resume", Shape, CoroCloner::Kind::SwitchResume, TTI);
1499-
auto *DestroyClone = CoroCloner::createClone(
1500-
F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind, TTI);
1529+
auto *ResumeClone = CoroCloner::createClone(F, ".resume", Shape,
1530+
CoroCloner::Kind::SwitchResume,
1531+
TTI, GlobalDebugInfo);
1532+
auto *DestroyClone = CoroCloner::createClone(F, ".destroy", Shape,
1533+
CoroCloner::Kind::SwitchUnwind,
1534+
TTI, GlobalDebugInfo);
15011535
auto *CleanupClone = CoroCloner::createClone(
1502-
F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI);
1536+
F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI,
1537+
GlobalDebugInfo);
15031538

15041539
postSplitCleanup(*ResumeClone);
15051540
postSplitCleanup(*DestroyClone);
@@ -1884,12 +1919,16 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
18841919
}
18851920

18861921
assert(Clones.size() == Shape.CoroSuspends.size());
1922+
1923+
MetadataSetTy GlobalDebugInfo;
1924+
collectGlobalDebugInfo(F, GlobalDebugInfo);
1925+
18871926
for (size_t Idx = 0, End = Shape.CoroSuspends.size(); Idx != End; ++Idx) {
18881927
auto *Suspend = Shape.CoroSuspends[Idx];
18891928
auto *Clone = Clones[Idx];
18901929

18911930
CoroCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, Suspend,
1892-
TTI);
1931+
TTI, GlobalDebugInfo);
18931932
}
18941933
}
18951934

@@ -2014,12 +2053,16 @@ void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape,
20142053
}
20152054

20162055
assert(Clones.size() == Shape.CoroSuspends.size());
2056+
2057+
MetadataSetTy GlobalDebugInfo;
2058+
collectGlobalDebugInfo(F, GlobalDebugInfo);
2059+
20172060
for (size_t i = 0, e = Shape.CoroSuspends.size(); i != e; ++i) {
20182061
auto Suspend = Shape.CoroSuspends[i];
20192062
auto Clone = Clones[i];
20202063

2021-
CoroCloner::createClone(F, "resume." + Twine(i), Shape, Clone, Suspend,
2022-
TTI);
2064+
CoroCloner::createClone(F, "resume." + Twine(i), Shape, Clone, Suspend, TTI,
2065+
GlobalDebugInfo);
20232066
}
20242067
}
20252068

0 commit comments

Comments
 (0)