[llvm] 8175190 - [SPIR-V] Emit proper pointer type for OpenCL kernel arguments (#67726)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 18 20:51:57 PDT 2023


Author: Michal Paszkowski
Date: 2023-10-18T20:51:53-07:00
New Revision: 817519058a986794e6acc06e4386fa183c4472a0

URL: https://github.com/llvm/llvm-project/commit/817519058a986794e6acc06e4386fa183c4472a0
DIFF: https://github.com/llvm/llvm-project/commit/817519058a986794e6acc06e4386fa183c4472a0.diff

LOG: [SPIR-V] Emit proper pointer type for OpenCL kernel arguments (#67726)

Added: 
    llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll
    llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll
    llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
    llvm/lib/Target/SPIRV/SPIRVBuiltins.h
    llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
    llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
    llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
    llvm/lib/Target/SPIRV/SPIRVUtils.cpp
    llvm/lib/Target/SPIRV/SPIRVUtils.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index b4452d0f46a3475..d6354876b558744 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -2010,60 +2010,6 @@ static Type *parseTypeString(const StringRef Name, LLVMContext &Context) {
   llvm_unreachable("Unable to recognize type!");
 }
 
-static const TargetExtType *parseToTargetExtType(const Type *OpaqueType,
-                                                 MachineIRBuilder &MIRBuilder) {
-  assert(isSpecialOpaqueType(OpaqueType) &&
-         "Not a SPIR-V/OpenCL special opaque type!");
-  assert(!OpaqueType->isTargetExtTy() &&
-         "This already is SPIR-V/OpenCL TargetExtType!");
-
-  StringRef NameWithParameters = OpaqueType->getStructName();
-
-  // Pointers-to-opaque-structs representing OpenCL types are first translated
-  // to equivalent SPIR-V types. OpenCL builtin type names should have the
-  // following format: e.g. %opencl.event_t
-  if (NameWithParameters.startswith("opencl.")) {
-    const SPIRV::OpenCLType *OCLTypeRecord =
-        SPIRV::lookupOpenCLType(NameWithParameters);
-    if (!OCLTypeRecord)
-      report_fatal_error("Missing TableGen record for OpenCL type: " +
-                         NameWithParameters);
-    NameWithParameters = OCLTypeRecord->SpirvTypeLiteral;
-    // Continue with the SPIR-V builtin type...
-  }
-
-  // Names of the opaque structs representing a SPIR-V builtins without
-  // parameters should have the following format: e.g. %spirv.Event
-  assert(NameWithParameters.startswith("spirv.") &&
-         "Unknown builtin opaque type!");
-
-  // Parameterized SPIR-V builtins names follow this format:
-  // e.g. %spirv.Image._void_1_0_0_0_0_0_0, %spirv.Pipe._0
-  if (NameWithParameters.find('_') == std::string::npos)
-    return TargetExtType::get(OpaqueType->getContext(), NameWithParameters);
-
-  SmallVector<StringRef> Parameters;
-  unsigned BaseNameLength = NameWithParameters.find('_') - 1;
-  SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_");
-
-  SmallVector<Type *, 1> TypeParameters;
-  bool HasTypeParameter = !isDigit(Parameters[0][0]);
-  if (HasTypeParameter)
-    TypeParameters.push_back(parseTypeString(
-        Parameters[0], MIRBuilder.getMF().getFunction().getContext()));
-  SmallVector<unsigned> IntParameters;
-  for (unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
-    unsigned IntParameter = 0;
-    bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
-    assert(ValidLiteral &&
-           "Invalid format of SPIR-V builtin parameter literal!");
-    IntParameters.push_back(IntParameter);
-  }
-  return TargetExtType::get(OpaqueType->getContext(),
-                            NameWithParameters.substr(0, BaseNameLength),
-                            TypeParameters, IntParameters);
-}
-
 //===----------------------------------------------------------------------===//
 // Implementation functions for builtin types.
 //===----------------------------------------------------------------------===//
@@ -2127,6 +2073,56 @@ static SPIRVType *getSampledImageType(const TargetExtType *OpaqueType,
 }
 
 namespace SPIRV {
+const TargetExtType *
+parseBuiltinTypeNameToTargetExtType(std::string TypeName,
+                                    MachineIRBuilder &MIRBuilder) {
+  StringRef NameWithParameters = TypeName;
+
+  // Pointers-to-opaque-structs representing OpenCL types are first translated
+  // to equivalent SPIR-V types. OpenCL builtin type names should have the
+  // following format: e.g. %opencl.event_t
+  if (NameWithParameters.startswith("opencl.")) {
+    const SPIRV::OpenCLType *OCLTypeRecord =
+        SPIRV::lookupOpenCLType(NameWithParameters);
+    if (!OCLTypeRecord)
+      report_fatal_error("Missing TableGen record for OpenCL type: " +
+                         NameWithParameters);
+    NameWithParameters = OCLTypeRecord->SpirvTypeLiteral;
+    // Continue with the SPIR-V builtin type...
+  }
+
+  // Names of the opaque structs representing a SPIR-V builtins without
+  // parameters should have the following format: e.g. %spirv.Event
+  assert(NameWithParameters.startswith("spirv.") &&
+         "Unknown builtin opaque type!");
+
+  // Parameterized SPIR-V builtins names follow this format:
+  // e.g. %spirv.Image._void_1_0_0_0_0_0_0, %spirv.Pipe._0
+  if (NameWithParameters.find('_') == std::string::npos)
+    return TargetExtType::get(MIRBuilder.getContext(), NameWithParameters);
+
+  SmallVector<StringRef> Parameters;
+  unsigned BaseNameLength = NameWithParameters.find('_') - 1;
+  SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_");
+
+  SmallVector<Type *, 1> TypeParameters;
+  bool HasTypeParameter = !isDigit(Parameters[0][0]);
+  if (HasTypeParameter)
+    TypeParameters.push_back(parseTypeString(
+        Parameters[0], MIRBuilder.getMF().getFunction().getContext()));
+  SmallVector<unsigned> IntParameters;
+  for (unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
+    unsigned IntParameter = 0;
+    bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
+    assert(ValidLiteral &&
+           "Invalid format of SPIR-V builtin parameter literal!");
+    IntParameters.push_back(IntParameter);
+  }
+  return TargetExtType::get(MIRBuilder.getContext(),
+                            NameWithParameters.substr(0, BaseNameLength),
+                            TypeParameters, IntParameters);
+}
+
 SPIRVType *lowerBuiltinType(const Type *OpaqueType,
                             SPIRV::AccessQualifier::AccessQualifier AccessQual,
                             MachineIRBuilder &MIRBuilder,
@@ -2141,7 +2137,8 @@ SPIRVType *lowerBuiltinType(const Type *OpaqueType,
   // will be removed in the future release of LLVM.
   const TargetExtType *BuiltinType = dyn_cast<TargetExtType>(OpaqueType);
   if (!BuiltinType)
-    BuiltinType = parseToTargetExtType(OpaqueType, MIRBuilder);
+    BuiltinType = parseBuiltinTypeNameToTargetExtType(
+        OpaqueType->getStructName().str(), MIRBuilder);
 
   unsigned NumStartingVRegs = MIRBuilder.getMRI()->getNumVirtRegs();
 

diff  --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
index 7ee5c49dc5b3259..6f957295464812e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
@@ -37,6 +37,18 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
                                  const Register OrigRet, const Type *OrigRetTy,
                                  const SmallVectorImpl<Register> &Args,
                                  SPIRVGlobalRegistry *GR);
+
+/// Translates a string representing a SPIR-V or OpenCL builtin type to a
+/// TargetExtType that can be further lowered with lowerBuiltinType().
+///
+/// \return A TargetExtType representing the builtin SPIR-V type.
+///
+/// \p TypeName is the full string representation of the SPIR-V or OpenCL
+/// builtin type.
+const TargetExtType *
+parseBuiltinTypeNameToTargetExtType(std::string TypeName,
+                                    MachineIRBuilder &MIRBuilder);
+
 /// Handles the translation of the provided special opaque/builtin type \p Type
 /// to SPIR-V type. Generates the corresponding machine instructions for the
 /// target type or gets the already existing OpType<...> register from the

diff  --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index cae7c0e9ac5b8ac..629db8e2eb4d04f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -194,23 +194,38 @@ getKernelArgTypeQual(const Function &KernelFunction, unsigned ArgIdx) {
   return {};
 }
 
-static Type *getArgType(const Function &F, unsigned ArgIdx) {
+static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx,
+                                  SPIRVGlobalRegistry *GR,
+                                  MachineIRBuilder &MIRBuilder) {
+  // Read argument's access qualifier from metadata or default.
+  SPIRV::AccessQualifier::AccessQualifier ArgAccessQual =
+      getArgAccessQual(F, ArgIdx);
+
   Type *OriginalArgType = getOriginalFunctionType(F)->getParamType(ArgIdx);
+
+  // In case of non-kernel SPIR-V function or already TargetExtType, use the
+  // original IR type.
   if (F.getCallingConv() != CallingConv::SPIR_KERNEL ||
       isSpecialOpaqueType(OriginalArgType))
-    return OriginalArgType;
+    return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
 
   MDString *MDKernelArgType =
       getKernelArgAttribute(F, ArgIdx, "kernel_arg_type");
-  if (!MDKernelArgType || !MDKernelArgType->getString().endswith("_t"))
-    return OriginalArgType;
-
-  std::string KernelArgTypeStr = "opencl." + MDKernelArgType->getString().str();
-  Type *ExistingOpaqueType =
-      StructType::getTypeByName(F.getContext(), KernelArgTypeStr);
-  return ExistingOpaqueType
-             ? ExistingOpaqueType
-             : StructType::create(F.getContext(), KernelArgTypeStr);
+  if (!MDKernelArgType || (MDKernelArgType->getString().ends_with("*") &&
+                           MDKernelArgType->getString().ends_with("_t")))
+    return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
+
+  if (MDKernelArgType->getString().ends_with("*"))
+    return GR->getOrCreateSPIRVTypeByName(
+        MDKernelArgType->getString(), MIRBuilder,
+        addressSpaceToStorageClass(OriginalArgType->getPointerAddressSpace()));
+
+  if (MDKernelArgType->getString().ends_with("_t"))
+    return GR->getOrCreateSPIRVTypeByName(
+        "opencl." + MDKernelArgType->getString().str(), MIRBuilder,
+        SPIRV::StorageClass::Function, ArgAccessQual);
+
+  llvm_unreachable("Unable to recognize argument type name.");
 }
 
 static bool isEntryPoint(const Function &F) {
@@ -262,10 +277,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
       // TODO: handle the case of multiple registers.
       if (VRegs[i].size() > 1)
         return false;
-      SPIRV::AccessQualifier::AccessQualifier ArgAccessQual =
-          getArgAccessQual(F, i);
-      auto *SpirvTy = GR->assignTypeToVReg(getArgType(F, i), VRegs[i][0],
-                                           MIRBuilder, ArgAccessQual);
+      auto *SpirvTy = getArgSPIRVType(F, i, GR, MIRBuilder);
+      GR->assignSPIRVTypeToVReg(SpirvTy, VRegs[i][0], MIRBuilder.getMF());
       ArgTypeVRegs.push_back(SpirvTy);
 
       if (Arg.hasName())

diff  --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index dbfad5b15750a12..ef527cd4af4c60d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -956,40 +956,82 @@ SPIRVGlobalRegistry::checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,
 }
 
 // TODO: maybe use tablegen to implement this.
-SPIRVType *
-SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(StringRef TypeStr,
-                                                MachineIRBuilder &MIRBuilder) {
+SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVTypeByName(
+    StringRef TypeStr, MachineIRBuilder &MIRBuilder,
+    SPIRV::StorageClass::StorageClass SC,
+    SPIRV::AccessQualifier::AccessQualifier AQ) {
   unsigned VecElts = 0;
   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
 
+  // Parse strings representing either a SPIR-V or OpenCL builtin type.
+  if (hasBuiltinTypePrefix(TypeStr))
+    return getOrCreateSPIRVType(
+        SPIRV::parseBuiltinTypeNameToTargetExtType(TypeStr.str(), MIRBuilder),
+        MIRBuilder, AQ);
+
   // Parse type name in either "typeN" or "type vector[N]" format, where
   // N is the number of elements of the vector.
-  Type *Type;
+  Type *Ty;
+
+  if (TypeStr.starts_with("atomic_"))
+    TypeStr = TypeStr.substr(strlen("atomic_"));
+
   if (TypeStr.startswith("void")) {
-    Type = Type::getVoidTy(Ctx);
+    Ty = Type::getVoidTy(Ctx);
     TypeStr = TypeStr.substr(strlen("void"));
+  } else if (TypeStr.startswith("bool")) {
+    Ty = Type::getIntNTy(Ctx, 1);
+    TypeStr = TypeStr.substr(strlen("bool"));
+  } else if (TypeStr.startswith("char") || TypeStr.startswith("uchar")) {
+    Ty = Type::getInt8Ty(Ctx);
+    TypeStr = TypeStr.startswith("char") ? TypeStr.substr(strlen("char"))
+                                         : TypeStr.substr(strlen("uchar"));
+  } else if (TypeStr.startswith("short") || TypeStr.startswith("ushort")) {
+    Ty = Type::getInt16Ty(Ctx);
+    TypeStr = TypeStr.startswith("short") ? TypeStr.substr(strlen("short"))
+                                          : TypeStr.substr(strlen("ushort"));
   } else if (TypeStr.startswith("int") || TypeStr.startswith("uint")) {
-    Type = Type::getInt32Ty(Ctx);
+    Ty = Type::getInt32Ty(Ctx);
     TypeStr = TypeStr.startswith("int") ? TypeStr.substr(strlen("int"))
                                         : TypeStr.substr(strlen("uint"));
-  } else if (TypeStr.startswith("float")) {
-    Type = Type::getFloatTy(Ctx);
-    TypeStr = TypeStr.substr(strlen("float"));
+  } else if (TypeStr.starts_with("long") || TypeStr.starts_with("ulong")) {
+    Ty = Type::getInt64Ty(Ctx);
+    TypeStr = TypeStr.startswith("long") ? TypeStr.substr(strlen("long"))
+                                         : TypeStr.substr(strlen("ulong"));
   } else if (TypeStr.startswith("half")) {
-    Type = Type::getHalfTy(Ctx);
+    Ty = Type::getHalfTy(Ctx);
     TypeStr = TypeStr.substr(strlen("half"));
-  } else if (TypeStr.startswith("opencl.sampler_t")) {
-    Type = StructType::create(Ctx, "opencl.sampler_t");
+  } else if (TypeStr.startswith("float")) {
+    Ty = Type::getFloatTy(Ctx);
+    TypeStr = TypeStr.substr(strlen("float"));
+  } else if (TypeStr.startswith("double")) {
+    Ty = Type::getDoubleTy(Ctx);
+    TypeStr = TypeStr.substr(strlen("double"));
   } else
     llvm_unreachable("Unable to recognize SPIRV type name.");
+
+  auto SpirvTy = getOrCreateSPIRVType(Ty, MIRBuilder, AQ);
+
+  // Handle "type*" or  "type* vector[N]".
+  if (TypeStr.starts_with("*")) {
+    SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
+    TypeStr = TypeStr.substr(strlen("*"));
+  }
+
+  // Handle "typeN*" or  "type vector[N]*".
+  bool IsPtrToVec = TypeStr.consume_back("*");
+
   if (TypeStr.startswith(" vector[")) {
     TypeStr = TypeStr.substr(strlen(" vector["));
     TypeStr = TypeStr.substr(0, TypeStr.find(']'));
   }
   TypeStr.getAsInteger(10, VecElts);
-  auto SpirvTy = getOrCreateSPIRVType(Type, MIRBuilder);
   if (VecElts > 0)
     SpirvTy = getOrCreateSPIRVVectorType(SpirvTy, VecElts, MIRBuilder);
+
+  if (IsPtrToVec)
+    SpirvTy = getOrCreateSPIRVPointerType(SpirvTy, MIRBuilder, SC);
+
   return SpirvTy;
 }
 

diff  --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 88769f84b3e504b..60967bfb68a87e3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -138,8 +138,11 @@ class SPIRVGlobalRegistry {
 
   // Either generate a new OpTypeXXX instruction or return an existing one
   // corresponding to the given string containing the name of the builtin type.
-  SPIRVType *getOrCreateSPIRVTypeByName(StringRef TypeStr,
-                                        MachineIRBuilder &MIRBuilder);
+  SPIRVType *getOrCreateSPIRVTypeByName(
+      StringRef TypeStr, MachineIRBuilder &MIRBuilder,
+      SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,
+      SPIRV::AccessQualifier::AccessQualifier AQ =
+          SPIRV::AccessQualifier::ReadWrite);
 
   // Return the SPIR-V type instruction corresponding to the given VReg, or
   // nullptr if no such type instruction exists.

diff  --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index e5094e8a4d33e9f..6cb51d782919d50 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -332,7 +332,7 @@ const Type *getTypedPtrEltType(const Type *Ty) {
   return PType->getNonOpaquePointerElementType();
 }
 
-static bool hasBuiltinTypePrefix(StringRef Name) {
+bool hasBuiltinTypePrefix(StringRef Name) {
   if (Name.starts_with("opencl.") || Name.starts_with("spirv."))
     return true;
   return false;

diff  --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 7c193611a857453..30fae6c7de479f2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -92,6 +92,9 @@ std::string getOclOrSpirvBuiltinDemangledName(StringRef Name);
 // element type, otherwise return Type.
 const Type *getTypedPtrEltType(const Type *Type);
 
+// Check if a string contains a builtin prefix.
+bool hasBuiltinTypePrefix(StringRef Name);
+
 // Check if given LLVM type is a special opaque builtin type.
 bool isSpecialOpaqueType(const Type *Ty);
 } // namespace llvm

diff  --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll
new file mode 100644
index 000000000000000..aaf97f8cc836c6b
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK:  %[[#FLOAT32:]] = OpTypeFloat 32
+; CHECK:  %[[#PTR:]] = OpTypePointer CrossWorkgroup %[[#FLOAT32]]
+; CHECK:  %[[#ARG:]] = OpFunctionParameter %[[#PTR]]
+; CHECK:  %[[#GEP:]] = OpInBoundsPtrAccessChain %[[#PTR]] %[[#ARG]] %[[#]]
+; CHECK:  %[[#]] = OpLoad %[[#FLOAT32]] %[[#GEP]] Aligned 4
+
+define spir_kernel void @test1(ptr addrspace(1) %arg1) !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_type_qual !4 {
+  %a = getelementptr inbounds float, ptr addrspace(1) %arg1, i64 1
+  %b = load float, ptr addrspace(1) %a, align 4
+  ret void
+}
+
+!1 = !{i32 1}
+!2 = !{!"none"}
+!3 = !{!"float*"}
+!4 = !{!""}

diff  --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll
new file mode 100644
index 000000000000000..6d1202328197d95
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll
@@ -0,0 +1,63 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK-DAG:  %[[#INT:]] = OpTypeInt 32 0
+; CHECK-DAG:  %[[#PTR1:]] = OpTypePointer Function %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR1]]
+
+define spir_kernel void @test1(ptr addrspace(0) %arg1) !kernel_arg_addr_space !1 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(0) %arg1, i32 2
+  ret void
+}
+
+!1 = !{i32 0}
+!2 = !{!"int*"}
+
+; CHECK-DAG:  %[[#PTR2:]] = OpTypePointer CrossWorkgroup %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR2]]
+
+define spir_kernel void @test2(ptr addrspace(1) %arg1) !kernel_arg_addr_space !3 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(1) %arg1, i32 2
+  ret void
+}
+
+!3 = !{i32 1}
+
+; CHECK-DAG:  %[[#PTR3:]] = OpTypePointer UniformConstant %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR3]]
+
+define spir_kernel void @test3(ptr addrspace(2) %arg1) !kernel_arg_addr_space !4 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(2) %arg1, i32 2
+  ret void
+}
+
+!4 = !{i32 2}
+
+; CHECK-DAG:  %[[#PTR4:]] = OpTypePointer Workgroup %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR4]]
+
+define spir_kernel void @test4(ptr addrspace(3) %arg1) !kernel_arg_addr_space !5 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(3) %arg1, i32 2
+  ret void
+}
+
+!5 = !{i32 3}
+
+; CHECK-DAG:  %[[#PTR5:]] = OpTypePointer Generic %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR5]]
+
+define spir_kernel void @test5(ptr addrspace(4) %arg1) !kernel_arg_addr_space !6 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(4) %arg1, i32 2
+  ret void
+}
+
+!6 = !{i32 4}
+
+; CHECK-DAG:  %[[#PTR6:]] = OpTypePointer Input %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR6]]
+
+define spir_kernel void @test6(ptr addrspace(7) %arg1) !kernel_arg_addr_space !7 !kernel_arg_type !2 {
+  %a = getelementptr inbounds i32, ptr addrspace(7) %arg1, i32 2
+  ret void
+}
+
+!7 = !{i32 7}

diff  --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll
new file mode 100644
index 000000000000000..1fcc6d9da9c7876
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll
@@ -0,0 +1,78 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK-DAG:  %[[#FLOAT32:]] = OpTypeFloat 32
+; CHECK-DAG:  %[[#PTR1:]] = OpTypePointer Function %[[#FLOAT32]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR1]]
+
+define spir_kernel void @test1(ptr %arg) !kernel_arg_type !1 {
+  %a = getelementptr inbounds float, ptr %arg, i64 1
+  ret void
+}
+
+!1 = !{!"float*"}
+
+; CHECK-DAG:  %[[#CHAR:]] = OpTypeInt 8 0
+; CHECK-DAG:  %[[#PTR2:]] = OpTypePointer Function %[[#CHAR]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR2]]
+
+define spir_kernel void @test2(ptr %arg) !kernel_arg_type !2 {
+  %a = getelementptr inbounds i8, ptr %arg, i64 1
+  ret void
+}
+
+!2 = !{!"char*"}
+
+; CHECK-DAG:  %[[#SHORT:]] = OpTypeInt 16 0
+; CHECK-DAG:  %[[#PTR3:]] = OpTypePointer Function %[[#SHORT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR3]]
+
+define spir_kernel void @test3(ptr %arg) !kernel_arg_type !3 {
+  %a = getelementptr inbounds i16, ptr %arg, i64 1
+  ret void
+}
+
+!3 = !{!"short*"}
+
+; CHECK-DAG:  %[[#INT:]] = OpTypeInt 32 0
+; CHECK-DAG:  %[[#PTR4:]] = OpTypePointer Function %[[#INT]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR4]]
+
+define spir_kernel void @test4(ptr %arg) !kernel_arg_type !4 {
+  %a = getelementptr inbounds i32, ptr %arg, i64 1
+  ret void
+}
+
+!4 = !{!"int*"}
+
+; CHECK-DAG:  %[[#LONG:]] = OpTypeInt 64 0
+; CHECK-DAG:  %[[#PTR5:]] = OpTypePointer Function %[[#LONG]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR5]]
+
+define spir_kernel void @test5(ptr %arg) !kernel_arg_type !5 {
+  %a = getelementptr inbounds i64, ptr %arg, i64 1
+  ret void
+}
+
+!5 = !{!"long*"}
+
+; CHECK-DAG:  %[[#DOUBLE:]] = OpTypeFloat 64
+; CHECK-DAG:  %[[#PTR6:]] = OpTypePointer Function %[[#DOUBLE]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR6]]
+
+define spir_kernel void @test6(ptr %arg) !kernel_arg_type !6 {
+  %a = getelementptr inbounds double, ptr %arg, i64 1
+  ret void
+}
+
+!6 = !{!"double*"}
+
+; CHECK-DAG:  %[[#HALF:]] = OpTypeFloat 16
+; CHECK-DAG:  %[[#PTR7:]] = OpTypePointer Function %[[#HALF]]
+; CHECK-DAG:  %[[#ARG:]] = OpFunctionParameter %[[#PTR7]]
+
+define spir_kernel void @test7(ptr %arg) !kernel_arg_type !7 {
+  %a = getelementptr inbounds half, ptr %arg, i64 1
+  ret void
+}
+
+!7 = !{!"half*"}


        


More information about the llvm-commits mailing list