[llvm] r266537 - ValueMapper: Separate mapping of distinct and uniqued nodes (again)
Duncan P. N. Exon Smith via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 16 14:44:08 PDT 2016
Author: dexonsmith
Date: Sat Apr 16 16:44:08 2016
New Revision: 266537
URL: http://llvm.org/viewvc/llvm-project?rev=266537&view=rev
Log:
ValueMapper: Separate mapping of distinct and uniqued nodes (again)
Since the result of a mapped distinct node is known up front, it's more
efficient to map them separately from uniqued nodes. This commit pulls
them out of the post-order traversal and stores them in a worklist to be
remapped at the top-level.
This is essentially reapplying r244181 ("ValueMapper: Rotate distinct
node remapping algorithm") to the new iterative algorithm from r265456
("ValueMapper: Rewrite Mapper::mapMetadata without recursion").
Now that the traversal logic only handles uniqued MDNodes, it's much
simpler to inline it all into MDNodeMapper::createPOT (I've killed the
MDNodeMapper::push and MDNodeMapper::tryToPop helpers and localized the
traversal worklist).
The resulting high-level algorithm for MDNodeMapper::map now looks like
this:
- Distinct nodes are immediately mapped and added to
MDNodeMapper::DistinctWorklist using MDNodeMapper::mapDistinctNode.
- Uniqued nodes are mapped via MDNodeMapper::mapTopLevelUniquedNode,
which traverses the transitive uniqued subgraph of a node to
calculate uniqued node mappings in bulk.
- This is a simplified version of MDNodeMapper::map from before
this commit (originally r265456) that doesn't traverse through
any distinct nodes.
- Distinct nodes are added to MDNodeMapper::DistinctWorklist via
MDNodeMapper::mapDistinctNode.
- This uses MDNodeMapper::createPOT to fill a
MDNodeMapper::UniquedGraph (a post-order traversal and side
table), UniquedGraph::propagateChanges to track which uniqued
nodes need to change, and MDNodeMapper::mapNodesInPOT to create
the uniqued nodes.
- Placeholders for forward references are now only needed when
there's a uniquing cycle (a cycle of uniqued nodes unbroken by
distinct nodes). This is the key functionality change that
we're reintroducing (from r244181). As of r265456, a temporary
forward reference might be needed for any cycle that involved
uniqued nodes.
- After mapping the first node appropriately, MDNodeMapper::map works
through MDNodeMapper::DistinctWorklist. For each distinct node, its
operands are remapped with MDNodeMapper::mapDistinctNode and
MDNodeMapper::mapTopLevelUniquedNode until all nodes have been
mapped.
Sadly there's nothing observable I can test here; no real functionality
change, just a compile-time speedup from reduced malloc traffic.
Modified:
llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=266537&r1=266536&r2=266537&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Sat Apr 16 16:44:08 2016
@@ -189,149 +189,149 @@ private:
class MDNodeMapper {
Mapper &M;
+ /// Data about a node in \a UniquedGraph.
struct Data {
- bool HasChangedOps = false;
- bool HasChangedAddress = false;
+ bool HasChanged = false;
unsigned ID = ~0u;
TempMDNode Placeholder;
Data() {}
Data(Data &&X)
- : HasChangedOps(std::move(X.HasChangedOps)),
- HasChangedAddress(std::move(X.HasChangedAddress)),
- ID(std::move(X.ID)), Placeholder(std::move(X.Placeholder)) {}
+ : HasChanged(std::move(X.HasChanged)), ID(std::move(X.ID)),
+ Placeholder(std::move(X.Placeholder)) {}
Data &operator=(Data &&X) {
- HasChangedOps = std::move(X.HasChangedOps);
- HasChangedAddress = std::move(X.HasChangedAddress);
+ HasChanged = std::move(X.HasChanged);
ID = std::move(X.ID);
Placeholder = std::move(X.Placeholder);
return *this;
}
};
- SmallDenseMap<const Metadata *, Data, 32> Info;
- SmallVector<std::pair<MDNode *, bool>, 16> Worklist;
- SmallVector<MDNode *, 16> POT;
+ /// A graph of uniqued nodes.
+ struct UniquedGraph {
+ SmallDenseMap<const Metadata *, Data, 32> Info; // Node properties.
+ SmallVector<MDNode *, 16> POT; // Post-order traversal.
+
+ /// Propagate changed operands through the post-order traversal.
+ ///
+ /// Iteratively update \a Data::HasChanged for each node based on \a
+ /// Data::HasChanged of its operands, until fixed point.
+ void propagateChanges();
+
+ /// Get a forward reference to a node to use as an operand.
+ Metadata &getFwdReference(MDNode &Op);
+ };
+
+ /// Worklist of distinct nodes whose operands need to be remapped.
+ SmallVector<MDNode *, 16> DistinctWorklist;
+
+ // Storage for a UniquedGraph.
+ SmallDenseMap<const Metadata *, Data, 32> InfoStorage;
+ SmallVector<MDNode *, 16> POTStorage;
public:
MDNodeMapper(Mapper &M) : M(M) {}
/// Map a metadata node (and its transitive operands).
///
- /// This is the only entry point into MDNodeMapper. It works as follows:
+ /// Map all the (unmapped) nodes in the subgraph under \c N. The iterative
+ /// algorithm handles distinct nodes and uniqued node subgraphs using
+ /// different strategies.
+ ///
+ /// Distinct nodes are immediately mapped and added to \a DistinctWorklist
+ /// using \a mapDistinctNode(). Their mapping can always be computed
+ /// immediately without visiting operands, even if their operands change.
+ ///
+ /// The mapping for uniqued nodes depends on whether their operands change.
+ /// \a mapTopLevelUniquedNode() traverses the transitive uniqued subgraph of
+ /// a node to calculate uniqued node mappings in bulk. Distinct leafs are
+ /// added to \a DistinctWorklist with \a mapDistinctNode().
+ ///
+ /// After mapping \c N itself, this function remaps the operands of the
+ /// distinct nodes in \a DistinctWorklist until the entire subgraph under \c
+ /// N has been mapped.
+ Metadata *map(const MDNode &N);
+
+private:
+ /// Map a top-level uniqued node and the uniqued subgraph underneath it.
///
- /// 1. \a createPOT(): use a worklist to perform a post-order traversal of
- /// the transitively referenced unmapped nodes.
+ /// This builds up a post-order traversal of the (unmapped) uniqued subgraph
+ /// underneath \c FirstN and calculates the nodes' mapping. Each node uses
+ /// the identity mapping (\a Mapper::mapToSelf()) as long as all of its
+ /// operands uses the identity mapping.
///
- /// 2. \a propagateChangedOperands(): track which nodes will change
- /// operands, and which will have new addresses in the mapped scheme.
- /// Propagate the changes through the POT until fixed point, to pick up
- /// uniquing cycles that need to change.
+ /// The algorithm works as follows:
///
- /// 3. \a mapDistinctNodes(): map all the distinct nodes without touching
- /// their operands. If RF_MoveDistinctMetadata, they get mapped to
- /// themselves; otherwise, they get mapped to clones.
+ /// 1. \a createPOT(): traverse the uniqued subgraph under \c FirstN and
+ /// save the post-order traversal in the given \a UniquedGraph, tracking
+ /// nodes' operands change.
///
- /// 4. \a mapUniquedNodes(): map the uniqued nodes (bottom-up), lazily
- /// creating temporaries for forward references as needed.
+ /// 2. \a UniquedGraph::propagateChanges(): propagate changed operands
+ /// through the \a UniquedGraph until fixed point, following the rule
+ /// that if a node changes, any node that references must also change.
///
- /// 5. \a remapDistinctOperands(): remap the operands of the distinct nodes.
- Metadata *map(const MDNode &FirstN);
-
-private:
- /// Return \c true as long as there's work to do.
- bool hasWork() const { return !Worklist.empty(); }
+ /// 3. \a mapNodesInPOT(): map the uniqued nodes, creating new uniqued nodes
+ /// (referencing new operands) where necessary.
+ Metadata *mapTopLevelUniquedNode(const MDNode &FirstN);
- /// Get the current node in the worklist.
- MDNode &getCurrentNode() const { return *Worklist.back().first; }
-
- /// Push a node onto the worklist.
- ///
- /// Adds \c N to \a Worklist and \a Info, unless it's already inserted. If
- /// \c N.isDistinct(), \a Data::HasChangedAddress will be set based on \a
- /// RF_MoveDistinctMDs.
+ /// Try to map the operand of an \a MDNode.
///
- /// Returns the data for the node.
+ /// If \c Op is already mapped, return the mapping. If it's not an \a
+ /// MDNode, compute and return the mapping. If it's a distinct \a MDNode,
+ /// return the result of \a mapDistinctNode().
///
- /// \post Data::HasChangedAddress iff !RF_MoveDistinctMDs && N.isDistinct().
- /// \post Worklist.back().first == &N.
- /// \post Worklist.back().second == false.
- Data &push(const MDNode &N);
+ /// \return None if \c Op is an unmapped uniqued \a MDNode.
+ /// \post getMappedOp(Op) only returns None if this returns None.
+ Optional<Metadata *> tryToMapOperand(const Metadata *Op);
- /// Map a node operand, and return true if it changes.
+ /// Map a distinct node.
///
- /// \post getMappedOp(Op) does not return None.
- bool mapOperand(const Metadata *Op);
+ /// Return the mapping for the distinct node \c N, saving the result in \a
+ /// DistinctWorklist for later remapping.
+ ///
+ /// \pre \c N is not yet mapped.
+ /// \pre \c N.isDistinct().
+ MDNode *mapDistinctNode(const MDNode &N);
/// Get a previously mapped node.
Optional<Metadata *> getMappedOp(const Metadata *Op) const;
- /// Try to pop a node off the worklist and store it in POT.
- ///
- /// Returns \c true if it popped; \c false if its operands need to be
- /// visited.
- ///
- /// \post If Worklist.back().second == false: Worklist.back().second == true.
- /// \post Else: Worklist.back() has been popped off and added to \a POT.
- bool tryToPop();
-
- /// Get a forward reference to a node to use as an operand.
- ///
- /// Returns \c Op if it's not changing; otherwise, lazily creates a temporary
- /// node and returns it.
- Metadata &getFwdReference(const Data &D, MDNode &Op);
-
- /// Create a post-order traversal from the given node.
+ /// Create a post-order traversal of an unmapped uniqued node subgraph.
///
/// This traverses the metadata graph deeply enough to map \c FirstN. It
- /// uses \a mapOperand() (indirectly, \a Mapper::mapSimplifiedNode()), so any
+ /// uses \a tryToMapOperand() (via \a Mapper::mapSimplifiedNode()), so any
/// metadata that has already been mapped will not be part of the POT.
///
- /// \post \a POT is a post-order traversal ending with \c FirstN.
- bool createPOT(const MDNode &FirstN);
+ /// Each node that has a changed operand from outside the graph (e.g., a
+ /// distinct node, an already-mapped uniqued node, or \a ConstantAsMetadata)
+ /// is marked with \a Data::HasChanged.
+ ///
+ /// \return \c true if any nodes in \c G have \a Data::HasChanged.
+ /// \post \c G.POT is a post-order traversal ending with \c FirstN.
+ /// \post \a Data::hasChanged in \c G.Info indicates whether any node needs
+ /// to change because of operands outside the graph.
+ bool createPOT(UniquedGraph &G, const MDNode &FirstN);
+
+ /// Map all the nodes in the given uniqued graph.
+ ///
+ /// This visits all the nodes in \c G in post-order, using the identity
+ /// mapping or creating a new node depending on \a Data::HasChanged.
+ ///
+ /// \pre \a getMappedOp() returns None for nodes in \c G, but not for any of
+ /// their operands outside of \c G.
+ /// \pre \a Data::HasChanged is true for a node in \c G iff any of its
+ /// operands have changed.
+ /// \post \a getMappedOp() returns the mapped node for every node in \c G.
+ void mapNodesInPOT(UniquedGraph &G);
- /// Propagate changed operands through post-order traversal.
+ /// Remap a node's operands using the given functor.
///
- /// Until fixed point, iteratively update:
- ///
- /// - \a Data::HasChangedOps based on \a Data::HasChangedAddress of operands;
- /// - \a Data::HasChangedAddress based on Data::HasChangedOps.
- ///
- /// This algorithm never changes \a Data::HasChangedAddress for distinct
- /// nodes.
- ///
- /// \post \a POT is a post-order traversal ending with \c FirstN.
- void propagateChangedOperands();
-
- /// Map all distinct nodes in POT.
- ///
- /// \post \a getMappedOp() returns the correct node for every distinct node.
- void mapDistinctNodes();
-
- /// Map all uniqued nodes in POT with the correct operands.
- ///
- /// \pre Distinct nodes are mapped (\a mapDistinctNodes() has been called).
- /// \post \a getMappedOp() returns the correct node for every node.
- /// \post \a MDNode::operands() is correct for every uniqued node.
- /// \post \a MDNode::isResolved() returns true for every node.
- void mapUniquedNodes();
-
- /// Re-map the operands for distinct nodes in POT.
- ///
- /// \pre Distinct nodes are mapped (\a mapDistinctNodes() has been called).
- /// \pre Uniqued nodes are mapped (\a mapUniquedNodes() has been called).
- /// \post \a MDNode::operands() is correct for every distinct node.
- void remapDistinctOperands();
-
- /// Remap a node's operands.
- ///
- /// Iterate through operands and update them in place using \a getMappedOp()
- /// and \a getFwdReference().
+ /// Iterate through the operands of \c N and update them in place using \c
+ /// mapOperand.
///
/// \pre N.isDistinct() or N.isTemporary().
- /// \pre Distinct nodes are mapped (\a mapDistinctNodes() has been called).
- /// \pre If \c N is distinct, all uniqued nodes are already mapped.
- void remapOperands(const Data &D, MDNode &N);
+ template <class OperandMapper>
+ void remapOperands(MDNode &N, OperandMapper mapOperand);
};
} // end namespace
@@ -500,9 +500,9 @@ Metadata *Mapper::mapToSelf(const Metada
return mapToMetadata(MD, const_cast<Metadata *>(MD));
}
-bool MDNodeMapper::mapOperand(const Metadata *Op) {
+Optional<Metadata *> MDNodeMapper::tryToMapOperand(const Metadata *Op) {
if (!Op)
- return false;
+ return nullptr;
if (Optional<Metadata *> MappedOp = M.mapSimpleMetadata(Op)) {
#ifndef NDEBUG
@@ -514,10 +514,23 @@ bool MDNodeMapper::mapOperand(const Meta
assert((isa<MDString>(Op) || M.getVM().getMappedMD(Op)) &&
"Expected result to be memoized");
#endif
- return *MappedOp != Op;
+ return *MappedOp;
}
- return push(*cast<MDNode>(Op)).HasChangedAddress;
+ const MDNode &N = *cast<MDNode>(Op);
+ if (N.isDistinct())
+ return mapDistinctNode(N);
+ return None;
+}
+
+MDNode *MDNodeMapper::mapDistinctNode(const MDNode &N) {
+ assert(N.isDistinct() && "Expected a distinct node");
+ assert(!M.getVM().getMappedMD(&N) && "Expected an unmapped node");
+ DistinctWorklist.push_back(cast<MDNode>(
+ (M.Flags & RF_MoveDistinctMDs)
+ ? M.mapToSelf(&N)
+ : M.mapToMetadata(&N, MDNode::replaceWithDistinct(N.clone()))));
+ return DistinctWorklist.back();
}
static ConstantAsMetadata *wrapConstantAsMetadata(const ConstantAsMetadata &CMD,
@@ -543,14 +556,12 @@ Optional<Metadata *> MDNodeMapper::getMa
return None;
}
-Metadata &MDNodeMapper::getFwdReference(const Data &D, MDNode &Op) {
+Metadata &MDNodeMapper::UniquedGraph::getFwdReference(MDNode &Op) {
auto Where = Info.find(&Op);
assert(Where != Info.end() && "Expected a valid reference");
auto &OpD = Where->second;
- assert(OpD.ID > D.ID && "Expected a forward reference");
-
- if (!OpD.HasChangedAddress)
+ if (!OpD.HasChanged)
return Op;
// Lazily construct a temporary node.
@@ -560,128 +571,93 @@ Metadata &MDNodeMapper::getFwdReference(
return *OpD.Placeholder;
}
-void MDNodeMapper::remapOperands(const Data &D, MDNode &N) {
+template <class OperandMapper>
+void MDNodeMapper::remapOperands(MDNode &N, OperandMapper mapOperand) {
+ assert(!N.isUniqued() && "Expected distinct or temporary nodes");
for (unsigned I = 0, E = N.getNumOperands(); I != E; ++I) {
Metadata *Old = N.getOperand(I);
- Metadata *New;
- if (Optional<Metadata *> MappedOp = getMappedOp(Old)){
- New = *MappedOp;
- } else {
- assert(!N.isDistinct() &&
- "Expected all nodes to be pre-mapped for distinct operands");
- MDNode &OldN = *cast<MDNode>(Old);
- assert(!OldN.isDistinct() && "Expected distinct nodes to be pre-mapped");
- New = &getFwdReference(D, OldN);
- }
+ Metadata *New = mapOperand(Old);
if (Old != New)
N.replaceOperandWith(I, New);
}
}
-MDNodeMapper::Data &MDNodeMapper::push(const MDNode &N) {
- auto Insertion = Info.insert(std::make_pair(&N, Data()));
- auto &D = Insertion.first->second;
- if (!Insertion.second)
- return D;
-
- // Add to the worklist; check for distinct nodes that are required to be
- // copied.
- Worklist.push_back(std::make_pair(&const_cast<MDNode &>(N), false));
- D.HasChangedAddress = !(M.Flags & RF_MoveDistinctMDs) && N.isDistinct();
- return D;
-}
-
-bool MDNodeMapper::tryToPop() {
- if (!Worklist.back().second) {
- Worklist.back().second = true;
- return false;
- }
+bool MDNodeMapper::createPOT(UniquedGraph &G, const MDNode &FirstN) {
+ assert(G.Info.empty() && "Expected a fresh traversal");
+ assert(FirstN.isUniqued() && "Expected uniqued node in POT");
- MDNode *N = Worklist.pop_back_val().first;
- Info[N].ID = POT.size();
- POT.push_back(N);
- return true;
-}
-
-bool MDNodeMapper::createPOT(const MDNode &FirstN) {
+ // Construct a post-order traversal of the uniqued subgraph under FirstN.
bool AnyChanges = false;
- // Do a traversal of the unmapped subgraph, tracking whether operands change.
- // In some cases, these changes will propagate naturally, but
- // propagateChangedOperands() catches the general case.
- AnyChanges |= push(FirstN).HasChangedAddress;
- while (hasWork()) {
- if (tryToPop())
+ // The flag on the worklist indicates whether this is the first or second
+ // visit of a node. The first visit looks through the operands; the second
+ // visit adds the node to POT.
+ SmallVector<std::pair<MDNode *, bool>, 16> Worklist;
+ Worklist.push_back(std::make_pair(&const_cast<MDNode &>(FirstN), false));
+ (void)G.Info[&FirstN];
+ while (!Worklist.empty()) {
+ MDNode &N = *Worklist.back().first;
+ if (Worklist.back().second) {
+ // We've already visited operands. Add this to POT.
+ Worklist.pop_back();
+ G.Info[&N].ID = G.POT.size();
+ G.POT.push_back(&N);
continue;
+ }
+ Worklist.back().second = true;
- MDNode &N = getCurrentNode();
+ // Look through the operands for changes, pushing unmapped uniqued nodes
+ // onto to the worklist.
+ assert(N.isUniqued() && "Expected only uniqued nodes in POT");
bool LocalChanges = false;
- for (const Metadata *Op : N.operands())
- LocalChanges |= mapOperand(Op);
+ for (Metadata *Op : N.operands()) {
+ assert(Op != &N && "Uniqued nodes cannot have self-references");
+ if (Optional<Metadata *> MappedOp = tryToMapOperand(Op)) {
+ AnyChanges |= LocalChanges |= Op != *MappedOp;
+ continue;
+ }
- if (!LocalChanges)
- continue;
+ MDNode &OpN = *cast<MDNode>(Op);
+ assert(OpN.isUniqued() &&
+ "Only uniqued operands cannot be mapped immediately");
+ if (G.Info.insert(std::make_pair(&OpN, Data())).second)
+ Worklist.push_back(std::make_pair(&OpN, false));
+ }
- AnyChanges = true;
- auto &D = Info[&N];
- D.HasChangedOps = true;
-
- // Uniqued nodes change address when operands change.
- if (!N.isDistinct())
- D.HasChangedAddress = true;
+ if (LocalChanges)
+ G.Info[&N].HasChanged = true;
}
return AnyChanges;
}
-void MDNodeMapper::propagateChangedOperands() {
- bool AnyChangedAddresses;
+void MDNodeMapper::UniquedGraph::propagateChanges() {
+ bool AnyChanges;
do {
- AnyChangedAddresses = false;
+ AnyChanges = false;
for (MDNode *N : POT) {
- auto &NI = Info[N];
- if (NI.HasChangedOps)
+ auto &D = Info[N];
+ if (D.HasChanged)
continue;
if (!llvm::any_of(N->operands(), [&](const Metadata *Op) {
auto Where = Info.find(Op);
- return Where != Info.end() && Where->second.HasChangedAddress;
+ return Where != Info.end() && Where->second.HasChanged;
}))
continue;
- NI.HasChangedOps = true;
- if (!N->isDistinct()) {
- NI.HasChangedAddress = true;
- AnyChangedAddresses = true;
- }
+ AnyChanges = D.HasChanged = true;
}
- } while (AnyChangedAddresses);
+ } while (AnyChanges);
}
-void MDNodeMapper::mapDistinctNodes() {
- // Map all the distinct nodes in POT.
- for (MDNode *N : POT) {
- if (!N->isDistinct())
- continue;
-
- if (M.Flags & RF_MoveDistinctMDs)
- M.mapToSelf(N);
- else
- M.mapToMetadata(N, MDNode::replaceWithDistinct(N->clone()));
- }
-}
-
-void MDNodeMapper::mapUniquedNodes() {
+void MDNodeMapper::mapNodesInPOT(UniquedGraph &G) {
// Construct uniqued nodes, building forward references as necessary.
SmallVector<MDNode *, 16> CyclicNodes;
- for (auto *N : POT) {
- if (N->isDistinct())
- continue;
-
- auto &D = Info[N];
- assert(D.HasChangedAddress == D.HasChangedOps &&
- "Uniqued nodes should change address iff ops change");
- if (!D.HasChangedAddress) {
+ for (auto *N : G.POT) {
+ auto &D = G.Info[N];
+ if (!D.HasChanged) {
+ // The node hasn't changed.
M.mapToSelf(N);
continue;
}
@@ -691,7 +667,13 @@ void MDNodeMapper::mapUniquedNodes() {
// Clone the uniqued node and remap the operands.
TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone();
- remapOperands(D, *ClonedN);
+ remapOperands(*ClonedN, [this, &D, &G](Metadata *Old) {
+ if (Optional<Metadata *> MappedOp = getMappedOp(Old))
+ return *MappedOp;
+ assert(G.Info[Old].ID > D.ID && "Expected a forward reference");
+ return &G.getFwdReference(*cast<MDNode>(Old));
+ });
+
auto *NewN = MDNode::replaceWithUniqued(std::move(ClonedN));
M.mapToMetadata(N, NewN);
@@ -707,40 +689,42 @@ void MDNodeMapper::mapUniquedNodes() {
N->resolveCycles();
}
-void MDNodeMapper::remapDistinctOperands() {
- for (auto *N : POT) {
- if (!N->isDistinct())
- continue;
-
- auto &D = Info[N];
- if (!D.HasChangedOps)
- continue;
-
- assert(D.HasChangedAddress == !bool(M.Flags & RF_MoveDistinctMDs) &&
- "Distinct nodes should change address iff they cannot be moved");
- remapOperands(D, D.HasChangedAddress ? *cast<MDNode>(*getMappedOp(N)) : *N);
- }
-}
-
-Metadata *MDNodeMapper::map(const MDNode &FirstN) {
+Metadata *MDNodeMapper::map(const MDNode &N) {
+ assert(DistinctWorklist.empty() && "MDNodeMapper::map is not recursive");
assert(!(M.Flags & RF_NoModuleLevelChanges) &&
"MDNodeMapper::map assumes module-level changes");
- assert(POT.empty() && "MDNodeMapper::map is not re-entrant");
// Require resolved nodes whenever metadata might be remapped.
- assert(FirstN.isResolved() && "Unexpected unresolved node");
+ assert(N.isResolved() && "Unexpected unresolved node");
- // Return early if nothing at all changed.
- if (!createPOT(FirstN)) {
- for (const MDNode *N : POT)
+ Metadata *MappedN =
+ N.isUniqued() ? mapTopLevelUniquedNode(N) : mapDistinctNode(N);
+ while (!DistinctWorklist.empty())
+ remapOperands(*DistinctWorklist.pop_back_val(), [this](Metadata *Old) {
+ if (Optional<Metadata *> MappedOp = tryToMapOperand(Old))
+ return *MappedOp;
+ return mapTopLevelUniquedNode(*cast<MDNode>(Old));
+ });
+ return MappedN;
+}
+
+Metadata *MDNodeMapper::mapTopLevelUniquedNode(const MDNode &FirstN) {
+ assert(FirstN.isUniqued() && "Expected uniqued node");
+
+ // Create a post-order traversal of uniqued nodes under FirstN.
+ UniquedGraph G;
+ if (!createPOT(G, FirstN)) {
+ // Return early if no nodes have changed.
+ for (const MDNode *N : G.POT)
M.mapToSelf(N);
return &const_cast<MDNode &>(FirstN);
}
- propagateChangedOperands();
- mapDistinctNodes();
- mapUniquedNodes();
- remapDistinctOperands();
+ // Update graph with all nodes that have changed.
+ G.propagateChanges();
+
+ // Map all the nodes in the graph.
+ mapNodesInPOT(G);
// Return the original node, remapped.
return *getMappedOp(&FirstN);
More information about the llvm-commits
mailing list