intel / intel/llvm

Kernel fails to compile for CPU target seemingly due to use of OpBitReverse in SPIR-V

Open
#7,868 6 comments 0 reactions 0 assignees View on GitHub
bug confirmed OCL CPU Experimental RT SPIR-V
Dominant language
LLVM
Stars
1.5k
Forks
854
Avg merge
3d 17h
Merged PRs (30d)
137

Description

**Describe the bug**
I've found a scenario where a particular simple function used by my SYCL kernel fails with either JIT or AOT SPIR-V compilation for a CPU target (although not a GPU target). Looking at SPIR-V disassembly suggests that the failure only happens when the compiler was able to recognize the function can be reduced to the `OpBitReverse` operation. Breaking up the function so that the compiler doesn't recognize the `OpBitReverse` optimization allows the kernel to compile for the CPU target without a problem.

**To Reproduce**
Call this function from a SYCL kernel (e.g. just add the call to any simple SYCL tutorial's kernel):
```cpp
uint8_t reverse_byte(uint8_t a)
{
a = ((0x55 & a) << 1) | (0x55 & (a >> 1));
a = ((0x33 & a) << 2) | (0x33 & (a >> 2));
return (a << 4) | (a >> 4);
}
```
Compile with vanilla options:
```
icpx -fsycl .cpp -o
```
Runtime fails for a CPU target:
```
The program was built for 1 devices
Build program log for 'Intel(R) Xeon(R) W-10885M CPU @ 2.40GHz':
Compilation started
Unsupported SPIR-V module
SPIRV module requires unsupported capability 0
Compilation failed
-11 (CL_BUILD_PROGRAM_FAILURE)
```
NOTE: I _only_ see this problem with a CPU target. When I target a GPU it has no problem.
Now replace that function definition with these without changing anything at the `reverse_byte` call site in the kernel:
```cpp
uint8_t parital_reverse_byte(uint8_t a)
{
a = ((0x55 & a) << 1) | (0x55 & (a >> 1));
return ((0x33 & a) << 2) | (0x33 & (a >> 2));
}
uint8_t reverse_byte(uint8_t a)
{
a = parital_reverse_byte(a);
return (a << 4) | (a >> 4);
}
```
Recompile and run. Now there are no issues at runtime.
SPIR-V disassembly (via `-fsycl-device-only -fsycl-device-obj=spirv` and https://github.com/KhronosGroup/SPIRV-Tools) shows that only in the first case does it optimize the `reverse_byte` function down to the `OpBitReverse` operation. So my suspicion is that there is no backing implementation for `OpBitReverse` for CPU targets (or at least my CPU, see above). But I don't know how to decipher "SPIRV module requires unsupported capability 0" any further to know for sure that that's the issue.

**Environment:**

- OS: Linux (Ubuntu 20.04.1)
- Target device and vendor: Intel(R) Xeon(R) W-10885M CPU @ 2.40GHz
- DPC++ version: Intel(R) oneAPI DPC++/C++ Compiler 2022.2.1 (2022.2.1.20221020)
- Dependencies version: n/a

**Additional context**
None.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.