Compile-Only Tool¶
python -m tilelang.tools.compile_only lowers a TileLang program to
inspectable kernel source without running it. No GPU, CUDA driver, or device
compilation is required: the tool stops after
tilelang.lower(..., enable_device_compile=False) and writes the generated
kernel source to a file. It backs the TileLang integration in
Compiler Explorer and is equally useful for inspecting
locally what lower() produces for a kernel.
Requirements¶
The tool ships with the standard TileLang installation and has no optional
dependencies. The default c target works on any machine, including CPU-only
hosts. --target cuda requires a wheel whose CUDA codegen FFI is compiled in:
Linux wheels include it and can emit CUDA source without a GPU present, while
macOS Metal wheels do not and fail with a clear
CUDA codegen FFI missing message instead of an AttributeError.
Quick Start¶
Write a self-contained example that defines a kernel but never launches it:
# example.py
import tilelang
import tilelang.language as T
@tilelang.jit
def add(A, B):
N = 64
A: T.Tensor((N,), T.float16)
B: T.Tensor((N,), T.float16)
C = T.empty((N,), T.float16)
with T.Kernel(1, threads=64):
for i in T.Parallel(N):
C[i] = A[i] + B[i]
return C
Compile it to CPU C source:
python -I -m tilelang.tools.compile_only --output_file out.c example.py
out.c then contains the generated kernel source:
// tilelang target: {"kind":"c","tag":"","keys":["cpu"],"host":{"kind":"c","tag":"","keys":["cpu"]}}
#include <tl_templates/cpp/common.h>
#ifdef __cplusplus
extern "C"
#endif
int32_t add_kernel(half* A, half* B, half* C);
#ifdef __cplusplus
extern "C"
#endif
int32_t add_kernel(half* A, half* B, half* C) {
for (int32_t i = 0; i < 8; ++i) {
*(half8*)(C + (i * 8)) = (*(half8*)(A + (i * 8)) + *(half8*)(B + (i * 8)));
}
return 0;
}
CUDA source generation works the same way and still needs no GPU; the architecture is pinned instead of detected:
python -I -m tilelang.tools.compile_only --target cuda --output_file out.cu example.py
extern "C" __global__ void __launch_bounds__(64, 1) add_kernel(const half_t* __restrict__ A, const half_t* __restrict__ B, half_t* __restrict__ C) {
C[((int)threadIdx.x)] = (A[((int)threadIdx.x)] + B[((int)threadIdx.x)]);
}
How the Input Is Processed¶
The input file is imported as a regular Python module, so its top-level code runs. Keep examples compile-only: define kernels, do not launch them or allocate tensors at import time. Running the CLI with
python -I(isolated mode) is recommended, and is how Compiler Explorer invokes it.The first
@tilelang.jitfunction orPrimFuncin module order is selected. Objects are inspected in definition order, so aPrimFuncdefined before a@tilelang.jitkernel wins.The kernel is lowered but never device-compiled or executed, so no tensor arguments are needed and no GPU is touched.
CLI Reference¶
python -I -m tilelang.tools.compile_only [--target TARGET] --output_file OUTPUT input_file
Argument |
Meaning |
|---|---|
|
Compile-only example file. Imported, never launched. |
|
Required destination for the generated kernel source. Must not name the input file (symlinks to it are also rejected). |
|
Explicit target. Defaults to |
On success the CLI exits with 0 and writes the source to --output_file. On
any failure it exits with 1, prints a single
tilelang compile-only error: ... line to stderr, and leaves no stale output
behind: a previous artifact at --output_file is removed before compilation,
so a failed rerun cannot leave an earlier run’s source for a consumer such as
Compiler Explorer to read.
Targets¶
Targets must be explicit. auto performs device detection and is therefore
rejected, as a plain string and in JSON form:
$ python -I -m tilelang.tools.compile_only --target auto --output_file out.c example.py
tilelang compile-only error: target must be explicit; do not use auto
|
Behavior |
|---|---|
|
CPU C source. Works on every wheel, no GPU needed. |
|
CUDA source pinned to |
|
CUDA source for the given architecture. Options must look like |
|
JSON target. A bare |
|
Rejected: |
On wheels without the CUDA codegen FFI (for example macOS Metal wheels), every
CUDA target form fails softly with
tilelang compile-only error: CUDA codegen FFI missing (e.g. macOS Metal wheel); use default --target c.
Error Reporting¶
Compile problems are reported as diagnostics on stderr with exit code 1, not
as tracebacks about missing GPUs or drivers:
$ python -I -m tilelang.tools.compile_only --output_file out.c broken.py
tilelang compile-only error: no @tilelang.jit kernel or PrimFunc found
Syntax errors in the input, missing input files, and empty kernels are reported the same way.
Line Directives¶
When the installed build registers the tl.emit_line_directives pass config
(PassConfigKey.TL_EMIT_LINE_DIRECTIVES), the tool enables it automatically
and the generated source carries #line <n> "<input_file>" directives that map
each statement back to the originating line of the example. Compiler Explorer
uses these to link generated source to the input pane. Older wheels without
the config key simply produce source without #line directives; no flag is
needed either way.
Programmatic API¶
The same functionality is available in Python:
from tilelang.tools.compile_only import compile_kernel_source
source = compile_kernel_source(add.get_tir()) # default target "c"
cuda_source = compile_kernel_source(add.get_tir(), "cuda") # pinned to sm_80
compile_kernel_source(func, target="c")lowers aPrimFunc(for example fromJITImpl.get_tir()) and returns the non-empty kernel source string.resolve_target(target)maps a CLI-style target string to the explicit target passed tolower(), applying the rules from the table above.cuda_codegen_available()reports whether the installed wheel can lower CUDA targets.
Limitations¶
Only the first
@tilelang.jitkernel orPrimFuncin the module is compiled; additional kernels in the same file are ignored.The output is lowered kernel source, not a compiled binary: nothing is passed to
nvcc, and PTX/SASS is out of scope.The input file is executed with the invoking Python interpreter. Treat it like any script you run:
python -Iisolates it from your environment but does not sandbox it.