520 Commits

Author SHA1 Message Date
Dmitry Sidorov
339e2005d8
[NFC][SPIRV] Disable spirv-val in tests for constrained intrinsics (#181516)
Currently it errors out due to FPRoundingMode misplacement.
2026-02-16 12:24:08 +01:00
Nikita Popov
c4721872af Revert "[Clang][inlineasm] Add special support for "rm" output constraints (#92040)"
This change landed without approval.

This reverts commit 45e666a8531c1148bdb170b9a120f99e1500c427.
This reverts commit a636dd4c37f12594275de2fe180ca35bc04d76ea.
2026-02-14 15:59:04 +01:00
Bill Wendling
45e666a853
[Clang][inlineasm] Add special support for "rm" output constraints (#92040)
Clang isn't able to support multiple constraints on inputs and outputs,
like "rm". Instead, it picks the "safest" one to use, i.e. the memory
constraint for "rm". This leads to obviously horrible code:

  asm __volatile__ ("pushf\n\t"
                    "popq %0"
                    : "=rm" (x));

is compiled to:

        pushf
	popq -8(%rsp)
	movq	-8(%rsp), %rax

It gets worse when inlined into other functions, because it may
introduce
a stack where none is needed.

With this change, Clang now generates IR for the more optimistic choice
("r"). All but the fast register allocator are able to fold registers if
it turns out that register pressure is too high.

This leaves the fast register allocator. The fast register allocator, as
the name suggests, is built for execution speed, not code quality. Thus,
we add special processing to convert the "optimistic" IR into the
"conservative" choice (again at the IR level), which we know it can
handle.

We focus on "rm" for the initial commit, but that can be expanded in the
future for other constraints where Clang generates ++ungood code (like
"g").

Fixes: https://github.com/llvm/llvm-project/issues/20571
2026-02-14 05:02:24 -08:00
Nick Sarnie
e4c30c15c8
[SPIRV] Extend lowering of variadic functions (#178980)
Variadic function lowering for SPIR-V was initially added in
https://github.com/llvm/llvm-project/pull/175076.

However, I tried a full OpenMP offloading example that includes a vararg
call and hit a few issues:

1) The OpenMP Deivce library function `ompx::printf` was incorrectly
being considered a builtin `printf` function that would be handled
specifically by the SPIR-V backend.

The fix here is to remove the `printf` special handling.

2) We were getting an assert in ModuleVerifier saying the LLVM lifetime
intrinsics were being called with an argument that was neither an
`alloca` ptr or `poison`. The problem is the `alloca` was replaced with
a SPIR-V intrinsic `alloca` in `SPIRVPrepareFunctions`, but the lifetime
intrinsic added in `ExpandVariadics` was not lowered to the SPIR-V
lifetime intrinsic since `ExpandVariadics` is run after
`SPIRVPrepareFunctions`,

The fix here is to just run `ExpandVariadics` first.

3) There were `va` intrinsics taking in a `addrspace(4)` pointer that
were not being expanded.

The fix here is to extend `ExpandVariadics` to support expanding `va`
intrinsics with target-specific address spaces.

---------

