[llvm] [NFC][Utils] Eliminate DISubprogram set from BuildDebugInfoMDMap (PR #118625)
Artem Pianykh via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 9 08:57:33 PST 2024
https://github.com/artempyanykh updated https://github.com/llvm/llvm-project/pull/118625
>From b2ef3f3d57a5e12e266f897c172966dff6fdbb4c Mon Sep 17 00:00:00 2001
From: Artem Pianykh <arr at fb.com>
Date: Thu, 12 Sep 2024 15:23:43 -0700
Subject: [PATCH 1/4] [NFC][Utils] Extract BuildDebugInfoMDMap from
CloneFunctionInto
Summary:
Extract the logic to build up a metadata map to use in metadata cloning
into a separate function.
Test Plan:
ninja check-llvm-unit check-llvm
stack-info: PR: https://github.com/llvm/llvm-project/pull/118622, branch: users/artempyanykh/fast-coro-upstream/3
---
llvm/include/llvm/Transforms/Utils/Cloning.h | 8 ++
llvm/lib/Transforms/Utils/CloneFunction.cpp | 89 +++++++++++---------
2 files changed, 58 insertions(+), 39 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h
index 3c8f2cbfaa9b81..7858c9d9def0da 100644
--- a/llvm/include/llvm/Transforms/Utils/Cloning.h
+++ b/llvm/include/llvm/Transforms/Utils/Cloning.h
@@ -220,6 +220,14 @@ DISubprogram *CollectDebugInfoForCloning(const Function &F,
CloneFunctionChangeType Changes,
DebugInfoFinder &DIFinder);
+/// Build a map of debug info to use during Metadata cloning.
+/// Returns true if cloning would need module level changes and false if there
+/// would only be local changes.
+bool BuildDebugInfoMDMap(DenseMap<const Metadata *, TrackingMDRef> &MD,
+ CloneFunctionChangeType Changes,
+ DebugInfoFinder &DIFinder,
+ DISubprogram *SPClonedWithinModule);
+
/// This class captures the data input to the InlineFunction call, and records
/// the auxiliary results produced by it.
class InlineFunctionInfo {
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index d038117090e4cc..6dc5f601b7fcaa 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -152,6 +152,54 @@ DISubprogram *llvm::CollectDebugInfoForCloning(const Function &F,
return SPClonedWithinModule;
}
+bool llvm::BuildDebugInfoMDMap(DenseMap<const Metadata *, TrackingMDRef> &MD,
+ CloneFunctionChangeType Changes,
+ DebugInfoFinder &DIFinder,
+ DISubprogram *SPClonedWithinModule) {
+ bool ModuleLevelChanges = Changes > CloneFunctionChangeType::LocalChangesOnly;
+ if (Changes < CloneFunctionChangeType::DifferentModule &&
+ DIFinder.subprogram_count() > 0) {
+ // Turn on module-level changes, since we need to clone (some of) the
+ // debug info metadata.
+ //
+ // FIXME: Metadata effectively owned by a function should be made
+ // local, and only that local metadata should be cloned.
+ ModuleLevelChanges = true;
+
+ auto mapToSelfIfNew = [&MD](MDNode *N) {
+ // Avoid clobbering an existing mapping.
+ (void)MD.try_emplace(N, N);
+ };
+
+ // Avoid cloning types, compile units, and (other) subprograms.
+ SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
+ for (DISubprogram *ISP : DIFinder.subprograms()) {
+ if (ISP != SPClonedWithinModule) {
+ mapToSelfIfNew(ISP);
+ MappedToSelfSPs.insert(ISP);
+ }
+ }
+
+ // 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);
+ if (LScope && MappedToSelfSPs.count(LScope->getSubprogram()))
+ mapToSelfIfNew(S);
+ }
+
+ for (DICompileUnit *CU : DIFinder.compile_units())
+ mapToSelfIfNew(CU);
+
+ for (DIType *Type : DIFinder.types())
+ mapToSelfIfNew(Type);
+ } else {
+ assert(!SPClonedWithinModule &&
+ "Subprogram should be in DIFinder->subprogram_count()...");
+ }
+
+ return ModuleLevelChanges;
+}
+
// Clone OldFunc into NewFunc, transforming the old arguments into references to
// VMap values.
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
@@ -210,45 +258,8 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
DISubprogram *SPClonedWithinModule =
CollectDebugInfoForCloning(*OldFunc, Changes, DIFinder);
- if (Changes < CloneFunctionChangeType::DifferentModule &&
- DIFinder.subprogram_count() > 0) {
- // Turn on module-level changes, since we need to clone (some of) the
- // debug info metadata.
- //
- // FIXME: Metadata effectively owned by a function should be made
- // local, and only that local metadata should be cloned.
- ModuleLevelChanges = true;
-
- auto mapToSelfIfNew = [&VMap](MDNode *N) {
- // Avoid clobbering an existing mapping.
- (void)VMap.MD().try_emplace(N, N);
- };
-
- // Avoid cloning types, compile units, and (other) subprograms.
- SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
- for (DISubprogram *ISP : DIFinder.subprograms()) {
- if (ISP != SPClonedWithinModule) {
- mapToSelfIfNew(ISP);
- MappedToSelfSPs.insert(ISP);
- }
- }
-
- // 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);
- if (LScope && MappedToSelfSPs.count(LScope->getSubprogram()))
- mapToSelfIfNew(S);
- }
-
- for (DICompileUnit *CU : DIFinder.compile_units())
- mapToSelfIfNew(CU);
-
- for (DIType *Type : DIFinder.types())
- mapToSelfIfNew(Type);
- } else {
- assert(!SPClonedWithinModule &&
- "Subprogram should be in DIFinder->subprogram_count()...");
- }
+ ModuleLevelChanges =
+ BuildDebugInfoMDMap(VMap.MD(), Changes, DIFinder, SPClonedWithinModule);
const auto RemapFlag = ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges;
// Duplicate the metadata that is attached to the cloned function.
>From 9dcfc56cf669e9b8b571469ba5ba850b7565faa7 Mon Sep 17 00:00:00 2001
From: Artem Pianykh <arr at fb.com>
Date: Thu, 12 Sep 2024 15:35:38 -0700
Subject: [PATCH 2/4] [NFC][Utils] Extract CloneFunctionMetadataInto from
CloneFunctionInto
Summary:
The new API expects the caller to populate the VMap. We need it this way
for a subsequent change around coroutine cloning.
Test Plan:
ninja check-llvm-unit check-llvm
stack-info: PR: https://github.com/llvm/llvm-project/pull/118623, branch: users/artempyanykh/fast-coro-upstream/4
---
llvm/include/llvm/Transforms/Utils/Cloning.h | 12 +++++++++
llvm/lib/Transforms/Utils/CloneFunction.cpp | 28 +++++++++++++-------
2 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h
index 7858c9d9def0da..9a574fc4e4c08e 100644
--- a/llvm/include/llvm/Transforms/Utils/Cloning.h
+++ b/llvm/include/llvm/Transforms/Utils/Cloning.h
@@ -182,6 +182,18 @@ void CloneFunctionAttributesInto(Function *NewFunc, const Function *OldFunc,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+/// Clone OldFunc's metadata into NewFunc.
+///
+/// The caller is expected to populate \p VMap beforehand and set an appropriate
+/// \p RemapFlag.
+///
+/// NOTE: This function doesn't clone !llvm.dbg.cu when cloning into a different
+/// module. Use CloneFunctionInto for that behavior.
+void CloneFunctionMetadataInto(Function *NewFunc, const Function *OldFunc,
+ ValueToValueMapTy &VMap, RemapFlags RemapFlag,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
const Instruction *StartingInst,
ValueToValueMapTy &VMap, bool ModuleLevelChanges,
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 6dc5f601b7fcaa..c967e78123af1f 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -200,6 +200,22 @@ bool llvm::BuildDebugInfoMDMap(DenseMap<const Metadata *, TrackingMDRef> &MD,
return ModuleLevelChanges;
}
+void llvm::CloneFunctionMetadataInto(Function *NewFunc, const Function *OldFunc,
+ ValueToValueMapTy &VMap,
+ RemapFlags RemapFlag,
+ ValueMapTypeRemapper *TypeMapper,
+ ValueMaterializer *Materializer) {
+ // Duplicate the metadata that is attached to the cloned function.
+ // Subprograms/CUs/types that were already mapped to themselves won't be
+ // duplicated.
+ SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
+ OldFunc->getAllMetadata(MDs);
+ for (auto MD : MDs) {
+ NewFunc->addMetadata(MD.first, *MapMetadata(MD.second, VMap, RemapFlag,
+ TypeMapper, Materializer));
+ }
+}
+
// Clone OldFunc into NewFunc, transforming the old arguments into references to
// VMap values.
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
@@ -262,15 +278,9 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
BuildDebugInfoMDMap(VMap.MD(), Changes, DIFinder, SPClonedWithinModule);
const auto RemapFlag = ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges;
- // Duplicate the metadata that is attached to the cloned function.
- // Subprograms/CUs/types that were already mapped to themselves won't be
- // duplicated.
- SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
- OldFunc->getAllMetadata(MDs);
- for (auto MD : MDs) {
- NewFunc->addMetadata(MD.first, *MapMetadata(MD.second, VMap, RemapFlag,
- TypeMapper, Materializer));
- }
+
+ CloneFunctionMetadataInto(NewFunc, OldFunc, VMap, RemapFlag, TypeMapper,
+ Materializer);
// Loop over all of the basic blocks in the function, cloning them as
// appropriate. Note that we save BE this way in order to handle cloning of
>From 6845960eea8fe58cc5f6e05611ef2920c49a34b9 Mon Sep 17 00:00:00 2001
From: Artem Pianykh <arr at fb.com>
Date: Thu, 12 Sep 2024 15:50:25 -0700
Subject: [PATCH 3/4] [NFC][Utils] Extract CloneFunctionBodyInto from
CloneFunctionInto
Summary:
This and previously extracted `CloneFunction*Into` functions will be used in later diffs.
Test Plan:
ninja check-llvm-unit check-llvm
stack-info: PR: https://github.com/llvm/llvm-project/pull/118624, branch: users/artempyanykh/fast-coro-upstream/5
---
llvm/include/llvm/Transforms/Utils/Cloning.h | 34 ++++---
llvm/lib/Transforms/Utils/CloneFunction.cpp | 96 +++++++++++---------
2 files changed, 76 insertions(+), 54 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h
index 9a574fc4e4c08e..50518c746d11ca 100644
--- a/llvm/include/llvm/Transforms/Utils/Cloning.h
+++ b/llvm/include/llvm/Transforms/Utils/Cloning.h
@@ -194,6 +194,15 @@ void CloneFunctionMetadataInto(Function *NewFunc, const Function *OldFunc,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+/// Clone OldFunc's body into NewFunc.
+void CloneFunctionBodyInto(Function *NewFunc, const Function *OldFunc,
+ ValueToValueMapTy &VMap, RemapFlags RemapFlag,
+ SmallVectorImpl<ReturnInst *> &Returns,
+ const char *NameSuffix = "",
+ ClonedCodeInfo *CodeInfo = nullptr,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
const Instruction *StartingInst,
ValueToValueMapTy &VMap, bool ModuleLevelChanges,
@@ -214,7 +223,7 @@ void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
///
void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
ValueToValueMapTy &VMap, bool ModuleLevelChanges,
- SmallVectorImpl<ReturnInst*> &Returns,
+ SmallVectorImpl<ReturnInst *> &Returns,
const char *NameSuffix = "",
ClonedCodeInfo *CodeInfo = nullptr);
@@ -361,32 +370,31 @@ void updateProfileCallee(
/// Find the 'llvm.experimental.noalias.scope.decl' intrinsics in the specified
/// basic blocks and extract their scope. These are candidates for duplication
/// when cloning.
-void identifyNoAliasScopesToClone(
- ArrayRef<BasicBlock *> BBs, SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
+void identifyNoAliasScopesToClone(ArrayRef<BasicBlock *> BBs,
+ SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
/// Find the 'llvm.experimental.noalias.scope.decl' intrinsics in the specified
/// instruction range and extract their scope. These are candidates for
/// duplication when cloning.
-void identifyNoAliasScopesToClone(
- BasicBlock::iterator Start, BasicBlock::iterator End,
- SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
+void identifyNoAliasScopesToClone(BasicBlock::iterator Start,
+ BasicBlock::iterator End,
+ SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
/// Duplicate the specified list of noalias decl scopes.
/// The 'Ext' string is added as an extension to the name.
/// Afterwards, the ClonedScopes contains the mapping of the original scope
/// MDNode onto the cloned scope.
/// Be aware that the cloned scopes are still part of the original scope domain.
-void cloneNoAliasScopes(
- ArrayRef<MDNode *> NoAliasDeclScopes,
- DenseMap<MDNode *, MDNode *> &ClonedScopes,
- StringRef Ext, LLVMContext &Context);
+void cloneNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
+ DenseMap<MDNode *, MDNode *> &ClonedScopes,
+ StringRef Ext, LLVMContext &Context);
/// Adapt the metadata for the specified instruction according to the
/// provided mapping. This is normally used after cloning an instruction, when
/// some noalias scopes needed to be cloned.
-void adaptNoAliasScopes(
- llvm::Instruction *I, const DenseMap<MDNode *, MDNode *> &ClonedScopes,
- LLVMContext &Context);
+void adaptNoAliasScopes(llvm::Instruction *I,
+ const DenseMap<MDNode *, MDNode *> &ClonedScopes,
+ LLVMContext &Context);
/// Clone the specified noalias decl scopes. Then adapt all instructions in the
/// NewBlocks basicblocks to the cloned versions.
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index c967e78123af1f..cf4b1c7a045e05 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -216,6 +216,59 @@ void llvm::CloneFunctionMetadataInto(Function *NewFunc, const Function *OldFunc,
}
}
+void llvm::CloneFunctionBodyInto(Function *NewFunc, const Function *OldFunc,
+ ValueToValueMapTy &VMap, RemapFlags RemapFlag,
+ SmallVectorImpl<ReturnInst *> &Returns,
+ const char *NameSuffix,
+ ClonedCodeInfo *CodeInfo,
+ ValueMapTypeRemapper *TypeMapper,
+ ValueMaterializer *Materializer) {
+ if (OldFunc->isDeclaration())
+ return;
+
+ // Loop over all of the basic blocks in the function, cloning them as
+ // appropriate. Note that we save BE this way in order to handle cloning of
+ // recursive functions into themselves.
+ for (const BasicBlock &BB : *OldFunc) {
+
+ // Create a new basic block and copy instructions into it!
+ BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo);
+
+ // Add basic block mapping.
+ VMap[&BB] = CBB;
+
+ // It is only legal to clone a function if a block address within that
+ // function is never referenced outside of the function. Given that, we
+ // want to map block addresses from the old function to block addresses in
+ // the clone. (This is different from the generic ValueMapper
+ // implementation, which generates an invalid blockaddress when
+ // cloning a function.)
+ if (BB.hasAddressTaken()) {
+ Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(OldFunc),
+ const_cast<BasicBlock *>(&BB));
+ VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB);
+ }
+
+ // Note return instructions for the caller.
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator()))
+ Returns.push_back(RI);
+ }
+
+ // Loop over all of the instructions in the new function, fixing up operand
+ // references as we go. This uses VMap to do all the hard work.
+ for (Function::iterator
+ BB = cast<BasicBlock>(VMap[&OldFunc->front()])->getIterator(),
+ BE = NewFunc->end();
+ BB != BE; ++BB)
+ // Loop over all instructions, fixing each one as we find it, and any
+ // attached debug-info records.
+ for (Instruction &II : *BB) {
+ RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer);
+ RemapDbgRecordRange(II.getModule(), II.getDbgRecordRange(), VMap,
+ RemapFlag, TypeMapper, Materializer);
+ }
+}
+
// Clone OldFunc into NewFunc, transforming the old arguments into references to
// VMap values.
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
@@ -282,47 +335,8 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
CloneFunctionMetadataInto(NewFunc, OldFunc, VMap, RemapFlag, TypeMapper,
Materializer);
- // Loop over all of the basic blocks in the function, cloning them as
- // appropriate. Note that we save BE this way in order to handle cloning of
- // recursive functions into themselves.
- for (const BasicBlock &BB : *OldFunc) {
-
- // Create a new basic block and copy instructions into it!
- BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo);
-
- // Add basic block mapping.
- VMap[&BB] = CBB;
-
- // It is only legal to clone a function if a block address within that
- // function is never referenced outside of the function. Given that, we
- // want to map block addresses from the old function to block addresses in
- // the clone. (This is different from the generic ValueMapper
- // implementation, which generates an invalid blockaddress when
- // cloning a function.)
- if (BB.hasAddressTaken()) {
- Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(OldFunc),
- const_cast<BasicBlock *>(&BB));
- VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB);
- }
-
- // Note return instructions for the caller.
- if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator()))
- Returns.push_back(RI);
- }
-
- // Loop over all of the instructions in the new function, fixing up operand
- // references as we go. This uses VMap to do all the hard work.
- for (Function::iterator
- BB = cast<BasicBlock>(VMap[&OldFunc->front()])->getIterator(),
- BE = NewFunc->end();
- BB != BE; ++BB)
- // Loop over all instructions, fixing each one as we find it, and any
- // attached debug-info records.
- for (Instruction &II : *BB) {
- RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer);
- RemapDbgRecordRange(II.getModule(), II.getDbgRecordRange(), VMap,
- RemapFlag, TypeMapper, Materializer);
- }
+ CloneFunctionBodyInto(NewFunc, OldFunc, VMap, RemapFlag, Returns, NameSuffix,
+ CodeInfo, TypeMapper, Materializer);
// Only update !llvm.dbg.cu for DifferentModule (not CloneModule). In the
// same module, the compile unit will already be listed (or not). When
>From a6885e92b192c398d51f3723baccf628d3bdcb26 Mon Sep 17 00:00:00 2001
From: Artem Pianykh <arr at fb.com>
Date: Sat, 14 Sep 2024 16:02:51 -0700
Subject: [PATCH 4/4] [NFC][Utils] Eliminate DISubprogram set from
BuildDebugInfoMDMap
Summary:
Previously, we'd add all SPs distinct from the cloned one into a set.
Then when cloning a local scope we'd check if it's from one of those
'distinct' SPs by checking if it's in the set. We don't need to do that.
We can just check against the cloned SP directly and drop the set.
Test Plan:
ninja check-llvm-unit check-llvm
stack-info: PR: https://github.com/llvm/llvm-project/pull/118625, branch: users/artempyanykh/fast-coro-upstream/6
---
llvm/lib/Transforms/Utils/CloneFunction.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index cf4b1c7a045e05..34400d45aa6e72 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -172,18 +172,15 @@ bool llvm::BuildDebugInfoMDMap(DenseMap<const Metadata *, TrackingMDRef> &MD,
};
// Avoid cloning types, compile units, and (other) subprograms.
- SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
for (DISubprogram *ISP : DIFinder.subprograms()) {
- if (ISP != SPClonedWithinModule) {
+ if (ISP != SPClonedWithinModule)
mapToSelfIfNew(ISP);
- MappedToSelfSPs.insert(ISP);
- }
}
// 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);
- if (LScope && MappedToSelfSPs.count(LScope->getSubprogram()))
+ if (LScope && LScope->getSubprogram() != SPClonedWithinModule)
mapToSelfIfNew(S);
}
More information about the llvm-commits
mailing list