This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch unity
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/unity by this push:
     new 3b8aa040e4 [Unity][op] Relax rsqrt and sinh (#14479)
3b8aa040e4 is described below

commit 3b8aa040e46fc849a747eeef213296ede0580736
Author: Yong Wu <[email protected]>
AuthorDate: Tue Apr 4 06:22:46 2023 -0700

    [Unity][op] Relax rsqrt and sinh (#14479)
---
 python/tvm/relax/frontend/torch/fx_translator.py   |   5 +-
 python/tvm/relax/op/unary.py                       |  24 ++++
 python/tvm/relax/transform/legalize_ops/unary.py   |   2 +
 python/tvm/script/ir_builder/relax/ir.py           |   2 +
 src/relax/op/tensor/unary.cc                       |   1 +
 src/relax/op/tensor/unary.h                        |   3 +
 tests/python/relax/test_frontend_from_fx.py        |   5 +-
 tests/python/relax/test_op_unary.py                |   2 +
 .../relax/test_transform_legalize_ops_unary.py     | 146 +++++++++++++++++++++
 .../relax/test_tvmscript_parser_op_arith_cmp.py    |   1 +
 10 files changed, 184 insertions(+), 7 deletions(-)

diff --git a/python/tvm/relax/frontend/torch/fx_translator.py 
b/python/tvm/relax/frontend/torch/fx_translator.py
index 58c7563419..f1ffbeac4b 100644
--- a/python/tvm/relax/frontend/torch/fx_translator.py
+++ b/python/tvm/relax/frontend/torch/fx_translator.py
@@ -157,10 +157,7 @@ class TorchFXImporter:
         arg = self.env[node.args[0]]
         if isinstance(arg, (int, float)):
             arg = relax.const(arg, "float32")
-        sqrt = self.block_builder.emit(relax.op.sqrt(arg))
-        return self.block_builder.emit(
-            relax.op.divide(relax.const(1, sqrt.struct_info.dtype), sqrt)
-        )
+        return self.block_builder.emit(relax.op.rsqrt(arg))
 
     def _round(self, node: fx.node.Node) -> relax.Expr:
         if "decimals" in node.kwargs and node.kwargs["decimals"] != 0:
diff --git a/python/tvm/relax/op/unary.py b/python/tvm/relax/op/unary.py
index 866d2a8273..f885c103e7 100644
--- a/python/tvm/relax/op/unary.py
+++ b/python/tvm/relax/op/unary.py
@@ -303,6 +303,30 @@ def round(x: Expr) -> Expr:
     return _ffi_api.round(x)  # type: ignore
 
 
+def rsqrt(x: Expr) -> Expr:
+    """Compute element-wise reciprocal square root of the input data.
+
+    .. math::
+
+      1/sqrt(x)
+
+    Parameters
+    ----------
+    x : relax.Expr
+        The input data
+
+    Returns
+    -------
+    result : relax.Expr
+        The computed result.
+
+    Note
+    ----
+    The input tensor is required to have float dtype
+    """
+    return _ffi_api.rsqrt(x)  # type: ignore
+
+
 def sigmoid(x: Expr) -> Expr:
     """Compute element-wise sigmoid of the input data.
 
diff --git a/python/tvm/relax/transform/legalize_ops/unary.py 
b/python/tvm/relax/transform/legalize_ops/unary.py
index ca84cbf0ad..9d19abe16e 100644
--- a/python/tvm/relax/transform/legalize_ops/unary.py
+++ b/python/tvm/relax/transform/legalize_ops/unary.py
@@ -28,8 +28,10 @@ register_legalize("relax.exp", 
_call_topi_without_attr(topi.exp, "tir_exp"))
 register_legalize("relax.floor", _call_topi_without_attr(topi.floor, 
"tir_floor"))
 register_legalize("relax.negative", _call_topi_without_attr(topi.negative, 
"tir_negative"))
 register_legalize("relax.round", _call_topi_without_attr(topi.round, 
"tir_round"))
+register_legalize("relax.rsqrt", _call_topi_without_attr(topi.rsqrt, 
"tir_rsqrt"))
 register_legalize("relax.sigmoid", _call_topi_without_attr(topi.sigmoid, 
"tir_sigmoid"))
 register_legalize("relax.sign", _call_topi_without_attr(topi.sign, "tir_sign"))
+register_legalize("relax.sinh", _call_topi_without_attr(topi.sinh, "tir_sinh"))
 register_legalize("relax.sin", _call_topi_without_attr(topi.sin, "tir_sin"))
 register_legalize("relax.sqrt", _call_topi_without_attr(topi.sqrt, "tir_sqrt"))
 register_legalize("relax.tanh", _call_topi_without_attr(topi.tanh, "tir_tanh"))
diff --git a/python/tvm/script/ir_builder/relax/ir.py 
b/python/tvm/script/ir_builder/relax/ir.py
index c6d36c8587..9857853a80 100644
--- a/python/tvm/script/ir_builder/relax/ir.py
+++ b/python/tvm/script/ir_builder/relax/ir.py
@@ -103,6 +103,7 @@ from tvm.relax.op import (
     tensor_to_shape,
     shape_to_tensor,
     round,
+    rsqrt,
     shape_of,
     std,
     strided_slice,
@@ -624,6 +625,7 @@ __all__ = [
     "tensor_to_shape",
     "shape_to_tensor",
     "round",
+    "rsqrt",
     "shape",
     "shape_of",
     "ShapeExpr",
diff --git a/src/relax/op/tensor/unary.cc b/src/relax/op/tensor/unary.cc
index f1117c1826..5d4a39067f 100644
--- a/src/relax/op/tensor/unary.cc
+++ b/src/relax/op/tensor/unary.cc
@@ -51,6 +51,7 @@ RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(floor, 
/*require_float_dtype=*/false);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(log, /*require_float_dtype=*/true);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(negative, 
/*require_float_dtype=*/false);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(round, /*require_float_dtype=*/false);
+RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(rsqrt, /*require_float_dtype=*/true);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(sigmoid, /*require_float_dtype=*/true);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(sign, /*require_float_dtype=*/false);
 RELAX_REGISTER_UNARY_ARITH_OP_AND_IMPL(sin, /*require_float_dtype=*/true);
diff --git a/src/relax/op/tensor/unary.h b/src/relax/op/tensor/unary.h
index 8f6404c5d9..60dd5148e2 100644
--- a/src/relax/op/tensor/unary.h
+++ b/src/relax/op/tensor/unary.h
@@ -100,6 +100,9 @@ Expr negative(Expr x);
 /*! \brief Rounds each element of the input data to nearest integer. */
 Expr round(Expr x);
 
+/*! \brief Compute element-wise reciprocal square root of data. */
+Expr rsqrt(Expr x);
+
 /*! \brief Compute element-wise sigmoid of data. */
 Expr sigmoid(Expr x);
 
diff --git a/tests/python/relax/test_frontend_from_fx.py 
b/tests/python/relax/test_frontend_from_fx.py
index 9e07ff7b59..2285131e39 100644
--- a/tests/python/relax/test_frontend_from_fx.py
+++ b/tests/python/relax/test_frontend_from_fx.py
@@ -2685,9 +2685,8 @@ def test_rsqrt():
             inp_0: R.Tensor((256, 256), dtype="float32")
         ) -> R.Tensor((256, 256), dtype="float32"):
             with R.dataflow():
-                lv: R.Tensor((256, 256), dtype="float32") = R.sqrt(inp_0)
-                lv1: R.Tensor((256, 256), dtype="float32") = 
R.divide(R.const(1, "float32"), lv)
-                gv: R.Tensor((256, 256), dtype="float32") = lv1
+                lv: R.Tensor((256, 256), dtype="float32") = R.rsqrt(inp_0)
+                gv: R.Tensor((256, 256), dtype="float32") = lv
                 R.output(gv)
             return gv
 
diff --git a/tests/python/relax/test_op_unary.py 
b/tests/python/relax/test_op_unary.py
index 45336661a1..c8751dbaca 100644
--- a/tests/python/relax/test_op_unary.py
+++ b/tests/python/relax/test_op_unary.py
@@ -44,6 +44,7 @@ def test_op_correctness():
     assert relax.op.log(x).op == Op.get("relax.log")
     assert relax.op.negative(x).op == Op.get("relax.negative")
     assert relax.op.round(x).op == Op.get("relax.round")
+    assert relax.op.rsqrt(x).op == Op.get("relax.rsqrt")
     assert relax.op.sigmoid(x).op == Op.get("relax.sigmoid")
     assert relax.op.sin(x).op == Op.get("relax.sin")
     assert relax.op.sinh(x).op == Op.get("relax.sinh")
@@ -75,6 +76,7 @@ unary_arith_op, require_float_dtype = tvm.testing.parameters(
     (relax.op.log, True),
     (relax.op.negative, False),
     (relax.op.round, False),
+    (relax.op.rsqrt, True),
     (relax.op.sigmoid, True),
     (relax.op.sign, False),
     (relax.op.sin, True),
diff --git a/tests/python/relax/test_transform_legalize_ops_unary.py 
b/tests/python/relax/test_transform_legalize_ops_unary.py
index 27103e5f8f..1a5d474c3e 100644
--- a/tests/python/relax/test_transform_legalize_ops_unary.py
+++ b/tests/python/relax/test_transform_legalize_ops_unary.py
@@ -676,6 +676,76 @@ def test_round_symbolic():
     tvm.ir.assert_structural_equal(mod, Expected)
 
 
+def test_rsqrt():
+    # fmt: off
+    @tvm.script.ir_module
+    class Rsqrt:
+        @R.function
+        def main(x: R.Tensor((2, 3), "float32")) -> R.Tensor((2, 3), 
"float32"):
+            gv: R.Tensor((2, 3), "float32") = R.rsqrt(x)
+            return gv
+
+    @tvm.script.ir_module
+    class Expected:
+        @R.function
+        def main(x: R.Tensor((2, 3), "float32")) -> R.Tensor((2, 3), 
"float32"):
+            gv = R.call_tir(Expected.tir_rsqrt, (x,), R.Tensor((2, 3), 
dtype="float32"))
+            return gv
+
+        @T.prim_func
+        def tir_rsqrt(rxplaceholder: T.Buffer((T.int64(2), T.int64(3)), 
"float32"), compute: T.Buffer((T.int64(2), T.int64(3)), "float32")):
+            T.func_attr({"tir.noalias": True})
+            for i0, i1 in T.grid(T.int64(2), T.int64(3)):
+                with T.block("compute"):
+                    i0_1, i1_1 = T.axis.remap("SS", [i0, i1])
+                    T.reads(rxplaceholder[i0_1, i1_1])
+                    T.writes(compute[i0_1, i1_1])
+                    compute[i0_1, i1_1] = T.rsqrt(rxplaceholder[i0_1, i1_1])
+    # fmt: on
+
+    mod = LegalizeOps()(Rsqrt)
+    tvm.ir.assert_structural_equal(mod, Expected)
+
+
+def test_rsqrt_symbolic():
+    # fmt: off
+    @tvm.script.ir_module
+    class Rsqrt:
+        @R.function
+        def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor(("m", "n"), 
"float32"):
+            m = T.int64()
+            n = T.int64()
+            gv: R.Tensor((m, n), "float32") = R.rsqrt(x)
+            return gv
+
+    @tvm.script.ir_module
+    class Expected:
+        @R.function
+        def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor(("m", "n"), 
"float32"):
+            m = T.int64()
+            n = T.int64()
+            gv = R.call_tir(Expected.tir_rsqrt, (x,), R.Tensor((m, n), 
dtype="float32"))
+            return gv
+
+        @T.prim_func
+        def tir_rsqrt(var_rxplaceholder: T.handle, var_compute: T.handle):
+            T.func_attr({"tir.noalias": True})
+            m = T.int64()
+            n = T.int64()
+            rxplaceholder = T.match_buffer(var_rxplaceholder, [m, n], 
dtype="float32")
+            compute = T.match_buffer(var_compute, [m, n], dtype="float32")
+            for i0, i1 in T.grid(m, n):
+                with T.block("compute"):
+                    i0_1, i1_1 = T.axis.remap("SS", [i0, i1])
+                    T.reads(rxplaceholder[i0_1, i1_1])
+                    T.writes(compute[i0_1, i1_1])
+                    compute[i0_1, i1_1] = T.rsqrt(rxplaceholder[i0_1, i1_1])
+    # fmt: on
+
+    mod = LegalizeOps()(Rsqrt)
+    tvm.ir.assert_structural_equal(mod, Expected)
+
+
 def test_sigmoid():
     # fmt: off
     @tvm.script.ir_module
@@ -917,6 +987,82 @@ def test_sin_symbolic():
     tvm.ir.assert_structural_equal(mod, Expected)
 
 
+def test_sinh():
+    # fmt: off
+    @tvm.script.ir_module
+    class Sinh:
+        @R.function
+        def main(x: R.Tensor((2, 3), "float32")) -> R.Tensor((2, 3), 
"float32"):
+            gv: R.Tensor((2, 3), "float32") = R.sinh(x)
+            return gv
+
+    @tvm.script.ir_module
+    class Expected:
+        @R.function
+        def main(x: R.Tensor((2, 3), dtype="float32")) -> R.Tensor((2, 3), 
dtype="float32"):
+            cls = Expected
+            gv = R.call_tir(cls.tir_sinh, (x,), out_sinfo=R.Tensor((2, 3), 
dtype="float32"))
+            return gv
+
+        @T.prim_func
+        def tir_sinh(
+            rxplaceholder: T.Buffer((T.int64(2), T.int64(3)), "float32"),
+            compute: T.Buffer((T.int64(2), T.int64(3)), "float32"),
+        ):
+            T.func_attr({"tir.noalias": T.bool(True)})
+            for i0, i1 in T.grid(T.int64(2), T.int64(3)):
+                with T.block("compute"):
+                    v_i0, v_i1 = T.axis.remap("SS", [i0, i1])
+                    T.reads(rxplaceholder[v_i0, v_i1])
+                    T.writes(compute[v_i0, v_i1])
+                    compute[v_i0, v_i1] = T.sinh(rxplaceholder[v_i0, v_i1])
+    # fmt: on
+
+    mod = LegalizeOps()(Sinh)
+    tvm.ir.assert_structural_equal(mod, Expected)
+
+
+def test_sinh_symbolic():
+    # fmt: off
+    @tvm.script.ir_module
+    class Sinh:
+        @R.function
+        def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor(("m", "n"), 
"float32"):
+            m = T.int64()
+            n = T.int64()
+            gv: R.Tensor((m, n), "float32") = R.sinh(x)
+            return gv
+
+    @tvm.script.ir_module
+    class Expected:
+        @R.function
+        def main(
+            x: R.Tensor(("m", "n"), dtype="float32")
+        ) -> R.Tensor(("m", "n"), dtype="float32"):
+            m = T.int64()
+            n = T.int64()
+            cls = Expected
+            gv = R.call_tir(cls.tir_sinh, (x,), out_sinfo=R.Tensor((m, n), 
dtype="float32"))
+            return gv
+
+        @T.prim_func
+        def tir_sinh(var_rxplaceholder: T.handle, var_compute: T.handle):
+            T.func_attr({"tir.noalias": T.bool(True)})
+            m, n = T.int64(), T.int64()
+            rxplaceholder = T.match_buffer(var_rxplaceholder, (m, n))
+            compute = T.match_buffer(var_compute, (m, n))
+            for i0, i1 in T.grid(m, n):
+                with T.block("compute"):
+                    v_i0, v_i1 = T.axis.remap("SS", [i0, i1])
+                    T.reads(rxplaceholder[v_i0, v_i1])
+                    T.writes(compute[v_i0, v_i1])
+                    compute[v_i0, v_i1] = T.sinh(rxplaceholder[v_i0, v_i1])
+    # fmt: on
+
+    mod = LegalizeOps()(Sinh)
+    tvm.ir.assert_structural_equal(mod, Expected)
+
+
 def test_sqrt():
     # fmt: off
     @tvm.script.ir_module
diff --git a/tests/python/relax/test_tvmscript_parser_op_arith_cmp.py 
b/tests/python/relax/test_tvmscript_parser_op_arith_cmp.py
index d43e9a626b..a0c9218b2f 100644
--- a/tests/python/relax/test_tvmscript_parser_op_arith_cmp.py
+++ b/tests/python/relax/test_tvmscript_parser_op_arith_cmp.py
@@ -51,6 +51,7 @@ def _check(
     (relax.op.log,),
     (relax.op.negative,),
     (relax.op.round,),
+    (relax.op.rsqrt,),
     (relax.op.sigmoid,),
     (relax.op.sign,),
     (relax.op.sin,),

Reply via email to