Skip to content

LLVM and SPIRV-LLVM-Translator pulldown (WW29 2026)#22660

Draft
iclsrc wants to merge 2646 commits into
syclfrom
llvmspirv_pulldown
Draft

LLVM and SPIRV-LLVM-Translator pulldown (WW29 2026)#22660
iclsrc wants to merge 2646 commits into
syclfrom
llvmspirv_pulldown

Conversation

@iclsrc

@iclsrc iclsrc commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

arsenm and others added 30 commits July 11, 2026 11:23
Mechanically migrate the command-line target spelling on llc/opt RUN
lines in llvm/test/CodeGen/AMDGPU from -mtriple=amdgcn ... -mcpu=<gfx> to the
folded subarch triple form (e.g. -mtriple=amdgpu9.00-amd-amdhsa), dropping the
redundant -mcpu.

Co-Authored-By: Claude <noreply@anthropic.com> (Claude-Opus-4.8)
StackColoring tracks the total size of the stack as `unsigned int`. This
will wrap around, even on 64-bit systems, if the stack is greater than
that resulting in a wrong size. This can happen on both PPC and RISCV64.
This alters the lowering of bf16 G_TRUNC to exclude the check for nan if
the operation being extended is nnan. Flags are then threaded through so
that the G_FPEXT and G_FPTRUNC from promoted nodes keep the same FMF.
This alters the extension of f16 vecreduce to bf16, allowing us to
handle the non-strict fadd and fmul reductions, along with fmin and fmax
variants.
BlockInCriticalSectionChecker registers the pre-call for the RAII ctors
and Dtors - and also the raw 'lock' and 'unlock' handlers.

However, pre-call does not prevent inlining. This means that (in the
likely case of) that the body is present, the analyzer will model the
effect of the lock twice. This happens on libc++ unique_lock.

We really should have eval-called the ctor/dtor to avoid the inlining of
those, but here we are.

rdar://175814310
The static analyzer's HTML reports contain misnested tags whenever a
variable with a `variable_popup` is the last token on a source line.
`AddLineNumber` inserts the row-closing `</td></tr>` with `InsertTextBefore`, which
places it in front of text previously inserted at the same offset. As a result,
the popup's closing `</table></span>` tags and the arrow anchor `</span>`
tags end up outside the table row. HTML parsers (jsoup, pup) and validators
reject the file from that point on.

Before:

<span class='variable'>b</td></tr><table
class='variable_popup'>...</table></span></span></span>

<img width="786" height="414" alt="image"
src="https://github.com/user-attachments/assets/023461ad-73e4-424e-a4fb-42faf7a945f0"
/>

After:

<span class='variable'>b<table
class='variable_popup'>...</table></span></span></span></td></tr>

<img width="877" height="477" alt="image"
src="https://github.com/user-attachments/assets/cf8aada4-21c8-4af7-9e07-c2d8cc1d0724"
/>

The fix inserts `</td></tr>` with `InsertTextAfter` so tags closing at
the end-of-line offset stay inside the row. To keep the message bubbles
outside the code rows, the line number table is now added before the path pieces
are processed, and bubbles are inserted after the newline, between the
current and the next row.

The pre-existing tests only exercised popups on variables followed by
more tokens (`if (b)`), which is why this was never caught; the new test
places the variable at the end of the line. This has been broken since at least
clang 10; the earlier fix (D73993 / commit 482e236)
only covered the macro popup variant.

I verified this with the Analysis/html_diagnostics tests, the full
clang/test/Analysis suite, and by running generated reports through an
HTML parser that checks tag nesting: 4 errors before / 0 after on the
reproducer above, and 8 → 0 on a larger file with macro popups, multiple
events per line, and mid-line popups. The visible report content is
unchanged.

