chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# 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.
|
||||
"""Test TVMScript with PEP 563 (from __future__ import annotations).
|
||||
|
||||
IMPORTANT: The `from __future__ import annotations` import below is the
|
||||
test condition itself, because we need to test compatibility with it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tvm
|
||||
import tvm.testing
|
||||
from tvm.script import ir as I
|
||||
from tvm.script import tirx as T
|
||||
|
||||
|
||||
def _normalize(func):
|
||||
"""Strip the global_symbol so function names do not affect structural equality."""
|
||||
return func.with_attr("global_symbol", "")
|
||||
|
||||
|
||||
def test_prim_func_closure_shape():
|
||||
"""Closure variable used in Buffer shape annotation."""
|
||||
|
||||
def f(M=16):
|
||||
@T.prim_func(s_tir=True)
|
||||
def func(A: T.Buffer((M,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
return func
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_16(A: T.Buffer((16,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_32(A: T.Buffer((32,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
tvm.ir.assert_structural_equal(_normalize(f(16)), _normalize(expected_16))
|
||||
tvm.ir.assert_structural_equal(_normalize(f(32)), _normalize(expected_32))
|
||||
|
||||
|
||||
def test_prim_func_closure_dtype():
|
||||
"""Closure variable used as Buffer dtype."""
|
||||
|
||||
def f(dtype="float32"):
|
||||
@T.prim_func(s_tir=True)
|
||||
def func(A: T.Buffer((16,), dtype)):
|
||||
T.evaluate(0)
|
||||
|
||||
return func
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_f32(A: T.Buffer((16,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_f16(A: T.Buffer((16,), "float16")):
|
||||
T.evaluate(0)
|
||||
|
||||
tvm.ir.assert_structural_equal(_normalize(f("float32")), _normalize(expected_f32))
|
||||
tvm.ir.assert_structural_equal(_normalize(f("float16")), _normalize(expected_f16))
|
||||
|
||||
|
||||
def test_prim_func_nested_closure():
|
||||
"""Variables from enclosing scope active on the call stack (grandparent frame fallback).
|
||||
|
||||
With PEP 563, closure-only variables are missing from __closure__ unless they
|
||||
appear in the function body. The ChainMap fallback walks the live call stack,
|
||||
so this works when the enclosing frames are still active (outer calls middle
|
||||
which applies the decorator, keeping outer's frame alive on the stack).
|
||||
"""
|
||||
|
||||
def outer(M=16):
|
||||
def middle(N=8):
|
||||
@T.prim_func(s_tir=True)
|
||||
def func(A: T.Buffer((M, N), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
return func
|
||||
|
||||
return middle()
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_16_8(A: T.Buffer((16, 8), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_32_8(A: T.Buffer((32, 8), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
tvm.ir.assert_structural_equal(_normalize(outer(16)), _normalize(expected_16_8))
|
||||
tvm.ir.assert_structural_equal(_normalize(outer(32)), _normalize(expected_32_8))
|
||||
|
||||
|
||||
def test_ir_module_closure():
|
||||
"""Closure variable in @I.ir_module class method."""
|
||||
|
||||
def f(M=16):
|
||||
@I.ir_module
|
||||
class Mod:
|
||||
@T.prim_func(s_tir=True)
|
||||
def main(A: T.Buffer((M,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
return Mod
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_16(A: T.Buffer((16,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_32(A: T.Buffer((32,), "float32")):
|
||||
T.evaluate(0)
|
||||
|
||||
tvm.ir.assert_structural_equal(_normalize(f(16)["main"]), _normalize(expected_16))
|
||||
tvm.ir.assert_structural_equal(_normalize(f(32)["main"]), _normalize(expected_32))
|
||||
|
||||
|
||||
def test_mixed_closure_usage():
|
||||
"""Closure var used in both annotation AND body -- regression check."""
|
||||
|
||||
def f(M=16):
|
||||
@T.prim_func(s_tir=True)
|
||||
def func(A: T.Buffer((M,), "float32")):
|
||||
T.evaluate(M)
|
||||
|
||||
return func
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_16(A: T.Buffer((16,), "float32")):
|
||||
T.evaluate(16)
|
||||
|
||||
@T.prim_func(s_tir=True)
|
||||
def expected_32(A: T.Buffer((32,), "float32")):
|
||||
T.evaluate(32)
|
||||
|
||||
tvm.ir.assert_structural_equal(_normalize(f(16)), _normalize(expected_16))
|
||||
tvm.ir.assert_structural_equal(_normalize(f(32)), _normalize(expected_32))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
tvm.testing.main()
|
||||
Reference in New Issue
Block a user