Skip to content

Commit e14a46f

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 d7f598c commit e14a46f

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
@@ -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"
@@ -81,6 +82,23 @@ using namespace llvm;
8182

8283
namespace {
8384

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

118136
TargetTransformInfo &TTI;
119137

138+
const MetadataSetTy &GlobalDebugInfo;
139+
120140
/// Create a cloner for a switch lowering.
121141
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
122-
Kind FKind, TargetTransformInfo &TTI)
142+
Kind FKind, TargetTransformInfo &TTI,
143+
const MetadataSetTy &GlobalDebugInfo)
123144
: OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind),
124-
Builder(OrigF.getContext()), TTI(TTI) {
145+
Builder(OrigF.getContext()), TTI(TTI),
146+
GlobalDebugInfo(GlobalDebugInfo) {
125147
assert(Shape.ABI == coro::ABI::Switch);
126148
}
127149

128150
/// Create a cloner for a continuation lowering.
129151
CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
130152
Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
131-
TargetTransformInfo &TTI)
153+
TargetTransformInfo &TTI, const MetadataSetTy &GlobalDebugInfo)
132154
: OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
133155
FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
134-
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) {
156+
Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI),
157+
GlobalDebugInfo(GlobalDebugInfo) {
135158
assert(Shape.ABI == coro::ABI::Retcon ||
136159
Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async);
137160
assert(NewF && "need existing function for continuation");
@@ -142,10 +165,11 @@ class CoroCloner {
142165
/// Create a clone for a switch lowering.
143166
static Function *createClone(Function &OrigF, const Twine &Suffix,
144167
coro::Shape &Shape, Kind FKind,
145-
TargetTransformInfo &TTI) {
168+
TargetTransformInfo &TTI,
169+
const MetadataSetTy &GlobalDebugInfo) {
146170
TimeTraceScope FunctionScope("CoroCloner");
147171

148-
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);
172+
CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI, GlobalDebugInfo);
149173
Cloner.create();
150174
return Cloner.getFunction();
151175
}
@@ -154,10 +178,12 @@ class CoroCloner {
154178
static Function *createClone(Function &OrigF, const Twine &Suffix,
155179
coro::Shape &Shape, Function *NewF,
156180
AnyCoroSuspendInst *ActiveSuspend,
157-
TargetTransformInfo &TTI) {
181+
TargetTransformInfo &TTI,
182+
const MetadataSetTy &GlobalDebugInfo) {
158183
TimeTraceScope FunctionScope("CoroCloner");
159184

160-
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
185+
CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI,
186+
GlobalDebugInfo);
161187
Cloner.create();
162188
return Cloner.getFunction();
163189
}
@@ -1013,8 +1039,11 @@ void CoroCloner::create() {
10131039
auto savedLinkage = NewF->getLinkage();
10141040
NewF->setLinkage(llvm::GlobalValue::ExternalLinkage);
10151041

1016-
CloneFunctionInto(NewF, &OrigF, VMap,
1017-
CloneFunctionChangeType::LocalChangesOnly, Returns);
1042+
CloneFunctionAttributesInto(NewF, &OrigF, VMap, false);
1043+
CloneFunctionMetadataInto(NewF, &OrigF, VMap, RF_None, nullptr, nullptr,
1044+
&GlobalDebugInfo);
1045+
CloneFunctionBodyInto(NewF, &OrigF, VMap, RF_None, Returns, "", nullptr,
1046+
nullptr, nullptr, &GlobalDebugInfo);
10181047

10191048
auto &Context = NewF->getContext();
10201049

@@ -1488,16 +1517,22 @@ struct SwitchCoroutineSplitter {
14881517
TargetTransformInfo &TTI) {
14891518
assert(Shape.ABI == coro::ABI::Switch);
14901519

1520+
MetadataSetTy GlobalDebugInfo;
1521+
collectGlobalDebugInfo(F, GlobalDebugInfo);
1522+
14911523
// Create a resume clone by cloning the body of the original function,
14921524
// setting new entry block and replacing coro.suspend an appropriate value
14931525
// to force resume or cleanup pass for every suspend point.
14941526
createResumeEntryBlock(F, Shape);
1495-
auto *ResumeClone = CoroCloner::createClone(
1496-
F, ".resume", Shape, CoroCloner::Kind::SwitchResume, TTI);
1497-
auto *DestroyClone = CoroCloner::createClone(
1498-
F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind, TTI);
1527+
auto *ResumeClone = CoroCloner::createClone(F, ".resume", Shape,
1528+
CoroCloner::Kind::SwitchResume,
1529+
TTI, GlobalDebugInfo);
1530+
auto *DestroyClone = CoroCloner::createClone(F, ".destroy", Shape,
1531+
CoroCloner::Kind::SwitchUnwind,
1532+
TTI, GlobalDebugInfo);
14991533
auto *CleanupClone = CoroCloner::createClone(
1500-
F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI);
1534+
F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI,
1535+
GlobalDebugInfo);
15011536

15021537
postSplitCleanup(*ResumeClone);
15031538
postSplitCleanup(*DestroyClone);
@@ -1882,12 +1917,16 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,
18821917
}
18831918

18841919
assert(Clones.size() == Shape.CoroSuspends.size());
1920+
1921+
MetadataSetTy GlobalDebugInfo;
1922+
collectGlobalDebugInfo(F, GlobalDebugInfo);
1923+
18851924
for (size_t Idx = 0, End = Shape.CoroSuspends.size(); Idx != End; ++Idx) {
18861925
auto *Suspend = Shape.CoroSuspends[Idx];
18871926
auto *Clone = Clones[Idx];
18881927

18891928
CoroCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, Suspend,
1890-
TTI);
1929+
TTI, GlobalDebugInfo);
18911930
}
18921931
}
18931932

@@ -2012,12 +2051,16 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
20122051
}
20132052

20142053
assert(Clones.size() == Shape.CoroSuspends.size());
2054+
2055+
MetadataSetTy GlobalDebugInfo;
2056+
collectGlobalDebugInfo(F, GlobalDebugInfo);
2057+
20152058
for (size_t i = 0, e = Shape.CoroSuspends.size(); i != e; ++i) {
20162059
auto Suspend = Shape.CoroSuspends[i];
20172060
auto Clone = Clones[i];
20182061

2019-
CoroCloner::createClone(F, "resume." + Twine(i), Shape, Clone, Suspend,
2020-
TTI);
2062+
CoroCloner::createClone(F, "resume." + Twine(i), Shape, Clone, Suspend, TTI,
2063+
GlobalDebugInfo);
20212064
}
20222065
}
20232066

0 commit comments

Comments
 (0)