@@ -123,6 +123,8 @@ class Stage : public NodeRef {
123123 IterVar* p_x_outer, IterVar* p_y_outer,
124124 IterVar* p_x_inner, IterVar* p_y_inner,
125125 Expr x_factor, Expr y_factor);
126+ // declare container type
127+ using ContainerType = StageNode;
126128};
127129
128130/* !
@@ -152,11 +154,22 @@ class Schedule : public NodeRef {
152154 Stage operator [](const Tensor& tensor) {
153155 return this ->operator [](tensor->op );
154156 }
157+ /* !
158+ * \brief Normalize the schedule.
159+ * This is needed before bound inference.
160+ * Insert necessary RebaseNode to make sure all leaf_iter_vars
161+ * are in form [0, extent)
162+ *
163+ * \return A normalized schedule, can be same as current one.
164+ */
165+ void normalize ();
155166 /* !
156167 * \brief access the internal node container
157168 * \return the pointer to the internal node container
158169 */
159170 inline const ScheduleNode* operator ->() const ;
171+ // declare container type
172+ using ContainerType = ScheduleNode;
160173};
161174
162175/* !
@@ -308,6 +321,30 @@ class FuseNode : public IterVarRelationNode {
308321 TVM_DECLARE_NODE_TYPE_INFO (FuseNode);
309322};
310323
324+ /* !
325+ * \brief Rebase the iteration to make min to be 0.
326+ * This is useful to normalize the Schedule
327+ * to make every leaf variable's min to be 0.
328+ */
329+ class RebaseNode : public IterVarRelationNode {
330+ public:
331+ /* ! \brief The parent domain */
332+ IterVar parent;
333+ /* ! \brief The inner domain */
334+ IterVar rebased;
335+
336+ void VisitAttrs (AttrVisitor* v) final {
337+ v->Visit (" parent" , &parent);
338+ v->Visit (" rebased" , &rebased);
339+ }
340+
341+ static IterVarRelation make (IterVar parent, IterVar rebased);
342+
343+ static constexpr const char * _type_key = " Rebase" ;
344+ TVM_DECLARE_NODE_TYPE_INFO (RebaseNode);
345+ };
346+
347+
311348// implementations
312349inline const StageNode* Stage::operator ->() const {
313350 return static_cast <const StageNode*>(node_.get ());
0 commit comments