#include "loco/IR/Algorithm.h"
#include <cassert>
+#include <set>
#include <stack>
namespace
{
std::vector<loco::Node *> res;
+ std::set<loco::Node *> visited_nodes;
std::stack<Frame> frames;
+ auto visited = [&visited_nodes](loco::Node *node) {
+ return visited_nodes.find(node) != visited_nodes.end();
+ };
+
// NOTE There is not much difference between "auto" and "auto &" as node is of "loco::Node *"
// type.
for (auto node : roots)
{
auto &top_frame = frames.top();
+ if (top_frame.pos() == -1)
+ {
+ if (visited(top_frame.ptr()))
+ {
+ frames.pop();
+ continue;
+ }
+ visited_nodes.insert(top_frame.ptr());
+ }
+
top_frame.advance();
assert(top_frame.pos() >= 0);
#include "loco/IR/Algorithm.h"
#include "loco/IR/Graph.h"
+#include <algorithm>
+
#include <gtest/gtest.h>
+namespace
+{
+
+bool contains(const std::vector<loco::Node *> &vec, loco::Node *val)
+{
+ return std::any_of(vec.begin(), vec.end(), [val](loco::Node *node) { return node == val; });
+}
+
+} // namespace
+
TEST(AlgorithmTest, postorder_traversal)
{
auto g = loco::make_graph();
ASSERT_EQ(seq.at(0), pull_1);
ASSERT_EQ(seq.at(1), push);
}
+
+TEST(AlgorithmTest, postorder_traversal_visit_once)
+{
+ auto g = loco::make_graph();
+
+ // Create a network of the following form:
+ //
+ // Push1 Push2 <-- outputs
+ // \ /
+ // Pull <-- input
+ //
+ auto pull = g->nodes()->create<loco::Pull>();
+ auto push_1 = g->nodes()->create<loco::Push>();
+ auto push_2 = g->nodes()->create<loco::Push>();
+
+ push_1->from(pull);
+ push_2->from(pull);
+
+ auto seq = loco::postorder_traversal({push_1, push_2});
+
+ ASSERT_EQ(seq.size(), 3);
+ ASSERT_TRUE(contains(seq, pull));
+ ASSERT_TRUE(contains(seq, push_1));
+ ASSERT_TRUE(contains(seq, push_2));
+}