diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -590,6 +590,8 @@ getVT(VTy->getElementType(), /*HandleUnknown=*/ false), VTy->getElementCount()); } + case Type::TargetExtTyID: + return MVT(MVT::Other); } } diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -862,7 +862,7 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { LLVMContext &C = Ty->getContext(); StringRef Name = Ty->getName(); - if (Name.startswith("spirv.")) { + if (Name.startswith("spirv.") || Name.startswith("opencl.")) { return TargetTypeInfo(Type::getInt8PtrTy(C, 0), TargetExtType::HasZeroInit, TargetExtType::CanBeGlobal); } diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h @@ -45,7 +45,7 @@ /// \return A machine instruction representing the OpType<...> SPIR-V type. /// /// \p Type is the special opaque/builtin type to be lowered. -SPIRVType *lowerBuiltinType(const StructType *Type, +SPIRVType *lowerBuiltinType(const Type *Type, AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR); diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1913,135 +1913,106 @@ return false; } -struct DemangledType { +struct BuiltinType { StringRef Name; uint32_t Opcode; }; -#define GET_DemangledTypes_DECL -#define GET_DemangledTypes_IMPL +#define GET_BuiltinTypes_DECL +#define GET_BuiltinTypes_IMPL -struct ImageType { +struct OpenCLType { StringRef Name; - StringRef SampledType; - AccessQualifier::AccessQualifier Qualifier; - Dim::Dim Dimensionality; - bool Arrayed; - bool Depth; - bool Multisampled; - bool Sampled; - ImageFormat::ImageFormat Format; + StringRef SpirvTypeLiteral; }; -struct PipeType { - StringRef Name; - AccessQualifier::AccessQualifier Qualifier; -}; +#define GET_OpenCLTypes_DECL +#define GET_OpenCLTypes_IMPL -using namespace AccessQualifier; -using namespace Dim; -using namespace ImageFormat; -#define GET_ImageTypes_DECL -#define GET_ImageTypes_IMPL -#define GET_PipeTypes_DECL -#define GET_PipeTypes_IMPL #include "SPIRVGenTables.inc" } // namespace SPIRV //===----------------------------------------------------------------------===// -// Misc functions for parsing builtin types and looking up implementation -// details in TableGenerated tables. +// Misc functions for parsing builtin types. //===----------------------------------------------------------------------===// -static const SPIRV::DemangledType *findBuiltinType(StringRef Name) { - if (Name.startswith("opencl.")) - return SPIRV::lookupBuiltinType(Name); - if (!Name.startswith("spirv.")) - return nullptr; - // Some SPIR-V builtin types have a complex list of parameters as part of - // their name (e.g. spirv.Image._void_1_0_0_0_0_0_0). Those parameters often - // are numeric literals which cannot be easily represented by TableGen - // records and should be parsed instead. - unsigned BaseTypeNameLength = - Name.contains('_') ? Name.find('_') - 1 : Name.size(); - return SPIRV::lookupBuiltinType(Name.substr(0, BaseTypeNameLength).str()); +static Type *parseTypeString(const StringRef Name, LLVMContext &Context) { + if (Name.startswith("void")) + return Type::getVoidTy(Context); + else if (Name.startswith("int") || Name.startswith("uint")) + return Type::getInt32Ty(Context); + else if (Name.startswith("float")) + return Type::getFloatTy(Context); + else if (Name.startswith("half")) + return Type::getHalfTy(Context); + llvm_unreachable("Unable to recognize type!"); } -static std::unique_ptr -lookupOrParseBuiltinImageType(StringRef Name) { - if (Name.startswith("opencl.")) { - // Lookup OpenCL builtin image type lowering details in TableGen records. - const SPIRV::ImageType *Record = SPIRV::lookupImageType(Name); - return std::unique_ptr(new SPIRV::ImageType(*Record)); +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... } - if (!Name.startswith("spirv.")) - llvm_unreachable("Unknown builtin image type name/literal"); - // Parse the literals of SPIR-V image builtin parameters. The name should - // have the following format: - // spirv.Image._Type_Dim_Depth_Arrayed_MS_Sampled_ImageFormat_AccessQualifier - // e.g. %spirv.Image._void_1_0_0_0_0_0_0 - StringRef TypeParametersString = Name.substr(strlen("spirv.Image.")); - SmallVector TypeParameters; - SplitString(TypeParametersString, TypeParameters, "_"); - assert(TypeParameters.size() == 8 && - "Wrong number of literals in SPIR-V builtin image type"); - - StringRef SampledType = TypeParameters[0]; - unsigned Dim, Depth, Arrayed, Multisampled, Sampled, Format, AccessQual; - bool AreParameterLiteralsValid = - !(TypeParameters[1].getAsInteger(10, Dim) || - TypeParameters[2].getAsInteger(10, Depth) || - TypeParameters[3].getAsInteger(10, Arrayed) || - TypeParameters[4].getAsInteger(10, Multisampled) || - TypeParameters[5].getAsInteger(10, Sampled) || - TypeParameters[6].getAsInteger(10, Format) || - TypeParameters[7].getAsInteger(10, AccessQual)); - assert(AreParameterLiteralsValid && - "Invalid format of SPIR-V image type parameter literals."); - - return std::unique_ptr(new SPIRV::ImageType{ - Name, SampledType, SPIRV::AccessQualifier::AccessQualifier(AccessQual), - SPIRV::Dim::Dim(Dim), static_cast(Arrayed), - static_cast(Depth), static_cast(Multisampled), - static_cast(Sampled), SPIRV::ImageFormat::ImageFormat(Format)}); -} -static std::unique_ptr -lookupOrParseBuiltinPipeType(StringRef Name) { - if (Name.startswith("opencl.")) { - // Lookup OpenCL builtin pipe type lowering details in TableGen records. - const SPIRV::PipeType *Record = SPIRV::lookupPipeType(Name); - return std::unique_ptr(new SPIRV::PipeType(*Record)); + // 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!"); + + // Parametrized 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 HasTypeParamter = !isDigit(Parameters[0][0]); + if (HasTypeParamter) + TypeParameters.push_back(parseTypeString( + Parameters[0], MIRBuilder.getMF().getFunction().getContext())); + SmallVector IntParameters; + for (unsigned i = HasTypeParamter ? 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); } - if (!Name.startswith("spirv.")) - llvm_unreachable("Unknown builtin pipe type name/literal"); - // Parse the access qualifier literal in the name of the SPIR-V pipe type. - // The name should have the following format: - // spirv.Pipe._AccessQualifier - // e.g. %spirv.Pipe._1 - if (Name.endswith("_0")) - return std::unique_ptr( - new SPIRV::PipeType{Name, SPIRV::AccessQualifier::ReadOnly}); - if (Name.endswith("_1")) - return std::unique_ptr( - new SPIRV::PipeType{Name, SPIRV::AccessQualifier::WriteOnly}); - if (Name.endswith("_2")) - return std::unique_ptr( - new SPIRV::PipeType{Name, SPIRV::AccessQualifier::ReadWrite}); - llvm_unreachable("Unknown pipe type access qualifier literal"); + return TargetExtType::get(OpaqueType->getContext(), + NameWithParameters.substr(0, BaseNameLength), + TypeParameters, IntParameters); } //===----------------------------------------------------------------------===// // Implementation functions for builtin types. //===----------------------------------------------------------------------===// -static SPIRVType *getNonParametrizedType(const StructType *OpaqueType, - const SPIRV::DemangledType *TypeRecord, +static SPIRVType *getNonParametrizedType(const TargetExtType *ExtensionType, + const SPIRV::BuiltinType *TypeRecord, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { unsigned Opcode = TypeRecord->Opcode; // Create or get an existing type from GlobalRegistry. - return GR->getOrCreateOpTypeByOpcode(OpaqueType, MIRBuilder, Opcode); + return GR->getOrCreateOpTypeByOpcode(ExtensionType, MIRBuilder, Opcode); } static SPIRVType *getSamplerType(MachineIRBuilder &MIRBuilder, @@ -2050,78 +2021,87 @@ return GR->getOrCreateOpTypeSampler(MIRBuilder); } -static SPIRVType *getPipeType(const StructType *OpaqueType, +static SPIRVType *getPipeType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - // Lookup pipe type lowering details in TableGen records or parse the - // name/literal for details. - std::unique_ptr Record = - lookupOrParseBuiltinPipeType(OpaqueType->getName()); + assert(ExtensionType->getNumIntParameters() == 1 && + "Invalid number of parameters for SPIR-V pipe builtin!"); // Create or get an existing type from GlobalRegistry. - return GR->getOrCreateOpTypePipe(MIRBuilder, Record.get()->Qualifier); + return GR->getOrCreateOpTypePipe(MIRBuilder, + SPIRV::AccessQualifier::AccessQualifier( + ExtensionType->getIntParameter(0))); } static SPIRVType * -getImageType(const StructType *OpaqueType, - SPIRV::AccessQualifier::AccessQualifier AccessQual, +getImageType(const TargetExtType *ExtensionType, + const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - // Lookup image type lowering details in TableGen records or parse the - // name/literal for details. - std::unique_ptr Record = - lookupOrParseBuiltinImageType(OpaqueType->getName()); - - SPIRVType *SampledType = - GR->getOrCreateSPIRVTypeByName(Record.get()->SampledType, MIRBuilder); + assert(ExtensionType->getNumTypeParameters() == 1 && + "SPIR-V image builtin type must have sampled type parameter!"); + const SPIRVType *SampledType = + GR->getOrCreateSPIRVType(ExtensionType->getTypeParameter(0), MIRBuilder); + assert(ExtensionType->getNumIntParameters() == 7 && + "Invalid number of parameters for SPIR-V image builtin!"); + // Create or get an existing type from GlobalRegistry. return GR->getOrCreateOpTypeImage( - MIRBuilder, SampledType, Record.get()->Dimensionality, - Record.get()->Depth, Record.get()->Arrayed, Record.get()->Multisampled, - Record.get()->Sampled, Record.get()->Format, - AccessQual == SPIRV::AccessQualifier::WriteOnly + MIRBuilder, SampledType, + SPIRV::Dim::Dim(ExtensionType->getIntParameter(0)), + ExtensionType->getIntParameter(1), ExtensionType->getIntParameter(2), + ExtensionType->getIntParameter(3), ExtensionType->getIntParameter(4), + SPIRV::ImageFormat::ImageFormat(ExtensionType->getIntParameter(5)), + Qualifier == SPIRV::AccessQualifier::WriteOnly ? SPIRV::AccessQualifier::WriteOnly - : Record.get()->Qualifier); + : SPIRV::AccessQualifier::AccessQualifier( + ExtensionType->getIntParameter(6))); } -static SPIRVType *getSampledImageType(const StructType *OpaqueType, +static SPIRVType *getSampledImageType(const TargetExtType *OpaqueType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - StringRef TypeParametersString = - OpaqueType->getName().substr(strlen("spirv.SampledImage.")); - LLVMContext &Context = MIRBuilder.getMF().getFunction().getContext(); - Type *ImageOpaqueType = StructType::getTypeByName( - Context, "spirv.Image." + TypeParametersString.str()); - SPIRVType *TargetImageType = - GR->getOrCreateSPIRVType(ImageOpaqueType, MIRBuilder); - return GR->getOrCreateOpTypeSampledImage(TargetImageType, MIRBuilder); + SPIRVType *OpaqueImageType = getImageType( + OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder, GR); + // Create or get an existing type from GlobalRegistry. + return GR->getOrCreateOpTypeSampledImage(OpaqueImageType, MIRBuilder); } namespace SPIRV { -SPIRVType *lowerBuiltinType(const StructType *OpaqueType, +SPIRVType *lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { - assert(OpaqueType->hasName() && - "Structs representing builtin types must have a parsable name"); + // In LLVM IR, SPIR-V and OpenCL builtin types are represented as either + // target(...) target extension types or pointers-to-opaque-structs. The + // approach relying on structs is deprecated and works only in the non-opaque + // pointer mode (-opaque-pointers=0). + // In order to maintain compatibility with LLVM IR generated by older versions + // of Clang and LLVM/SPIR-V Translator, the pointers-to-opaque-structs are + // "translated" to target extension types. This translation is temporary and + // will be removed in the future release of LLVM. + const TargetExtType *BuiltinType = dyn_cast(OpaqueType); + if (!BuiltinType) + BuiltinType = parseToTargetExtType(OpaqueType, MIRBuilder); + unsigned NumStartingVRegs = MIRBuilder.getMRI()->getNumVirtRegs(); - const StringRef Name = OpaqueType->getName(); + const StringRef Name = BuiltinType->getName(); LLVM_DEBUG(dbgs() << "Lowering builtin type: " << Name << "\n"); // Lookup the demangled builtin type in the TableGen records. - const SPIRV::DemangledType *TypeRecord = findBuiltinType(Name); + const SPIRV::BuiltinType *TypeRecord = SPIRV::lookupBuiltinType(Name); if (!TypeRecord) report_fatal_error("Missing TableGen record for builtin type: " + Name); // "Lower" the BuiltinType into TargetType. The following get<...>Type methods - // use the implementation details from TableGen records to either create a new - // OpType<...> machine instruction or get an existing equivalent SPIRVType - // from GlobalRegistry. + // use the implementation details from TableGen records or TargetExtType + // parameters to either create a new OpType<...> machine instruction or get an + // existing equivalent SPIRVType from GlobalRegistry. SPIRVType *TargetType; switch (TypeRecord->Opcode) { case SPIRV::OpTypeImage: - TargetType = getImageType(OpaqueType, AccessQual, MIRBuilder, GR); + TargetType = getImageType(BuiltinType, AccessQual, MIRBuilder, GR); break; case SPIRV::OpTypePipe: - TargetType = getPipeType(OpaqueType, MIRBuilder, GR); + TargetType = getPipeType(BuiltinType, MIRBuilder, GR); break; case SPIRV::OpTypeDeviceEvent: TargetType = GR->getOrCreateOpTypeDeviceEvent(MIRBuilder); @@ -2130,18 +2110,18 @@ TargetType = getSamplerType(MIRBuilder, GR); break; case SPIRV::OpTypeSampledImage: - TargetType = getSampledImageType(OpaqueType, MIRBuilder, GR); + TargetType = getSampledImageType(BuiltinType, MIRBuilder, GR); break; default: - TargetType = getNonParametrizedType(OpaqueType, TypeRecord, MIRBuilder, GR); + TargetType = + getNonParametrizedType(BuiltinType, TypeRecord, MIRBuilder, GR); break; } // Emit OpName instruction if a new OpType<...> instruction was added // (equivalent type was not found in GlobalRegistry). if (NumStartingVRegs < MIRBuilder.getMRI()->getNumVirtRegs()) - buildOpName(GR->getSPIRVTypeID(TargetType), OpaqueType->getName(), - MIRBuilder); + buildOpName(GR->getSPIRVTypeID(TargetType), Name, MIRBuilder); return TargetType; } diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -1101,141 +1101,105 @@ } //===----------------------------------------------------------------------===// -// Class defining implementation details of demangled builtin types. The info +// Class defining implementation details of SPIR-V builtin types. The info // in the record is used for lowering into OpType. // -// name is the demangled name of the given builtin. +// name is the name of the given SPIR-V builtin type. // operation specifies the SPIR-V opcode the StructType should be lowered to. //===----------------------------------------------------------------------===// -class DemangledType { +class BuiltinType { string Name = name; Op Opcode = operation; } -// Table gathering all the demangled type records. -def DemangledTypes : GenericTable { - let FilterClass = "DemangledType"; +// Table gathering all the builtin type records. +def BuiltinTypes : GenericTable { + let FilterClass = "BuiltinType"; let Fields = ["Name", "Opcode"]; } // Function to lookup builtin types by their demangled name. def lookupBuiltinType : SearchIndex { - let Table = DemangledTypes; + let Table = BuiltinTypes; let Key = ["Name"]; } -def : DemangledType<"opencl.reserve_id_t", OpTypeReserveId>; -def : DemangledType<"opencl.event_t", OpTypeEvent>; -def : DemangledType<"opencl.queue_t", OpTypeQueue>; -def : DemangledType<"opencl.sampler_t", OpTypeSampler>; -def : DemangledType<"opencl.clk_event_t", OpTypeDeviceEvent>; - -def : DemangledType<"spirv.ReserveId", OpTypeReserveId>; -def : DemangledType<"spirv.PipeStorage", OpTypePipeStorage>; -def : DemangledType<"spirv.Queue", OpTypeQueue>; -def : DemangledType<"spirv.Event", OpTypeEvent>; -def : DemangledType<"spirv.Sampler", OpTypeSampler>; -def : DemangledType<"spirv.DeviceEvent", OpTypeDeviceEvent>; - -// Some SPIR-V builtin types (e.g. spirv.Image) have a complex list of -// parameters as part of their name. Some of those parameters should be treated -// as numeric literals and therefore they cannot be represented in TableGen and -// should be parsed instead. -def : DemangledType<"spirv.Image", OpTypeImage>; -def : DemangledType<"spirv.SampledImage", OpTypeSampledImage>; -def : DemangledType<"spirv.Pipe", OpTypePipe>; - -// Class definining lowering details for various variants of image type indentifiers. -class ImageType { +def : BuiltinType<"spirv.ReserveId", OpTypeReserveId>; +def : BuiltinType<"spirv.PipeStorage", OpTypePipeStorage>; +def : BuiltinType<"spirv.Queue", OpTypeQueue>; +def : BuiltinType<"spirv.Event", OpTypeEvent>; +def : BuiltinType<"spirv.Sampler", OpTypeSampler>; +def : BuiltinType<"spirv.DeviceEvent", OpTypeDeviceEvent>; +def : BuiltinType<"spirv.Image", OpTypeImage>; +def : BuiltinType<"spirv.SampledImage", OpTypeSampledImage>; +def : BuiltinType<"spirv.Pipe", OpTypePipe>; + + +//===----------------------------------------------------------------------===// +// Class matching an OpenCL builtin type name to an equivalent SPIR-V +// builtin type literal. +// +// name is the name of the given OpenCL builtin type. +// spirvTypeLiteral is the literal of an equivalent SPIR-V builtin type. +//===----------------------------------------------------------------------===// +class OpenCLType { string Name = name; - string Type = "void"; - AccessQualifier Qualifier = !cond(!not(!eq(!find(name, "_ro_t"), -1)) : ReadOnly, - !not(!eq(!find(name, "_wo_t"), -1)) : WriteOnly, - !not(!eq(!find(name, "_rw_t"), -1)) : ReadWrite, - true : ReadOnly); - Dim Dimensionality = !cond(!not(!eq(!find(name, "buffer"), -1)) : DIM_Buffer, - !not(!eq(!find(name, "image1"), -1)) : DIM_1D, - !not(!eq(!find(name, "image2"), -1)) : DIM_2D, - !not(!eq(!find(name, "image3"), -1)) : DIM_3D); - bit Arrayed = !not(!eq(!find(name, "array"), -1)); - bit Depth = !not(!eq(!find(name, "depth"), -1)); - bit Multisampled = false; - bit Sampled = false; - ImageFormat Format = Unknown; + string SpirvTypeLiteral = spirvTypeLiteral; } -// Table gathering all the image type records. -def ImageTypes : GenericTable { - let FilterClass = "ImageType"; - let Fields = ["Name", "Type", "Qualifier", "Dimensionality", "Arrayed", - "Depth", "Multisampled", "Sampled", "Format"]; - string TypeOf_Qualifier = "AccessQualifier"; - string TypeOf_Dimensionality = "Dim"; - string TypeOf_Format = "ImageFormat"; +// Table gathering all the OpenCL type records. +def OpenCLTypes : GenericTable { + let FilterClass = "OpenCLType"; + let Fields = ["Name", "SpirvTypeLiteral"]; } -// Function to lookup builtin image types by their demangled name. -def lookupImageType : SearchIndex { - let Table = ImageTypes; +// Function to lookup OpenCL types by their name. +def lookupOpenCLType : SearchIndex { + let Table = OpenCLTypes; let Key = ["Name"]; } -// Multiclass used to define at the same time a DemangledType record used -// for matching an incoming demangled string to the OpTypeImage opcode and -// ImageType conatining the lowering details. -multiclass DemangledImageType { - def : DemangledType; - def : ImageType; +def : OpenCLType<"opencl.reserve_id_t", "spirv.ReserveId">; +def : OpenCLType<"opencl.event_t", "spirv.Event">; +def : OpenCLType<"opencl.queue_t", "spirv.Queue">; +def : OpenCLType<"opencl.sampler_t", "spirv.Sampler">; +def : OpenCLType<"opencl.clk_event_t", "spirv.DeviceEvent">; + +foreach aq = ["_t", "_ro_t", "_wo_t", "_rw_t"] in { + defvar p = !cond(!not(!eq(!find(aq, "_rw_t"), -1)) : "2", + !not(!eq(!find(aq, "_wo_t"), -1)) : "1", + true : "0"); + def : OpenCLType; } foreach aq = ["_t", "_ro_t", "_wo_t", "_rw_t"] in { - defm : DemangledImageType; - defm : DemangledImageType; - defm : DemangledImageType; + defvar p7 = !cond(!not(!eq(!find(aq, "_rw_t"), -1)) : "2", + !not(!eq(!find(aq, "_wo_t"), -1)) : "1", + true : "0"); + + def : OpenCLType; + def : OpenCLType; + def : OpenCLType; foreach a1 = ["", "_array"] in { foreach a2 = ["", "_msaa"] in { foreach a3 = ["", "_depth"] in { - defm : DemangledImageType; + defvar p2 = !cond(!not(!eq(!find(a3, "_depth"), -1)) : "1", true : "0"); + defvar p3 = !cond(!not(!eq(!find(a1, "_array"), -1)) : "1", true : "0"); + defvar p4 = !cond(!not(!eq(!find(a2, "msaa"), -1)) : "1", true : "0"); + + def : OpenCLType; } } } - - defm : DemangledImageType; -} - -// Class definining lowering details for various variants of pipe type indentifiers. -class PipeType { - string Name = name; - AccessQualifier Qualifier = !cond(!not(!eq(!find(name, "_ro_t"), -1)) : ReadOnly, - !not(!eq(!find(name, "_wo_t"), -1)) : WriteOnly, - !not(!eq(!find(name, "_rw_t"), -1)) : ReadWrite, - true : ReadOnly); -} - -// Table gathering all the pipe type records. -def PipeTypes : GenericTable { - let FilterClass = "PipeType"; - let Fields = ["Name", "Qualifier"]; - string TypeOf_Qualifier = "AccessQualifier"; -} - -// Function to lookup builtin pipe types by their demangled name. -def lookupPipeType : SearchIndex { - let Table = PipeTypes; - let Key = ["Name"]; -} - -// Multiclass used to define at the same time a DemangledType record used -// for matching an incoming demangled string to the OpTypePipe opcode and -// PipeType conatining the lowering details. -multiclass DemangledPipeType { - def : DemangledType; - def : PipeType; -} - -foreach aq = ["_t", "_ro_t", "_wo_t", "_rw_t"] in { - defm : DemangledPipeType; + + def : OpenCLType; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -573,9 +573,8 @@ assert(!PType->isOpaque()); Ty = PType->getNonOpaquePointerElementType(); } - auto SType = cast(Ty); - assert(isSpecialOpaqueType(SType) && "Not a special opaque builtin type"); - return SPIRV::lowerBuiltinType(SType, AccQual, MIRBuilder, this); + assert(isSpecialOpaqueType(Ty) && "Not a special opaque builtin type"); + return SPIRV::lowerBuiltinType(Ty, AccQual, MIRBuilder, this); } SPIRVType *SPIRVGlobalRegistry::getOpTypePointer( diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -332,16 +332,6 @@ return Name.substr(Start, Len).str(); } -static bool isOpenCLBuiltinType(const StructType *SType) { - return SType->isOpaque() && SType->hasName() && - SType->getName().startswith("opencl."); -} - -static bool isSPIRVBuiltinType(const StructType *SType) { - return SType->isOpaque() && SType->hasName() && - SType->getName().startswith("spirv."); -} - const Type *getTypedPtrEltType(const Type *Ty) { auto PType = dyn_cast(Ty); if (!PType || PType->isOpaque()) @@ -349,9 +339,21 @@ return PType->getNonOpaquePointerElementType(); } +static bool hasBuiltinTypePrefix(StringRef Name) { + if (Name.starts_with("opencl.") || Name.starts_with("spirv.")) + return true; + return false; +} + bool isSpecialOpaqueType(const Type *Ty) { - if (auto SType = dyn_cast(getTypedPtrEltType(Ty))) - return isOpenCLBuiltinType(SType) || isSPIRVBuiltinType(SType); + const StructType *SType = dyn_cast(getTypedPtrEltType(Ty)); + if (SType && SType->hasName()) + return hasBuiltinTypePrefix(SType->getName()); + + if (const TargetExtType *EType = + dyn_cast(getTypedPtrEltType(Ty))) + return hasBuiltinTypePrefix(EType->getName()); + return false; } } // namespace llvm diff --git a/llvm/test/CodeGen/SPIRV/image_store.ll b/llvm/test/CodeGen/SPIRV/image_store.ll --- a/llvm/test/CodeGen/SPIRV/image_store.ll +++ b/llvm/test/CodeGen/SPIRV/image_store.ll @@ -1,8 +1,8 @@ ; RUN: llc -O0 -opaque-pointers=0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s ;; Image types may be represented in two ways while translating to SPIR-V: -;; - OpenCL form, for example, '%opencl.image2d_ro_t', -;; - SPIR-V form, for example, '%spirv.Image._void_1_0_0_0_0_0_0', +;; - OpenCL form based on pointers-to-opaque-structs, e.g. '%opencl.image2d_ro_t', +;; - SPIR-V form based on TargetExtType, e.g. 'target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0)', ;; but it is still one type which should be translated to one SPIR-V type. ;; ;; The test checks that the code below is successfully translated and only one @@ -12,12 +12,11 @@ ; CHECK-NOT: OpTypeImage %opencl.image2d_ro_t = type opaque -%spirv.Image._void_1_0_0_0_0_0_0 = type opaque define spir_kernel void @read_image(%opencl.image2d_ro_t addrspace(1)* %srcimg) { entry: %srcimg.addr = alloca %opencl.image2d_ro_t addrspace(1)*, align 8 - %spirvimg.addr = alloca %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*, align 8 + %spirvimg.addr = alloca target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 0), align 8 store %opencl.image2d_ro_t addrspace(1)* %srcimg, %opencl.image2d_ro_t addrspace(1)** %srcimg.addr, align 8 ret void } diff --git a/llvm/test/CodeGen/SPIRV/spirv.Queue.ll b/llvm/test/CodeGen/SPIRV/spirv.Queue.ll --- a/llvm/test/CodeGen/SPIRV/spirv.Queue.ll +++ b/llvm/test/CodeGen/SPIRV/spirv.Queue.ll @@ -1,11 +1,9 @@ -; RUN: llc -O0 -opaque-pointers=0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; CHECK-SPIRV: OpCapability DeviceEnqueue ; CHECK-SPIRV: OpTypeQueue -%spirv.Queue = type opaque - -define spir_func void @enqueue_simple_block(%spirv.Queue* addrspace(3)* nocapture %q) { +define spir_func void @enqueue_simple_block(target("spirv.Queue") %q) { entry: ret void } diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll --- a/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll @@ -1,6 +1,6 @@ ;; Test SPIR-V opaque types -; RUN: llc -O0 -opaque-pointers=0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; CHECK-SPIRV-DAG: OpCapability Float16 ; CHECK-SPIRV-DAG: OpCapability ImageReadWrite @@ -28,23 +28,6 @@ ; CHECK-SPIRV-DAG: %[[#SAMP:]] = OpTypeSampler ; CHECK-SPIRV-DAG: %[[#SAMPIMG:]] = OpTypeSampledImage %[[#IMG2DD_RD]] -%spirv.Pipe._0 = type opaque ; read_only pipe -%spirv.Pipe._1 = type opaque ; write_only pipe -%spirv.Image._void_0_0_0_0_0_0_0 = type opaque ; read_only image1d_ro_t -%spirv.Image._int_1_0_0_0_0_0_0 = type opaque ; read_only image2d_ro_t -%spirv.Image._uint_2_0_0_0_0_0_0 = type opaque ; read_only image3d_ro_t -%spirv.Image._float_1_1_0_0_0_0_0 = type opaque; read_only image2d_depth_ro_t -%spirv.Image._half_1_0_1_0_0_0_0 = type opaque ; read_only image2d_array_ro_t -%spirv.Image._float_5_0_0_0_0_0_0 = type opaque ; read_only image1d_buffer_ro_t -%spirv.Image._void_0_0_0_0_0_0_1 = type opaque ; write_only image1d_wo_t -%spirv.Image._void_1_0_0_0_0_0_2 = type opaque ; read_write image2d_rw_t -%spirv.DeviceEvent = type opaque ; clk_event_t -%spirv.Event = type opaque ; event_t -%spirv.Queue = type opaque ; queue_t -%spirv.ReserveId = type opaque ; reserve_id_t -%spirv.Sampler = type opaque ; sampler_t -%spirv.SampledImage._float_1_1_0_0_0_0_0 = type opaque - ; CHECK-SPIRV: OpFunction ; CHECK-SPIRV: %[[#]] = OpFunctionParameter %[[#PIPE_RD]] ; CHECK-SPIRV: %[[#]] = OpFunctionParameter %[[#PIPE_WR]] @@ -57,15 +40,15 @@ ; CHECK-SPIRV: %[[#]] = OpFunctionParameter %[[#IMG2D_RW]] define spir_kernel void @foo( - %spirv.Pipe._0 addrspace(1)* nocapture %a, - %spirv.Pipe._1 addrspace(1)* nocapture %b, - %spirv.Image._void_0_0_0_0_0_0_0 addrspace(1)* nocapture %c1, - %spirv.Image._int_1_0_0_0_0_0_0 addrspace(1)* nocapture %d1, - %spirv.Image._uint_2_0_0_0_0_0_0 addrspace(1)* nocapture %e1, - %spirv.Image._half_1_0_1_0_0_0_0 addrspace(1)* nocapture %f1, - %spirv.Image._float_5_0_0_0_0_0_0 addrspace(1)* nocapture %g1, - %spirv.Image._void_0_0_0_0_0_0_1 addrspace(1)* nocapture %c2, - %spirv.Image._void_1_0_0_0_0_0_2 addrspace(1)* nocapture %d3) { + target("spirv.Pipe", 0) %a, + target("spirv.Pipe", 1) %b, + target("spirv.Image", void, 0, 0, 0, 0, 0, 0, 0) %c1, + target("spirv.Image", i32, 1, 0, 0, 0, 0, 0, 0) %d1, + target("spirv.Image", i32, 2, 0, 0, 0, 0, 0, 0) %e1, + target("spirv.Image", half, 1, 0, 1, 0, 0, 0, 0) %f1, + target("spirv.Image", float, 5, 0, 0, 0, 0, 0, 0) %g1, + target("spirv.Image", void, 0, 0, 0, 0, 0, 0, 1) %c2, + target("spirv.Image", void, 1, 0, 0, 0, 0, 0, 2) %d3) { entry: ret void } @@ -77,10 +60,10 @@ ; CHECK-SPIRV: %[[#]] = OpFunctionParameter %[[#RESID]] define spir_func void @bar( - %spirv.DeviceEvent * %a, - %spirv.Event * %b, - %spirv.Queue * %c, - %spirv.ReserveId * %d) { + target("spirv.DeviceEvent") %a, + target("spirv.Event") %b, + target("spirv.Queue") %c, + target("spirv.ReserveId") %d) { ret void } @@ -90,13 +73,13 @@ ; CHECK-SPIRV: %[[#SAMPIMG_VAR:]] = OpSampledImage %[[#SAMPIMG]] %[[#IMG_ARG]] %[[#SAMP_ARG]] ; CHECK-SPIRV: %[[#]] = OpImageSampleExplicitLod %[[#]] %[[#SAMPIMG_VAR]] -define spir_func void @test_sampler(%spirv.Image._float_1_1_0_0_0_0_0 addrspace(1)* %srcimg.coerce, - %spirv.Sampler addrspace(1)* %s.coerce) { - %1 = tail call spir_func %spirv.SampledImage._float_1_1_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImagePU3AS1K34__spirv_Image__float_1_1_0_0_0_0_0PU3AS1K15__spirv_Sampler(%spirv.Image._float_1_1_0_0_0_0_0 addrspace(1)* %srcimg.coerce, %spirv.Sampler addrspace(1)* %s.coerce) - %2 = tail call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS120__spirv_SampledImageDv4_iif(%spirv.SampledImage._float_1_1_0_0_0_0_0 addrspace(1)* %1, <4 x i32> zeroinitializer, i32 2, float 1.000000e+00) +define spir_func void @test_sampler(target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0) %srcimg.coerce, + target("spirv.Sampler") %s.coerce) { + %1 = tail call spir_func target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0) @_Z20__spirv_SampledImagePU3AS1K34__spirv_Image__float_1_1_0_0_0_0_0PU3AS1K15__spirv_Sampler(target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0) %srcimg.coerce, target("spirv.Sampler") %s.coerce) + %2 = tail call spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS120__spirv_SampledImageDv4_iif(target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0) %1, <4 x i32> zeroinitializer, i32 2, float 1.000000e+00) ret void } -declare spir_func %spirv.SampledImage._float_1_1_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImagePU3AS1K34__spirv_Image__float_1_1_0_0_0_0_0PU3AS1K15__spirv_Sampler(%spirv.Image._float_1_1_0_0_0_0_0 addrspace(1)*, %spirv.Sampler addrspace(1)*) +declare spir_func target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0) @_Z20__spirv_SampledImagePU3AS1K34__spirv_Image__float_1_1_0_0_0_0_0PU3AS1K15__spirv_Sampler(target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0), target("spirv.Sampler")) -declare spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS120__spirv_SampledImageDv4_iif(%spirv.SampledImage._float_1_1_0_0_0_0_0 addrspace(1)*, <4 x i32>, i32, float) +declare spir_func <4 x float> @_Z38__spirv_ImageSampleExplicitLod_Rfloat4PU3AS120__spirv_SampledImageDv4_iif(target("spirv.Image", float, 1, 1, 0, 0, 0, 0, 0), <4 x i32>, i32, float)