[enco] Introduce DuplicatePass (#1177)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Fri, 24 Aug 2018 07:16:29 +0000 (16:16 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 24 Aug 2018 07:16:29 +0000 (16:16 +0900)
This commit introduces DuplicatePass which eliminates a pair of
input/ouput that share the same bag as their underlying bag.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/enco/core/src/Backend.cpp
contrib/enco/core/src/Transforms/Duplicate.cpp [new file with mode: 0644]
contrib/enco/core/src/Transforms/Duplicate.h [new file with mode: 0644]

index 58edd2e..5baf763 100644 (file)
@@ -3,6 +3,8 @@
 #include "Code.h"
 #include "CppCode.h"
 
+#include "Transforms/Duplicate.h"
+
 #include <stdexcept>
 
 namespace
@@ -33,6 +35,13 @@ void Backend::compile(coco::Module *m, coco::Data *d)
 {
   Code code{m, d};
 
+  // As explained below, the current implementation does not work if there is a pair of input/ouput
+  // that share the same bag as their underlying bag.
+  //
+  // This DuplicatePass creates a copy of such bags in order to eliminate such a pair.
+  DuplicatePass duplicate;
+  duplicate.runOnCode(&code);
+
   // The current implementation will assign memory region for each bag as follows:
   //   Bind input bag to the region provided by Network_input_bind
   //   Bind output bag to the region provided by Network_output_bind
diff --git a/contrib/enco/core/src/Transforms/Duplicate.cpp b/contrib/enco/core/src/Transforms/Duplicate.cpp
new file mode 100644 (file)
index 0000000..ab640c9
--- /dev/null
@@ -0,0 +1,99 @@
+#include "Duplicate.h"
+
+#include <map>
+#include <set>
+
+#include <cassert>
+
+namespace
+{
+
+coco::Block *find_or_create_first_block(coco::Module *m)
+{
+  if (m->block()->empty())
+  {
+    auto blk = m->entity()->block()->create();
+    m->block()->append(blk);
+    return blk;
+  }
+
+  return m->block()->head();
+}
+
+} // namespace
+
+namespace enco
+{
+
+void DuplicatePass::runOnModule(coco::Module *m) const
+{
+  // Let's find candidates
+  std::set<coco::Bag *> candidates;
+
+  for (uint32_t n = 0; n < m->entity()->bag()->size(); ++n)
+  {
+    auto bag = m->entity()->bag()->at(n);
+
+    if (bag->isInput() && bag->isOutput())
+    {
+      candidates.insert(bag);
+    }
+  }
+
+  // Return if there is no candidate
+  if (candidates.empty())
+  {
+    return;
+  }
+
+  std::map<const coco::Bag *, coco::Input *> input_map;
+  std::map<const coco::Bag *, coco::Output *> output_map;
+
+  for (uint32_t n = 0; n < m->input()->size(); ++n)
+  {
+    auto input = m->input()->at(n);
+    assert(input->bag() != nullptr);
+    input_map[input->bag()] = input;
+  }
+
+  for (uint32_t n = 0; n < m->output()->size(); ++n)
+  {
+    auto output = m->output()->at(n);
+    assert(output->bag() != nullptr);
+    output_map[output->bag()] = output;
+  }
+
+  // For each in/out bag,
+  //   1. Create a new bag of the same size
+  //   2. Copy the content from the original bag
+  //   3. Mark the newly created bag as an output
+  for (const auto &candidate : candidates)
+  {
+    assert(candidate->updates().empty());
+    assert(input_map.find(candidate) != input_map.end());
+    assert(output_map.find(candidate) != output_map.end());
+
+    auto src = candidate;
+    auto dst = m->entity()->bag()->create(src->size());
+
+    // Create a copy instruction
+    auto shuffle = m->entity()->instr()->create<coco::Shuffle>();
+
+    shuffle->from(src);
+    shuffle->into(dst);
+
+    for (uint32_t n = 0; n < src->size(); ++n)
+    {
+      shuffle->at(n) = coco::ElemID{n};
+    }
+
+    find_or_create_first_block(m)->instr()->prepend(shuffle);
+
+    // Let's use the new bag as an output
+    output_map.at(src)->bag(dst);
+  }
+}
+
+void DuplicatePass::runOnCode(Code *code) const { runOnModule(code->module()); }
+
+} // namespace enco
diff --git a/contrib/enco/core/src/Transforms/Duplicate.h b/contrib/enco/core/src/Transforms/Duplicate.h
new file mode 100644 (file)
index 0000000..ede2109
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __DUPLICATE_H__
+#define __DUPLICATE_H__
+
+#include "Code.h"
+
+namespace enco
+{
+
+/**
+ * @brief Eliminate in/out bags by duplication
+ */
+class DuplicatePass
+{
+private:
+  void runOnModule(coco::Module *m) const;
+
+public:
+  void runOnCode(enco::Code *) const;
+};
+
+} // namespace enco
+
+#endif // __DUPLICATE_H__