174d09ee2c
* [TIR] Added BufferLoadNode::LegalizeDtype
When modifying a BufferLoad object, the return dtype must also be
updated. This exposes the legalization function, so that passes that
use `BufferLoad::CopyOnWrite` to modify the buffer/indices don't need
to repeat the logic to update the dtype returned.
* Replacing Store/Load in Stmt/Expr Visitor/Mutator
* Removing Store/Load from optimization passes
- UpdatePointerStorageScope
- UnrollLoop
- ThreadSync
- LinearAccessPatternFinder
- StoragePlanRewriter
- VectorTypeRewriter
- VectorTypeAccessChecker
- NarrowDataType
- IRConvertSSA
- CompactBufferRegion
* Removing Store/Load from examples
- ConvertAddToSubtract
* Replacing Store/Load in StorageFlatten
Now, outputs BufferLoad/BufferStore with a flattened buffer object.
temp commit, replacing Store/Load, BufferBindUnwrapper
temp commit, replacing Store/Load, StorageFlattener
* Replacing Store/Load in utility passes.
- StmtSimplifier
- IRSubstitute
- BaseInliner
- FeatureVisitor
* Replacing Store/Load in analysis functions
- StorageAccessVisitor
- VarTouchedAnalysis
- MemoryAccessVerifier
- InplaceOpVerifier
- GPUCodeVerifier
- VarTouchVisitor
- LCADetector
- BlockReadWriteDetector
- InstrumentBoundCheckers
* Replacing Store/Load in lowering/legalization passes.
- MakeCrossThreadReduction
- CacheReadRewriter/CacheWriteRewriter
- InjectVirtualThread
- InjectDoubleBuffer
- InjectCopyIntrin
- LowerWarpMemory
- LowerThreadAllreduce
- LowerThreadAllreduce
- LowerCustomDatatypes
- LowerTVMBuiltin
- CoProcSync
- MergeDynamicSharedMemAllocations
- VectorizeLoop
- BF16Legalize
* Replacing Load/Store in codegens.
- Device code generators
- CodegenC
- CodegenLLVM
- CodeGenOpenCL
- Utilities used during codegen
- ArgBinder
- MakePackedAPI
- ReturnRewriter
- SplitHostDevice
- Execution environments
- CodeGenStackVM
- CodeGenHybrid
- AOTExecutorCodegen
* [UnitTest] Add unit tests to test physical layout remapping.
* Updated tvm::address_of() to hold BufferLoad instead of Load.
* [TIR] Added IndexMap class.
Holds a set of variables representing the input indices and
expressions in terms of those input indices.
TODO:
- Add validation, the index mapping should be invertible.
- Add helper function, apply mapping to a set of indices.
- Add helper function, apply mapping to bounds of input indices.
* Updated Buffer::vstore/vload to return BufferLoad/BufferStore objects.
StorageFlatten/FlattenBuffer passes updated to modify the
buffer/indices directly, rather than using vload/vstore.
- Primary purpose of vstore/vload is to allow IR written in python to
define vectorized load/store. This usage is maintained by returning
a BufferLoad/BufferStore node whose index is a Ramp.
- Previously, vstore/vload was also used to compute the 1-d physical
index of a location within a N-d tensor. This usage will no longer
be allowed, as it would not allow layout transformations to be
performed after a schedule definition, but any uses of the buffer
are flattened.
* [TE] Added Stage::transform_layout to the C++ TE implementation.
Adds an `Array<IndexMap>` in the stage to define the transformations
to be applied on the tensor's layout. As of this commit, this mapping
isn't propagated into the TIR graph yet.
* Replace Store/Load with BufferStore/BufferLoad in ir_builder
* [TE] Added Stage.transform_layout to the Python TE interface.
Allows users to specify `s[A].transform_layout(mapping)`, and
propagate into the TE definitions.
* Added pre_flattened_shape/pre_flattened_stride fields to Buffer.
The shape and stride checks performed in ArgBinder::BindDLTensor
(called from MakePackedAPI) require the tensor shape/strides prior to
index flattening. Therefore, though it is no longer used by the
low-level code generators, we must maintain that information for use
in MakePackedAPI.
* [UnitTest] Test N-d indices exposed to low-level codegen
When using te.AXIS_SEPARATOR in the call to .transform_layout, this
should define groups of axes, each of which is flattened to a single
axis, then exposed to the low-level codegen.
* [TIR] Added PrimFunc attribute "layout_transform_map", filled from TE.
Propagated the TE definition of the physical layout into the TIR
graph.
* Added pre_flattened_type.
If a boolean tensor is backed by an int8 buffer, the check on the
argument buffer's type should be against the boolean type.
When rebasing this PR, should be placed after the addition of
pre_flatten_shape/pre_flatten_strides.
* [UnitTest] Added tests for loop iteration order.
After transformation, the iteration order should follow the new
transformed axes. In addition, the loop iteration variables should be
exposed through the TE interface for further manipulation.
* [TIR] Added BufferNode::axis_separators
- Add axis_separators to represent divisions between groups
of tensor axes, where each group is flattened into a single
output axis, to be exposed to the low-level code generators.
- Expose axis_separators to the python interface.
- Update existing C++ calls to the Buffer() constructor.
* [TIR] Added ApplyLayoutTransforms as part of StorageFlatten.
For any buffers that have layout transforms defined in the
"layout_transform_map" attribute of a PrimFunc, rewrite access into
the buffer such that they use the updated ordering.
* Update usage of ir_builder where necessary.
* [TE] Implement te::Transform
Similar to Fuse and Split, this represents a modification to the
existing loop iterations.
* [TE] Added Stage::set_axis_separators.
In C++, this is implemented as an `Array<IntImm>`, specifying
pre-flatteneing axes after which a new post-flattening should be
started. The python interface uses a sentinel value
`te.AXIS_SEPARATOR` in the call to `transform_layout`, which is then
used to define the array of axis separators.
* [TIR] Expose tir.transform.ApplyLayoutTransforms for testing
* [TE] Rewrite loop iteration order
After .transform_layout, rewrite leaf_iter_vars to follow the updated
order. Use the te::Transform iter_var relationship to track use of
the transformed variable.
* [TE] Fill BufferNode::axis_separators from StageNode
During ScheduleOps and SchedulePostprocToPrimfunc, the axis separators
defined in the stage must be passed through to the TIR BufferNode.
* [TE] Return transformed iteration variables
* Moved Buffer's pre-flatten information to PrimFunc.
Since the pre-flatten information is only used for validating user
inputs, it makes much more sense to store it alongside the buffer_map.
* Updated ethos-u C++ unit tests to remove use of Load/Store.
* Bugfix, layout transformation.
Error occured during conversion from TE to IRModule, when layout
transforms were applied to a reader of a `cache_read`.
* In test directory, replacing all instances of T.load.
* Return buffer object from tvm.tir.script.scope_handler.Allocate
Now that the load/store require buffer objects, allocation should also
return a buffer object to be used.
* Added .astype to tvm.script.tir.node.BufferSlice
Since `buf[i]` returns a `BufferSlice`, this lets the TIR examples
that use `buf[i].astype('out_dtype')` continue functioning.
* Replacing all T.store TIR calls.
* Added LOG(FATAL) in constructor of Store/Load nodes.
* Updated tvmscript parser to report error for Store/Load nodes.
* [TVMScript] Added T.preflattened_buffer stmt
Used to specify `PrimFunc::preflattened_buffer_map`. Takes an argument
of the postflattened buffer, so that it will work for both simple
declarations and `T.match_buffer` statements without needing to
introduce a param handle. All other arguments are identical to
`T.match_buffer.`
* [TVMScript] Updated TVMscript for BufferLoad/BufferStore
- Use `T.preflattened_buffer` calls in TVMScript to represent
`PrimFunc::preflattened_buffer_map`.
- Remove `T.buffer_decl` for return value of `T.allocate`, now that
`T.allocate` returns a buffer.
- For buffer access as a different type, make a `T.buffer_decl` for
those accesses.
* Updated test_tvmscript_roundtrip.py for BufferLoad/BufferStore.
* Updated TIR reference in USMP pool allocation unit tests.
Using let var handles as the data pointer in buffers, rather than just
as `T.load`/`T.store` arguments, requires annotation as
`T.Ptr[T.primtype]`, rather than as `T.handle`.
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* fixup! Replacing all T.store TIR calls.
* fixup! Replacing all T.store TIR calls.
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* fixup! In test directory, replacing all instances of T.load.
* tir.ComputeInline, correct variable count.
Previously, this metaschedule primitive relied on `tir::UndefinedVars`
ignoring the data pointer of BufferLoad/BufferStore nodes. When
`tir::UndefinedVars` was updated to visit the data pointer, similar to
the previous behavior when visiting Load/Store nodes, this caused the
count of undefined variables to be unexpectedly high.
* fixup! Replacing all T.store TIR calls.
* fixup! Updated Buffer::vstore/vload to return BufferLoad/BufferStore objects.
* fixup! In test directory, replacing all instances of T.load.
* fixup! In test directory, replacing all instances of T.load.
* fixup! Replacing all T.store TIR calls.
* Expose Buffer index flattening function to Python.
* Updated test_tir_buffer.py offset tests.
Replacing calls to `Buffer.vload` with `Buffer.offset_of`, when
testing the index calculations.
* fixup! Replacing all T.store TIR calls.
* fixup! Replacing all T.store TIR calls.
* fixup! Updated Buffer::vstore/vload to return BufferLoad/BufferStore objects.
* fixup! Replacing Store/Load in lowering/legalization passes.
* fixup! Replacing all T.store TIR calls.
* fixup! Updated ethos-u C++ unit tests to remove use of Load/Store.
* fixup! Replacing Store/Load in lowering/legalization passes.
Fix linting for inject_double_buffer.cc
* fixup! Updated ethos-u C++ unit tests to remove use of Load/Store.
* fixup! Added .astype to tvm.script.tir.node.BufferSlice
* fixup! In test directory, replacing all instances of T.load.
* fixup! Replacing all T.store TIR calls.
* fixup! Replacing all T.store TIR calls.
* fixup! In test directory, replacing all instances of T.load.
* fixup! Replacing all T.store TIR calls.
* fixup! Replacing Store/Load in lowering/legalization passes.
* [UnitTests] Added T.preflattened_buffer in expected result
* fixup! In test directory, replacing all instances of T.load.
* [UnitTests] Bound checker update, compare against N-d buffer bounds.
* Fixup, bound checker vectorize test.
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* [UnitTest] Fixed breakage in InjectRollingBuffer test.
Needed a bit more re-writing than usual, because the test was
explicitly calling lowering passes, then calling `tvm.build`. Fixed
by using the standard lowering flow, with preprocessing steps
inserting with `tir.add_lower_pass`.
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* [UnitTest] Fixed breakage in flatten buffer unit tests.
- Updated pass to allow BufferStore/BufferLoad nodes to be visited
before the block's alloc buffer.
- Added `T.preflattened_buffer` annotations.
* fixup! Return buffer object from tvm.tir.script.scope_handler.Allocate
* [UnitTests] Fixed breakage in test_tir_buffer.py
- Updated vload test for new behavior.
- Added test for offset_of, testing behavior no longer in vload.
- Added null check for buffer visitor.
* fixup! Replacing Load/Store in codegens.
* [UnitTest] ComputeInline, opaque access test updates
* [UnitTest] Fixup, allow unit test to use `ib.pointer()[0]`.
* fixup! Replacing Load/Store in codegens.
The updated CodegenLLVM should use the BufferStore/BufferLoad
convention of indexing by `sizeof(dtype)`, rather than
`sizeof(dtype.element_of())`.
* fixup! Replacing Store/Load in lowering/legalization passes.
BF16Legalize should also update the preflattened_buffer_map, since it
is overwriting the `BufferNode::data` stored in the buffer_map.
* fixup! Replacing all T.store TIR calls.
* Fixed failing codegen c host unit tests.
- Generated functions were making `uint8_t*` parameter arguments for
array handle for return value, rather than the earlier `void*`.
- New parameter type was due to using
`PointerType(PrimType(DataType::UInt(8)))` as the type annotation, to
be usable as `BufferNode::data`.
- Changing to `PointerType(PrimType(DataType::Void()))` still allows
usage as buffer, more appropriately expresses semantics.
- Updated C codegens to allow `void*` types to be generated from
variables with type annotation, in addition to the previous behavior
of `DataType::Handle()` variables without type annotation.
* Fixup, StorageFlatten when applied to post-StorageRewrite functions.
Identified in a test that applied `tvm.lower`, then `tvm.build` on the
result. If the result of an allocate node is used as the backing
buffer for multiple buffers, such as the output of the StorageRewrite
pass, then StorageFlatten would erroneously think that the second
occurrence was an usage without earlier definition.
* fixup, StorageFlatten
When flattening a boolean buffer, the backing buffer should have type
int8, not the preflattened buffer.
* Bugfix, correctly represent void* in LLVM IR.
* Update, replace tir.Load with tir.BufferLoad
* Added TVMScript error check for matching buffer/index dimensionality
Needed for tests/python/unittest/test_tvmscript_error_report.py::test_high_dim_store
* Bugfix, correct return type when lowering custom datatype.
* Bugfix, removed unused primfunc from test_tvmscript_complete.py
* Updated test_meta_schedule_postproc_verify_gpu_code.py TIR
Replaced Load/Store with BufferLoad/BufferStore.
* Allowed ramp nodes with buffer use analysis.
* Updated tests in test_meta_schedule_postproc_verify_gpu_code.py
Needed dummy writes to prevent buffer resizing, in order to trigger
the verification failure due to memory limits.
* Updated TIR examples to be compatible with buffer dimension check.
* Corrected section header in docstring.
* Corrected indices size check in CogeGenC.
* Fixed breakage in LowerThreadAllreduce.
Since the AllocateNode is rewritten, any buffers that refer to those
variables must also be rewritten.
* [UnitTests] Replaced Store/Load in CUDA codegen tests.
* Resolved breakage in C-based codegen for vectorized store/load.
Needed to update to new convention of using the buffer's element type
as the stride.
* Bugfix, incorrect LCA for buffer access in root scope.
This had been present before the BufferLoad/BufferStore changes, but
hadn't triggered on tests using Load/Store nodes.
* Added docstrings for TransformNode member variables.
* Added TODO for future removal of preflattened_buffer_map.
* Fixup, transform layout + cache write tests.
The correct sequence is to first apply any caching as needed, then to
apply layout transformations, and finally to apply thread binds for
the computation step.
* Bugfix, correct element type for scalarized access.
* Bugfix, cuda buffer indexing when declared as different type.
* Cuda codegen, update reference.
* Bugfix, lower allreduce
Loads of the output of the reduction should be replaced for all
buffers sharing a buffer pointer, not just for the buffer object
itself.
* Removed obsolete comment.
* Changed PrimFunc constructor preflattened_buffer_map to Optional
* Removed flatten_buffer argument from T.match_buffer.
* Correct call to VarUseDefAnalysis::VisitBuffer
* Reverted unintentional testing change, lanes=2.
* Updated lower_cross_thread_reduction to use buffer in allreduce
* Updated transform_layout test to disable CSE
* Updated CSE unit tests to use BufferStore
* Replaced Store/Load for vta.transform and unit tests.
* Updated unit tests for lower_cross_thread_reduction.
* Updated arange to use scalar tensors.
The start/stop/step tensors are declared as 0-d scalar tensors, but
were accessed as 1-d tensors.
* Fix breakage in ethosu constant encoding.
Buffers generated by "ethosu_copy" should have their buffer objects
rewritten, but shouldn't have their size updated in ethosu-specific
Call nodes.
* Fix breakage in ethosu call argument checks.
Need to pull out indices from BufferLoad holders, not Load.
* Resolve breakage from mismatched shape/index dimensions
* Split out encoded parameters from preflattened buffer map.
* Updated buffer shape/index dimensions to match in more ethosu tests
* Fixed lint error
* Removed debug code
* Moved arith::Analyzer local variable to class member
* Fixed SSA conversion of allocations.
Can occur if allocation is inside an unrolled loop. Added unit test
to catch this failure mode.
* Ethos-u index/buffer dimension updates.
* Updated ethosu passes to handle buffer load/store.
* Resolved bug in tvmscript printing of duplicate buffers.
* Fix breakage in ethos-u test_assign_addresses, encode constants
* Apply same changes to T.allocate_const as to T.allocate
Return a buffer when used in TVMScript, allow for aliasing buffers.
* Fix lint errors.
* Further updates for ethos-u tests.
* Updated ethos.u buffer sizes in test.
* Updated tir.BindParams to use BufferLoad instead of Load.
* Updated topi.cuda.scan implementation to follow buffer dimensions.
* Resolved breakage when flattening AllocateConst nodes.
* Resolved breakages from latest merge with main.
* Corrected error in merge.
* Use empty indices for rank-0 tensor.
* Added ir_builder workaround for 1-d indexing.
* Consistent buffer access type in LLVM codegen, to match C codegen
* StorageRewrite, update indices of modified buffers.
* Dynamic relay nodes, access 0-d tensors with 0-d indices.
* BFloat16 legalization, update buffer type.
* Updated meshgrid to use 0-d index for 0-d buffer.
* Corrected boolean handling in Allocate nodes.
* Added workaround to unpack 1-d Tensor indices into N-d buffer indices.
* Resolved a few more failures in relay tests on cuda.
* Resolve linting
* CI bump
* Updated renormalize_split_pattern tests to use BufferLoad/BufferStore
* Fixed cuda codegen checks for BufferStore/Ramp.
* Simplify indices further, needed to avoid cuda register limit.
* fixed dyn onehot shape func accessing 1d buffer with ()
* Fixed codegen indexing for int4 scalar types.
* Temporary workaround for incorrect constant folding.
Need to further investigate vectorized LLVM constants
* s/find_allocate_usage/FindAllocateUsage/g
* Added buffer type consistency TODO.
* Improved comment on address_of Op.
* Rename LegalizeDtype to LegalizeDType, made private.
* fix format and lint errors
* Disable vectorization of AllocateConst buffer in StorageRewrite.
* Pass buffer_map through to the PrimFunc in cmsisnn
* try disabling problematic winograd test case
* try different way of buffer mapping in storage_rewrite
* Removed unnecessary ramp node in ir_builder.
* Updated LLVM codegen for buffer indexing.
TVM data arrays are always densely packed. If the LLVM type
corresponding to a vectorized TVM datatype contains padding for
alignment, the array location should be computed based on the
primitive element type.
Co-authored-by: Masahiro Masuda <masahi129@gmail.com>
Co-authored-by: adstraw <astraw@octoml.ai>
809 lines
19 KiB
Python
809 lines
19 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
|
|
from typing import Optional
|
|
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.tir.transform.prim_func_pass
|
|
|
|
Parameters
|
|
----------
|
|
ftransform: tvm.tir.PrimFunc -> tvm.tir.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 Filter(fcond):
|
|
"""Filter functions by the calling convention attribute.
|
|
|
|
Parameters
|
|
----------
|
|
fcond : tvm.tir.PrimFunc -> bool
|
|
The condition of the filtering.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
# pylint: disable=unused-argument
|
|
def _transform(func, mod, ctx):
|
|
return func if fcond(func) else None
|
|
|
|
return _fpass.prim_func_pass(_transform, opt_level=0, name="Filter") # type: ignore
|
|
|
|
|
|
def InjectPrefetch():
|
|
"""Inject prefetch instructions into stmt.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectPrefetch() # type: ignore
|
|
|
|
|
|
def ApplyLayoutTransforms():
|
|
"""Reshape buffers that appear in the "layout_transform_map"
|
|
fucntion attribute.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
|
|
"""
|
|
return _ffi_api.ApplyLayoutTransforms() # type: ignore
|
|
|
|
|
|
def StorageFlatten(cache_line_size, create_bound_attribute: bool = False):
|
|
"""Flatten the multi-dimensional read/write to 1D.
|
|
|
|
|
|
Parameters
|
|
----------
|
|
cache_line_size: int
|
|
The size of CPU cache line.
|
|
|
|
create_bound_attribute:
|
|
Whether to create bound attributes.
|
|
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.StorageFlatten(cache_line_size, create_bound_attribute) # type: ignore
|
|
|
|
|
|
def TextureFlatten():
|
|
"""Flatten the multi-dimensional read/write to 2D.
|
|
|
|
|
|
Parameters
|
|
----------
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.TextureFlatten() # type: ignore
|
|
|
|
|
|
def InjectCopyIntrin(pragma_key: str, fintrin):
|
|
"""Inject virtual thread loops.
|
|
|
|
Parameters
|
|
----------
|
|
pragma_key : str
|
|
The pragma key for hint of copy.
|
|
|
|
fintrin : function
|
|
The function with signature copyintrin(src, dst, pad_before, pad_after, pad_value)
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectCopyIntrin(pragma_key, fintrin) # type: ignore
|
|
|
|
|
|
def CoProcSync():
|
|
"""Detect and insert sync points to co-processor.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.CoProcSync() # type: ignore
|
|
|
|
|
|
def LiftAttrScope(attr_key: str):
|
|
"""Lift common attrs with attr_key to outer scope.
|
|
|
|
Parameters
|
|
----------
|
|
attr_key : str
|
|
The attribute key to be checked.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LiftAttrScope(attr_key) # type: ignore
|
|
|
|
|
|
def LoopPartition():
|
|
"""Inject virtual thread loops.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LoopPartition() # 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 InjectVirtualThread():
|
|
"""Inject virtual thread loops.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectVirtualThread() # type: ignore
|
|
|
|
|
|
def InjectDoubleBuffer():
|
|
"""Inject double buffer statements.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectDoubleBuffer() # type: ignore
|
|
|
|
|
|
def InjectRollingBuffer():
|
|
"""Inject rolling buffer statements.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectRollingBuffer() # 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 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
|
|
|
|
|
|
def RemoveNoOp():
|
|
"""Remove No Op from the Stmt.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.RemoveNoOp() # type: ignore
|
|
|
|
|
|
def BF16Legalize():
|
|
"""Legalize bf16 typed Ops.
|
|
Runs BF16Promote, BF16CastElimination and BF16TypeLowering
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.BF16Legalize() # type: ignore
|
|
|
|
|
|
def BF16Promote():
|
|
"""Promote bf16 to fp32. Add a cast to fp32
|
|
before Ops, then add a cast back to bf16.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.BF16Promote() # type: ignore
|
|
|
|
|
|
def BF16CastElimination():
|
|
"""Eliminate verbose casting between fp32 and bf16
|
|
Checks if the AST has the pattern:
|
|
castto32(castto16(some_fp32_op(...)))
|
|
The verbose casting is generated by BF16Promote for multiple
|
|
bf16 Ops in a row. e.g.:
|
|
X[i] + Y[i] + T[i] =>
|
|
bf16((float32(bf16((float32(X[i]) + float32(Y[i])))) + float32(T[i])))
|
|
After this pass:
|
|
bf16(float32(X[i]) + float32(Y[i]) + float32(T[i]))
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.BF16CastElimination() # type: ignore
|
|
|
|
|
|
def BF16TypeLowering():
|
|
"""Replace all bf16 type with uint16. Also lower the casting
|
|
between fp32 and bf16
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.BF16TypeLowering() # type: ignore
|
|
|
|
|
|
def CommonSubexprElimTIR(enable_cse_tir: bool = True):
|
|
"""Replace redundant computations by new variables.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.CommonSubexprElimTIR(enable_cse_tir) # type: ignore
|
|
|
|
|
|
def RewriteUnsafeSelect():
|
|
"""Detect and rewrite unsafe select that contains memory access.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.RewriteUnsafeSelect() # type: ignore
|
|
|
|
|
|
def Simplify():
|
|
"""Run arithmetic simplifications on the statements and expressions.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.Simplify() # type: ignore
|
|
|
|
|
|
def InstrumentBoundCheckers():
|
|
"""Instruments bound checkers.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InstrumentBoundCheckers() # type: ignore
|
|
|
|
|
|
def LowerCustomDatatypes():
|
|
"""Lower custom datatypes.
|
|
|
|
See tvm::datatypes::Registry for more information on adding custom datatypes.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerCustomDatatypes() # type: ignore
|
|
|
|
|
|
def MakePackedAPI(num_unpacked_params: int = -1):
|
|
"""Transform the PrimFuncs in the module to a packed func API.
|
|
|
|
Parameters
|
|
----------
|
|
num_unpacked_params : int
|
|
Number of parameters that we hope to directly pass via normal arguments
|
|
following the PackedFunc input signature. If it is specified as -1 or it
|
|
is less than the number of arguments, the pass will packed arguments still.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.MakePackedAPI(num_unpacked_params) # type: ignore
|
|
|
|
|
|
def MakeUnpackedAPI():
|
|
"""Transform the PrimFuncs in the module to a C API compatible with internal calls.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.MakeUnpackedAPI() # type: ignore
|
|
|
|
|
|
def SplitHostDevice():
|
|
"""Split the function into a host function and device functions.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.SplitHostDevice() # type: ignore
|
|
|
|
|
|
def DecorateDeviceScope():
|
|
"""Decorate all the function's body as device function.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.DecorateDeviceScope() # type: ignore
|
|
|
|
|
|
def SkipAssert():
|
|
"""Skip assert stmt.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.SkipAssert() # type: ignore
|
|
|
|
|
|
def ThreadSync(storage_scope: str):
|
|
"""Insert sync between parallel read/write of shared buffers.
|
|
|
|
Parameters
|
|
----------
|
|
storage_scope: str
|
|
The target storage scope.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.ThreadSync(storage_scope) # type: ignore
|
|
|
|
|
|
def LowerThreadAllreduce():
|
|
"""Lower cross thread alleduce.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerThreadAllreduce() # type: ignore
|
|
|
|
|
|
def InferFragment():
|
|
"""Infer the TensorCore fragment infomation using tensor intrinsics.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InferFragment() # 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 LegalizePackedCalls():
|
|
"""Legalize packed calls to have its arguments wrapped in TVMValues
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LegalizePackedCalls() # type: ignore
|
|
|
|
|
|
def LowerIntrin():
|
|
"""Lower target specific intrinsic calls.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerIntrin() # type: ignore
|
|
|
|
|
|
def LowerDeviceStorageAccessInfo():
|
|
"""Lower attached storage access information on device.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
|
|
Note
|
|
----
|
|
Run this pass after all storage access analysis finish.
|
|
"""
|
|
return _ffi_api.LowerDeviceStorageAccessInfo() # type: ignore
|
|
|
|
|
|
def CombineContextCall():
|
|
"""Combine context calls in the host function.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.CombineContextCall() # type: ignore
|
|
|
|
|
|
def NarrowDataType(target_bits: int):
|
|
"""Narrow down PrimExpr 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 StorageFlatten.
|
|
"""
|
|
return _ffi_api.NarrowDataType(target_bits) # 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
|
|
|
|
|
|
# pylint: disable=no-else-return,inconsistent-return-statements
|
|
def HoistIfThenElse(variant: Optional[str] = None):
|
|
"""Hoist loop-invariant IfThenElse nodes to outside the eligible loops.
|
|
|
|
Parameters
|
|
----------
|
|
variant : Optional[String]
|
|
The variant of the pass.
|
|
variant can have any one of following values ["basic", None(Default)].
|
|
|
|
The basic variant supports basic hoisting scenarios where it expects
|
|
the For & If Nodes are in place consecutively and does not involve
|
|
global scope variables or more advanced scenarios.
|
|
|
|
Default variant supports all hoisting scenarios,i.e., {"Basic" + "Advanced"}
|
|
supported with control with PassContext configs like below:
|
|
|
|
config={"tir.HoistIfThenElse": {"support_block_scope_hosting": True}}
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
if variant == "basic":
|
|
return _ffi_api.HoistIfThenElseBasic() # type: ignore
|
|
elif variant is None:
|
|
return _ffi_api.HoistIfThenElse() # type: ignore
|
|
|
|
|
|
def LowerCrossThreadReduction():
|
|
"""Lower cross-thread reduction from thread bindings to
|
|
intrinsic function calls.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerCrossThreadReduction() # type: ignore
|
|
|
|
|
|
def LowerInitBlock():
|
|
"""Lower block init stmt into IfThenElse statements.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerInitBlock() # type: ignore
|
|
|
|
|
|
def PlanAndUpdateBufferAllocationLocation():
|
|
"""Locate the buffer allocation to the exact position (usually is
|
|
the lca of buffer access). This pass will inject opaque block
|
|
with alloc_buffers at the allocation site.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.PlanAndUpdateBufferAllocationLocation() # type: ignore
|
|
|
|
|
|
def ConvertBlocksToOpaque():
|
|
"""Substitute all the block vars with the PrimExprs they are bound to, indicated by
|
|
the corresponding iter_values in BlockRealize, and then convert the blocks into
|
|
opaque ones by removing all the iter_values in BlockRealize and iter_vars in Block.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.ConvertBlocksToOpaque() # type: ignore
|
|
|
|
|
|
def CompactBufferAllocation():
|
|
"""Compact the buffer access region. by removing the buffer regions
|
|
that are not accessed, i.e. narrowing the buffer shape and adjust
|
|
the access region if necessary.
|
|
|
|
Example
|
|
-------
|
|
|
|
Before narrowing, ``B`` is a ``[16, 16]`` buffer, but only a
|
|
skinny vector ``B[i, 0:16]`` is accessed.
|
|
|
|
.. code-block:: python
|
|
|
|
for i in range(0, 16):
|
|
with T.block():
|
|
B = T.alloc_buffer(16, 16)
|
|
for j in range(0, 16):
|
|
B[i, j] = A[i, j] + 1
|
|
for j in range(0, 16):
|
|
C[i, j] = B[i, j] + 1
|
|
|
|
This pass narrows the buffer shape and adjust its accessed region
|
|
accordingly. In this particular case, because only a ``1 * 16``
|
|
vector of ``B`` is accessed, the pass narrows ``B`` to shape ``[1,
|
|
16]``, and changes the access to ``B[i, j]`` to ``B[0, j]``.
|
|
|
|
.. code-block:: python
|
|
|
|
for i in range(0, 16):
|
|
with T.block():
|
|
B = T.alloc_buffer(1, 16)
|
|
for j in range(0, 16):
|
|
B[0, j] = A[i, j] + 1
|
|
for j in range(0, 16):
|
|
C[i, j] = B[0, j] + 1
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
|
|
"""
|
|
return _ffi_api.CompactBufferAllocation() # type: ignore
|
|
|
|
|
|
def LowerMatchBuffer():
|
|
"""Remove match buffers inside the block. Also, it will validate the binding.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.LowerMatchBuffer() # type: ignore
|
|
|
|
|
|
def FlattenBuffer():
|
|
"""Flatten the multi-dimensional BufferLoad and BufferStore
|
|
to single dimensional Load/Store. Also remove Block to
|
|
ensure that the flattened TIR can not be scheduled again.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.FlattenBuffer() # type: ignore
|
|
|
|
|
|
def UnifyThreadBinding():
|
|
"""Unify all the thread bindings for "blockIdx.x/y/z",
|
|
"threadIdx.x/y/z", and "vthread.x/y/z". Before the unification,
|
|
two vars that are bound to a thread axis (e.g., "threadIdx.x")
|
|
use different IterVars and variables in their AttrStmts. After
|
|
the unification, we use a consolidated IterVar and a variable
|
|
for them.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
|
|
Note
|
|
----
|
|
`vthread` is a legacy behavior that will be deprecated, though
|
|
thread bindings of `vthread` are still also unified in this
|
|
pass. Please use `vthread.x`, `vthread.y` and `vthread.z` instead.
|
|
"""
|
|
return _ffi_api.UnifyThreadBinding() # type: ignore
|
|
|
|
|
|
def MergeDynamicSharedMemoryAllocations():
|
|
"""This pass merges multiple TIR-level dynamic shared memory allocations
|
|
into one allocation.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.MergeDynamicSharedMemoryAllocations() # type: ignore
|
|
|
|
|
|
def ConvertForLoopsToSerial():
|
|
"""Convert Parallel For Loops to Serial For Loops.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.ConvertForLoopsToSerial() # type: ignore
|
|
|
|
|
|
def InjectSoftwarePipeline():
|
|
"""Transform annotated loops into pipelined one that parallelize producers and consumers
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.InjectSoftwarePipeline() # type: ignore
|
|
|
|
|
|
def ExtractPrimFuncConstants():
|
|
"""Collects and unificates tir non-scalar constants to module's attr 'Constants' array.
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.ExtractPrimFuncConstants() # type: ignore
|
|
|
|
|
|
def RenormalizeSplitPattern():
|
|
"""Renormalize the split pattern from floordiv(floormod()) to floormod(floordiv())
|
|
|
|
Returns
|
|
-------
|
|
fpass : tvm.transform.Pass
|
|
The result pass
|
|
"""
|
|
return _ffi_api.RenormalizeSplitPattern() # type: ignore
|