[enco] Free Op Elimination (#2491)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Tue, 4 Dec 2018 10:35:34 +0000 (19:35 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Tue, 4 Dec 2018 10:35:34 +0000 (19:35 +0900)
* [enco] Free Op Elimination

This commit introduces Free Op Elimination pass (and a related test) to
enco pipeline.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
* Use consistent testcase name

contrib/enco/core/src/Backend.cpp
contrib/enco/core/src/Transforms/FreeOpElimination.cpp [new file with mode: 0644]
contrib/enco/core/src/Transforms/FreeOpElimination.h [new file with mode: 0644]
contrib/enco/core/src/Transforms/FreeOpElimination.test.cpp [new file with mode: 0644]

index d97c57e..c0409f2 100644 (file)
@@ -34,6 +34,7 @@
 #include "Transforms/CopyLowering.h"
 #include "Transforms/ConcatLowering.h"
 #include "Transforms/FreeInstrElimination.h"
+#include "Transforms/FreeOpElimination.h"
 #include "Transforms/DeadBagElimination.h"
 #include "Transforms/Optimizations.h"
 #include "Transforms/Split.h"
@@ -129,6 +130,9 @@ void BackendImpl::compile(coco::Module *m, coco::Data *d)
   generate_bypass_shuffle(code(sess));
 
   eliminate_free_instr(code(sess));
+  // NOTE Free Op Elimination should be applied after Free Instr Elimination
+  //      - Free Instr Elimination may generate additional free Op(s)
+  eliminate_free_op(code(sess));
   eliminate_dead_bag(code(sess));
 
   // Split instructions into a set of phases (each block serves as a phase)
diff --git a/contrib/enco/core/src/Transforms/FreeOpElimination.cpp b/contrib/enco/core/src/Transforms/FreeOpElimination.cpp
new file mode 100644 (file)
index 0000000..2bdadfb
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 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 "FreeOpElimination.h"
+
+#include <cassert>
+#include <set>
+#include <queue>
+
+namespace
+{
+
+/**
+ * @brief Return the set of Free Op Elimination candidates
+ */
+std::set<coco::Op *> candidates(const coco::Module *m)
+{
+  std::set<coco::Op *> res;
+
+  for (uint32_t n = 0; n < m->entity()->op()->size(); ++n)
+  {
+    if (auto op = m->entity()->op()->at(n))
+    {
+      if ((op->parent() == nullptr) && (op->up() == nullptr))
+      {
+        res.insert(op);
+      }
+    }
+  }
+
+  return res;
+}
+
+/**
+ * @brief Destroy op tree
+ */
+void destroy(coco::Op *op)
+{
+  assert(coco::root(op) == op);
+  auto m = op->module();
+
+  std::queue<coco::Op *> q;
+
+  q.emplace(op);
+
+  while (q.size() > 0)
+  {
+    auto cur = q.front();
+    q.pop();
+
+    // Insert child op nodes
+    for (uint32_t n = 0; n < cur->arity(); ++n)
+    {
+      q.emplace(cur->arg(n));
+    }
+
+    // Destroy the current op node
+    m->entity()->op()->destroy(cur);
+  }
+}
+
+} // namespace
+
+namespace enco
+{
+
+void eliminate_free_op(coco::Module *m)
+{
+  for (auto op : candidates(m))
+  {
+    destroy(op);
+  }
+}
+
+} // namespace enco
diff --git a/contrib/enco/core/src/Transforms/FreeOpElimination.h b/contrib/enco/core/src/Transforms/FreeOpElimination.h
new file mode 100644 (file)
index 0000000..a9cd315
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 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 __ENCO_TRANSFORM_FREE_OP_ELIMINATION_H__
+#define __ENCO_TRANSFORM_FREE_OP_ELIMINATION_H__
+
+#include "Code.h"
+
+namespace enco
+{
+
+/**
+ * @brief Eliminate free op
+ *
+ * An op is referred to as "free" if it is not bound to any "instruction"
+ */
+void eliminate_free_op(coco::Module *mod);
+
+/**
+ * @brief Eliminate free op
+ */
+static inline void eliminate_free_op(enco::Code *code)
+{
+  // This function is just a wrapper of the above "void eliminate_free_op(coco::Module *mod)"
+  eliminate_free_op(code->module());
+}
+
+} // namespace enco
+
+#endif // __ENCO_TRANSFORM_FREE_OP_ELIMINATION_H__
diff --git a/contrib/enco/core/src/Transforms/FreeOpElimination.test.cpp b/contrib/enco/core/src/Transforms/FreeOpElimination.test.cpp
new file mode 100644 (file)
index 0000000..4160052
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 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 "FreeOpElimination.h"
+
+#include <gtest/gtest.h>
+
+TEST(FreeOpEliminationTest, case_000)
+{
+  auto m = coco::Module::create();
+
+  // Create a "free" Load op
+  m->entity()->op()->create<coco::Load>();
+
+  ASSERT_EQ(m->entity()->op()->size(), 1);
+
+  // Apply "Free Op Elimination"
+  enco::eliminate_free_op(m.get());
+
+  ASSERT_EQ(m->entity()->op()->size(), 0);
+}