Skip to content

Commit f5002a0

Browse files
authored
[Utils] Extract CollectDebugInfoForCloning from CloneFunctionInto (#114537)
Summary: Consolidate the logic in a single function. We do an extra pass over Instructions but this is necessary to untangle things and extract metadata cloning in a future diff. Test Plan: ``` $ ninja check-llvm-unit check-llvm [211/213] Running the LLVM regression tests Testing Time: 106.06s Total Discovered Tests: 62601 Skipped : 17 (0.03%) Unsupported : 2518 (4.02%) Passed : 59911 (95.70%) Expectedly Failed: 155 (0.25%) [212/213] Running lit suite Testing Time: 12.47s Total Discovered Tests: 8474 Skipped: 17 (0.20%) Passed : 8457 (99.80%) ``` Extracted from #109032 (commit 3) (there are more refactors and cleanups in subsequent commits)
1 parent ecda140 commit f5002a0

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

llvm/include/llvm/Transforms/Utils/Cloning.h

+14
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
207207
const char *NameSuffix = "",
208208
ClonedCodeInfo *CodeInfo = nullptr);
209209

210+
/// Collect debug information such as types, compile units, and other
211+
/// subprograms that are reachable from \p F and can be considered global for
212+
/// the purposes of cloning (and hence not needing to be cloned).
213+
///
214+
/// What debug information should be processed depends on \p Changes: when
215+
/// cloning into the same module we process \p F's subprogram and instructions;
216+
/// when into a cloned module, neither of those.
217+
///
218+
/// Returns DISubprogram of the cloned function when cloning into the same
219+
/// module or nullptr otherwise.
220+
DISubprogram *CollectDebugInfoForCloning(const Function &F,
221+
CloneFunctionChangeType Changes,
222+
DebugInfoFinder &DIFinder);
223+
210224
/// This class captures the data input to the InlineFunction call, and records
211225
/// the auxiliary results produced by it.
212226
class InlineFunctionInfo {

llvm/lib/Transforms/Utils/CloneFunction.cpp

+39-20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/IR/DebugInfo.h"
2424
#include "llvm/IR/DerivedTypes.h"
2525
#include "llvm/IR/Function.h"
26+
#include "llvm/IR/InstIterator.h"
2627
#include "llvm/IR/Instructions.h"
2728
#include "llvm/IR/IntrinsicInst.h"
2829
#include "llvm/IR/LLVMContext.h"
@@ -136,6 +137,26 @@ void llvm::CloneFunctionAttributesInto(Function *NewFunc,
136137
OldAttrs.getRetAttrs(), NewArgAttrs));
137138
}
138139

140+
DISubprogram *llvm::CollectDebugInfoForCloning(const Function &F,
141+
CloneFunctionChangeType Changes,
142+
DebugInfoFinder &DIFinder) {
143+
DISubprogram *SPClonedWithinModule = nullptr;
144+
if (Changes < CloneFunctionChangeType::DifferentModule) {
145+
SPClonedWithinModule = F.getSubprogram();
146+
}
147+
if (SPClonedWithinModule)
148+
DIFinder.processSubprogram(SPClonedWithinModule);
149+
150+
const Module *M = F.getParent();
151+
if (Changes != CloneFunctionChangeType::ClonedModule && M) {
152+
// Inspect instructions to process e.g. DILexicalBlocks of inlined functions
153+
for (const auto &I : instructions(F))
154+
DIFinder.processInstruction(*M, I);
155+
}
156+
157+
return SPClonedWithinModule;
158+
}
159+
139160
// Clone OldFunc into NewFunc, transforming the old arguments into references to
140161
// VMap values.
141162
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
@@ -168,44 +189,42 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
168189
// duplicate instructions and then freeze them in the MD map. We also record
169190
// information about dbg.value and dbg.declare to avoid duplicating the
170191
// types.
171-
std::optional<DebugInfoFinder> DIFinder;
192+
DebugInfoFinder DIFinder;
172193

