30 template<
typename Traverser>
33 template<
typename Traverser>
39 template<
typename Traverser>
43 traverser_.onNodeCreate(node);
46 template<
typename Traverser>
50 traverser_.onNodeDestroy(node);
53 template<
typename Traverser>
57 traverser_.onInputCreate(input);
60 template<
typename Traverser>
64 traverser_.onInputChange(input, oldOrigin, newOrigin);
67 template<
typename Traverser>
71 traverser_.onInputDestroy(input);
74 template<
bool IsConst>
77 template<
bool IsConst>
79 : observer_(*region, *this),
80 nodeIdCutoff_(region->getNextNodeId())
82 for (
auto & node : region->TopNodes())
84 tracker_.checkNodeActivation(&node, node.ninputs());
87 for (
auto argument : region->Arguments())
89 for (
const auto & user : argument->Users())
91 if (
auto node = TryGetOwnerNode<Node>(user))
93 tracker_.incActivationCount(node, node->ninputs());
99 template<
bool IsConst>
103 if (
auto pred = TryGetOwnerNode<Node>(output))
105 return tracker_.isNodeVisited(pred);
112 template<
bool IsConst>
116 tracker_.checkMarkNodeVisitedIfFrontier(&node);
117 for (
const auto & output : node.Outputs())
119 for (
const auto & user : output.Users())
121 if (
auto next = TryGetOwnerNode<Node>(user))
123 tracker_.incActivationCount(next, next->ninputs());
129 template<
bool IsConst>
135 const auto node = tracker_.peek();
139 markAsVisited(*node);
142 if (node->GetNodeId() >= nodeIdCutoff_)
149 template<
bool IsConst>
153 if (node->ninputs() == 0)
155 tracker_.checkNodeActivation(node, node->ninputs());
159 for (
const auto & input : node->Inputs())
161 if (isOutputActivated(*input.origin()))
163 tracker_.incActivationCount(node, node->ninputs());
171 tracker_.checkMarkNodeVisitedIfFrontier(node);
174 template<
bool IsConst>
179 tracker_.removeNode(node);
182 template<
bool IsConst>
186 const auto node = TryGetOwnerNode<Node>(*input);
190 if (isOutputActivated(*input->
origin()))
192 tracker_.incActivationCount(node, node->ninputs());
196 tracker_.checkNodeDeactivation(node, node->ninputs());
200 template<
bool IsConst>
207 const auto node = TryGetOwnerNode<Node>(*input);
212 if (isOutputActivated(*newOrigin))
216 if (isOutputActivated(*oldOrigin))
223 tracker_.incActivationCount(node, node->ninputs());
225 else if (change == -1)
227 tracker_.decActivationCount(node, node->ninputs());
231 template<
bool IsConst>
235 const auto node = TryGetOwnerNode<Node>(*input);
239 if (isOutputActivated(*input->
origin()))
243 tracker_.decActivationCount(node, 0);
248 tracker_.checkNodeActivation(node, node->ninputs() - 1);
252 template<
bool IsConst>
255 template<
bool IsConst>
257 : observer_(*region, *this)
259 for (
auto & node : region->BottomNodes())
261 tracker_.checkNodeActivation(&node, node.numSuccessors());
264 for (
auto result : region->Results())
266 if (
auto node = TryGetOwnerNode<Node>(*result->origin()))
268 tracker_.incActivationCount(node, node->numSuccessors());
273 template<
bool IsConst>
277 if (
auto node = TryGetOwnerNode<Node>(input))
279 return tracker_.isNodeVisited(node);
286 template<
bool IsConst>
290 tracker_.checkMarkNodeVisitedIfFrontier(&node);
291 for (
const auto & input : node.Inputs())
293 if (
auto predecessor = TryGetOwnerNode<Node>(*input.origin()))
295 tracker_.incActivationCount(predecessor, predecessor->numSuccessors());
300 template<
bool IsConst>
304 auto node = tracker_.peek();
308 markAsVisited(*node);
312 template<
bool IsConst>
317 markAsVisited(*node);
320 template<
bool IsConst>
326 if (!tracker_.isNodeVisited(node))
327 markAsVisited(*node);
329 for (
const auto & input : node->Inputs())
331 if (
auto pred = TryGetOwnerNode<Node>(*input.origin()))
337 tracker_.decActivationCount(pred, 0);
342 template<
bool IsConst>
346 const auto node = TryGetOwnerNode<Node>(*input->
origin());
350 if (isInputActivated(*input))
352 tracker_.incActivationCount(node, node->numSuccessors());
356 tracker_.checkNodeDeactivation(node, node->numSuccessors());
360 template<
bool IsConst>
367 const auto inputActive = isInputActivated(*input);
369 if (
auto oldNode = TryGetOwnerNode<Node>(*oldOrigin))
373 tracker_.decActivationCount(oldNode, oldNode->numSuccessors());
378 tracker_.checkNodeActivation(oldNode, oldNode->numSuccessors());
382 if (
auto newNode = TryGetOwnerNode<Node>(*newOrigin))
386 tracker_.incActivationCount(newNode, newNode->numSuccessors());
390 tracker_.checkNodeDeactivation(newNode, newNode->numSuccessors());
395 template<
bool IsConst>
399 const auto pred = TryGetOwnerNode<Node>(*input->
origin());
403 if (isInputActivated(*input))
407 tracker_.decActivationCount(pred, 0);
411 tracker_.checkNodeActivation(pred, pred->numSuccessors() - 1);
415 template<
typename NodeType>
419 auto i = states_.find(node);
423 template<
typename NodeType>
430 frontier_.push_back(node);
431 i->second.pos = std::prev(frontier_.end());
436 template<
typename NodeType>
443 frontier_.erase(i->second.pos);
444 i->second.pos = frontier_.end();
449 template<
typename NodeType>
456 frontier_.erase(i->second.pos);
457 i->second.pos = frontier_.end();
462 template<
typename NodeType>
467 i->second.activationCount += 1;
468 checkNodeActivation(node, threshold);
471 template<
typename NodeType>
476 i->second.activationCount -= 1;
477 checkNodeDeactivation(node, threshold);
480 template<
typename NodeType>
484 if (
const auto it = states_.find(node); it != states_.end())
487 frontier_.erase(it->second.pos);
492 template<
typename NodeType>
496 return frontier_.empty() ? nullptr : frontier_.front();
Proxy object to observe changes to a region.
Represent acyclic RVSDG subgraphs.
void onInputDestroy(Input *input)
std::conditional_t< IsConst, const Node, Node > NodeType
bool isInputActivated(const Input &input) const
void onNodeDestroy(NodeType *node)
void markAsVisited(NodeType &node)
void onInputCreate(Input *input)
void onNodeCreate(NodeType *node)
std::conditional_t< IsConst, const Region, Region > RegionType
~BottomUpTraverserGeneric() noexcept
void onInputChange(Input *input, Output *oldOrigin, Output *newOrigin)
void onNodeDestroy(Node *node) override
ForwardingObserver(const Region ®ion, Traverser &traverser)
~ForwardingObserver() noexcept override
void onInputCreate(Input *input) override
void onInputChange(Input *input, Output *oldOrigin, Output *newOrigin) override
void onNodeCreate(Node *node) override
void onInputDestroy(Input *input) override
bool isOutputActivated(const Output &output) const
void markAsVisited(NodeType &node)
void onInputDestroy(Input *input)
void onNodeCreate(NodeType *node)
void onInputChange(Input *in, Output *old_origin, Output *new_origin)
void onInputCreate(Input *input)
~TopDownTraverserGeneric() noexcept
void onNodeDestroy(NodeType *node)
std::conditional_t< IsConst, const Node, Node > NodeType
std::conditional_t< IsConst, const Region, Region > RegionType
void checkMarkNodeVisitedIfFrontier(NodeType *node)
Marks a node visited if it is currently ready for visiting.
bool isNodeVisited(NodeType *node) const
Determines whether node has been visited already.
void decActivationCount(NodeType *node, std::size_t threshold)
Decrements activation count; removes from frontier if threshold is no longer met.
void incActivationCount(NodeType *node, std::size_t threshold)
Increments activation count; adds to frontier if threshold is met.
void checkNodeActivation(NodeType *node, std::size_t threshold)
Checks activation count whether node is ready for visiting.
void checkNodeDeactivation(NodeType *node, std::size_t threshold)
Checks activation count whether node is no longer ready for visiting.
void removeNode(NodeType *node)
Removes any state associated with the given node.