[logo] Introduce RemoveDeadNodePass (#6935)
author박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Tue, 27 Aug 2019 04:21:18 +0000 (13:21 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Tue, 27 Aug 2019 04:21:18 +0000 (13:21 +0900)
This will introduce RemoveDeadNodePass copied from moco

Signed-off-by: SaeHie Park <saehie.park@samsung.com>
compiler/logo/include/logo/RemoveDeadNodePass.h [new file with mode: 0644]
compiler/logo/src/Passes/RemoveDeadNodePass.cpp [new file with mode: 0644]

diff --git a/compiler/logo/include/logo/RemoveDeadNodePass.h b/compiler/logo/include/logo/RemoveDeadNodePass.h
new file mode 100644 (file)
index 0000000..ae1c67f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LOGO_REMOVE_DEAD_NODE_PASS_H__
+#define __LOGO_REMOVE_DEAD_NODE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace logo
+{
+
+struct RemoveDeadNodePass final : public Pass
+{
+  const char *name(void) const final { return "RemoveDeadNodePass"; }
+
+  bool run(loco::Graph *g);
+};
+
+} // namespace logo
+
+#endif // __LOGO_REMOVE_DEAD_NODE_PASS_H__
diff --git a/compiler/logo/src/Passes/RemoveDeadNodePass.cpp b/compiler/logo/src/Passes/RemoveDeadNodePass.cpp
new file mode 100644 (file)
index 0000000..9b6ed6a
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/RemoveDeadNodePass.h>
+
+#include <loco/IR/Algorithm.h>
+#include <loco/IR/CanonicalDialect.h>
+#include <loco/IR/CanonicalNode.h>
+
+#include <set>
+
+namespace logo
+{
+
+bool RemoveDeadNodePass::run(loco::Graph *g)
+{
+  // Let's enumerate nodes required to compute output nodes
+  auto active_nodes = loco::active_nodes(loco::output_nodes(g));
+
+  // Find dead(= non-active) nodes
+  std::set<loco::Node *> candidates;
+
+  for (auto node : loco::all_nodes(g))
+  {
+    if (active_nodes.find(node) == active_nodes.end())
+    {
+      candidates.insert(node);
+    }
+  }
+
+  // Let's drop the references from each dead node first and then remove these dead nodes
+  //
+  // Why?
+  //
+  // Let us consider the following example:
+  //    %0 = Pull(...)
+  //    %1 = ConstGen(...)
+  //    %2 = Forward(input: %1)
+  //    %3 = Push(from: %0) <- OUTPUT
+  //
+  // Forward (%2) is dead as it does not contribute to the final result (%3). However, it
+  // refers to another dead node (%1).
+  //
+  // This example indicates that naive implementation results in dangling references.
+  //
+  // There are two possible solutions:
+  //  1. Destroy nodes in topological order
+  //  2. Drop the reference first and then destroy them
+  //
+  // The current implementation takes the latter approach for the simplicity of implementation.
+  for (auto node : candidates)
+  {
+    node->drop();
+  }
+
+  for (auto node : candidates)
+  {
+    g->nodes()->destroy(node);
+  }
+
+  return candidates.size() > 0;
+}
+
+} // namespace logo