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

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 2 07:21:59 PST 2025


Author: Nick Sarnie
Date: 2025-12-02T15:21:55Z
New Revision: 87f4e809425da31b19a5a86833c3f1af4981cc99

URL: https://github.com/llvm/llvm-project/commit/87f4e809425da31b19a5a86833c3f1af4981cc99
DIFF: https://github.com/llvm/llvm-project/commit/87f4e809425da31b19a5a86833c3f1af4981cc99.diff

LOG: [SPIRV] Add support for CodeSectionINTEL storage class in legalizer (#167961)

The
[SPV_INTEL_function_pointers](https://github.com/intel/llvm/blob/sycl/sycl/doc/design/spirv-extensions/SPV_INTEL_function_pointers.asciidoc)
extension defines a new storage class `CodeSectionINTEL` that is
represented in LLVM IR as `addrspace(9)`.

Per the spec, it is basically not allowed to be casted to or interact
with pointers with other storage classes.

Add `addrspace(9)` as a known pointer type to the legalizer, and then
add some error cases for IR that is impossible to legalize.

Right now, if you try to run the backend on input with SPIR-V, basically
everything errors saying that it is unable to legalize because `ptr
addrspace(9)` is not considered a pointer type.

Ideally the FE should not generate the illegal IR or error out earlier,
but we should catch it before generating invalid SPIR-V.

---------

Signed-off-by: Nick Sarnie <nick.sarnie at intel.com>

Added: 
    llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
    llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
    llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
    llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
    llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-store.ll
    llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 9d5a685fdbc84..b5912c27316c9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -90,17 +90,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,
@@ -131,10 +133,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};
 
   auto &allowedVectorTypes = ST.isShader() ? allShaderVectors : allVectors;
 
@@ -246,15 +248,22 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
       .legalIf(vectorElementCountIsLessThanOrEqualTo(1, MaxVectorSize));
 
   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,
@@ -323,9 +332,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..58638578bb3f0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-addrspacecast.ll
@@ -0,0 +1,8 @@
+; 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)
+  %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..229f2234220ab
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-load.ll
@@ -0,0 +1,8 @@
+; RUN: not llc --global-isel %s -filetype=null 2>&1 | FileCheck %s
+target triple = "spirv64"
+
+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
new file mode 100644
index 0000000000000..f72b69b4fec81
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memcpy.ll
@@ -0,0 +1,8 @@
+; 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
+  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..b8102582bba74
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/GlobalISel/fn-ptr-memset.ll
@@ -0,0 +1,8 @@
+; 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)
+  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/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
new file mode 100644
index 0000000000000..da9771914b819
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_cmp.ll
@@ -0,0 +1,27 @@
+; 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 %[[ARG:.*]] "arg"
+
+; CHECK: %[[TyBool:.*]] = OpTypeBool
+
+; CHECK: %[[F1Ptr:.*]] = OpConstantFunctionPointerINTEL %{{.*}} %[[F1]]
+
+; CHECK: OpPtrEqual %[[TyBool]] %[[F1Ptr]] %[[ARG]]
+
+target triple = "spirv64"
+
+define spir_func void @f1() addrspace(9) {
+entry:
+  ret void
+}
+
+define spir_func i1 @foo(ptr addrspace(9) %arg) addrspace(9) {
+entry:
+  %a = icmp eq ptr addrspace(9) @f1, %arg
+  ret i1 %a
+}


        


More information about the llvm-commits mailing list