diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp | 292 |
1 files changed, 242 insertions, 50 deletions
diff --git a/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp b/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp index 0f20e6d..477fba4 100644 --- a/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/contrib/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -40,7 +40,7 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, // Global values do not need to be seeded into the VM if they // are using the identity mapping. - if (isa<GlobalValue>(V) || isa<MDString>(V)) + if (isa<GlobalValue>(V)) return VM[V] = const_cast<Value*>(V); if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) { @@ -56,57 +56,24 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, return VM[V] = const_cast<Value*>(V); } - - if (const MDNode *MD = dyn_cast<MDNode>(V)) { + if (const auto *MDV = dyn_cast<MetadataAsValue>(V)) { + const Metadata *MD = MDV->getMetadata(); // If this is a module-level metadata and we know that nothing at the module // level is changing, then use an identity mapping. - if (!MD->isFunctionLocal() && (Flags & RF_NoModuleLevelChanges)) - return VM[V] = const_cast<Value*>(V); - - // Create a dummy node in case we have a metadata cycle. - MDNode *Dummy = MDNode::getTemporary(V->getContext(), None); - VM[V] = Dummy; - - // Check all operands to see if any need to be remapped. - for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) { - Value *OP = MD->getOperand(i); - if (!OP) continue; - Value *Mapped_OP = MapValue(OP, VM, Flags, TypeMapper, Materializer); - // Use identity map if Mapped_Op is null and we can ignore missing - // entries. - if (Mapped_OP == OP || - (Mapped_OP == nullptr && (Flags & RF_IgnoreMissingEntries))) - continue; - - // Ok, at least one operand needs remapping. - SmallVector<Value*, 4> Elts; - Elts.reserve(MD->getNumOperands()); - for (i = 0; i != e; ++i) { - Value *Op = MD->getOperand(i); - if (!Op) - Elts.push_back(nullptr); - else { - Value *Mapped_Op = MapValue(Op, VM, Flags, TypeMapper, Materializer); - // Use identity map if Mapped_Op is null and we can ignore missing - // entries. - if (Mapped_Op == nullptr && (Flags & RF_IgnoreMissingEntries)) - Mapped_Op = Op; - Elts.push_back(Mapped_Op); - } - } - MDNode *NewMD = MDNode::get(V->getContext(), Elts); - Dummy->replaceAllUsesWith(NewMD); - VM[V] = NewMD; - MDNode::deleteTemporary(Dummy); - return NewMD; - } + if (!isa<LocalAsMetadata>(MD) && (Flags & RF_NoModuleLevelChanges)) + return VM[V] = const_cast<Value *>(V); - VM[V] = const_cast<Value*>(V); - MDNode::deleteTemporary(Dummy); + auto *MappedMD = MapMetadata(MD, VM, Flags, TypeMapper, Materializer); + if (MD == MappedMD || (!MappedMD && (Flags & RF_IgnoreMissingEntries))) + return VM[V] = const_cast<Value *>(V); - // No operands needed remapping. Use an identity mapping. - return const_cast<Value*>(V); + // FIXME: This assert crashes during bootstrap, but I think it should be + // correct. For now, just match behaviour from before the metadata/value + // split. + // + // assert(MappedMD && "Referenced metadata value not in value map"); + return VM[V] = MetadataAsValue::get(V->getContext(), MappedMD); } // Okay, this either must be a constant (which may or may not be mappable) or @@ -177,6 +144,229 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy)); } +static Metadata *mapToMetadata(ValueToValueMapTy &VM, const Metadata *Key, + Metadata *Val) { + VM.MD()[Key].reset(Val); + return Val; +} + +static Metadata *mapToSelf(ValueToValueMapTy &VM, const Metadata *MD) { + return mapToMetadata(VM, MD, const_cast<Metadata *>(MD)); +} + +static Metadata *MapMetadataImpl(const Metadata *MD, ValueToValueMapTy &VM, + RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer); + +static Metadata *mapMetadataOp(Metadata *Op, ValueToValueMapTy &VM, + RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + if (!Op) + return nullptr; + if (Metadata *MappedOp = + MapMetadataImpl(Op, VM, Flags, TypeMapper, Materializer)) + return MappedOp; + // Use identity map if MappedOp is null and we can ignore missing entries. + if (Flags & RF_IgnoreMissingEntries) + return Op; + + // FIXME: This assert crashes during bootstrap, but I think it should be + // correct. For now, just match behaviour from before the metadata/value + // split. + // + // llvm_unreachable("Referenced metadata not in value map!"); + return nullptr; +} + +static Metadata *cloneMDTuple(const MDTuple *Node, ValueToValueMapTy &VM, + RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer, + bool IsDistinct) { + // Distinct MDTuples have their own code path. + assert(!IsDistinct && "Unexpected distinct tuple"); + (void)IsDistinct; + + SmallVector<Metadata *, 4> Elts; + Elts.reserve(Node->getNumOperands()); + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) + Elts.push_back(mapMetadataOp(Node->getOperand(I), VM, Flags, TypeMapper, + Materializer)); + + return MDTuple::get(Node->getContext(), Elts); +} + +static Metadata *cloneMDLocation(const MDLocation *Node, ValueToValueMapTy &VM, + RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer, + bool IsDistinct) { + return (IsDistinct ? MDLocation::getDistinct : MDLocation::get)( + Node->getContext(), Node->getLine(), Node->getColumn(), + mapMetadataOp(Node->getScope(), VM, Flags, TypeMapper, Materializer), + mapMetadataOp(Node->getInlinedAt(), VM, Flags, TypeMapper, Materializer)); +} + +static Metadata *cloneMDNode(const UniquableMDNode *Node, ValueToValueMapTy &VM, + RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer, bool IsDistinct) { + switch (Node->getMetadataID()) { + default: + llvm_unreachable("Invalid UniquableMDNode subclass"); +#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + case Metadata::CLASS##Kind: \ + return clone##CLASS(cast<CLASS>(Node), VM, Flags, TypeMapper, \ + Materializer, IsDistinct); +#include "llvm/IR/Metadata.def" + } +} + +/// \brief Map a distinct MDNode. +/// +/// Distinct nodes are not uniqued, so they must always recreated. +static Metadata *mapDistinctNode(const UniquableMDNode *Node, + ValueToValueMapTy &VM, RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + assert(Node->isDistinct() && "Expected distinct node"); + + // Optimization for MDTuples. + if (isa<MDTuple>(Node)) { + // Create the node first so it's available for cyclical references. + SmallVector<Metadata *, 4> EmptyOps(Node->getNumOperands()); + MDTuple *NewMD = MDTuple::getDistinct(Node->getContext(), EmptyOps); + mapToMetadata(VM, Node, NewMD); + + // Fix the operands. + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) + NewMD->replaceOperandWith(I, mapMetadataOp(Node->getOperand(I), VM, Flags, + TypeMapper, Materializer)); + + return NewMD; + } + + // In general we need a dummy node, since whether the operands are null can + // affect the size of the node. + std::unique_ptr<MDNodeFwdDecl> Dummy( + MDNode::getTemporary(Node->getContext(), None)); + mapToMetadata(VM, Node, Dummy.get()); + Metadata *NewMD = cloneMDNode(Node, VM, Flags, TypeMapper, Materializer, + /* IsDistinct */ true); + Dummy->replaceAllUsesWith(NewMD); + return mapToMetadata(VM, Node, NewMD); +} + +/// \brief Check whether a uniqued node needs to be remapped. +/// +/// Check whether a uniqued node needs to be remapped (due to any operands +/// changing). +static bool shouldRemapUniquedNode(const UniquableMDNode *Node, + ValueToValueMapTy &VM, RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + // Check all operands to see if any need to be remapped. + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) { + Metadata *Op = Node->getOperand(I); + if (Op != mapMetadataOp(Op, VM, Flags, TypeMapper, Materializer)) + return true; + } + return false; +} + +/// \brief Map a uniqued MDNode. +/// +/// Uniqued nodes may not need to be recreated (they may map to themselves). +static Metadata *mapUniquedNode(const UniquableMDNode *Node, + ValueToValueMapTy &VM, RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + assert(!Node->isDistinct() && "Expected uniqued node"); + + // Create a dummy node in case we have a metadata cycle. + MDNodeFwdDecl *Dummy = MDNode::getTemporary(Node->getContext(), None); + mapToMetadata(VM, Node, Dummy); + + // Check all operands to see if any need to be remapped. + if (!shouldRemapUniquedNode(Node, VM, Flags, TypeMapper, Materializer)) { + // Use an identity mapping. + mapToSelf(VM, Node); + MDNode::deleteTemporary(Dummy); + return const_cast<Metadata *>(static_cast<const Metadata *>(Node)); + } + + // At least one operand needs remapping. + Metadata *NewMD = cloneMDNode(Node, VM, Flags, TypeMapper, Materializer, + /* IsDistinct */ false); + Dummy->replaceAllUsesWith(NewMD); + MDNode::deleteTemporary(Dummy); + return mapToMetadata(VM, Node, NewMD); +} + +static Metadata *MapMetadataImpl(const Metadata *MD, ValueToValueMapTy &VM, + RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + // If the value already exists in the map, use it. + if (Metadata *NewMD = VM.MD().lookup(MD).get()) + return NewMD; + + if (isa<MDString>(MD)) + return mapToSelf(VM, MD); + + if (isa<ConstantAsMetadata>(MD)) + if ((Flags & RF_NoModuleLevelChanges)) + return mapToSelf(VM, MD); + + 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); + + // FIXME: This assert crashes during bootstrap, but I think it should be + // correct. For now, just match behaviour from before the metadata/value + // split. + // + // assert(MappedV && "Referenced metadata not in value map!"); + if (MappedV) + return mapToMetadata(VM, MD, ValueAsMetadata::get(MappedV)); + return nullptr; + } + + const UniquableMDNode *Node = cast<UniquableMDNode>(MD); + assert(Node->isResolved() && "Unexpected unresolved node"); + + // 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); + + if (Node->isDistinct()) + return mapDistinctNode(Node, VM, Flags, TypeMapper, Materializer); + + return mapUniquedNode(Node, VM, Flags, TypeMapper, Materializer); +} + +Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM, + RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + Metadata *NewMD = MapMetadataImpl(MD, VM, Flags, TypeMapper, Materializer); + if (NewMD && NewMD != MD) + if (auto *N = dyn_cast<UniquableMDNode>(NewMD)) + N->resolveCycles(); + return NewMD; +} + +MDNode *llvm::MapMetadata(const MDNode *MD, ValueToValueMapTy &VM, + RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + return cast<MDNode>(MapMetadata(static_cast<const Metadata *>(MD), VM, Flags, + TypeMapper, Materializer)); +} + /// RemapInstruction - Convert the instruction operands from referencing the /// current values into those specified by VMap. /// @@ -210,10 +400,12 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap, // Remap attached metadata. SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; I->getAllMetadata(MDs); - for (SmallVectorImpl<std::pair<unsigned, MDNode *> >::iterator - MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) { + for (SmallVectorImpl<std::pair<unsigned, MDNode *>>::iterator + MI = MDs.begin(), + ME = MDs.end(); + MI != ME; ++MI) { MDNode *Old = MI->second; - MDNode *New = MapValue(Old, VMap, Flags, TypeMapper, Materializer); + MDNode *New = MapMetadata(Old, VMap, Flags, TypeMapper, Materializer); if (New != Old) I->setMetadata(MI->first, New); } |