# 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. import pytest import tvm import tvm.script from tvm import relax from tvm.script import ir as I from tvm.script import relax as R from tvm.script import tirx as T def test_vm_builtin_lower_mem_alloc_storage(): @I.ir_module class Before: @R.function def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor: R.func_attr({"relax.force_pure": True}) m, n = T.int64(), T.int64() storage = R.memory.alloc_storage(R.shape([m * n * 4]), 0, "global", "uint8") alloc = R.memory.alloc_tensor(storage, 0, R.shape([m, n]), "float32") _ = R.call_packed( "test.op.identity", x, alloc, ty_args=(R.Tensor(ndim=2, dtype="float32")) ) gv0 = alloc return gv0 @I.ir_module class Expected: @R.function def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor: # we expected RemovePurityChecking to have been called first R.func_attr({"relax.force_pure": True}) m, n = T.int64(), T.int64() storage = R.vm.alloc_storage(R.shape([m * n * 4]), R.prim_value(0), "uint8", "global") alloc = R.vm.alloc_tensor(storage, R.prim_value(0), R.shape([m, n]), "float32") _ = R.call_packed( "test.op.identity", x, alloc, ty_args=(R.Tensor(ndim=2, dtype="float32")) ) gv0 = alloc return gv0 After = relax.transform.LowerRuntimeBuiltin()(Before) tvm.ir.assert_structural_equal(Expected, After) def test_vm_builtin_alloc_tensor_raises_error(): """R.builtin.alloc_tensor should be handled earlier""" @I.ir_module class Before: @R.function def main(x: R.Tensor(("m", "n"), "float32")) -> R.Tensor: R.func_attr({"relax.force_pure": True}) m, n = T.int64(), T.int64() alloc = R.builtin.alloc_tensor(R.shape([m, n]), runtime_device_index=0, dtype="float32") _ = R.call_packed( "test.op.identity", x, alloc, ty_args=(R.Tensor(ndim=2, dtype="float32")) ) gv0 = alloc return gv0 with pytest.raises(RuntimeError): relax.transform.LowerRuntimeBuiltin()(Before) def test_vm_reshape_may_be_var(): """R.reshape does not require an in-line R.shape""" @I.ir_module class Before: @R.function def main(A: R.Tensor([16], "float32"), shape: R.Shape): R.func_attr({"relax.force_pure": True}) reshape = R.reshape(A, shape) return reshape @I.ir_module class Expected: @R.function def main(A: R.Tensor([16], "float32"), shape: R.Shape): R.func_attr({"relax.force_pure": True}) reshape = R.call_packed( "vm.builtin.reshape", A, shape, ty_args=R.Tensor(shape, dtype="float32"), ) return reshape After = relax.transform.VMBuiltinLower()(Before) tvm.ir.assert_structural_equal(Expected, After) def test_vm_reshape_using_tensor_to_shape(): """Shape argument of R.reshape may come from tensor_to_shape""" @I.ir_module class Before: @R.function def main(A: R.Tensor([16], "float32"), shape_tensor: R.Tensor([2], "int64")): R.func_attr({"relax.force_pure": True}) shape = R.tensor_to_shape(shape_tensor) reshape = R.reshape(A, shape) return reshape @I.ir_module class Expected: @R.function def main(A: R.Tensor([16], "float32"), shape_tensor: R.Tensor([2], "int64")): R.func_attr({"relax.force_pure": True}) shape = R.call_packed( "vm.builtin.tensor_to_shape", shape_tensor, ty_args=R.Shape(ndim=2), ) reshape = R.call_packed( "vm.builtin.reshape", A, shape, ty_args=R.Tensor(shape, dtype="float32"), ) return reshape After = relax.transform.VMBuiltinLower()(Before) tvm.ir.assert_structural_equal(Expected, After) if __name__ == "__main__": tvm.testing.main()