X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FUtils%2FValueMapper.cpp;h=528bf373fffaff65cdde49d20c70bf4916e28021;hb=f9eaea701dd2771fbd72145ed8eaaaeb62779b08;hp=df11cbbcb276b2fbd9e200e15c297ad1a5ea9e46;hpb=fd406f1ee2d94bafcb4943e4b21c2f4ea4bd8f3a;p=oota-llvm.git diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index df11cbbcb27..528bf373fff 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/lib/Transforms/Utils/ValueMapper.cpp @@ -13,144 +13,401 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/ValueMapper.h" -#include "llvm/Type.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Metadata.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" using namespace llvm; -Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM) { - Value *&VMSlot = VM[V]; - if (VMSlot) return VMSlot; // Does it exist in the map yet? +// Out of line method to get vtable etc for class. +void ValueMapTypeRemapper::anchor() {} +void ValueMaterializer::anchor() {} + +Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags, + ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + ValueToValueMapTy::iterator I = VM.find(V); + + // If the value already exists in the map, use it. + if (I != VM.end() && I->second) return I->second; - // NOTE: VMSlot can be invalidated by any reference to VM, which can grow the - // DenseMap. This includes any recursive calls to MapValue. + // If we have a materializer and it can materialize a value, use that. + if (Materializer) { + if (Value *NewV = Materializer->materializeValueFor(const_cast(V))) + return VM[V] = NewV; + } // Global values do not need to be seeded into the VM if they // are using the identity mapping. - if (isa(V) || isa(V) || isa(V)) - return VMSlot = const_cast(V); - - if (const MDNode *MD = dyn_cast(V)) { - // Start by assuming that we'll use the identity mapping. - VMSlot = const_cast(V); - - // 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 || MapValue(OP, VM) == OP) continue; - - // Ok, at least one operand needs remapping. - MDNode *Dummy = MDNode::getTemporary(V->getContext(), 0, 0); - VM[V] = Dummy; - SmallVector Elts; - Elts.reserve(MD->getNumOperands()); - for (i = 0; i != e; ++i) - Elts.push_back(MD->getOperand(i) ? - MapValue(MD->getOperand(i), VM) : 0); - MDNode *NewMD = MDNode::get(V->getContext(), Elts.data(), Elts.size()); - Dummy->replaceAllUsesWith(NewMD); - MDNode::deleteTemporary(Dummy); - return VM[V] = NewMD; + if (isa(V)) + return VM[V] = const_cast(V); + + if (const InlineAsm *IA = dyn_cast(V)) { + // Inline asm may need *type* remapping. + FunctionType *NewTy = IA->getFunctionType(); + if (TypeMapper) { + NewTy = cast(TypeMapper->remapType(NewTy)); + + if (NewTy != IA->getFunctionType()) + V = InlineAsm::get(NewTy, IA->getAsmString(), IA->getConstraintString(), + IA->hasSideEffects(), IA->isAlignStack()); } + + return VM[V] = const_cast(V); + } + + if (const auto *MDV = dyn_cast(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 (!isa(MD) && (Flags & RF_NoModuleLevelChanges)) + return VM[V] = const_cast(V); + + auto *MappedMD = MapMetadata(MD, VM, Flags, TypeMapper, Materializer); + if (MD == MappedMD || (!MappedMD && (Flags & RF_IgnoreMissingEntries))) + return VM[V] = const_cast(V); - // No operands needed remapping; keep the identity map. - return const_cast(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 + // is something that is not in the mapping table. Constant *C = const_cast(dyn_cast(V)); - if (C == 0) return 0; + if (!C) + return nullptr; - if (isa(C) || isa(C) || - isa(C) || isa(C) || - isa(C)) - return VMSlot = C; // Primitive constants map directly + if (BlockAddress *BA = dyn_cast(C)) { + Function *F = + cast(MapValue(BA->getFunction(), VM, Flags, TypeMapper, Materializer)); + BasicBlock *BB = cast_or_null(MapValue(BA->getBasicBlock(), VM, + Flags, TypeMapper, Materializer)); + return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); + } - if (ConstantArray *CA = dyn_cast(C)) { - for (User::op_iterator b = CA->op_begin(), i = b, e = CA->op_end(); - i != e; ++i) { - Value *MV = MapValue(*i, VM); - if (MV != *i) { - // This array must contain a reference to a global, make a new array - // and return it. - // - std::vector Values; - Values.reserve(CA->getNumOperands()); - for (User::op_iterator j = b; j != i; ++j) - Values.push_back(cast(*j)); - Values.push_back(cast(MV)); - for (++i; i != e; ++i) - Values.push_back(cast(MapValue(*i, VM))); - return VM[V] = ConstantArray::get(CA->getType(), Values); - } - } - return VM[V] = C; + // Otherwise, we have some other constant to remap. Start by checking to see + // if all operands have an identity remapping. + unsigned OpNo = 0, NumOperands = C->getNumOperands(); + Value *Mapped = nullptr; + for (; OpNo != NumOperands; ++OpNo) { + Value *Op = C->getOperand(OpNo); + Mapped = MapValue(Op, VM, Flags, TypeMapper, Materializer); + if (Mapped != C) break; } - if (ConstantStruct *CS = dyn_cast(C)) { - for (User::op_iterator b = CS->op_begin(), i = b, e = CS->op_end(); - i != e; ++i) { - Value *MV = MapValue(*i, VM); - if (MV != *i) { - // This struct must contain a reference to a global, make a new struct - // and return it. - // - std::vector Values; - Values.reserve(CS->getNumOperands()); - for (User::op_iterator j = b; j != i; ++j) - Values.push_back(cast(*j)); - Values.push_back(cast(MV)); - for (++i; i != e; ++i) - Values.push_back(cast(MapValue(*i, VM))); - return VM[V] = ConstantStruct::get(CS->getType(), Values); - } - } + // See if the type mapper wants to remap the type as well. + Type *NewTy = C->getType(); + if (TypeMapper) + NewTy = TypeMapper->remapType(NewTy); + + // If the result type and all operands match up, then just insert an identity + // mapping. + if (OpNo == NumOperands && NewTy == C->getType()) return VM[V] = C; - } - if (ConstantExpr *CE = dyn_cast(C)) { - std::vector Ops; - for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) - Ops.push_back(cast(MapValue(*i, VM))); - return VM[V] = CE->getWithOperands(Ops); - } + // Okay, we need to create a new constant. We've already processed some or + // all of the operands, set them all up now. + SmallVector Ops; + Ops.reserve(NumOperands); + for (unsigned j = 0; j != OpNo; ++j) + Ops.push_back(cast(C->getOperand(j))); - if (ConstantVector *CV = dyn_cast(C)) { - for (User::op_iterator b = CV->op_begin(), i = b, e = CV->op_end(); - i != e; ++i) { - Value *MV = MapValue(*i, VM); - if (MV != *i) { - // This vector value must contain a reference to a global, make a new - // vector constant and return it. - // - std::vector Values; - Values.reserve(CV->getNumOperands()); - for (User::op_iterator j = b; j != i; ++j) - Values.push_back(cast(*j)); - Values.push_back(cast(MV)); - for (++i; i != e; ++i) - Values.push_back(cast(MapValue(*i, VM))); - return VM[V] = ConstantVector::get(Values); - } - } - return VM[V] = C; + // If one of the operands mismatch, push it and the other mapped operands. + if (OpNo != NumOperands) { + Ops.push_back(cast(Mapped)); + + // Map the rest of the operands that aren't processed yet. + for (++OpNo; OpNo != NumOperands; ++OpNo) + Ops.push_back(MapValue(cast(C->getOperand(OpNo)), VM, + Flags, TypeMapper, Materializer)); } - BlockAddress *BA = cast(C); - Function *F = cast(MapValue(BA->getFunction(), VM)); - BasicBlock *BB = cast_or_null(MapValue(BA->getBasicBlock(),VM)); - return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock()); + if (ConstantExpr *CE = dyn_cast(C)) + return VM[V] = CE->getWithOperands(Ops, NewTy); + if (isa(C)) + return VM[V] = ConstantArray::get(cast(NewTy), Ops); + if (isa(C)) + return VM[V] = ConstantStruct::get(cast(NewTy), Ops); + if (isa(C)) + return VM[V] = ConstantVector::get(Ops); + // If this is a no-operand constant, it must be because the type was remapped. + if (isa(C)) + return VM[V] = UndefValue::get(NewTy); + if (isa(C)) + return VM[V] = ConstantAggregateZero::get(NewTy); + assert(isa(C)); + return VM[V] = ConstantPointerNull::get(cast(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(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 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(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(Node)) { + // Create the node first so it's available for cyclical references. + SmallVector 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. + auto Dummy = MDTuple::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->isUniqued() && "Expected uniqued node"); + + // Create a dummy node in case we have a metadata cycle. + auto Dummy = MDTuple::getTemporary(Node->getContext(), None); + mapToMetadata(VM, Node, Dummy.get()); + + // 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); + return const_cast(static_cast(Node)); + } + + // At least one operand needs remapping. + Metadata *NewMD = cloneMDNode(Node, VM, Flags, TypeMapper, Materializer, + /* IsDistinct */ false); + Dummy->replaceAllUsesWith(NewMD); + 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(MD)) + return mapToSelf(VM, MD); + + if (isa(MD)) + if ((Flags & RF_NoModuleLevelChanges)) + return mapToSelf(VM, MD); + + if (const auto *VMD = dyn_cast(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(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(NewMD)) + N->resolveCycles(); + return NewMD; +} + +MDNode *llvm::MapMetadata(const MDNode *MD, ValueToValueMapTy &VM, + RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer) { + return cast(MapMetadata(static_cast(MD), VM, Flags, + TypeMapper, Materializer)); } /// RemapInstruction - Convert the instruction operands from referencing the /// current values into those specified by VMap. /// -void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap) { +void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap, + RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, + ValueMaterializer *Materializer){ + // Remap operands. for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) { - Value *V = MapValue(*op, VMap); - assert(V && "Referenced value not in value map!"); - *op = V; + Value *V = MapValue(*op, VMap, Flags, TypeMapper, Materializer); + // If we aren't ignoring missing entries, assert that something happened. + if (V) + *op = V; + else + assert((Flags & RF_IgnoreMissingEntries) && + "Referenced value not in value map!"); } -} + // Remap phi nodes' incoming blocks. + if (PHINode *PN = dyn_cast(I)) { + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *V = MapValue(PN->getIncomingBlock(i), VMap, Flags); + // If we aren't ignoring missing entries, assert that something happened. + if (V) + PN->setIncomingBlock(i, cast(V)); + else + assert((Flags & RF_IgnoreMissingEntries) && + "Referenced block not in value map!"); + } + } + + // Remap attached metadata. + SmallVector, 4> MDs; + I->getAllMetadata(MDs); + for (SmallVectorImpl>::iterator + MI = MDs.begin(), + ME = MDs.end(); + MI != ME; ++MI) { + MDNode *Old = MI->second; + MDNode *New = MapMetadata(Old, VMap, Flags, TypeMapper, Materializer); + if (New != Old) + I->setMetadata(MI->first, New); + } + + // If the instruction's type is being remapped, do so now. + if (TypeMapper) + I->mutateType(TypeMapper->remapType(I->getType())); +}