Skip to content

Commit b92706a

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 3a8fe6c commit b92706a

File tree

1 file changed

+60
-17
lines changed

1 file changed

+60
-17
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "llvm/IR/CallingConv.h"
4343
#include "llvm/IR/Constants.h"
4444
#include "llvm/IR/DataLayout.h"
45+
#include "llvm/IR/DebugInfo.h"
4546
#include "llvm/IR/DerivedTypes.h"
4647
#include "llvm/IR/Dominators.h"
4748
#include "llvm/IR/Function.h"
@@ -84,6 +85,23 @@ using namespace llvm;
8485

8586
namespace {
8687

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

121139
TargetTransformInfo &TTI;
122140

141+
const MetadataSetTy &GlobalDebugInfo;
142+
123143
/// Create a cloner for a switch lowering.
124144
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
125-
Kind FKind, TargetTransformInfo &TTI)
145+
Kind FKind, TargetTransformInfo &TTI,
146+
const MetadataSetTy &GlobalDebugInfo)
126147
: OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind),
127-
Builder(OrigF.getContext()), TTI(TTI) {
148+
Builder(OrigF.getContext()), TTI(TTI),
149+
GlobalDebugInfo(GlobalDebugInfo) {
128150
assert(Shape.ABI == coro::ABI::Switch);
129151
}
130152

131153
/// Create a cloner for a continuation lowering.
132154
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
133155
Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
134-
TargetTransformInfo &TTI)
156+
TargetTransformInfo &TTI, const MetadataSetTy &GlobalDebugInfo)
135157
: OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
136158
FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
137-
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) {
159+
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI),
160+
GlobalDebugInfo(GlobalDebugInfo) {
138161
assert(Shape.ABI == coro::ABI::Retcon ||
139162
Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async);
140163
assert(NewF && "need existing function for continuation");
@@ -145,10 +168,11 @@ class CoroCloner {
145168
/// Create a clone for a switch lowering.
146169
static Function *createClone(Function &OrigF, const Twine &Suffix,
147170
coro::Shape &Shape, Kind FKind,
148-
TargetTransformInfo &TTI) {
171+
TargetTransformInfo &TTI,
172+
const MetadataSetTy &GlobalDebugInfo) {
149173
TimeTraceScope FunctionScope("CoroCloner");
150174

151-
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);
175+
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI, GlobalDebugInfo);
152176
Cloner.create();
153177
return Cloner.getFunction();
154178
}
@@ -157,10 +181,12 @@ class CoroCloner {
157181
static Function *createClone(Function &OrigF, const Twine &Suffix,
158182
coro::Shape &Shape, Function *NewF,
159183
AnyCoroSuspendInst *ActiveSuspend,
160-
TargetTransformInfo &TTI) {
184+
TargetTransformInfo &TTI,
185+
const MetadataSetTy &GlobalDebugInfo) {
161186
TimeTraceScope FunctionScope("CoroCloner");
162187

163-
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
188+
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI,
189+
GlobalDebugInfo);
164190
Cloner.create();
165191
return Cloner.getFunction();
166192
}
@@ -1016,8 +1042,11 @@ void CoroCloner::create() {
10161042
auto savedLinkage = NewF->getLinkage();
10171043
NewF->setLinkage(llvm::GlobalValue::ExternalLinkage);
10181044

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

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

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

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

15051540
postSplitCleanup(*ResumeClone);
15061541
postSplitCleanup(*DestroyClone);
@@ -1885,12 +1920,16 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
18851920
}
18861921

18871922
assert(Clones.size() == Shape.CoroSuspends.size());
1923+
1924+
MetadataSetTy GlobalDebugInfo;
1925+
collectGlobalDebugInfo(F, GlobalDebugInfo);
1926+
18881927
for (auto CS : llvm::enumerate(Shape.CoroSuspends)) {
18891928
auto *Suspend = CS.value();
18901929
auto *Clone = Clones[CS.index()];
18911930

18921931
CoroCloner::createClone(F, "resume." + Twine(CS.index()), Shape, Clone,
1893-
Suspend, TTI);
1932+
Suspend, TTI, GlobalDebugInfo);
18941933
}
18951934
}
18961935

@@ -2016,12 +2055,16 @@ void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape,
20162055
}
20172056

20182057
assert(Clones.size() == Shape.CoroSuspends.size());
2058+
2059+
MetadataSetTy GlobalDebugInfo;
2060+
collectGlobalDebugInfo(F, GlobalDebugInfo);
2061+
20192062
for (auto CS : llvm::enumerate(Shape.CoroSuspends)) {
20202063
auto Suspend = CS.value();
20212064
auto Clone = Clones[CS.index()];
20222065

20232066
CoroCloner::createClone(F, "resume." + Twine(CS.index()), Shape, Clone,
2024-
Suspend, TTI);
2067+
Suspend, TTI, GlobalDebugInfo);
20252068
}
20262069
}
20272070

0 commit comments

Comments
 (0)