[llvm] [SPIRV] Add support for CodeSectionINTEL storage class in legalizer (PR #167961)

Nick Sarnie via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 17 08:00:09 PST 2025


https://github.com/sarnex updated https://github.com/llvm/llvm-project/pull/167961

>From d7eff11900eb5eae01a16b8facf33e770553a76e Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Thu, 13 Nov 2025 13:46:11 -0800
Subject: [PATCH 1/2] [SPIRV] Add support for CodeSectionINTEL addrspace in
 legalizer

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
 llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp  | 40 ++++++++++++-------
 .../SPIRV/GlobalISel/fn-ptr-addrspacecast.ll  |  9 +++++
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll   |  9 +++++
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll |  9 +++++
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll |  9 +++++
 .../SPV_INTEL_function_pointers/fp_cmp.ll     | 34 ++++++++++++++++
 6 files changed, 96 insertions(+), 14 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 53074ea3b2597..822fee8a9da35 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -84,17 +84,19 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
   const LLT p6 = LLT::pointer(6, PSize); // SPV_INTEL_usm_storage_classes (Host)
   const LLT p7 = LLT::pointer(7, PSize); // Input
   const LLT p8 = LLT::pointer(8, PSize); // Output
+  const LLT p9 =
+      LLT::pointer(9, PSize); // CodeSectionINTEL, SPV_INTEL_function_pointers
   const LLT p10 = LLT::pointer(10, PSize); // Private
   const LLT p11 = LLT::pointer(11, PSize); // StorageBuffer
   const LLT p12 = LLT::pointer(12, PSize); // Uniform
 
   // TODO: remove copy-pasting here by using concatenation in some way.
   auto allPtrsScalarsAndVectors = {
-      p0,    p1,    p2,    p3,     p4,     p5,    p6,    p7,    p8,
-      p10,   p11,   p12,   s1,     s8,     s16,   s32,   s64,   v2s1,
-      v2s8,  v2s16, v2s32, v2s64,  v3s1,   v3s8,  v3s16, v3s32, v3s64,
-      v4s1,  v4s8,  v4s16, v4s32,  v4s64,  v8s1,  v8s8,  v8s16, v8s32,
-      v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
+      p0,    p1,    p2,    p3,    p4,     p5,     p6,    p7,    p8,
+      p9,    p10,   p11,   p12,   s1,     s8,     s16,   s32,   s64,
+      v2s1,  v2s8,  v2s16, v2s32, v2s64,  v3s1,   v3s8,  v3s16, v3s32,
+      v3s64, v4s1,  v4s8,  v4s16, v4s32,  v4s64,  v8s1,  v8s8,  v8s16,
+      v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
 
   auto allVectors = {v2s1,  v2s8,   v2s16,  v2s32, v2s64, v3s1,  v3s8,
                      v3s16, v3s32,  v3s64,  v4s1,  v4s8,  v4s16, v4s32,
@@ -121,10 +123,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
       s16,   s32,   s64,   v2s16, v2s32, v2s64, v3s16,  v3s32,  v3s64,
       v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
 
-  auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1,  p2,  p3,
-                                       p4, p5,  p6,  p7,  p8, p10, p11, p12};
+  auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1,  p2,  p3, p4,
+                                       p5, p6,  p7,  p8,  p9, p10, p11, p12};
 
-  auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11, p12};
+  auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12};
 
   bool IsExtendedInts =
       ST.canUseExtension(
@@ -177,15 +179,22 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
   getActionDefinitionsBuilder(G_UNMERGE_VALUES).alwaysLegal();
 
   getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE})
+      .unsupportedIf(LegalityPredicates::any(typeIs(0, p9), typeIs(1, p9)))
       .legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allPtrs)));
 
-  getActionDefinitionsBuilder(G_MEMSET).legalIf(
-      all(typeInSet(0, allPtrs), typeInSet(1, allIntScalars)));
+  getActionDefinitionsBuilder(G_MEMSET)
+      .unsupportedIf(typeIs(0, p9))
+      .legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allIntScalars)));
 
   getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
+      .unsupportedIf(
+          LegalityPredicates::any(all(typeIs(0, p9), typeIsNot(1, p9)),
+                                  all(typeIsNot(0, p9), typeIs(1, p9))))
       .legalForCartesianProduct(allPtrs, allPtrs);
 
