From a762236ad6bc64acdb85cfd3efdf396f6dff23eb Mon Sep 17 00:00:00 2001 From: mbrookhart Date: Wed, 16 Dec 2020 11:14:41 -0700 Subject: [PATCH 1/5] Add Syntatic Sugar for C++ Pattern API, Support DataType Attribute match --- include/tvm/relay/dataflow_pattern.h | 56 +++++-- python/tvm/relay/dataflow_pattern/__init__.py | 4 +- src/relay/ir/dataflow_matcher.cc | 14 +- src/relay/ir/dataflow_pattern.cc | 68 ++++++-- src/relay/transforms/simplify_expr.cc | 9 +- tests/cpp/dataflow_pattern_test.cc | 152 ++++++++++++++++++ tests/python/relay/test_dataflow_pattern.py | 6 + 7 files changed, 270 insertions(+), 39 deletions(-) create mode 100644 tests/cpp/dataflow_pattern_test.cc diff --git a/include/tvm/relay/dataflow_pattern.h b/include/tvm/relay/dataflow_pattern.h index 909a4fe44eb1..77268dc2b66a 100644 --- a/include/tvm/relay/dataflow_pattern.h +++ b/include/tvm/relay/dataflow_pattern.h @@ -1,5 +1,4 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file @@ -46,6 +45,29 @@ class DFPatternNode : public Object { */ class DFPattern : public ObjectRef { public: + /*! \brief Syntatic Sugar for creating a CallPattern */ + DFPattern operator()(const std::vector& args); + /*! \brief Syntatic Sugar for creating a CallPattern with an "add" op */ + DFPattern operator+(const DFPattern& other); + /*! \brief Syntatic Sugar for creating a CallPattern with a "subtract" op */ + DFPattern operator-(const DFPattern& other); + /*! \brief Syntatic Sugar for creating a CallPattern with a "multiply" op */ + DFPattern operator*(const DFPattern& other); + /*! \brief Syntatic Sugar for creating a CallPattern with a "divide" op */ + DFPattern operator/(const DFPattern& other); + /*! \brief Syntatic Sugar for creating an AltPattern */ + DFPattern operator||(const DFPattern& other); + /*! \brief Syntatic Sugar for creating an AttrPattern */ + DFPattern HasAttr(const Map& attrs); + /*! \brief Syntatic Sugar for creating a TypePattern */ + DFPattern HasType(const Type& type); + /*! \brief Syntatic Sugar for creating a DataTypePattern with a DataType */ + DFPattern HasDtype(const DataType& dtype); + /*! \brief Syntatic Sugar for creating a DataTypePattern with a data type's name */ + DFPattern HasDtype(const std::string& dtype); + /*! \brief Syntatic Sugar for creating a ShapePattern */ + DFPattern HasShape(const Array shape); + TVM_DEFINE_OBJECT_REF_METHODS(DFPattern, ObjectRef, DFPatternNode); }; @@ -86,20 +108,11 @@ class VarPatternNode : public DFPatternNode { * \brief The name of the Var (optional). */ String name; - /*! - * \brief type annotation of the variable. - * This field records user provided type annotation of the Var. - * This field is optional and can be None. - */ - Type type_annotation; /*! \return The name hint of the variable */ const String& name_hint() const { return name; } - void VisitAttrs(tvm::AttrVisitor* v) { - v->Visit("name", &name); - v->Visit("type_annotation", &type_annotation); - } + void VisitAttrs(tvm::AttrVisitor* v) { v->Visit("name", &name); } static constexpr const char* _type_key = "relay.dataflow_pattern.VarPattern"; TVM_DECLARE_FINAL_OBJECT_INFO(VarPatternNode, DFPatternNode); @@ -107,7 +120,7 @@ class VarPatternNode : public DFPatternNode { class VarPattern : public DFPattern { public: - TVM_DLL VarPattern(String name_hint, Type type_annotation); + TVM_DLL VarPattern(String name_hint); TVM_DEFINE_OBJECT_REF_METHODS(VarPattern, DFPattern, VarPatternNode); }; @@ -393,7 +406,7 @@ class AttrPatternNode : public DFPatternNode { /*! \brief The pattern. */ DFPattern pattern; /*! \brief The attribute to match */ - Attrs attrs; + DictAttrs attrs; void VisitAttrs(tvm::AttrVisitor* v) { v->Visit("pattern", &pattern); @@ -409,7 +422,7 @@ class AttrPatternNode : public DFPatternNode { */ class AttrPattern : public DFPattern { public: - TVM_DLL AttrPattern(DFPattern pattern, Attrs attrs); + TVM_DLL AttrPattern(DFPattern pattern, DictAttrs attrs); TVM_DEFINE_OBJECT_REF_METHODS(AttrPattern, DFPattern, AttrPatternNode); }; @@ -447,6 +460,19 @@ class DominatorPattern : public DFPattern { TVM_DEFINE_OBJECT_REF_METHODS(DominatorPattern, DFPattern, DominatorPatternNode); }; +/*! \brief Syntatic Sugar for creating a VarPattern with a name */ +DFPattern IsVar(const String& name); +/*! \brief Syntatic Sugar for creating a ConstantPattern */ +DFPattern IsConstant(); +/*! \brief Syntatic Sugar for creating a ExprPattern */ +DFPattern IsExpr(const Expr& expr); +/*! \brief Syntatic Sugar for creating a ExprPattern base on an Op*/ +DFPattern IsOp(const String& op_name); +/*! \brief Syntatic Sugar for creating a TuplePattern*/ +DFPattern IsTuple(const Array& fields); +/*! \brief Syntatic Sugar for creating a TupleGetItemPattern*/ +DFPattern IsTupleGetItem(const DFPattern tuple, int index = -1); + } // namespace relay } // namespace tvm #endif // TVM_RELAY_DATAFLOW_PATTERN_H_ diff --git a/python/tvm/relay/dataflow_pattern/__init__.py b/python/tvm/relay/dataflow_pattern/__init__.py index 233c696fd716..f5161ad0bfa7 100644 --- a/python/tvm/relay/dataflow_pattern/__init__.py +++ b/python/tvm/relay/dataflow_pattern/__init__.py @@ -480,8 +480,8 @@ class VarPattern(DFPattern): The type annotation on the variable. """ - def __init__(self, name_hint: str = "", type_annotation: Optional[tvm.ir.type.Type] = None): - self.__init_handle_by_constructor__(ffi.VarPattern, name_hint, type_annotation) + def __init__(self, name_hint: str = ""): + self.__init_handle_by_constructor__(ffi.VarPattern, name_hint) @register_df_node diff --git a/src/relay/ir/dataflow_matcher.cc b/src/relay/ir/dataflow_matcher.cc index c5cc3dd17429..e4c0c7fa1c94 100644 --- a/src/relay/ir/dataflow_matcher.cc +++ b/src/relay/ir/dataflow_matcher.cc @@ -124,6 +124,13 @@ bool MatchRetValue(const ObjectRef& lhs, const TVMRetValue& rhs) { return val->data == rhs.operator std::string(); } break; + case kTVMDataType: + if (auto* val = lhs.as()) { + return rhs.operator std::string() == val->value; + } else if (auto* val = lhs.as()) { + return rhs.operator std::string() == val->data; + } + break; case kTVMObjectHandle: if (rhs.IsObjectRef()) { if (auto* val = lhs.as()) { @@ -140,7 +147,10 @@ bool MatchRetValue(const ObjectRef& lhs, const TVMRetValue& rhs) { } bool DFPatternMatcher::VisitDFPattern_(const AttrPatternNode* attr_pattern, const Expr& expr) { - bool matches = false; + bool matches = VisitDFPattern(attr_pattern->pattern, expr); + if (!matches) { + return matches; + } auto attributes = attr_pattern->attrs.as()->dict; if (const auto* op_node = expr.as()) { Op op = GetRef(op_node); @@ -179,7 +189,7 @@ bool DFPatternMatcher::VisitDFPattern_(const AttrPatternNode* attr_pattern, cons } } } - return matches && VisitDFPattern(attr_pattern->pattern, expr); + return matches; } Array reverse(const Array& args) { diff --git a/src/relay/ir/dataflow_pattern.cc b/src/relay/ir/dataflow_pattern.cc index 46c53c8bd96c..8cf8f32e5f3a 100644 --- a/src/relay/ir/dataflow_pattern.cc +++ b/src/relay/ir/dataflow_pattern.cc @@ -22,6 +22,7 @@ * \brief The dataflow pattern language for Relay. */ #include +#include namespace tvm { namespace relay { @@ -44,29 +45,22 @@ TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) p->Print(node->expr); }); -VarPattern::VarPattern(String name_hint, Type type_annotation) { +VarPattern::VarPattern(String name_hint) { ObjectPtr n = make_object(); n->name = std::move(name_hint); - n->type_annotation = std::move(type_annotation); data_ = std::move(n); } TVM_REGISTER_NODE_TYPE(VarPatternNode); -TVM_REGISTER_GLOBAL("relay.dataflow_pattern.VarPattern") - .set_body_typed([](String name_hint, Type type_annotation) { - return VarPattern(name_hint, type_annotation); - }); +TVM_REGISTER_GLOBAL("relay.dataflow_pattern.VarPattern").set_body_typed([](String name_hint) { + return VarPattern(name_hint); +}); TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) .set_dispatch([](const ObjectRef& ref, ReprPrinter* p) { auto* node = static_cast(ref.get()); - p->stream << "VarPattern(" << node->name_hint(); - if (node->type_annotation.defined()) { - p->stream << ", ty="; - p->Print(node->type_annotation); - } - p->stream << ")"; + p->stream << "VarPattern(" << node->name_hint() << ")"; }); TVM_REGISTER_NODE_TYPE(ConstantPatternNode); @@ -241,7 +235,7 @@ TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) p->stream << "TypePattern(" << node->pattern << " has dtype " << node->dtype << ")"; }); -AttrPattern::AttrPattern(DFPattern pattern, Attrs attrs) { +AttrPattern::AttrPattern(DFPattern pattern, DictAttrs attrs) { ObjectPtr n = make_object(); n->pattern = std::move(pattern); n->attrs = std::move(attrs); @@ -251,7 +245,7 @@ AttrPattern::AttrPattern(DFPattern pattern, Attrs attrs) { TVM_REGISTER_NODE_TYPE(AttrPatternNode); TVM_REGISTER_GLOBAL("relay.dataflow_pattern.AttrPattern") - .set_body_typed([](DFPattern pattern, Attrs attrs) { return AttrPattern(pattern, attrs); }); + .set_body_typed([](DFPattern pattern, DictAttrs attrs) { return AttrPattern(pattern, attrs); }); TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) .set_dispatch([](const ObjectRef& ref, ReprPrinter* p) { @@ -263,6 +257,7 @@ DominatorPattern::DominatorPattern(DFPattern parent, DFPattern path, DFPattern c ObjectPtr n = make_object(); n->parent = std::move(parent); n->path = std::move(path); + n->child = std::move(child); data_ = std::move(n); } @@ -281,5 +276,50 @@ TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) << ")"; }); +// Syntatic Sugar +DFPattern DFPattern::operator()(const std::vector& args) { + return CallPattern(GetRef(this->get()), Array(args), NullValue(), + Array()); +} +DFPattern DFPattern::operator+(const DFPattern& other) { + return IsOp("add")({GetRef(this->get()), other}); +} +DFPattern DFPattern::operator-(const DFPattern& other) { + return IsOp("subtract")({GetRef(this->get()), other}); +} +DFPattern DFPattern::operator*(const DFPattern& other) { + return IsOp("multiply")({GetRef(this->get()), other}); +} +DFPattern DFPattern::operator/(const DFPattern& other) { + return IsOp("divide")({GetRef(this->get()), other}); +} +DFPattern DFPattern::operator||(const DFPattern& other) { + return AltPattern(GetRef(this->get()), other); +} + +DFPattern DFPattern::HasAttr(const Map& attrs) { + return AttrPattern(GetRef(this->get()), DictAttrs(attrs)); +} +DFPattern DFPattern::HasType(const Type& type) { + return TypePattern(GetRef(this->get()), type); +} +DFPattern DFPattern::HasDtype(const DataType& dtype) { + return DataTypePattern(GetRef(this->get()), dtype); +} +DFPattern DFPattern::HasDtype(const std::string& dtype) { + return HasDtype(DataType(runtime::String2DLDataType(dtype))); +} +DFPattern DFPattern::HasShape(const Array shape) { + return ShapePattern(GetRef(this->get()), shape); +} +DFPattern IsVar(const String& name) { return VarPattern(name); } +DFPattern IsConstant() { return ConstantPattern(make_object()); } +DFPattern IsExpr(const Expr& expr) { return ExprPattern(expr); } +DFPattern IsOp(const String& op_name) { return IsExpr(Op::Get(op_name)); } +DFPattern IsTuple(const Array& fields) { return TuplePattern(fields); } +DFPattern IsTupleGetItem(const DFPattern tuple, int index) { + return TupleGetItemPattern(tuple, index); +} + } // namespace relay } // namespace tvm diff --git a/src/relay/transforms/simplify_expr.cc b/src/relay/transforms/simplify_expr.cc index cb42ab09aae4..0f78c260378c 100644 --- a/src/relay/transforms/simplify_expr.cc +++ b/src/relay/transforms/simplify_expr.cc @@ -33,9 +33,6 @@ namespace tvm { namespace relay { -static Op reshape_op = Op::Get("reshape"); -static Op reverse_reshape_op = Op::Get("contrib_reverse_reshape"); - /*! * \brief SimplifyReshape matches the pattern of consecutive reshape or reverse_reshape ops, * and merges into one reshape op. @@ -44,9 +41,9 @@ class SimplifyReshape { public: SimplifyReshape() { x_ = WildcardPattern(make_object()); - auto reshape1 = AltPattern(ExprPattern(reshape_op), ExprPattern(reverse_reshape_op)); - auto reshape2 = AltPattern(ExprPattern(reshape_op), ExprPattern(reverse_reshape_op)); - pattern_ = CallPattern(reshape1, {CallPattern(reshape2, {x_})}); + auto reshape1 = IsOp("reshape") || IsOp("contrib_reverse_reshape"); + auto reshape2 = IsOp("reshape") || IsOp("contrib_reverse_reshape"); + pattern_ = reshape1({reshape2({x_})}); } Expr callback(const Expr& pre, const Expr& post, const Map>& node_map) { diff --git a/tests/cpp/dataflow_pattern_test.cc b/tests/cpp/dataflow_pattern_test.cc new file mode 100644 index 000000000000..8c5b1903a0c8 --- /dev/null +++ b/tests/cpp/dataflow_pattern_test.cc @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#include +#include +#include + +TEST(DFPattern, IsVar) { + using namespace tvm; + using namespace tvm::relay; + auto pattern = IsVar("add"); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->name == String("add")); +} + +TEST(DFPattern, IsConstant) { + using namespace tvm; + using namespace tvm::relay; + auto pattern = IsConstant(); + auto* node = pattern.as(); + ICHECK(node); +} + +TEST(DFPattern, IsOp) { + using namespace tvm; + using namespace tvm::relay; + auto pattern = IsOp("add"); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->expr == Op::Get("add")); +} + +TEST(DFPattern, IsTuple) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = IsTuple({a, b}); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->fields[0] == a); + ICHECK(node->fields[1] == b); +} + +TEST(DFPattern, IsTupleGetItem) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto tuple = IsTuple({a, b}); + auto pattern = IsTupleGetItem(tuple, 1); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->tuple == tuple); + ICHECK(node->index == 1); +} + +TEST(DFPattern, ADD) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = a + b; + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->args[0] == a); + ICHECK(node->args[1] == b); + auto* expr_pattern = node->op.as(); + ICHECK(expr_pattern); + ICHECK(expr_pattern->expr == Op::Get("add")); +} + +TEST(DFPattern, SUB) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = a - b; + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->args[0] == a); + ICHECK(node->args[1] == b); + auto* expr_pattern = node->op.as(); + ICHECK(expr_pattern); + ICHECK(expr_pattern->expr == Op::Get("subtract")); +} + +TEST(DFPattern, MUL) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = a * b; + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->args[0] == a); + ICHECK(node->args[1] == b); + auto* expr_pattern = node->op.as(); + ICHECK(expr_pattern); + ICHECK(expr_pattern->expr == Op::Get("multiply")); +} + +TEST(DFPattern, DIV) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = a / b; + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->args[0] == a); + ICHECK(node->args[1] == b); + auto* expr_pattern = node->op.as(); + ICHECK(expr_pattern); + ICHECK(expr_pattern->expr == Op::Get("divide")); +} + +TEST(DFPattern, OR) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto b = WildcardPattern(); + auto pattern = a || b; + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->left == a); + ICHECK(node->right == b); +} + +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + testing::FLAGS_gtest_death_test_style = "threadsafe"; + return RUN_ALL_TESTS(); +} diff --git a/tests/python/relay/test_dataflow_pattern.py b/tests/python/relay/test_dataflow_pattern.py index d99e55b7c33f..f30a4e747c33 100644 --- a/tests/python/relay/test_dataflow_pattern.py +++ b/tests/python/relay/test_dataflow_pattern.py @@ -401,6 +401,12 @@ def test_no_match_call_attr(): assert not is_conv2d.match(relay.op.nn.conv2d(x, y)) +def test_match_call_attr_dtype(): + is_cast = is_op("cast")(wildcard()).has_attr({"dtype": "float32"}) + x = relay.var("x") + assert is_cast.match(relay.op.cast(x, "float32")) + + def test_match_diamond(): # Pattern is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()) From d74484d578c7bf7f10a8938929713b28b11cd52f Mon Sep 17 00:00:00 2001 From: mbrookhart Date: Wed, 16 Dec 2020 12:03:00 -0700 Subject: [PATCH 2/5] add missing tests --- tests/cpp/dataflow_pattern_test.cc | 50 +++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/cpp/dataflow_pattern_test.cc b/tests/cpp/dataflow_pattern_test.cc index 8c5b1903a0c8..bdccaaa2e6ba 100644 --- a/tests/cpp/dataflow_pattern_test.cc +++ b/tests/cpp/dataflow_pattern_test.cc @@ -17,7 +17,6 @@ * under the License. */ - #include #include #include @@ -145,6 +144,55 @@ TEST(DFPattern, OR) { ICHECK(node->right == b); } +TEST(DFPattern, HasAttr) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + Map attrs; + auto b = String("b"); + attrs.Set("a", b); + auto pattern = a.HasAttr(attrs); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->pattern == a); + ICHECK(node->attrs->dict.at("a") == b); +} + +TEST(DFPattern, HasType) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + TensorType type({1, 2, 3}, DataType(runtime::String2DLDataType("float32"))); + auto pattern = a.HasType(type); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->pattern == a); + ICHECK(node->type == type); +} + +TEST(DFPattern, HasDtype) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + auto pattern = a.HasDtype("float32"); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->pattern == a); + ICHECK(runtime::DLDataType2String(node->dtype.operator DLDataType()) == "float32"); +} + +TEST(DFPattern, HasShape) { + using namespace tvm; + using namespace tvm::relay; + auto a = WildcardPattern(); + Array shape{1, 2, 3}; + auto pattern = a.HasShape(shape); + auto* node = pattern.as(); + ICHECK(node); + ICHECK(node->pattern == a); + ICHECK(node->shape == shape); +} + int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); testing::FLAGS_gtest_death_test_style = "threadsafe"; From 710f9e8564d9bc8516c4618495c00001ed5a6ecb Mon Sep 17 00:00:00 2001 From: mbrookhart Date: Wed, 16 Dec 2020 12:05:41 -0700 Subject: [PATCH 3/5] fix lint --- include/tvm/relay/dataflow_pattern.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/tvm/relay/dataflow_pattern.h b/include/tvm/relay/dataflow_pattern.h index 77268dc2b66a..f5d02911bc96 100644 --- a/include/tvm/relay/dataflow_pattern.h +++ b/include/tvm/relay/dataflow_pattern.h @@ -26,6 +26,9 @@ #include #include +#include +#include + namespace tvm { namespace relay { From 535972e80e21f61f3f085923d0ce70463c22fb18 Mon Sep 17 00:00:00 2001 From: mbrookhart Date: Thu, 17 Dec 2020 10:53:20 -0700 Subject: [PATCH 4/5] fix license edit --- include/tvm/relay/dataflow_pattern.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/tvm/relay/dataflow_pattern.h b/include/tvm/relay/dataflow_pattern.h index f5d02911bc96..5b2734f52ede 100644 --- a/include/tvm/relay/dataflow_pattern.h +++ b/include/tvm/relay/dataflow_pattern.h @@ -1,4 +1,5 @@ -/* * Licensed to the Apache Software Foundation (ASF) under one +/* + * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file From eda5bed6bdca5f114c5c5d7dfe6770d490ad6239 Mon Sep 17 00:00:00 2001 From: mbrookhart Date: Tue, 5 Jan 2021 10:14:05 -0700 Subject: [PATCH 5/5] fix bad rebase --- src/relay/ir/dataflow_pattern.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/relay/ir/dataflow_pattern.cc b/src/relay/ir/dataflow_pattern.cc index 8cf8f32e5f3a..086c3852b13f 100644 --- a/src/relay/ir/dataflow_pattern.cc +++ b/src/relay/ir/dataflow_pattern.cc @@ -278,8 +278,7 @@ TVM_STATIC_IR_FUNCTOR(ReprPrinter, vtable) // Syntatic Sugar DFPattern DFPattern::operator()(const std::vector& args) { - return CallPattern(GetRef(this->get()), Array(args), NullValue(), - Array()); + return CallPattern(GetRef(this->get()), Array(args)); } DFPattern DFPattern::operator+(const DFPattern& other) { return IsOp("add")({GetRef(this->get()), other});