Files
apache--tvm/python/tvm/tirx/transform/transform.py
T
wehub-resource-sync 26446540fa
Lint / lint (push) Has been cancelled
CI / MacOS (push) Has been cancelled
CI / Windows (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

529 lines
13 KiB
Python

# 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.
"""Wrapping existing transformations."""
# pylint: disable=invalid-name, unsupported-binary-operation
import enum
from collections.abc import Callable
import tvm_ffi as _ffi
from . import _ffi_api
from . import function_pass as _fpass
def Apply(ftransform):
"""Apply ftransform to each function in the Module.
This function is a thin wrapper around tvm.tirx.transform.prim_func_pass
Parameters
----------
ftransform: tvm.tirx.PrimFunc -> tvm.tirx.PrimFunc
The transformation pass.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
# pylint: disable=unused-argument
def _transform(func, mod, ctx):
return ftransform(func)
return _fpass.prim_func_pass(_transform, opt_level=0, name="Apply") # type: ignore
def VectorizeLoop(enable_vectorize: bool = True):
"""Lower vectorization loops.
Parameters
----------
enable_vectorize : bool
Whether vectorization is enabled.
Will lower to scalar loop when it is turned off.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.VectorizeLoop(enable_vectorize) # type: ignore
def StorageRewrite():
"""Rewrite storage allocation pattern.
Moves the allocation to outer most possible scope.
Trying to share space between allocations to make
a static allocation plan when possible.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.StorageRewrite() # type: ignore
def InlinePrivateFunctions():
"""Inline calls to private functions
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.InlinePrivateFunctions() # type: ignore
def PointerValueTypeRewrite():
"""
Rewrite the pointer content type of arguments, as well as Alloc internal to the function to use
the most frequently accessed type for load/store to avoid pointer casting in backend when
possible.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.PointerValueTypeRewrite() # type: ignore
@_ffi.register_object("tirx.transform.UnrollLoopConfig")
class UnrollLoopConfig(_ffi.Object):
"""Config for unroll loop pass"""
def UnrollLoop():
"""Unroll the constant loop marked by unroll.
This pass also automatically attach pragma unroll tag to loops which meets the standard.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.UnrollLoop() # type: ignore
@_ffi.register_object("tirx.transform.RemoveNoOpConfig")
class RemoveNoOpConfig(_ffi.Object):
"""Config for remove no op pass"""
def RemoveNoOp():
"""Remove No Op from the Stmt.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.RemoveNoOp() # type: ignore
def RemoveAssume():
"""Remove all instances of builtin::assume
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.RemoveAssume() # type: ignore
def BF16ComputeLegalize():
"""Legalize bf16 compute Ops.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.BF16ComputeLegalize() # type: ignore
def FP8ComputeLegalize(promote_dtype: str = "float32"):
"""Legalize fp8 compute Ops.
Parameters
----------
promote_dtype : str
The data type we promote fp8 to, options: float16/float32.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.FP8ComputeLegalize(promote_dtype) # type: ignore
def BF16StorageLegalize():
"""Legalize bf16 storage types to u16.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.BF16StorageLegalize() # type: ignore
def FP8StorageLegalize():
"""Legalize fp8 storage types to u8.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.FP8StorageLegalize() # type: ignore
def CommonSubexprElim():
"""Replace redundant computations by new variables.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.CommonSubexprElim() # type: ignore
@_ffi.register_object("tirx.transform.StmtSimplifyConfig")
class StmtSimplifyConfig(_ffi.Object):
"""Config for stmt simplify pass"""
def StmtSimplify():
"""Run statement-level arithmetic simplifications on the TIR PrimFunc.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.StmtSimplify() # type: ignore
def ConvertSSA():
"""Convert an IRModule to be SSA form.
This pass handles cases where the same `tirx.Var` appears in
multiple functions within the same module. For example, after
extracting a fragment from one function into another, where the
same `tirx.Var` may be defined both as within the body of the
original function, and as a parameter within the hoisted function.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.ConvertSSA() # type: ignore
def MakePackedAPI():
"""Transform the PrimFuncs in the module to a packed func API.
Prior to this pass, the PrimFunc may have Buffer arguments defined
in the `PrimFuncNode::buffer_map`. This pass consumes the
`buffer_map`, using it to generate arguments that implement
the packed based TVM FFI API.
For static shapes, the `BufferNode::shape`, `BufferNode::strides`,
and `BufferNode::elem_offset` member variables are used to
generate runtime checks on the corresponding member variables in
the user-provided `DLTensor*` or `tvm.runtime.tensor` argument. (e.g. A
PrimFunc that accepts a buffer of shape `[16,32]` validates that
the `DLTensor::shape` array is `[16,32]`.)
For dynamic Buffers, in which one or more of these `BufferNode` member
variables use `tirx.Var` that are not defined by other PrimFunc
parameters, these are instead used to define the variables based on
the corresponding `DLTensor` members. (e.g. A PrimFunc that accepts a
buffer of shape `[tirx.Var("n"), tirx.Var("m")]`, when passed a
`DLTensor` of shape `[16,32]`, will define `n = 16` and `n=32`, based
on the argument's shape.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.MakePackedAPI() # type: ignore
def SplitHostDevice():
"""Annotate, split, and lower host/device functions.
This pass first annotates device regions within host functions,
then splits them into host and device-side PrimFuncs, and finally
lowers host-to-device calls into the device kernel launch ABI.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.SplitHostDevice() # type: ignore
def SkipAssert():
"""Skip assert stmt.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.SkipAssert() # type: ignore
def LowerWarpMemory():
"""Lower warp memory access to low-level device related function calls.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.LowerWarpMemory() # type: ignore
def LowerTVMBuiltin():
"""Lower tvm builtin intrinsics.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.LowerTVMBuiltin() # type: ignore
def LowerIntrin():
"""Lower target specific intrinsic calls.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.LowerIntrin() # type: ignore
def NarrowDataType(target_bits: int):
"""Narrow down Expr datatype in stmt to target_bits.
Parameters
----------
target_bits : int
The target bit configuration.
Returns
-------
fpass : tvm.transform.Pass
The result pass
Note
----
Run this pass after FlattenBuffer.
"""
return _ffi_api.NarrowDataType(target_bits) # type: ignore
def ForceNarrowIndexToInt32():
"""Force narrow down indexing expressions and integer buffers to int32 dtype.
Returns
-------
fpass : tvm.transform.Pass
The result pass
Note
----
This pass should not be used in default cases.
"""
return _ffi_api.ForceNarrowIndexToInt32() # type: ignore
def VerifyMemory():
"""Verify if func contains illegal host side direct memory access.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.VerifyMemory() # type: ignore
@_ffi.register_object("s_tir.transform.HoistIfThenElseConfig")
class HoistIfThenElseConfig(_ffi.Object):
"""Config for hoist if then else pass"""
class HoistedConditionals(enum.Flag):
"""Flags for use in HoistExpressionConfig.conditional_types
Each bitflag represents a type of expression that should be
hoisted to the outermost loop possible.
"""
Never = 0
""" No hoisting of conditionals """
IfElseStmt = 1
""" If set, look for hoist candidates in IfElseStmt """
IfElseExpr = 2
""" If set, look for hoist candidates in tirx.if_then_else """
BooleanExpression = 4
""" If set, look for hoist candidates in all boolean expressions """
UsingBlockVar = 8
""" If set, allow hoisting of conditionals that use a block variable (e.g. threadIdx.x) """
All = IfElseStmt | IfElseExpr | BooleanExpression | UsingBlockVar
""" Enable all hoisting of conditionals"""
class HoistedLetBindings(enum.Flag):
"""Flags for use in HoistExpressionConfig.let_binding_types
Each bitflag represents a type of let binding expression that should be
hoisted to the outermost loop possible.
"""
Never = 0
""" No hoisting of let bindings """
RequiredByConditional = 1
""" Bindings that are used by a hoisted conditional """
Bind = 2
""" Bindings occurring in Bind nodes """
LetExpr = 4
""" Bindings occurring in Let expressions """
All = RequiredByConditional | Bind | LetExpr
""" Enable all hoisting of let bindings """
@_ffi.register_object("s_tir.transform.HoistExpressionConfig")
class HoistExpressionConfig(_ffi.Object):
"""Config for hoist expression pass"""
def FlattenBuffer():
"""Flatten the multi-dimensional BufferLoad and BufferStore to single dimensional
BufferLoad/BufferStore for the TIR not contains opaque block.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.FlattenBuffer() # type: ignore
def BindTarget(target):
"""Annotate a PrimFunc with a given target.
Parameters
-------
target : tvm.target.Target
target
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.BindTarget(target) # type: ignore
def AnnotateEntryFunc():
"""Set a PrimFunc as the entry point if it is only function in IRModule.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.AnnotateEntryFunc() # type: ignore
def Filter(fcond: Callable):
"""Filter out PrimFuncs that does not satisfy the given condition.
`fcond` should be a function that takes a primfunc and returns boolean.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.Filter(fcond) # type: ignore
def TilePrimitiveDispatch():
"""Lower TIRx tile primitive calls through the active backend dispatch table.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.TilePrimitiveDispatch() # type: ignore
def LowerTIRx():
"""Lower TIR to a lower-level IR.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.LowerTIRx() # type: ignore
def LowerTIRxOpaque():
"""Lower opaque constructs in TIRX programs.
Handles AllocBuffer lowering, For(thread_binding) to AttrStmt(thread_extent)
conversion, unit loop elimination, and pragma annotation handling.
This is the tirx-specific counterpart of s_tir.LowerOpaqueBlock,
without any SBlock/SBlockRealize handling.
Returns
-------
fpass : tvm.transform.Pass
The result pass
"""
return _ffi_api.LowerTIRxOpaque() # type: ignore