173194
// Track the subprogram attachment that needs to be cloned to fine-tune the
174195
// mapping within the same module.
175-
DISubprogram *SPClonedWithinModule = nullptr;
176196
if (Changes < CloneFunctionChangeType::DifferentModule) {
197+
// Need to find subprograms, types, and compile units.
198+
177199
assert((NewFunc->getParent() == nullptr ||
178200
NewFunc->getParent() == OldFunc->getParent()) &&
179201
"Expected NewFunc to have the same parent, or no parent");
180-
181-
// Need to find subprograms, types, and compile units.
182-
DIFinder.emplace();
183-
184-
SPClonedWithinModule = OldFunc->getSubprogram();
185-
if (SPClonedWithinModule)
186-
DIFinder->processSubprogram(SPClonedWithinModule);
187202
} else {
203+
// Need to find all the compile units.
204+
188205
assert((NewFunc->getParent() == nullptr ||
189206
NewFunc->getParent() != OldFunc->getParent()) &&
190207
"Expected NewFunc to have different parents, or no parent");
191208

192209
if (Changes == CloneFunctionChangeType::DifferentModule) {
193210
assert(NewFunc->getParent() &&
194211
"Need parent of new function to maintain debug info invariants");
195-
196-
// Need to find all the compile units.
197-
DIFinder.emplace();
198212
}
199213
}
200214

215+
DISubprogram *SPClonedWithinModule =
216+
CollectDebugInfoForCloning(*OldFunc, Changes, DIFinder);
217+
201218
// Loop over all of the basic blocks in the function, cloning them as
202219
// appropriate. Note that we save BE this way in order to handle cloning of
203220
// recursive functions into themselves.
204221
for (const BasicBlock &BB : *OldFunc) {
205222

206223
// Create a new basic block and copy instructions into it!
207-
BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo,
208-
DIFinder ? &*DIFinder : nullptr);
224+
// NOTE: don't pass DIFinder because instructions' debug info was processed
225+
// in ProcessSubprogramAttachment. This will be cleaned up further.
226+
BasicBlock *CBB =
227+
CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo, nullptr);
209228

210229
// Add basic block mapping.
211230
VMap[&BB] = CBB;
@@ -228,7 +247,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
228247
}
229248

230249
if (Changes < CloneFunctionChangeType::DifferentModule &&
231-
DIFinder->subprogram_count() > 0) {
250+
DIFinder.subprogram_count() > 0) {
232251
// Turn on module-level changes, since we need to clone (some of) the
233252
// debug info metadata.
234253
//
@@ -243,24 +262,24 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
243262

244263
// Avoid cloning types, compile units, and (other) subprograms.
245264
SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
246-
for (DISubprogram *ISP : DIFinder->subprograms()) {
265+
for (DISubprogram *ISP : DIFinder.subprograms()) {
247266
if (ISP != SPClonedWithinModule) {
248267
mapToSelfIfNew(ISP);
249268
MappedToSelfSPs.insert(ISP);
250269
}
251270
}
252271

253272
// If a subprogram isn't going to be cloned skip its lexical blocks as well.
254-
for (DIScope *S : DIFinder->scopes()) {
273+
for (DIScope *S : DIFinder.scopes()) {
255274
auto *LScope = dyn_cast<DILocalScope>(S);
256275
if (LScope && MappedToSelfSPs.count(LScope->getSubprogram()))
257276
mapToSelfIfNew(S);
258277
}
259278

260-
for (DICompileUnit *CU : DIFinder->compile_units())
279+
for (DICompileUnit *CU : DIFinder.compile_units())
261280
mapToSelfIfNew(CU);
262281

263-
for (DIType *Type : DIFinder->types())
282+
for (DIType *Type : DIFinder.types())
264283
mapToSelfIfNew(Type);
265284
} else {
266285
assert(!SPClonedWithinModule &&
@@ -314,7 +333,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
314333
SmallPtrSet<const void *, 8> Visited;
315334
for (auto *Operand : NMD->operands())
316335
Visited.insert(Operand);
317-
for (auto *Unit : DIFinder->compile_units()) {
336+
for (auto *Unit : DIFinder.compile_units()) {
318337
MDNode *MappedUnit =
319338
MapMetadata(Unit, VMap, RF_None, TypeMapper, Materializer);
320339
if (Visited.insert(MappedUnit).second)

0 commit comments

Comments
 (0)