diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index b4452d0f46a34..d6354876b5587 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 Parameters; - unsigned BaseNameLength = NameWithParameters.find('_') - 1; - SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_"); - - SmallVector TypeParameters; - bool HasTypeParameter = !isDigit(Parameters[0][0]); - if (HasTypeParameter) - TypeParameters.push_back(parseTypeString( - Parameters[0], MIRBuilder.getMF().getFunction().getContext())); - SmallVector 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 Parameters; + unsigned BaseNameLength = NameWithParameters.find('_') - 1; + SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_"); + + SmallVector TypeParameters; + bool HasTypeParameter = !isDigit(Parameters[0][0]); + if (HasTypeParameter) + TypeParameters.push_back(parseTypeString( + Parameters[0], MIRBuilder.getMF().getFunction().getContext())); + SmallVector 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(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 7ee5c49dc5b32..6f95729546481 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h @@ -37,6 +37,18 @@ std::optional lowerBuiltin(const StringRef DemangledCall, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl &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 cae7c0e9ac5b8..629db8e2eb4d0 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 dbfad5b15750a..ef527cd4af4c6 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 88769f84b3e50..60967bfb68a87 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 e5094e8a4d33e..6cb51d782919d 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 7c193611a8574..30fae6c7de479 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 0000000000000..aaf97f8cc836c --- /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 0000000000000..6d1202328197d --- /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 0000000000000..1fcc6d9da9c78 --- /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*"}