Skip to content

Commit

Permalink
[SPIRV] Add support for cl_khr_extended_bit_ops (#120571)
Browse files Browse the repository at this point in the history
This PR adds support for `cl_khr_extended_bit_ops` in SPIRV Backend.
Note that `cl_khr_extended_bit_ops` only supports types in
```
char, charn, uchar, ucharn, short, shortn, ushort, ushortn, int, intn, uint, uintn, long, longn, ulong, and ulongn
```
where `n is 2, 3, 4, 8, or 16`.

Subsequent PRs will introduce support for non-standard bit width
required by `SPV_KHR_bit_instructions`.
  • Loading branch information
maarquitos14 authored Feb 11, 2025
1 parent 64735ad commit a09beae
Show file tree
Hide file tree
Showing 6 changed files with 2,999 additions and 0 deletions.
45 changes: 45 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,38 @@ static bool buildBarrierInst(const SPIRV::IncomingCall *Call, unsigned Opcode,
return true;
}

/// Helper function for building extended bit operations.
static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call,
unsigned Opcode,
MachineIRBuilder &MIRBuilder,
SPIRVGlobalRegistry *GR) {
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
const auto *ST =
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
if ((Opcode == SPIRV::OpBitFieldInsert ||
Opcode == SPIRV::OpBitFieldSExtract ||
Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
!ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
std::string DiagMsg = std::string(Builtin->Name) +
": the builtin requires the following SPIR-V "
"extension: SPV_KHR_bit_instructions";
report_fatal_error(DiagMsg.c_str(), false);
}

// Generate SPIRV instruction accordingly.
if (Call->isSpirvOp())
return buildOpFromWrapper(MIRBuilder, Opcode, Call,
GR->getSPIRVTypeID(Call->ReturnType));

auto MIB = MIRBuilder.buildInstr(Opcode)
.addDef(Call->ReturnRegister)
.addUse(GR->getSPIRVTypeID(Call->ReturnType));
for (unsigned i = 0; i < Call->Arguments.size(); ++i)
MIB.addUse(Call->Arguments[i]);

return true;
}

static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim) {
switch (dim) {
case SPIRV::Dim::DIM_1D:
Expand Down Expand Up @@ -2180,6 +2212,17 @@ static bool generateSpecConstantInst(const SPIRV::IncomingCall *Call,
}
}

static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call,
MachineIRBuilder &MIRBuilder,
SPIRVGlobalRegistry *GR) {
// Lookup the instruction opcode in the TableGen records.
const SPIRV::DemangledBuiltin *Builtin = Call->Builtin;
unsigned Opcode =
SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

return buildExtendedBitOpsInst(Call, Opcode, MIRBuilder, GR);
}

static bool buildNDRange(const SPIRV::IncomingCall *Call,
MachineIRBuilder &MIRBuilder,
SPIRVGlobalRegistry *GR) {
Expand Down Expand Up @@ -2755,6 +2798,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall,
return generateKernelClockInst(Call.get(), MIRBuilder, GR);
case SPIRV::CoopMatr:
return generateCoopMatrInst(Call.get(), MIRBuilder, GR);
case SPIRV::ExtendedBitOps:
return generateExtendedBitOpsInst(Call.get(), MIRBuilder, GR);
}
return false;
}
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVBuiltins.td
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def CastToPtr : BuiltinGroup;
def Construct : BuiltinGroup;
def CoopMatr : BuiltinGroup;
def ICarryBorrow : BuiltinGroup;
def ExtendedBitOps : BuiltinGroup;

//===----------------------------------------------------------------------===//
// Class defining a demangled builtin record. The information in the record
Expand Down Expand Up @@ -1465,6 +1466,16 @@ defm : DemangledNativeBuiltin<"__spirv_SatConvertSToU", OpenCL_std, Convert, 1,
defm : DemangledNativeBuiltin<"__spirv_SatConvertUToS", OpenCL_std, Convert, 1, 1, OpSatConvertUToS>;
defm : DemangledNativeBuiltin<"__spirv_ConvertUToPtr", OpenCL_std, Convert, 1, 1, OpConvertUToPtr>;

// cl_khr_extended_bit_ops / SPV_KHR_bit_instructions
defm : DemangledNativeBuiltin<"bitfield_insert", OpenCL_std, ExtendedBitOps, 4, 4, OpBitFieldInsert>;
defm : DemangledNativeBuiltin<"__spirv_BitFieldInsert", OpenCL_std, ExtendedBitOps, 4, 4, OpBitFieldInsert>;
defm : DemangledNativeBuiltin<"bitfield_extract_signed", OpenCL_std, ExtendedBitOps, 3, 3, OpBitFieldSExtract>;
defm : DemangledNativeBuiltin<"__spirv_BitFieldSExtract", OpenCL_std, ExtendedBitOps, 3, 3, OpBitFieldSExtract>;
defm : DemangledNativeBuiltin<"bitfield_extract_unsigned", OpenCL_std, ExtendedBitOps, 3, 3, OpBitFieldUExtract>;
defm : DemangledNativeBuiltin<"__spirv_BitFieldUExtract", OpenCL_std, ExtendedBitOps, 3, 3, OpBitFieldUExtract>;
defm : DemangledNativeBuiltin<"bit_reverse", OpenCL_std, ExtendedBitOps, 1, 1, OpBitReverse>;
defm : DemangledNativeBuiltin<"__spirv_BitReverse", OpenCL_std, ExtendedBitOps, 1, 1, OpBitReverse>;

// cl_intel_bfloat16_conversions / SPV_INTEL_bfloat16_conversion
// Multiclass used to define at the same time both a demangled builtin records
// and a corresponding convert builtin records.
Expand Down
Loading

0 comments on commit a09beae

Please sign in to comment.