[llvm] [SPIRV] Correctly map OpGenericCastToPtrExplicit builtins (PR #137189)

Victor Lomuller via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 24 07:53:23 PDT 2025


https://github.com/Naghasan created https://github.com/llvm/llvm-project/pull/137189

The __spirv_GenericCastToPtrExplicit_To* builtins and its equivalent OpenCL builtins (to_global, to_local and to_private) were mapped to OpGenericCastToPtr instead of OpGenericCastToPtrExplicit.

The patch now uses OpGenericCastToPtrExplicit for these builtins.

>From 51184b1be28087812d81a52789fdaddb5526ff91 Mon Sep 17 00:00:00 2001
From: Victor Lomuller <victor at codeplay.com>
Date: Thu, 24 Apr 2025 15:46:08 +0100
Subject: [PATCH] [SPIRV] Correctly map OpGenericCastToPtrExplicit builtins

The __spirv_GenericCastToPtrExplicit_To* builtins and
its equivalent OpenCL builtins (to_global, to_local and to_private)
were mapped to OpGenericCastToPtr instead of OpGenericCastToPtrExplicit.

The patch now uses OpGenericCastToPtrExplicit for these builtins.
---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp       | 29 ++++++++++++---
 llvm/lib/Target/SPIRV/SPIRVBuiltins.td        | 12 +++----
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   |  1 +
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 11 ------
 .../lib/Target/SPIRV/SPIRVSymbolicOperands.td |  1 +
 llvm/lib/Target/SPIRV/SPIRVUtils.h            | 13 +++++++
 .../SPIRV/transcoding/OpGenericCastToPtr.ll   | 36 +++++++++----------
 7 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index e090fb67b3231..78c0d252cb834 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1656,10 +1656,29 @@ static bool generateBarrierInst(const SPIRV::IncomingCall *Call,
 }
 
 static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call,
-                                  MachineIRBuilder &MIRBuilder) {
-  MIRBuilder.buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
-      .addDef(Call->ReturnRegister)
-      .addUse(Call->Arguments[0]);
+                                  MachineIRBuilder &MIRBuilder,
+                                  SPIRVGlobalRegistry *GR) {
+  // Lookup the instruction opcode in the TableGen records.
+  const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
+  unsigned Opcode =
+      SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
+
+  if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
+    SPIRV::StorageClass::StorageClass ResSC =
+        GR->getPointerStorageClass(Call->ReturnRegister);
+    if (!isGenericCastablePtr(ResSC))
+      return false;
+
+    MIRBuilder.buildInstr(Opcode)
+        .addDef(Call->ReturnRegister)
+        .addUse(GR->getSPIRVTypeID(Call->ReturnType))
+        .addUse(Call->Arguments[0])
+        .addImm(ResSC);
+  } else {
+    MIRBuilder.buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
+        .addDef(Call->ReturnRegister)
+        .addUse(Call->Arguments[0]);
+  }
   return true;
 }
 
@@ -2833,7 +2852,7 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
   case SPIRV::Barrier:
     return generateBarrierInst(Call.get(), MIRBuilder, GR);
   case SPIRV::CastToPtr:
-    return generateCastToPtrInst(Call.get(), MIRBuilder);
+    return generateCastToPtrInst(Call.get(), MIRBuilder, GR);
   case SPIRV::Dot:
   case SPIRV::IntegerDot:
     return generateDotOrFMulInst(DemangledCall, Call.get(), MIRBuilder, GR);
diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
index a3f27dde76b65..59cd38126cc01 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td
@@ -687,15 +687,15 @@ defm : DemangledNativeBuiltin<"__spirv_Load", OpenCL_std, LoadStore, 1, 3, OpLoa
 defm : DemangledNativeBuiltin<"__spirv_Store", OpenCL_std, LoadStore, 2, 4, OpStore>;
 
 // Address Space Qualifier Functions/Pointers Conversion Instructions:
-defm : DemangledNativeBuiltin<"to_global", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtr>;
-defm : DemangledNativeBuiltin<"to_local", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtr>;
-defm : DemangledNativeBuiltin<"to_private", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtr>;
+defm : DemangledNativeBuiltin<"to_global", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtrExplicit>;
+defm : DemangledNativeBuiltin<"to_local", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtrExplicit>;
+defm : DemangledNativeBuiltin<"to_private", OpenCL_std, CastToPtr, 1, 1, OpGenericCastToPtrExplicit>;
 defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtr_ToGlobal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
 defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtr_ToLocal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
 defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtr_ToPrivate", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
-defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToGlobal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
-defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToLocal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
-defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToPrivate", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtr>;
+defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToGlobal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtrExplicit>;
+defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToLocal", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtrExplicit>;
+defm : DemangledNativeBuiltin<"__spirv_GenericCastToPtrExplicit_ToPrivate", OpenCL_std, CastToPtr, 2, 2, OpGenericCastToPtrExplicit>;
 
 // Cooperative Matrix builtin records:
 defm : DemangledNativeBuiltin<"__spirv_CooperativeMatrixLoadKHR", OpenCL_std, CoopMatr, 2, 4, OpCooperativeMatrixLoadKHR>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index d274839af82eb..216c3e26be1bf 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -390,6 +390,7 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
         break;
       case SPIRV::OpPtrCastToGeneric:
       case SPIRV::OpGenericCastToPtr:
