1919
2020/* !
2121 * \file extract_constants.cc
22- * \brief Collects constants from PrimFunc
23- TODO:
24- For more information, see the RFC:
25- TODO
26- https://discuss.tvm.apache.org/t/rfc-introducing-a-rolling-buffer-scheduling-primitive/9836
22+ * \brief Collects PrimFunc's constant data into mod's 'tvm::attr::kConstantsArray' attrs array,
23+ * sets irmod_storage_idx as index in this array.
24+ * For more information, see the RFC:
25+ * https://github.com/apache/tvm-rfcs/blob/main/rfcs/0022-tir-non-scalar-constants.md
2726 */
2827#include < tvm/arith/analyzer.h>
28+ #include < tvm/ir/transform.h>
2929#include < tvm/runtime/registry.h>
3030#include < tvm/tir/stmt_functor.h>
31- #include < tvm/tir/transform.h>
3231
3332#include " ir_utils.h"
3433
3534namespace tvm {
3635namespace tir {
3736
38- // Replaces constant data to index into mod's "Constants" attrs array.
39- // Only processes tir::PrimFunc and ignores everything else
4037using ConstArrayType = Array<runtime::NDArray>;
41- class Applicator : public tir ::StmtExprVisitor {
38+ class Applicator : public tir ::StmtMutator {
4239 protected:
4340 // returns index of the a in constant_array_, if not found - appends
44- size_t deDup (const runtime::NDArray& a) {
41+ size_t DeDup (const runtime::NDArray& a) {
4542 tvm::SEqualReducer eql;
4643 auto it = std::find_if (
4744 constant_array_.begin (), constant_array_.end (), [&eql, a](const runtime::NDArray& v) {
@@ -56,32 +53,28 @@ class Applicator : public tir::StmtExprVisitor {
5653 }
5754
5855 public:
59- ConstArrayType Apply (tir::Stmt body, const ConstArrayType& constant_array) {
56+ Stmt Apply (tir::Stmt body, const ConstArrayType& constant_array) {
6057 constant_array_ = constant_array;
61- this ->VisitStmt (body);
62- return constant_array_;
58+ return this ->VisitStmt (body);
6359 }
6460
65- void VisitStmt_ (const tir::AllocateConstNode* acn) override {
66- tir::AllocateConstNode* node = const_cast <tir::AllocateConstNode*>(acn);
61+ Stmt VisitStmt_ (const tir::AllocateConstNode* acn) override {
6762 // Check whether the data already defined within the module's attrs
68- // and replace it with array index;
69- ICHECK (node->data ) << " data field should be defined" ;
70- if (node->data ) {
71- node->irmod_storage_idx = Optional<Integer>(Integer (deDup (node->data .value ())));
72- }
73- tir::StmtExprVisitor::VisitStmt_ (acn);
63+ // and add array index.
64+ ICHECK (acn->data ) << " data field should be defined" ;
65+ auto node = CopyOnWrite (acn);
66+ node->irmod_storage_idx = Optional<Integer>(Integer (DeDup (node->data .value ())));
67+ return Stmt (node);
7468 }
7569
76- private:
7770 ConstArrayType constant_array_;
7871};
7972
8073namespace transform {
8174
82- Pass ExtractPrimFuncConstants () {
83- auto pass_func = [=](PrimFunc f , IRModule m, PassContext ctx) {
84- auto * func = f .CopyOnWrite ();
75+ tvm::transform:: Pass ExtractPrimFuncConstants () {
76+ auto prim_func_pass = [=](PrimFunc foo , IRModule m, tvm::transform:: PassContext ctx) {
77+ auto * func = foo .CopyOnWrite ();
8578 if (!m->attrs .defined ()) {
8679 m->attrs = DictAttrs (Map<String, ObjectRef>());
8780 }
@@ -90,14 +83,27 @@ Pass ExtractPrimFuncConstants() {
9083 (attrs->dict .count (tvm::attr::kConstantsArray ))
9184 ? Downcast<ConstArrayType>(attrs->dict [tvm::attr::kConstantsArray ])
9285 : ConstArrayType ();
93-
94- const ConstArrayType constant_list = Applicator ().Apply (func->body , constant_array_);
86+ Applicator a = Applicator ();
87+ func->body = a.Apply (func->body , constant_array_);
88+ const ConstArrayType constant_list = a.constant_array_ ;
9589 if (constant_list.size ()) {
9690 attrs->dict .Set (tvm::attr::kConstantsArray , constant_list);
9791 }
98- return f;
92+ return GetRef<PrimFunc>(func);
93+ };
94+
95+ auto pass_func = [=](IRModule module , tvm::transform::PassContext pc) {
96+ auto m = GetRef<IRModule>(module .CopyOnWrite ());
97+ for (const auto & kv : m->functions ) {
98+ BaseFunc f = kv.second ;
99+ if (f->IsInstance <PrimFuncNode>()) {
100+ m->Update (kv.first , prim_func_pass (GetRef<PrimFunc>(f.as <PrimFuncNode>()), m, pc));
101+ }
102+ }
103+ return m;
99104 };
100- return CreatePrimFuncPass (pass_func, 0 , " tir.ExtractPrimFuncConstants" , {});
105+
106+ return tvm::transform::CreateModulePass (pass_func, 0 , " tir.ExtractPrimFuncConstants" , {});
101107}
102108
103109TVM_REGISTER_GLOBAL (" tir.transform.ExtractPrimFuncConstants" )
0 commit comments