diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp index 81a901fbb72d..e37f15494f5b 100644 --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -582,6 +582,7 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){ 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 index 3d02ad2bba72..8c77e9862df0 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -862,7 +862,7 @@ struct TargetTypeInfo { 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/MCTargetDesc/SPIRVBaseInfo.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp index 0b7b0160dee7..020cfa6ee20f 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp @@ -129,6 +129,24 @@ getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, return Capabilities; } +CapabilityList +getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) { + const SPIRV::ExtensionEntry *Entry = + SPIRV::lookupSymbolicOperandsEnabledByExtension( + Extension, SPIRV::OperandCategory::CapabilityOperand); + + CapabilityList Capabilities; + while (Entry && + Entry->Category == SPIRV::OperandCategory::CapabilityOperand && + Entry->ReqExtension == Extension) { + Capabilities.push_back( + static_cast(Entry->Value)); + ++Entry; + } + + return Capabilities; +} + ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value) { diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h index d6075f72e55c..616d2ea71b39 100644 --- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h +++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h @@ -223,6 +223,8 @@ getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); +CapabilityList +getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension); ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value); diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index fd9f5b226ab9..38be30ad1519 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1912,135 +1912,107 @@ std::optional lowerBuiltin(const StringRef DemangledCall, 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 + if (!NameWithParameters.startswith("spirv.")) + llvm_unreachable("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, @@ -2049,78 +2021,87 @@ static SPIRVType *getSamplerType(MachineIRBuilder &MIRBuilder, 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); @@ -2129,18 +2110,18 @@ SPIRVType *lowerBuiltinType(const StructType *OpaqueType, 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.h b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h index 26d2e8ab0fd6..7ee5c49dc5b3 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h @@ -45,7 +45,7 @@ std::optional lowerBuiltin(const StringRef DemangledCall, /// \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.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td index 635c6451ea04..8acd4691787e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -1101,141 +1101,105 @@ foreach i = ["", "2", "3", "4", "8", "16"] in { } //===----------------------------------------------------------------------===// -// 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 index 0f85c4839e10..2f64249de375 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -80,6 +80,24 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeBool(MachineIRBuilder &MIRBuilder) { SPIRVType *SPIRVGlobalRegistry::getOpTypeInt(uint32_t Width, MachineIRBuilder &MIRBuilder, bool IsSigned) { + assert(Width <= 64 && "Unsupported integer width!"); + const SPIRVSubtarget &ST = + cast(MIRBuilder.getMF().getSubtarget()); + if (ST.canUseExtension( + SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers)) { + MIRBuilder.buildInstr(SPIRV::OpExtension) + .addImm(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers); + MIRBuilder.buildInstr(SPIRV::OpCapability) + .addImm(SPIRV::Capability::ArbitraryPrecisionIntegersINTEL); + } else if (Width <= 8) + Width = 8; + else if (Width <= 16) + Width = 16; + else if (Width <= 32) + Width = 32; + else if (Width <= 64) + Width = 64; + auto MIB = MIRBuilder.buildInstr(SPIRV::OpTypeInt) .addDef(createTypeVReg(MIRBuilder)) .addImm(Width) @@ -573,9 +591,8 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType( 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/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp index c226b1ac7528..c2582bc298b4 100644 --- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp @@ -27,6 +27,8 @@ unsigned SPIRVTargetLowering::getNumRegistersForCallingConv( (VT.getVectorElementType() == MVT::i1 || VT.getVectorElementType() == MVT::i8)) return 1; + if (!VT.isVector() && VT.isInteger() && VT.getSizeInBits() <= 64) + return 1; return getNumRegisters(Context, VT); } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 5ebec6b8fa13..ee44ff66e6f4 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1189,6 +1189,7 @@ bool SPIRVInstructionSelector::selectConst(Register ResVReg, .addUse(GR.getSPIRVTypeID(ResType)) .constrainAllUses(TII, TRI, RBI); if (TyOpcode == SPIRV::OpTypeInt) { + assert(Imm.getBitWidth() <= 64 && "Unsupported integer width!"); Register Reg = GR.getOrCreateConstInt(Imm.getZExtValue(), I, ResType, TII); if (Reg == ResVReg) return true; diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index af48d51a056f..f2a3e8ab6196 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -593,6 +593,12 @@ void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) { // TODO: verify if this needs some checks. addAvailableCaps({Capability::Float16, Capability::Float64}); + // Add capabilities enabled by extensions. + for (auto Extension : ST.getAllAvailableExtensions()) { + CapabilityList EnabledCapabilities = + getCapabilitiesEnabledByExtension(Extension); + addAvailableCaps(EnabledCapabilities); + } // TODO: add OpenCL extensions. } } // namespace SPIRV diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index 0a89f0151198..30e9008c155a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -27,6 +27,19 @@ using namespace llvm; #define GET_SUBTARGETINFO_CTOR #include "SPIRVGenSubtargetInfo.inc" +cl::list Extensions( + "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, + cl::Hidden, + cl::values( + clEnumValN( + SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers, + "SPV_INTEL_arbitrary_precision_integers", + "Allows generating arbitrary width integer types"), + clEnumValN(SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration, + "SPV_KHR_no_integer_wrap_decoration", + "Adds decorations to indicate that a given instruction does " + "not cause integer wrapping"))); + // Compare version numbers, but allow 0 to mean unspecified. static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { return Target == 0 || Target >= VerToCompareTo; @@ -90,14 +103,14 @@ bool SPIRVSubtarget::canDirectlyComparePointers() const { return isAtLeastVer(SPIRVVersion, 14); } -// TODO: use command line args for this rather than defaults. void SPIRVSubtarget::initAvailableExtensions() { AvailableExtensions.clear(); if (!isOpenCLEnv()) return; - // A default extension for testing. - AvailableExtensions.insert( - SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration); + + for (auto Extension : Extensions) { + AvailableExtensions.insert(Extension); + } } // TODO: use command line args for this rather than just defaults. diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h index dd19a1d0a9bb..f33ac81ef6d0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h @@ -79,6 +79,10 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo { // TODO: implement command line args or other ways to determine this. bool hasOpenCLFullProfile() const { return true; } bool hasOpenCLImageSupport() const { return true; } + const SmallSet & + getAllAvailableExtensions() const { + return AvailableExtensions; + } bool canUseExtension(SPIRV::Extension::Extension E) const; bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const; @@ -106,6 +110,10 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo { const SPIRVRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } + + static bool classof(const TargetSubtargetInfo *ST) { + return ST->getTargetTriple().isSPIRV(); + } }; } // namespace llvm diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 1b36c10df15b..91b13b7a3806 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -77,6 +77,12 @@ def ExtensionEntries : GenericTable { let PrimaryKeyName = "lookupExtensionByCategoryAndValue"; } +// Function to lookup symbolic operands enabled by a given extension. +def lookupSymbolicOperandsEnabledByExtension : SearchIndex { + let Table = ExtensionEntries; + let Key = ["ReqExtension", "Category"]; +} + //===----------------------------------------------------------------------===// // Lookup table for matching symbolic operands (category + 32-bit value) to // SPIR-V capabilities. If an operand requires more than one capability, there @@ -243,6 +249,51 @@ defm SPV_KHR_shader_clock : ExtensionOperand<54>; defm SPV_INTEL_unstructured_loop_controls : ExtensionOperand<55>; defm SPV_EXT_demote_to_helper_invocation : ExtensionOperand<56>; defm SPV_INTEL_fpga_reg : ExtensionOperand<57>; +defm SPV_INTEL_blocking_pipes : ExtensionOperand<58>; +defm SPV_GOOGLE_user_type : ExtensionOperand<59>; +defm SPV_KHR_physical_storage_buffer : ExtensionOperand<60>; +defm SPV_INTEL_kernel_attributes : ExtensionOperand<61>; +defm SPV_KHR_non_semantic_info : ExtensionOperand<62>; +defm SPV_INTEL_io_pipes : ExtensionOperand<63>; +defm SPV_KHR_ray_tracing : ExtensionOperand<64>; +defm SPV_KHR_ray_query : ExtensionOperand<65>; +defm SPV_INTEL_fpga_memory_accesses : ExtensionOperand<66>; +defm SPV_INTEL_arbitrary_precision_integers : ExtensionOperand<67>; +defm SPV_EXT_shader_atomic_float_add : ExtensionOperand<68>; +defm SPV_KHR_terminate_invocation : ExtensionOperand<69>; +defm SPV_KHR_fragment_shading_rate : ExtensionOperand<70>; +defm SPV_EXT_shader_image_int64 : ExtensionOperand<71>; +defm SPV_INTEL_fp_fast_math_mode : ExtensionOperand<72>; +defm SPV_INTEL_fpga_cluster_attributes : ExtensionOperand<73>; +defm SPV_INTEL_loop_fuse : ExtensionOperand<74>; +defm SPV_EXT_shader_atomic_float_min_max : ExtensionOperand<75>; +defm SPV_KHR_workgroup_memory_explicit_layout : ExtensionOperand<76>; +defm SPV_KHR_linkonce_odr : ExtensionOperand<77>; +defm SPV_KHR_expect_assume : ExtensionOperand<78>; +defm SPV_INTEL_fpga_dsp_control : ExtensionOperand<79>; +defm SPV_NV_bindless_texture : ExtensionOperand<80>; +defm SPV_INTEL_fpga_invocation_pipelining_attributes : ExtensionOperand<81>; +defm SPV_KHR_subgroup_uniform_control_flow : ExtensionOperand<82>; +defm SPV_HUAWEI_subpass_shading : ExtensionOperand<83>; +defm SPV_KHR_integer_dot_product : ExtensionOperand<84>; +defm SPV_EXT_shader_atomic_float16_add : ExtensionOperand<85>; +defm SPV_INTEL_runtime_aligned : ExtensionOperand<86>; +defm SPV_KHR_bit_instructions : ExtensionOperand<87>; +defm SPV_NV_ray_tracing_motion_blur : ExtensionOperand<88>; +defm SPV_KHR_uniform_group_instructions : ExtensionOperand<89>; +defm SPV_KHR_subgroup_rotate : ExtensionOperand<90>; +defm SPV_INTEL_split_barrier : ExtensionOperand<91>; +defm SPV_KHR_ray_cull_mask : ExtensionOperand<92>; +defm SPV_KHR_fragment_shader_barycentric : ExtensionOperand<93>; +defm SPV_EXT_relaxed_printf_string_address_space : ExtensionOperand<94>; +defm SPV_EXT_ycbcr_attachments : ExtensionOperand<95>; +defm SPV_EXT_mesh_shader : ExtensionOperand<96>; +defm SPV_ARM_core_builtins : ExtensionOperand<97>; +defm SPV_EXT_opacity_micromap : ExtensionOperand<98>; +defm SPV_NV_shader_invocation_reorder : ExtensionOperand<99>; +defm SPV_INTEL_usm_storage_classes : ExtensionOperand<100>; +defm SPV_INTEL_fpga_latency_control : ExtensionOperand<101>; +defm SPV_INTEL_fpga_argument_interfaces : ExtensionOperand<102>; //===----------------------------------------------------------------------===// // Multiclass used to define Capabilities enum values and at the same time @@ -396,6 +447,7 @@ defm ComputeDerivativeGroupLinearNV : CapabilityOperand<5350, 0, 0, [], []>; defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>; defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>; defm CooperativeMatrixNV : CapabilityOperand<5357, 0, 0, [], [Shader]>; +defm ArbitraryPrecisionIntegersINTEL : CapabilityOperand<5844, 0, 0, [SPV_INTEL_arbitrary_precision_integers], [Int8, Int16]>; //===----------------------------------------------------------------------===// // Multiclass used to define SourceLanguage enum values and at the same time diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index 89bb28abfd4f..060293e5a05e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -77,24 +77,19 @@ std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) { void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) { const auto Bitwidth = Imm.getBitWidth(); - switch (Bitwidth) { - case 1: - break; // Already handled. - case 8: - case 16: - case 32: + if (Bitwidth == 1) + return; // Already handled + else if (Bitwidth <= 32) { MIB.addImm(Imm.getZExtValue()); - break; - case 64: { + return; + } else if (Bitwidth <= 64) { uint64_t FullImm = Imm.getZExtValue(); uint32_t LowBits = FullImm & 0xffffffff; uint32_t HighBits = (FullImm >> 32) & 0xffffffff; MIB.addImm(LowBits).addImm(HighBits); - break; - } - default: - report_fatal_error("Unsupported constant bitwidth"); + return; } + report_fatal_error("Unsupported constant bitwidth"); } void buildOpName(Register Target, const StringRef &Name, @@ -331,16 +326,6 @@ std::string getOclOrSpirvBuiltinDemangledName(StringRef Name) { 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()) @@ -348,9 +333,20 @@ const Type *getTypedPtrEltType(const Type *Ty) { 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/constant/local-arbitrary-width-integers-constants-type-promotion.ll b/llvm/test/CodeGen/SPIRV/constant/local-arbitrary-width-integers-constants-type-promotion.ll new file mode 100644 index 000000000000..06ab469e7007 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/constant/local-arbitrary-width-integers-constants-type-promotion.ll @@ -0,0 +1,58 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s + +define i4 @getConstantI4() { + ret i4 2 ; i4 => OpTypeInt 8 +} + +define i11 @getConstantI11() { + ret i11 7 ; i11 => OpTypeInt 16 +} + +define i24 @getConstantI24() { + ret i24 42 ; i24 => OpTypeInt 32 +} + +define i63 @getConstantI63() { + ret i63 5705 ; i63 => OpTypeInt 64 +} + +;; Capabilities: +; CHECK-DAG: OpCapability Int8 +; CHECK-DAG: OpCapability Int16 +; CHECK-DAG: OpCapability Int64 + +; CHECK-NOT: DAG-FENCE + +;; Names: +; CHECK-DAG: OpName %[[#GET_I4:]] "getConstantI4" +; CHECK-DAG: OpName %[[#GET_I11:]] "getConstantI11" +; CHECK-DAG: OpName %[[#GET_I24:]] "getConstantI24" +; CHECK-DAG: OpName %[[#GET_I63:]] "getConstantI63" + +; CHECK-NOT: DAG-FENCE + +;; Types and Constants: +; CHECK-DAG: %[[#I8:]] = OpTypeInt 8 0 +; CHECK-DAG: %[[#I16:]] = OpTypeInt 16 0 +; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#CST_I8:]] = OpConstant %[[#I8]] 2 +; CHECK-DAG: %[[#CST_I16:]] = OpConstant %[[#I16]] 7 +; CHECK-DAG: %[[#CST_I32:]] = OpConstant %[[#I32]] 42 +; CHECK-DAG: %[[#CST_I64:]] = OpConstant %[[#I64]] 5705 + +; CHECK: %[[#GET_I4]] = OpFunction %[[#I8]] +; CHECK: OpReturnValue %[[#CST_I8]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I11]] = OpFunction %[[#I16]] +; CHECK: OpReturnValue %[[#CST_I16]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I24]] = OpFunction %[[#I32]] +; CHECK: OpReturnValue %[[#CST_I32]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I63]] = OpFunction %[[#I64]] +; CHECK: OpReturnValue %[[#CST_I64]] +; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll b/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll index 0530d1ffa4c6..9660ba446cfc 100644 --- a/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll +++ b/llvm/test/CodeGen/SPIRV/constant/local-integers-constants.ll @@ -1,5 +1,9 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +define i8 @getConstantI8() { + ret i8 2 +} + define i16 @getConstantI16() { ret i16 -58 } @@ -17,12 +21,14 @@ define i64 @getLargeConstantI64() { } ;; Capabilities: +; CHECK-DAG: OpCapability Int8 ; CHECK-DAG: OpCapability Int16 ; CHECK-DAG: OpCapability Int64 ; CHECK-NOT: DAG-FENCE ;; Names: +; CHECK-DAG: OpName %[[#GET_I8:]] "getConstantI8" ; CHECK-DAG: OpName %[[#GET_I16:]] "getConstantI16" ; CHECK-DAG: OpName %[[#GET_I32:]] "getConstantI32" ; CHECK-DAG: OpName %[[#GET_I64:]] "getConstantI64" @@ -31,14 +37,20 @@ define i64 @getLargeConstantI64() { ; CHECK-NOT: DAG-FENCE ;; Types and Constants: +; CHECK-DAG: %[[#I8:]] = OpTypeInt 8 0 ; CHECK-DAG: %[[#I16:]] = OpTypeInt 16 0 ; CHECK-DAG: %[[#I32:]] = OpTypeInt 32 0 ; CHECK-DAG: %[[#I64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#CST_I8:]] = OpConstant %[[#I8]] 2 ; CHECK-DAG: %[[#CST_I16:]] = OpConstant %[[#I16]] 65478 ; CHECK-DAG: %[[#CST_I32:]] = OpConstant %[[#I32]] 42 ; CHECK-DAG: %[[#CST_I64:]] = OpConstant %[[#I64]] 123456789 0 ; CHECK-DAG: %[[#CST_LARGE_I64:]] = OpConstant %[[#I64]] 0 8 +; CHECK: %[[#GET_I8]] = OpFunction %[[#I8]] +; CHECK: OpReturnValue %[[#CST_I8]] +; CHECK: OpFunctionEnd + ; CHECK: %[[#GET_I16]] = OpFunction %[[#I16]] ; CHECK: OpReturnValue %[[#CST_I16]] ; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll new file mode 100644 index 000000000000..b68fb363ad85 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll @@ -0,0 +1,35 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s + +define i6 @getConstantI6() { + ret i6 2 +} + +define i13 @getConstantI13() { + ret i13 42 +} + +;; Capabilities: +; CHECK-DAG: OpExtension "SPV_INTEL_arbitrary_precision_integers" +; CHECK-DAG: OpCapability ArbitraryPrecisionIntegersINTEL + +; CHECK-NOT: DAG-FENCE + +;; Names: +; CHECK-DAG: OpName %[[#GET_I6:]] "getConstantI6" +; CHECK-DAG: OpName %[[#GET_I13:]] "getConstantI13" + +; CHECK-NOT: DAG-FENCE + +;; Types and Constants: +; CHECK-DAG: %[[#I6:]] = OpTypeInt 6 0 +; CHECK-DAG: %[[#I13:]] = OpTypeInt 13 0 +; CHECK-DAG: %[[#CST_I6:]] = OpConstant %[[#I6]] 2 +; CHECK-DAG: %[[#CST_I13:]] = OpConstant %[[#I13]] 42 + +; CHECK: %[[#GET_I6]] = OpFunction %[[#I6]] +; CHECK: OpReturnValue %[[#CST_I6]] +; CHECK: OpFunctionEnd + +; CHECK: %[[#GET_I13]] = OpFunction %[[#I13]] +; CHECK: OpReturnValue %[[#CST_I13]] +; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll similarity index 90% rename from llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll rename to llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll index a988b0a3bfff..e74dd99617f9 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/no_wrap.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s ; CHECK-DAG: OpExtension "SPV_KHR_no_integer_wrap_decoration" diff --git a/llvm/test/CodeGen/SPIRV/image_store.ll b/llvm/test/CodeGen/SPIRV/image_store.ll index e66d1821142b..3542cc2e8e9b 100644 --- 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 index 6c0e11998f6f..d8175a6dda8c 100644 --- 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/NoSignedUnsignedWrap.ll b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll index 5a67dc259942..02d1250399f9 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll @@ -7,7 +7,7 @@ ;; ;; Positive tests: ;; -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE ;; ;; Negative tests: ;; diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll index 25ecb4f6d94f..f8db0ba2c1cd 100644 --- 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 @@ entry: ; 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 @@ define spir_func void @bar( ; 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)