Commit Graph
184 Commits
Author SHA1 Message Date
Tong WU 550e25d493 [Refactor] Refactor blockscaled TCGEN5, support .f8f6f4/.mxf8f6f4 and restore maint scripts (#2274)
* Add TMA copy for packed global FP4 to unpacked SMEM.

Wire IsValidTMACopyDtypePair and ALIGN16B tensor map descriptors for
float4_e2m1fn global to float4_e2m1_unpacked shared transfers, and
extend language tests for TMA and SIMT copy restrictions.

* Extend tcgen05 MMA metadata for FP4 f8f6f4 and dtype helpers.

* Refactor tcgen05_gemm_blockscaled API and lowering.

* Use separate A/B dtypes in GEMM tileop emitters across backends.

* Add maint/gemm correctness evaluation scripts and update gemm_sm100 examples.

* Fix profiler assert_allclose to compare outputs only.

* lint

* canonicalize data types

* add dpgm fp8-fp4 kernel

* resolve comments

* Refine FP4 unpacked SMEM dtype handling

Treat float4_e2m1_unpacked as a SMEM/TMA-only storage tag instead of a general vector/register dtype. Remove vectorized Python aliases and keep codegen uses constrained to shared-memory storage/reference paths that lower to uint8_t.

Allow packed FP4 global tensors to TMA-load into unpacked shared memory with the ALIGN16B TensorMap format, while keeping unpacked storage out of TMA store paths. Use payload-bit accounting for global strides and mbarrier transactions.

Add focused dtype and TMA descriptor tests, and validate the real tcgen05 fp4-unpacked GEMM paths.

* Restrict FP4 unpack TMA to loads

* Hide vectorized unpacked FP4 language aliases

* Update TVM for unpacked FP4 symbol exports

* Rebind TVM submodule to merged unpacked FP4 export fix

* Enable cache for persistent tcgen5 GEMM example
2026-06-04 18:14:52 +08:00
L1ngYiandL1ngYi ece49f1095 Fix eager AST handling for *args and **kwargs (#2330)
Fix eager AST varargs handling

Co-authored-by: L1ngYi <L1ngYiOpus@gmail.com>
2026-06-04 14:14:14 +08:00
Tong WU a8d9379877 [Feature] Add read option to TMA store wait (#2300)
Add read option to TMA store wait
2026-05-31 03:51:36 +08:00
Lei Wang d09375623b [CUDA] Support preferred copy instruction lowering (#2303)
Support preferred TMA lowering for copy
2026-05-29 16:06:40 +08:00
ec3be54879 [Feature] Add stochastic rounding cast for f32 -> fp8/fp4 on CUDA (#2260)
* Add draft

* Update tvm

* Fix lint

* Update 3rdparty/tvm

* Update CUDA compute version requirement in tilelang tests to 10.0

* Polish stochastic-cast comments

* Add rbits invariance tests for stochastic-cast

* Fix lint

---------

Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
Co-authored-by: wangxiangwen <xiangwen.wang@deepseek.com>
2026-05-28 20:02:38 +08:00
Lei Wang 4e9b0543d5 [Reduce][Codegen] Guard packed local reduce ramp loads (#2298)
Fix packed reduce ramp contiguity check
2026-05-28 19:47:47 +08:00
Tong WU 362d9e0bb1 [Feature] Add float4_e2m1_unpacked dtype (#2271)
* Add float4_e2m1_unpacked dtype

* Fix TIR cast for float4_e2m1_unpacked dtype.

Route custom[float4_e2m1_unpacked] through Float4E2M1Unpacked FFI
so T.float4_e2m1_unpacked(0.0) works in prim_func builders.

* Limit float4_e2m1_unpacked vector lanes and fix TMA transaction bytes.

Cap unpacked FP4 vector dtypes at x32 and count TMA/mbarrier
transactions using 4-bit payload size (0.5 byte per element).

* lint
2026-05-27 23:08:19 +08:00
Lei Wang 3bf3d00adc [Pipeline] Refactor software pipeline transforms (#2245)
* [Pipeline] Refactor software pipeline transforms

* enhance

* Refine pipeline handling for guarded binds

* Refactor IfStmtBindingRewriter and related classes for improved access analysis

- Removed unused Target parameter from IfStmtBindingRewriter.
- Introduced IfStmtAccessCollector to handle buffer access collection.
- Updated access analysis methods to utilize the new collector.
- Cleaned up includes and removed obsolete functions in access_analysis.
- Enhanced pipeline utility headers with necessary includes for consistency.
2026-05-26 15:55:03 +08:00
Lei Wang 124ba6affe [CUDA][Reduce] Fix packed mixed-dtype reduce casts (#2276)
Fix packed reduce casts for mixed dtypes
2026-05-26 15:09:15 +08:00
Tong WU 4ad6e3e0e0 [Feature] Add CUDA __ffs intrinsic for bit manipulation (#2264)
Add CUDA __ffs intrinsic
2026-05-25 17:44:45 +08:00
Lei Wang 146a1d3bef [TileOP] Add scan operators (#2262)
Add TileLang scan operators
2026-05-25 17:41:10 +08:00
6928c82442 [Feature] Add thread_extent parameter to T.tma_copy for flexible TMA copy (#2205)
* feat(tma_copy): add thread_extent parameter for per-warp TMA copy

Add a `thread_extent` parameter to `T.tma_copy()` that controls the
elect size for TMA leader thread selection. Defaults to full block
size, can be set to warp_size (32) for per-warp TMA operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(tma_copy): rename leader election scope parameter

* remove: delete test_per_warp_tma.py and its associated tests; add per_warp_tma_copy_kernel and block_tma_copy_kernel tests in test_tilelang_language_tma_copy.py

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
2026-05-25 13:33:24 +08:00
Liu Yunuo 09764cfd21 [Feature] Introduce T.tfloat32 data type support (#2032)
* [Feature] Introduce T.tfloat32

* fix: change tfloat32 type code to 130

* minor fix

* update tvm to latest

* minor fix

* minor fix

* update tvm

* add conversion from __nv_bfloat16 to tfloat32_t, update mhc example

* minor fix

* enable wgmma support for tfloat32, update gdn example

* update tf32 gemm test
2026-05-21 16:11:32 +08:00
b939fa0137 [TIR][IR] Update to use tirx (#2216)
* [Feature] Implement Hoist Loop-Invariant If Pass

- Added a new pass to hoist loop-invariant if statements out of loops, improving optimization opportunities.
- Introduced classes for collecting and checking conditions, as well as for rewriting statements.
- Integrated the new pass into the optimization pipeline and provided a corresponding API for usage.

* Add tilelang semantics guide to programming guides (#1740)

* Add CallNodeChecker to Loop Unswitching Pass and integrate tilelang cache disabling in benchmark script

- Introduced CallNodeChecker class to identify CallNode expressions in loop conditions, enhancing loop-invariant checks.
- Updated IsLoopInvariant function to reject conditions containing CallNodes, preventing potential side effects.
- Added tilelang.disable_cache() in benchmark_mha_sink_fwd.py to optimize performance during benchmarking.

* lint fix

* lint fix

* Enhance Loop Unswitching Pass with Let Binding Support

- Added support for Let-bound variables in the WrittenBufferReadChecker to improve buffer read checks.
- Introduced UsesLoopVarThroughLetBindings function to check if conditions depend on loop variables through Let bindings.
- Updated IsLoopInvariant function to account for Let bindings when determining loop invariance.
- Enhanced HoistableIfFinder to track Let bindings for variables bound to BufferLoad expressions.
- Added debug print statements in the OptimizeForTarget function to visualize the module state before and after loop unswitching.

* fix

* lint fix

* Enhance Loop Unswitching with CallNode Exclusion Check

- Added CallCheckerExcludingIf class to ensure function calls outside of hoisted if statements are identified, preventing potential synchronization issues during loop unswitching.
- Updated loop unswitching logic to incorporate the new call checker, enhancing safety and correctness.
- Integrated debug print statements in OptimizeForTarget to visualize module state before and after loop unswitching.
- Disabled tilelang cache in the benchmark script for improved performance.

* Update TVM subproject to latest commit and remove debug print statements in OptimizeForTarget function

* Add support for disabling loop unswitching optimization

- Introduced a new configuration option `tl.disable_loop_unswitching` to allow users to disable the loop unswitching optimization.
- Updated the Loop Unswitching pass to check this configuration and return the original function if the option is enabled.
- Added relevant documentation in the PassConfigKey enumeration for clarity.

* update tvm

* Refactor: Update TileLang to use tirx instead of tir

- Removed references to `tvm.tir` and replaced them with `tvm.tirx` across various files, including examples and backend operations.
- Updated target configuration in documentation to reflect the new usage of target config dictionaries instead of CLI-style strings.
- Cleaned up `pyproject.toml` and `load_tvm.cmake` by removing obsolete paths.
- Enhanced examples for dequantization and GEMM operations to utilize the new `tirx` constructs.
- Adjusted various backend operations to ensure compatibility with the new `tirx` namespace.

* pass fix

* Update submodule 'tvm' to latest commit f24c7b19

* Apply formatting fixes

* Update CMakeLists.txt to set HIDE_PRIVATE_SYMBOLS for TileLang and modify target_host initialization in lower.py for compatibility with TVM's target handling.

* Refactor CMakeLists.txt and kernel_cache.py to update target names and library dependencies for TVM integration. Adjusted output targets and library names for better compatibility across platforms.

* Update repair-wheel-command in pyproject.toml to exclude libz3.so with wildcard for better compatibility with dependency packages.

* Fix macOS Z3 dylib lookup

* Move macOS Z3 install-name fix to install step

* Update TVM submodule for runtime import fix

* Update ROCm backend for TVM module factory changes

* Fix build-tree Z3 runtime lookup

* Fix macOS build-tree Z3 lookup

* Support legacy target option strings

* Normalize CUDA target in transform test

* Qualify Metal stream FFI lookup

* Fix PyPI Z3 packaging links

* Update TVM for Windows DLL lookup

* Register Windows dependency DLL directories

* Bump tvm-ffi to match tirx

* tvm update

* Apply lint fixes

* Enhance reduction operations with support for nan propagation and vectorization. Introduce new functions for preferred vectorized size and update existing reduction logic to handle packed operations for bfloat16 and float16 types. Add nan-aware min and max operations in CUDA and ROCm backends, and update related tests to validate functionality.

* Refactor ReduceLowerer: Remove unnecessary buffer allocation logic for packed operations in reduce.h

* Normalize PyPI Z3 dylib before linking

* Drop legacy target option string support

* Fix type reference for barrier annotations in CUDA copy operations. Updated `BufferLoadNode` to `tirx::BufferLoadNode` in `GetBarrier` and `LowerCluster` methods to ensure compatibility with recent changes in the TIR API.

---------

Co-authored-by: Yu Cheng <yu.cheng@pku.edu.cn>
Co-authored-by: Yichen Yan <oraluben@outlook.com>
2026-05-20 15:38:13 +08:00
Subho GhoshandLeiWang1999 7c4718fc63 [CUDA][TMA] Add TMA tile::gather4 / tile::scatter4 support (#2129)
* Add TMA tile::gather4 / tile::scatter4 support (sm_90+)

* CUDA 12.8 guard, sm_100 skip, dtype/layout checks

* Reject non-None swizzle and validate buffer scopes (gather4/scatter4)

* fixed merge conflict + Auto-infer cuTensorMapDataType + swizzle for tma_gather4/scatter4

---------

Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
2026-05-20 15:09:11 +08:00
Jayce SuandJayce 2451f8d176 [CuTeDSL] Add PDL codegen and launcher support (#2220)
* [CuTeDSL] Support CUTLASS DSL 4.5 setup

Update the CUDA test requirements to the 4.5.0 CuTeDSL wheel stack and keep the runtime compatibility check accepting older supported CuTeDSL versions. Also accept the relocated Constexpr export while retaining the fallback for older wheels.

The 4.5.0 pin is a CI/test environment choice. CuTeDSL PDL APIs were introduced upstream in 4.3.4, so the pin should not be read as the minimum PDL version.

* [CuTeDSL] Wire PDL lowering and launch support

TileLang PDL intrinsics were already available for the CUDA backend, but the CuTeDSL backend did not lower them to cute.arch.griddepcontrol_* or enable PDL on generated kernel launches.

Lower T.pdl_trigger() and T.pdl_sync() to the CuTeDSL griddepcontrol APIs, re-export those APIs from tilelang.contrib.cutedsl when available, and pass use_pdl / programmatic stream serialization in Python and C++ launchers. Add CuTeDSL tests that cover device lowering and launcher generation.

---------

Co-authored-by: Jayce <jayce.su@enflame-tech.com>
2026-05-19 17:15:55 +08:00
KurisandLeiWang1999 719d23dce5 feat: auto-vectorize bf16/fp16 reduce with packed add2 intrinsics (#2112)
* fix: add missing TvmLogDebugSettings::ParseSpec and VerboseEnabledImpl for TVM_LOG_CUSTOMIZE builds

When TVM_LOG_CUSTOMIZE=1, TVM's logging.cc skips compiling
TvmLogDebugSettings::ParseSpec and VerboseEnabledImpl (guarded by
#if TVM_LOG_CUSTOMIZE == 0). However libtilelang.so calls these
functions via the inline FromFlag(), causing a runtime symbol
lookup error. Add the missing implementations to tilelang's own
logging.cc.

* feat: auto-vectorize bf16/fp16 reduce with packed add2 intrinsics

* style: clang-format

* fix: fp16 batch pack — fix Shuffle codegen taking address of temporary

- Add tl::pack_half2 helper in common.h that returns uint1, avoiding taking
  address of a temporary __pack_half2 return value
- Update ShuffleNode codegen for fp16x2 to use pack_half2 instead of
  &(__pack_half2(...))
- Re-enable fp16 batch pack (remove bf16-only restriction in can_batch_pack)
- Add SumOp_fp16x2/MaxOp_fp16x2/MinOp_fp16x2 packed reducer structs

* refactor: simplify reduce packing API

- Replace ReducePackConfig with simple GetPreferedVectorizedSize(DataType, Target) -> int
- Merge getBatchReducerSuffix into MakeCodegenReducer(vsize)
- MakeReduce(vsize, acc, b) -> optional<PrimExpr>
- MakeInitValue(vsize) handles Broadcast internally
- Guard nan_propagate in MakeCodegenReducer vsize>1 path (no packed nan ops exist)

* fix: guard nan_propagate in MakeReduce packed path, mirror scalar structure

* feat: support nan_propagate in packed reduce (max2_nan/min2_nan)

* fix: add bitwise reduce ops to MakeReduce vsize=1 path

* fix lint error

---------

Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
2026-05-19 15:03:44 +08:00
Chenhao Xu fa76eaf014 Allow variable barrier id in T.sync_threads() (#2197)
* fix: allow variable barrier id in T.sync_threads()

* ruff format
2026-05-18 14:50:43 +08:00
ZihaoMu 7bf8de13ca [ROCm] Try to fix ROCm CI error (#2179)
* Fix ROCm tvm-ffi DLPack handling

* Fix CuTeDSL FP4 torch dtype map

* Fix CuTeDSL FP4 packed stores

* Mark DeepSeek V4 FP4 CuTeDSL xfail

* Keep ROCm DLPack PR focused

* Revert "Keep ROCm DLPack PR focused"

This reverts commit bd7ebea864.

* Split FP4 changes from ROCm DLPack PR

* Clarify ROCm FP8 tvm-ffi runtime args

* Gate ROCm FP8 tvm-ffi runtime args

* Keep ROCm DLPack PR focused

* Drop FP8 fallback diff from ROCm CI PR
2026-05-12 15:13:34 +08:00
ZihaoMu beef5cf471 Fix float4 storage dtype torch mapping (#2174) 2026-05-10 21:50:30 +08:00
Tong WUandRachmanino 1fbd994cbb [Refactor] Refactor multiple TensorCoreIntrinEmitter to provide atom-level mma control interface (#2161)
* Enhance intrinsic modules by adding WGMMATensorCoreIntrinEmitter and TCGEN05TensorCoreIntrinEmitter. Introduce descriptor parameter classes for WGMMA and TCGEN05, improving the initialization and atom offset computation processes. Update the TensorCoreIntrinEmitter to support atom-level interfaces and macro definitions for efficient matrix multiplication operations.

* lint

* add test for mma/wgmma/tcgen5mma atom

* lint

* typo

* fix import path err

---------

Co-authored-by: Rachmanino <wutong.1109@bytedance.com>
2026-05-09 16:04:31 +08:00
Lei Wang a797e5120f [Refactor] Move backend-specific GEMM implementations and transforms into backend directories (#2165)
* [Refactor] Move backend-specific GEMM implementations and transforms into backend directories

Restructure the codebase so that each backend (cpu, cuda, rocm) owns its
GEMM implementations, sparse GEMM implementations, and transform passes
under a consistent op/ subdirectory layout. The shared GEMM registry and
base classes remain in tileop/ as the platform-agnostic dispatch layer.

- Move gemm/gemm_sp registries from backend/ into tileop/ as registry.py
- Move CUDA GEMM impls (mma, mma_sm70, wgmma, tcgen05) into backend/cuda/op/gemm/
- Move CUDA sparse GEMM impl into backend/cuda/op/gemm_sp/
- Move CPU GEMM impl (scalar) into backend/cpu/op/gemm/
- Move ROCm GEMM impls (mfma, wmma) into backend/rocm/op/gemm/
- Move CUDA-specific transform passes from src/transform/ into src/backend/cuda/transform/
- Move CUDA runtime sources from src/runtime/ into src/backend/cuda/
- Remove dead backend-importing wrappers from transform/__init__.py
- Update phase.py and tests to import CUDA transforms from their canonical location

Each backend now has a symmetric op/ directory structure. Adding a new
backend no longer requires modifying shared transform or tileop modules.

* Refactor Python backend package layout

* Remove deprecated intrinsic implementations and related tests for matrix multiplication and element-wise addition. This includes the deletion of files for `benchmark_matmul_intrinsic.py`, `example_tilelang_gemm_fp8_intrinsic.py`, and associated test files, streamlining the codebase by eliminating unused components.

* Move CUDA transform passes back to common transform
2026-05-08 17:11:34 +08:00
SepcntandSiriusNEO c2cabd9b3f [Feature] Add full Windows support and fix related cross-platform issues (#2093)
* [Feature] Add Windows support with cross-platform minimal diff

* [Feature] Add ccache support for Windows

* [Feature] Add parallel autotune support for Windows

* [Feature] Add nvrtc support for Windows

* [Bugfix] Fix tilelibrary support for Windows

* [Bugfix] Fix alignment for Windows

* [Feature] Add clang-cl support for Windows

* [Bugfix] Fix numeric limit for Windows

* [Bugfix] Fix rand for Windows

* [Misc] Use dynamic test workload to avoid hang

* [Bugfix] Fix TMA alignment for Windows and sm120

* [Bugfix] Add unix-like hex formatter for Windows

* [CI] Add Windows wheel job

* [Feature] Flexible CUDA loader

* fix rebase

---------

Co-authored-by: SiriusNEO <chaofan@deepseek.com>
2026-05-06 23:08:24 +08:00
Lei Wang 9452312af2 [codex] Fix 1D TMA store layout inference (#2137)
fix tma store 1d layout
2026-05-03 23:57:20 +08:00
6548c05f0c [Feature] Batched AllReduce for better T.reduce performance (#1976)
* [Feature] Batched AllReduce for better T.reduce performance (#1928)

When each thread holds multiple values to reduce, the previous code
emitted one AllReduce call per element inside a loop, causing redundant
synchronization barriers (e.g. 8 values × 6 syncs = 48 syncs).

This change adds batch support to AllReduce so all per-thread values are
reduced in a single butterfly pass sharing barriers (6 syncs total).

- Add `batch_size` and `workspace_stride` template parameters to
  `tl::AllReduce` (defaults preserve existing scalar behaviour).
- In ReduceOpNode::Lower, detect when batching is beneficial
  (batch_size > 1 and cross-warp reduction) and restructure into three
  phases: loop(init + local reduce), batched AllReduce, loop(copy-back).
- Apply same optimisation to FinalizeReducerOpNode::Lower.
- Mirror template changes in HIP AllReduce.

Closes #1928

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Test] Add codegen tests for batched AllReduce

Verify that the batched AllReduce path (batch_size > 1, workspace_stride)
is emitted in the generated CUDA source for reduce_max, reduce_sum, and
reduce_min with cross-warp reductions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Bugfix] Fix batched AllReduce codegen for HIP/ROCm targets

HIP AllReduce template has no Barrier type parameter, so the batched
path must omit tl::SyncThreadsBarrier for ROCm targets. Adds
TargetIsRocm() checks in both reduce.cc and finalize_reducer.cc.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Fix] Use target-aware warp size for cross-warp reduction threshold

Address CodeRabbit review: ROCm wavefronts are 64-wide, so the cross-warp
threshold should be 64 (not 32) on HIP targets. This avoids unnecessary
workspace allocation and batched codegen for single-wavefront reductions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Style] Fix ruff format for test assertion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Bugfix] Support batched AllReduce in CuteDSL Python codegen

The CuteDSL codegen translates C++ AllReduce template calls to Python.
With the new batch_size and workspace_stride template params, the
generated Python calls AllReduce() with 7 args instead of 5. Add
batch_size and workspace_stride params to the Python AllReduce function
and implement batched reduction logic for both standard and Hopper paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Feature] Add explicit batch parameter to T.reduce for user-controlled batched AllReduce

Expose a `batch` parameter on T.reduce (and all T.reduce_* wrappers,
default 1 = scalar / current behaviour).  When batch > 1 the compiler:

 - validates batch divides the per-thread output element count N;
 - emits ceil(N/batch) calls to the new AllReduce::run_batch interface,
   each sharing a single pair of barriers across all batch elements;
 - allocates workspace of size reducing_threads * batch (only for cross-
   warp reduce, i.e. reducing_threads > 32).

Key differences from the existing auto-detection approach:
 * The user controls when batching is enabled — no silent smem increase.
 * workspace_stride = reducing_threads (not block_size), so workspace is
   minimal and does not blow past the GPU shared-memory limit.
 * run_batch (not run) avoids C++ overload-resolution ambiguity when a
   pointer is passed as the first argument.

Files changed:
 - src/op/reduce.h: add `int batch{1}` field to ReduceOpNode
 - src/op/reduce.cc: read "batch" annotation; validate; emit N/batch
   batched AllReduce calls with address_of per-chunk pointers
 - src/tl_templates/cuda/reduce.h: rename batch run() -> run_batch(),
   fix recursive call
 - src/tl_templates/hip/reduce.h: same
 - tilelang/language/reduce_op.py: add batch param to reduce() and all
   reduce_max/min/sum/absmax/abssum/bitand/bitor/bitxor wrappers
 - testing/python/language/test_tilelang_language_reduce.py: update
   test_batched_allreduce_codegen to use explicit batch=2 and match
   run_batch in generated source

* [Fix] Use run_batch in finalize_reducer batched AllReduce codegen

finalize_reducer.cc also generates batched AllReduce calls (used by
T.alloc_reducer / T.finalize_reducer), but was still emitting ::run
instead of ::run_batch, causing a compiler error because the batched
pointer-based interface is now named run_batch to avoid overload
ambiguity.

* rocm fix

* [Feature] Add explicit batch parameter to T.finalize_reducer

Mirrors the batch= API already available on T.reduce:
- batch=1 (default) keeps the existing scalar AllReduce::run path
- batch>1 emits AllReduce::run_batch, sharing barriers across batch
  output elements and reducing barrier count by batch×

C++ changes:
- FinalizeReducerOpNode gains an int batch{1} field (registered via
  reflection) and reads it from the 'batch' annotation in the constructor
- Lower() validates batch against the layout output-element count and
  uses effective_batch to drive use_batch / codegen

Python changes:
- finalize_reducer(reducer, batch=1) – new optional argument
- batch < 1 raises ValueError (consistent with T.reduce)

Tests: add test_batched_finalize_reducer_codegen covering sum/max/min
with explicit batch values, verifying run_batch is emitted with the
correct template argument.

* [Test] Add comprehensive tests for T.finalize_reducer batch parameter

Covers all cases introduced by the explicit batch= API:

Codegen tests:
- batch>1 emits AllReduce::run_batch with correct template argument
- batch=1 (default) does NOT emit run_batch (scalar path)

Correctness tests:
- batch=1 scalar path: sum/max/min across float32/float16 (PASS)
- batch==block_M full-batch: correct by coincidence (PASS)
- batch>1 partial-batch: xfail(strict=True) – known bug where
  run_batch receives buffer->data directly but fragment layout is
  non-contiguous per thread; root cause documented in
  work/bug-finalize-reducer-batch.md

Error-input tests:
- batch=0 / batch<0 raise ValueError at Python layer
- batch > total output elements raises at compile/lower time
- batch that does not evenly divide output elements raises

* [Test] Rewrite finalize_reducer tests to follow clean outline

Replace the previous over-engineered test suite (4 case lists, 2 split
correctness functions, per-case xfail) with a minimal set organised by
the three categories that matter:

1. Codegen – single parametrised test covers both batch=1 (no run_batch)
   and batch>1 (run_batch with correct template arg), reusing one case
   list for both codegen and correctness.

2. Correctness – only batch=1 (scalar path), which is currently correct.
   batch>1 correctness tests are omitted until the underlying fragment
   layout bug is fixed (tracked in work/bug-finalize-reducer-batch.md).

3. Error inputs – batch<1 collapsed into one parametrised test; compile-
   time errors (batch>output, batch not divisible) each get one test
   using a shared _make_error_kernel helper.

* [Test] Rewrite reduce tests following clean outline

Replace fragmented per-function tests with four parametrized suites:

- test_reduce: op × dtype × src_scope × dst_scope × threads, covers
  fragment→fragment, shared→shared, fragment→shared for sum/max/min/
  abssum/absmax with float32/float16/int32/int64

- test_reduce_clear: op × src_scope × dst_scope with clear=False,
  verifies pre-filled dst is accumulated correctly

- test_reduce_batch_codegen: verify batch>1 emits AllReduce::run_batch

- test_finalize_reducer_codegen/correctness/invalid_batch: batch
  parameter feature tests, sharing one FINALIZE_REDUCER_CASES list

Use tilelang.jit lazy style and torch.testing.assert_close directly,
no profiler wrapper.

* [Test] Merge batch codegen+correctness into test_reduce

Add batch column to REDUCE_CASES; batch>1 cases verify both that
run_batch appears in generated source and that numerical output matches
reference, within the same test_reduce parametrization.

Remove the now-redundant test_reduce_batch_codegen.

* [Test] Add more batch>1 reduce cases covering all ops and dtypes

Add batch=2/4/8 cases for sum/max/min/abssum/absmax across float32/
float16/bfloat16, with both fragment and shared src/dst scopes.
Relax tolerance to 1e-1 for float16/bfloat16 to account for larger
rounding error in multi-element reductions.

* [Test] Limit int64 input range to avoid ROCm shfl_xor 64-bit bug

* Revert "[Test] Limit int64 input range to avoid ROCm shfl_xor 64-bit bug"

This reverts commit 9d60d6b197.

* fix(HIP): skip __launch_bounds__ for sub-wavefront threads to avoid miscompile of 64-bit shuffle ops

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
Co-authored-by: kurisu6912 <kurisu6912@users.noreply.github.com>
2026-04-28 15:15:30 +08:00
Lei Wang 5680e39e45 [TMA] Support FP4 TensorMap TMA copies (#2107)
Support FP4 TensorMap TMA copies
2026-04-28 12:35:16 +08:00
Chenhao Xu 64bd742071 [Bugfix] Fix reduce layout (#2074)
* fix: fix reduce layout

* test: add targeting test
2026-04-21 19:49:06 +08:00
Lei Wang 9c95a42dfb [Refactor] Phaseout legacy util map_torch_type with T.dtype.as_torch (#2075)
* Remove redundant `map_torch_type` in favor of `T.dtype.as_torch()`

`map_torch_type` was a standalone function that converted dtype strings or
TVM DataType objects to `torch.dtype`. This was redundant since
`T.dtype.as_torch()` (and `T.dtype(x).as_torch()`) already provides the
same functionality with better handling (HIP/CUDA awareness, proper dtype
lookup tables, etc.).

Changes:
- Remove `map_torch_type` from `tilelang/utils/tensor.py` and its re-export
- Make `T.dtype()` idempotent for existing dtype objects (pass-through)
- Add backward-compat for `"e4m3fnuz_float8"` TVM internal name in `as_torch()`
- Replace all usages across production code, tests, and examples
- Rebuild Cython extension to reflect the import change

* Refactor output and accumulation data types in GEMM FP8 example

Updated the `out_dtype` and `accum_dtype` variables in the `example_tilelang_gemm_fp8_intrinsic.py` file to use `T.float32` instead of string literals. This change enhances type consistency and aligns with recent updates in type handling.
2026-04-21 18:27:15 +08:00
Lei WangandClaude Opus 4.6 046b1bdc69 [FFI] Remove upper version bound on apache-tvm-ffi (#2071)
* ugrade tvm

* Remove upper version bound on apache-tvm-ffi

The <0.1.10 pin was introduced to avoid a derived_object regression,
which has since been resolved. Removing the cap allows compatibility
with newer versions of apache-tvm-ffi.

* Enhance ptxas usage level handling in CUDA compilation

Added type conversion for ptxas_usage_level in both tilelang_callback_cuda_compile and LibraryGenerator classes to ensure it is treated as an integer when specified. This change improves the robustness of the configuration handling for CUDA compilation.

* Fix IR string representation issues from tvm-ffi upgrade

The new tvm-ffi version changes str() output for IR nodes from compact
script format to verbose repr format. This caused two issues:
1. T.call_packed("name") is now tir.tvm_call_packed with value="name"
2. tir.Var str() now produces "tir.Var(span=None, ...)" instead of name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Simplify TMA descriptor globalAddress handling in cutedsl wrapper

Since global_address is now converted to string by pythonic_expr_func
in parse_tma_descriptor_args, remove the unnecessary tir.Var type check
and .name extraction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Refactor CUDA test for vectorization and update IR string representation

Updated the test for vectorization in CUDA by replacing the direct function definition with a JIT-compiled kernel. Additionally, modified the string representation of IR modules in multiple tests to use the script format instead of the default string format, ensuring consistency and clarity in assertions.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 18:09:24 +08:00
Lei Wang 99ee74b343 [CUDA] Support int4 T.gemm (#2063)
* Support int4 T.gemm and direct packed cp.async lowering

* Keep cp.async vectorization as a late fallback

* Change tl.ptx_cp_async to use num_elems semantics

* fix test
2026-04-20 16:35:43 +08:00
TerminusAkiviliandLeiWang1999 04468a3425 [Bugfix] Fix stage-expanded annotated-layout aliases in LayoutInference (#2031)
* Fix annotated layout inference for dtype-changing views

* lint fix

---------

Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
2026-04-17 17:22:54 +08:00
Chaofan Lin 77cbe6da87 [Feature] Introduce T.CUDASourceCodeKernel (#1970)
* [WIP][Feature] Introduce CUDARunner

* refactor

* refactor to T.SourceCodeKernel api

* remove streamk change

* remove runner

* remove prim func params

* enhance API

* add entry_name

* add IsCodeBlockKey

* remove misc file

* cleanup code

* move parse logic to python through callback

* fix

* comments
2026-04-17 16:48:28 +08:00
27f1f81c61 [Feature][Example] Introduce CLC tile schedule and add example for sm100 GEMM (#2029)
* [Feature] Add Blackwell Cluster Launch Control (CLC) primitives

Expose cluster launch control query operations (try_cancel,
try_cancel_multicast, is_canceled, get_first_ctaid_{x,y,z}) in both
the C++ codegen path and the Python tilelang.language API, plus a new
mbarrier_arrive_expect_tx builtin used with CLC multicast completion.
Enables writing persistent SM100 kernels that use the hardware scheduler
to fetch the next tile coordinate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [Example] Add SM100 persistent 2-CTA GEMM example using CLC scheduling

Adds examples/gemm_sm100/gemm_tcgen5mma_ws_clc.py, a warp-specialized
persistent GEMM for Blackwell (sm_100) that uses tcgen05 2-CTA MMA
with cluster launch control tile scheduling. The kernel is split into
producer/MMA/scheduler/epilogue warp groups, with the scheduler warp
running on both CTAs and feeding next-tile coordinates via the CLC
hardware multicast into schedule_arrived directly (no intermediate
barrier). Storage sync is disabled and all syncs are placed manually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* lint

* typo

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* remove unnecessary test

* Add CLC query intrinsics and async fence

* Refactor CLC response handling by introducing CLCResponseDecode struct. Update clc_get_first_ctaid_x/y/z and clc_is_canceled functions to utilize the new decode response method for improved clarity and maintainability.

* Enhance CLC scheduling in persistent GEMM by introducing shared variables for schedule validity and tile ID. Update cancellation checks to utilize the new shared variables, improving clarity and maintainability of the scheduling logic.

* test fix

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Zhiwen Mo <zm125@ic.ac.uk>
Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
2026-04-17 15:19:04 +08:00
KurisandClaude Opus 4.6 f309d8147e [Bugfix][Subtype] Fix scalar fp4 store/load codegen for non-packed buffers (#2037)
* [Bugfix][Subtype] Fix scalar fp4 load/store codegen and dynamic stride inference for sub-byte types

The scalar fp4 buffer access path in codegen_cuda.cc used GetBufferRef which
applies a /2 index division (mapping two fp4 elements to one byte), then
performed a plain byte assignment — destroying the neighboring nibble. This
caused incorrect results whenever fp4 stores couldn't be vectorized (e.g.
with dynamic/non-constant strides in StridedTensor).

Fix: use tl_fp4_packed_load/tl_fp4_packed_store with (fp4_e2_2_t*) cast for
scalar fp4 accesses to non-packed buffers, which correctly handles nibble-level
read-modify-write via set_x/set_y.

Also add stride_scale factor to _process_dynamic_symbolic in the cython and
tvm_ffi adapters, so torch strides (in storage units) are correctly converted
to logical element strides for sub-byte dtypes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [Test][Subtype] Add correctness tests for fp4 dynamic-stride store codegen

Add regression test that scatters fp4 rows into a non-contiguous
StridedTensor with dynamic strides and verifies byte-for-byte match
against a static-stride reference.  Parametrized over block_size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [Enhancement][Subtype] Inject stride divisibility assume for sub-byte dtypes and add scalar fp4 store codegen test

- Extend InjectAssumes pass to emit `assume(stride % pack_factor == 0)` for
  non-last-dimension strides of sub-byte buffers (e.g. fp4 with pack_factor=2).
  This provides the TIR analyzer with divisibility information before LetStmt
  inlining.
- Add `test_subtype_fp4_scalar_store_codegen`: scatter fp4 elements via
  indirection to force the scalar (non-vectorized) store codegen path and
  verify nibble-level correctness.
- Convert new tests to eager-style @tilelang.jit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: apply clang-format and ruff formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix lint error

* fix: unpack 4-tuple in cython_wrapper dynamic_symbolic_map lookup

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:54:28 +08:00
Lei Wang b3d5981b00 [API] Default warp-lane mask to 0xFFFFFFFF for warp-sync builtins (#2039)
Reorder the `mask` parameter to the end with a default of `_FULL_WARP_MASK`
for shfl_xor/down/up/sync, any_sync, all_sync, ballot_sync, and
match_any/all_sync. Full-warp is the overwhelmingly common case, so making
mask an optional trailing kwarg removes boilerplate at call sites and lets
old `(value, delta)`-style callers keep working. Update the test suite and
docs/instructions.md to match the new signatures.
2026-04-14 01:05:54 +08:00
19236b44c0 [Feature] Add TIR builtins for warp-level vote and block-level predicate sync (#1858)
* [Feature] Add TIR builtins for warp-level vote and block-level predicate sync

* [Refactor] Lower warp-level intrinsics through tl.* ops

Convert the warp-vote, warp-shuffle, predicated block-sync, and warp-match
builtins from raw `tir.call_extern` wrappers to proper TIR ops registered
under `tl.*` and lowered in `codegen_cuda` / `codegen_hip`. This removes
Python-side `_IS_HIP_AVAILABLE` branching and pushes the CUDA/HIP split
into codegen, where it belongs.

* Register new tl ops: any_sync, all_sync, ballot_sync, ballot,
  activemask, syncthreads_count/and/or, shfl_sync, shfl_xor_sync,
  shfl_down_sync, shfl_up_sync, match_any_sync, match_all_sync.
* Codegen lowering on both CUDA and HIP. uint32->uint64 zero-extension
  for ballot/activemask now happens in codegen. HIP drops the mask
  argument for shfl/vote and emits LOG(FATAL) for match_*_sync.
* `__match_all_sync`'s int* pred output is hidden behind an
  immediately-invoked lambda so the wrapper stays expression-form.
* Python wrappers normalize Python int masks to uint32 TIR consts via
  `_as_uint32_mask`, so the emitted source prints `(uint)0xFFFFFFFF`
  instead of `(int64_t)4294967295`.
* Unify `shfl_xor/down/up` signatures to `(mask, value, delta, width=32)`,
  matching CUDA convention and `shfl_sync`. No in-tree callers existed.
* Add tests for match_any_sync and match_all_sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 23:35:03 +08:00
8243f7e089 Nan propagation option for bf16 and half16 (#1958)
* register op, and add to build file

* update semantics of NaN for Max and Min ops in Reduce

* lower Max op to cutlass fastmax in general case, _hmax for bf16 and _hmax_nan for hf16

* update semantics of NaN for Max and Min ops in Reduce in reduce.h

* develope codes transforming ReduceOpNode in TIR and handling CallNode in CUDA code generator's runtime template

* test file for reduce maxmin nan

* refine test case message and explanation“
”
‘
“

* invert the senamtics of global config TL_REDUCE_MAXMIN_NAN_PROPAGATE

* lint fix

* refactor reduce maxmin NaN propagate into per-call annotation

Replace the global tl.reduce_maxmin_nan_propagate pass-config with a
per-op nan_propagate flag carried on the ReduceOp annotation map.
Frontend exposes it as a kwarg on T.reduce_max/min/absmax (default
False, preserving prior behavior). The CUDA codegen MinNode/MaxNode
visitors are reverted to plain __hmin/__hmax; only the new tl::max_nan
/tl::min_nan CallNode handler emits __hmax_nan/__hmin_nan, so non-reduce
Min/Max ops are no longer silently rewritten. ReduceOp::Lower now errors
early with a clear message if nan_propagate=True is requested for fp16
/bf16 on a non-CUDA target, instead of emitting an undefined symbol on
HIP/CPU. Tests rewritten to parametrize on the kwarg and assert runtime
NaN-propagation behavior, not just generated source substrings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Haoran <chaoran@umich.edu>
Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:18:24 +08:00
Lei Wang 5d729eeebc [Refactor] Remove GEMM v1 and promote gemm_py to be the canonical gemm op (#2033)
* [Refactor] Remove GEMM v1 and merge gemm_py into the canonical gemm op

GEMM v2 has been the default for a while and no tests or examples still
depend on v1. This removes the legacy C++ GemmNode path entirely and
promotes the former GemmPyNode (Python-delegated lowering) to be the one
and only GEMM tile op.

C++:
- Merge src/op/gemm_py.{h,cc} into src/op/gemm.{h,cc}. GemmPyNode becomes
  GemmNode, GemmPy becomes Gemm, FFI type key "tl.GemmPy" becomes "tl.Gemm",
  and the op names "tl.tileop.{gemm_py,wgmma_gemm_py,tcgen05_gemm_py}"
  collapse to "tl.tileop.{gemm,wgmma_gemm,tcgen05_gemm}". The shared
  infrastructure (GemmWarpPolicyNode, GemmInst enum,
  GemmWarpPolicyNode::computeWarpPartition) is preserved in place so
  GemmSP/GemmSPPy keep compiling unchanged.
- Delete the tl_gemm builtin, its codegen dispatch in
  codegen_{cuda,hip,cutedsl}.cc, and its matching branches in
  inject_fence_proxy.cc and merge_shared_memory_allocations.cc. tl_gemm_sp
  is kept as the remaining async-proxy gemm builtin.
- Drop #include "gemm_py.h" and GemmPyNode/GemmPy references from
  inject_pipeline.cc, producer_consumer_ws.cc, and lower_blackwell_2sm.cc.

Python:
- tileop/gemm: rename GemmPy -> Gemm, register as "tl.Gemm", and rename
  the FFI callbacks tl.gemm_py.{lower,infer_layout} -> tl.gemm.{lower,
  infer_layout}. _ffi_api.GemmPyGemmInst becomes GemmGetGemmInst.
- language/gemm_op.py: delete gemm_v1/gemm_v2 wrappers. gemm() now emits
  tl.tileop.gemm directly; wgmma_gemm/tcgen05_gemm drop the _py suffix.
- env.py: remove TILELANG_USE_GEMM_V1 and the use_gemm_v1() helper.
- ir.py: drop the empty v1-era `class Gemm(Node, Scriptable): ...`
  placeholder that was colliding with the real tileop.gemm.Gemm wrapper
  under the "tl.Gemm" FFI type key.
- contrib/cutedsl: delete cutedsl/gemm_v1.py (runtime helper for the v1
  cutedsl lowering path) and its re-export in cutedsl/__init__.py.

Tests / maint:
- testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py switches
  from T.gemm_v2 to T.gemm.
- testing/python/transform/test_tilelang_transform_inject_fence_proxy.py::
  test_lower_fence_proxy is rewritten to exercise tl.tl_gemm_sp instead
  of the removed tl.tl_gemm, preserving the fence-proxy assertion.
- Delete maint/gemm_v2/ (v1-vs-v2 benchmarking scripts) and drop the
  v1-specific comment from maint/scripts/run_local_ci_test.sh.

C++ headers under src/tl_templates/{cuda,hip,cpp}/gemm*.h are left in
place as reference implementations; they are no longer reachable from
the generated code path since the only consumer (tl_gemm builtin) is
gone, but keeping them avoids a large, hard-to-reverse deletion.

* [Fix] Restore cutedsl/gemm_v1.py (Gemm_SM80 / Gemm_SM90 helpers)

The previous commit deleted cutedsl/gemm_v1.py on the assumption that it
was the CuteDSL lowering helper for the removed T.gemm_v1 path. It is
actually a runtime helper module that defines SM80/SM90 CUTE DSL
primitives (make_smem_layout_AB, get_tma_atom, etc.) which are emitted
into generated cutedsl kernel code via
`import tilelang.contrib.cutedsl as tl; tl.Gemm_SM90.get_tma_atom(...)`
(see jit/adapter/cutedsl/wrapper.py CUBIN_TMA_ATOM_INIT_TEMPLATE).

The "v1" in the filename refers to the CuteDSL helper version, not to
the deleted T.gemm_v1 op, so removing it broke the cutedsl code path for
attention_sink, blocksparse_attention, blocksparse_gemm, and deepgemm
examples with `module 'tilelang.contrib.cutedsl' has no attribute
'Gemm_SM90'`. Restore the file and its `from .gemm_v1 import *` wildcard
re-export.

* [Refactor] Restore tl_gemm builtin as a call_intrin path to tl:: templates

The previous commit in this PR deleted the `tl_gemm` builtin entirely on
the argument that no code emitted it anymore. That was too aggressive:
keeping the builtin preserves a deliberate extension point for any
Python-side gemm lowering backend (for example a future
GemmLegacyExtern) to delegate into the existing C++ templates in
src/tl_templates/<target>/gemm*.h via

    T.call_intrin("handle", tir.op.Op.get("tl.tl_gemm"),
                  op_instance_str, A_ptr, B_ptr, C_ptr)

without any extra C++ plumbing. It is also the only thing that keeps
those tl_templates headers reachable rather than dead code.

Restore:
- tl_gemm builtin declaration in src/op/builtin.h (with an updated
  docstring describing the call_intrin entry point) and its
  TIR_DEFINE_TL_BUILTIN registration in src/op/builtin.cc.
- Codegen dispatch branches in codegen_cuda.cc, codegen_hip.cc, and
  codegen_cutedsl.cc that turn a tl_gemm Call into a PrintCallExtern
  emission of `tl::gemm_xx<...>(A, B, C)`.
- SMEM alignment and async-proxy fence handling for tl_gemm in
  merge_shared_memory_allocations.cc and inject_fence_proxy.cc. These
  passes are tied to the builtin's semantics (not to the removed v1
  GemmNode) and are still correct the moment anything emits tl_gemm.
- test_lower_fence_proxy in test_tilelang_transform_inject_fence_proxy
  reverts to exercising `tl.tl_gemm` instead of the temporary
  `tl.tl_gemm_sp` substitution introduced when the builtin was gone.

Note that the current sole gemm lowering path (the merged GemmNode that
delegates to Python via tl.gemm.lower) still emits inline mma/wgmma/
tcgen5mma via the Python macro generators, not tl_gemm. So restoring
the builtin is a no-op for the default path - it only re-enables the
"call into v1 templates from Python" option for anyone who wants it.

* [Fix] Default HIP execution backend to tvm_ffi, not cython

resolve_execution_backend() only promoted cuda and metal to tvm_ffi for
the "auto" path, so hip fell into the else branch and picked cython. But
allowed_backends_for_target() already lists tvm_ffi as an allowed
backend for hip, and the cuda default is tvm_ffi for good reasons:

- The cython SourceWrapper path in src/tilelang/jit/adapter/wrapper.py
  has known gaps (for example T.alloc_global is not handled in
  create_dispatch_func, which breaks any test that uses an internally
  allocated global scratch buffer).
- libgen.py appends user-supplied compile_flags verbatim to the
  hipcc/nvcc command. nvcc accepts --use_fast_math, clang++/hipcc does
  not, so a CUDA-style flag leaks into HIP compilation.

Neither of these leak through the tvm_ffi backend. Aligning hip's
default with cuda makes the two paths symmetric and unbreaks
test_alloc_global and test_all_attrs_together_lazy on ROCm without
having to mark the tests skip or rewrite the cython wrapper.

cython is still available on hip via execution_backend='cython' for
anyone who explicitly wants it.

* [Test] Gate CUDA-only language tests with requires_cuda

Three language tests hardcode target='cuda' (or rely on CUDA-only
codegen behavior) but lacked a CUDA availability marker, so they failed
on the ROCm CI runner with "Cannot find global function
target.build.tilelang_cuda" once the earlier pre-existing failures got
past --maxfail=3. Add @tilelang.testing.requires_cuda to:

- test_tilelang_if_range
- test_annotate_min_blocks_per_sm_launch_bounds
- test_tilelang_transpose and test_tilelang_transpose_square

Also replace the hand-rolled __main__ block in test_tilelang_transpose
with tilelang.testing.main() so the skip markers are honored when the
file is run directly.

* [Test] Delete tile library gemm test

Remove testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py.
2026-04-13 12:42:44 +08:00
Lei WangandClaude Opus 4.6 3ee0988c86 [Refactor][Pipeline] Run pipeline rewriting before layout inference and stabilize tiled WS (#2002)
* Refactor optimization pipeline in phase.py to streamline barrier handling

- Consolidated the handling of shared barriers and pipeline planning by removing redundant conditional checks.
- Ensured that `LowerSharedBarrier`, `PipelinePlanning`, and `InjectSoftwarePipeline` are consistently applied, enhancing the clarity and efficiency of the optimization process.

This change improves the maintainability of the code while preserving existing functionality.

* Enhance tile operation handling with instruction annotation and refactor gemm.h

- Added a new `InstructionAnnotation` pass to annotate tile operations with their instruction kind before layout inference, improving the optimization pipeline's ability to reason about instruction mixes.
- Refactored `gemm.h` to move the `allowTcgen5Mma` and `allowWgmma` methods under the private section, enhancing code organization and encapsulation.

These changes improve the clarity and maintainability of the code while preserving existing functionality.

* Enhance multi-version buffer handling and introduce tile-level warp specialization

- Updated `multi_version_buffer_rewriter.cc` to improve read/write access detection for tile operations by analyzing `tl.tileop.region` calls, ensuring accurate buffer access tracking.
- Modified `phase.py` to integrate `ProducerConsumerWarpSpecializedTiled` before layout inference, allowing for high-level tile-op IR transformations that enhance producer/consumer splits.
- Added a new `ProducerConsumerWarpSpecializedTiled` function in `__init__.py` to facilitate tile-level warp specialization, improving the optimization pipeline's efficiency.

These changes enhance the handling of multi-version buffers and optimize the transformation process for tiled operations.

* Enable tiled WS for stage-1 pipelines

* Move Hopper pipeline planning before layout inference

* Run pipeline rewriting before layout inference

* Add pipeline refactor WIP: subtree_modified_ guard, debug prints, and plan

- inject_pipeline.cc: guard reads/writes recalculation with subtree_modified_
  flag to prevent local.var buffer promotion to kernel parameters
- phase.py: add temporary debug prints after PipelinePlanning and
  InjectSoftwarePipeline (to be removed during CI fix work)
- example_group_per_split_token_cast_to_fp8.py: add disable_cache for debugging
- docs/plan.md: implementation plan for fixing CI test failures
- draft.md: original design draft

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove debug artifacts: prints in phase.py, disable_cache in example

- Remove print("After PipelinePlanning"), print(mod),
  print("After InjectSoftwarePipeline"), print(mod) from
  LowerAndLegalize in tilelang/engine/phase.py
- Remove tilelang.disable_cache() from
  examples/cast/example_group_per_split_token_cast_to_fp8.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix LayoutInference crash on multi-versioned pipeline buffers

After InjectSoftwarePipeline, multi-versioned buffers share the same
data Var as the original but have an extra leading dimension (num_stages).
LayoutInference's alias propagation and annotation handling tried to
Reshape layouts between these buffers, which failed because the total
element counts differ.

Guard three Reshape call sites in layout_inference.cc to skip sibling
buffers whose total storage size is incompatible with the source layout.
This lets multi-versioned buffers get their own layout inference instead
of inheriting an incompatible layout from the original buffer.

Fixes compilation failures in dequantize_gemm, GDN, and other kernels
that use software pipelining with shared memory buffers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Strip pipeline annotations on WS fallback for TMA kernels

When ProducerConsumerWarpSpecializedTiled identifies a TMA kernel as a
warp-specialization candidate but the tiled rewriter cannot handle it
(e.g., conditional loop bodies like sparse block masks), the fallback
previously returned the original function with num_stages annotations
intact.  PipelinePlanning and InjectSoftwarePipeline would then generate
non-WS TMA pipeline code with broken barrier phase tracking for
conditional pipeline bodies (barrier waits outside conditionals cause
deadlocks when the condition is false).

Fix: on WS fallback, strip num_stages annotations from pipeline loops
so that the pipeline passes skip the function.  The kernel runs
unpipelined but correctly.

Fixes CUDA_ERROR_LAUNCH_FAILED in blocksparse_gemm and related TMA
kernels with conditional loop bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add guarded phase-counter support to tiled WS pass

Port PhaseCounter and StageExprReplacer from the legacy
ProducerConsumerWarpSpecialized pass into the tiled WS pass to handle
conditional loop bodies (e.g., sparse block masks).

When the pipeline loop body is wrapped in an IfThenElse without else:
1. Unwrap the condition before classifying statements
2. Create separate producer/consumer PhaseCounters (local int32 buffers)
3. Use counter-based stage/parity expressions instead of loop-variable
4. Wrap producer and consumer bodies in the original condition
5. Increment counters at end of each guarded iteration
6. Rewrite shared-buffer stage indices via StageExprReplacer

This ensures barrier parity stays correct when iterations are
conditionally skipped, fixing CUDA_ERROR_LAUNCH_FAILED in
blocksparse_gemm and related TMA kernels with conditional execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add GemmSPNode support to pipeline planning and injection

Add GemmSPNode handling to:
- inject_pipeline.cc AddReadsWritesForTileOp: model A, E, B as reads
  and C as write (E is the sparse metadata buffer)
- pipeline_planning.cc: same access model for dependency analysis

This makes sparse GEMM visible to the pipeline machinery for correct
stage assignment and buffer multi-versioning. However, the tile-op's
consumer-side buffer accesses still don't get stage-indexed because
the pipeline body rewriter can't rewrite high-level tile-op Call
arguments (an architectural limitation of running InjectSoftwarePipeline
before LowerTileOp).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix GemmSPNode::Lower to use MakeAccessPtrFromRegion

Replace whole-buffer access_ptr(1) calls with MakeAccessPtrFromRegion
for A, B, C, and E buffers in sparse GEMM lowering. This preserves
stage-specific region offsets from pipeline multi-versioning, matching
the dense GemmNode::Lower pattern.

CUDA output now shows correct stage-indexed consumer accesses:
  gemm_sp_ss(..., (k%3)*8192, (k%3)*8192+27648, C_local, (k%3)*2048+49152)
instead of always using stage-0 offsets.

Note: gemm_sp still produces incorrect results because the kernel needs
warp specialization but TiledWSCandidate::Check doesn't recognize it
as a TMA candidate. The non-WS pipeline path generates structurally
different code from the reference WS path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix gemm_sp and seer_attention regressions

Three changes in producer_consumer_ws_tiled.cc:
1. Require num_stages >= 2 for WS candidacy (was >= 1). Single-stage
   kernels like seer_attention don't need WS and the transformation
   produces incorrect results for them.
2. Add HasTmaPipeline() check to detect TMA kernels with pipeline
   annotations that are rejected by the full WS candidate check (e.g.,
   kernels with manual layout annotations like gemm_sp).
3. Strip num_stages annotations for rejected TMA pipeline kernels to
   prevent InjectSoftwarePipeline from generating broken non-WS TMA
   pipeline code.

One change in gemm_sp.cc:
- Use MakeAccessPtrFromRegion for A, B, C, E buffer access pointers
  instead of whole-buffer access_ptr. This preserves stage-specific
  region offsets from pipeline multi-versioning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix WS conditional body unwrapping for complex loop bodies

Only unwrap IfThenElse wrapper when the then-branch is a simple flat
sequence of tile-op Evaluate calls. Skip unwrapping for complex bodies
with LetStmt, For, or other control flow that could break variable
scoping when split into producer/consumer for WS.

Fixes variable-used-before-definition error in
blocksparse_attention sparse_gqa_decode_varlen_indice, which has a
conditional loop body containing LetStmt bindings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert num_stages >= 2 to >= 1 for WS candidacy

The >= 2 threshold broke test_num_stages_one_pure_tma_keeps_auto_warp_specialize.
Pure TMA kernels with num_stages=1 should still be WS candidates.
The seer_attention issue (num_stages=1 with manual layout) is handled
by the has_manual_layout_ check, not the num_stages threshold.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Propagate manual layouts onto MVB-expanded buffers via Layout::Expand

When LayoutInference encounters an MVB-expanded buffer (with leading
stage dimensions) whose trailing dimensions match the original layout,
use Layout::Expand to propagate the manual layout instead of rejecting
or skipping the buffer. Applied to all 3 layout propagation paths:
annotated layout map, alias propagation, and finalization.

Also remove the blanket !has_manual_layout_ WS candidate rejection
since manual layouts now survive onto versioned shared buffers via
Layout::Expand.

Fixes test_sparse_ws_regular_metadata_copy_stays_in_producer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Extend conditional body unwrapping for LetStmt chains and restore
has_manual_layout_ guard

1. LetStmt chain peeling: when IfThenElse then_case starts with
   LetStmt bindings, peel them and append to let_bindings before
   checking the simple-body guard. This allows WS for conditional
   bodies with variable definitions (e.g., sparse attention patterns).

2. Restore !has_manual_layout_ in WS candidacy check: removing it
   caused dequant_groupedgemm_bf16_mxfp4_hopper to fail because
   MXFP4 layouts don't survive MVB expansion. The Layout::Expand fix
   handles sparse metadata layouts but not all manual layout types.

3. Layout::Expand propagation (from Round 6) remains in place for
   future use when MVB learns to handle all manual layout types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove is_simple_body guard from conditional WS unwrapping

The simple-body guard only accepted flat Evaluate sequences inside
IfThenElse, blocking legitimate WS for complex conditional bodies
like sparse flash attention (T.clear, T.reduce_max, T.gemm inside
the guard). The LetStmt peeling already handles variable scoping.

Fixes test_pure_tma_consumer_local_init_does_not_leak_into_producer
and test_sparse_ws_regular_metadata_copy_stays_in_producer.

The remaining test_mixed_tma_cp_async_shared_stage_barriers failure
is a pre-existing issue on the original branch: the tiled WS pass
produces SIMT copies instead of cp.async because LowerPTXAsyncCopy
is not in the pass pipeline (the comment at phase.py:308 says it
runs earlier but no actual call exists on either branch or reference).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Preserve pipeline context for WS producer cp.async injection

Wrap the WS producer loop body in a kPipelineContextNumStages AttrStmt
so that LowerTileOp's pipelined_depth_ is > 0 when processing SIMT
producer copies. This enables InjectPTXAsyncCopy to generate cp.async
for global-to-shared copies in the WS producer branch.

Without this, the WS rewriter strips all pipeline annotations from
the rewritten loops, causing LowerTileOp to skip cp.async injection
for SIMT producers. The consumer loop stays annotation-free since it
doesn't need cp.async.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix mixed barrier protocol, consumer-init sinking, restore manual-layout guard

1. Mixed TMA+cp.async barrier: use ptx_cp_async_barrier_noinc for
   forward barrier arrival in mixed producer groups, matching the
   reference producer_consumer_ws.cc protocol.

2. Consumer-only pre-loop init sinking: in ReplacePipelineLoopInStmt,
   guard pre-loop siblings as consumer-only when they're not classified
   as producer (TMA/SIMT/cp.async). Fragment init (T.fill, T.clear)
   and local buffer init are placed in the consumer branch instead of
   the shared prelude.

3. Restored blanket has_manual_layout_ guard: the dtype-based heuristic
   to distinguish sparse metadata from MXFP4 layouts doesn't work
   because both use uint8. Dequant_groupedgemm_bf16_mxfp4_hopper
   requires the guard to prevent broken WS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Narrow consumer-init sinking, targeted manual-layout check, per-group barrier

1. Consumer-init sinking: only sink pre-loop stmts that are FillNode
   writing to fragment/local buffers. Keep block_mask setup and shared
   state in the shared prelude.

2. Manual-layout: attempt targeted check that only rejects when TMA
   copy destinations match layout_map entries. Collect layout_map vars
   and compare against TMA copy destinations.

3. Per-group cp.async barrier: use group-level cp.async flag (single
   group for now) instead of function-wide boolean.

The 3 WS issue tests still fail because the layout_map annotation
parsing falls through to the conservative rejection path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix layout_map parsing with Var→Buffer mapping for manual-layout check

The layout_map annotation uses Map<Var, Layout> before LayoutInference
(not Map<Buffer, Layout>). Parse as Map<ObjectRef, ObjectRef> and
handle both key types: Buffer (post-inference) and Var (pre-inference).
For Var keys, look up the corresponding alloc_buffer by data Var match.

Compare collected manual-layout buffers against pipeline copy
destinations: reject only when a manually-laid-out buffer is also
a producer copy target (TMA/SIMT/cp.async) inside the pipeline.
This allows sparse metadata (E_shared, SIMT-copied) onto the WS path
while rejecting dequant MXFP4 (B_shared, SIMT-copied with swizzle).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix SEGFAULT in manual-layout check, use DetectSwizzleMode

1. Fixed SEGFAULT: removed dangling layout_map_layouts_ vector that
   was never populated, causing OOB access. Now stores Buffer+Layout
   pairs in layout_map_entries_.

2. Use DetectSwizzleMode to distinguish swizzled layouts (MXFP4,
   incompatible with MVB) from non-swizzled (sparse metadata, safe).
   Swizzled layouts reject WS candidacy; non-swizzled layouts allow it.

3. Removed debug LOG(WARNING) from hot path.

4. Parse layout_map annotation keys as both Buffer and Var (via
   Map<ObjectRef, ObjectRef>), resolving Var keys to alloc_buffers.

Results: sparse metadata WS test PASSES, dequant PASSES (protected).
Down to 2 failures: mixed barrier pattern + consumer init sinking.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Simplify consumer-init sinking to Evaluate-only classification

Sink pre-loop Evaluate nodes classified as kConsumer into consumer
branch. Keep For loops (block_mask setup), producer copies, and other
control flow in the shared prelude. This is simpler and safer than
the FillNode scope check approach.

The test_pure_tma_consumer_local_init test still fails because the
T.fill statements are at a different structural level than the
SeqStmt where the pipeline loop lives. Fixing this requires deeper
IR structure analysis.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Sink consumer-only pre-loop init into WS consumer branch

Extract consumer-only pre-loop Evaluate statements (T.fill on
fragments) from the shared prelude and prepend them to the consumer
branch inside the WS if/else structure. This ensures fragment init
like acc_o, logsum, scores_max appears only in the consumer branch,
not in the shared prelude or producer branch.

Uses a two-pass approach: first ReplacePipelineLoopInStmt extracts
consumer-only stmts into extracted_consumer_init_, then the WS body
is rebuilt with the extracted stmts prepended to the consumer branch.

Fixes test_pure_tma_consumer_local_init_does_not_leak_into_producer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Finalize pipeline refactor fixes

* Refactor CopyNode stride checks for TMA bulk load/store

- Extracted the global stride validation logic into a new static method `CheckGlobalStrides` for better readability and reusability.
- Updated `CheckBulkLoad` and `CheckBulkStore` methods to utilize the new stride checking function, improving code clarity and maintainability.
- Enhanced documentation for the new method to clarify its purpose and requirements.

* Remove redundant copy direction notes from documentation in `copy.h` for stride checks. This simplifies the comments while maintaining clarity on TMA requirements.

* refactor

* layout related fix

* refactor mbarrier with software pipeline.

* remove legacy pass

* Enhance TMA barrier handling and merging logic

- Updated `CopyToTmaCopyRewriter` to conditionally emit arrive barriers based on the last TMA copy.
- Refactored barrier creation to allow merging of TMA barriers when conditions are met, reducing the number of barriers needed.
- Adjusted consumer and producer logic to accommodate merged barriers, ensuring correct synchronization across TMA copies.
- Improved documentation and comments for clarity on the new barrier merging behavior.

* Update example_mhc_post.py to disable main execution and add test function call

- Commented out the main function call in `example_mhc_post.py`.
- Added a call to `tilelang.disable_cache()` and a new `test(n=4096, h=2560)` function for testing purposes.

* Enhance pipeline barrier handling and TMA copy detection

- Updated `RewritePipelineTmaBarriers` to accept additional parameters for loop variable and stage count, improving barrier synchronization.
- Modified `HandleTileOp` to ensure only user-defined T.copy patterns are marked for pipeline barriers, preventing interference with T.tma_copy.
- Adjusted test cases to enforce specific CUDA compute version requirements for better compatibility and consistency.

* lint fix

* Enhance convolution example and TMA handling

- Added kernel source printing in `example_convolution.py` for debugging.
- Disabled the main function call and invoked `run_regression_perf()` to streamline execution.
- Introduced `MakeTmaLeaderCondition` function in `copy.cc` to improve TMA leader-thread condition handling.
- Updated `LowerBulkCopy` and `LowerBulkCopy1D` methods to utilize the new TMA leader condition for better thread management.
- Enhanced `Conv2DIm2ColOpNode` to support barrier annotations, improving synchronization in TMA operations.

* enhance

* Remove example_dequant_groupedgemm_bf16_mxfp4_hopper.py and clean up phase.py by removing unnecessary whitespace. Enhance TMA handling in producer_consumer_ws_tiled.cc to improve barrier synchronization and streamline TMA copy operations.

* fix

* fix

* Eliminate MVB(barrier_only=true) late fixup from OptimizeForTarget

Move pipeline barrier ownership into InjectSoftwarePipeline: create
pipeline_mbar[num_stages] at final expanded size instead of
pipeline_mbar[1] that required late MVB expansion.

Key changes:
- RewritePipelineTmaBarriers creates barriers at num_stages size
- Barrier indices use FloorMod(loop_var - loop_min, num_stages)
- barrier_init has num_stages entries (one per slot, arrive_count=1)
- CopyToTmaCopyRewriter accepts PrimExpr barrier_id (was int)
- phase.py: remove MVB(barrier_only=True), unify both paths under
  PlanAndUpdateBufferAllocationLocation
- Fix pre-existing test expectation for tma_copies annotation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix Codex review issues: num_stages=1 regression, im2col pipeline barriers, test fixes

1. Fix num_stages=1 regression: use tl_pipelined_num_stages annotation
   for barrier sizing instead of max_stage+1. Gate barrier creation on
   pipeline_depth > 1 so num_stages=1 kernels don't get multi-versioned
   pipeline barriers.

2. Extend RewritePipelineTmaBarriers to handle c2d_im2col: annotate
   im2col calls with pipeline barrier in CopyToTmaCopyRewriter. Add
   im2col TMA recognition to PipelinePlanning. Fix im2col Lower() to
   respect emit_arrive annotation from pipeline barriers.

3. Fix test_simple_pipeline: use annotation-checking approach instead of
   structural equality with hardcoded tma_copies annotation that fails
   on non-Hopper targets.

4. Remove dead kPipelineMVBStageExpr/kPipelineMVBParityExpr/
   kPipelineMVBContextNumStages emission from inject_pipeline.cc since
   pipeline barriers are now created at final size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix depth-1 barrier ownership, add regression tests, remove dead kPipelineMVB*

1. Fix depth-1 ownership gap: always create shared pipeline barrier for
   TMA copies even when pipeline_depth=1. This prevents LowerTileOp from
   allocating separate per-copy internal barriers, keeping num_stages=1
   kernels at pipeline_mbar[1] (single slot).

2. Add checked-in lowering regression tests:
   - non-WS num_stages=3 TMA GEMM → asserts pipeline_mbar[3], no fallback
   - non-WS num_stages=1 TMA GEMM → asserts pipeline_mbar[1], no multi-slot
   - non-WS num_stages=3 im2col → asserts pipeline_mbar[3] feeds tma_load_im2col

3. Remove dead kPipelineMVB* definitions from pipeline_utils.h and
   consumption code from multi_version_buffer_rewriter.cc (stacks,
   explicit parity/version index logic, attr stripping).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix GemmWMMA.lower() signature and autotuner cache backwards compatibility

[P1] Add missing mbar_phase_expr parameter to GemmWMMA.lower() to match
the interface expected by GemmPy.lower() dispatch. Without this, any
RDNA kernel using the WMMA path would fail with TypeError.

[P2] Make out_idx.json loading optional in autotuner load_from_disk().
Older cache directories don't have this file; fallback to
compile_args.out_idx when the file is absent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add .humanize to gitignore

* Fix HIP swizzle codegen and CPU scalar GEMM region handling

[P2] Update codegen_hip.cc to parse tvm_tuple(device_func, panel_size)
format for threadblock_swizzle_pattern, matching the annotation format
now emitted by T.use_swizzle(). Previously expected StringImmNode which
would ICHECK-fail.

[P2] Fix gemm_scalar.py: clear only the output tile region (not the
whole buffer), and use the last two dimensions from regions to handle
rank>2 buffers with leading singleton dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix HIP codegen to parse tvm_tuple swizzle annotation format

Update codegen_hip.cc threadblock_swizzle_pattern handler to parse
tvm_tuple(device_func, panel_size) format, matching CUDA and cutedsl
codegens. Previously expected StringImmNode which ICHECK-fails with
the current annotation format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Restore kPipelineMVB* annotations — still needed by WS tiled full MVB

The kPipelineMVBStageExpr/ParityExpr/ContextNumStages annotations and
their MVB consumption code cannot be removed: they are emitted by
EmitImpl for ALL pipelines and consumed by the full MVB call inside
ProducerConsumerWarpSpecializedTiled. Removing them broke non-TMA
pipeline kernels like mhc_post that go through the WS path.

Restores: annotation emission in inject_pipeline.cc, constant
definitions in pipeline_utils.h, and consumption code in
multi_version_buffer_rewriter.cc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Unify barrier multi-versioning in InjectSoftwarePipeline (Direction A)

Move all pipeline barrier multi-versioning into InjectSoftwarePipeline
via ExpandPipelineBarriers, eliminating the need for late
MVB(barrier_only=true) in OptimizeForTarget.

ExpandPipelineBarriers runs before BuildPipeline and handles:
- ISP-created pipeline_mbar (for non-WS TMA pipelines)
- User-written T.alloc_barrier (for manual WS pipelines like softpipe)

Key design: only barriers with explicit ptx_arrive_barrier calls OR
ISP-created local barriers are expanded. Barriers whose arrival is
managed internally by tile-ops (e.g., tcgen05 MMA arrive) are left
unchanged. This distinguishes pipeline sync barriers from hardware-
managed barriers.

Buffer expansion: barrier[N] -> barrier[N * num_stages]
Index rewriting: barrier[idx] -> barrier[stage_expr * N + idx]
Parity rewriting: user_parity -> (iteration_block + offset) % 2
barrier_init replication: [c0,c1] -> [c0,c1,c0,c1] for num_stages=2

Expanded buffers propagate to outer blocks via pending_buffer_remap_.
barrier_init annotations are replicated in VisitStmt_(BlockNode).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix Python 3.9 compat: replace star expression in index with tuple concat

* fix

* fix

* revert changes

* fix

* enhance pipeline

* enhance pipeline

* implement descriptor reuse pass

* Refactor pipeline management and enhance async copy handling

- Updated `example_mhc_pre.py` to replace the main function call with a test function for better testing flexibility.
- Modified `example_gqa_decode.py` to disable argument parsing and added latency measurement for regression performance.
- Enhanced `copy.cc` and `copy.h` with new checks for pipeline-managed cp.async synchronization and improved async copy handling.
- Updated `inject_pipeline.cc` and `pipeline_planning.cc` to refine the handling of tile operations and global/shared buffer checks.
- Added tests to ensure correct behavior of async pipeline and descriptor allocation reuse.

This commit improves the overall pipeline management and async copy capabilities, ensuring better performance and flexibility in the codebase.

* enhance pipeline

* enhance pipeline

* enhance pipeline

* enhance pipeline

* enhance pipeline

* Revert "enhance pipeline"

This reverts commit c056ded3c9.

* preloop tma handling

* lint fix

* Clean up debug changes in examples

* Refactor PTX async copy injection result

* refactor

* Refactor tile op access region collection

* Clean up pipeline access and async analysis

* Refactor head async wait analysis

* refactor layout expand

* auto tma fix

* Allow auto TMA store for plain copy

* slash sparse test fix

* Unify warp specialization and internalize buffer versioning

* Revert formatting-only changes

* Keep deprecated TL_DISABLE_TMA_LOWER compat

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:54:55 +08:00
KurisandClaude Opus 4.6 e45ecf7dc4 [Feature] Support T.annotate_compile_flags, T.annotate_pass_configs, and out_idx as PrimFunc attrs (#2006)
Allow configuring pass configs, compile flags, and out_idx directly
inside function bodies using T.annotate_compile_flags(),
T.annotate_pass_configs(), and T.empty()+return. These are stored as
proper PrimFunc attrs (tilelang_compile_flags, tilelang_pass_configs,
tilelang_out_idx) instead of monkey-patching, and merged at compile
time. Annotations can be placed before or after tensor type annotations.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 12:42:47 +08:00
Lei WangandClaude Opus 4.6 1ede0bd748 Introduce T.deallocate_tmem and T.transpose (#1971)
* Fix tcgen05 barrier allocation planning regression

* Add explicit TMEM deallocation and shared transpose copy

* Add transpose operation to documentation and update implementation in copy_op.py

* LINT FIX

* Refactor: extract transpose from CopyNode into standalone TransposeNode op

Remove the transpose annotation logic from CopyNode (GetTranspose,
MakeIndices transpose branch, MakePredicate transpose branch, and
GetCopyInst early return). Transpose is now handled by the independent
TransposeNode registered as tl.tileop.transpose.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Refactor CopyNode to remove transpose handling from index generation and predicate creation. Simplify MakeIndices and MakePredicate methods by eliminating unnecessary transpose checks and related logic. Update associated checks to ensure index consistency. Clean up unused GetTranspose method in copy.h.

* lint fix

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 15:56:21 +08:00
Lei Wang bdf436d4c3 [Feature] Support TMA store in T.tma_copy() (#1981)
* [Feature] Support TMA store in T.tma_copy() with user-managed synchronization

T.tma_copy() previously only supported TMA loads (global -> shared) with
user-managed barrier synchronization. This extends it to also support TMA
stores (shared -> global), where:

- The barrier parameter is now optional (not needed for stores)
- For stores, only tma_store + tma_store_arrive is emitted (no wait)
- Users call T.tma_store_wait() explicitly to synchronize

* Refine tma_store_wait to accept count parameter and clean up builtin signatures

- Wire tma_store_wait count parameter through the full stack (Python -> C++
  builtin registration -> CUDA/CuTeDSL codegen)
- Replace vague *args with proper signatures for fence_proxy_async() and
  tma_store_arrive() (both take no arguments)
- Improve docstrings for internal TMA APIs (create_tma_descriptor, tma_load,
  tma_load_2sm)
2026-03-27 15:29:48 +08:00
KurisandClaude Opus 4.6 dc60ab8f04 [Bugfix] Fix alloc_var re-bind warning when assigned with comparison ops (#1974)
* [Bugfix] Fix alloc_var re-bind warning when assigned with comparison ops

EqualOp/NotEqualOp (returned by BufferLoad == / !=) are not PrimExpr
subclasses, so `bind()` missed the alloc_var store path and fell through
to `bind_immutable`, triggering a spurious "Immutable value is re-bound"
warning.

Convert them to PrimExpr via `.asobject()` before the store check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix pre-commit lint: double quotes, remove redundant parens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix ruff format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 11:17:21 +08:00
Tong WU 88049820fe [Feature] Introduce annotation for minBlocksPerMultiprocessor in __launch_bounds__ (#1979)
* Add annotate_min_blocks_per_sm for __launch_bounds__(..., minBlocksPerSM)

- Python: T.annotate_min_blocks_per_sm(n) sets tl.min_blocks_per_sm on the prim_func
- Codegen: emit second launch_bounds argument from attr; default remains 1 when unset
- Export from tilelang.language; document attr key in builtin.h

Made-with: Cursor

* test

* lint
2026-03-26 19:42:20 +08:00
Chaofan Lin d0090b428e [Feature] Support alloc global workspace (#1940)
* add docstring

* add hoist global allocation pass

* fix rebase

* fix

* fix tvm

* fix
2026-03-23 19:26:24 +08:00
Lei Wang b5bd642479 [Refactor] Separate gemm into explicit wgmma_gemm and tcgen05_gemm functions (#1949)
* Refactor GEMM operations to use explicit WGMMA and TCGEN5MMA functions

- Replaced instances of T.gemm with T.wgmma_gemm and T.tcgen05_gemm in various example scripts to enhance performance and control over asynchronous execution.
- Updated related documentation to reflect the changes in GEMM function usage, ensuring clarity on the new explicit interfaces.
- Removed unnecessary wg_wait parameters from GEMM calls, aligning with the new function signatures.

This refactor improves the efficiency of matrix multiplication operations in the TileLang framework, particularly for Hopper and Blackwell architectures.

* lint fix

* Refactor GEMM operations to unify function signatures

- Replaced deprecated GEMM function variants (gemm_v1, gemm_v2, tcgen05_gemm_v1, tcgen05_gemm_v2) with a single unified function (gemm, tcgen05_gemm) across examples and tests.
- Updated test cases to reflect the new function signatures, ensuring consistency and clarity in GEMM operation usage.
- This change simplifies the API and enhances maintainability within the TileLang framework.

* Refactor GEMM initialization to improve annotation checks

- Simplified the handling of "is_wgmma" and "is_tcgen05" annotations by removing redundant checks and adding explicit error messages for type validation.
- Enhanced the validation for the "mbar" argument to ensure it is a BufferLoadNode, improving error handling and code clarity.
- These changes streamline the initialization process for GEMM operations, enhancing maintainability and robustness in the TileLang framework.
2026-03-20 14:54:43 +08:00
Lei WangandZhiwen Mo 5a538f3b37 Support packed subtype views during layout reshape (#1947)
* Support packed subtype views in layout reshape

* lint fix

---------

Co-authored-by: Zhiwen Mo <zm125@ic.ac.uk>
2026-03-19 16:08:15 +08:00
Lei WangandZhiwen Mo f8dc61c02c test: reduce CI runtime for slow Python suites (#1932)
* test: trim CI runtime for slow Python suites

* remove useless test

* Update TVM submodule to latest commit and remove manual device assert test from CI. Replace with a call to tilelang.testing.main().

* lint fix

* fix

* revert test for eager jit

---------

Co-authored-by: Zhiwen Mo <zm125@ic.ac.uk>
2026-03-18 13:08:30 +08:00
Lei WangandClaude Opus 4.6 ded6a99221 [Feature] Add Producer-Consumer Warp Specialization and T.tma_copy() API (#1909)
* [Feature] Add Producer-Consumer Warp Specialization and T.tma_copy() API

This PR introduces Producer-Consumer Warp Specialization for sm90+ TMA
pipelines and a new T.tma_copy() API for explicit mbarrier management.

Key changes:

1. **ProducerConsumerWarpSpecialized pass** (new):
   Splits pipelined TMA loops into producer (TMA loads) and consumer
   (compute) warp groups with back-pressure barriers for buffer reuse.
   Works with num_stages >= 1. Producer warp (128 threads) handles
   arrive_expect_tx + tma_load; consumer warps handle compute + arrive
   on back-pressure barriers.

2. **T.tma_copy() API** (new):
   Fire-and-forget TMA copy with a required `barrier` parameter. Unlike
   T.copy() which emits producer+wait pairs, T.tma_copy() emits only
   arrive_expect_tx + tma_load. User manages synchronization via
   T.mbarrier_wait_parity().

3. **MultiVersionBuffer barrier expansion**:
   Extended to handle `shared.barrier` scope buffers, expanding them for
   pipelining (1D size multiplication instead of prepending a dimension).
   Auto-computes mbarrier parity as `(k // num_stages) % 2`.

4. **Pass ordering** (phase.py):
   LowerSharedBarrier now runs after MultiVersionBuffer in the TMA path
   so barrier buffers retain their `shared.barrier` scope during expansion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix for annotate reg alloc

* Enhance debugging and performance measurement in examples

- Added print statements to output kernel source for both forward and backward sparse MLA examples, aiding in debugging.
- Updated `sparse_mla_fwd_pipelined.py` to run performance regression tests and print average latency, improving performance tracking.
- Disabled auto cache in `example_mha_sink_fwd_bhsd.py` for better control during testing.

* fix

* Enhance debugging and performance tracking in examples

- Added print statements to output kernel source in various example scripts, including `example_gqa_sink_bwd_bhsd.py`, `example_blocksparse_gemm.py`, and `example_dequant_groupedgemm_bf16_mxfp4_hopper.py`, aiding in debugging.
- Updated default `window_size` in `example_gqa_sink_bwd_bhsd.py` for improved configuration.
- Disabled auto cache in `example_gemm_schedule.py` to enhance control during testing.
- Introduced a new test for preserving protected auto-injected wait groups in the async copy optimization process.

* clean

* Remove unnecessary print statements for kernel source in example scripts

- Eliminated print statements from `example_gqa_sink_bwd_bhsd.py`, `example_blocksparse_gemm.py`, and `example_dequant_groupedgemm_bf16_mxfp4_hopper.py` to clean up output and improve readability.
- These changes streamline the examples while maintaining functionality.

* clean

* lint fix

* Refactor T.tma_copy() and barrier synchronization in examples and tests

- Updated `example_warp_specialize_gemm_copy_1_gemm_0.py` to use `T.tma_copy()` for optimized memory copying with explicit barrier management.
- Enhanced test cases in `test_tilelang_issue_tma_no_ws.py` and `test_tilelang_language_tma_copy.py` to reflect changes in barrier synchronization, ensuring proper functionality with the new T.tma_copy() API.
- Removed unnecessary print statements and adjusted barrier allocations for clarity and performance.
- Cleaned up the `test_tilelang_transform_inject_tma_barrier.py` file by deleting it, as it was no longer needed.

* Add buffer data mapping for remapped buffers in multi_version_buffer_rewriter

- Introduced a check to ensure that the data variable of a buffer is discoverable, allowing the barrier_init annotation update to find the remapped buffer correctly.
- This change enhances the functionality of the buffer remapping process, ensuring proper synchronization in the transformation pipeline.

* Implement TMA im2col load synchronization with mbarrier allocation

- Added support for allocating mbarriers to synchronize TMA im2col loads, enhancing the pipeline's barrier management.
- Introduced logic to handle mbarrier creation and integration into the TMA copy process, ensuring proper synchronization and data transfer.
- Updated the handling of the mbarrier in the TMA copy statement to improve performance and maintain functionality within the thread-gated block.

* Implement TMA im2col load synchronization with mbarrier allocation

- Added support for allocating mbarriers to synchronize TMA im2col loads, enhancing the pipeline's barrier management.
- Introduced logic to handle mbarrier initialization and integration within the TMA copy process, ensuring proper synchronization during memory operations.
- Updated the handling of the mbarrier in the im2col operation to improve performance and maintain consistency in multi-threaded environments.

* disable tma lower for test_cutedsl_barrier

* Refactor code formatting in test_tilelang_jit_cutedsl.py

- Improved readability by adjusting the formatting of the `tilelang.compile` function call.
- Enabled the main testing function in the script to run without being commented out.

* Enhance sparse_mla_fwd.py and thread_storage_sync.cc with code cleanup and new functionality

- Added a call to disable cache in the main execution block of `sparse_mla_fwd.py` for improved performance.
- Commented out unused benchmarking code in `test_sparse_mla_fwd` to streamline testing.
- Introduced new utility functions in `thread_storage_sync.cc` to analyze and optimize shared memory access patterns, enhancing synchronization management.
- Improved readability and organization of the code by restructuring and commenting on key sections.

* Add thread storage synchronization utilities and optimizations

- Introduced functions to identify shared-like scopes, buffers, and pointer variables, enhancing memory management.
- Implemented a `BarrierTransparentStmtAnalyzer` to analyze statement transparency concerning shared memory.
- Developed a `ThreadStorageSyncOptimizer` to optimize sequences of statements by removing unnecessary synchronization calls, improving performance in multi-threaded environments.
- Enhanced handling of shared memory access in various call types, ensuring proper synchronization during memory operations.

* remove optimize thread_storage_sync

* Refactor pipeline planning to enhance cp.async group scheduling

- Introduced a last-use index for cp.async groups to improve scheduling accuracy.
- Removed unnecessary tracking of first consumers, simplifying the scheduling logic.
- Updated the handling of cp.async and commit statements to ensure proper group ordering based on last-use.
- Added a new test to verify that cp.async groups are ordered correctly by their last-use index.

* lint fix

* Add CUDA requirements to TMA copy tests and update main execution call

- Added decorators to require CUDA and a minimum compute version for the `test_tma_copy_pipeline_2_stages` and `test_tma_copy_pipeline_3_stages` functions.
- Updated the main execution block to call `tilelang.testing.main()` instead of directly invoking the test functions, improving test execution management.

* Refactor attention sink examples by removing pipelined implementations

- Updated imports in `benchmark_gqa_sink_fwd.py` and `benchmark_mha_sink_fwd.py` to use the non-pipelined versions of the attention sink functions.
- Deleted the pipelined implementations of `example_gqa_sink_fwd_bhsd_wgmma_pipelined.py` and `example_mha_sink_fwd_bhsd_wgmma_pipelined.py`.
- Cleaned up regression and test files to remove references to the deleted pipelined examples, ensuring consistency across the codebase.

* performance fix

* Enhance example_blocksparse_gemm.py and inject_pipeline.cc with debugging and utility improvements

- Added a print statement to output the kernel source in `example_blocksparse_gemm.py` for debugging purposes.
- Updated `inject_pipeline.cc` to include a new utility function for stripping TMA copy write buffer attributes, improving code clarity and functionality.
- Modified `producer_consumer_ws.cc` to utilize the new utility function, enhancing the handling of TMA barriers.
- Expanded the `_compile_tvm_ffi` function in the test file to accept additional keyword arguments, improving flexibility for test configurations.
- Introduced a new test to verify that pure TMA warp specialization correctly emits barriers, ensuring compliance with expected behavior.

* lint fix

* Refactor guard variable declarations in producer_consumer_ws.cc for clarity

- Changed guard variable declarations from non-const to const references to improve performance and readability.
- This minor adjustment enhances the handling of producer guards in the context of TMA barriers.

* lint fix

* fix

* lint fix

* perf fix

* Add print statement for kernel source and update main execution in example_dequant_gemm_w4a8.py

- Introduced a print statement to output the kernel source for debugging purposes.
- Updated the main execution block to call `run_regression_perf()` and print the latency, enhancing performance measurement capabilities.

* fix

* Add debugging output and update execution flow in example_tilelang_block_sparse_attn.py

- Added a print statement to display the kernel source for better debugging.
- Updated the main execution block to disable cache and call `run_regression_perf()`, printing the resulting latency for performance measurement.
- Enhanced the producer-consumer logic in producer_consumer_ws.cc with new utility functions to manage local variable access and improve code clarity.
- Introduced a new test case in test_tilelang_issue_tma_no_ws.py to ensure consumer-only local initializations do not leak into the producer, verifying correct behavior in TMA contexts.

* Revert "Add debugging output and update execution flow in example_tilelang_block_sparse_attn.py"

This reverts commit 4995504098.

* Enhance producer-consumer logic and add tests for TMA behavior

- Updated the logic in producer_consumer_ws.cc to avoid reserving unused pre-loop barriers, improving efficiency.
- Introduced a new test case in test_tilelang_transform_producer_consumer_ws.py to verify that consumer-only local initializations do not leak into the producer.
- Added assertions in test_tilelang_issue_tma_no_ws.py to ensure correct behavior of TMA contexts.

* Add local access tracking and buffer management in producer_consumer_ws.cc

- Introduced LocalAccessSummary and LocalLiveSet structures to track read/write buffers and variable definitions.
- Implemented BufferDataToBufferCollector and LocalAccessCollector classes for efficient buffer data collection and access summary generation.
- Enhanced the logic for handling TMA copy write buffer data extraction, improving the producer-consumer interaction in TMA contexts.

* fix

* fix

* fix

* Refactor producer-consumer logic and enhance kernel execution in tilelang

- Updated the SparseFlashAttn class to improve kernel invocation clarity by separating kernel definition and execution.
- Enhanced producer-consumer workflow in producer_consumer_ws.cc by introducing optional guards for wait statements, ensuring correct behavior in concurrent contexts.
- Added utility functions to manage loop body lets, improving code readability and maintainability.
- Expanded test coverage in test_tilelang_transform_producer_consumer_ws.py to verify the preservation of guarded waits and backpressure logic.

* Enhance test coverage and execution flow in attention sink examples

- Added pytest timeout decorators to tests in test_example_attention_sink.py and test_example_blocksparse_attention.py to prevent long-running tests.
- Updated the main execution block in test_example_attention_sink.py to disable cache and directly call the sliding window test function, improving test execution clarity.

* update

* lint fix

* lint fix

* Refactor and enhance barrier handling in tilelang transformations

- Removed unused VisitStmt_ method from fuse_mbarrier_arrive_expect_tx.cc to streamline code.
- Introduced ProducerSimtCopyDetector in producer_consumer_ws.cc to identify SIMT copy patterns, improving buffer access tracking.
- Enhanced test coverage in test_tilelang_transform_fuse_mbarrier_arrive_expect_tx.py and test_tilelang_transform_producer_consumer_ws.py to validate new functionality and ensure correct barrier behavior.

* lint fix

* lint fix

* Refactor example scripts and clean up utility functions

- Removed commented-out print statements in example_warp_specialize_gemm_copy_1_gemm_0.py and example_warp_specialize_gemm_softpipe_stage2.py for cleaner code.
- Simplified buffer scope checks in utils.h by removing inline functions and directly using scope comparisons in relevant functions.
- Enhanced buffer handling in lower_tile_op.cc and producer_consumer_ws.cc by streamlining condition checks for buffer types.

* Remove unnecessary cache disabling in tilelang tests and examples

- Eliminated calls to tilelang.disable_cache() in example_gqa_decode_varlen_logits.py, test_tilelang_issue_tma_no_ws.py, and test_tilelang_language_tma_copy.py for cleaner code and improved performance.
- Updated test execution flow in test_tilelang_issue_tma_no_ws.py to directly call the main testing function.

* fix

* Add LocalAccessSummary collection for loop bounds in producer_consumer_ws.cc

- Introduced CollectExpr method in LocalAccessCollector to gather access summaries for expressions.
- Updated pre-loop liveness assignment to include variables used in pipeline loop bounds, ensuring accurate classification of scalar setups.

* enhance

* fix

* enhance

* fix

* fix

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:08:10 +08:00
Lei WangandZhiwen Mo d338c4ff95 [Bugfix] Fix concurrent TempDirectory creation during CUDA compilation (#1926)
* [Refactor] Update TVM subproject and enhance CUDA artifact path resolution

- Updated the TVM subproject to commit 470430cf.
- Introduced a new helper function `_resolve_artifact_paths` in `nvcc.py` to streamline the resolution of CUDA artifact paths, improving code clarity and maintainability.
- Refactored the `compile_cuda` function to utilize the new helper for managing temporary file paths based on the specified output directory.

* [Enhancement] Add CUDA requirement decorator to matmul test

- Introduced the `@tilelang.testing.requires_cuda` decorator to the `test_matmul` function, ensuring that the test is only executed in environments with CUDA support. This change improves test reliability and clarity regarding dependencies.

* lint fix

---------

Co-authored-by: Zhiwen Mo <zm125@ic.ac.uk>
2026-03-13 12:43:33 +08:00