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.
|
||||
# pylint: disable=no-else-return, invalid-name
|
||||
"""Developer API of add/remove/replace bindings in Relax."""
|
||||
|
||||
import tvm_ffi
|
||||
|
||||
import tvm
|
||||
from tvm.runtime import Object
|
||||
|
||||
from . import Binding, DataflowBlock, Expr, Function, Var, _ffi_api
|
||||
|
||||
|
||||
@tvm_ffi.register_object("relax.DataflowBlockRewrite")
|
||||
class DataflowBlockRewrite(Object):
|
||||
"""
|
||||
A binding/statement-level dataflow block rewriter.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Due to the immutable and copy-on-write nature of TVM AST nodes, the rewriting is not done in
|
||||
place. Instead, a new DataflowBlock is created and returned with mutated_dfb. Similarly, its new
|
||||
root Function is created and returned by mutated_root_fn. To apply this change for an IRModule,
|
||||
use mutate_irmodule which rewrites the old function that registered in the constructor.
|
||||
"""
|
||||
|
||||
__slots__ = ("__dict__",)
|
||||
|
||||
def __init__(self, dfb: DataflowBlock, root_fn: Function):
|
||||
"""
|
||||
Construct a rewriter with the DataflowBlock to rewrite and its root function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
dfb : DataflowBlock
|
||||
The DataflowBlock to rewrite.
|
||||
root_fn : Function
|
||||
The root function of the DataflowBlock.
|
||||
"""
|
||||
self.func_name = root_fn.__name__ if hasattr(root_fn, "__name__") else None
|
||||
self.__init_handle_by_constructor__(
|
||||
_ffi_api.DataflowBlockRewrite,
|
||||
dfb,
|
||||
root_fn, # type: ignore
|
||||
)
|
||||
|
||||
def replace_all_uses(self, old_var: Var, new_var: Var) -> None:
|
||||
"""
|
||||
Replace all uses of old_var with new_var.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
old_var : Var
|
||||
The old variable to replace.
|
||||
new_var : Var
|
||||
The new variable to replace with.
|
||||
"""
|
||||
_ffi_api.dfb_rewrite_replace_all_uses(self, old_var, new_var) # type: ignore
|
||||
|
||||
def add_binding(self, binding: Binding) -> None:
|
||||
return _ffi_api.dfb_rewrite_add_binding(self, binding) # type: ignore
|
||||
|
||||
def add(self, expr: Expr, name: str | None = None, is_dfvar: bool = False) -> None:
|
||||
"""
|
||||
Add a new statement to the DataflowBlock with an automatically generated variable name.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
expr : Expr
|
||||
The expression to add.
|
||||
name : Optional[str], optional
|
||||
Variable name, by default None
|
||||
is_dfvar : bool, optional
|
||||
The variable type, by default False
|
||||
|
||||
Notes
|
||||
-----
|
||||
If the variable name is not given, it will be automatically generated in a form of
|
||||
"tmp${COUNTER}". The variable type will be DataflowVar if is_dfvar is True, otherwise
|
||||
it will be Var. Being Var means the variables are output variables of the DataflowBlock.
|
||||
While being DataflowVar means the variables are internal variables of the DataflowBlock.
|
||||
"""
|
||||
_ffi_api.dfb_rewrite_add(self, expr, name, is_dfvar) # type: ignore
|
||||
|
||||
def remove_unused(self, var: Var, allow_undef=False) -> None:
|
||||
"""
|
||||
Remove a statement by its variable definition if and only if it is unused.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
var : Var
|
||||
The unused variable definition.
|
||||
allow_undef : bool, optional
|
||||
Whether to allow var being undefined variable, by default False
|
||||
|
||||
Raises
|
||||
------
|
||||
RuntimeError if the variable is used or undefined (allow_undef=False).
|
||||
"""
|
||||
_ffi_api.dfb_rewrite_remove_unused(self, var, allow_undef) # type: ignore
|
||||
|
||||
def remove_all_unused(self) -> None:
|
||||
"""
|
||||
Remove all unused variables.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This could remove unused variables in other DataflowBlocks as well.
|
||||
"""
|
||||
_ffi_api.dfb_rewrite_remove_all_unused(self) # type: ignore
|
||||
|
||||
def mutated_dfb(self) -> DataflowBlock:
|
||||
"""
|
||||
Returns the mutated DataflowBlock.
|
||||
"""
|
||||
return self.dfb
|
||||
|
||||
def mutated_root_fn(self) -> Function:
|
||||
"""
|
||||
Returns the mutated root function.
|
||||
"""
|
||||
ret = self.root_fn
|
||||
if self.func_name:
|
||||
ret.__name__ = self.func_name
|
||||
return ret
|
||||
|
||||
def mutate_irmodule(self, irmodule: tvm.IRModule) -> tvm.IRModule:
|
||||
"""
|
||||
Return an updated IRModule by replacing the old function with the mutated root function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
irmodule : tvm.IRModule
|
||||
The base IRModule to update.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tvm.IRModule
|
||||
The updated IRModule.
|
||||
"""
|
||||
ret = _ffi_api.dfb_rewrite_mutate_irmodule(self, irmodule) # type: ignore
|
||||
if hasattr(irmodule, "__name__"):
|
||||
ret.__name__ = irmodule.__name__
|
||||
return ret
|
||||
Reference in New Issue
Block a user