From 4798284f34b6b3d732e64572d80af2a0d6a1de99 Mon Sep 17 00:00:00 2001 From: tqchen Date: Sun, 5 Jan 2020 16:21:04 -0800 Subject: [PATCH] [REFACTOR] Remove Block --- include/tvm/ir.h | 22 -------- include/tvm/ir_functor_ext.h | 4 -- python/tvm/stmt.py | 20 ------- src/api/api_ir.cc | 3 -- src/codegen/codegen_c.cc | 5 -- src/codegen/codegen_c.h | 1 - src/codegen/llvm/codegen_llvm.cc | 7 --- src/codegen/llvm/codegen_llvm.h | 1 - src/codegen/spirv/codegen_spirv.cc | 7 --- src/codegen/spirv/codegen_spirv.h | 1 - src/codegen/stackvm/codegen_stackvm.cc | 5 -- src/codegen/stackvm/codegen_stackvm.h | 1 - src/contrib/hybrid/codegen_hybrid.cc | 5 -- src/contrib/hybrid/codegen_hybrid.h | 1 - src/lang/ir.cc | 35 ------------ src/pass/inject_virtual_thread.cc | 16 +----- src/pass/ir_deep_compare.cc | 7 --- src/pass/ir_functor.cc | 19 ------- src/pass/ir_util.cc | 5 -- src/pass/lift_attr_scope.cc | 75 -------------------------- src/pass/loop_partition.cc | 10 ---- src/pass/remove_no_op.cc | 12 ----- src/pass/unroll_loop.cc | 22 -------- 23 files changed, 1 insertion(+), 283 deletions(-) diff --git a/include/tvm/ir.h b/include/tvm/ir.h index 03c66a80bfd7c..9c31721600975 100644 --- a/include/tvm/ir.h +++ b/include/tvm/ir.h @@ -1120,28 +1120,6 @@ class SeqStmt : public Stmt { TVM_DEFINE_OBJECT_REF_METHODS(SeqStmt, Stmt, SeqStmtNode); }; -/*! - * \brief A sequence of statements. - */ -class Block : public StmtNode { - public: - /*! \brief The first statement. */ - Stmt first; - /*! \brief The restof statments. */ - Stmt rest; - - void VisitAttrs(AttrVisitor* v) { - v->Visit("first", &first); - v->Visit("rest", &rest); - } - - TVM_DLL static Stmt make(Stmt first, Stmt rest); - TVM_DLL static Stmt make(const std::vector &stmts); - - static constexpr const char* _type_key = "Block"; - TVM_DECLARE_FINAL_OBJECT_INFO(Block, StmtNode); -}; - /*! * \brief IfThenElse statment. */ diff --git a/include/tvm/ir_functor_ext.h b/include/tvm/ir_functor_ext.h index 5462e8799f619..6cc6d702c7cde 100644 --- a/include/tvm/ir_functor_ext.h +++ b/include/tvm/ir_functor_ext.h @@ -253,7 +253,6 @@ class StmtFunctor { virtual R VisitStmt_(const Provide* op, Args... args) STMT_FUNCTOR_DEFAULT; virtual R VisitStmt_(const Realize* op, Args... args) STMT_FUNCTOR_DEFAULT; virtual R VisitStmt_(const Prefetch* op, Args... args) STMT_FUNCTOR_DEFAULT; - virtual R VisitStmt_(const Block* op, Args... args) STMT_FUNCTOR_DEFAULT; virtual R VisitStmt_(const SeqStmtNode* op, Args... args) STMT_FUNCTOR_DEFAULT; virtual R VisitStmt_(const Evaluate* op, Args... args) STMT_FUNCTOR_DEFAULT; virtual R VisitStmtDefault_(const Object* op, Args ...) { @@ -277,7 +276,6 @@ class StmtFunctor { IR_STMT_FUNCTOR_DISPATCH(Provide); IR_STMT_FUNCTOR_DISPATCH(Realize); IR_STMT_FUNCTOR_DISPATCH(Prefetch); - IR_STMT_FUNCTOR_DISPATCH(Block); IR_STMT_FUNCTOR_DISPATCH(SeqStmtNode); IR_STMT_FUNCTOR_DISPATCH(Evaluate); return vtable; @@ -410,7 +408,6 @@ class TVM_DLL StmtVisitor : void VisitStmt_(const Provide* op) override; void VisitStmt_(const Realize* op) override; void VisitStmt_(const Prefetch* op) override; - void VisitStmt_(const Block* op) override; void VisitStmt_(const SeqStmtNode* op) override; void VisitStmt_(const Evaluate* op) override; }; @@ -505,7 +502,6 @@ class TVM_DLL StmtMutator : Stmt VisitStmt_(const Provide* op) override; Stmt VisitStmt_(const Realize* op) override; Stmt VisitStmt_(const Prefetch* op) override; - Stmt VisitStmt_(const Block* op) override; Stmt VisitStmt_(const SeqStmtNode* op) override; Stmt VisitStmt_(const Evaluate* op) override; /*! diff --git a/python/tvm/stmt.py b/python/tvm/stmt.py index 3073e86cd8901..64628d1d41987 100644 --- a/python/tvm/stmt.py +++ b/python/tvm/stmt.py @@ -288,23 +288,6 @@ def __init__(self, bounds, condition, body) -@register_node -class Block(Stmt): - """Block node. - - Parameters - ---------- - first : Stmt - The first statement. - - rest : Stmt - The following statement. - """ - def __init__(self, first, rest): - self.__init_handle_by_constructor__( - _make.Block, first, rest) - - @register_node class SeqStmt(Stmt): """Sequence of statements. @@ -422,12 +405,9 @@ def stmt_list(stmt): for x in stmt: res += stmt_list(x) return res - elif isinstance(stmt, Block): - return stmt_list(stmt.first) + stmt_list(stmt.rest) if isinstance(stmt, ProducerConsumer): return stmt_list(stmt.body) return [stmt] _make.stmt_list = stmt_list -_make.stmt_seq = stmt_seq diff --git a/src/api/api_ir.cc b/src/api/api_ir.cc index 2b98f45095ca7..25325b515e408 100644 --- a/src/api/api_ir.cc +++ b/src/api/api_ir.cc @@ -169,9 +169,6 @@ REGISTER_MAKE(IfThenElse); REGISTER_MAKE(Evaluate); // overloaded, needs special handling -TVM_REGISTER_GLOBAL("make.Block") - .set_body_typed(static_cast(Block::make)); - // has default args TVM_REGISTER_GLOBAL("make.Allocate") .set_body_typed, Expr, Stmt)>([]( diff --git a/src/codegen/codegen_c.cc b/src/codegen/codegen_c.cc index 2c24e07eb5d67..a3f145994f2ca 100644 --- a/src/codegen/codegen_c.cc +++ b/src/codegen/codegen_c.cc @@ -875,11 +875,6 @@ void CodeGenC::VisitStmt_(const IfThenElse* op) { stream << "}\n"; } -void CodeGenC::VisitStmt_(const Block* op) { - PrintStmt(op->first); - if (op->rest.defined()) PrintStmt(op->rest); -} - void CodeGenC::VisitStmt_(const SeqStmtNode* op) { for (Stmt stmt : op->seq) { PrintStmt(stmt); diff --git a/src/codegen/codegen_c.h b/src/codegen/codegen_c.h index 1773bcbfd88fd..eae1e4961b773 100644 --- a/src/codegen/codegen_c.h +++ b/src/codegen/codegen_c.h @@ -140,7 +140,6 @@ class CodeGenC : void VisitStmt_(const AttrStmt* op) override; void VisitStmt_(const AssertStmt* op) override; void VisitStmt_(const Evaluate* op) override; - void VisitStmt_(const Block* op) override; void VisitStmt_(const SeqStmtNode* op) override; void VisitStmt_(const ProducerConsumer* op) override; /*! diff --git a/src/codegen/llvm/codegen_llvm.cc b/src/codegen/llvm/codegen_llvm.cc index 9461eee0ee8cc..b0d86a9f66ce1 100644 --- a/src/codegen/llvm/codegen_llvm.cc +++ b/src/codegen/llvm/codegen_llvm.cc @@ -1214,13 +1214,6 @@ void CodeGenLLVM::VisitStmt_(const LetStmt* op) { this->VisitStmt(op->body); } -void CodeGenLLVM::VisitStmt_(const Block* op) { - this->VisitStmt(op->first); - if (op->rest.defined()) { - this->VisitStmt(op->rest); - } -} - void CodeGenLLVM::VisitStmt_(const SeqStmtNode* op) { for (Stmt stmt : op->seq) { this->VisitStmt(stmt); diff --git a/src/codegen/llvm/codegen_llvm.h b/src/codegen/llvm/codegen_llvm.h index 56a710392497c..076ffb2af5880 100644 --- a/src/codegen/llvm/codegen_llvm.h +++ b/src/codegen/llvm/codegen_llvm.h @@ -140,7 +140,6 @@ class CodeGenLLVM : void VisitStmt_(const AttrStmt* op) override; void VisitStmt_(const AssertStmt* op) override; void VisitStmt_(const LetStmt* op) override; - void VisitStmt_(const Block* op) override; void VisitStmt_(const SeqStmtNode* op) override; void VisitStmt_(const Evaluate* op) override; void VisitStmt_(const ProducerConsumer* op) override; diff --git a/src/codegen/spirv/codegen_spirv.cc b/src/codegen/spirv/codegen_spirv.cc index 38235a8c81bfb..7056780d6fceb 100644 --- a/src/codegen/spirv/codegen_spirv.cc +++ b/src/codegen/spirv/codegen_spirv.cc @@ -638,13 +638,6 @@ void CodeGenSPIRV::VisitStmt_(const LetStmt* op) { this->VisitStmt(op->body); } -void CodeGenSPIRV::VisitStmt_(const Block* op) { - VisitStmt(op->first); - if (op->rest.defined()) { - this->VisitStmt(op->rest); - } -} - void CodeGenSPIRV::VisitStmt_(const SeqStmtNode* op) { for (Stmt stmt : op->seq) { PrintStmt(stmt); diff --git a/src/codegen/spirv/codegen_spirv.h b/src/codegen/spirv/codegen_spirv.h index b2f3fc3ad99ee..5cd88c9f267af 100644 --- a/src/codegen/spirv/codegen_spirv.h +++ b/src/codegen/spirv/codegen_spirv.h @@ -98,7 +98,6 @@ class CodeGenSPIRV: void VisitStmt_(const AttrStmt* op) override; void VisitStmt_(const AssertStmt* op) override; void VisitStmt_(const LetStmt* op) override; - void VisitStmt_(const Block* op) override; void VisitStmt_(const SeqStmtNode* op) override; void VisitStmt_(const Evaluate* op) override; void VisitStmt_(const ProducerConsumer* op) override; diff --git a/src/codegen/stackvm/codegen_stackvm.cc b/src/codegen/stackvm/codegen_stackvm.cc index e0cda5d03f947..23bb008a0e7e9 100644 --- a/src/codegen/stackvm/codegen_stackvm.cc +++ b/src/codegen/stackvm/codegen_stackvm.cc @@ -417,11 +417,6 @@ void CodeGenStackVM::VisitStmt_(const For* op) { this->SetOperand(backward_jump, loop_head - label_bjump); } -void CodeGenStackVM::VisitStmt_(const Block* op) { - this->Push(op->first); - if (op->rest.defined()) this->Push(op->rest); -} - void CodeGenStackVM::VisitStmt_(const SeqStmtNode* op) { for (Stmt stmt : op->seq) { this->Push(stmt); diff --git a/src/codegen/stackvm/codegen_stackvm.h b/src/codegen/stackvm/codegen_stackvm.h index 63f354d4bffc4..7a4c0ab797fd5 100644 --- a/src/codegen/stackvm/codegen_stackvm.h +++ b/src/codegen/stackvm/codegen_stackvm.h @@ -148,7 +148,6 @@ class CodeGenStackVM void VisitStmt_(const AttrStmt* op) final; void VisitStmt_(const AssertStmt* op) final; void VisitStmt_(const Evaluate* op) final; - void VisitStmt_(const Block* op) final; void VisitStmt_(const SeqStmtNode* op) final; void VisitStmt_(const ProducerConsumer* op) final; diff --git a/src/contrib/hybrid/codegen_hybrid.cc b/src/contrib/hybrid/codegen_hybrid.cc index d88716bc343d3..00b2c230c5bb6 100644 --- a/src/contrib/hybrid/codegen_hybrid.cc +++ b/src/contrib/hybrid/codegen_hybrid.cc @@ -389,11 +389,6 @@ void CodeGenHybrid::VisitStmt_(const IfThenElse* op) { } } -void CodeGenHybrid::VisitStmt_(const Block* op) { - PrintStmt(op->first); - if (op->rest.defined()) PrintStmt(op->rest); -} - void CodeGenHybrid::VisitStmt_(const SeqStmtNode* op) { for (Stmt stmt : op->seq) { PrintStmt(stmt); diff --git a/src/contrib/hybrid/codegen_hybrid.h b/src/contrib/hybrid/codegen_hybrid.h index 8fb2dcd1cae6f..27c97c73e3330 100644 --- a/src/contrib/hybrid/codegen_hybrid.h +++ b/src/contrib/hybrid/codegen_hybrid.h @@ -131,7 +131,6 @@ class CodeGenHybrid : void VisitStmt_(const AttrStmt* op) override; void VisitStmt_(const AssertStmt* op) override; void VisitStmt_(const Evaluate* op) override; - void VisitStmt_(const Block* op) override; void VisitStmt_(const SeqStmtNode* op) override; void VisitStmt_(const ProducerConsumer* op) override; /*! diff --git a/src/lang/ir.cc b/src/lang/ir.cc index 08167affac00e..de047f330630b 100644 --- a/src/lang/ir.cc +++ b/src/lang/ir.cc @@ -510,33 +510,6 @@ SeqStmt::SeqStmt(Array seq) { data_ = std::move(node); } -Stmt Block::make(Stmt first, Stmt rest) { - CHECK(first.defined()); - CHECK(rest.defined()); - ObjectPtr node = make_object(); - - // canonicalize. - if (const Block* b = first.as()) { - node->first = b->first; - node->rest = Block::make(b->rest, rest); - } else { - node->first = std::move(first); - node->rest = std::move(rest); - } - return Stmt(node); -} - -Stmt Block::make(const std::vector& stmts) { - if (stmts.empty()) { - return Stmt(); - } - Stmt result = stmts.back(); - for (size_t i = stmts.size() - 1; i != 0; --i) { - result = Block::make(stmts[i - 1], result); - } - return result; -} - Stmt IfThenElse::make(Expr condition, Stmt then_case, Stmt else_case) { CHECK(condition.defined()); CHECK(then_case.defined()); @@ -1037,13 +1010,6 @@ TVM_STATIC_IR_FUNCTOR(NodePrinter, vtable) } }); -TVM_STATIC_IR_FUNCTOR(NodePrinter, vtable) -.set_dispatch([](const ObjectRef& node, NodePrinter* p) { - auto* op = static_cast(node.get()); - p->Print(op->first); - if (op->rest.defined()) p->Print(op->rest); - }); - TVM_STATIC_IR_FUNCTOR(NodePrinter, vtable) .set_dispatch([](const ObjectRef& node, NodePrinter* p) { auto* op = static_cast(node.get()); @@ -1226,7 +1192,6 @@ TVM_REGISTER_NODE_TYPE(Provide); TVM_REGISTER_NODE_TYPE(Allocate); TVM_REGISTER_NODE_TYPE(Free); TVM_REGISTER_NODE_TYPE(Realize); -TVM_REGISTER_NODE_TYPE(Block); TVM_REGISTER_NODE_TYPE(SeqStmtNode); TVM_REGISTER_NODE_TYPE(IfThenElse); TVM_REGISTER_NODE_TYPE(Evaluate); diff --git a/src/pass/inject_virtual_thread.cc b/src/pass/inject_virtual_thread.cc index 848aa8f8e34e7..0887a83c1a48d 100644 --- a/src/pass/inject_virtual_thread.cc +++ b/src/pass/inject_virtual_thread.cc @@ -356,21 +356,7 @@ class VTInjector : public StmtExprMutator { return IfThenElse::make(condition, then_case, else_case); } } - // Block - Stmt VisitStmt_(const Block* op) final { - CHECK_EQ(max_loop_depth_, 0); - Stmt first = this->VisitStmt(op->first); - int temp = max_loop_depth_; - max_loop_depth_ = 0; - Stmt rest = this->VisitStmt(op->rest); - max_loop_depth_ = std::max(max_loop_depth_, temp); - if (first.same_as(op->first) && - rest.same_as(op->rest)) { - return GetRef(op); - } else { - return Block::make(first, rest); - } - } + // Seq Stmt VisitStmt_(const SeqStmtNode* op) final { CHECK_EQ(max_loop_depth_, 0); diff --git a/src/pass/ir_deep_compare.cc b/src/pass/ir_deep_compare.cc index 0c6cb17422bca..bbee9eeb7c8a3 100644 --- a/src/pass/ir_deep_compare.cc +++ b/src/pass/ir_deep_compare.cc @@ -179,13 +179,6 @@ class IRDeepCompare : if (CompareRegion(op->bounds, rhs->bounds) != 0) return; } - void VisitStmt_(const Block* op, const Stmt& other) final { - const Block* rhs = other.as(); - if (CompareStmt(op->first, rhs->first) != 0) return; - if (CompareStmt(op->rest, rhs->rest) != 0) return; - } - - void VisitStmt_(const SeqStmtNode* op, const Stmt& other) final { const SeqStmtNode* rhs = other.as(); if (CompareValue(op->size(), rhs->size()) != 0) return; diff --git a/src/pass/ir_functor.cc b/src/pass/ir_functor.cc index e5f842d98115a..3456a65124e71 100644 --- a/src/pass/ir_functor.cc +++ b/src/pass/ir_functor.cc @@ -199,11 +199,6 @@ void StmtVisitor::VisitStmt_(const Prefetch* op) { }); } -void StmtVisitor::VisitStmt_(const Block* op) { - this->VisitStmt(op->first); - this->VisitStmt(op->rest); -} - void StmtVisitor::VisitStmt_(const SeqStmtNode* op) { VisitArray(op->seq, [this](const Stmt& s) { this->VisitStmt(s); @@ -486,20 +481,6 @@ Stmt StmtMutator::VisitStmt_(const Prefetch* op) { } } -Stmt StmtMutator::VisitStmt_(const Block* op) { - Stmt first = this->VisitStmt(op->first); - Stmt rest = this->VisitStmt(op->rest); - if (first.same_as(op->first) && - rest.same_as(op->rest)) { - return GetRef(op); - } else { - auto n = CopyOnWrite(op); - n->first = std::move(first); - n->rest = std::move(rest); - return Stmt(n); - } -} - Stmt StmtMutator::VisitStmt_(const SeqStmtNode* op) { Array seq = Internal::Mutate(this, op->seq); if (seq.same_as(op->seq)) { diff --git a/src/pass/ir_util.cc b/src/pass/ir_util.cc index 7d7b15d18a4cd..8956a4d11e7cc 100644 --- a/src/pass/ir_util.cc +++ b/src/pass/ir_util.cc @@ -51,11 +51,6 @@ Stmt MergeNest(const std::vector& nest, Stmt body) { CHECK(!n->else_case.defined()); n->then_case = body; body = Stmt(n); - } else if (const auto* block = s.as()) { - auto n = make_object(*block); - CHECK(is_no_op(n->rest)); - n->rest = body; - body = Stmt(n); } else if (const auto* seq = s.as()) { auto n = make_object(*seq); CHECK(n->size() != 0 && is_no_op(n->seq[n->size() - 1])); diff --git a/src/pass/lift_attr_scope.cc b/src/pass/lift_attr_scope.cc index 6d998a6acc3aa..4f2df7b22b097 100644 --- a/src/pass/lift_attr_scope.cc +++ b/src/pass/lift_attr_scope.cc @@ -75,19 +75,6 @@ class AttrScopeLifter : public StmtMutator { } } - Stmt VisitStmt_(const Block* op) final { - std::vector seq; - FlattenSeq(op->first, &seq); - FlattenSeq(op->rest, &seq); - seq = MutateSeq(seq); - if (seq.size() == 2 && - seq[0].same_as(op->first) && - seq[1].same_as(op->rest)) { - return GetRef(op); - } - return SeqStmt::Flatten(seq); - } - Stmt VisitStmt_(const SeqStmtNode* op) final { // remember the decorations. std::vector attr_node; @@ -184,68 +171,6 @@ class AttrScopeLifter : public StmtMutator { } private: - void FlattenSeq(Stmt s, std::vector* res) { - if (const Block* op = s.as()) { - FlattenSeq(op->first, res); - FlattenSeq(op->rest, res); - } else if (const ProducerConsumer* op = s.as()) { - if (!op->is_producer) { - FlattenSeq(op->body, res); - } else { - res->emplace_back(s); - } - } else { - res->emplace_back(s); - } - } - - std::vector MutateSeq(const Array& seq) { - std::vector res_seq; - ObjectRef curr_node; - Expr curr_value; - Stmt curr_stmt; - for (const Stmt & stmt : seq) { - attr_node_ = ObjectRef(); - attr_value_ = Expr(); - Stmt rest = this->VisitStmt(stmt); - if (attr_node_.defined() && - attr_value_.defined() && - curr_node.defined() && - curr_value.defined() && - attr_node_.same_as(curr_node) && - ValueSame(attr_value_, curr_value)) { - curr_stmt = Block::make(curr_stmt, rest); - } else { - if (curr_stmt.defined()) { - if (curr_node.defined()) { - curr_stmt = AttrStmt::make( - curr_node, attr_key_, curr_value, curr_stmt); - } - res_seq.push_back(curr_stmt); - } - curr_stmt = rest; - curr_node = attr_node_; - curr_value = attr_value_; - } - } - - if (curr_stmt.defined()) { - // keep attr_node_, attr_node_ - if (res_seq.size() == 0) { - return {curr_stmt}; - } - if (curr_node.defined()) { - curr_stmt = AttrStmt::make( - curr_node, attr_key_, curr_value, curr_stmt); - } - res_seq.push_back(curr_stmt); - // reset - attr_node_ = ObjectRef(); - attr_value_ = Expr(); - } - return res_seq; - } - // value comparison that also compares content of int constant static bool ValueSame(const Expr& a, const Expr& b) { if (a.same_as(b)) return true; diff --git a/src/pass/loop_partition.cc b/src/pass/loop_partition.cc index 09559c1bb8b25..aa8ebe1eb19bd 100644 --- a/src/pass/loop_partition.cc +++ b/src/pass/loop_partition.cc @@ -106,16 +106,6 @@ class CandidateSelector final : public StmtExprVisitor { StmtExprVisitor::VisitStmt_(op); } - void VisitStmt_(const Block* op) final { - bool temp = no_split_; - this->VisitStmt(op->first); - // erase the no split state of first when visit rest. - std::swap(temp, no_split_); - this->VisitStmt(op->rest); - // restore the no split flag. - no_split_ = no_split_ || temp; - } - void VisitStmt_(const SeqStmtNode* op) final { bool init_no_split = no_split_; for (Stmt stmt : op->seq) { diff --git a/src/pass/remove_no_op.cc b/src/pass/remove_no_op.cc index 59ec113fcaffe..68918708b9fb0 100644 --- a/src/pass/remove_no_op.cc +++ b/src/pass/remove_no_op.cc @@ -94,18 +94,6 @@ class NoOpRemover : public StmtMutator { return Evaluate::make(0); } - Stmt VisitStmt_(const Block* op) final { - Stmt stmt = StmtMutator::VisitStmt_(op); - op = stmt.as(); - if (is_no_op(op->first)) { - return op->rest; - } else if (is_no_op(op->rest)) { - return op->first; - } else { - return stmt; - } - } - Stmt VisitStmt_(const SeqStmtNode* op) final { Stmt ret = StmtMutator::VisitSeqStmt_(op, true); op = ret.as(); diff --git a/src/pass/unroll_loop.cc b/src/pass/unroll_loop.cc index 269bf0933c0b1..7826a9b3a666f 100644 --- a/src/pass/unroll_loop.cc +++ b/src/pass/unroll_loop.cc @@ -120,28 +120,6 @@ class LoopUnroller : public StmtExprMutator { return StmtExprMutator::VisitStmt_(op); } - Stmt VisitStmt_(const Block* op) final { - Stmt first = this->VisitStmt(op->first); - // cleanup state - int step_count = step_count_; - int unroll_depth = unroll_depth_; - int normal_loop_depth = normal_loop_depth_; - step_count_ = 0; - unroll_depth_ = 0; - normal_loop_depth_ = 0; - // work on rest part - Stmt rest = this->VisitStmt(op->rest); - step_count_ += step_count; - normal_loop_depth_ = std::max(normal_loop_depth, normal_loop_depth_); - unroll_depth_ = std::max(unroll_depth_, unroll_depth); - if (first.same_as(op->first) && - rest.same_as(op->rest)) { - return GetRef(op); - } else { - return Block::make(first, rest); - } - } - Stmt VisitStmt_(const SeqStmtNode* op) final { auto fmutate = [this](const Stmt& s) { int step_count = step_count_;