Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/ValueTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/IR/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SPIRV::Capability::Capability>(Entry->Value));
++Entry;
}

return Capabilities;
}

ExtensionList
getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,
uint32_t Value) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
265 changes: 123 additions & 142 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion llvm/lib/Target/SPIRV/SPIRVBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
166 changes: 65 additions & 101 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)>;
}

//===----------------------------------------------------------------------===//
Expand Down
23 changes: 20 additions & 3 deletions llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SPIRVSubtarget>(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)
Expand Down Expand Up @@ -573,9 +591,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(
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am considering extracting generating all instructions relevant to extensions (decorations, capabilities, etc.) out to a separate pass. I will prepare a an experimental pull request.

If it works out, I will consider extracting emitting capabilities also to a separate pass. Then SPIRVModuleAnalysis would truly be "analysis only" pass.

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 17 additions & 4 deletions llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ using namespace llvm;
#define GET_SUBTARGETINFO_CTOR
#include "SPIRVGenSubtargetInfo.inc"

cl::list<SPIRV::Extension::Extension> 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;
Expand Down Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<SPIRV::Extension::Extension, 4> &
getAllAvailableExtensions() const {
return AvailableExtensions;
}
bool canUseExtension(SPIRV::Extension::Extension E) const;
bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const;

Expand Down Expand Up @@ -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

Expand Down
Loading