-  getActionDefinitionsBuilder({G_LOAD, G_STORE}).legalIf(typeInSet(1, allPtrs));
+  getActionDefinitionsBuilder({G_LOAD, G_STORE})
+      .unsupportedIf(typeIs(1, p9))
+      .legalIf(typeInSet(1, allPtrs));
 
   getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS,
                                G_BITREVERSE, G_SADDSAT, G_UADDSAT, G_SSUBSAT,
@@ -247,9 +256,12 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
 
   // ST.canDirectlyComparePointers() for pointer args is supported in
   // legalizeCustom().
-  getActionDefinitionsBuilder(G_ICMP).customIf(
-      all(typeInSet(0, allBoolScalarsAndVectors),
-          typeInSet(1, allPtrsScalarsAndVectors)));
+  getActionDefinitionsBuilder(G_ICMP)
+      .unsupportedIf(LegalityPredicates::any(
+          all(typeIs(0, p9), typeInSet(1, allPtrs), typeIsNot(1, p9)),
+          all(typeInSet(0, allPtrs), typeIsNot(0, p9), typeIs(1, p9))))
+      .customIf(all(typeInSet(0, allBoolScalarsAndVectors),
+                    typeInSet(1, allPtrsScalarsAndVectors)));
 
   getActionDefinitionsBuilder(G_FCMP).legalIf(
       all(typeInSet(0, allBoolScalarsAndVectors),
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
new file mode 100644
index 0000000000000..62f9c7f06b937
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
@@ -0,0 +1,9 @@
+; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
+target triple = "spirv64-intel"
+
+define void @addrspacecast(ptr addrspace(9) %a) {
+; CHECK: unable to legalize instruction: %{{.*}}:pid(p4) = G_ADDRSPACE_CAST %{{.*}}:pid(p9)
+  %res1 = addrspacecast ptr addrspace(9) %a to ptr addrspace(4)
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
new file mode 100644
index 0000000000000..888560d53a7ae
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
@@ -0,0 +1,9 @@
+; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
+target triple = "spirv64-intel"
+
+define void @memset(ptr addrspace(9) %a) {
+; CHECK: unable to legalize instruction: %{{.*}}:iid(s32) = G_LOAD %{{.*}}:pid(p9) 
+  %val = load i32, ptr addrspace(9) %a
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
new file mode 100644
index 0000000000000..26566e50f1db2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
@@ -0,0 +1,9 @@
+; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
+target triple = "spirv64-intel"
+
+define void @memcpy(ptr addrspace(9) %a) {
+; CHECK: unable to legalize instruction: G_MEMCPY %{{.*}}:pid(p9), %{{.*}}:pid(p0), %{{.*}}:iid(s64), 0
+  call void @llvm.memcpy.p9.p0.i64(ptr addrspace(9) %a, ptr null, i32 1, i1 0)
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
new file mode 100644
index 0000000000000..3dd4ef0107495
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
@@ -0,0 +1,9 @@
+; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
+target triple = "spirv64-intel"
+
+define void @memset(ptr addrspace(9) %a) {
+; CHECK: unable to legalize instruction: G_MEMSET %{{.*}}:pid(p9), %{{.*}}:iid(s8), %{{.*}}:iid(s64)
+  call void @llvm.memset.p9.i32(ptr addrspace(9) %a, i8 0, i32 1, i1 0)
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
new file mode 100644
index 0000000000000..6b345f708442c
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
@@ -0,0 +1,34 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-intel --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-intel %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpCapability FunctionPointersINTEL
+; CHECK: OpExtension "SPV_INTEL_function_pointers"
+
+; CHECK: OpName %[[F1:.*]] "f1"
+; CHECK: OpName %[[F2:.*]] "f2"
+
+; CHECK: %[[TyBool:.*]] = OpTypeBool
+
+; CHECK %[[F1Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F2]]
+; CHECK %[[F2Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F2]]
+
+; CHECK OpPtrEqual %[[TyBool]] %[[F1Ptr]] %[[F2Ptr]]
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
+target triple = "spirv64-intel"
+
+define spir_func void @f1() addrspace(9) {
+entry:
+  ret void
+}
+
+define spir_func void @f2() addrspace(9) {
+entry:
+  ret void
+}
+
+define spir_kernel void @foo() addrspace(9) {
+entry:
+  %a = icmp eq ptr addrspace(9) @f1, @f2
+  ret void
+}

>From 43bd25e0f65020b071045dbd2b4b5f0f6052d210 Mon Sep 17 00:00:00 2001
From: Nick Sarnie <nick.sarnie at intel.com>
Date: Mon, 17 Nov 2025 07:59:23 -0800
Subject: [PATCH 2/2] address feedback

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>
---
 .../SPIRV/GlobalISel/fn-ptr-addrspacecast.ll  |  5 ++--
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll   |  7 +++---
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll |  5 ++--
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll |  5 ++--
 .../CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll  |  8 ++++++
 .../SPV_INTEL_function_pointers/fp_cmp.ll     | 25 +++++++------------
 6 files changed, 26 insertions(+), 29 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll

diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
index 62f9c7f06b937..58638578bb3f0 100644
--- a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
@@ -1,6 +1,5 @@
-; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
-target triple = "spirv64-intel"
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
 
 define void @addrspacecast(ptr addrspace(9) %a) {
 ; CHECK: unable to legalize instruction: %{{.*}}:pid(p4) = G_ADDRSPACE_CAST %{{.*}}:pid(p9)
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
index 888560d53a7ae..229f2234220ab 100644
--- a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
@@ -1,8 +1,7 @@
-; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
-target triple = "spirv64-intel"
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
 
-define void @memset(ptr addrspace(9) %a) {
+define void @do_load(ptr addrspace(9) %a) {
 ; CHECK: unable to legalize instruction: %{{.*}}:iid(s32) = G_LOAD %{{.*}}:pid(p9) 
   %val = load i32, ptr addrspace(9) %a
   ret void
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
index 26566e50f1db2..f72b69b4fec81 100644
--- a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
@@ -1,6 +1,5 @@
-; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
-target triple = "spirv64-intel"
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
 
 define void @memcpy(ptr addrspace(9) %a) {
 ; CHECK: unable to legalize instruction: G_MEMCPY %{{.*}}:pid(p9), %{{.*}}:pid(p0), %{{.*}}:iid(s64), 0
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
index 3dd4ef0107495..b8102582bba74 100644
--- a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
@@ -1,6 +1,5 @@
-; RUN: not llc --global-isel %s -o /dev/null 2>&1 | FileCheck %s
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
-target triple = "spirv64-intel"
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
 
 define void @memset(ptr addrspace(9) %a) {
 ; CHECK: unable to legalize instruction: G_MEMSET %{{.*}}:pid(p9), %{{.*}}:iid(s8), %{{.*}}:iid(s64)
diff --git a/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll
new file mode 100644
index 0000000000000..c00f15e82f2fe
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll
@@ -0,0 +1,8 @@
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
+
+define void @do_store(ptr addrspace(9) %a) {
+; CHECK: unable to legalize instruction: G_STORE %{{.*}}:iid(s32), %{{.*}}:pid(p9) 
+  store i32 5, ptr addrspace(9) %a
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
index 6b345f708442c..da9771914b819 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
@@ -1,34 +1,27 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-intel --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
-; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-intel %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 %s -o - -filetype=obj | spirv-val %}
 
 ; CHECK-DAG: OpCapability FunctionPointersINTEL
 ; CHECK: OpExtension "SPV_INTEL_function_pointers"
 
 ; CHECK: OpName %[[F1:.*]] "f1"
-; CHECK: OpName %[[F2:.*]] "f2"
+; CHECK: OpName %[[ARG:.*]] "arg"
 
 ; CHECK: %[[TyBool:.*]] = OpTypeBool
 
-; CHECK %[[F1Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F2]]
-; CHECK %[[F2Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F2]]
+; CHECK: %[[F1Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F1]]
 
-; CHECK OpPtrEqual %[[TyBool]] %[[F1Ptr]] %[[F2Ptr]]
+; CHECK: OpPtrEqual %[[TyBool]] %[[F1Ptr]] %[[ARG]]
 
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1-P9-A0"
-target triple = "spirv64-intel"
+target triple = "spirv64"
 
 define spir_func void @f1() addrspace(9) {
 entry:
   ret void
 }
 
-define spir_func void @f2() addrspace(9) {
+define spir_func i1 @foo(ptr addrspace(9) %arg) addrspace(9) {
 entry:
-  ret void
-}
-
-define spir_kernel void @foo() addrspace(9) {
-entry:
-  %a = icmp eq ptr addrspace(9) @f1, @f2
-  ret void
+  %a = icmp eq ptr addrspace(9) @f1, %arg
+  ret i1 %a
 }



More information about the llvm-commits mailing list