diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 | 
| commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
| tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /lib/Transforms/Utils/ValueMapper.cpp | |
| parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) | |
Notes
Diffstat (limited to 'lib/Transforms/Utils/ValueMapper.cpp')
| -rw-r--r-- | lib/Transforms/Utils/ValueMapper.cpp | 292 | 
1 files changed, 242 insertions, 50 deletions
diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index 0f20e6df6c965..477fba42412e4 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/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);    }  | 