+      case SPIRV::OpGenericCastToPtrExplicit:
         validateAccessChain(STI, MRI, GR, MI);
         break;
       case SPIRV::OpPtrAccessChain:
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..47f8ace4f7d0b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1552,17 +1552,6 @@ bool SPIRVInstructionSelector::selectAtomicCmpXchg(Register ResVReg,
              .constrainAllUses(TII, TRI, RBI);
 }
 
-static bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC) {
-  switch (SC) {
-  case SPIRV::StorageClass::Workgroup:
-  case SPIRV::StorageClass::CrossWorkgroup:
-  case SPIRV::StorageClass::Function:
-    return true;
-  default:
-    return false;
-  }
-}
-
 static bool isUSMStorageClass(SPIRV::StorageClass::StorageClass SC) {
   switch (SC) {
   case SPIRV::StorageClass::DeviceOnlyINTEL:
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index afd3a5206926c..cc32200a0a261 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -1683,6 +1683,7 @@ defm InBoundsAccessChain : OpcodeOperand<66>;
 defm InBoundsPtrAccessChain : OpcodeOperand<70>;
 defm PtrCastToGeneric : OpcodeOperand<121>;
 defm GenericCastToPtr : OpcodeOperand<122>;
+defm GenericCastToPtrExplicit : OpcodeOperand<123>;
 defm Bitcast : OpcodeOperand<124>;
 defm ConvertPtrToU : OpcodeOperand<117>;
 defm ConvertUToPtr : OpcodeOperand<120>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 0498c7beb073c..ccf394de45c89 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -167,6 +167,19 @@ MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I);
 // terminators and debug instructions.
 MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB);
 
+// Returns true if a pointer to the storage class can be casted to/from a
+// pointer to the Generic storage class.
+constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC) {
+  switch (SC) {
+  case SPIRV::StorageClass::Workgroup:
+  case SPIRV::StorageClass::CrossWorkgroup:
+  case SPIRV::StorageClass::Function:
+    return true;
+  default:
+    return false;
+  }
+}
+
 // Convert a SPIR-V storage class to the corresponding LLVM IR address space.
 // TODO: maybe the following two functions should be handled in the subtarget
 // to allow for different OpenCL vs Vulkan handling.
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpGenericCastToPtr.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpGenericCastToPtr.ll
index 2cba0f6ebd74b..119dbe14446c1 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/OpGenericCastToPtr.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/OpGenericCastToPtr.ll
@@ -24,9 +24,9 @@
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#GlobalIntPtr]] %{{.*}} CrossWorkgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#LocalCharPtr]] %{{.*}} Workgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#PrivateIntPtr]] %{{.*}} Function
 ; CHECK-SPIRV:      OpFunctionEnd
 
 define spir_kernel void @test1(ptr addrspace(1) %_arg_GlobalA, ptr byval(%id) %_arg_GlobalId, ptr addrspace(3) %_arg_LocalA) {
@@ -52,9 +52,9 @@ entry:
 ; CHECK-SPIRV:      OpPtrCastToGeneric %[[#GenericIntPtr]]
 ; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericCharPtr]]
 ; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#GlobalIntPtr]] %{{.*}} CrossWorkgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#LocalCharPtr]] %{{.*}} Workgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#PrivateIntPtr]] %{{.*}} Function
 ; CHECK-SPIRV:      OpFunctionEnd
 
 define spir_kernel void @test2(ptr addrspace(1) %_arg_GlobalA, ptr byval(%id) %_arg_GlobalId, ptr addrspace(3) %_arg_LocalA) {
@@ -93,18 +93,9 @@ declare spir_func ptr @_Z10to_privatePv(ptr addrspace(4))
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
 ; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
-; CHECK-SPIRV:      OpFunctionEnd
-
-; CHECK-SPIRV:      OpFunction
-; CHECK-SPIRV:      OpPtrCastToGeneric %[[#GenericIntPtr]]
-; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericCharPtr]]
-; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#GlobalIntPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#LocalCharPtr]]
-; CHECK-SPIRV-NEXT: OpGenericCastToPtr %[[#PrivateIntPtr]]
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#GlobalIntPtr]] %{{.*}} CrossWorkgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#LocalCharPtr]] %{{.*}} Workgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#PrivateIntPtr]] %{{.*}} Function
 ; CHECK-SPIRV:      OpFunctionEnd
 
 define spir_kernel void @test3(ptr addrspace(1) %_arg_GlobalA, ptr byval(%id) %_arg_GlobalId, ptr addrspace(3) %_arg_LocalA) {
@@ -126,6 +117,15 @@ entry:
   ret void
 }
 
+; CHECK-SPIRV:      OpFunction
+; CHECK-SPIRV:      OpPtrCastToGeneric %[[#GenericIntPtr]]
+; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericCharPtr]]
+; CHECK-SPIRV-NEXT: OpPtrCastToGeneric %[[#GenericIntPtr]]
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#GlobalIntPtr]] %{{.*}} CrossWorkgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#LocalCharPtr]] %{{.*}} Workgroup
+; CHECK-SPIRV-NEXT: OpGenericCastToPtrExplicit %[[#PrivateIntPtr]] %{{.*}} Function
+; CHECK-SPIRV:      OpFunctionEnd
+
 define spir_kernel void @test4(ptr addrspace(1) %_arg_GlobalA, ptr byval(%id) %_arg_GlobalId, ptr addrspace(3) %_arg_LocalA) {
 entry:
   %var = alloca i32



More information about the llvm-commits mailing list