Triton · Pyodide · Emscripten

Build the compiler.

A compilation-only WebAssembly recipe for Triton, NVIDIA PTX, AMDGCN, and Gluon gfx950. The browser receives Python plus one side module; it never receives LLVM archives or a GPU runtime.

O4 + full LTO shipped
Current shipped profile
Full LTO · Release O3 · wasm-opt O4

The deployed side module is 96,531,399 bytes after Full LTO, section garbage collection, andwasm-opt -O4. It passes the NVIDIA PTX, AMD gfx942, Gluon GFX950, and supplied v9 compilation-only checks. The older 92,972,220-byte O3 module is kept as the benchmark baseline; this profile favors compiler speed and backend coverage.

compile-only

What the build proves

Textual GPU output only; no driver or device is needed.

PathTargetOutputBoundary
Triton / NVIDIAcuda:80:32PTX textNo cubin or ptxas
Triton / AMDhip:gfx942:64AMDGCN textNo HSACO or ROCm
Gluon / AMDhip:gfx950:64AMDGCN textNo GPU launch
Supplied v9 kernelhip:gfx950:64LLIR + AMDGPU asmCompile-only
Stage 01

Pin the sources

Use a Triton checkout and an LLVM checkout that are known to agree. The POC keeps both trees outside the website and writes all build products into a side folder.

export REPO_ROOT=/path/to/my-website
export POC_ROOT="$REPO_ROOT/triton-wasm-poc/.artifacts"
export TRITON_ROOT=/path/to/triton
export LLVM_ROOT=/path/to/llvm-project
export PYODIDE_ROOT=/path/to/pyodide
export EMSDK_ROOT=/path/to/emsdk
export PYODIDE_JOBS=4
export CMAKE_BUILD_PARALLEL_LEVEL=4
export MAKEFLAGS=-j4
Stage 02

Build the LLVM host library

Only MLIR plus the WebAssembly, NVPTX, and AMDGPU targets are retained. The static archives are link-time inputs and are not shipped to the browser.

nice -n 10 emcmake cmake -S "$LLVM_ROOT/llvm" \
  -B "$POC_ROOT/llvm-build-full-lto" -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DLLVM_ENABLE_PROJECTS='mlir;lld' \
  -DLLVM_TARGETS_TO_BUILD='WebAssembly;NVPTX;AMDGPU' \
  -DLLVM_ENABLE_LTO=Full \
  -DCMAKE_C_FLAGS_RELEASE='-O3 -DNDEBUG -ffunction-sections -fdata-sections -flto -mexception-handling' \
  -DCMAKE_CXX_FLAGS_RELEASE='-O3 -DNDEBUG -ffunction-sections -fdata-sections -flto -mexception-handling' \
  -DCMAKE_EXE_LINKER_FLAGS='-flto' \
  -DCMAKE_SHARED_LINKER_FLAGS='-flto' \
  -DLLVM_BUILD_TOOLS=OFF -DLLVM_BUILD_UTILS=OFF \
  -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF \
  -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_DOCS=OFF \
  -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_ENABLE_THREADS=OFF \
  -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF \
  -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_LIBXML2=OFF \
  -DLLVM_ENABLE_CURL=OFF -DMLIR_INCLUDE_TESTS=OFF \
  -DMLIR_ENABLE_BINDINGS_PYTHON=OFF
nice -n 10 cmake --build "$POC_ROOT/llvm-build-full-lto" --parallel 4
nice -n 10 cmake --install "$POC_ROOT/llvm-build-full-lto"
Stage 03

Build the Pyodide package

Pyodide treats LLVM as a host-only static-library dependency. Triton owns the runtime Python files and one Emscripten side module; CUDA, ROCm, ptxas, HSACO, and a GPU are intentionally absent.

nice -n 10 pyodide build-recipes \
  --recipe-dir "$POC_ROOT/pyodide-recipe" \
  --build-dir "$POC_ROOT/recipe-build" \
  --install-dir "$POC_ROOT/recipe-dist" \
  --n-jobs 1 --skip-emscripten-install \
  triton-wasm-poc
Stage 04

Relink, optimize, and test

Relink the side module with Full LTO, run Binaryen at the requested O4 level, package the Python tree, and run every compilation-only target test before staging it.

nice -n 10 em++ ... -fwasm-exceptions -sSIDE_MODULE=1 \
  -flto -O3 -Wl,--gc-sections -shared -o libtriton.so ...
wasm-opt -O4 --strip-debug --strip-producers \
  --enable-bulk-memory --enable-exception-handling \
  --enable-reference-types --enable-nontrapping-float-to-int \
  --enable-simd --enable-mutable-globals \
  libtriton.so -o libtriton.opt.wasm
node "$POC_ROOT/test-pyodide-optimized.mjs" \
  "$POC_ROOT/triton-wasm-poc-package.zip" \
  "$POC_ROOT/optimized-results"

Important wiring

These are the details that make the browser package different from native Triton.

Pyodide dependencies

Declaretriton-llvminrequirements.hostand keeprequirements.runempty. LLVM/MLIR archives are consumed while linking the side module. AMDocml.bc,ockl.bc, andasanrtl.bcremain package data because they are compiler inputs.

GFX950 contract

The supplied Gluon kernel useship:gfx950:64, four warps,amdgpu-agpr-alloc=256, 16-byte pointer alignment, and K-contiguous B strides:stride_bk=1,stride_bn=K.

Inspect the output

The harness writes TTGIR, LLIR, and AMDGPU assembly. The final assembly isgfx950-v9-beyond-hotloop.amdgcn; it is not HSACO and is not launchable by this package.