From 4e4622ddc53cea384c8013df9e450540c77feda9 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 10 Jun 2021 16:02:15 -0600 Subject: [PATCH] support matching attributes with more complext objects --- docs/langref/relay_pattern.rst | 11 +++++++++++ src/relay/ir/dataflow_matcher.cc | 9 +++++++++ tests/python/relay/test_dataflow_pattern.py | 11 +++++++++++ 3 files changed, 31 insertions(+) diff --git a/docs/langref/relay_pattern.rst b/docs/langref/relay_pattern.rst index 257fe085bfe5..49d3a42d3e98 100644 --- a/docs/langref/relay_pattern.rst +++ b/docs/langref/relay_pattern.rst @@ -80,6 +80,17 @@ Here is another example to match an op with a specific attribute: y = relay.var('y') assert not is_conv2d.match(relay.op.nn.conv2d(x, y)) +Or a convolution with a specific kernel size: + +.. code-block:: python + + def test_match_kernel_size(): + is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()).has_attr({"kernel_size": [3, 3]}) + x = relay.var('x') + y = relay.var('y') + assert is_conv2d.match(relay.op.nn.conv2d(x, y, kernel_size=[3, 3])) + + Matching an Optional Op *********************** diff --git a/src/relay/ir/dataflow_matcher.cc b/src/relay/ir/dataflow_matcher.cc index 6ed24d5053c4..5ce06d9fefaa 100644 --- a/src/relay/ir/dataflow_matcher.cc +++ b/src/relay/ir/dataflow_matcher.cc @@ -131,6 +131,8 @@ bool MatchRetValue(const ObjectRef& lhs, const TVMRetValue& rhs) { return rhs.operator std::string() == val->value; } else if (auto* val = lhs.as()) { return rhs.operator std::string() == val->data; + } else { + ICHECK(false) << "PatternMatcher: Unsupported TVMDataType " << lhs; } break; case kTVMObjectHandle: @@ -140,6 +142,13 @@ bool MatchRetValue(const ObjectRef& lhs, const TVMRetValue& rhs) { } else if (auto* val = lhs.as()) { return rhs.operator String() == val->data; } + } else { + // Compare the objects for structural equality + static auto* structural_equal = runtime::Registry::Get("node.StructuralEqual"); + ICHECK(structural_equal) << "node.StructuralEqual is not registered."; + if ((*structural_equal)(lhs, GetRef(rhs.ptr()), false, true)) { + return true; + } } break; default: diff --git a/tests/python/relay/test_dataflow_pattern.py b/tests/python/relay/test_dataflow_pattern.py index 229b9905050c..f95a009f9dff 100644 --- a/tests/python/relay/test_dataflow_pattern.py +++ b/tests/python/relay/test_dataflow_pattern.py @@ -478,11 +478,17 @@ def test_no_match_func_attr(): def test_match_call_attr(): + # String attr is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()).has_attr({"data_layout": "NCHW"}) x = relay.var("x") y = relay.var("y") assert is_conv2d.match(relay.op.nn.conv2d(x, y)) + # Array attr + is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()).has_attr({"kernel_size": [3, 3]}) + out = relay.op.nn.conv2d(x, y, kernel_size=[3, 3]) + assert is_conv2d.match(out) + # non-operator call attr_dict = {"call_attr": "attr"} call_has_attr = wildcard()(wildcard()).has_attr(attr_dict) @@ -508,6 +514,11 @@ def test_no_match_call_attr(): is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()).has_attr({"RandomAttr": "NCHW"}) assert not is_conv2d.match(relay.op.nn.conv2d(x, y)) + # Array attr + is_conv2d = is_op("nn.conv2d")(wildcard(), wildcard()).has_attr({"kernel_size": [3, 3]}) + out = relay.op.nn.conv2d(x, y, kernel_size=[2, 1]) + assert not is_conv2d.match(out) + # non-operator calls call_has_attr = wildcard()(wildcard()).has_attr({"call_attr": "attr"}) wrong_key = tvm.ir.make_node("DictAttrs", **{"wrong": "attr"})