Fixes #46089
…set for stack store/load instructions with preserve_all (#207026)

Fix AArch64 framelowering bug exposed by a preserve_all function that
spills 30+ callee-saved registers: paired stp/ldp offsets overflows the
signed 7-bit immediate, fixed by spilling those registers as single
str/ldr instead.

AI Usage Disclosure
AI was used to help the: 
- investigation process 
- suggestion of solution  
- suggestion of comment wordings

Fixes #204564
… a type smaller than the combined load (#207229)
…ns (#199911)

When insertColumns does not trigger a physical reallocation, the inner
loop needlessly loops up to nReservedColumns - 1. This causes massive
redundant zero-writes on trailing columns that are already zero. This
patch truncates the inner loop start boundary to nColumns - 1, when the
reserved capacity is unchanged, optimizing the non-realloc path from
O(nRows * nReservedColumns) to O(nRows * nColumns).
The second argument of `llvm.is_fpclass` is a mask, where each bit
represents a floating-point class. Understanding the check that the call
makes in an IR dump requires additional effort. To simplify the
interpretation of IR dumps, a previously implemented pretty-printing
mechanism can be used:
llvm/llvm-project@39e7712.
This commit implements this mechanism for printing the arguments of
`llvm.is_fpclass`.

This change also fixes the printing of argument names: if an argument
name is absent, it is simply not printed.
…on_ptr (#208883)

These were accidentally placed in LLVM 22 rather than 23 file.
Remove member functions with no remaining callers anywhere in the tree:

 - VPExpressionRecipe::getOperandOfResultType
- VPBlockBase::getSingleHierarchicalSuccessor
 - VPIRFlags::hasNonNegFlag
- VPWidenIntOrFpInductionRecipe::getStartValue, which is an exact
duplicate of the inherited VPWidenInductionRecipe::getStartValue.
…#203386)

VPRecipeBase::dump() constructs a fresh VPSlotTracker instance on each
call. VPSlotTracker construction requires iterating over all recipes in
the plan, to number all VPValues.

To avoid doing lots of unnecessary work when printing VPlan costs,
construct a shared VPSlotTracker in VPCostContext, re-used by all
prints.

This can speed up debug output for large loops.

PR: llvm/llvm-project#203386
Mechanically migrate the command-line target spelling on llc/opt RUN
lines in llvm/test/CodeGen/AMDGPU from -mtriple=amdgcn ... -mcpu=<gfx> to the
folded subarch triple form (e.g. -mtriple=amdgpu9.00-amd-amdhsa), dropping the
redundant -mcpu.

Co-Authored-By: Claude <noreply@anthropic.com> (Claude-Opus-4.8)
…956)

The ieExpr == R_GOT PIC case (e.g. R_386_TLS_IE in -shared links) calls
the unsynchronized addRelativeReloc from concurrent scanSectionImpl
tasks, racing on relaDyn->relativeRelocs. Use the sharded variant like
processAux. Split i386-tls-ie-shared.s into two input files so that a
ThreadSanitizer build detects the race.
…#208959)

Parallel relocation scanning (https://reviews.llvm.org/D133003) appends
dynamic relocations to `relocsVec[parallel::getThreadIndex()]`.
`getThreadIndex` returns -1u on main, which is a known hazard.

Instead, run one scan task per worker via `parallelFor`, with tasks
claiming object files off a shared counter, and pass the task index
through scanSection/RelocScan as the relocsVec shard.
…#208085)

This PR adds a default parallel implementation of `std::reverse_copy`
based on `std::reverse_iterator` + parallel `std::copy`.

Effectively it's a one-liner:
```c++
    return _Copy()(__policy,
                   std::reverse_iterator<_BidirectionalIterator>(std::move(__last)),
                   std::reverse_iterator<_BidirectionalIterator>(std::move(__first)),
                   std::move(__result));
```

Included tests check that:

- Semantics of the function is correct.
- The function correctly SFINAE out when the first argument is not an
execution policy.
- The `nodiscard` policy is followed.
- The `noexcept` policy is followed.
- `static_assert` verifies iterators' categories (bidirectional and
forward).

Part of #99938.

---------

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
Connect to every LLDB MCP server advertised under ~/.lldb rather than a
single one, and present them to the client as one server. A stale
registry entry from a crashed instance simply fails to connect and is
skipped.

Each instance is identified by the pid of its lldb process, now recorded
in the ServerInfo registry file. Tools and resources are addressed with
instance-qualified URIs, e.g. lldb-mcp://instance/{pid}/debugger/{id}
and lldb://instance/{pid}/debugger/{id}/target/{idx}. Listing requests
(sessions_list, resources/list) fan out to every backend and aggregate;
targeted requests (command, resources/read) are routed by the pid parsed
from the URI. Backends only know their local lldb-mcp://debugger/{id}
form, so URIs are rewritten in both directions.

Add Binder::FailPendingRequests (and Client::CancelPendingRequests) so
that when the client disconnects with a request still in flight to a
backend, the abandoned reply is satisfied with an error instead of being
destroyed unanswered, which would trip the binder's "must reply" assert.
The multiplexer cancels its backends on shutdown before unwinding.

Assisted-by: Claude
…208974)

The parallel mark loop appends deeper discoveries to per-thread queues
indexed by `parallel::getThreadIndex()`, the last getThreadIndex user in
lld. Instead, have each worker claim frontier items off a shared
counter, accumulating into an explicit shard.

The finer-grained item claiming improves load balancing: the markLive
--time-trace phase is ~5% faster for a clang --gc-sections link and ~4%
for a larger chromium one.
Add missing enum values related to CXXExpansionStmt
…indirection" (#208968)

There is a few breakages between `clang-armv8-quick` failing the
`Interpreter/execute-weak.cpp` test and bots failing linking
`libclang_rt.atomic.so`.

Reverts llvm/llvm-project#208372
…erns (#199371) (#208960)

Reverts llvm/llvm-project#199371.

The strided path emits wide loads without checking that the widened
range is dereferenceable. The last wide load reads up to (stride -
element) bytes past the last element and faults when the data ends at a
page boundary. Flagged by @nikic in
llvm/llvm-project#199371 (comment).

Reproducer on current main **MADE WITH CLAUDE OPUS**

strided.ll, 8 x i16 at a 4 byte stride, the source only touches bytes
[0, 30):
```llvm
define void @strided8i16(ptr %p, ptr %out) {
  %g0 = getelementptr inbounds i8, ptr %p, i64 0
  %g1 = getelementptr inbounds i8, ptr %p, i64 4
  %g2 = getelementptr inbounds i8, ptr %p, i64 8
  %g3 = getelementptr inbounds i8, ptr %p, i64 12
  %g4 = getelementptr inbounds i8, ptr %p, i64 16
  %g5 = getelementptr inbounds i8, ptr %p, i64 20
  %g6 = getelementptr inbounds i8, ptr %p, i64 24
  %g7 = getelementptr inbounds i8, ptr %p, i64 28
  %v0 = load i16, ptr %g0, align 1
  %v1 = load i16, ptr %g1, align 1
  %v2 = load i16, ptr %g2, align 1
  %v3 = load i16, ptr %g3, align 1
  %v4 = load i16, ptr %g4, align 1
  %v5 = load i16, ptr %g5, align 1
  %v6 = load i16, ptr %g6, align 1
  %v7 = load i16, ptr %g7, align 1
  %r0 = insertelement <8 x i16> undef, i16 %v0, i32 0
  %r1 = insertelement <8 x i16> %r0,   i16 %v1, i32 1
  %r2 = insertelement <8 x i16> %r1,   i16 %v2, i32 2
  %r3 = insertelement <8 x i16> %r2,   i16 %v3, i32 3
  %r4 = insertelement <8 x i16> %r3,   i16 %v4, i32 4
  %r5 = insertelement <8 x i16> %r4,   i16 %v5, i32 5
  %r6 = insertelement <8 x i16> %r5,   i16 %v6, i32 6
  %r7 = insertelement <8 x i16> %r6,   i16 %v7, i32 7
  store <8 x i16> %r7, ptr %out, align 1
  ret void
}
```

driver.c, puts the 30 data bytes flush against a PROT_NONE page:
```c
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
void strided8i16(void *p, void *out);
int main(void) {
  long pg = sysconf(_SC_PAGESIZE);
  char *m = mmap(0, 2*pg, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  mprotect(m + pg, pg, PROT_NONE);        /* unmapped guard page right after */
  memset(m, 0x11, pg);
  char *p = m + pg - 30;                  /* data [0,30) ends exactly at page end */
  uint16_t out[8];
  strided8i16(p, out);                    /* source touches only bytes [0,30) */
  printf("  returned OK, out[0]=%u\n", out[0]);
  return 0;
}
```

```
$ llc -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 -filetype=obj strided.ll -o strided.o
$ cc driver.c strided.o -o repro
$ ./repro; echo "exit: $?"
Segmentation fault (core dumped)
exit: 139

$ llc -mtriple=x86_64-unknown-linux-gnu -mattr=+sse2 -filetype=obj strided.ll -o strided_sse2.o
$ cc driver.c strided_sse2.o -o repro_sse2
$ ./repro_sse2; echo "exit: $?"
  returned OK, out[0]=4369
exit: 0
```

With +avx2 the fold fires and emits a 32 byte `vmovdqu (%rdi), %ymm0`
over the 30 byte footprint. With plain sse2 the buildvector stays scalar
and only the accessed bytes are read.
…#195649)

Address the following issues reported in #171475:

1. Proper adjustment of `__rela_iplt_end` address if a move from
`.relr.auth.dyn` to `.rela.dyn` took place

2. Set `__rela_iplt_start` properly if prior to such movement from
`.relr.auth.dyn`, the `.rela.dyn` was empty

3. Allocate enough space for both RELA* and AARCH64_AUTH_RELR* tags in
the `.dynamic` section in case we end up with both `.relr.auth.dyn` and
`.rela.dyn`. If one of the sections becomes empty - just pad the
`.dynamic` section with null tags in the end.

Resolves #171475

---------

Co-authored-by: Jessica Clarke <jrtc27@jrtc27.com>
We pass this when evaluting opcodes in EvalEmitter, but we never set it
to anything, so the underlying pointer is always null and we later and
up using the source location of the expression we're evaluating.

This seems to only cause problems when Statement expressions are
involved so far.
…s (#196447)

D107208 allows consecutive SHF_TLS SHT_NOBITS (.tbss) output sections by
making
each .tbss start at the end address of the previous one
(state->tbssAddr). This
happens unconditionally, so an explicit output section address
(`.tbss ADDR : { ... }`) is silently ignored, unlike GNU ld.

Apply the tbssAddr fallback only when the section has no address
expression.

Some embedded/RTOS applications link the kernel and several mutually
isolated
tasks into a single ELF and require every section, .tbss included, to
sit at a
specific address matching the memory map. Placing a task's .tbss in its
own
protected region is a security boundary: one task must not be able to
modify
another's TLS. Previously lld placed .tbss adjacent to .text in RX
memory
instead of where the linker script directed it, in RW memory.
The canonical form preferred by instCombine is to use 64-bit values for
constant index in ExtractElement and InsertElement.
…8991)

Test two behaviors of #195649 that were unasserted:

- .dynamic shrinks when all .relr.auth.dyn entries are moved to a
  non-empty .rela.dyn. Check the section header size: readelf -d stops
  at the first DT_NULL and cannot show stale padding. This subsumes
  empty-relr.s (a size-neutral tag swap, which passed even without the
  fix), so remove it.
- An empty .rela.dyn is removed when .relr.auth.dyn is unused. Assert
  this in pack-dyn-relocs-relr-loop.s.
forking-google-bazel-bot Bot and others added 28 commits July 13, 2026 16:48
This fixes 9bf20bd.

Buildkite error link:
https://buildkite.com/llvm-project/upstream-bazel/builds?commit=9bf20bdfc685477e349f335d1b128403342fc361

Co-authored-by: Google Bazel Bot <google-bazel-bot@google.com>
Reverts llvm/llvm-project#208822.

We should avoid raising toolchain requirements immediately before
branching. Revert this now so it can be reapplied after branching.
…instructions (#198785)

This fixes "TODO: GlobalISel should generate v_s_rsq." give in file
"llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll"
…s (#209174)

Allow i4 for FP4, i6 for FP6 and i8 for FP8.

Assisted-by: Claude Code Opus 4.8
When LLVM used curl to do HTTP requests, the timeout test failed even
though the request correctly timed out
(llvm/llvm-project#188969 (comment)).

On curl, we prepend the error with `curl_easy_perform() failed: `
whereas with WinHTTP, the error is fixed as "Timeout was reached".

This PR relaxes the check to allow for the prefix in the curl case.
…9131)

After the amdgcn-amd-amdhsa -> amdgpu-amd-amdhsa rename, look up the
device runtime libraries in the legacy directory when the runtime was
built under the old triple name.

Claude assisted with this patch.
…#209192)

Mirror the isEffectivelySerial() function in acc.compute_region to
acc.parallel and acc.kernel so this check is unified anywhere it needs
to be used, namely before ACCComputeLowering. Should be NFC
  CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChain.cpp
  CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChains/Clang.cpp
This reverts commit 1a6f5ab.
- Split FloatConversionsINTEL (6215) into FloatConversionsFtoFINTEL (6215) and FloatConversionsFtoSINTEL (6216).
- Drop OpClampConvertFToFINTEL and OpClampStochasticRoundFToFINTEL.
Their behavior is now expressed as OpFConvert / OpStochasticRoundFToFINTEL decorated with SaturatedToLargestFloat8NormalConversionEXT (fp8) or unconditionally clamped (fp4).
- Drop ClampConvert\*ToE2M1INTEL builtins - fp4 saturation is unconditional, so they collapse into Convert*ToE2M1INTEL.

Spec:
https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_fp_conversions.asciidoc

AI-assisted: Claude Opus 4.7 (commercial SaaS)

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@8edb4243a4be261
These extensions are now recognized by SPIRV-Tools and the tests pass
validation.

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@dd66f0bded35a57
* Add `OpSubgroupScaledMatrixMultiplyAccumulateINTEL`, a scaled variant
of `OpSubgroupMatrixMultiplyAccumulateINTEL` with two extra operands
carrying per-row/column scale factors for `Matrix A` and `Matrix B`,
sharing the parent instruction's operand-flag validation via
inheritance.
* Add two `Matrix Multiply Accumulate Operands` values for E8M0 scale factors.

Spec:
https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_subgroup_scaled_matrix_multiply_accumulate.asciidoc

AI-assisted: Claude Opus 4.8 (commercial SaaS)

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@f361da0325e0273
For a vector type, add `SPV_EXT_long_vector` extension and prioritize it
over `SPV_INTEL_vector_compute` whenever the vector type doesn't have a
standard component size (2, 3, 4, 8, or 16).

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@7d4b128df7e6ff3
Inspired by recent discussion whether we should validate each
instruction and what is cost for it - surprisingly the checks themselves
were cheap, the cost came from the way checkError was written.

The function constructed a std::stringstream unconditionally, *before*
the early-out taken when the condition is satisfied, and the SPIRVCK /
SPIRVCKRT macros built a std::string ("std::string() + (ErrMsg)") at
every call site. Both costs were therefore paid even on the error check
success path.

Moved "std::stringstream SS" past the early-out in checkError(). Added a
const char* checkError overload that returns before constructing any
std::string when the condition holds.
Changed SPIRVCK/SPIRVCKRT to pass the message through directly.

On OpVariable-heavy modules it improves translation time by 5-10%.

Assisted-By: Claude Fable 5

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@7d7593251d75942
… WordCount (#3787)

Following up on #3671, this adds additional guardrails for cases that
were still unhandled by the previous patch. This PR also includes
multiple new tests for invalid wordcounts, and joins them all --the new,
and the ones added by #3671-- in their own directory
(test/negative/invalid-wordcount).

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@a1441b281976ff1
#3829)

#3777 added `SPV_EXT_long_vector` and gave it priority over
`SPV_INTEL_vector_compute`: when both extensions are enabled and a
vector has a non-standard component count, the translator now emits
`CapabilityLongVectorEXT` instead of `CapabilityVectorAnyINTEL`.

This regresses `VectorCompute` modules. The offloading flow (producing
both `VectorCompute` and non-`VectorCompute` modules) applies a single,
fixed extension list uniformly to every device image, so a
`VectorCompute` module is translated with both
`SPV_INTEL_vector_compute` and `SPV_EXT_long_vector` enabled. Before
#3777 such a module emitted `VectorAnyINTEL` for its non-standard
vectors; after #3777 it emits `LongVectorEXT`. `VectorCompute` consumers
require `VectorAnyINTEL`, so this is a functional regression.

Hence, the enabled extension list does not identify a module as
`VectorCompute` - the `VectorCompute` metadata (`VCFunction`
/`VCGlobalVariable`) does. `IsVectorComputeModule` records the presence
of that metadata before type translation. `VectorCompute` modules keep
using `VectorAnyINTEL`, restoring the pre-#3777 behavior; all other
modules still prefer the multi-vendor `LongVectorEXT` when its extension
is enabled.

---------

Co-authored-by: Ye, Qi <qi.ye@intel.com>

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@3238c2903cd177e
A constant zero Size operand is invalid for OpCopyMemorySized, and these
intrinsics are no-ops, so erase them instead of lowering

Inspired by llvm/llvm-project#201904

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@94156dfb1a6af07
Some merged changes from llvm-project breaks compilation and tests of
translator.

[#187927](llvm/llvm-project#187927):
- `DISubprogram::getRetainedNodes()` returns `MDNodeArray` now, instead
of `DINodeArray`.
- Originally, a global variable in function scope (a `DIGlobalVariable`
whose scope is a `DILocalScope`) was on the `globals:` list of the
`DICompileUnit`. This has changed now: it must be on `retainedNodes` of
the owning `DISubprogram`, otherwise LLVM IR verifier will reject it.

[#207347](llvm/llvm-project#207347):
- Now `llc` requires `SPV_INTEL_function_pointers` to be enabled when
using function pointer in SPIRV BE.

---------

Co-authored-by: Sven van Haastregt <sven.vanhaastregt@arm.com>
Co-authored-by: Yury Plyakhin <yury.plyakhin@intel.com>

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@db65012182dae78
@iclsrc iclsrc added the disable-lint Skip linter check step and proceed with build jobs label Jul 17, 2026

import os
import struct
import subprocess
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disable-lint Skip linter check step and proceed with build jobs

Projects

None yet

Development

Successfully merging this pull request may close these issues.