What Actually Happens When You Run JAX Code?

Without jax.jit, JAX dispatches each operation to the device one at a time, as Python reaches it. With jax.jit, JAX traces your function into a jaxpr, lowers it to StableHLO, and hands the whole program to the XLA compiler, which fuses operations and compiles them for the target device. On CPUs and NVIDIA GPUs XLA generates code through LLVM (PTX for NVIDIA), uses Triton for some GPU kernels and NVIDIA libraries such as cuBLAS for others. Either way, JAX runs the result on the device through the PJRT runtime.
Mode
Device

Showing jax.jit on an NVIDIA GPU: 12 stages, 13 steps.

Your JAX code calls JAX JAX dispatches each op through PJRT runtime JAX traces to jaxpr jaxpr lowers to StableHLO StableHLO compiled by XLA compiler XLA compiler emits LLVM IR XLA compiler emits, for some kernels Triton IR XLA compiler calls, for common ops cuBLAS and cuDNN XLA compiler compiles with XLA TPU backend LLVM IR compiled to native code Compiled executable LLVM IR lowers to PTX Triton IR lowers to PTX PTX built into Compiled executable cuBLAS and cuDNN called from Compiled executable XLA TPU backend produces Compiled executable Compiled executable run through PJRT runtime PJRT runtime runs on CPU PJRT runtime launches on NVIDIA GPU PJRT runtime launches on TPU Your JAX code programming language JAX framework component jaxpr intermediate representation StableHLO intermediate representation XLA compiler compiler LLVM IR intermediate representation Triton IR intermediate representation cuBLAS and cuDNN kernel PTX intermediate representation XLA TPU backend compiler Compiled executable machine code PJRT runtime runtime CPU hardware NVIDIA GPU hardware TPU hardware

The selected path, step by step

  1. Your JAX code calls JAX: Your functions call JAX's array operations.
  2. JAX traces to jaxpr: jax.jit runs the function once with tracers and records it as a jaxpr, specialized to the argument shapes and dtypes.
  3. jaxpr lowers to StableHLO: The jaxpr is lowered to StableHLO, the XLA compiler's input language.
  4. StableHLO compiled by XLA compiler: XLA compiles the whole StableHLO program, fusing operations and specializing it for the device.
  5. XLA compiler emits LLVM IR: XLA's CPU and GPU backends emit LLVM IR for the computation.
  6. XLA compiler emits, for some kernels Triton IR: XLA:GPU generates some kernels through Triton IR emitters.
  7. XLA compiler calls, for common ops cuBLAS and cuDNN: For each operation XLA chooses between generating code and calling a library; many common operations go to cuBLAS or cuDNN.
  8. LLVM IR lowers to PTX: On NVIDIA GPUs, LLVM's NVPTX backend turns the IR into PTX.
  9. Triton IR lowers to PTX: Triton-emitted kernels also end up as PTX.
  10. PTX built into Compiled executable: The generated kernels become part of the compiled executable.
  11. cuBLAS and cuDNN called from Compiled executable: Library calls are linked into the runtime and invoked by the executable.
  12. Compiled executable run through PJRT runtime: JAX runs the compiled executable on the device through the PJRT runtime API.
  13. PJRT runtime launches on NVIDIA GPU: PJRT's GPU implementation launches the work on the NVIDIA GPU.

Where Python ends

Without jit, Python stays in charge of every operation: each jnp call is dispatched to the device on its own, so the compiler never sees more than one operation at a time.

With jax.jit, Python runs once to trace the function. From then on the computation is a jaxpr, then a StableHLO program, then an executable that XLA built for the device, and later calls with the same shapes reuse the compiled executable without running the Python body again.

How this differs from PyTorch

Both JAX and PyTorch's torch.compile capture a whole computation and compile it, and both can end up in Triton and LLVM on NVIDIA GPUs. JAX hands its program to XLA through a stable intermediate language, StableHLO, and runs it through PJRT; torch.compile captures an FX graph and generates kernels with TorchInductor. See what happens when you run a PyTorch model.

Every stage

Your JAX code

programming language

Python functions using jax.numpy and other JAX APIs.

In the atlas: Python

JAX

framework component

The JAX library. It traces and transforms your functions, and calls out to XLA and PJRT to compile for and run on devices.

  • To manage hardware devices and memory, and for compilation to such devices, JAX calls out to the open XLA compiler and the PJRT runtime.
    About the project (JAX documentation) Project docs

jaxpr

intermediate representation

JAX's own intermediate language: the traced function as a list of primitive operations, specialized to the argument shapes and dtypes.

StableHLO

intermediate representation

XLA's versioned input language, a portability layer between ML frameworks and compilers. It is an operation set, not a programming language.

XLA compiler

compiler

OpenXLA's machine-learning compiler. It optimizes the whole program, fusing operations, and generates code for the target device.

  • The XLA compiler takes model graphs from ML frameworks defined in StableHLO and compiles them into machine instructions for various architectures.
    XLA architecture (OpenXLA) Project docs
  • It traces the function to a jaxpr (How transformations work: tracing) and hands the whole jaxpr to XLA, which compiles it into a single optimized executable, fusing operations, eliminating temporary arrays, and specializing for your CPU, GPU, or TPU.
    Just-in-time compilation (JAX documentation) Project docs

LLVM IR

intermediate representation

XLA's CPU and GPU backends emit LLVM IR and use LLVM to generate native code.