Signed-off-by: Nick Sarnie <nick.sarnie@intel.com>
Co-authored-by: Joseph Huber <huberjn@outlook.com>
2026-02-13 18:22:25 +00:00
Dmitry Sidorov
1919b3b047
[SPIRV] Scalarize single-element vectors in type creation (#180735)
SPIR-V requires vectors to have at least 2 components. So treat <1 x T>
as T.

Fixes: https://github.com/llvm/llvm-project/issues/171175
2026-02-11 22:12:06 +01:00
Faijul Amin
643c235694
[SPIRV] Legalize extended integers for compare instructions. (#180254)
Currently, legalization fails for integer (lower than 8 bit) comparison
with extensions, for example, SPV_INTEL_int4. This PR extends integers
for supported extensions.

---------

Co-authored-by: Michal Paszkowski <michal@michalpaszkowski.com>
2026-02-10 13:29:25 -08:00
Lleu Yang
8fc59bc0e3
[SPIRV] Add handling for uinc_wrap and udec_wrap atomics (#179114)
This adds atomicrmw `uinc_wrap` and `udec_wrap` operations support for
SPIR-V. Since SPIR-V doesn't provide dedicated instructions for those
two operations, we have to use the `AtomicExpand` pass to expand the
operations into CAS forms.

Closes #177204.
2026-02-10 01:39:05 +01:00
Dmitry Sidorov
19705bd7fc
[SPIR-V] Emit ceil(Bitwidth / 32) words during OpConstant creation (#180218)
Fixes error of handing constant integers with width in (64; 128) range.
Found during review of
https://github.com/llvm/llvm-project/pull/180182
2026-02-10 00:40:35 +01:00
Steven Perron
e1d2ff6caf
[SPIRV] Implement lowering for HLSL Texture2D sampling intrinsics (#179312)
This patch implements the SPIR-V lowering for the following HLSL
intrinsics:
- SampleBias
- SampleGrad
- SampleLevel
- SampleCmp
- SampleCmpLevelZero

It defines the required LLVM intrinsics in 'IntrinsicsDirectX.td' and
'IntrinsicsSPIRV.td'.

It updates 'SPIRVInstructionSelector.cpp' to handle the new intrinsics
and
generates the correct 'OpImageSample*' instructions with the required
operands
(Bias, Grad, Lod, ConstOffset, MinLod, etc.).

CodeGen tests are added to verify the implementation for images with
dimension 1D, 2D, 3D, and Cube.

Assisted-by: Gemini
2026-02-09 17:28:58 -05:00
Nathan Gauër
091972c354
[SPIR-V] initial support for @llvm.structured.gep (#178668)
This commit adds initial support to lower the intrinsinc
`@llvm.structured.gep` into proper SPIR-V.
For now, the backend continues to support both GEP formats. We might
want to revisit this at some point for the logical part.
2026-02-09 15:51:07 +00:00
Dmitry Sidorov
f6ee5bd4df
[SPIRV] Fix constant materialization for width > 64bit (#180182)
selectConst() was asserting for constants wider than 64 bits. Add APInt
overloads of getOrCreateConstInt and getOrCreateConstVector that avoid
the uint64_t truncation.
2026-02-09 15:05:23 +01:00
Jameson Nash
2a2a394215
[SPIRV] Optimize getAllocatedType calls in LegalizeZeroSizeArrays (#179068)
Compute zero-sized allocation accurately using size APIs, and replace
them with 1 byte instead of 1 pointer of space.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 23:12:51 -05:00
Dmitry Sidorov
be18ac87b7
[SPIRV] Fix APInt overflow in memset constant array creation (#180189)
In getOrCreateConstIntArray(), the cache UniqueKey encoded the array
size (Num) using the array element type (e.g. i8 for memset). Since Num
is a size_t that can exceed 255, this caused an APInt overflow when Num
> 255. Use i64 for Num in the UniqueKey.
2026-02-06 22:59:04 +01:00
Dmitry Sidorov
9e355c8ec3
[SPIRV] Fix alignment overflow in memory intrinsics (#180184)
Per SPIR-V spec alignment is 32-bit integer, so it should be encoded as
i8 in the intrinsics'
def.
2026-02-06 22:58:33 +01:00
Nick Sarnie
3a08424124
[SPIRV] Do not emit @llvm.used (#179498)
Extending the work from https://github.com/llvm/llvm-project/pull/162678
which skips `llvm.compiler.used`, we also need to skip processing of
`llvm.used`.

The OpenMP frontend puts an `addrspace(2)` variable in `llvm_used`, but
the `llvm.used` array type uses the generic AS `addrspace(4)` so there's
a `addrspacecast` from `2` to `4` inside the initalizer for `llvm.used`
which is illegal and errors in the backend.

There is
[discussion](https://github.com/llvm/llvm-project/pull/162678#issuecomment-3396735124)
in the above linked PR that the handing should be the same for
`llvm.used` and `llvm.compiler.used`, but `llvm.used` was not added to
minimize the scope of the PR.

This is required to use the OpenMP Device RTL with SPIR-V.

Signed-off-by: Nick Sarnie <nick.sarnie@intel.com>
2026-02-05 16:28:23 +00:00
Dmitry Sidorov
c487e248b9
[SPIR-V] Fix environment resolution causing legalization crash (#179052)
When the triple is spirv-unknown-unknown, SPIRVSubtarget::Env starts as
Unknown and was set via const_cast in SPIRVCallLowering when the first
entry point was lowered. This is too late: SPIRVLegalizerInfo has
already been constructed with, for example, the wrong vector size
limits, causing a crash (at best) or invalid SPIR-V generation.

Resolve the environment early in SPIRVPrepareFunctions::runOnModule() by
scanning the module for "hlsl.shader" attributes. Reinitialize the
legalizer and extended instruction sets after resolution. Remove the
const_cast lazy setting from SPIRVCallLowering.

Fixes: https://github.com/llvm/llvm-project/issues/171898
2026-02-04 15:27:48 +01:00
Fabian Ritter
d24a6754ce
[LowerMemIntrinsics] Optimize memset lowering (#169040)
This patch changes the memset lowering to match the optimized memcpy lowering.
The memset lowering now queries TTI.getMemcpyLoopLoweringType for a preferred
memory access type. If that type is larger than a byte, the memset is lowered
into two loops: a main loop that stores a sufficiently wide vector splat of the
SetValue with the preferred memory access type and a residual loop that covers
the remaining bytes individually. If the memset size is statically known, the
residual loop is replaced by a sequence of stores.

This improves memset performance on gfx1030 (AMDGPU) in microbenchmarks by
around 7-20x.

I'm planning similar treatment for memset.pattern as a follow-up PR.

For SWDEV-543208.
2026-02-04 13:35:13 +01:00
Juan Manuel Martinez Caamaño
4553f991a8
[SPIRV] selectDot4AddPacked: add missing PackedVectorFormat4x8Bit optional operand (#179476)
According to SPIRV:

```
PackedVectorFormat4x8Bit (PackedVectorFormat4x8BitKHR)

Interpret 32-bit scalar integer operands as vectors of four 8-bit
components. Vector components follow byte significance order with the
lowest-numbered component stored in the least significant byte.
```

And in OpSDot / OpUDot:

```
When Vector 1 and Vector 2 are scalar integer types, Packed Vector
Format must be specified to select how the integers are to be
interpreted as vectors.
```
2026-02-04 08:58:54 +01:00
Dmitry Sidorov
cb5e2db75a
[SPIR-V] Add lowering for G_FSINCOS (#179053)
Use either OpenCL::sincos for compute or sequence of HLSL::sin +
HLSL::cos for shader.
2026-02-03 19:38:41 +01:00
Kai
751a546fa9
[HLSL][DXIL][SPIRV] WavePrefixSum intrinsic support (#167946)
Issue: https://github.com/llvm/llvm-project/issues/99172
- [x] Implement `WavePrefixSum` clang builtin
- [x] Link `WavePrefixSum` clang builtin with `hlsl_intrinsics.h`
- [x] Add sema checks for `WavePrefixSum` to
`CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp`
- [x] Add codegen for `WavePrefixSum` to `EmitHLSLBuiltinExpr` in
`CGBuiltin.cpp`
- [x] Add codegen tests to
`clang/test/CodeGenHLSL/builtins/WavePrefixSum.hlsl`
- [x] Add sema tests to
`clang/test/SemaHLSL/BuiltIns/WavePrefixSum-errors.hlsl`
- [x] Create the `int_dx_WavePrefixSum` intrinsic in
`IntrinsicsDirectX.td`
- [x] Create the `DXILOpMapping` of `int_dx_WavePrefixSum` to `121` in
`DXIL.td`
- [x] Create the `WavePrefixSum.ll` and `WavePrefixSum_errors.ll` tests
in `llvm/test/CodeGen/DirectX/`
- [x] Create the `int_spv_WavePrefixSum` intrinsic in
`IntrinsicsSPIRV.td`
- [x] In SPIRVInstructionSelector.cpp create the `WavePrefixSum`
lowering and map it to `int_spv_WavePrefixSum` in
`SPIRVInstructionSelector::selectIntrinsic`.
- [x] Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WavePrefixSum.ll`

I also added a new macro
`GENERATE_HLSL_INTRINSIC_FUNCTION_SELECT_UNSIGNED` in conjunction with
the new function `getUnsignedIntrinsicVariant` to make selecting
unsigned variants of the intrinsic easier. As a result, I was able to
replace `getWaveActiveSumIntrinsic`, `getWaveActiveMaxIntrinsic`, and
`getWaveActiveMinIntrinsic` using the new macro.
2026-02-03 03:00:45 -05:00
Juan Manuel Martinez Caamaño
395858d9f1
Revert "[SPIRV] Emit intrinsics for globals only in function that references them (#178143 (#179268)
This reverts commit 1daef5927ff0e43b92d615380a8d60f213cc5e52.

From the ASAN buildbot:

```bash
FAIL: LLVM :: CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll (46596 of 94488)
******************** TEST 'LLVM :: CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll' FAILED ********************
Exit Code: 2

Command Output (stdout):
--
# RUN: at line 5
/home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll -o - --spirv-ext=+SPV_INTEL_function_pointers | /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/FileCheck /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll
# executed command: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll -o - --spirv-ext=+SPV_INTEL_function_pointers
# note: command had no output on stdout or stderr
# error: command failed with exit status: 1
# executed command: /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/FileCheck /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll
# .---command stderr------------
# | FileCheck error: '<stdin>' is empty.
# | FileCheck command line:  /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm_build_asan/bin/FileCheck /home/b/sanitizer-aarch64-linux-bootstrap-asan/build/llvm-project/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fun-ptr-addrcast.ll
# `-----------------------------
# error: command failed with exit status: 2
```

I did not confirm this commit is introducing the issue. But since its
likely related I'm reverting it until I confirm everything is ok or fix
it.
2026-02-02 16:34:05 +00:00
Dmitry Sidorov
fcc4231ac5
[SPIR-V] Add SPV_INTEL_unstructured_loop_controls extension (#178799)
For compute we don't run structurizer hence we won't be able to preserve
loop metadata via LoopMerge instruction. So
SPV_INTEL_unstructured_loop_controls is the only way we can preserve the
info in unstructured control flow.
2026-02-02 15:06:18 +01:00
Juan Manuel Martinez Caamaño
1daef5927f
[SPIRV] Emit intrinsics for globals only in function that references them (#178143)
In the SPIRV backend, the `SPIRVEmitIntrinscs::processGlobalValue`
function adds intrinsic calls for every global variable of the module,
on every function.

These intrinsics are used to keep track of global variables, their types
and initializers.

In SPIRV everything is an instruction (even globals/constants). We
currently represent these global entities as individual instructions on
every function. Later, the `SPIRVModuleAnalysis` collects these entities
and maps function _local_ registers to _global_ registers. The
`SPIRVAsmPrinter` is in charge of mapping back the _local_ registers to
the appropriate _global_ register.

These instructions associated with global entities on functions that do
not reference them leads to a bloated intermediate representation and
high memory consumption (as it happened in
https://github.com/llvm/llvm-project/issues/170339).

Consider this example:

```cpp
  int A[1024] = { 0, 1, 2, ..., 1023 };
  int get_a(int i) {
    return A[i];
  }

  void say_hi() {
    puts("hi!\n");
  }
```

Although, `say_hi` does not reference `A`; we would generate machine
instructions for the declaration of `A`, for the constant array that
initializes it, and for the 1024 constant elements of `A`.

This patch doesn't fix the underlying issue, but it mitigates it by only
emitting global-variable SPIRV intrinsics on the functions that use it.
If the global is not referenced by any function, we just pick the first
function definition.

With this patch, the example in
https://github.com/llvm/llvm-project/issues/170339 drops from ~33Gb of
maximum resident set size to less than ~590Mb. And compile time goes
from 2:09min to ~5secs.

The changes in the tests are due to changes in the order in which the
instructions appear.
In `fun-with-aggregate-arg-in-const-init.ll` 2 duplicated
`OpConstantComposite` are emitted anymore.
2026-02-02 14:42:10 +01:00
Manuel Carrasco
9e97f0b3d0
[SPIRV] Split async copy tests and fix invalid tests (#178718)
Some tests started failing recently because `spirv-val` now considers
their output invalid. This is likely due to an update in `spirv-val`.
I'm not familiar with what the tests are doing but here is my attempt to
fix them. At the LLVM-IR level, tests had for example incorrect
`addresspace` for certain arguments. To fix them, I used as a reference
some of the tests in the SPIRV-LLVM translator. The goal of the PR is
just to fix the tests in case they had incorrect IR.
2026-02-02 11:22:03 +00:00
Viktoria Maximova
8f8dfbf8c9
[SPIR-V] Implement SPV_KHR_fma extension (#173057)
The extension adds support for the `OpFmaKHR` instruction, which
provides a native SPIR-V instruction for fused multiply-add operations
as an alternative to using OpenCL.std::Fma extended instruction.

Translate both LLVM fma intrinsics as well as OCL builtins to `OpFmaKHR`
if the extension is available.

Specification:

https://github.khronos.org/SPIRV-Registry/extensions/KHR/SPV_KHR_fma.html
2026-01-29 17:39:57 -08:00
Joshua Batista
293a668329
[HLSL] Add wave prefix count bits function (#178059)
This PR adds the WavePrefixCountBits function to HLSL, including spirv
and DXIL code generation.
Fixes https://github.com/llvm/llvm-project/issues/99171
2026-01-29 12:09:27 -08:00
Jameson Nash
9d5d2eec21
[Mem2Reg] Remove extraneous getAllocatedType() check (#177438)
Replace uses of getAllocatedType() in PromoteMemoryToRegister.cpp with
type tracking from actual loads and stores. This makes the promotion
logic more semantic - it now checks that all loads/stores use a
consistent type rather than requiring them to match the alloca's
declared type.

Changes:
- isAllocaPromotable() now tracks the first load/store type seen and
ensures all subsequent accesses use the same type
- AllocaInfo gains a ValueType field populated during AnalyzeAlloca()
- PromoteMem2Reg tracks AllocaValueTypes alongside other per-alloca info
- PHI nodes and UndefValues are created using the tracked type

This is semantically more permissive - an alloca declared as i64 but
only accessed as i32 is now promotable. This is correct because the
alloca is just a blob of memory; what matters for Mem2Reg is consistent
access patterns.

Test changes:
- asan-stack-safety.ll: Changed loads/stores to volatile to prevent
promotion while preserving ASAN stack safety analysis behavior
- SPIRV pointer tests (array-skips-gep.ll, load-struct.ll,
store-struct.ll, store-to-array-first-element.ll): Added escape calls to
prevent alloca promotion, as these tests verify SPIRV backend handling
of Function-storage-class pointers

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:10:48 -05:00
Marcos Maronas
4631208375
[SPIRV] Extend and fix SPV_KHR_bit_instructions testing. (#175825)
On one hand, this patch adds a couple of new testcases related to
SPV_KHR_bit_instructions. On the other hand, it fixes a couple of
testcases that were using `llvm.bitreverse.*`, while they were supposed
to use the SPIRV-friendly equivalent.

---------

Co-authored-by: Marcos Maronas <marcos.maronas@intel.com>
2026-01-27 07:52:15 +00:00
Tim Corringham
d5f405558d
[HLSL] Implement f32tof16() intrinsic (#172469)
Implement the f32tof16() intrinsic, DXIL and SPIRV codegen, and related
tests.

Fixes #99113

---------

Co-authored-by: Tim Corringham <tcorring@amd.com>
2026-01-26 15:06:48 +00:00
Steven Perron
296f5a75bd
[SPIR-V] Implement sample and sample_clamp intrinsics for HLSL resources (#177234)
This patch implements the `sample` and `sample_clamp` intrinsics for
HLSL
resources in the SPIR-V backend. It adds the necessary intrinsic
definitions
in `IntrinsicsDirectX.td` and `IntrinsicsSPIRV.td`, and implements the
instruction selection logic in `SPIRVInstructionSelector.cpp`.

Key changes:
- Added `int_dx_resource_sample` and `int_dx_resource_sample_clamp`
intrinsics.
- Added `int_spv_resource_sample` and `int_spv_resource_sample_clamp`
intrinsics.
- Implemented `selectSampleIntrinsic` to handle
`OpImageSampleImplicitLod` generation.
- Added `ResourceDimension` enum in `DXILABI.h` and `HLSLResource.h`.
- Added a new test case
`llvm/test/CodeGen/SPIRV/hlsl-resources/Sample.ll` to verify the
implementation.
2026-01-23 12:21:31 -05:00
Nick Sarnie
3954cd2db6
[SPIRV] Process indirect function calls immediately (#177222)
The SPIR-V backend processes indirect function calls in
`SPIRVCallLowering`, which is a subclass of the generic `CallLowering`.

It intends to process them function by function, by first collecting all
indirect calls in a function, and then processing all of a function's
indirect calls at once when the call lowering for the function is about
to end.

Today, it relies on the `lowerReturn` virtual function to be called by
the generic call lowering infra to know the function processing is about
to end, and at that time it processes all of the collected indirect
calls and clears the vector of indirect calls.

The problem is that not all functions have return instructions. Every
basic block must have a terminator instruction, but it does
[not](https://llvm.org/docs/LangRef.html#terminator-instructions) have
to be a return.

In the failing case here, function `a` has an infinite loop, with every
iteration having an indirect call and a check to see if it should break
out of the infinite loop. There is a return instruction initially, but
it is optimized out in the middle end. There is also an unrelated
function `b` with no indirect calls.

During call lowering, information about the indirect call in `a` is
captured in the vector in SPIRVCallLowering, but since there is no
return instruction, it is never processed.

Then, function `b` is processed. `b` happens to have a return
instruction, so the indirect call from `a` is processed, but the
processing assumes that the indirect call is inside the function being
processed, and it writes to a `{function, register}->SPIRVType` map, but
the function is `b` not `a`.

This ends up causing the map to have an invalid SPIRVType for the
register in function `b`, and `b` happens to have a register of the same
type, causing an invalid result from the map lookup and thus invalid IR
(`G_ADDRSPACE_CAST` from `ptr addrspace(4)` to `i32`).

We can't move the indirect call processing into a seperate pass because
we lose required information after call lowering ends.

Here, we change the indirect call processing to be done immediately when
it is seen.

Comments say the reason the collect all then process style was done was
to get better type information for the caller of the indirect function
if an opaque pointer is an arg to the caller and the indirect function,
but [an existing test
case](https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp-simple-hierarchy.ll)
seems to exercise this, and the test still passes after this change and
actually has the exact same assembly.

The test case added is a minimal example from `llvm-reduce`, so it's
just an infinite loop with no exit condition.

Signed-off-by: Nick Sarnie <nick.sarnie@intel.com>
2026-01-22 15:57:19 +00:00
Alex Voicu
9357c5906c
[SPIRV] Unify unsized array handling for AMGCN flavoured SPIR-V (#175848)
Currently we handle 0-sized arrays in multiple places, non-uniformly,
either via `SPIRVLegalizeZeroSizeArrays` or via `SPIRVPrepareGlobals`.
For AMDGCN flavoured SPIR-V we have a singular, simpler solution: set
all 0-sized arrays to be `UINT64_MAX` sized. This is an unambiguous
token that we can use during reverse translation to restore the intended
0 size.
2026-01-22 13:39:21 +00:00
Michal Paszkowski
a679a25ceb
Revert " [SPIRV] Addition of extension SPV_KHR_non_semantic_info and SPV_KHR_relaxed_extended_instruction" (#177093)
Reverts llvm/llvm-project#169643 due to build issues
2026-01-20 21:41:31 -08:00
Aadesh Premkumar
287be74a02
[SPIRV] Addition of extension SPV_KHR_non_semantic_info and SPV_KHR_relaxed_extended_instruction (#169643)
--Added support for the extension SPV_KHR_non_semantic_info
--Added support for the extension SPV_KHR_relaxed_extended_instruction 
--Added instructions from the documentation of the extension. 
--Added supporting tests for the same.

Same as #165302

---------

Co-authored-by: Michal Paszkowski <michal@michalpaszkowski.com>
2026-01-20 21:36:01 -08:00
Joshua Batista
11b1836282
[HLSL] Handle WaveActiveBallot struct return type appropriately (#175105)
The previous WaveActiveBallot implementation did not account for the
fact that the DXC implementation of the intrinsic returns a struct type
with 4 uints, rather than a vector of 4 uints. This must be respected,
otherwise the validator will reject the uses of WaveActiveBallot that
return a vector of 4 uints.
This PR updates the return type and adds the DXC-specific return type
`fouri32` to use for the intrinsic.
2026-01-20 10:08:26 -08:00
Viktoria Maximova
d265996cc6
[SPIR-V] Fix builtin name extraction for templated functions (#173027)
This patch improves the `lookupBuiltinNameHelper` function to handle
demangled function signatures more robustly.

SPIR-V backend failed to get builtin function name from demangled calls
when the function signature contained complex template types.

For example, a demangled call like: 
`__spv::__spirv_CooperativeMatrixKHR<short, ...>*
__spirv_CooperativeMatrixLoadKHR<...>(...)`
was not correctly parsed to extract `__spirv_CooperativeMatrixLoadKHR`.
2026-01-20 05:41:51 -08:00
Joseph Huber
efb57947ba
[SPIR-V] Enable variadic function lowering for the SPIR-V target (#175076)
Summary:
We support variadic functions in AMDGPU / NVPTX via an LLVM-IR pass.
This patch applies the same handling here to support them on this
target.

I am unsure what the ABI should look like here, I have mostly copied the
one we use for NVPTX where it's basically a struct layout with natural
alignment. This wastes some space, which is why AMDGPU does not pad
them.

Additionally, this required allowing the SPIRV_FUNC calling convention.
I'm assuming this is compatible with the C calling convention in IR, but
I will need someone to confirm that for me.
2026-01-19 12:19:15 -06:00
Steven Perron
0c5c920aa7
[SPIRV] Improve vector legalization and type deduction (#175067)
This patch adds support for scalarizing vector loads in the legalizer
and
implements legalization for the spv_const_composite intrinsic. It also
refactors stack temporary creation for vector operations to ensure
correct
SPIR-V types are assigned. Additionally, type deduction in the
PostLegalizer is improved to handle GEP and Load instructions.

Fixes https://github.com/llvm/llvm-project/issues/170534
2026-01-15 07:55:14 -05:00
Nathan Gauër
0431b71680
[SPIR-V] Fix store to first element array (#175546)
The IR can store to the first element of an array the same way it stores
to the first element of a struct by specifying the base pointer. This
commit fixes the pointercast legalization pass to support this.
2026-01-14 17:43:06 +01:00
Subash B
075e4672a6
[SPIRV] Added Support for the SPV_ALTERA_arbitrary_precision_floating_point Extension (#160054)
Added support for the SPV_ALTERA_arbitrary_precision_floating_point
extension, enabling all the arbitrary precision floating-point
operations with instruction definitions and test files.
2026-01-14 00:37:22 -08:00
Subash B
17aa32c243
[SPIRV] Added support for the constrained arithmetic(Fmuladd) intrinsic (#170270)
Added SPIR-V support for constrained arithmetic intrinsic fmuladd,
lowered as a sequence of OpFMul and OpFAdd with roundingmode, consistent
with the SPIR-V translator.
2026-01-14 00:20:40 -08:00
Alex Voicu
35a20d7e92
[SPIRV] Handle externally_initialized for AMDGCN flavoured SPIRV (#175277)
SPIR-V doesn't currently have a way to encode the `externally_initialized` LLVM concept. Unfortunately, certain HIP constructs (e.g. `__managed__` or `__constant__` variables) rely on it. Hence, this patch allows AMDGCN flavoured SPIR-V to encode `externally_initialized` via the `HostAccessINTEL` decoration, which approximates some of the semantics; the decoration is handled during reverse translation. It also appears that we never fully implemented the decoration, which I intend to handle in a subsequent, independent patch.
2026-01-13 23:56:32 +02:00
Alex Voicu
e531f48fc4
[SPIRV] Deduce result type for G_SEXT and G_ZEXT (#175401)
During legalisation we can fold / combine `sext` followed by a widening
via `zext`. Unfortunately, this yields a new result register with no
SPIRV Type, which leads to incorrect behaviour during post legalisation
when we end up deducing the (narrower) type from the operand. This patch
corrects the behaviour in that it ensures that we use the (widened) type
of the result to yield the SPIRV Type for the register.
2026-01-12 18:11:14 +02:00
Nathan Gauër
9725cb8ede
[SPIR-V] Fix Linkage capability with pushconstant (#175192)
When the SPIR-V backend handles a push constant, a new global with a
target-specific is generated. This global should have the same
visibility as the source, but turns out it was not the case: linkage was
still external, but visibility went from hidden to visible.

This causes the later passes to generate a Linkage decoration, adding
the Linkage capability, which is not compatible with Vulkan. Fixing
this.
2026-01-12 10:23:13 +01:00
Alex Voicu
f5c39a6b0a
[SPIRV] Additional fixes for const init via UtoPtr (#172584)
#166494 added support for using `inttoptr` in global initialisation, and
lowering int into `OpSpecConstantOp OpConvertUToPtr`. Unfortunately, it
slightly more subtle case / exposed an existing issue around the `COPY`
pseudo-op. This patch ensures that we glance through a `COPY` when
figuring out whether an `OpConvertUToPtr` is actually operating on a
global. We also correctly handle the case where a `G_PTR_ADD` is used by
an `OpSpecConstantOp` in the context of global initialisation, which
would otherwise lead to broken SPIR-V wherein the latter would reference
a non constant Op.

---------

Co-authored-by: Marcos Maronas <marcos.maronas@intel.com>
2026-01-08 15:32:55 +00:00
Manuel Carrasco
90b8a481e4
[SPIRV] Support additional comparison predicates for i1 types (#174585)
Previously, the SPIRV BE only handled equality and inequality
comparisons (ICMP_EQ, ICMP_NE) for i1 types using logical operations
(OpLogicalEqual, OpLogicalNotEqual). Other comparison predicates
(signed/unsigned less than, greater than, etc.) triggered an unreachable
assertion.

This patch extends the support for the missing predicates. The BE
considers i1 values as booleans and in SPIR-V only logical operations
can work on them. This patch lowers the missing predicates into
supported logical operations.

The lowering has been validated with instcombine to avoid introducing an
unsound transformation (using the new test case).
2026-01-08 11:53:45 +00:00
Alex Voicu
9519d52512
[SPIRV] Handle aggregate arguments to spv_store (#172348)
This patch handles the special case where an extract value yields an
aggregate result, which then is used as an argument to a store. The
SPIRV BE uses special intrinsics (`spv_extractv` and `spv_store`) to
represent these through IRTranslator, however this creates a problem:
`spv_store` is called as a function, and IRTranslator cannot handle
arguments that take more than a vreg. For other functions, the aggregate
argument replacement pass would have solved things, but it does not
apply here. Hence, we apply the same mutate-into-Int32 solution here
when dealing with stores, and restore the extract value's type (which we
have available as a ValueAttr) during instruction selection.
2026-01-08 02:21:02 +00:00
Joshua Batista
65b0de42e7
[HLSL] Add WaveActiveBallot builtins and lower to DXIL / SPIR-V (#174638)
This PR adds WaveActiveBallot as a builtin function to HLSL.
Fixes https://github.com/llvm/llvm-project/issues/99163
2026-01-07 10:06:27 -08:00
Nick Sarnie
75ec177483
[SPIRV] Add legalization pass for zero-size arrays (#172367)
This adds a legalization pass to convert zero size arrays to legal types
for common cases. It doesn't handle all cases, but if we see real use
cases for other cases, we can add them in the future.

For globals, and their initializers, we generally replace `[0 x T]` with
`ptr`.

For instructions, we either replace `[0 x T]` with `poision`, for
`alloca` we just allocate `T`.

This is motivated by IR generated by the OpenMP front end.

Issue: https://github.com/llvm/llvm-project/issues/170150

---------

Signed-off-by: Nick Sarnie <nick.sarnie@intel.com>
2026-01-07 16:58:53 +00:00
Steven Perron
88b77d5eaa
[SPIRV] Support non-constant indices for vector insert/extract (#172514)
This patch updates the legalization of spv_insertelt and spv_extractelt
to
handle non-constant (dynamic) indices. When a dynamic index is
encountered, the
vector is spilled to the stack, and the element is accessed via
OpAccessChain
(lowered from spv_gep).

This patch also adds custom legalization for G_STORE to scalarize vector
stores
and refines the legalization rules for G_LOAD, G_STORE, and
G_BUILD_VECTOR.

Fixes https://github.com/llvm/llvm-project/issues/170534
2026-01-07 14:37:53 +00:00