[llvm] 5ac6967 - [SPIR-V] Support TargetExtType for SPIR-V builtin types
Michal Paszkowski via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 27 12:40:13 PST 2023
Author: Michal Paszkowski
Date: 2023-02-27T21:39:25+01:00
New Revision: 5ac69674bf4fbe4adaca4170a2ad60c8a32613ed
URL: https://github.com/llvm/llvm-project/commit/5ac69674bf4fbe4adaca4170a2ad60c8a32613ed
DIFF: https://github.com/llvm/llvm-project/commit/5ac69674bf4fbe4adaca4170a2ad60c8a32613ed.diff
LOG: [SPIR-V] Support TargetExtType for SPIR-V builtin types
This patch adds support for TargetExtType/target(...) representing
SPIR-V builtin types. After D135202, target(...) is the preferred way
for representing SPIR-V builtin types in LLVM IR and the only working
in the opaque pointer mode.
In order to maintain compatibility with LLVM IR generated by older
versions of Clang and LLVM/SPIR-V Translator, pointers-to-opaque-structs
denoting SPIR-V/OpenCL builtin types will be translated to equivalent
SPIR-V target extension types. This translation is only available in the
typed pointer mode (-opaque-pointers=0).
The relevant LIT tests with SPIR-V builtins were converted to use the
new target(...) notation.
Differential Revision: https://reviews.llvm.org/D144494
Added:
Modified:
llvm/lib/CodeGen/ValueTypes.cpp
llvm/lib/IR/Type.cpp
llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
llvm/lib/Target/SPIRV/SPIRVBuiltins.h
llvm/lib/Target/SPIRV/SPIRVBuiltins.td
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
llvm/lib/Target/SPIRV/SPIRVUtils.cpp
llvm/test/CodeGen/SPIRV/image_store.ll
llvm/test/CodeGen/SPIRV/spirv.Queue.ll
llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index 99590d99ddb8d..753650dc3eb0c 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -590,6 +590,8 @@ 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 3d02ad2bba720..8c77e9862df07 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/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
index d3876f4ba7469..1e0f8ca87a20c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
@@ -1913,135 +1913,106 @@ std::optional<bool> 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<const SPIRV::ImageType>
-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<SPIRV::ImageType>(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<StringRef> 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<SPIRV::ImageType>(new SPIRV::ImageType{
- Name, SampledType, SPIRV::AccessQualifier::AccessQualifier(AccessQual),
- SPIRV::Dim::Dim(Dim), static_cast<bool>(Arrayed),
- static_cast<bool>(Depth), static_cast<bool>(Multisampled),
- static_cast<bool>(Sampled), SPIRV::ImageFormat::ImageFormat(Format)});
-}
-static std::unique_ptr<const SPIRV::PipeType>
-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<SPIRV::PipeType>(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<StringRef> Parameters;
+ unsigned BaseNameLength = NameWithParameters.find('_') - 1;
+ SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_");
+
+ SmallVector<Type *, 1> TypeParameters;
+ bool HasTypeParamter = !isDigit(Parameters[0][0]);
+ if (HasTypeParamter)
+ TypeParameters.push_back(parseTypeString(
+ Parameters[0], MIRBuilder.getMF().getFunction().getContext()));
+ SmallVector<unsigned> 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<SPIRV::PipeType>(
- new SPIRV::PipeType{Name, SPIRV::AccessQualifier::ReadOnly});
- if (Name.endswith("_1"))
- return std::unique_ptr<SPIRV::PipeType>(
- new SPIRV::PipeType{Name, SPIRV::AccessQualifier::WriteOnly});
- if (Name.endswith("_2"))
- return std::unique_ptr<SPIRV::PipeType>(
- 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 @@ 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<const SPIRV::PipeType> 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<const SPIRV::ImageType> 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<TargetExtType>(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 @@ 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 26d2e8ab0fd6b..7ee5c49dc5b32 100644
--- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
+++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.h
@@ -45,7 +45,7 @@ std::optional<bool> 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 635c6451ea04a..8acd4691787e4 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<string name, Op operation> {
+class BuiltinType<string name, Op operation> {
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<string name> {
+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, string spirvTypeLiteral> {
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<string name> {
- def : DemangledType<name, OpTypeImage>;
- def : ImageType<name>;
+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<!strconcat("opencl.pipe", aq),
+ !strconcat("spirv.Pipe._", p)>;
}
foreach aq = ["_t", "_ro_t", "_wo_t", "_rw_t"] in {
- defm : DemangledImageType<!strconcat("opencl.image1d", aq)>;
- defm : DemangledImageType<!strconcat("opencl.image1d_array", aq)>;
- defm : DemangledImageType<!strconcat("opencl.image1d_buffer", aq)>;
+ defvar p7 = !cond(!not(!eq(!find(aq, "_rw_t"), -1)) : "2",
+ !not(!eq(!find(aq, "_wo_t"), -1)) : "1",
+ true : "0");
+
+ def : OpenCLType<!strconcat("opencl.image1d", aq),
+ !strconcat("spirv.Image._void_0_0_0_0_0_0_", p7)>;
+ def : OpenCLType<!strconcat("opencl.image1d_array", aq),
+ !strconcat("spirv.Image._void_0_0_1_0_0_0_", p7)>;
+ def : OpenCLType<!strconcat("opencl.image1d_buffer", aq),
+ !strconcat("spirv.Image._void_5_0_0_0_0_0_", p7)>;
foreach a1 = ["", "_array"] in {
foreach a2 = ["", "_msaa"] in {
foreach a3 = ["", "_depth"] in {
- defm : DemangledImageType<!strconcat("opencl.image2d", a1, a2, a3, aq)>;
+ 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<!strconcat("opencl.image2d", a1, a2, a3, aq),
+ !strconcat("spirv.Image._void_1_", p2 , "_", p3, "_", p4, "_0_0_", p7)>;
}
}
}
-
- defm : DemangledImageType<!strconcat("opencl.image3d", aq)>;
-}
-
-// Class definining lowering details for various variants of pipe type indentifiers.
-class PipeType<string name> {
- 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<string name> {
- def : DemangledType<name, OpTypePipe>;
- def : PipeType<name>;
-}
-
-foreach aq = ["_t", "_ro_t", "_wo_t", "_rw_t"] in {
- defm : DemangledPipeType<!strconcat("opencl.pipe", aq)>;
+
+ def : OpenCLType<!strconcat("opencl.image3d", aq),
+ !strconcat("spirv.Image._void_2_0_0_0_0_0_", p7)>;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 0f85c4839e107..7da239cd31ff7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -573,9 +573,8 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSpecialType(
assert(!PType->isOpaque());
Ty = PType->getNonOpaquePointerElementType();
}
- auto SType = cast<StructType>(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
index df1817f91cf87..b6353ec2fb6b4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -332,16 +332,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<PointerType>(Ty);
if (!PType || PType->isOpaque())
@@ -349,9 +339,21 @@ 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<StructType>(getTypedPtrEltType(Ty)))
- return isOpenCLBuiltinType(SType) || isSPIRVBuiltinType(SType);
+ const StructType *SType = dyn_cast<StructType>(getTypedPtrEltType(Ty));
+ if (SType && SType->hasName())
+ return hasBuiltinTypePrefix(SType->getName());
+
+ if (const TargetExtType *EType =
+ dyn_cast<TargetExtType>(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
index e66d1821142b3..3542cc2e8e9b3 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 6c0e11998f6f5..d8175a6dda8c0 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/spirv-types.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-types.ll
index 25ecb4f6d94f1..f8db0ba2c1cd4 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)
More information about the llvm-commits
mailing list