Rotate the algorithm for remapping distinct nodes in order to simplify
how uniquing cycles get resolved. This removes some of the recursion,
and, most importantly, exposes all uniquing cycles at the top-level.
Besides being a little more efficient -- temporary MDNodes won't live as
long -- the clearer logic should help protect against bugs like those
fixed in r243961 and r243976.
What are uniquing cycles? Why do they present challenges when remapping
metadata?
!0 = !{!1}
!1 = !{!0}
!0 and !1 form a simple uniquing cycle. When remapping from one
metadata graph to another, every uniquing cycle gets "duplicated"
through a dance:
!0-temp = !{!1?} ; map(!0): clone !0, VM[!0] = !0-temp
!1-temp = !{!0?} ; ..map(!1): clone !1, VM[!1] = !1-temp
!1-temp = !{!0-temp} ; ..map(!1): remap !1's operands
!2 = !{!0-temp} ; ..map(!1): uniquify: !1-temp => !2
!0-temp = !{!2} ; map(!0): remap !0's operands
!3 = !{!2} ; map(!0): uniquify: !0-temp => !3
; Result
!2 = !{!3}
!3 = !{!2}
(In the two "uniquify" steps above, the operands of !X-temp are compared
to the operands of !X. If they're the same, then !X-temp gets RAUW'ed
to !X; if they're different, then !X-temp is promoted to a new unique
node. The latter case always hits in for uniquing cycles, so we
duplicate all the nodes involved.)
Why is this a problem? Uniquable Metadata nodes that have temporary
node as transitive operands keep RAUW support until the temporary nodes
get finalized. With non-cycles, this happens automatically: when a
uniquable node's count of unresolved operands drops to zero, it
immediately sheds its own RAUW support (possibly triggering the same in
any node that references it). However, uniquing cycles create a
reference cycle, and uniqued nodes that transitively reference a
uniquing cycle are "stuck" in an unresolved state until someone calls
`MDNode::resolveCycles()` on a node in the unresolved subgraph.
Distinct nodes should help here (and mostly do): since they aren't
uniqued anywhere, they are guaranteed not to be RAUW'ed. They
effectively form a barrier between uniqued nodes, breaking some uniquing
cycles, and shielding uniqued nodes from uniquing cycles.
Unfortunately, with this barrier in place, the unresolved subgraph(s)
can be disjoint from the top-level node. The mapping algorithm needs to
find at least one representative from each disjoint subgraph. But which
nodes are *stuck*, and which will get resolved automatically? And which
nodes are in the unresolved subgraph? The old logic was conservative.
This commit rotates the logic for distinct nodes, so that we have access
to unresolved nodes at the top-level call to `llvm::MapMetadata()`.
Each time we return to the top-level, we know that all temporaries have
been RAUW'ed away. Here, it's safe (and necessary) to call
`resolveCycles()` immediately on unresolved operands.
This should also perform better than the old algorithm. The recursion
stack is shorter, temporary nodes don't live as long, and there are
fewer tracking references to unresolved nodes. As the debug info graph
introduces more 'distinct' nodes, remapping should incrementally get
cheaper and cheaper.
Aside from possible performance improvements (and reduced cruft in the
`LLVMContext`), there should be no functionality change here.
llvm-svn: 244181
417 lines
16 KiB
C++
417 lines
16 KiB
C++
//===- ValueMapper.cpp - Interface shared by lib/Transforms/Utils ---------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the MapValue function, which is shared by various parts of
|
|
// the lib/Transforms/Utils library.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
|
#include "llvm/IR/CallSite.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;
|
|
|
|
// 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;
|
|
|
|
// If we have a materializer and it can materialize a value, use that.
|
|
if (Materializer) {
|
|
if (Value *NewV = Materializer->materializeValueFor(const_cast<Value*>(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<GlobalValue>(V))
|
|
return VM[V] = const_cast<Value*>(V);
|
|
|
|
if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
|
|
// Inline asm may need *type* remapping.
|
|
FunctionType *NewTy = IA->getFunctionType();
|
|
if (TypeMapper) {
|
|
NewTy = cast<FunctionType>(TypeMapper->remapType(NewTy));
|
|
|
|
if (NewTy != IA->getFunctionType())
|
|
V = InlineAsm::get(NewTy, IA->getAsmString(), IA->getConstraintString(),
|
|
IA->hasSideEffects(), IA->isAlignStack());
|
|
}
|
|
|
|
return VM[V] = const_cast<Value*>(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 (!isa<LocalAsMetadata>(MD) && (Flags & RF_NoModuleLevelChanges))
|
|
return VM[V] = const_cast<Value *>(V);
|
|
|
|
auto *MappedMD = MapMetadata(MD, VM, Flags, TypeMapper, Materializer);
|
|
if (MD == MappedMD || (!MappedMD && (Flags & RF_IgnoreMissingEntries)))
|
|
return VM[V] = 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
|
|
// is something that is not in the mapping table.
|
|
Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V));
|
|
if (!C)
|
|
return nullptr;
|
|
|
|
if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
|
|
Function *F =
|
|
cast<Function>(MapValue(BA->getFunction(), VM, Flags, TypeMapper, Materializer));
|
|
BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(), VM,
|
|
Flags, TypeMapper, Materializer));
|
|
return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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;
|
|
|
|
// Okay, we need to create a new constant. We've already processed some or
|
|
// all of the operands, set them all up now.
|
|
SmallVector<Constant*, 8> Ops;
|
|
Ops.reserve(NumOperands);
|
|
for (unsigned j = 0; j != OpNo; ++j)
|
|
Ops.push_back(cast<Constant>(C->getOperand(j)));
|
|
|
|
// If one of the operands mismatch, push it and the other mapped operands.
|
|
if (OpNo != NumOperands) {
|
|
Ops.push_back(cast<Constant>(Mapped));
|
|
|
|
// Map the rest of the operands that aren't processed yet.
|
|
for (++OpNo; OpNo != NumOperands; ++OpNo)
|
|
Ops.push_back(MapValue(cast<Constant>(C->getOperand(OpNo)), VM,
|
|
Flags, TypeMapper, Materializer));
|
|
}
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
|
|
return VM[V] = CE->getWithOperands(Ops, NewTy);
|
|
if (isa<ConstantArray>(C))
|
|
return VM[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops);
|
|
if (isa<ConstantStruct>(C))
|
|
return VM[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops);
|
|
if (isa<ConstantVector>(C))
|
|
return VM[V] = ConstantVector::get(Ops);
|
|
// If this is a no-operand constant, it must be because the type was remapped.
|
|
if (isa<UndefValue>(C))
|
|
return VM[V] = UndefValue::get(NewTy);
|
|
if (isa<ConstantAggregateZero>(C))
|
|
return VM[V] = ConstantAggregateZero::get(NewTy);
|
|
assert(isa<ConstantPointerNull>(C));
|
|
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,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
ValueToValueMapTy &VM, RemapFlags Flags,
|
|
ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer);
|
|
|
|
static Metadata *mapMetadataOp(Metadata *Op,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
ValueToValueMapTy &VM, RemapFlags Flags,
|
|
ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer) {
|
|
if (!Op)
|
|
return nullptr;
|
|
if (Metadata *MappedOp = MapMetadataImpl(Op, DistinctWorklist, 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;
|
|
}
|
|
|
|
/// Remap the operands of an MDNode.
|
|
static bool remapOperands(MDNode &Node,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
ValueToValueMapTy &VM, RemapFlags Flags,
|
|
ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer) {
|
|
assert(!Node.isUniqued() && "Expected temporary or distinct node");
|
|
|
|
bool AnyChanged = false;
|
|
for (unsigned I = 0, E = Node.getNumOperands(); I != E; ++I) {
|
|
Metadata *Old = Node.getOperand(I);
|
|
Metadata *New = mapMetadataOp(Old, DistinctWorklist, VM, Flags, TypeMapper,
|
|
Materializer);
|
|
if (Old != New) {
|
|
AnyChanged = true;
|
|
Node.replaceOperandWith(I, New);
|
|
}
|
|
}
|
|
|
|
return AnyChanged;
|
|
}
|
|
|
|
/// Map a distinct MDNode.
|
|
///
|
|
/// Whether distinct nodes change is independent of their operands. If \a
|
|
/// RF_MoveDistinctMDs, then they are reused, and their operands remapped in
|
|
/// place; effectively, they're moved from one graph to another. Otherwise,
|
|
/// they're cloned/duplicated, and the new copy's operands are remapped.
|
|
static Metadata *mapDistinctNode(const MDNode *Node,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
ValueToValueMapTy &VM, RemapFlags Flags,
|
|
ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer) {
|
|
assert(Node->isDistinct() && "Expected distinct node");
|
|
|
|
MDNode *NewMD;
|
|
if (Flags & RF_MoveDistinctMDs)
|
|
NewMD = const_cast<MDNode *>(Node);
|
|
else
|
|
NewMD = MDNode::replaceWithDistinct(Node->clone());
|
|
|
|
// Remap operands later.
|
|
DistinctWorklist.push_back(NewMD);
|
|
return mapToMetadata(VM, Node, NewMD);
|
|
}
|
|
|
|
/// \brief Map a uniqued MDNode.
|
|
///
|
|
/// Uniqued nodes may not need to be recreated (they may map to themselves).
|
|
static Metadata *mapUniquedNode(const MDNode *Node,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
ValueToValueMapTy &VM, RemapFlags Flags,
|
|
ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer) {
|
|
assert(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());
|
|
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);
|
|
}
|
|
|
|
// Uniquify the cloned node.
|
|
return MDNode::replaceWithUniqued(std::move(ClonedMD));
|
|
}
|
|
|
|
static Metadata *MapMetadataImpl(const Metadata *MD,
|
|
SmallVectorImpl<MDNode *> &DistinctWorklist,
|
|
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;
|
|
}
|
|
|
|
// Note: this cast precedes the Flags check so we always get its associated
|
|
// assertion.
|
|
const MDNode *Node = cast<MDNode>(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);
|
|
|
|
// Require resolved nodes whenever metadata might be remapped.
|
|
assert(Node->isResolved() && "Unexpected unresolved node");
|
|
|
|
if (Node->isDistinct())
|
|
return mapDistinctNode(Node, DistinctWorklist, VM, Flags, TypeMapper,
|
|
Materializer);
|
|
|
|
return mapUniquedNode(Node, DistinctWorklist, VM, Flags, TypeMapper,
|
|
Materializer);
|
|
}
|
|
|
|
Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
|
|
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
|
|
ValueMaterializer *Materializer) {
|
|
SmallVector<MDNode *, 8> DistinctWorklist;
|
|
Metadata *NewMD = MapMetadataImpl(MD, DistinctWorklist, VM, Flags, TypeMapper,
|
|
Materializer);
|
|
|
|
// When there are no module-level changes, it's possible that the metadata
|
|
// graph has temporaries. Skip the logic to resolve cycles, since it's
|
|
// unnecessary (and invalid) in that case.
|
|
if (Flags & RF_NoModuleLevelChanges)
|
|
return NewMD;
|
|
|
|
// If the top-level metadata was a uniqued MDNode, it could be involved in a
|
|
// uniquing cycle.
|
|
if (auto *N = dyn_cast<MDNode>(NewMD))
|
|
if (!N->isResolved())
|
|
N->resolveCycles();
|
|
|
|
// Remap the operands of distinct MDNodes.
|
|
while (!DistinctWorklist.empty()) {
|
|
auto *N = DistinctWorklist.pop_back_val();
|
|
|
|
// If an operand changes, then it may be involved in a uniquing cycle.
|
|
if (remapOperands(*N, DistinctWorklist, VM, Flags, TypeMapper,
|
|
Materializer))
|
|
for (Metadata *MD : N->operands())
|
|
if (auto *Op = dyn_cast_or_null<MDNode>(MD))
|
|
if (!Op->isResolved())
|
|
Op->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.
|
|
///
|
|
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, 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<PHINode>(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<BasicBlock>(V));
|
|
else
|
|
assert((Flags & RF_IgnoreMissingEntries) &&
|
|
"Referenced block not in value map!");
|
|
}
|
|
}
|
|
|
|
// Remap attached metadata.
|
|
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
|
|
I->getAllMetadata(MDs);
|
|
for (const auto &MI : MDs) {
|
|
MDNode *Old = MI.second;
|
|
MDNode *New = MapMetadata(Old, VMap, Flags, TypeMapper, Materializer);
|
|
if (New != Old)
|
|
I->setMetadata(MI.first, New);
|
|
}
|
|
|
|
if (!TypeMapper)
|
|
return;
|
|
|
|
// If the instruction's type is being remapped, do so now.
|
|
if (auto CS = CallSite(I)) {
|
|
SmallVector<Type *, 3> Tys;
|
|
FunctionType *FTy = CS.getFunctionType();
|
|
Tys.reserve(FTy->getNumParams());
|
|
for (Type *Ty : FTy->params())
|
|
Tys.push_back(TypeMapper->remapType(Ty));
|
|
CS.mutateFunctionType(FunctionType::get(
|
|
TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg()));
|
|
return;
|
|
}
|
|
if (auto *AI = dyn_cast<AllocaInst>(I))
|
|
AI->setAllocatedType(TypeMapper->remapType(AI->getAllocatedType()));
|
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
|
|
GEP->setSourceElementType(
|
|
TypeMapper->remapType(GEP->getSourceElementType()));
|
|
GEP->setResultElementType(
|
|
TypeMapper->remapType(GEP->getResultElementType()));
|
|
}
|
|
I->mutateType(TypeMapper->remapType(I->getType()));
|
|
}
|