From: 박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 Date: Tue, 28 Aug 2018 03:03:39 +0000 (+0900) Subject: [enco] Introduce Split pass (#1200) X-Git-Tag: nncc_backup~2044 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9473231641f4cf13facd65d6e9b4e13c8db7aeb;p=platform%2Fcore%2Fml%2Fnnfw.git [enco] Introduce Split pass (#1200) This commit introduces Split pass which split a sequence of instructions into a sequence of phases. This Split pass marks aome of phases as Andoird NN compatible if all the op/instruction in it have a correponds Andoird NN operation. Signed-off-by: Jonghyun Park --- diff --git a/contrib/enco/core/src/Backend.cpp b/contrib/enco/core/src/Backend.cpp index 02a7e8d..d0e3142 100644 --- a/contrib/enco/core/src/Backend.cpp +++ b/contrib/enco/core/src/Backend.cpp @@ -5,6 +5,7 @@ #include "Transforms/Duplicate.h" #include "Transforms/Normalize.h" +#include "Transforms/Split.h" #include @@ -56,6 +57,10 @@ void Backend::compile(coco::Module *m, coco::Data *d) NormalizePass normalize; normalize.runOnCode(&code); + // Split instructions into a set of phases (each block serves as a phase) + SplitPass split; + split.runOnCode(&code); + // TODO Run various transforms over enco::Code _os << CppCode{&code} << std::endl; diff --git a/contrib/enco/core/src/Transforms/Split.cpp b/contrib/enco/core/src/Transforms/Split.cpp new file mode 100644 index 0000000..b99be04 --- /dev/null +++ b/contrib/enco/core/src/Transforms/Split.cpp @@ -0,0 +1,146 @@ +#include "Split.h" + +#include + +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::Visitor, + public coco::Op::Visitor + { + // + // 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; + } + }; + + 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 + +namespace enco +{ + +void SplitPass::runOnCode(enco::Code *code) const +{ + ANNGroupBuilder group_builder{code}; + group_builder.build(); + + // TODO Construct Android NN module for each compatible block +} + +} // namespace enco diff --git a/contrib/enco/core/src/Transforms/Split.h b/contrib/enco/core/src/Transforms/Split.h new file mode 100644 index 0000000..4781919 --- /dev/null +++ b/contrib/enco/core/src/Transforms/Split.h @@ -0,0 +1,20 @@ +#ifndef __SPLIT_H__ +#define __SPLIT_H__ + +#include "Code.h" + +namespace enco +{ + +/** + * @brief Split instructions into a set of phases + */ +class SplitPass +{ +public: + void runOnCode(enco::Code *code) const; +}; + +} // namespace enco; + +#endif // __SPLIT_H__