intel / intel/llvm

Intel Bindless Images extension produces non-spec-compliant SPIR-V when compiled with -O0

Open
#22,951 0 comments 0 reactions 0 assignees View on GitHub
bug SPIR-V sycl-bindless-images
Dominant language
LLVM
Stars
1.5k
Forks
854
Avg merge
3d 17h
Merged PRs (30d)
137

Description

### Describe the bug

The test `sycl/test-e2e/bindless_images/sampled_fetch/fetch_1D_O0.cpp` produces SPIR-V code with the following pattern:

```
%call_5 = OpConvertHandleToSampledImageINTEL %648 %675
...
OpStore %SmpImg_addr_ascast_i %call_5 Aligned 8
...
%693 = OpLoad %648 %SmpImg_addr_ascast_i Aligned 8
...
%call1_i = OpImageSampleExplicitLod %v4float %693 %694 Lod %695
```

This code does not comply with the SPIR-V specification, specifically under 2.16.1 "Universal Validation Rules", subsection "Data rules":

> Image, sampler, and sampled image objects must not appear as operands to [OpPhi](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpPhi) instructions, or [OpSelect](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpSelect) instructions, *or any instructions other than the image or sampler instructions specified to operate on them.*

In other words, the result of the `OpConvertHandleToSampledImageINTEL` must (according to the spec) be directly used by the `OpImageSampleExplicitLod`, and may not appear as an operand to the `OpStore`.

At higher optimisation levels (`-O1` and above), this pattern is eliminated, resulting in spec-compliant SPIR-V code.

This pattern does _not_ appear when compiling code that uses "traditional" sampled images. For example, the test `sycl/test-e2e/bindless_images/Sampled/normalized-clam-linear-float.cpp`, when compiled with `-O0`, produces the following correct SPIR-V:

```
%call_i_0 = OpFunctionCall %float %_ZN4sycl3_V16detail19convertToOpenCLTypeIRfEEDaOT_ %Coords_addr_ascast_i_0
OpStore %TmpCoords_ascast_i_0 %call_i_0 Aligned|NoAliasINTELMask 4 %984
%989 = OpLoad %246 %Img_addr_ascast_i_0 Aligned|NoAliasINTELMask 8 %984
%990 = OpLoad %_ptr_Generic_247 %Smpl_addr_ascast_i Aligned|NoAliasINTELMask 8 %984
%991 = OpLoad %247 %990 Aligned|NoAliasINTELMask 8 %984
%call1_i_0 = OpSampledImage %992 %989 %991
%994 = OpLoad %float %TmpCoords_ascast_i_0 Aligned|NoAliasINTELMask 4 %984
%call2_i_0 = OpImageSampleExplicitLod %v4float %call1_i_0 %994 Lod %float_0
```

Note that although the coordinates, image, and sampler are all written to and read from pointers, the `OpSampledImage` is directly used by `OpImageSampleExplicitLod`.

In conclusion: the result of `OpSampledImage` is correctly immediately used, as specified by the SPIR-V spec. The result of `OpConvertHandleToSampledImageINTEL`, despite having the same return type, is written to a pointer, which is in violation of the spec.

### To reproduce

1. Compile the e2e test `sycl/test-e2e/bindless_images/sampled_fetch/fetch_1D_O0.cpp` with SYCL clang. I.e.:

`$(SYCL_ROOT)/clang++ -fsycl-device-obj=spirv -fsycl -fsycl-device-only -std=c++17 -O0 -I$(SYCL_ROOT)/include fetch_1D_O0.cpp -o fetch_1D_O0.spv`

2. Disassemble the resulting SPIR-V binary, e.g. with `spirv-dis`:

`spirv-dis fetch_1D_O0.spv -o fetch_1D_O0.spvasm`

3. Inspect the resulting SPIR-V assembly file (`fetch_1D_O0.spvasm`), and search for `OpImageSampleExplicitLod`. The call should take a pointer, rather than the result of `OpConvertHandleToSampledImageINTEL`.

4. Repeat the above process for any of the tests from `sycl/test-e2e/bindless_images/Sampler`, and observe that the `OpImageSampleExplicitLod` directly takes the result of the call to `OpSampledImage`.

----

Alternatively, the sycle2e test suite can be run, and SPIR-V extracted using `clang-offload-extract`. Note however, that if this approach is taken, the `lit` directive `// RUN: %{build} -o %t.out` will need to be modified to pass `-O0`.
### Environment

- OS: Linux
- Target device and vendor: N/A
- DPC++ version: `DPC++ compiler 7.0.0 build based on: clang version 22.1.0`
- Dependencies version: sycl-ls not built

### Additional context

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with sycl/test-e2e/bindless_images/sampled_fetch/fetch_1D_O0.cpp and reproduce the issue using the shown SYCL clang -O0 command, then disassemble with spirv-dis. Compare the bindless-image output with the Sampler tests, and confirm the fix when OpConvertHandleToSampledImageINTEL is used directly by OpImageSampleExplicitLod without an intervening OpStore or OpLoad.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.