Proteus
Programmable JIT compilation and optimization for C/C++ using LLVM
Loading...
Searching...
No Matches
Cloning.h
Go to the documentation of this file.
1#ifndef PROTEUS_CLONING_H
2#define PROTEUS_CLONING_H
3
4#include "proteus/Error.h"
8
9#include <llvm/Analysis/CallGraph.h>
10#include <llvm/IR/Constants.h>
11#include <llvm/IR/Module.h>
12#include <llvm/IR/Verifier.h>
13#include <llvm/Transforms/Utils/Cloning.h>
14
15namespace proteus {
16
17using namespace llvm;
18
19inline std::unique_ptr<Module> cloneKernelFromModule(Module &M, StringRef Name,
20 CallGraph &CG) {
21 auto KernelModuleTmp = std::make_unique<Module>("JitModule", M.getContext());
22 KernelModuleTmp->setSourceFileName(M.getSourceFileName());
23 KernelModuleTmp->setDataLayout(M.getDataLayout());
24 KernelModuleTmp->setTargetTriple(M.getTargetTriple());
25 KernelModuleTmp->setModuleInlineAsm(M.getModuleInlineAsm());
26#if LLVM_VERSION_MAJOR >= 18
27 KernelModuleTmp->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
28#endif
29
30 auto *KernelFunction = M.getFunction(Name);
31 if (!KernelFunction)
32 reportFatalError("Expected function " + Name);
33
34 SmallPtrSet<Function *, 8> ReachableFunctions;
35 SmallPtrSet<GlobalVariable *, 16> ReachableGlobals;
36 SmallPtrSet<Function *, 8> ReachableDeclarations;
37 SmallVector<Function *, 8> ToVisit;
38 ReachableFunctions.insert(KernelFunction);
39 ToVisit.push_back(KernelFunction);
40 while (!ToVisit.empty()) {
41 Function *VisitF = ToVisit.pop_back_val();
42 CallGraphNode *CGNode = CG[VisitF];
43
44 for (const auto &Callee : *CGNode) {
45 Function *CalleeF = Callee.second->getFunction();
46 if (!CalleeF)
47 continue;
48 if (CalleeF->isDeclaration()) {
49 ReachableDeclarations.insert(CalleeF);
50 continue;
51 }
52 if (ReachableFunctions.contains(CalleeF))
53 continue;
54 ReachableFunctions.insert(CalleeF);
55 ToVisit.push_back(CalleeF);
56 }
57 }
58
59 auto ProcessInstruction = [&](GlobalVariable &GV, const Instruction *I) {
60 const Function *ParentF = I->getFunction();
61 if (ReachableFunctions.contains(ParentF))
62 ReachableGlobals.insert(&GV);
63 };
64
65 for (auto &GV : M.globals()) {
66 for (const User *Usr : GV.users()) {
67 const Instruction *I = dyn_cast<Instruction>(Usr);
68
69 if (I) {
70 ProcessInstruction(GV, I);
71 continue;
72 }
73
74 // We follow non-instructions users to process them if those are
75 // instructions.
76 // TODO: We may need to follow deeper than just users of user and also
77 // expand to non-instruction users.
78 for (const User *NextUser : Usr->users()) {
79 I = dyn_cast<Instruction>(NextUser);
80 if (!I)
81 continue;
82
83 ProcessInstruction(GV, I);
84 }
85 }
86 }
87
88 ValueToValueMapTy VMap;
89
90 for (auto *GV : ReachableGlobals) {
91 // We will set the initializer later, after VMap has been populated.
92 GlobalVariable *NewGV = new GlobalVariable(
93 *KernelModuleTmp, GV->getValueType(), GV->isConstant(),
94 GV->getLinkage(), nullptr, GV->getName(), nullptr,
95 GV->getThreadLocalMode(), GV->getAddressSpace());
96 NewGV->copyAttributesFrom(GV);
97 VMap[GV] = NewGV;
98 }
99
100 for (auto *F : ReachableFunctions) {
101 auto *NewFunction = Function::Create(F->getFunctionType(), F->getLinkage(),
102 F->getAddressSpace(), F->getName(),
103 KernelModuleTmp.get());
104 NewFunction->copyAttributesFrom(F);
105 VMap[F] = NewFunction;
106 }
107
108 for (auto *F : ReachableDeclarations) {
109 auto *NewFunction = Function::Create(F->getFunctionType(), F->getLinkage(),
110 F->getAddressSpace(), F->getName(),
111 KernelModuleTmp.get());
112 NewFunction->copyAttributesFrom(F);
113 NewFunction->setLinkage(GlobalValue::ExternalLinkage);
114 VMap[F] = NewFunction;
115 }
116
117 for (GlobalVariable *GV : ReachableGlobals) {
118 if (GV->hasInitializer()) {
119 GlobalVariable *NewGV = cast<GlobalVariable>(VMap[GV]);
120 NewGV->setInitializer(MapValue(GV->getInitializer(), VMap));
121 }
122 }
123
124 for (auto *F : ReachableFunctions) {
125 SmallVector<ReturnInst *, 8> Returns;
126 auto *NewFunction = dyn_cast<Function>(VMap[F]);
127 Function::arg_iterator DestI = NewFunction->arg_begin();
128 for (const Argument &I : F->args())
129 if (VMap.count(&I) == 0) {
130 DestI->setName(I.getName());
131 VMap[&I] = &*DestI++;
132 }
133 llvm::CloneFunctionInto(NewFunction, F, VMap,
134 CloneFunctionChangeType::DifferentModule, Returns);
135 }
136
137 // Copy annotations from M into KernelModuleTmp now that VMap has been
138 // populated.
139 const std::string MetadataToCopy[] = {"llvm.annotations", "nvvm.annotations",
140 "nvvmir.version", "llvm.module.flags"};
141 for (auto &MetadataName : MetadataToCopy) {
142 NamedMDNode *NamedMD = M.getNamedMetadata(MetadataName);
143 if (!NamedMD)
144 continue;
145
146 auto *NewNamedMD = KernelModuleTmp->getOrInsertNamedMetadata(MetadataName);
147 for (unsigned I = 0, E = NamedMD->getNumOperands(); I < E; ++I) {
148 MDNode *MDEntry = NamedMD->getOperand(I);
149 bool ShouldClone = true;
150 // Skip if the operands of an MDNode refer to non-existing,
151 // unreachable global values.
152 for (auto &Operand : MDEntry->operands()) {
153 Metadata *MD = Operand.get();
154 auto *CMD = dyn_cast<ConstantAsMetadata>(MD);
155 if (!CMD)
156 continue;
157
158 auto *GV = dyn_cast<GlobalValue>(CMD->getValue());
159 if (!GV)
160 continue;
161
162 if (!VMap.count(GV)) {
163 ShouldClone = false;
164 break;
165 }
166 }
167
168 if (!ShouldClone)
169 continue;
170
171 NewNamedMD->addOperand(MapMetadata(MDEntry, VMap));
172 }
173 }
174
175 if (Config::get().ProteusDebugOutput) {
176 Logger::logfile(Name.str() + ".mini.ll", *KernelModuleTmp);
177 if (verifyModule(*KernelModuleTmp, &errs()))
178 reportFatalError("Broken mini-module found, JIT compilation aborted!");
179 }
180
181 return KernelModuleTmp;
182}
183
185 // Definitions maps that map symbol name to GlobalValue.
186 struct DefMaps {
187 StringMap<Function *> FuncDefs;
188 StringMap<GlobalVariable *> GlobDefs;
189 };
190
191 // Stores declaration prototype and GVs that map to it.
193 FunctionType *FuncTy;
194 GlobalValue::LinkageTypes Linkage;
195 unsigned int AddrSpace;
196 AttributeList Attributes;
197 SmallPtrSet<GlobalValue *, 32> GVs;
198 };
199
203 GlobalValue::LinkageTypes Linkage;
204 Constant *Initializer;
205 GlobalValue::ThreadLocalMode TLM;
206 unsigned int AddrSpace;
207 AttributeSet Attributes;
208 SmallPtrSet<GlobalValue *, 32> GVs;
209 };
210
211 // Maps a resolved GV to cross-module GV references.
212 DenseMap<GlobalValue *, SmallVector<GlobalValue *>> ResolvedMap;
213 // Stores declaration info by symbol name to clone and update references.
214 StringMap<FuncDeclInfo> FuncDecls;
215 StringMap<GlobDeclInfo> GlobDecls;
216
217 DefMaps buildDefMaps(ArrayRef<std::reference_wrapper<Module>> Mods) {
218 DefMaps SymbolMaps;
219 for (Module &M : Mods) {
220 for (Function &F : M.functions())
221 if (!F.isDeclaration())
222 SymbolMaps.FuncDefs[F.getName()] = &F;
223 for (GlobalVariable &G : M.globals())
224 if (G.hasInitializer())
225 SymbolMaps.GlobDefs[G.getName()] = &G;
226 }
227 return SymbolMaps;
228 }
229
230 // Resolve GlobalValue to its definition across modules or fallback to the
231 // declartion if not found (e.g., intrinsics). Add to WorkList if unseen.
232 void resolveGV(const DefMaps &Defs, GlobalValue *G,
233 SmallVector<GlobalValue *> &WorkList,
234 SmallPtrSetImpl<GlobalValue *> &Found) {
235 GlobalValue *ResolvedGV = nullptr;
236 if (auto *F = dyn_cast<Function>(G)) {
237 if (!F->isDeclaration())
238 ResolvedGV = F;
239 else if (auto *D = Defs.FuncDefs.lookup(F->getName()))
240 ResolvedGV = D;
241 else {
242 if (FuncDecls.contains(F->getName()))
243 FuncDecls[F->getName()].GVs.insert(G);
244 else
245 FuncDecls[F->getName()] = {F->getFunctionType(),
246 F->getLinkage(),
247 F->getAddressSpace(),
248 F->getAttributes(),
249 {G}};
250 }
251 } else if (auto *GV = dyn_cast<GlobalVariable>(G)) {
252 if (GV->hasInitializer())
253 ResolvedGV = GV;
254 else if (auto *D = Defs.GlobDefs.lookup(GV->getName()))
255 ResolvedGV = D;
256 else {
257 if (GlobDecls.contains(GV->getName()))
258 GlobDecls[GV->getName()].GVs.insert(G);
259 else
260 GlobDecls[GV->getName()] = {
261 GV->getValueType(), GV->isConstant(),
262 GV->getLinkage(), nullptr,
263 GV->getThreadLocalMode(), GV->getAddressSpace(),
264 GV->getAttributes(), {G}};
265 }
266 } else if (auto *GA = dyn_cast<GlobalAlias>(G)) {
267 auto *GVA = dyn_cast<GlobalValue>(GA->getAliasee()->stripPointerCasts());
268 if (!GVA) {
269 SmallVector<char> ErrMsg;
270 raw_svector_ostream OS{ErrMsg};
271 G->print(OS);
272 reportFatalError("Expected aliasee to be a global value: " + ErrMsg);
273 }
274 ResolvedGV = GA;
275 } else {
276 reportFatalError("Unsupported global value: " + toString(*G));
277 }
278
279 if (ResolvedGV && Found.insert(ResolvedGV).second) {
280 WorkList.push_back(ResolvedGV);
281 ResolvedMap[ResolvedGV].push_back(G);
282 }
283 }
284
285 void scanConstant(Constant *C, const DefMaps &Defs,
286 SmallVector<GlobalValue *> &WorkList,
287 SmallPtrSetImpl<GlobalValue *> &Found) {
288 // If this is a constant expression (e.g., bitcast), unwrap and scan its
289 // operand.
290 if (auto *CE = dyn_cast<ConstantExpr>(C)) {
291 if (CE->isCast())
292 scanConstant(CE->getOperand(0), Defs, WorkList, Found);
293 }
294
295 // If C itself is a global value resolve its definition.
296 if (auto *G = dyn_cast<GlobalValue>(C))
297 resolveGV(Defs, G, WorkList, Found);
298
299 // Recurse into any operand constants.
300 for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
301 if (auto *OpC = dyn_cast<Constant>(C->getOperand(I)))
302 scanConstant(OpC, Defs, WorkList, Found);
303 }
304
305 SmallPtrSet<GlobalValue *, 32> findTransitiveClosure(Function *Entry,
306 const DefMaps &Defs) {
307 SmallPtrSet<GlobalValue *, 32> Found;
308 SmallVector<GlobalValue *> WorkList;
309
310 // Seed with the entry function.
311 resolveGV(Defs, Entry, WorkList, Found);
312
313 // Process DFS work-list.
314 while (!WorkList.empty()) {
315 auto *GV = WorkList.pop_back_val();
316
317 if (auto *F = dyn_cast<Function>(GV)) {
318 // If the function has a personality function, resolve it as it needs to
319 // be declared in the cloned module.
320 if (F->hasPersonalityFn()) {
321 if (auto *PersGV = dyn_cast<GlobalValue>(
322 F->getPersonalityFn()->stripPointerCasts())) {
323 resolveGV(Defs, PersGV, WorkList, Found);
324 }
325 }
326
327 for (auto &BB : *F) {
328 for (auto &I : BB) {
329 // Add direct calls to other functions.
330 if (auto *CB = dyn_cast<CallBase>(&I))
331 if (Function *Callee = CB->getCalledFunction())
332 resolveGV(Defs, Callee, WorkList, Found);
333
334 // Scan GlobalValue operands or Constants.
335 for (Use &U : I.operands()) {
336 Value *Op = U.get()->stripPointerCasts();
337 if (auto *GVOp = dyn_cast<GlobalValue>(Op)) {
338 resolveGV(Defs, GVOp, WorkList, Found);
339 } else if (auto *C = dyn_cast<Constant>(Op)) {
340 scanConstant(C, Defs, WorkList, Found);
341 }
342 }
343 }
344 }
345 } else if (auto *GVar = dyn_cast<GlobalVariable>(GV)) {
346 if (auto *Init = GVar->getInitializer())
347 scanConstant(Init, Defs, WorkList, Found);
348 } else if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
349 scanConstant(GA->getAliasee(), Defs, WorkList, Found);
350 } else {
351 reportFatalError("Unsupported global value: " + toString(*GV));
352 }
353 }
354
355 return Found;
356 }
357
358 std::unique_ptr<Module> cloneClosure(
359 Module &M, LLVMContext &Ctx,
360 SmallPtrSetImpl<GlobalValue *> const &Reachable,
361 function_ref<bool(const GlobalValue *)> ShouldCloneDefinition = nullptr) {
362 auto ModuleOut =
363 std::make_unique<Module>(M.getName().str() + ".closure.clone", Ctx);
364 ModuleOut->setSourceFileName(M.getSourceFileName());
365 ModuleOut->setDataLayout(M.getDataLayout());
366 ModuleOut->setTargetTriple(M.getTargetTriple());
367 ModuleOut->setModuleInlineAsm(M.getModuleInlineAsm());
368#if LLVM_VERSION_MAJOR >= 18
369 ModuleOut->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;
370#endif
371
372 ValueToValueMapTy VMap;
373
374 // Emit the function declarations.
375 for (auto &D : FuncDecls) {
376 StringRef FuncName = D.getKey();
377 FuncDeclInfo &FuncInfo = D.getValue();
378 Function *NF =
379 Function::Create(FuncInfo.FuncTy, FuncInfo.Linkage,
380 FuncInfo.AddrSpace, FuncName, ModuleOut.get());
381 NF->setAttributes(FuncInfo.Attributes);
382 for (auto *GV : FuncInfo.GVs)
383 VMap[GV] = NF;
384 }
385
386 // Emit the global variable declarations.
387 for (auto &D : GlobDecls) {
388 StringRef GVName = D.getKey();
389 GlobDeclInfo &GlobInfo = D.getValue();
390 auto *NG = new GlobalVariable(
391 *ModuleOut, GlobInfo.ValueType, GlobInfo.IsConstant, GlobInfo.Linkage,
392 nullptr, GVName, nullptr, GlobInfo.TLM, GlobInfo.AddrSpace);
393 NG->setAttributes(GlobInfo.Attributes);
394 for (auto *GV : GlobInfo.GVs)
395 VMap[GV] = NG;
396 }
397
398 // Create unpopulated declarations.
399 for (GlobalValue *GV : Reachable) {
400 if (auto *F = dyn_cast<Function>(GV)) {
401 Function *NF = Function::Create(F->getFunctionType(), F->getLinkage(),
402 F->getAddressSpace(), F->getName(),
403 ModuleOut.get());
404 NF->copyAttributesFrom(F);
405 VMap[F] = NF;
406
407 for (auto *DeclGV : ResolvedMap[F])
408 VMap[DeclGV] = NF;
409 } else if (auto *GVar = dyn_cast<GlobalVariable>(GV)) {
410 auto *NG = new GlobalVariable(
411 *ModuleOut, GV->getValueType(), GVar->isConstant(),
412 GV->getLinkage(), nullptr, GV->getName(), nullptr,
413 GV->getThreadLocalMode(), GV->getAddressSpace());
414 NG->copyAttributesFrom(GVar);
415 VMap[GVar] = NG;
416
417 for (auto *DeclGV : ResolvedMap[GVar])
418 VMap[DeclGV] = NG;
419 } else if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
420 auto *NGA = GlobalAlias::create(GA->getValueType(),
421 GA->getAddressSpace(), GA->getLinkage(),
422 GA->getName(), ModuleOut.get());
423 NGA->copyAttributesFrom(GA);
424 NGA->setVisibility(GA->getVisibility());
425 VMap[GA] = NGA;
426 } else {
427 reportFatalError("Unsupported global value: " + toString(*GV));
428 }
429 }
430
431 // Clone function bodies and global variable initializers.
432 for (GlobalValue *GV : Reachable) {
433 // Check if the ShouldCloneDefinition callback exists and call to exclude
434 // or include the definition of this GV.
435 if (ShouldCloneDefinition)
436 if (!ShouldCloneDefinition(GV))
437 continue;
438
439 if (auto *F = dyn_cast<Function>(GV)) {
440 Function *NF = cast<Function>(VMap[F]);
441 SmallVector<ReturnInst *, 8> Returns;
442 Function::arg_iterator DestI = NF->arg_begin();
443 for (const Argument &I : F->args())
444 if (VMap.count(&I) == 0) {
445 DestI->setName(I.getName());
446 VMap[&I] = &*DestI++;
447 }
448
449 CloneFunctionInto(NF, F, VMap,
450 /*Changes=*/CloneFunctionChangeType::DifferentModule,
451 Returns);
452 } else if (auto *GVar = dyn_cast<GlobalVariable>(GV)) {
453 auto *NG = cast<GlobalVariable>(VMap[GVar]);
454 if (GVar->hasInitializer())
455 NG->setInitializer(MapValue(GVar->getInitializer(), VMap));
456 } else if (auto *GA = dyn_cast<GlobalAlias>(GV)) {
457 auto *Aliasee = GA->getAliasee();
458 auto *NGA = cast<GlobalAlias>(VMap[GA]);
459 NGA->setAliasee(MapValue(Aliasee, VMap));
460 } else {
461 reportFatalError("Unsupported global value: " + toString(*GV));
462 }
463 }
464
465 // Copy annotations from the entry module M into KernelModuleTmp now that
466 // VMap has been populated.
467 const std::string MetadataToCopy[] = {"llvm.annotations",
468 "nvvm.annotations", "nvvmir.version",
469 "llvm.module.flags"};
470 for (auto &MetadataName : MetadataToCopy) {
471 NamedMDNode *NamedMD = M.getNamedMetadata(MetadataName);
472 if (!NamedMD)
473 continue;
474
475 auto *NewNamedMD = ModuleOut->getOrInsertNamedMetadata(MetadataName);
476 for (unsigned I = 0, E = NamedMD->getNumOperands(); I < E; ++I) {
477 MDNode *MDEntry = NamedMD->getOperand(I);
478 bool ShouldClone = true;
479 // Skip if the operands of an MDNode refer to non-existing,
480 // unreachable global values.
481 for (auto &Operand : MDEntry->operands()) {
482 Metadata *MD = Operand.get();
483 auto *CMD = dyn_cast<ConstantAsMetadata>(MD);
484 if (!CMD)
485 continue;
486
487 auto *GV = dyn_cast<GlobalValue>(CMD->getValue());
488 if (!GV)
489 continue;
490
491 if (!VMap.count(GV)) {
492 ShouldClone = false;
493 break;
494 }
495 }
496
497 if (!ShouldClone)
498 continue;
499
500 NewNamedMD->addOperand(MapMetadata(MDEntry, VMap));
501 }
502 }
503
504 if (Config::get().ProteusDebugOutput) {
505 if (verifyModule(*ModuleOut, &errs()))
507 "Broken cross-module clone found, JIT compilation aborted!");
508 }
509 return ModuleOut;
510 }
511};
512
513inline std::unique_ptr<Module> cloneKernelFromModules(
514 ArrayRef<std::reference_wrapper<Module>> Mods, StringRef EntryName,
515 function_ref<bool(const GlobalValue *)> ShouldCloneDefinition = nullptr) {
516 auto Cloner = LinkingCloner();
517 LinkingCloner::DefMaps Defs = Cloner.buildDefMaps(Mods);
518
519 // Find the entry function and its module.
520 Function *EntryF = nullptr;
521 Module *EntryM = nullptr;
522 for (Module &M : Mods) {
523 if ((EntryF = M.getFunction(EntryName)) && !EntryF->isDeclaration()) {
524 EntryM = &M;
525 break;
526 }
527 }
528 if (!EntryF)
529 reportFatalError("Expected non-null entry function");
530
531 // Compute the transitive closure starting from the entry function.
532 SmallVector<Function *> ToVisit{EntryF};
533 SmallPtrSet<Function *, 32> VisitSet{EntryF};
534 SmallPtrSet<GlobalValue *, 32> Reachable;
535 while (!ToVisit.empty()) {
536 auto *F = ToVisit.pop_back_val();
537 // Due to lazy parsing, make sure the function is materialized before
538 // traversing it.
539 if (auto E = F->materialize())
540 reportFatalError("Failed to materialize: " + toString(std::move(E)));
541
542 auto ThisReachable = Cloner.findTransitiveClosure(F, Defs);
543 for (auto *GV : ThisReachable) {
544 Reachable.insert(GV);
545 if (auto *ThisF = dyn_cast<Function>(GV)) {
546 if (!VisitSet.contains(ThisF)) {
547 VisitSet.insert(ThisF);
548 ToVisit.push_back(ThisF);
549 }
550 }
551 }
552 }
553
554 // Clone closure in new module.
555 auto KernelModule = Cloner.cloneClosure(*EntryM, EntryF->getContext(),
556 Reachable, ShouldCloneDefinition);
557
558 return KernelModule;
559}
560
561} // namespace proteus
562
563#endif
static Config & get()
Definition Config.h:334
static void logfile(const std::string &Filename, T &&Data)
Definition Logger.h:33
Definition CompiledLibrary.h:7
Definition MemoryCache.h:26
std::unique_ptr< Module > cloneKernelFromModules(ArrayRef< std::reference_wrapper< Module > > Mods, StringRef EntryName, function_ref< bool(const GlobalValue *)> ShouldCloneDefinition=nullptr)
Definition Cloning.h:513
std::unique_ptr< Module > cloneKernelFromModule(Module &M, StringRef Name, CallGraph &CG)
Definition Cloning.h:19
void reportFatalError(const llvm::Twine &Reason, const char *FILE, unsigned Line)
Definition Error.cpp:14
std::string toString(CodegenOption Option)
Definition Config.h:28
Definition Cloning.h:186
StringMap< Function * > FuncDefs
Definition Cloning.h:187
StringMap< GlobalVariable * > GlobDefs
Definition Cloning.h:188
Definition Cloning.h:192
AttributeList Attributes
Definition Cloning.h:196
FunctionType * FuncTy
Definition Cloning.h:193
SmallPtrSet< GlobalValue *, 32 > GVs
Definition Cloning.h:197
GlobalValue::LinkageTypes Linkage
Definition Cloning.h:194
unsigned int AddrSpace
Definition Cloning.h:195
Definition Cloning.h:200
bool IsConstant
Definition Cloning.h:202
Type * ValueType
Definition Cloning.h:201
Constant * Initializer
Definition Cloning.h:204
GlobalValue::LinkageTypes Linkage
Definition Cloning.h:203
SmallPtrSet< GlobalValue *, 32 > GVs
Definition Cloning.h:208
AttributeSet Attributes
Definition Cloning.h:207
GlobalValue::ThreadLocalMode TLM
Definition Cloning.h:205
unsigned int AddrSpace
Definition Cloning.h:206
Definition Cloning.h:184
StringMap< FuncDeclInfo > FuncDecls
Definition Cloning.h:214
std::unique_ptr< Module > cloneClosure(Module &M, LLVMContext &Ctx, SmallPtrSetImpl< GlobalValue * > const &Reachable, function_ref< bool(const GlobalValue *)> ShouldCloneDefinition=nullptr)
Definition Cloning.h:358
void scanConstant(Constant *C, const DefMaps &Defs, SmallVector< GlobalValue * > &WorkList, SmallPtrSetImpl< GlobalValue * > &Found)
Definition Cloning.h:285
SmallPtrSet< GlobalValue *, 32 > findTransitiveClosure(Function *Entry, const DefMaps &Defs)
Definition Cloning.h:305
DefMaps buildDefMaps(ArrayRef< std::reference_wrapper< Module > > Mods)
Definition Cloning.h:217
StringMap< GlobDeclInfo > GlobDecls
Definition Cloning.h:215
void resolveGV(const DefMaps &Defs, GlobalValue *G, SmallVector< GlobalValue * > &WorkList, SmallPtrSetImpl< GlobalValue * > &Found)
Definition Cloning.h:232
DenseMap< GlobalValue *, SmallVector< GlobalValue * > > ResolvedMap
Definition Cloning.h:212