aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/CloneFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/CloneFunction.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index c0f3333..2547ac0 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -232,12 +232,20 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
// Avoid cloning types, compile units, and (other) subprograms.
SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
for (DISubprogram *ISP : DIFinder->subprograms()) {
+ // Don't clone inlined subprograms.
if (ISP != SPClonedWithinModule) {
mapToSelfIfNew(ISP);
MappedToSelfSPs.insert(ISP);
}
}
+ // Avoid cloning local variables of subprograms that won't be cloned.
+ for (DILocalVariable *DV : DIFinder->local_variables())
+ if (auto *S = dyn_cast_or_null<DILocalScope>(DV->getScope()))
+ if (DISubprogram *SP = S->getSubprogram())
+ if (MappedToSelfSPs.contains(SP))
+ mapToSelfIfNew(DV);
+
// If a subprogram isn't going to be cloned skip its lexical blocks as well.
for (DIScope *S : DIFinder->scopes()) {
auto *LScope = dyn_cast<DILocalScope>(S);
@@ -249,7 +257,12 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
mapToSelfIfNew(CU);
for (DIType *Type : DIFinder->types())
- mapToSelfIfNew(Type);
+ // Don't skip subprogram's local types.
+ if (!isa_and_present<DILocalScope>(Type->getScope()) ||
+ SPClonedWithinModule == nullptr ||
+ dyn_cast<DILocalScope>(Type->getScope())->getSubprogram() !=
+ SPClonedWithinModule)
+ mapToSelfIfNew(Type);
} else {
assert(!SPClonedWithinModule &&
"Subprogram should be in DIFinder->subprogram_count()...");