Author: Arseniy Obolenskiy Date: 2026-10-12T11:35:22+02:00 New Revision: 61b4fea0090f087c65031b0956748edb70811834
URL: https://github.com/llvm/llvm-project/commit/61b4fea0090f087c65031b0956748edb70811834 DIFF: https://github.com/llvm/llvm-project/commit/61b4fea0090f087c65031b0956748edb70811834.diff LOG: [SPIR-V] Fix enqueue_kernel crash on clang -O0 local sizes (#230924) Clang -O0 passes local sizes as a pointer to the first element, not to the array Added: clang/test/CodeGenOpenCL/spirv-enqueue-kernel-local-size.cl Modified: llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll Removed: ################################################################################ diff --git a/clang/test/CodeGenOpenCL/spirv-enqueue-kernel-local-size.cl b/clang/test/CodeGenOpenCL/spirv-enqueue-kernel-local-size.cl new file mode 100644 index 00000000000000..806cc854582dba --- /dev/null +++ b/clang/test/CodeGenOpenCL/spirv-enqueue-kernel-local-size.cl @@ -0,0 +1,24 @@ +// REQUIRES: spirv-registered-target +// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -emit-llvm -o - -triple spirv64-unknown-unknown %s | FileCheck %s +// RUN: %clang_cc1 -cl-std=CL2.0 -O0 -S -o - -triple spirv64-unknown-unknown -mllvm --spirv-ext=+SPV_INTEL_function_pointers %s | FileCheck %s --check-prefix=SPIRV + +// Check that local sizes are passed as a pointer to the first array element +// and that the SPIR-V backend lowers this form. + +typedef struct {int a;} ndrange_t; + +kernel void test(queue_t q) { + ndrange_t nd; +// CHECK-LABEL: define {{.*}} void @__clang_ocl_kern_imp_test( +// CHECK: %[[SIZES:.*]] = alloca [2 x i64] +// CHECK: %[[ELEM:.*]] = getelementptr [2 x i64], ptr %[[SIZES]], i32 0, i32 0 +// CHECK: call spir_func i32 @__enqueue_kernel_varargs({{.*}}, i32 2, ptr %[[ELEM]]) + +// SPIRV-DAG: %[[#INT32:]] = OpTypeInt 32 0 +// SPIRV-DAG: %[[#ZERO:]] = OpConstantNull %[[#INT32]] +// SPIRV: %[[#ELEM:]] = OpPtrAccessChain %[[#]] %[[#]] %[[#ZERO]] %[[#ZERO]] +// SPIRV: %[[#SIZE0:]] = OpPtrAccessChain %[[#]] %[[#ELEM]] %[[#ZERO]]{{$}} +// SPIRV-NEXT: %[[#SIZE1:]] = OpPtrAccessChain %[[#]] %[[#ELEM]] %[[#]]{{$}} +// SPIRV-NEXT: OpEnqueueKernel {{.*}} %[[#SIZE0]] %[[#SIZE1]]{{$}} + enqueue_kernel(q, 0, nd, ^(local void *p1, local void *p2){}, 101u, 102u); +} diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 245fe1d89ccf5a..43598565561c3b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -3176,16 +3176,20 @@ static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, uint64_t NumElem = ConstOp.getCImm()->getValue().getZExtValue(); Register LocalSizeArrayReg = Call->Arguments[LocalSizeElemPtrIdx]; + SPIRVTypeInst PointeeTy = + GR->getPointeeType(GR->getSPIRVTypeForVReg(LocalSizeArrayReg)); + bool IsArrayPtr = PointeeTy && PointeeTy->getOpcode() == SPIRV::OpTypeArray; for (unsigned i = 0; i < NumElem; ++i) { Register Reg = MRI->createVirtualRegister(&SPIRV::pIDRegClass); auto GEPInst = MIRBuilder.buildIntrinsic( Intrinsic::spv_gep, ArrayRef<Register>{Reg}, true, false); GEPInst - .addImm(0) // In bound. - .addUse(LocalSizeArrayReg) // Base pointer. - .addUse(buildConstantIntReg32(0, MIRBuilder, GR)) // Indices. - .addUse(buildConstantIntReg32(i, MIRBuilder, GR)); + .addImm(0) // In bound. + .addUse(LocalSizeArrayReg); // Base pointer. + if (IsArrayPtr) + GEPInst.addUse(buildConstantIntReg32(0, MIRBuilder, GR)); + GEPInst.addUse(buildConstantIntReg32(i, MIRBuilder, GR)); LocalSizes.push_back(Reg); } } diff --git a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll index 592e387db851b5..b5f17332c98913 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll @@ -110,6 +110,13 @@ ;; }, ;; 101, 102, 104); ;; +;; // same, but local sizes passed as a pointer to the first element +; CHECK: %[[#ElemPtr:]] = OpPtrAccessChain %[[#]] %[[#]] %[[#Num0i32]] %[[#Num0i32]] +; CHECK: %[[#LocalSize0:]] = OpPtrAccessChain %[[#]] %[[#ElemPtr]] %[[#Num0i32]]{{$}} +; CHECK-NEXT: %[[#LocalSize1:]] = OpPtrAccessChain %[[#]] %[[#ElemPtr]] %[[#Num1i32]]{{$}} +; CHECK-NEXT: %[[#LocalSize2:]] = OpPtrAccessChain %[[#]] %[[#ElemPtr]] %[[#Num2i32]]{{$}} +; CHECK-NEXT: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num0i32]] %[[#nullPtrEvent]] %[[#nullPtrEvent]] %[[#InvokeKernel5Ptr]] %[[#]] %[[#Num16i32]] %[[#Num8i32]] %[[#LocalSize0]] %[[#LocalSize1]] %[[#LocalSize2]] +;; ;; // null event, no var args ; CHECK: %[[#]] = OpEnqueueKernel %[[#typeInt32]] %[[#default_queue]] %[[#Num0i32]] %[[#]] %[[#Num0i32]] %[[#nullPtrEvent]] %[[#event2]] %[[#InvokeKernel6Ptr]] %[[#]] %[[#Num36i32]] %[[#Num8i32]] ;; enqueue_kernel(default_queue, flags, ndrange, 0, NULL, &clk_event, @@ -198,6 +205,8 @@ entry: %10 = getelementptr inbounds i8, ptr %block_sizes15.i, i64 16 store i64 104, ptr %10, align 8 %11 = call spir_func i32 @__enqueue_kernel_varargs(target("spirv.Queue") %default_queue, i32 0, ptr %tmp14.i, ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_5_kernel to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @__block_literal_global.2 to ptr addrspace(4)), i32 3, ptr %block_sizes15.i) + %elem_sizes = getelementptr [3 x i64], ptr %block_sizes15.i, i32 0, i32 0 + %elem_call = call spir_func i32 @__enqueue_kernel_varargs(target("spirv.Queue") %default_queue, i32 0, ptr %tmp14.i, ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_5_kernel to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @__block_literal_global.2 to ptr addrspace(4)), i32 3, ptr %elem_sizes) store i32 36, ptr %block17.i, align 8 %block.align19.i = getelementptr inbounds i8, ptr %block17.i, i64 4 store i32 8, ptr %block.align19.i, align 4 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
