intel / intel/intel-graphics-compiler
OpUMulExtended: SPIR-V reader mangles operands as signed, BiFModule only defines the unsigned overloads
- Dominant language
- C++
- Stars
- 718
- Forks
- 191
- PR merge metrics
- No merged PRs in 30d
Description
A module using `OpUMulExtended` fails to build on every IGC I have tested:
$ ocloc compile -file umulo.spv -spirv_input -device pvc
error: undefined reference to `_Z20__spirv_UMulExtendedll'
in function: '__spirv_UMulExtended(long, long)' called by kernel: 'k'
error: backend compiler failed build.
The module is `spirv-val` clean and `OpUMulExtended` is core SPIR-V 1.0, no extension involved.
The SPIR-V reader mangles the operands as signed, `_Z20__spirv_UMulExtendedll`, but `IGC/BiFModule/Implementation/arithmetic.cl` defines only the unsigned overloads, `__spirv_UMulExtended(ulong Operand1, ulong Operand2)` and friends, which mangle to `_Z20__spirv_UMulExtendedmm`. There is no signed-typed `__spirv_UMulExtended` in that file. The same module with `OpSMulExtended` instead builds fine, because there the signed mangling matches `__spirv_SMulExtended(long, long)`.
Tested:
Intel Data Center GPU Max 1550, IGC 2.11.29 (agama 25.18), ocloc -device pvc : fails
Intel Arc B570, IGC 2.38.2, ocloc -device bmg : fails
This looks fixed upstream by KhronosGroup/SPIRV-LLVM-Translator#3963 (merged 2026-08-18), which adds `OpUMulExtended` to the opcodes whose builtin arguments are mangled unsigned. That commit is on `main` only; it is not on `llvm_release_170`, which is what `external/llvm/llvm_preferred_version.cmake` points IGC at today, so no released IGC picks it up. Would you take a backport of that into the translator release branch IGC builds against, or alternatively add the signed overloads to the BiF module?
Reproducer, as SPIR-V assembly for `spirv-as`:
```
OpCapability Kernel
OpCapability Addresses
OpCapability Int64
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %15 "k"
OpName %11 "lo"
OpName %12 "ov"
%3 = OpTypeInt 64 0
%4 = OpTypePointer CrossWorkgroup %3
%5 = OpTypeVoid
%6 = OpTypeFunction %5 %4 %4 %3 %3
%7 = OpTypeBool
%8 = OpConstantNull %3
%9 = OpConstant %3 1
%10 = OpTypeStruct %3 %3
%15 = OpFunction %5 None %6
%11 = OpFunctionParameter %4
%12 = OpFunctionParameter %4
%13 = OpFunctionParameter %3
%14 = OpFunctionParameter %3
%2 = OpLabel
%16 = OpUMulExtended %10 %13 %14
%17 = OpCompositeExtract %3 %16 0
%18 = OpCompositeExtract %3 %16 1
%19 = OpINotEqual %7 %18 %8
%20 = OpSelect %3 %19 %9 %8
OpStore %11 %17 Aligned 8
OpStore %12 %20 Aligned 8
OpReturn
OpFunctionEnd
```
The same SPIR-V comes out of the in-tree LLVM SPIR-V backend for this input, so any language frontend that emits `llvm.umul.with.overflow` hits it:
```llvm
define spir_kernel void @k(ptr addrspace(1) %lo, ptr addrspace(1) %ov, i64 %a, i64 %b) {
entry:
%r = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
%v = extractvalue { i64, i1 } %r, 0
%o = extractvalue { i64, i1 } %r, 1
%oz = zext i1 %o to i64
store i64 %v, ptr addrspace(1) %lo
store i64 %oz, ptr addrspace(1) %ov
ret void
}
```
llc -mtriple=spirv64-unknown-unknown umulo.ll -filetype=obj -o umulo.spv
Impact for us: clang emits `llvm.umul.with.overflow.i64` for a C++ `new T[n]` in device code, so any HIP or SYCL kernel that news an array fails to build. In chipStar all device code of a binary lands in one module, so the one unresolved symbol fails every kernel in the program.
Update: this is about to matter on a second path as well. KhronosGroup/SPIRV-LLVM-Translator#3977 changes `llvm-spirv` to lower `llvm.umul.with.overflow` to `OpUMulExtended` directly, instead of the `spirv.llvm_umul_with_overflow_*` helper function it emits today. That helper is the only reason SPIR-V produced by the translator still builds on a released IGC. If #3977 lands before IGC picks up #3963, modules coming from the translator will carry `OpUMulExtended` too, and hit the same undefined reference.
Contributor guide
Research direction
Reproduce the failure with the listed ocloc command and inspect external/llvm/llvm_preferred_version.cmake to confirm the translator branch IGC uses. Compare the SPIR-V reader handling of OpUMulExtended with KhronosGroup/SPIRV-LLVM-Translator#3963, and review IGC/BiFModule/Implementation/arithmetic.cl for the available overloads. Done means the supplied SPIR-V and affected device-code paths build without the unresolved signed-mangled symbol.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100