diff options
| author | Teresa Johnson <tejohnson@google.com> | 2015-12-17 17:14:09 +0000 |
|---|---|---|
| committer | Teresa Johnson <tejohnson@google.com> | 2015-12-17 17:14:09 +0000 |
| commit | e5a619173274bf2a9033ea1c8b2346f1bee2766b (patch) | |
| tree | df1a23654ddaef760e878af89977d13945649896 /llvm/lib/Transforms | |
| parent | caaa3aa07c8fa129c8032597f2d0317637a1569a (diff) | |
| download | bcm5719-llvm-e5a619173274bf2a9033ea1c8b2346f1bee2766b.tar.gz bcm5719-llvm-e5a619173274bf2a9033ea1c8b2346f1bee2766b.zip | |
[ThinLTO] Metadata linking for imported functions
Summary:
Second patch split out from http://reviews.llvm.org/D14752.
Maps metadata as a post-pass from each module when importing complete,
suturing up final metadata to the temporary metadata left on the
imported instructions.
This entails saving the mapping from bitcode value id to temporary
metadata in the importing pass, and from bitcode value id to final
metadata during the metadata linking postpass.
Depends on D14825.
Reviewers: dexonsmith, joker.eph
Subscribers: davidxl, llvm-commits, joker.eph
Differential Revision: http://reviews.llvm.org/D14838
llvm-svn: 255909
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/IPO/FunctionImport.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Utils/ValueMapper.cpp | 74 |
2 files changed, 77 insertions, 21 deletions
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index b8c2ea7dce2..639f15a03f5 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -292,6 +292,9 @@ bool FunctionImporter::importFunctions(Module &DestModule) { ModuleToFunctionsToImportMap, Index, ModuleLoaderCache); assert(Worklist.empty() && "Worklist hasn't been flushed in GetImportList"); + StringMap<std::unique_ptr<DenseMap<unsigned, MDNode *>>> + ModuleToTempMDValsMap; + // Do the actual import of functions now, one Module at a time for (auto &FunctionsToImportPerModule : ModuleToFunctionsToImportMap) { // Get the module for the import @@ -301,13 +304,32 @@ bool FunctionImporter::importFunctions(Module &DestModule) { assert(&DestModule.getContext() == &SrcModule->getContext() && "Context mismatch"); + // Save the mapping of value ids to temporary metadata created when + // importing this function. If we have already imported from this module, + // add new temporary metadata to the existing mapping. + auto &TempMDVals = ModuleToTempMDValsMap[SrcModule->getModuleIdentifier()]; + if (!TempMDVals) + TempMDVals = llvm::make_unique<DenseMap<unsigned, MDNode *>>(); + // Link in the specified functions. if (TheLinker.linkInModule(std::move(SrcModule), Linker::Flags::None, - &Index, &FunctionsToImport)) + &Index, &FunctionsToImport, TempMDVals.get())) report_fatal_error("Function Import: link error"); ImportedCount += FunctionsToImport.size(); } + + // Now link in metadata for all modules from which we imported functions. + for (StringMapEntry<std::unique_ptr<DenseMap<unsigned, MDNode *>>> &SME : + ModuleToTempMDValsMap) { + // Load the specified source module. + auto &SrcModule = ModuleLoaderCache(SME.getKey()); + + // Link in all necessary metadata from this module. + if (TheLinker.linkInMetadata(SrcModule, SME.getValue().get())) + return false; + } + DEBUG(dbgs() << "Imported " << ImportedCount << " functions for Module " << DestModule.getModuleIdentifier() << "\n"); return ImportedCount; diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp index 00a8984845d..00ee3385981 100644 --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -167,13 +167,21 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, } static Metadata *mapToMetadata(ValueToValueMapTy &VM, const Metadata *Key, - Metadata *Val) { + Metadata *Val, ValueMaterializer *Materializer, + RemapFlags Flags) { VM.MD()[Key].reset(Val); + if (Materializer && !(Flags & RF_HaveUnmaterializedMetadata)) { + auto *N = dyn_cast_or_null<MDNode>(Val); + // Need to invoke this once we have non-temporary MD. + if (!N || !N->isTemporary()) + Materializer->replaceTemporaryMetadata(Key, Val); + } return Val; } -static Metadata *mapToSelf(ValueToValueMapTy &VM, const Metadata *MD) { - return mapToMetadata(VM, MD, const_cast<Metadata *>(MD)); +static Metadata *mapToSelf(ValueToValueMapTy &VM, const Metadata *MD, + ValueMaterializer *Materializer, RemapFlags Flags) { + return mapToMetadata(VM, MD, const_cast<Metadata *>(MD), Materializer, Flags); } static Metadata *MapMetadataImpl(const Metadata *MD, @@ -206,10 +214,13 @@ static Metadata *mapMetadataOp(Metadata *Op, } /// Resolve uniquing cycles involving the given metadata. -static void resolveCycles(Metadata *MD) { - if (auto *N = dyn_cast_or_null<MDNode>(MD)) +static void resolveCycles(Metadata *MD, bool MDMaterialized) { + if (auto *N = dyn_cast_or_null<MDNode>(MD)) { + if (!MDMaterialized && N->isTemporary()) + return; if (!N->isResolved()) - N->resolveCycles(); + N->resolveCycles(MDMaterialized); + } } /// Remap the operands of an MDNode. @@ -238,7 +249,7 @@ static bool remapOperands(MDNode &Node, // Resolve uniquing cycles underneath distinct nodes on the fly so they // don't infect later operands. if (IsDistinct) - resolveCycles(New); + resolveCycles(New, !(Flags & RF_HaveUnmaterializedMetadata)); } } @@ -266,7 +277,7 @@ static Metadata *mapDistinctNode(const MDNode *Node, // Remap operands later. DistinctWorklist.push_back(NewMD); - return mapToMetadata(VM, Node, NewMD); + return mapToMetadata(VM, Node, NewMD, Materializer, Flags); } /// \brief Map a uniqued MDNode. @@ -277,22 +288,29 @@ static Metadata *mapUniquedNode(const MDNode *Node, ValueToValueMapTy &VM, RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer) { - assert(Node->isUniqued() && "Expected uniqued node"); + assert(((Flags & RF_HaveUnmaterializedMetadata) || Node->isUniqued()) && + "Expected uniqued node"); // Create a temporary node and map it upfront in case we have a uniquing // cycle. If necessary, this mapping will get updated by RAUW logic before // returning. auto ClonedMD = Node->clone(); - mapToMetadata(VM, Node, ClonedMD.get()); + mapToMetadata(VM, Node, ClonedMD.get(), Materializer, Flags); if (!remapOperands(*ClonedMD, DistinctWorklist, VM, Flags, TypeMapper, Materializer)) { // No operands changed, so use the original. ClonedMD->replaceAllUsesWith(const_cast<MDNode *>(Node)); - return const_cast<MDNode *>(Node); + // Even though replaceAllUsesWith would have replaced the value map + // entry, we need to explictly map with the final non-temporary node + // to replace any temporary metadata via the callback. + return mapToSelf(VM, Node, Materializer, Flags); } - // Uniquify the cloned node. - return MDNode::replaceWithUniqued(std::move(ClonedMD)); + // Uniquify the cloned node. Explicitly map it with the final non-temporary + // node so that replacement of temporary metadata via the callback occurs. + return mapToMetadata(VM, Node, + MDNode::replaceWithUniqued(std::move(ClonedMD)), + Materializer, Flags); } static Metadata *MapMetadataImpl(const Metadata *MD, @@ -305,18 +323,18 @@ static Metadata *MapMetadataImpl(const Metadata *MD, return NewMD; if (isa<MDString>(MD)) - return mapToSelf(VM, MD); + return mapToSelf(VM, MD, Materializer, Flags); if (isa<ConstantAsMetadata>(MD)) if ((Flags & RF_NoModuleLevelChanges)) - return mapToSelf(VM, MD); + return mapToSelf(VM, MD, Materializer, Flags); if (const auto *VMD = dyn_cast<ValueAsMetadata>(MD)) { Value *MappedV = MapValue(VMD->getValue(), VM, Flags, TypeMapper, Materializer); if (VMD->getValue() == MappedV || (!MappedV && (Flags & RF_IgnoreMissingEntries))) - return mapToSelf(VM, MD); + return mapToSelf(VM, MD, Materializer, Flags); // FIXME: This assert crashes during bootstrap, but I think it should be // correct. For now, just match behaviour from before the metadata/value @@ -325,7 +343,8 @@ static Metadata *MapMetadataImpl(const Metadata *MD, // assert((MappedV || (Flags & RF_NullMapMissingGlobalValues)) && // "Referenced metadata not in value map!"); if (MappedV) - return mapToMetadata(VM, MD, ValueAsMetadata::get(MappedV)); + return mapToMetadata(VM, MD, ValueAsMetadata::get(MappedV), Materializer, + Flags); return nullptr; } @@ -336,10 +355,25 @@ static Metadata *MapMetadataImpl(const Metadata *MD, // If this is a module-level metadata and we know that nothing at the // module level is changing, then use an identity mapping. if (Flags & RF_NoModuleLevelChanges) - return mapToSelf(VM, MD); + return mapToSelf(VM, MD, Materializer, Flags); // Require resolved nodes whenever metadata might be remapped. - assert(Node->isResolved() && "Unexpected unresolved node"); + assert(((Flags & RF_HaveUnmaterializedMetadata) || Node->isResolved()) && + "Unexpected unresolved node"); + + if (Materializer && Node->isTemporary()) { + assert(Flags & RF_HaveUnmaterializedMetadata); + Metadata *TempMD = + Materializer->mapTemporaryMetadata(const_cast<Metadata *>(MD)); + // If the above callback returned an existing temporary node, use it + // instead of the current temporary node. This happens when earlier + // function importing passes already created and saved a temporary + // metadata node for the same value id. + if (TempMD) { + mapToMetadata(VM, MD, TempMD, Materializer, Flags); + return TempMD; + } + } if (Node->isDistinct()) return mapDistinctNode(Node, DistinctWorklist, VM, Flags, TypeMapper, @@ -363,7 +397,7 @@ Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM, return NewMD; // Resolve cycles involving the entry metadata. - resolveCycles(NewMD); + resolveCycles(NewMD, !(Flags & RF_HaveUnmaterializedMetadata)); // Remap the operands of distinct MDNodes. while (!DistinctWorklist.empty()) |

