[llvm] [SPIR-V] Fix i8 pointer type for NULL events in OpEnqueueKernel (PR #201125)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 07:06:56 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/201125
>From d4e96f1d123c9e60c50598370fb79a07c356f39d Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Tue, 2 Jun 2026 16:03:54 +0200
Subject: [PATCH] [SPIR-V] Fix i8 pointer type for NULL events in
OpEnqueueKernel
---
llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 38 +++++++++++++------
.../SPIRV/transcoding/enqueue_kernel.ll | 6 +--
2 files changed, 28 insertions(+), 16 deletions(-)
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..2053b13882545 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),
@@ -103,7 +101,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];
More information about the llvm-commits
mailing list