KhronosGroup / KhronosGroup/SPIRV-LLVM-Translator

Reverse translation of OpCompositeConstruct with a vector constituent produces invalid insertelement

Open
#3,860 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
LLVM
Stars
625
Forks
279
Avg merge
3d 5h
Merged PRs (30d)
34

Description

## Summary

`llvm-spirv -r` translates an `OpCompositeConstruct` whose result is a vector and one of whose constituents is a **smaller vector** (e.g. a `vec4` built from a `vec3` plus a scalar) into an invalid `insertelement` that inserts the whole sub-vector as a single scalar element. The resulting module fails the LLVM verifier:

```
Invalid insertelement operands!
%6 = insertelement <4 x i32> poison, <3 x i32> %5, i32 0
```

Per the SPIR-V spec, an `OpCompositeConstruct` result-vector constituent that is itself a vector contributes **all of its components, in order**. So `OpCompositeConstruct %v4uint %v3 %scalar` should yield a 4-component vector from the three components of `%v3` followed by `%scalar`. The reverse translator instead treats the `<3 x i32>` constituent as if it were a single scalar element of the `<4 x i32>`.

## Reproducer

Image-independent, minimal (`repro.spvasm`, SPIR-V 1.0):

```
OpCapability Addresses
OpCapability Kernel
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %k "k"
%void = OpTypeVoid
%uint = OpTypeInt 32 0
%v3uint = OpTypeVector %uint 3
%v4uint = OpTypeVector %uint 4
%ptr_g = OpTypePointer CrossWorkgroup %v4uint
%fnty = OpTypeFunction %void %ptr_g %uint
%uint_0 = OpConstant %uint 0
%k = OpFunction %void None %fnty
%out = OpFunctionParameter %ptr_g
%n = OpFunctionParameter %uint
%entry = OpLabel
%rt3 = OpCompositeConstruct %v3uint %n %n %n
%v4 = OpCompositeConstruct %v4uint %rt3 %uint_0
OpStore %out %v4 Aligned 16
OpReturn
OpFunctionEnd
```

```console
$ spirv-as repro.spvasm -o repro.spv # SPIRV-Tools v2026.1; spirv-val repro.spv passes
$ llvm-spirv -r repro.spv -o repro.bc
Fails to verify module: Invalid insertelement operands!
%6 = insertelement <4 x i32> poison, <3 x i32> %5, i32 0
```

The input passes `spirv-val`; the failure is purely in the reverse translation. (The `poison` base of the `insertelement` is normal LLVM vector-build idiom; the defect is the `<3 x i32>` value operand where a scalar `i32` is required.)

## Versions tested

Reproduces on `llvm-spirv` **14.0.6, 18.1.8, 19.1.7, 20.1.8, 21.1.8, and 22.1.2** (the newest release available). 17.x segfaults on this input for an apparently unrelated reason.

## Note

`OpVectorShuffle` widening of the same vec3 to vec4 (`OpVectorShuffle %v4uint %rt3 %zero_v3 0 1 2 3`) translates without error on all the versions above — this is the form Clang emits for `(uint4)(v3, 0)`, which is presumably why the `OpCompositeConstruct` form has stayed latent for OpenCL C. It is reachable from non-Clang SPIR-V producers ([rust-gpu](https://github.com/Rust-GPU/rust-gpu) in my case).

The runtime-vector-constituent test added in #2296 (`test/composite_construct_vector_non_constant.spvasm`) constructs a vector from scalar constituents; it does not include a case with a (smaller) vector constituent.

## Expected

`OpCompositeConstruct` with a vector constituent should lower to a `shufflevector` (or a per-component `insertelement` sequence that spreads the sub-vector's components), matching the "contributes all its components in order" semantics.

Contributor guide

Open the contributing guide

Research direction

Start by running the provided repro.spvasm through spirv-as, spirv-val, and llvm-spirv -r, then read test/composite_construct_vector_non_constant.spvasm. Extend coverage for a smaller vector constituent in OpCompositeConstruct and verify that reverse translation produces valid LLVM IR, using shufflevector or per-component insertion as the expected behavior.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.