In the atlas: LLVM

  • The CPU and GPU backends included with XLA use LLVM for low-level IR, optimization, and code generation.
    XLA architecture (OpenXLA) Project docs
  • These backends emit the LLVM IR necessary to represent the HLO computation in an efficient manner, and then invoke LLVM to emit native code from this LLVM IR.
    XLA architecture (OpenXLA) Project docs

Triton IR

intermediate representation

For some GPU kernels, XLA:GPU emits Triton IR instead of going straight to LLVM.

In the atlas: Triton

cuBLAS and cuDNN

kernel

NVIDIA's libraries, which XLA:GPU calls for many common operations instead of generating code.

In the atlas: CUDA

PTX

intermediate representation

NVIDIA's virtual instruction set, produced through LLVM's NVPTX backend.

In the atlas: CUDA

XLA TPU backend

compiler

XLA compiles for TPUs too. How its TPU backend generates code is not covered by the open documentation cited here.

Compiled executable

machine code

The optimized program for one device and one set of argument shapes. Later calls with the same shapes reuse it.

PJRT runtime

runtime

OpenXLA's uniform device API. Frameworks call PJRT; each device type implements it as a plug-in.

CPU

hardware

XLA's CPU backend supports several CPU instruction sets.

NVIDIA GPU

hardware

XLA reaches NVIDIA GPUs through LLVM's NVPTX backend and NVIDIA libraries.

Every step

FromStepToWhenWhat happensSource
Your JAX codecallsJAXany mode · any deviceYour functions call JAX's array operations.Project docs
JAXdispatches each op throughPJRT runtimeWithout jit · any deviceWithout jit, each operation is dispatched to the device on its own, as Python reaches it.Project docs
Project docs
JAXtraces tojaxprjax.jit · any devicejax.jit runs the function once with tracers and records it as a jaxpr, specialized to the argument shapes and dtypes.Project docs
Project docs
jaxprlowers toStableHLOjax.jit · any deviceThe jaxpr is lowered to StableHLO, the XLA compiler's input language.Project docs
StableHLOcompiled byXLA compilerjax.jit · any deviceXLA compiles the whole StableHLO program, fusing operations and specializing it for the device.Project docs
Project docs
XLA compileremitsLLVM IRjax.jit · CPU or NVIDIA GPUXLA's CPU and GPU backends emit LLVM IR for the computation.Project docs
XLA compileremits, for some kernelsTriton IRjax.jit · NVIDIA GPUXLA:GPU generates some kernels through Triton IR emitters.Project docs
XLA compilercalls, for common opscuBLAS and cuDNNjax.jit · NVIDIA GPUFor each operation XLA chooses between generating code and calling a library; many common operations go to cuBLAS or cuDNN.Project docs
Project docs
XLA compilercompiles withXLA TPU backendjax.jit · TPUFor TPUs, XLA's TPU backend produces the executable; its internals are not covered here.Project docs
LLVM IRcompiled to native codeCompiled executablejax.jit · CPUOn CPU, LLVM turns the IR into native machine code.Project docs
Project docs
LLVM IRlowers toPTXjax.jit · NVIDIA GPUOn NVIDIA GPUs, LLVM's NVPTX backend turns the IR into PTX.Project docs
Project docs
Triton IRlowers toPTXjax.jit · NVIDIA GPUTriton-emitted kernels also end up as PTX.Project docs
PTXbuilt intoCompiled executablejax.jit · NVIDIA GPUThe generated kernels become part of the compiled executable.Project docs
cuBLAS and cuDNNcalled fromCompiled executablejax.jit · NVIDIA GPULibrary calls are linked into the runtime and invoked by the executable.Project docs
XLA TPU backendproducesCompiled executablejax.jit · TPUThe TPU backend produces the executable for the TPU.Project docs
Compiled executablerun throughPJRT runtimejax.jit · any deviceJAX runs the compiled executable on the device through the PJRT runtime API.Project docs
Project docs
PJRT runtimeruns onCPUany mode · CPUPJRT's CPU implementation runs the work on the host CPU.Project docs
PJRT runtimelaunches onNVIDIA GPUany mode · NVIDIA GPUPJRT's GPU implementation launches the work on the NVIDIA GPU.Project docs
Project docs
PJRT runtimelaunches onTPUany mode · TPUPJRT's TPU implementation runs the work on the TPU.Project docs
Project docs

What this does not show

Documented paths for one JAX program run without jit and with jax.jit, on a CPU, an NVIDIA GPU, or a TPU. Multi-device sharding, Pallas kernels, AMD GPUs, PJRT plugins for other hardware, and the internals of XLA's TPU backend are out of scope. XLA's TPU backend is not described in the open-source documentation cited here, so this page shows that XLA compiles for TPUs without showing how.

How this page is checked

Every stage and step above quotes the source that supports it. The quotes were checked against the JAX documentation (About, Just-in-time compilation, Ahead-of-time lowering) and the OpenXLA documentation (XLA architecture, XLA:GPU architecture, PJRT) on 2026-11-11. The data is a versioned JSON file under the same CC BY 4.0 license as the dataset. Found something wrong or out of date? Open an issue with the better source.

What these tools are written in is in the main atlas: Python, LLVM, Triton, CUDA. More execution paths: How Does llama.cpp Run a Model on Your Hardware, What Actually Happens When You Run a PyTorch Model.

Explore the full graph →