PR Digest Iteration 66 - intel/intel-xpu-backend-for-triton GitHub Wiki
PR Summary
Period: 2026-09-13 to 2026-09-26 (Iteration 66) | Total PRs: 65 (Xe2/Xe3/Xe3P) | Lines changed: +28,855 / -7,302
Triton XPU BE (Xe2/Xe3/Xe3P) (65 PRs, +28,855 / -7,302)
The compiler got noticeably smarter about register usage: several passes now measure real register pressure before moving work around, which prevents slowdowns from spilling on large matrix and attention kernels. A cluster of fixes closed out-of-bounds memory reads and restored stable support for the Long Term Support driver, and the 3.9.0 release branch received the key fixes. Seven upstream synchronizations were completed with a 98.88–99.22% test pass rate.
Key accomplishments:
- Made register-saving optimizations decide from measured register pressure instead of guesswork, and fixed a units bug that had effectively disabled one of those checks
- Added a new optimization that removes redundant memory reads commonly produced by PyTorch's compiler
- Fixed several bugs that could read memory out of bounds, produce invalid hardware instructions, or crash the compiler or the Python process
- Restored stable Long Term Support driver builds, including recovering a 21% slowdown on one PyTorch benchmark
- Improved vLLM attention performance (about 10% on average, up to 3x on some shapes) and re-enabled SGLang end-to-end testing
Compiler Optimization & Register Pressure
Register-pressure-aware scheduling and layout decisions, plus a new pass that removes redundant memory reads in PyTorch-generated kernels.
- #8098 Shrink the forked ReduceOp lowering and reject num_ctas > 1 — Shrinks the 884-line Intel ReduceOp fork by moving its fold order to the getReductionTreeArity hook, deleting a never-built code path and rejecting num_ctas > 1. (+206/-185, @etiotto)
- #8139 Sink in-loop 2D dot operand loads to their first use — Extends ReduceVariableLiveness to sink 2D dot operand loads already inside a loop body down to their first use, shortening live ranges that dominate peak pressure (closes #8137). (+330/-12, @oelayan7)
- #8068 Add a whole-function peak gate to HoistLayoutConversions — Adds a function-wide peak-pressure check so a layout-conversion hoist that one loop can afford is rejected if it would raise the function's overall peak (gap (b) of #7993). (+2069/-203, @etiotto)
- #8119 Keep masked block_io loads anchored unless they feed a dot (#8112) — Backport of #8112 to release/3.9.0. (+157/-1, @whitneywhtsang)
- #8112 Keep masked block_io loads anchored unless they feed a dot — Keeps masked 2D-block loads as layout anchors in RemoveLayoutConversions unless they feed a dot, avoiding costly rematerialization into non-DPAS layouts. (+157/-1, @whitneywhtsang)
- #7963 Gate sinking on measured register pressure — Gates ReduceVariableLiveness sinking on the loop body's measured register pressure against the per-lane GRF budget, deciding per loop (fixes #7934). (+544/-115, @oelayan7)
- #8056 Add
OptimizeLoadMaskspass (#7997) — Backport of #7997 to release/3.9.0. (+1397/-0, @whitneywhtsang) - #7997 Add
OptimizeLoadMaskspass — New pass that removes redundant or unneeded memory reads in Inductor kernels that check the same bounds with both a load mask and a later select. (+1396/-0, @whitneywhtsang) - #7933 Fix GRF budget unit mismatch and additive-only cost accounting in HoistLayoutConversions — Fixes a ~16x unit mismatch in the HoistLayoutConversions pressure gate and makes its cost accounting account for freed registers (fixes #7929, gap (a) of #7993). (+704/-78, @oelayan7)
Correctness & Memory Access
Fixes for out-of-bounds reads, invalid hardware block messages, missing atomic support, a compiler divide-by-zero, and kernel launch failures that aborted the process, plus earlier resource-limit checks.
- #8069 Fix out-of-bounds loads from fusing a reshape into a descriptor load — Makes the bounds declared by FuseReshape match the rank-3 load, including dynamic collapsed indices and runtime-empty dimensions, so fused loads no longer read outside the tensor. (+2224/-66, @etiotto)
- #8173 Raise instead of aborting when a kernel launch is rejected — Catches SYCL exceptions from kernel submit and raises
IntelGPUError, instead of aborting the Python process and every pytest-xdist test queued on the worker. (+22/-3, @whitneywhtsang) - #8156 Take an int64_t divisor in
ttgi::isDivisibleand reject non-positive ones — Stops a zero divisor from raising SIGFPE and i64 divisors from being narrowed tounsignedand proving false divisibility; addresses parts of #8073. (+129/-17, @Niz13) - #8128 Emulate sub-word atomic load and store — Emulates 8- and 16-bit atomic load/store on top of 32-bit word atomics (load + extract, CAS-loop store), since most Intel targets lack native sub-word atomics (fixes #8027). (+221/-29, @wdziurdz)
- #8100 Wrap descriptor candidates in DescriptorDefinitions — Wraps every tensor-descriptor definition reachable from a value in a DescriptorDefinitions class, so callers can no longer silently assume the first candidate (closes #6873). (+511/-91, @etiotto)
- #8124 Check the shared memory limit before lowering to LLVM (#8120) — Backport of #8120 to release/3.9.0. (+30/-12, @whitneywhtsang)
- #8120 Check the shared memory limit before lowering to LLVM — Moves the shared-memory limit check ahead of LLVM lowering so autotuners and Inductor's static launcher can drop oversized configs without paying for a full compile. (+30/-12, @whitneywhtsang)
- #7998 Stop emitting an unrepresentable 2D block message — Stops MaterializeBlockPointer from tagging loads whose loop-carried offset breaks 2D block alignment, which produced an unrepresentable 2D block message. (+357/-2, @aditzhaki)
- #8023 Bounds-check batch dimensions of rank>2 descriptor block loads — Bounds-checks batch dimensions of rank>2 descriptor block loads so out-of-range batch indices return padding instead of reading out of bounds (fixes #7922). (+392/-32, @januszjah)
- #8025 Enable AnnotateCacheControl by default on Windows too — Enables the AnnotateCacheControl pass on Windows by default, since the workaround it was disabled for has been removed; adds a regression test. (+22/-3, @januszjah)
LTS Driver Support
Brings the Long Term Support driver back in line with the rolling driver: extension gating, spill-rebuild policy, and LTS-specific workarounds.
- #8198 Keep umulhi on the mul_hi builtin for the LTS driver — Restores the libdevice mul_hi lowering for
tl.umulhion LTS only, since the LTS IGC compiled upstream's i128 multiply to zeros after #8144. (+28/-0, @wdziurdz) - #8141 Key the bfloat16 translator workaround on the allowed extension set — Drives the LTS bfloat16 translator fallback off the allowed SPIR-V extension set rather than an environment variable set on every compile. (+6/-15, @whitneywhtsang)
- #8140 Do not allow SPIR-V extensions unknown to the LTS driver's IGC — Stops allowing 12 SPIR-V extensions that the LTS driver's IGC does not recognize. (+24/-15, @whitneywhtsang)
- #8149 Skip the LTS bf16<->f16 and fp16 scaled_dot failures — Skip-lists LTS-only bf16<->f16 conversion and fp16 scaled_dot failures that appeared after the #8088 upstream merge. (+19/-0, @whitneywhtsang)
- #8118 Rebuild on any spill on the LTS driver (#8115) — Backport of #8115 to release/3.9.0. (+59/-9, @whitneywhtsang)
- #8115 Rebuild on any spill on the LTS driver — Restores rebuilding at 256 GRF on any spill for the LTS driver, recovering a 21% loss on pyhpc_isoneutral_mixing; rolling keeps the threshold (fixes #8106). (+59/-9, @etiotto)
- #8086 Use the integer-domain fp8e4m3 -> fp16 sequence on LTS (#8066) — Backport of #8066 to release/3.9.0. (+155/-0, @anmyachev)
- #8066 Use the integer-domain fp8e4m3 -> fp16 sequence on LTS — Selects an integer-domain fp8e4m3 -> fp16 conversion sequence on LTS to avoid an LTS IGC compile-time regression (fixes #8046). (+155/-0, @whitneywhtsang)
- #7884 Update PyTorch pin; restrict
TORCH_XPU_ARCH_LISTtopvcwhen using LTS driver. — Updates the PyTorch pin and restricts TORCH_XPU_ARCH_LIST to pvc for LTS driver builds. (+34/-5, @anmyachev) - #8035 Disable sub-group reinterpret cast on LTS drivers — Disables the sub-group reinterpret-cast lowering on LTS, where the GenISA intrinsic it emits is not implemented. (+18/-10, @whitneywhtsang)
Upstream Alignment
Seven synchronizations with OpenAI Triton, plus cleanups that move Intel-only code out of shared files to cut merge friction.
7 upstream merges from OpenAI Triton (commits 3a07c15, 8a51a34, 10d342c, c7342ca, 30dd06e, dd34455, 2ff84c3) — pass rate 98.88–99.22%.
- #8127 Move Intel test passes into
third_party/intel/test/lib/Analysis— Moves five Intel-only analysis test passes into an Intel test library, matching the layout upstream already uses for AMD. (+27/-6, @mieshkiwrk) - #8096 Reduce core divergence in
triton-opt, two lit tests andAsmDict— Reduces divergence from upstream in triton-opt dialect registration, two lit tests and AsmDict (closes #8095, part of #2030). (+7/-7, @mieshkiwrk) - #8061 Move the pass-manager timing binding to the Intel backend — Moves the pass-manager timing binding into the Intel backend, making python/src/ir.cc identical to upstream. (+39/-39, @mieshkiwrk)
- #7991 Move the Intel reduce scratch helpers to the Intel backend — Moves four Intel-only ReduceOpHelper members into the Intel backend as free functions. (+79/-54, @mieshkiwrk)
- #8037 Cleanup undefined extras components in pip install command — Removes pip install extras that upstream no longer defines. (+6/-6, @anmyachev)
Workloads, Build, Test & CI
vLLM and SGLang enablement and tuning, benchmark infrastructure, the 3.9.0 version bump, and CI reliability.
- #8134 Update pin — Bumps the vLLM pin with no vLLM benchmark impact on B580 CI; closes #8084. (+136/-109, @quinnlp)
- #8007 Add an e2e suite covering the two forward-path kernels — Adds a
--sglang-e2esuite running upstream's XPU basic test, the only one that reaches the SGLang position and request-to-token-pool kernels. (+108/-10, @wdziurdz) - #8182 Switch CodeQL jobs to cpu/runner-0.0.22 runner label — Moves the CodeQL analyze and report jobs to the CPU runner label used elsewhere in CI. (+6/-2, @kwasd)
- #8006 Enable the dense attention unittests on XPU — Routes the SGLang dense attention tests' device gate, RNG seeding and capture stream through the device module, taking the suite from 8 to 18 passing; closes #8010. (+203/-4, @wdziurdz)
- #8116 Remove skips for fixed Dynamo stream registration — Removes vLLM MRv2 skips after the upstream vLLM fix for Dynamo stream registration; closes #7160. (+12/-36, @sarah12121212)
- #8130 Install sgl-kernel-xpu in the BMG jobs — Builds and installs sgl-kernel-xpu at a pinned commit in the BMG SGLang jobs so the e2e suite can load models again. (+390/-10, @wdziurdz)
- #7883 Use tensor descriptors in the fla kernels on the GDN path — Converts the fla kernels on the SGLang GDN path from block pointers to tensor descriptors, re-enabling 29 skipped tests. (+656/-62, @wdziurdz)
- #8097 Clean-up unified attention benchmark patch and re-add dead batch invariance clause — Tidies the vLLM unified attention benchmark patch and restores the batch-invariance clause. (+15/-19, @quinnlp)
- #8110 Add
SLIDING_WINDOWas an autotuning key for unified attention — Adds SLIDING_WINDOW as an autotune key for vLLM unified attention, giving a 1.096x geomean speedup (up to 2.99x) on bf16 triton-td (closes #8113). (+20/-19, @quinnlp) - #8108 Update Triton version: 3.8.0 -> 3.9.0 (#8107) — Backport of #8107 to release/3.9.0. (+9/-9, @anmyachev)
- #8107 Update Triton version: 3.8.0 -> 3.9.0 — Bumps the Triton version from 3.8.0 to 3.9.0. (+9/-9, @anmyachev)
- #8024 Install vLLM XPU kernels from the release vLLM pins — Installs vLLM XPU kernels from the release vLLM pins, dropping the nightly-wheel search and pin-file workflow. (+91/-269, @whitneywhtsang)
- #8041 Include the PyTorch-injection flag in the spirv_utils cache key — Adds the PyTorch-injection flag to the spirv_utils cache key so profiler-based benchmarks do not reuse an incompatible build. (+7/-0, @whitneywhtsang)
- #8080 Don't trust
ONEAPI_ROOTwithout a SYCL install under it (#8054) — Backport of #8054 to release/3.9.0. (+80/-6, @anmyachev) - #8020 Use B60 BMG runners for vLLM tests — Moves vLLM functional tests from B580 to B60 BMG runners to relieve the B580 performance fleet. (+7/-308, @quinnlp)
- #8054 Don't trust
ONEAPI_ROOTwithout a SYCL install under it — Validates that ONEAPI_ROOT actually contains a SYCL install before using it, falling back to the intel-sycl-rt wheel (fixes #7977). (+80/-6, @pk1d3v) - #7936 Disable pyenv-built Python by default in CI workflows — Defaults CI workflows to the system Python instead of a pyenv-built one to reduce CI time. (+11/-11, @kwasd)
- #7780 Enable intel triton_kernels_benchmark tests to run on NV… — Lets the Intel triton_kernels_benchmark scripts run on NVIDIA GPUs to measure cross-vendor performance gaps (closes #7837). (+224/-136, @dudilester)
- #8050 Remove stale debug scaffold from test_state — Removes a stale debug try/except from the Proton test_state test. (+10/-15, @oelayan7)
- #7476 Blockm autotune prune logic fix — Limits the vLLM unified attention BLOCK_Q power-of-2 pruning to the USE_TD_QO path, widening the autotune space elsewhere (closes #7465). (+32/-1017, @sarah12121212)
- #8034 Stop running SGLang benchmarks on max1550 automatically — Makes SGLang benchmarks on scarce max1550 runners opt-in, matching #8031 for vLLM; BMG still covers PR and nightly runs on b580. (+1/-49, @wdziurdz)
- #8039 Skip flex attention test that wedges the GPU on IGC 2.40.x — Skips a flex attention test whose kernel never retires on IGC 2.40.x and hangs the job. (+17/-0, @whitneywhtsang)
- #7974 Unskip tests relying on gated HF models (#7347) — Unskips vLLM spec_decode tests that use gated HF models and now pass in CI (closes #7347). (+5/-28, @dudilester)
- #8032 Fix KDA test collection: drop non-argument
NCfrom autotune key — Fixes vLLM KDA test collection by dropping the grid variable NC from an autotune key, which upstream Triton now rejects. (+36/-10, @quinnlp)