#include "Split.h"
+#include "Usage.h"
#include <coco/IR.h>
-namespace
-{
-
-enum Compatibility
-{
- COMPATIBLE,
- INCOMPATIBLE
-};
-
-class ANNGroupBuilder
-{
-public:
- ANNGroupBuilder(enco::Code *code) : _code{code}
- {
- // DO NOTHING
- }
-
-public:
- Compatibility kind(const coco::Instr *ins) const;
- Compatibility kind(const coco::Block *blk) const;
-
-public:
- void build(void) const;
-
-private:
- enco::Code *_code;
-};
-
-Compatibility ANNGroupBuilder::kind(const coco::Instr *ins) const
-{
- struct CompatibilityCheck final : public coco::Instr::DefaultVisitor<bool>,
- public coco::Op::DefaultVisitor<bool>
- {
- //
- // Instruction
- //
- bool visit(const coco::UnitF *unit) override
- {
- // TODO Check data layout
- return unit->op()->accept(this);
- }
-
- bool visit(const coco::Shuffle *) override
- {
- // TODO Distinguish Reshape
- return false;
- }
-
- //
- // Op
- //
- bool visit(const coco::Conv2D *) override
- {
- // TODO Check data layout
- return true;
- }
-
- bool visit(const coco::MaxPool2D *) override
- {
- // TODO Check data layout
- return true;
- }
-
- bool visit(const coco::AvgPool2D *avgpool) override
- {
- if (avgpool->divisor() != coco::AvgPool2D::Divisor::PaddingExcluded)
- {
- // When ANN runtime computes the average of each receptive field,
- // it uses the number of valid(=non-padding) elements as a divisor.
- return false;
- }
-
- // TODO Check data layout
- return true;
- }
-
- bool visit(const coco::ReLU *) override
- {
- // TODO Check data layout
- return true;
- }
-
- bool visit(const coco::PadF *) override
- {
- // TODO Check data layout
- return true;
- }
- };
-
- return ins->accept(CompatibilityCheck{}) ? COMPATIBLE : INCOMPATIBLE;
-}
-
-Compatibility ANNGroupBuilder::kind(const coco::Block *blk) const
-{
- return (_code->ann()->find(blk) != nullptr) ? COMPATIBLE : INCOMPATIBLE;
-}
-
-void ANNGroupBuilder::build(void) const
-{
- auto m = _code->module();
-
- // ANNGroupBuilder will construct a sequence of blocks from the original block sequence, and
- // a destination block (that dst_blk points to) is the tail of the generated sequence.
- coco::Block *dst_blk = nullptr;
-
- auto append = [&](const Compatibility &t) {
- auto blk = m->entity()->block()->create();
-
- if (dst_blk == nullptr)
- {
- m->block()->prepend(blk);
- }
- else
- {
- blk->insertAfter(dst_blk);
- }
-
- dst_blk = blk;
-
- if (COMPATIBLE == t)
- {
- _code->ann()->create(blk);
- }
- };
-
- for (auto blk = m->block()->head(); blk;)
- {
- // Let's move instructions from a block of interest (referred to as source block) into
- // a destination block
- auto src_blk = blk;
- blk = src_blk->next();
- src_blk->detach();
-
- for (auto ins = src_blk->instr()->head(); ins;)
- {
- auto cur_ins = ins;
- ins = cur_ins->next();
- cur_ins->detach();
-
- // Create a new compatible block and use it as a destination block if the current
- // destination block is absent or incompatible with the instruction of intereset.
- if ((dst_blk == nullptr) || (kind(cur_ins) != kind(dst_blk)))
- {
- append(kind(cur_ins));
- }
-
- assert(dst_blk != nullptr);
- assert(kind(cur_ins) == kind(dst_blk));
-
- // Append ins to the dst_blk block
- dst_blk->instr()->append(cur_ins);
- }
-
- // Destroy the source block
- assert(src_blk->instr()->empty());
- m->entity()->block()->destroy(src_blk);
- }
-}
-
-} // namespace
-
-#include "Usage.h"
+#include <nncc/core/ADT/kernel/NHWCLayout.h>
#include <stdexcept>
#include <functional>
-#include <nncc/core/ADT/kernel/NHWCLayout.h>
-
namespace
{
coco::Data *const _data;
};
+namespace
+{
+
+enum Compatibility
+{
+ COMPATIBLE,
+ INCOMPATIBLE
+};
+
+class ANNGroupBuilder
+{
+public:
+ ANNGroupBuilder(enco::Code *code) : _code{code}
+ {
+ // DO NOTHING
+ }
+
+public:
+ Compatibility kind(const coco::Instr *ins) const;
+ Compatibility kind(const coco::Block *blk) const;
+
+public:
+ void build(void) const;
+
+private:
+ enco::Code *_code;
+};
+
+Compatibility ANNGroupBuilder::kind(const coco::Instr *ins) const
+{
+ struct CompatibilityCheck final : public coco::Instr::DefaultVisitor<bool>,
+ public coco::Op::DefaultVisitor<bool>
+ {
+ //
+ // Instruction
+ //
+ bool visit(const coco::UnitF *unit) override
+ {
+ // TODO Check data layout
+ return unit->op()->accept(this);
+ }
+
+ bool visit(const coco::Shuffle *) override
+ {
+ // TODO Distinguish Reshape
+ return false;
+ }
+
+ //
+ // Op
+ //
+ bool visit(const coco::Conv2D *) override
+ {
+ // TODO Check data layout
+ return true;
+ }
+
+ bool visit(const coco::MaxPool2D *) override
+ {
+ // TODO Check data layout
+ return true;
+ }
+
+ bool visit(const coco::AvgPool2D *avgpool) override
+ {
+ if (avgpool->divisor() != coco::AvgPool2D::Divisor::PaddingExcluded)
+ {
+ // When ANN runtime computes the average of each receptive field,
+ // it uses the number of valid(=non-padding) elements as a divisor.
+ return false;
+ }
+
+ // TODO Check data layout
+ return true;
+ }
+
+ bool visit(const coco::ReLU *) override
+ {
+ // TODO Check data layout
+ return true;
+ }
+
+ bool visit(const coco::PadF *) override
+ {
+ // TODO Check data layout
+ return true;
+ }
+ };
+
+ return ins->accept(CompatibilityCheck{}) ? COMPATIBLE : INCOMPATIBLE;
+}
+
+Compatibility ANNGroupBuilder::kind(const coco::Block *blk) const
+{
+ return (_code->ann()->find(blk) != nullptr) ? COMPATIBLE : INCOMPATIBLE;
+}
+
+void ANNGroupBuilder::build(void) const
+{
+ auto m = _code->module();
+
+ // ANNGroupBuilder will construct a sequence of blocks from the original block sequence, and
+ // a destination block (that dst_blk points to) is the tail of the generated sequence.
+ coco::Block *dst_blk = nullptr;
+
+ auto append = [&](const Compatibility &t) {
+ auto blk = m->entity()->block()->create();
+
+ if (dst_blk == nullptr)
+ {
+ m->block()->prepend(blk);
+ }
+ else
+ {
+ blk->insertAfter(dst_blk);
+ }
+
+ dst_blk = blk;
+
+ if (COMPATIBLE == t)
+ {
+ _code->ann()->create(blk);
+ }
+ };
+
+ for (auto blk = m->block()->head(); blk;)
+ {
+ // Let's move instructions from a block of interest (referred to as source block) into
+ // a destination block
+ auto src_blk = blk;
+ blk = src_blk->next();
+ src_blk->detach();
+
+ for (auto ins = src_blk->instr()->head(); ins;)
+ {
+ auto cur_ins = ins;
+ ins = cur_ins->next();
+ cur_ins->detach();
+
+ // Create a new compatible block and use it as a destination block if the current
+ // destination block is absent or incompatible with the instruction of intereset.
+ if ((dst_blk == nullptr) || (kind(cur_ins) != kind(dst_blk)))
+ {
+ append(kind(cur_ins));
+ }
+
+ assert(dst_blk != nullptr);
+ assert(kind(cur_ins) == kind(dst_blk));
+
+ // Append ins to the dst_blk block
+ dst_blk->instr()->append(cur_ins);
+ }
+
+ // Destroy the source block
+ assert(src_blk->instr()->empty());
+ m->entity()->block()->destroy(src_blk);
+ }
+}
+
+} // namespace
+
class ANNModuleBuilder
{
public: