aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/CloneFunction.cpp
diff options
context:
space:
mode:
authorArtem Pianykh <artem.pyanykh@gmail.com>2025-03-13 17:18:12 +0000
committerGitHub <noreply@github.com>2025-03-13 17:18:12 +0000
commitaa612f3ade66b5dd3e95d028c0345a94c38e1ff8 (patch)
treef7650d13ea21e742158387448bf872d07568ca28 /llvm/lib/Transforms/Utils/CloneFunction.cpp
parent09d8e442ac2884aabe4cdfb01d1444b54cff7147 (diff)
downloadllvm-aa612f3ade66b5dd3e95d028c0345a94c38e1ff8.zip
llvm-aa612f3ade66b5dd3e95d028c0345a94c38e1ff8.tar.gz
llvm-aa612f3ade66b5dd3e95d028c0345a94c38e1ff8.tar.bz2
[NFC][Cloning] Replace DIFinder usage in CloneFunctionInto with a MetadataPredicate (#129148)
Summary: The new code should be functionally identical to the old one (but faster). The reasoning is as follows. In the old code when cloning within the module: 1. DIFinder traverses and collects *all* debug info reachable from a function, its instructions, and its owning compile unit. 2. Then "compile units, types, other subprograms, and lexical blocks of other subprograms" are saved in a set. 3. Then when we MapMetadata, we traverse the function's debug info _again_ and those nodes that are in the set from p.2 are identity mapped. This looks equivalent to just doing step 3 with identity mapping based on a predicate that says to identity map "compile units, types, other subprograms, and lexical blocks of other subprograms" (same as in step 2). This is what the new code does. Test Plan: ninja check-all There's a bunch of tests around cloning and all of them pass.
Diffstat (limited to 'llvm/lib/Transforms/Utils/CloneFunction.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp32
1 files changed, 25 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 502c489..bdabe0e 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -50,6 +50,30 @@ void collectDebugInfoFromInstructions(const Function &F,
DIFinder.processInstruction(*M, I);
}
}
+
+// Create a predicate that matches the metadata that should be identity mapped
+// during function cloning.
+MetadataPredicate createIdentityMDPredicate(const Function &F,
+ CloneFunctionChangeType Changes) {
+ if (Changes >= CloneFunctionChangeType::DifferentModule)
+ return [](const Metadata *MD) { return false; };
+
+ DISubprogram *SPClonedWithinModule = F.getSubprogram();
+ return [=](const Metadata *MD) {
+ // Avoid cloning types, compile units, and (other) subprograms.
+ if (isa<DICompileUnit>(MD) || isa<DIType>(MD))
+ return true;
+
+ if (auto *SP = dyn_cast<DISubprogram>(MD))
+ return SP != SPClonedWithinModule;
+
+ // If a subprogram isn't going to be cloned skip its lexical blocks as well.
+ if (auto *LScope = dyn_cast<DILocalScope>(MD))
+ return LScope->getSubprogram() != SPClonedWithinModule;
+
+ return false;
+ };
+}
} // namespace
/// See comments in Cloning.h.
@@ -325,13 +349,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
}
}
- DISubprogram *SPClonedWithinModule =
- CollectDebugInfoForCloning(*OldFunc, Changes, DIFinder);
-
- MetadataPredicate IdentityMD =
- [MDSet =
- FindDebugInfoToIdentityMap(Changes, DIFinder, SPClonedWithinModule)](
- const Metadata *MD) { return MDSet.contains(MD); };
+ MetadataPredicate IdentityMD = createIdentityMDPredicate(*OldFunc, Changes);
// Cloning is always a Module level operation, since Metadata needs to be
// cloned.