[llvm] [SPIRV] fix `alloca` -> `OpVariable` lowering (PR #164175)

Simeon David Schaub via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 20 02:03:28 PDT 2025


https://github.com/simeonschaub updated https://github.com/llvm/llvm-project/pull/164175

>From dfa5dfe008054afae2903cef05ce0926d4315360 Mon Sep 17 00:00:00 2001
From: Simeon David Schaub <simeon at schaub.rocks>
Date: Sun, 19 Oct 2025 19:49:09 +0200
Subject: [PATCH 1/3] [SPIRV] fix `alloca` -> `OpVariable` lowering

fixes #163777

Test was written with help from Copilot
---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp |  2 +-
 .../CodeGen/SPIRV/alloca-aggregate-type.ll    | 36 +++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/alloca-aggregate-type.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index c6c618218006a..678ecfe32174d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1706,7 +1706,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
       return;
     } else if (isTodoType(Pointer)) {
       eraseTodoType(Pointer);
-      if (!isa<CallInst>(Pointer) && !isa<GetElementPtrInst>(Pointer)) {
+      if (!isa<CallInst>(Pointer) && !isa<GetElementPtrInst>(Pointer) && !isa<AllocaInst>(Pointer)) {
         //  If this wouldn't be the first spv_ptrcast but existing type info is
         //  uncomplete, update spv_assign_ptr_type arguments.
         if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Pointer)) {
diff --git a/llvm/test/CodeGen/SPIRV/alloca-aggregate-type.ll b/llvm/test/CodeGen/SPIRV/alloca-aggregate-type.ll
new file mode 100644
index 0000000000000..82cbae2d8d908
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/alloca-aggregate-type.ll
@@ -0,0 +1,36 @@
+; Test that alloca with aggregate type generates correct OpVariable
+; with the array type as the pointee, not a pointer-to-pointer type
+;
+; This test verifies that when we have an alloca of an array containing
+; structs with pointers, the OpVariable uses the correct array type
+; instead of incorrectly using a pointer-to-pointer type.
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#Int8:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#Int64:]] = OpTypeInt 64 0
+; CHECK-DAG: %[[#Int32:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#One:]] = OpConstant %[[#Int32]] 1
+; CHECK-DAG: %[[#Two:]] = OpConstant %[[#Int32]] 2
+; CHECK-DAG: %[[#PtrCross:]] = OpTypePointer CrossWorkgroup %[[#Int8]]
+; CHECK-DAG: %[[#Array1:]] = OpTypeArray %[[#Int64]] %[[#One]]
+; CHECK-DAG: %[[#Struct1:]] = OpTypeStruct %[[#PtrCross]] %[[#Int64]] %[[#Array1]] %[[#Int64]]
+; CHECK-DAG: %[[#Array2:]] = OpTypeArray %[[#Array1]] %[[#Two]]
+; CHECK-DAG: %[[#Struct2:]] = OpTypeStruct %[[#Struct1]] %[[#Array2]]
+; CHECK-DAG: %[[#Struct3:]] = OpTypeStruct %[[#Struct2]]
+; CHECK-DAG: %[[#ArrayStruct:]] = OpTypeArray %[[#Struct3]] %[[#One]]
+; CHECK-DAG: %[[#PtrFunc:]] = OpTypePointer Function %[[#ArrayStruct]]
+
+; Verify OpVariable uses the array type, not pointer-to-pointer
+; CHECK: %[[#Var:]] = OpVariable %[[#PtrFunc]] Function
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
+target triple = "spirv64-unknown-unknown"
+
+define spir_kernel void @test_alloca_aggregate() local_unnamed_addr {
+entry:
+  %y = alloca [1 x { { { ptr addrspace(1), i64, [1 x i64], i64 }, [2 x [1 x i64]] } }], align 8
+  %ptr = load ptr addrspace(1), ptr %y, align 8
+  ret void
+}

>From 6546c09d8bb42fa84c2b16c2ce802f9064c8ed6d Mon Sep 17 00:00:00 2001
From: Simeon David Schaub <simeon at schaub.rocks>
Date: Sun, 19 Oct 2025 21:44:54 +0200
Subject: [PATCH 2/3] fix formatting

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 678ecfe32174d..1913394ef4ec5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1706,7 +1706,8 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
       return;
     } else if (isTodoType(Pointer)) {
       eraseTodoType(Pointer);
-      if (!isa<CallInst>(Pointer) && !isa<GetElementPtrInst>(Pointer) && !isa<AllocaInst>(Pointer)) {
+      if (!isa<CallInst>(Pointer) && !isa<GetElementPtrInst>(Pointer) &&
+          !isa<AllocaInst>(Pointer)) {
         //  If this wouldn't be the first spv_ptrcast but existing type info is
         //  uncomplete, update spv_assign_ptr_type arguments.
         if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Pointer)) {

>From 52c7c1c61bc70fca6a527ce41521a99eb6f76b35 Mon Sep 17 00:00:00 2001
From: Simeon David Schaub <simeon at schaub.rocks>
Date: Mon, 20 Oct 2025 11:02:31 +0200
Subject: [PATCH 3/3] fix `fp_const` FileCheck

---
 .../SPV_INTEL_function_pointers/fp_const.ll     | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll
index b96da631c0a85..35adc03aec7fd 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll
@@ -8,17 +8,22 @@
 ; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid
 ; CHECK-DAG: %[[TyInt64:.*]] = OpTypeInt 64 0
 ; CHECK-DAG: %[[TyFun:.*]] = OpTypeFunction %[[TyInt64]] %[[TyInt64]]
-; CHECK-DAG: %[[TyPtrFunCodeSection:.*]] = OpTypePointer CodeSectionINTEL %[[TyFun]]
-; CHECK-DAG: %[[ConstFunFp:.*]] = OpConstantFunctionPointerINTEL %[[TyPtrFunCodeSection]] %[[DefFunFp:.*]]
 ; CHECK-DAG: %[[TyPtrFun:.*]] = OpTypePointer Function %[[TyFun]]
 ; CHECK-DAG: %[[TyPtrPtrFun:.*]] = OpTypePointer Function %[[TyPtrFun]]
+; CHECK-DAG: %[[TyInt8:.*]] = OpTypeInt 8 0
+; CHECK-DAG: %[[TyPtrInt8:.*]] = OpTypePointer Function %[[TyInt8]]
+; CHECK-DAG: %[[TyPtrPtrInt8:.*]] = OpTypePointer Function %[[TyPtrInt8]]
+; CHECK-DAG: %[[TyPtrFunCodeSection:.*]] = OpTypePointer CodeSectionINTEL %[[TyFun]]
+; CHECK-DAG: %[[ConstFunFp:.*]] = OpConstantFunctionPointerINTEL %[[TyPtrFunCodeSection]] %[[DefFunFp:.*]]
 ; CHECK: OpFunction
-; CHECK: %[[Var:.*]] = OpVariable %[[TyPtrPtrFun]] Function
-; CHECK: OpStore %[[Var]] %[[ConstFunFp]]
-; CHECK: %[[FP:.*]] = OpLoad %[[TyPtrFun]] %[[Var]]
+; CHECK: %[[Var:.*]] = OpVariable %[[TyPtrPtrInt8]] Function
+; CHECK: %[[VarStore:.*]] = OpBitcast %[[TyPtrPtrFun]] %[[Var]]
+; CHECK: OpStore %[[VarStore]] %[[ConstFunFp]]
+; CHECK: %[[VarLoad:.*]] = OpBitcast %[[TyPtrPtrFun]] %[[Var]]
+; CHECK: %[[FP:.*]] = OpLoad %[[TyPtrFun]] %[[VarLoad]]
 ; CHECK: OpFunctionPointerCallINTEL %[[TyInt64]] %[[FP]] %[[#]]
 ; CHECK: OpFunctionEnd
- 
+
 ; CHECK: %[[DefFunFp]] = OpFunction %[[TyInt64]] None %[[TyFun]]
 
 target triple = "spir64-unknown-unknown"



More information about the llvm-commits mailing list