[llvm] [SPIR-V] Fix i8 pointer type for NULL events in OpEnqueueKernel (PR #201125)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 07:05:21 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Arseniy Obolenskiy (aobolensk)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/201125.diff
2 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp (+26-12)
- (modified) llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll (+4-5)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index 9bc29dd0103a6..7c32914e609eb 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2975,27 +2975,41 @@ static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call,
// 2. Process all arguments which requered preparation.
// 2.1 Events - use Call arguments, or use dummy nulls in case of absence of
// events
+
+ // Per SPIR-V spec, OpEnqueueKernel's Wait Events / Ret Event operands
+ // must be pointers to OpTypeDeviceEvent. Build the LLVM TargetExtType
+ // for spirv.DeviceEvent so getOrCreateSPIRVPointerType can register
+ // both the SPIR-V type and the LLVM-side mapping; deriving the pointer
+ // from an opaque LLVM PointerType would lose the pointee and deduce
+ // to <Generic i8*>.
+ auto BuildDeviceEventNullPtr = [&]() {
+ LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
+ Type *DeviceEventTy = TargetExtType::get(Ctx, "spirv.DeviceEvent");
+ SPIRVTypeInst DeviceEventPtrTy = GR->getOrCreateSPIRVPointerType(
+ DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
+ return GR->getOrCreateConstNullPtr(MIRBuilder, DeviceEventPtrTy);
+ };
+
Register NumEventsReg;
Register WaitEventsReg;
Register RetEventReg;
if (HasEvents) {
+ auto IsNullEvent = [&](Register R) {
+ MachineInstr *Def = getDefInstrMaybeConstant(R, MRI);
+ return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
+ Def->getOperand(1).getCImm()->isZero();
+ };
+
NumEventsReg = Call->Arguments[NumEventsIdx];
WaitEventsReg = Call->Arguments[WaitEventsIdx];
RetEventReg = Call->Arguments[RetEventIdx];
+ if (IsNullEvent(WaitEventsReg))
+ WaitEventsReg = BuildDeviceEventNullPtr();
+ if (IsNullEvent(RetEventReg))
+ RetEventReg = BuildDeviceEventNullPtr();
} else {
NumEventsReg = buildConstantIntReg32(0, MIRBuilder, GR);
- // Per SPIR-V spec, OpEnqueueKernel's Wait Events / Ret Event operands
- // must be pointers to OpTypeDeviceEvent. Build the LLVM TargetExtType
- // for spirv.DeviceEvent so getOrCreateSPIRVPointerType can register
- // both the SPIR-V type and the LLVM-side mapping; deriving the pointer
- // from an opaque LLVM PointerType would lose the pointee and deduce
- // to <Generic i8*>.
- LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
- Type *DeviceEventTy = TargetExtType::get(Ctx, "spirv.DeviceEvent");
- SPIRVTypeInst DeviceEventPtrTy = GR->getOrCreateSPIRVPointerType(
- DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
- Register NullPtr =
- GR->getOrCreateConstNullPtr(MIRBuilder, DeviceEventPtrTy);
+ Register NullPtr = BuildDeviceEventNullPtr();
WaitEventsReg = NullPtr;
RetEventReg = NullPtr;
}
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll
index 2d7e73d71094e..ce51b91b775ff 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll
@@ -24,7 +24,6 @@
; CHECK-DAG: %[[#TypeNDRangeStruct:]] = OpTypeStruct %[[#typeInt32]] %[[#Array3x64]] %[[#Array3x64]] %[[#Array3x64]]
; CHECK-DAG: %[[#pointerInt8:]] = OpTypePointer Generic %[[#typeInt8]]
-; CHECK-DAG: %[[#nullPtrInt8:]] = OpConstantNull %[[#pointerInt8]]
; CHECK-DAG: %[[#nullArray3x64:]] = OpConstantNull %[[#Array3x64]]
; CHECK-DAG: %[[#typeEvent:]] = OpTypeDeviceEvent
@@ -60,9 +59,8 @@
;;
;; const size_t gs[] = {1,2,4};
;;
-; TODO: Fix int8 type came from clang in case of NULL events passed in opencl's enqueue_kernel.
;; // enqueue empty kernel
-; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue:]] %[[#Num1i32]] %[[#NDRange3]] %[[#Num0i32]] %[[#nullPtrInt8]] %[[#nullPtrInt8]] %[[#InvokeKernel1]] %[[#]] %[[#Num16i32]] %[[#Num8i32]]
+; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue:]] %[[#Num1i32]] %[[#NDRange3]] %[[#Num0i32]] %[[#nullPtrEvent]] %[[#nullPtrEvent]] %[[#InvokeKernel1]] %[[#]] %[[#Num16i32]] %[[#Num8i32]]
;; enqueue_kernel(default_queue,
;; CLK_ENQUEUE_FLAGS_WAIT_KERNEL,
;; ndrange_3D(gs),
@@ -86,7 +84,8 @@
;; });
;;
;; // events, var arg
-; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num2i32]] %[[#event_wait_list2:]] %[[#event2]] %[[#InvokeKernel4]] %[[#]] %[[#Num16i32]] %[[#Num8i32]] %[[#]]
+; CHECK: %[[#event_wait_list2:]] = OpPtrCastToGeneric %[[#]] %[[#]]
+; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num2i32]] %[[#event_wait_list2]] %[[#event2]] %[[#InvokeKernel4]] %[[#]] %[[#Num16i32]] %[[#Num8i32]] %[[#]]
;; char c;
;; enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
;; ^(local void *p) {
@@ -103,7 +102,7 @@
;; 101, 102, 104);
;;
;; // null event, no var args
-; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num0i32]] %[[#nullPtrInt8]] %[[#event2]] %[[#InvokeKernel6]] %[[#]] %[[#Num36i32]] %[[#Num8i32]]
+; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num0i32]] %[[#nullPtrEvent]] %[[#event2]] %[[#InvokeKernel6]] %[[#]] %[[#Num36i32]] %[[#Num8i32]]
;; enqueue_kernel(default_queue, flags, ndrange, 0, NULL, &clk_event,
;; ^(void) {
;; a[i] = b[i];
``````````
</details>
https://github.com/llvm/llvm-project/pull/201125
More information about the llvm-commits
mailing list