diff --git a/llvm/include/llvm/IR/ValueMap.h b/llvm/include/llvm/IR/ValueMap.h index d12d639aaa888..fd4c08492e012 100644 --- a/llvm/include/llvm/IR/ValueMap.h +++ b/llvm/include/llvm/IR/ValueMap.h @@ -79,6 +79,9 @@ struct ValueMapConfig { static mutex_type *getMutex(const ExtraDataT &/*Data*/) { return nullptr; } }; +/// This type stores Metadata. Used in ValueMap. +using MDMapT = DenseMap; + /// See the file comment. template> class ValueMap { @@ -86,7 +89,6 @@ class ValueMap { using ValueMapCVH = ValueMapCallbackVH; using MapT = DenseMap>; - using MDMapT = DenseMap; using ExtraData = typename Config::ExtraData; MapT Map; diff --git a/llvm/include/llvm/Linker/IRMover.h b/llvm/include/llvm/Linker/IRMover.h index 1e3c5394ffa2a..89e9cbe0be18e 100644 --- a/llvm/include/llvm/Linker/IRMover.h +++ b/llvm/include/llvm/Linker/IRMover.h @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/IR/ValueMap.h" #include namespace llvm { @@ -41,9 +42,6 @@ class IRMover { static bool isEqual(const StructType *LHS, const StructType *RHS); }; - /// Type of the Metadata map in \a ValueToValueMapTy. - typedef DenseMap MDMapT; - public: class IdentifiedStructTypeSet { // The set of opaque types is the composite module. diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h index 3c8f2cbfaa9b8..47b75853ce948 100644 --- a/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -182,6 +182,27 @@ 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); + +/// Clone OldFunc's body into NewFunc. +void CloneFunctionBodyInto(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap, RemapFlags RemapFlag, + SmallVectorImpl &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, @@ -202,7 +223,7 @@ void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, /// void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, - SmallVectorImpl &Returns, + SmallVectorImpl &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = nullptr); @@ -220,6 +241,13 @@ 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(MDMapT &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 { @@ -341,32 +369,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 BBs, SmallVectorImpl &NoAliasDeclScopes); +void identifyNoAliasScopesToClone(ArrayRef BBs, + SmallVectorImpl &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 &NoAliasDeclScopes); +void identifyNoAliasScopesToClone(BasicBlock::iterator Start, + BasicBlock::iterator End, + SmallVectorImpl &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 NoAliasDeclScopes, - DenseMap &ClonedScopes, - StringRef Ext, LLVMContext &Context); +void cloneNoAliasScopes(ArrayRef NoAliasDeclScopes, + DenseMap &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 &ClonedScopes, - LLVMContext &Context); +void adaptNoAliasScopes(llvm::Instruction *I, + const DenseMap &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/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index a0c3f2c5b0baf..76af83df00cba 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -373,9 +373,6 @@ class LocalValueMaterializer final : public ValueMaterializer { Value *materialize(Value *V) override; }; -/// Type of the Metadata map in \a ValueToValueMapTy. -typedef DenseMap MDMapT; - /// This is responsible for keeping track of the state used for moving data /// from SrcM to DstM. class IRLinker { diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index b55776d736e66..5bc90bc7ae23d 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -152,6 +152,119 @@ DISubprogram *llvm::CollectDebugInfoForCloning(const Function &F, return SPClonedWithinModule; } +bool llvm::BuildDebugInfoMDMap(MDMapT &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. + for (DISubprogram *ISP : DIFinder.subprograms()) { + if (ISP != SPClonedWithinModule) + mapToSelfIfNew(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(S); + if (LScope && LScope->getSubprogram() != SPClonedWithinModule) + 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; +} + +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, 1> MDs; + OldFunc->getAllMetadata(MDs); + for (auto MD : MDs) { + NewFunc->addMetadata(MD.first, *MapMetadata(MD.second, VMap, RemapFlag, + TypeMapper, Materializer)); + } +} + +void llvm::CloneFunctionBodyInto(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap, RemapFlags RemapFlag, + SmallVectorImpl &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(OldFunc), + const_cast(&BB)); + VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB); + } + + // Note return instructions for the caller. + if (ReturnInst *RI = dyn_cast(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(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, @@ -210,98 +323,16 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, DISubprogram *SPClonedWithinModule = CollectDebugInfoForCloning(*OldFunc, Changes, DIFinder); - // 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(OldFunc), - const_cast(&BB)); - VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB); - } - - // Note return instructions for the caller. - if (ReturnInst *RI = dyn_cast(CBB->getTerminator())) - Returns.push_back(RI); - } - - 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 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(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. - // Subprograms/CUs/types that were already mapped to themselves won't be - // duplicated. - SmallVector, 1> MDs; - OldFunc->getAllMetadata(MDs); - for (auto MD : MDs) { - NewFunc->addMetadata(MD.first, *MapMetadata(MD.second, VMap, RemapFlag, - TypeMapper, Materializer)); - } - // 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(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); - } + CloneFunctionMetadataInto(NewFunc, OldFunc, 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