This change landed without approval.
This reverts commit 45e666a8531c1148bdb170b9a120f99e1500c427.
This reverts commit a636dd4c37f12594275de2fe180ca35bc04d76ea.
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
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>
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>
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.
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
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.
selectConst() was asserting for constants wider than 64 bits. Add APInt
overloads of getOrCreateConstInt and getOrCreateConstVector that avoid
the uint64_t truncation.
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>
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.
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>
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
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.
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.
```
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.
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.
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.
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.
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.
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
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>
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>
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.
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>
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.
--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>
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.
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`.
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.
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
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.
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.
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.
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.
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.
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.
#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>
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).
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.
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>
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