summaryrefslogtreecommitdiff
path: root/compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp')
-rw-r--r--compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp b/compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp
new file mode 100644
index 000000000..cb996d2ac
--- /dev/null
+++ b/compiler/enco/core/src/Transforms/IdenticalObjectReduction.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 "IdenticalObjectReduction.h"
+#include "IRUtils.h"
+
+#include <set>
+
+namespace enco
+{
+
+void reduce_identical_object(enco::Code *code)
+{
+ auto m = code->module();
+
+ std::set<coco::Copy *> detached;
+
+ // Preceding optimizations may generate "free" instructions.
+ // - i.e. an instruction not linked to a block
+ //
+ // Let's iterate over only a sequence of "bounded" instructions.
+ for (auto ins : instr_sequence(m))
+ {
+ assert(ins != nullptr);
+ assert(ins->parent() != nullptr);
+
+ auto copy = ins->asCopy();
+
+ if (copy == nullptr)
+ {
+ // Skip if instruction is not a copy
+ continue;
+ }
+
+ // TODO Support non-Feature Objects
+ auto ifm = copy->from()->asFeature();
+ auto ofm = copy->into()->asFeature();
+
+ assert(ofm->bag() != nullptr);
+
+ if (ifm->layout()->id() != ofm->layout()->id())
+ {
+ continue;
+ }
+
+ if (ifm->layout()->id() != coco::FeatureLayouts::BHWC::uid())
+ {
+ continue;
+ }
+
+ // Skip if this copy produces network output
+ if (ofm->bag()->output())
+ {
+ // TODO Optimize this case
+ //
+ // Note that the code under optimization is of the following form:
+ //
+ // %ifm <- Instr(...)
+ // %ofm <- Copy(%ifm)
+ //
+ // Let's assume that "Copy" is the only reader of %ifm (to be precise, its bag).
+ //
+ // Then, it is possible to rewrite the above fragment as follows:
+ //
+ // %ofm <- Instr(...)
+ //
+ continue;
+ }
+
+ if (ofm->bag()->reads()->size() > 0)
+ {
+ // Let us consider the following code:
+ //
+ // Bag:
+ // %bag_0 = Bag(...)
+ // %bag_1 = Bag(...)
+ // %bag_2 = Bag(...)
+ //
+ // Object:
+ // %obj_0 = FeatureObject(bag: %bag_0)
+ // %obj_1 = FeatureObject(bag: %bag_1)
+ //
+ // Instr:
+ // copy an object from %obj_0 into %obj_1
+ // shuffle values from %bag_1 into %bag_2
+ // eval Conv2D with %obj_1
+ //
+ // Identical Object Reduction (IOR) tries to eliminate the first copy via
+ // substitution (substitute all the occurrence of %obj_1 as use with %obj_0).
+ //
+ // Here is the code transformed by IOR:
+ //
+ // Bag:
+ // %bag_0 = Bag(...)
+ // %bag_1 = Bag(...)
+ // %bag_2 = Bag(...)
+ //
+ // Object:
+ // %obj_0 = FeatureObject(bag: %bag_0)
+ // %obj_1 = FeatureObject(bag: %bag_1)
+ //
+ // Instr:
+ // shuffle values from %bag_1 into %bag_2
+ // eval Conv2D with %obj_0
+ //
+ // Note that there is no updater of %bag_1 after IOR, and thus the behavior
+ // of the first shuffle instruction has changed.
+ //
+ // This examples shows that it is impossible to simply substitute %obj_1
+ // with %obj_0 in the presence of readers over its backing bag.
+ continue;
+ }
+
+ subst(copy->into(), copy->from());
+
+ copy->detach();
+ detached.insert(copy);
+ }
+
+ for (auto copy : detached)
+ {
+ m->entity()->instr()->destroy(copy);
+ }
+}
+
+} // namespace enco