21#include "llvm/IR/IntrinsicsSPIRV.h"
26#define DEBUG_TYPE "spirv-builtins"
30#define GET_BuiltinGroup_DECL
31#include "SPIRVGenTables.inc"
35 InstructionSet::InstructionSet
Set;
43#define GET_DemangledBuiltins_DECL
44#define GET_DemangledBuiltins_IMPL
66 InstructionSet::InstructionSet
Set;
70#define GET_NativeBuiltins_DECL
71#define GET_NativeBuiltins_IMPL
89#define GET_GroupBuiltins_DECL
90#define GET_GroupBuiltins_IMPL
100#define GET_IntelSubgroupsBuiltins_DECL
101#define GET_IntelSubgroupsBuiltins_IMPL
108#define GET_AtomicFloatingBuiltins_DECL
109#define GET_AtomicFloatingBuiltins_IMPL
116#define GET_GroupUniformBuiltins_DECL
117#define GET_GroupUniformBuiltins_IMPL
121 InstructionSet::InstructionSet
Set;
126#define GET_GetBuiltins_DECL
127#define GET_GetBuiltins_IMPL
131 InstructionSet::InstructionSet
Set;
135#define GET_ImageQueryBuiltins_DECL
136#define GET_ImageQueryBuiltins_IMPL
144#define GET_IntegerDotProductBuiltins_DECL
145#define GET_IntegerDotProductBuiltins_IMPL
149 InstructionSet::InstructionSet
Set;
160 InstructionSet::InstructionSet
Set;
168#define GET_ConvertBuiltins_DECL
169#define GET_ConvertBuiltins_IMPL
171using namespace InstructionSet;
172#define GET_VectorLoadStoreBuiltins_DECL
173#define GET_VectorLoadStoreBuiltins_IMPL
175#define GET_CLMemoryScope_DECL
176#define GET_CLSamplerAddressingMode_DECL
177#define GET_CLMemoryFenceFlags_DECL
178#define GET_ExtendedBuiltins_DECL
179#include "SPIRVGenTables.inc"
183 return getDemangledBuiltinStr(
Name);
196 StringRef PassPrefix =
"(anonymous namespace)::";
198 std::string BuiltinName = DemangledCall.
str();
203 std::size_t Pos = BuiltinName.find(
">(");
204 if (Pos != std::string::npos) {
205 BuiltinName = BuiltinName.substr(0, BuiltinName.rfind(
'<', Pos));
207 Pos = BuiltinName.find(
'(');
208 if (Pos != std::string::npos)
209 BuiltinName = BuiltinName.substr(0, Pos);
211 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(
' ') + 1);
215 if (BuiltinName.find(PassPrefix) == 0)
216 BuiltinName = BuiltinName.substr(PassPrefix.
size());
217 else if (BuiltinName.find(SpvPrefix) == 0)
218 BuiltinName = BuiltinName.substr(SpvPrefix.
size());
221 if (BuiltinName.rfind(
"__spirv_ocl_", 0) == 0)
222 BuiltinName = BuiltinName.substr(12);
248 static const std::regex SpvWithR(
249 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"
251 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"
252 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
253 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
255 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");
257 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
258 std::ssub_match SubMatch;
259 if (DecorationId && Match.size() > 3) {
264 BuiltinName = SubMatch.str();
281static std::unique_ptr<const SPIRV::IncomingCall>
283 SPIRV::InstructionSet::InstructionSet Set,
290 DemangledCall.
slice(DemangledCall.
find(
'(') + 1, DemangledCall.
find(
')'));
291 BuiltinArgs.
split(BuiltinArgumentTypes,
',', -1,
false);
296 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))
297 return std::make_unique<SPIRV::IncomingCall>(
298 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
303 if (BuiltinArgumentTypes.
size() >= 1) {
304 char FirstArgumentType = BuiltinArgumentTypes[0][0];
311 switch (FirstArgumentType) {
314 if (Set == SPIRV::InstructionSet::OpenCL_std)
316 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
325 if (Set == SPIRV::InstructionSet::OpenCL_std)
327 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
335 if (Set == SPIRV::InstructionSet::OpenCL_std ||
336 Set == SPIRV::InstructionSet::GLSL_std_450)
343 if (!Prefix.empty() &&
344 (Builtin = SPIRV::lookupBuiltin((Prefix + BuiltinName).str(), Set)))
345 return std::make_unique<SPIRV::IncomingCall>(
346 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
348 if (!Suffix.
empty() &&
349 (Builtin = SPIRV::lookupBuiltin((BuiltinName + Suffix).str(), Set)))
350 return std::make_unique<SPIRV::IncomingCall>(
351 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
363 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
364 MI->getOperand(1).isReg());
365 Register BitcastReg =
MI->getOperand(1).getReg();
367 assert(BitcastMI &&
"Definition for source reg not found.");
368 if (BitcastMI->
getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
383 Register ValueReg =
MI->getOperand(0).getReg();
389 assert(Ty &&
"Type is expected");
401 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
402 return MI->getOperand(1).getGlobal()->getValueType();
404 "Blocks in OpenCL C must be traceable to allocation site");
416static std::tuple<Register, SPIRVTypeInst>
422 if (ResultType->
getOpcode() == SPIRV::OpTypeVector) {
437 return std::make_tuple(ResultRegister, BoolType);
447 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {
458 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
468 if (!DestinationReg.isValid())
473 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
474 return DestinationReg;
483 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
484 SPIRV::LinkageType::Import}) {
492 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
498 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
505 return LoadedRegister;
516static SPIRV::MemorySemantics::MemorySemantics
519 case std::memory_order_relaxed:
520 return SPIRV::MemorySemantics::None;
521 case std::memory_order_acquire:
522 return SPIRV::MemorySemantics::Acquire;
523 case std::memory_order_release:
524 return SPIRV::MemorySemantics::Release;
525 case std::memory_order_acq_rel:
526 return SPIRV::MemorySemantics::AcquireRelease;
527 case std::memory_order_seq_cst:
528 return SPIRV::MemorySemantics::SequentiallyConsistent;
536 case SPIRV::CLMemoryScope::memory_scope_work_item:
537 return SPIRV::Scope::Invocation;
538 case SPIRV::CLMemoryScope::memory_scope_work_group:
539 return SPIRV::Scope::Workgroup;
540 case SPIRV::CLMemoryScope::memory_scope_device:
541 return SPIRV::Scope::Device;
542 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
543 return SPIRV::Scope::CrossDevice;
544 case SPIRV::CLMemoryScope::memory_scope_sub_group:
545 return SPIRV::Scope::Subgroup;
558 SPIRV::Scope::Scope Scope,
562 if (CLScopeRegister.
isValid()) {
564 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(CLScopeRegister, MRI));
567 if (CLScope ==
static_cast<unsigned>(Scope)) {
568 MRI->
setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
569 return CLScopeRegister;
581 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
585 Register PtrRegister,
unsigned &Semantics,
588 if (SemanticsRegister.
isValid()) {
590 std::memory_order Order =
591 static_cast<std::memory_order
>(
getIConstVal(SemanticsRegister, MRI));
595 if (
static_cast<unsigned>(Order) == Semantics) {
596 MRI->
setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);
597 return SemanticsRegister;
610 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
611 for (
unsigned i = 0; i < Sz; ++i)
612 MIB.addUse(
Call->Arguments[i]);
621 if (
Call->isSpirvOp())
625 "Need 2 arguments for atomic init translation");
637 if (
Call->isSpirvOp())
645 Call->Arguments.size() > 1
649 if (
Call->Arguments.size() > 2) {
651 MemSemanticsReg =
Call->Arguments[2];
654 SPIRV::MemorySemantics::SequentiallyConsistent |
672 if (
Call->isSpirvOp())
680 SPIRV::MemorySemantics::SequentiallyConsistent |
695 if (
Call->isSpirvOp())
699 bool IsCmpxchg =
Call->Builtin->name().contains(
"cmpxchg");
709 SPIRV::OpTypePointer);
712 assert(IsCmpxchg ? ExpectedType == SPIRV::OpTypeInt
713 : ExpectedType == SPIRV::OpTypePointer);
718 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
726 ? SPIRV::MemorySemantics::None
727 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
730 ? SPIRV::MemorySemantics::None
731 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
732 if (
Call->Arguments.size() >= 4) {
734 "Need 5+ args for explicit atomic cmpxchg");
741 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
742 MemSemEqualReg =
Call->Arguments[3];
743 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
744 MemSemUnequalReg =
Call->Arguments[4];
748 if (!MemSemUnequalReg.
isValid())
752 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
753 if (
Call->Arguments.size() >= 6) {
755 "Extra args for explicit atomic cmpxchg");
756 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
759 if (ClScope ==
static_cast<unsigned>(Scope))
760 ScopeReg =
Call->Arguments[5];
766 IsCmpxchg ? ExpectedArg
770 :
Call->ReturnRegister;
795 if (
Call->isSpirvOp())
804 "Too many args for explicit atomic RMW");
805 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
806 MIRBuilder, GR, MRI);
809 unsigned Semantics = SPIRV::MemorySemantics::None;
813 Semantics, MIRBuilder, GR);
817 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
818 if (Opcode == SPIRV::OpAtomicIAdd) {
819 Opcode = SPIRV::OpAtomicFAddEXT;
820 }
else if (Opcode == SPIRV::OpAtomicISub) {
823 Opcode = SPIRV::OpAtomicFAddEXT;
834 ValueReg = NegValueReg;
853 "Wrong number of atomic floating-type builtin");
873 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
875 if (
Call->isSpirvOp())
881 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
885 Semantics, MIRBuilder, GR);
887 assert((Opcode != SPIRV::OpAtomicFlagClear ||
888 (Semantics != SPIRV::MemorySemantics::Acquire &&
889 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
890 "Invalid memory order argument!");
895 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
913 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
914 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
915 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
916 std::string DiagMsg = std::string(Builtin->
name()) +
917 ": the builtin requires the following SPIR-V "
918 "extension: SPV_INTEL_split_barrier";
922 if (
Call->isSpirvOp())
927 unsigned MemSemantics = SPIRV::MemorySemantics::None;
929 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
930 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
932 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
933 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
935 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
936 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
938 if (Opcode == SPIRV::OpMemoryBarrier)
942 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
943 MemSemantics |= SPIRV::MemorySemantics::Release;
944 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
945 MemSemantics |= SPIRV::MemorySemantics::Acquire;
947 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
950 MemFlags == MemSemantics
954 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
955 SPIRV::Scope::Scope MemScope = Scope;
956 if (
Call->Arguments.size() >= 2) {
958 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
959 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
960 "Extra args for explicitly scoped barrier");
961 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
962 :
Call->Arguments[1];
963 SPIRV::CLMemoryScope CLScope =
964 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
966 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
967 (Opcode == SPIRV::OpMemoryBarrier))
969 if (CLScope ==
static_cast<unsigned>(Scope))
970 ScopeReg =
Call->Arguments[1];
977 if (Opcode != SPIRV::OpMemoryBarrier)
979 MIB.
addUse(MemSemanticsReg);
991 if ((Opcode == SPIRV::OpBitFieldInsert ||
992 Opcode == SPIRV::OpBitFieldSExtract ||
993 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
994 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
995 std::string DiagMsg = std::string(Builtin->
name()) +
996 ": the builtin requires the following SPIR-V "
997 "extension: SPV_KHR_bit_instructions";
1002 if (
Call->isSpirvOp())
1009 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1021 if (
Call->isSpirvOp())
1038 if (
Call->isSpirvOp())
1045 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1055 if (
Call->isSpirvOp())
1062 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1074 if (
Call->isSpirvOp())
1080 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1090 case SPIRV::OpCommitReadPipe:
1091 case SPIRV::OpCommitWritePipe:
1093 case SPIRV::OpGroupCommitReadPipe:
1094 case SPIRV::OpGroupCommitWritePipe:
1095 case SPIRV::OpGroupReserveReadPipePackets:
1096 case SPIRV::OpGroupReserveWritePipePackets: {
1100 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1104 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1105 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1109 MIB.
addUse(ScopeConstReg);
1110 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1123 case SPIRV::Dim::DIM_1D:
1124 case SPIRV::Dim::DIM_Buffer:
1126 case SPIRV::Dim::DIM_2D:
1127 case SPIRV::Dim::DIM_Cube:
1128 case SPIRV::Dim::DIM_Rect:
1130 case SPIRV::Dim::DIM_3D:
1143 return arrayed ? numComps + 1 : numComps;
1147 switch (BuiltinNumber) {
1148 case SPIRV::OpenCLExtInst::s_min:
1149 case SPIRV::OpenCLExtInst::u_min:
1150 case SPIRV::OpenCLExtInst::s_max:
1151 case SPIRV::OpenCLExtInst::u_max:
1152 case SPIRV::OpenCLExtInst::fmax:
1153 case SPIRV::OpenCLExtInst::fmin:
1154 case SPIRV::OpenCLExtInst::fmax_common:
1155 case SPIRV::OpenCLExtInst::fmin_common:
1156 case SPIRV::OpenCLExtInst::s_clamp:
1157 case SPIRV::OpenCLExtInst::fclamp:
1158 case SPIRV::OpenCLExtInst::u_clamp:
1159 case SPIRV::OpenCLExtInst::mix:
1160 case SPIRV::OpenCLExtInst::step:
1161 case SPIRV::OpenCLExtInst::smoothstep:
1162 case SPIRV::OpenCLExtInst::ldexp:
1163 case SPIRV::OpenCLExtInst::pown:
1164 case SPIRV::OpenCLExtInst::rootn:
1181 unsigned ResultElementCount =
1183 bool MayNeedPromotionToVec =
1186 if (!MayNeedPromotionToVec)
1187 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1194 ArgumentType !=
Call->ReturnType) {
1196 ArgumentType, ResultElementCount, MIRBuilder,
true);
1199 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1202 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1216 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1223 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1224 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1225 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1227 ? SPIRV::OpenCLExtInst::fmin
1228 : SPIRV::OpenCLExtInst::fmax;
1236 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1237 Number == SPIRV::OpenCLExtInst::fma) {
1245 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1248 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1256 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1257 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1266 if (ST.isKernel() ||
1267 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1273 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1277 AddNoNan = AddNoNan && ArgTest &
fcNan;
1278 AddNoInf = AddNoInf && ArgTest &
fcInf;
1296 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1300 std::tie(CompareRegister, RelationType) =
1306 Call->Arguments.end());
1307 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1336 Call->ReturnType, GR);
1344 SPIRV::lookupGroupBuiltin(Builtin->
name());
1347 if (
Call->isSpirvOp()) {
1350 if (GroupBuiltin->
Opcode ==
1351 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1352 Call->Arguments.size() > 4)
1361 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1363 "Group Operation parameter must be an integer constant");
1364 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1371 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1384 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1385 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1389 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1398 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1410 const bool HasBoolReturnTy =
1415 if (HasBoolReturnTy)
1416 std::tie(GroupResultRegister, GroupResultType) =
1420 ? SPIRV::Scope::Subgroup
1421 : SPIRV::Scope::Workgroup;
1425 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1426 Call->Arguments.size() > 2) {
1434 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1436 unsigned VecLen =
Call->Arguments.size() - 1;
1445 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1446 MIB.addUse(
Call->Arguments[i]);
1455 .
addDef(GroupResultRegister)
1461 if (
Call->Arguments.size() > 0) {
1462 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1467 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1468 MIB.addUse(
Call->Arguments[i]);
1472 if (HasBoolReturnTy)
1474 Call->ReturnType, GR);
1485 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1487 if (IntelSubgroups->
IsMedia &&
1488 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1489 std::string DiagMsg = std::string(Builtin->
name()) +
1490 ": the builtin requires the following SPIR-V "
1491 "extension: SPV_INTEL_media_block_io";
1493 }
else if (!IntelSubgroups->
IsMedia &&
1494 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1495 std::string DiagMsg = std::string(Builtin->
name()) +
1496 ": the builtin requires the following SPIR-V "
1497 "extension: SPV_INTEL_subgroups";
1502 if (
Call->isSpirvOp()) {
1503 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1504 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1505 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1511 if (IntelSubgroups->
IsBlock) {
1514 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1520 case SPIRV::OpSubgroupBlockReadINTEL:
1521 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1523 case SPIRV::OpSubgroupBlockWriteINTEL:
1524 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1547 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1558 if (!ST->canUseExtension(
1559 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1560 std::string DiagMsg = std::string(Builtin->
name()) +
1561 ": the builtin requires the following SPIR-V "
1562 "extension: SPV_KHR_uniform_group_instructions";
1566 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1576 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1578 "expect a constant group operation for a uniform group instruction",
1581 if (!ConstOperand.
isCImm())
1591 MIB.addUse(ValueReg);
1602 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1603 std::string DiagMsg = std::string(Builtin->
name()) +
1604 ": the builtin requires the following SPIR-V "
1605 "extension: SPV_KHR_shader_clock";
1611 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1618 SPIRV::Scope::Scope ScopeArg =
1620 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1621 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1622 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1663 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1666 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1677 bool IsConstantIndex =
1678 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1682 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1684 if (PointerSize != ResultWidth) {
1686 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1688 MIRBuilder.
getMF());
1689 ToTruncate = DefaultReg;
1693 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1702 if (!IsConstantIndex || PointerSize != ResultWidth) {
1711 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1714 if (!IsConstantIndex) {
1715 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1722 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1737 if (PointerSize != ResultWidth) {
1740 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1742 MIRBuilder.
getMF());
1745 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1747 ToTruncate = SelectionResult;
1749 ToTruncate = Extracted;
1753 if (PointerSize != ResultWidth)
1763 SPIRV::BuiltIn::BuiltIn
Value =
1764 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1766 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1772 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1779 LLType,
Call->ReturnRegister);
1788 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1791 case SPIRV::OpStore:
1793 case SPIRV::OpAtomicLoad:
1795 case SPIRV::OpAtomicStore:
1797 case SPIRV::OpAtomicCompareExchange:
1798 case SPIRV::OpAtomicCompareExchangeWeak:
1801 case SPIRV::OpAtomicIAdd:
1802 case SPIRV::OpAtomicISub:
1803 case SPIRV::OpAtomicOr:
1804 case SPIRV::OpAtomicXor:
1805 case SPIRV::OpAtomicAnd:
1806 case SPIRV::OpAtomicExchange:
1807 case SPIRV::OpAtomicSMax:
1808 case SPIRV::OpAtomicSMin:
1809 case SPIRV::OpAtomicUMax:
1810 case SPIRV::OpAtomicUMin:
1812 case SPIRV::OpMemoryBarrier:
1814 case SPIRV::OpAtomicFlagTestAndSet:
1815 case SPIRV::OpAtomicFlagClear:
1818 if (
Call->isSpirvOp())
1830 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1833 case SPIRV::OpAtomicFAddEXT:
1834 case SPIRV::OpAtomicFMinEXT:
1835 case SPIRV::OpAtomicFMaxEXT:
1848 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1859 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1861 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1862 SPIRV::StorageClass::StorageClass ResSC =
1873 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1884 if (
Call->isSpirvOp())
1889 SPIRV::OpTypeVector;
1891 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1892 bool IsSwapReq =
false;
1897 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1901 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
1911 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1912 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1914 if (
Call->BuiltinName ==
"dot") {
1915 if (IsFirstSigned && IsSecondSigned)
1917 else if (!IsFirstSigned && !IsSecondSigned)
1920 OC = SPIRV::OpSUDot;
1924 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1925 if (IsFirstSigned && IsSecondSigned)
1926 OC = SPIRV::OpSDotAccSat;
1927 else if (!IsFirstSigned && !IsSecondSigned)
1928 OC = SPIRV::OpUDotAccSat;
1930 OC = SPIRV::OpSUDotAccSat;
1946 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1949 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1955 if (!IsVec && OC != SPIRV::OpFMulS)
1956 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
1965 SPIRV::BuiltIn::BuiltIn
Value =
1966 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1969 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
1973 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
1974 false, std::nullopt);
2010 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2017 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2019 "overflow builtins");
2023 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2025 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
2027 case SPIRV::OpIAddCarryS:
2028 Opcode = SPIRV::OpIAddCarryV;
2030 case SPIRV::OpISubBorrowS:
2031 Opcode = SPIRV::OpISubBorrowV;
2036 RetType, MIRBuilder, GR);
2057 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2058 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2059 "Expected OpUMulExtended or OpSMulExtended");
2062 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2074 RetType =
Call->ReturnType;
2077 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2079 "multiplication builtins");
2082 "extended multiplication builtins");
2087 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2092 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2094 if (OpType1 != Member0Type)
2121 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2135 SPIRV::BuiltIn::BuiltIn
Value =
2136 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2137 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2138 Value == SPIRV::BuiltIn::NumWorkgroups ||
2139 Value == SPIRV::BuiltIn::WorkgroupSize ||
2140 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2150 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2154 unsigned NumExpectedRetComponents =
2161 if (NumExpectedRetComponents != NumActualRetComponents) {
2162 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2163 ?
Call->ReturnType->getOperand(1).getImm()
2170 IntTy, NumActualRetComponents, MIRBuilder,
true);
2175 bool UseQuerySize = IsDimBuf || IsMultisampled;
2177 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2184 if (NumExpectedRetComponents == NumActualRetComponents)
2186 if (NumExpectedRetComponents == 1) {
2188 unsigned ExtractedComposite =
2189 Component == 3 ? NumActualRetComponents - 1 : Component;
2190 assert(ExtractedComposite < NumActualRetComponents &&
2191 "Invalid composite index!");
2194 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2197 if (TypeReg != NewTypeReg)
2198 TypeReg = NewTypeReg;
2202 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2206 .
addImm(ExtractedComposite);
2212 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2217 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2218 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2226 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2227 "Image samples query result must be of int type!");
2232 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2235 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2237 (void)ImageDimensionality;
2240 case SPIRV::OpImageQuerySamples:
2241 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2242 "Image must be of 2D dimensionality");
2244 case SPIRV::OpImageQueryLevels:
2245 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2246 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2247 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2248 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2249 "Image must be of 1D/2D/3D/Cube dimensionality");
2261static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2263 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2264 case SPIRV::CLK_ADDRESS_CLAMP:
2265 return SPIRV::SamplerAddressingMode::Clamp;
2266 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2267 return SPIRV::SamplerAddressingMode::ClampToEdge;
2268 case SPIRV::CLK_ADDRESS_REPEAT:
2269 return SPIRV::SamplerAddressingMode::Repeat;
2270 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2271 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2272 case SPIRV::CLK_ADDRESS_NONE:
2273 return SPIRV::SamplerAddressingMode::None;
2280 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2283static SPIRV::SamplerFilterMode::SamplerFilterMode
2285 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2286 return SPIRV::SamplerFilterMode::Linear;
2287 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2288 return SPIRV::SamplerFilterMode::Nearest;
2289 return SPIRV::SamplerFilterMode::Nearest;
2296 if (
Call->isSpirvOp())
2303 if (HasOclSampler) {
2328 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2335 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2340 .
addImm(SPIRV::ImageOperand::Lod)
2342 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2348 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2353 .
addImm(SPIRV::ImageOperand::Lod)
2356 }
else if (HasMsaa) {
2362 .
addImm(SPIRV::ImageOperand::Sample)
2377 if (
Call->isSpirvOp())
2392 if (
Call->Builtin->name().contains_insensitive(
2393 "__translate_sampler_initializer")) {
2401 }
else if (
Call->Builtin->name().contains_insensitive(
2402 "__spirv_SampledImage")) {
2409 Call->ReturnRegister.isValid()
2410 ?
Call->ReturnRegister
2418 }
else if (
Call->Builtin->name().contains_insensitive(
2419 "__spirv_ImageSampleExplicitLod")) {
2421 std::string ReturnType = DemangledCall.
str();
2422 if (DemangledCall.
contains(
"_R")) {
2423 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2424 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2429 ReturnType, MIRBuilder,
true));
2431 std::string DiagMsg =
2432 "Unable to recognize SPIRV type name: " + ReturnType;
2435 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2440 .
addImm(SPIRV::ImageOperand::Lod)
2452 if (!ResTy.
isVector() && CondTy.isVector())
2454 "boolean condition");
2456 Call->Arguments[1],
Call->Arguments[2]);
2464 SPIRV::OpCompositeConstructContinuedINTEL,
2465 Call->Arguments,
Call->ReturnRegister,
2475 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2476 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2477 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2478 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2479 unsigned ArgSz =
Call->Arguments.size();
2480 unsigned LiteralIdx = 0;
2483 case SPIRV::OpCooperativeMatrixLoadKHR:
2484 LiteralIdx = ArgSz > 3 ? 3 : 0;
2486 case SPIRV::OpCooperativeMatrixStoreKHR:
2487 LiteralIdx = ArgSz > 4 ? 4 : 0;
2489 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2490 LiteralIdx = ArgSz > 7 ? 7 : 0;
2492 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2493 LiteralIdx = ArgSz > 8 ? 8 : 0;
2496 case SPIRV::OpCooperativeMatrixMulAddKHR:
2497 LiteralIdx = ArgSz > 3 ? 3 : 0;
2503 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2505 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2522 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2533 IsSet ? TypeReg :
Register(0), ImmArgs);
2542 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2546 case SPIRV::OpSpecConstant: {
2551 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2552 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2553 "Argument should be either an int or floating-point constant");
2556 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2557 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2559 ? SPIRV::OpSpecConstantTrue
2560 : SPIRV::OpSpecConstantFalse;
2566 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2567 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2579 case SPIRV::OpSpecConstantComposite: {
2581 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2582 Call->Arguments,
Call->ReturnRegister,
2597 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2608 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2618 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2636 InputReg =
Call->Arguments[1];
2639 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2647 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2648 MRI->
setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2652 for (
unsigned index = 2; index < 7; index++) {
2671 MRI->
setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2672 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2675 for (
unsigned index = 1; index < 6; index++)
2688 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2700 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2710 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2721 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2731 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2733 unsigned Scope = SPIRV::Scope::Workgroup;
2735 Scope = SPIRV::Scope::Subgroup;
2745 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2747 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2748 unsigned ArgSz =
Call->Arguments.size();
2757 IsSet ? TypeReg :
Register(0), ImmArgs);
2782 const unsigned NumCallArgs =
Call->Arguments.size();
2783 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2784 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2787 bool HasSRetArg = RetTy->
isVoidTy();
2789 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2790 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2791 const unsigned MaxNDRangeArgs = 3;
2792 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2794 const unsigned GlobalWorkSizeArgIdx =
2795 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2796 const unsigned LocalWorkSizeArgIdx =
2797 (NumNDRangeArgs == 1)
2799 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2800 const unsigned GlobalWorkOffsetArgIdx =
2801 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2806 assert(AddressModelBits == 64 || AddressModelBits == 32);
2810 unsigned Dimension = 0;
2811 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2812 assert(Dimension <= 3 && Dimension >= 1);
2819 if (Dimension == 1) {
2822 "Expected scalar integer type");
2824 if (NumNDRangeArgs < MaxNDRangeArgs)
2831 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2833 if (NumNDRangeArgs < MaxNDRangeArgs) {
2839 SpvFieldTy, *ST.getInstrInfo());
2845 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2846 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2854 "Only pointer types are supported for loading values");
2868 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2869 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2870 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2873 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2878 .
addUse(GlobalWorkOffset);
2895 .
addUse(GlobalWorkOffset);
2927 bool IsSpirvOp =
Call->isSpirvOp();
2928 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
2929 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
2931 const unsigned NumArgs =
Call->Arguments.size();
2932 const unsigned BaseArgIdx = 0;
2933 const unsigned IncorrectIdx = NumArgs + 1;
2935 const unsigned QueueIdx = BaseArgIdx;
2936 const unsigned FlagsIdx = BaseArgIdx + 1;
2937 const unsigned NDRangeIdx = BaseArgIdx + 2;
2938 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
2939 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
2940 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
2941 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
2942 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
2943 const unsigned LocalSizeNumElemIdx =
2944 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2945 const unsigned LocalSizeElemPtrIdx =
2946 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2948 [[maybe_unused]]
const unsigned LastArgIdx =
2949 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
2950 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
2956 auto BuildDeviceEventNullPtr = [&]() {
2960 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
2968 auto IsNullEvent = [&](
Register R) {
2970 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
2971 Def->getOperand(1).getCImm()->isZero();
2974 NumEventsReg =
Call->Arguments[NumEventsIdx];
2975 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
2976 RetEventReg =
Call->Arguments[RetEventIdx];
2977 if (IsNullEvent(WaitEventsReg))
2978 WaitEventsReg = BuildDeviceEventNullPtr();
2979 if (IsNullEvent(RetEventReg))
2980 RetEventReg = BuildDeviceEventNullPtr();
2983 Register NullPtr = BuildDeviceEventNullPtr();
2984 WaitEventsReg = NullPtr;
2985 RetEventReg = NullPtr;
3006 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3013 .
addUse(BlockLiteralReg);
3023 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3027 ConstOp.
isCImm() &&
"Expected constant immediate");
3030 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3032 for (
unsigned i = 0; i < NumElem; ++i) {
3038 .
addUse(LocalSizeArrayReg)
3046 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3059 for (
auto &LocalSize : LocalSizes)
3071 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3074 case SPIRV::OpRetainEvent:
3075 case SPIRV::OpReleaseEvent:
3077 case SPIRV::OpCreateUserEvent:
3078 case SPIRV::OpGetDefaultQueue:
3082 case SPIRV::OpIsValidEvent:
3087 case SPIRV::OpSetUserEventStatus:
3091 case SPIRV::OpCaptureEventProfilingInfo:
3096 case SPIRV::OpBuildNDRange:
3098 case SPIRV::OpEnqueueKernel:
3111 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3113 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3115 if (
Call->isSpirvOp())
3122 case SPIRV::OpGroupAsyncCopy: {
3124 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3128 unsigned NumArgs =
Call->Arguments.size();
3138 ?
Call->Arguments[3]
3146 case SPIRV::OpGroupWaitEvents:
3162 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3164 if (!Builtin &&
Call->isSpirvOp()) {
3167 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3172 assert(Builtin &&
"Conversion builtin not found.");
3175 SPIRV::Decoration::SaturatedConversion, {});
3178 bool AnyTypeIsFloat =
3185 if (AnyTypeIsFloat) {
3187 SPIRV::Decoration::FPRoundingMode,
3188 {(unsigned)Builtin->RoundingMode});
3192 std::string NeedExtMsg;
3193 bool IsRightComponentsNumber =
true;
3194 unsigned Opcode = SPIRV::OpNop;
3197 bool IsSourceSigned =
3203 : SPIRV::OpSatConvertSToU;
3205 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3207 SPIRV::OpTypeFloat)) {
3211 &MIRBuilder.
getMF().getSubtarget());
3212 if (!ST->canUseExtension(
3213 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3214 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3215 IsRightComponentsNumber =
3218 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3220 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3224 SPIRV::OpTypeFloat)) {
3230 &MIRBuilder.
getMF().getSubtarget());
3231 if (!ST->canUseExtension(
3232 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3233 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3234 IsRightComponentsNumber =
3237 Opcode = SPIRV::OpConvertFToBF16INTEL;
3240 : SPIRV::OpConvertFToU;
3243 SPIRV::OpTypeFloat)) {
3246 &MIRBuilder.
getMF().getSubtarget());
3247 if (!ST->canUseExtension(
3248 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3249 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3250 IsRightComponentsNumber =
3253 Opcode = SPIRV::OpRoundFToTF32INTEL;
3256 Opcode = SPIRV::OpFConvert;
3261 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3262 if (!NeedExtMsg.empty()) {
3263 std::string DiagMsg = std::string(BuiltinName) +
3264 ": the builtin requires the following SPIR-V "
3269 if (!IsRightComponentsNumber) {
3270 std::string DiagMsg =
3271 std::string(BuiltinName) +
3272 ": result and argument must have the same number of components";
3275 assert(Opcode != SPIRV::OpNop &&
3276 "Conversion between the types not implemented!");
3290 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->name(),
3291 Call->Builtin->Set);
3297 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3301 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3315 const auto *Builtin =
Call->Builtin;
3316 auto *MRI = MIRBuilder.
getMRI();
3318 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3324 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3325 DestReg = MRI->createGenericVirtualRegister(PtrTy);
3326 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3329 MIB.addDef(DestReg);
3332 MIB.addDef(
Call->ReturnRegister);
3335 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3338 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3339 DefMI->getOperand(1).isCImm()) {
3346 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3361 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3362 bool IsLoad = Opcode == SPIRV::OpLoad;
3366 MIB.addDef(
Call->ReturnRegister);
3374 MIB.addUse(
Call->Arguments[1]);
3376 unsigned NumArgs =
Call->Arguments.size();
3377 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3379 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3392std::tuple<int, unsigned, unsigned>
3394 SPIRV::InstructionSet::InstructionSet Set) {
3397 std::unique_ptr<const IncomingCall>
Call =
3400 return std::make_tuple(-1, 0, 0);
3402 switch (
Call->Builtin->Group) {
3403 case SPIRV::Relational:
3405 case SPIRV::Barrier:
3406 case SPIRV::CastToPtr:
3407 case SPIRV::ImageMiscQuery:
3408 case SPIRV::SpecConstant:
3409 case SPIRV::Enqueue:
3410 case SPIRV::AsyncCopy:
3411 case SPIRV::LoadStore:
3412 case SPIRV::CoopMatr:
3413 case SPIRV::Arithmetic:
3414 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3415 Call->Builtin->Set))
3416 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3418 case SPIRV::Extended:
3419 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3420 Call->Builtin->Set))
3421 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3423 case SPIRV::VectorLoadStore:
3424 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3425 Call->Builtin->name(),
Call->Builtin->Set))
3426 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3429 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3430 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3432 case SPIRV::AtomicFloating:
3434 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3435 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3437 case SPIRV::IntelSubgroups:
3439 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3440 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3442 case SPIRV::GroupUniform:
3443 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3444 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3446 case SPIRV::IntegerDot:
3448 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3449 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3451 case SPIRV::WriteImage:
3452 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3454 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3455 case SPIRV::Construct:
3456 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3458 case SPIRV::KernelClock:
3459 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3461 return std::make_tuple(-1, 0, 0);
3463 return std::make_tuple(-1, 0, 0);
3467 SPIRV::InstructionSet::InstructionSet Set,
3472 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3476 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3477 std::unique_ptr<const IncomingCall>
Call =
3482 return std::nullopt;
3487 if (Args.size() <
Call->Builtin->MinNumArgs) {
3488 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3489 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3490 <<
", got " << Args.size()
3491 <<
"; treating as a normal function\n");
3492 return std::nullopt;
3494 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3495 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3496 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3497 <<
", got " << Args.size()
3498 <<
"; treating as a normal function\n");
3499 return std::nullopt;
3503 switch (
Call->Builtin->Group) {
3504 case SPIRV::Extended:
3506 case SPIRV::Relational:
3510 case SPIRV::Variable:
3514 case SPIRV::AtomicFloating:
3516 case SPIRV::Barrier:
3518 case SPIRV::CastToPtr:
3521 case SPIRV::IntegerDot:
3525 case SPIRV::ICarryBorrow:
3527 case SPIRV::MulExtended:
3529 case SPIRV::Arithmetic:
3531 case SPIRV::GetQuery:
3533 case SPIRV::ImageSizeQuery:
3535 case SPIRV::ImageMiscQuery:
3537 case SPIRV::ReadImage:
3539 case SPIRV::WriteImage:
3541 case SPIRV::SampleImage:
3545 case SPIRV::Construct:
3547 case SPIRV::SpecConstant:
3549 case SPIRV::Enqueue:
3551 case SPIRV::AsyncCopy:
3553 case SPIRV::Convert:
3555 case SPIRV::VectorLoadStore:
3557 case SPIRV::LoadStore:
3559 case SPIRV::IntelSubgroups:
3561 case SPIRV::GroupUniform:
3563 case SPIRV::KernelClock:
3565 case SPIRV::CoopMatr:
3567 case SPIRV::ExtendedBitOps:
3569 case SPIRV::BindlessINTEL:
3571 case SPIRV::TernaryBitwiseINTEL:
3573 case SPIRV::Block2DLoadStore:
3577 case SPIRV::PredicatedLoadStore:
3579 case SPIRV::BlockingPipes:
3581 case SPIRV::ArbitraryPrecisionFixedPoint:
3583 case SPIRV::ImageChannelDataTypes:
3585 case SPIRV::ArbitraryFloatingPoint:
3596 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3597 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3614 unsigned VecElts = 0;
3625 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3637 auto Pos1 = DemangledCall.
find(
'(');
3640 auto Pos2 = DemangledCall.
find(
')');
3643 DemangledCall.
slice(Pos1 + 1, Pos2)
3644 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3652 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3654 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3663#define GET_BuiltinTypes_DECL
3664#define GET_BuiltinTypes_IMPL
3671#define GET_OpenCLTypes_DECL
3672#define GET_OpenCLTypes_IMPL
3674#include "SPIRVGenTables.inc"
3682 if (Name.starts_with(
"void"))
3684 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3686 else if (Name.starts_with(
"bfloat"))
3688 else if (Name.starts_with(
"float"))
3690 else if (Name.starts_with(
"half"))
3692 else if (Name.starts_with(
"double"))
3705 unsigned Opcode = TypeRecord->
Opcode;
3720 "Invalid number of parameters for SPIR-V pipe builtin!");
3723 SPIRV::AccessQualifier::AccessQualifier(
3731 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3733 "SPIR-V coop matrices builtin type must have a type parameter!");
3736 SPIRV::AccessQualifier::ReadWrite,
true);
3739 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3748 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3757 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3764 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3765 assert(ParamEType->getNumTypeParameters() == 1 &&
3766 "Inline SPIR-V integral constant builtin must have a type "
3768 assert(ParamEType->getNumIntParameters() == 1 &&
3769 "Inline SPIR-V integral constant builtin must have a "
3772 auto OperandValue = ParamEType->getIntParameter(0);
3773 auto *OperandType = ParamEType->getTypeParameter(0);
3776 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3779 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3781 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3782 assert(ParamEType->getNumTypeParameters() == 0 &&
3783 "Inline SPIR-V literal builtin does not take type "
3785 assert(ParamEType->getNumIntParameters() == 1 &&
3786 "Inline SPIR-V literal builtin must have an integer "
3789 auto OperandValue = ParamEType->getIntParameter(0);
3796 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3808 "Vulkan buffers have exactly one type for the type of the buffer.");
3810 "Vulkan buffer have 2 integer parameters: storage class and is "
3814 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
3825 "Vulkan push constants have exactly one type as argument.");
3839 StringRef NameWithParameters = TypeName;
3846 SPIRV::lookupOpenCLType(NameWithParameters);
3849 NameWithParameters);
3850 NameWithParameters =
3858 "Unknown builtin opaque type!");
3862 if (!NameWithParameters.
contains(
'_'))
3866 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
3870 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
3871 if (HasTypeParameter)
3874 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
3875 unsigned IntParameter = 0;
3876 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
3879 "Invalid format of SPIR-V builtin parameter literal!");
3883 NameWithParameters.
substr(0, BaseNameLength),
3884 TypeParameters, IntParameters);
3889 SPIRV::AccessQualifier::AccessQualifier AccessQual,
3910 if (Name ==
"spirv.Type") {
3912 }
else if (Name ==
"spirv.VulkanBuffer") {
3914 }
else if (Name ==
"spirv.Padding") {
3916 }
else if (Name ==
"spirv.PushConstant") {
3918 }
else if (Name ==
"spirv.Layout") {
3932 switch (TypeRecord->
Opcode) {
3933 case SPIRV::OpTypeImage:
3936 case SPIRV::OpTypePipe:
3939 case SPIRV::OpTypeDeviceEvent:
3942 case SPIRV::OpTypeSampler:
3945 case SPIRV::OpTypeSampledImage:
3948 case SPIRV::OpTypeCooperativeMatrixKHR:
3970 return Builtin->
Group == Pipe || Builtin->
Group == CastToPtr ||
3971 Builtin->
Group == BlockingPipes;
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Promote Memory to Register
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
static const fltSemantics & IEEEsingle()
APInt bitcastToAPInt() const
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
uint64_t getZExtValue() const
Get zero extended value.
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI FPClassTest getParamNoFPClass(unsigned i) const
Extract a test mask for disallowed floating-point value classes for the parameter.
LLVM_ABI FPClassTest getRetNoFPClass() const
Extract a test mask for disallowed floating-point value classes for the return value.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
@ ICMP_ULT
unsigned less than
const APFloat & getValueAPF() const
const APInt & getValue() const
Return the constant as an APInt value reference.
A parsed version of the target data layout string in and methods for querying it.
Tagged union holding either a T or a Error.
Class to represent fixed width SIMD vectors.
Class to represent function types.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type * getParamType(unsigned i) const
Parameter type accessors.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
This is an important class for using LLVM in a threaded context.
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
LLVMContext & getContext() const
MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_SELECT Tst, Op0, Op1.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)
Build and insert a G_INTRINSIC instruction.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void copyIRFlags(const Instruction &I)
Copy all flags to MachineInst MIFlags.
void setFlag(MIFlag Flag)
Set a MI flag.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const MDNode * getMetadata() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SPIRVTypeInst getImageType(const TargetExtType *ExtensionType, const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateOpTypeSampledImage(SPIRVTypeInst ImageType, MachineIRBuilder &MIRBuilder)
void assignSPIRVTypeToVReg(SPIRVTypeInst Type, Register VReg, const MachineFunction &MF)
const TargetRegisterClass * getRegClass(SPIRVTypeInst SpvType) const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVTypeInst getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
Register buildGlobalVariable(Register Reg, SPIRVTypeInst BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
SPIRVTypeInst getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
unsigned getScalarOrVectorComponentCount(Register VReg) const
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
SPIRVTypeInst getOrCreatePaddingType(MachineIRBuilder &MIRBuilder)
unsigned getPointerSize() const
LLT getRegType(SPIRVTypeInst SpvType) const
SPIRVTypeInst getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVTypeInst SpvType, const SPIRVInstrInfo &TII)
SPIRVTypeInst getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, SPIRVTypeInst ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use, bool EmitIR)
SPIRVTypeInst getOrCreateUnknownType(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode, const ArrayRef< MCOperand > Operands)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType=nullptr)
SPIRVTypeInst getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
SPIRVTypeInst getScalarOrVectorComponentType(SPIRVTypeInst Type) const
SPIRVTypeInst getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType, SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr=false)
SPIRVTypeInst getPointeeType(SPIRVTypeInst PtrType)
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
SPIRVTypeInst getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr=false)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType)
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
SPIRVTypeInst getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType, bool EmitIR, bool ZeroAsNull=true)
SPIRVTypeInst getOrCreateVulkanPushConstantType(MachineIRBuilder &MIRBuilder, Type *ElemType)
SPIRVTypeInst getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static constexpr size_t npos
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
bool contains_insensitive(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
A switch()-like statement whose cases are string literals.
StringSwitch & EndsWith(StringLiteral S, T Value)
Class to represent target extensions types, which are generally unintrospectable from target-independ...
ArrayRef< Type * > type_params() const
Return the type parameters for this particular target extension type.
unsigned getNumIntParameters() const
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Type * getTypeParameter(unsigned i) const
unsigned getNumTypeParameters() const
unsigned getIntParameter(unsigned i) const
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI StringRef getStructName() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getBFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents a version number in the form major[.minor[.subminor[.build]]].
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
LLVM_C_ABI LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount)
Create a vector type that contains a defined type and has a specific number of elements.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool parseBuiltinTypeStr(SmallVector< StringRef, 10 > &BuiltinArgsTypeStrs, StringRef DemangledCall, LLVMContext &Ctx)
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
Type * parseBuiltinCallArgumentType(StringRef TypeStr, LLVMContext &Ctx)
bool isPipeOrAddressSpaceCastBuiltin(StringRef Name)
Returns true if Name is a pipe or address-space-cast OpenCL builtin.
std::optional< bool > lowerBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR, const CallBase &CB)
Type * parseBuiltinCallArgumentBaseType(StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)
Parses the provided ArgIdx argument base type in the DemangledCall skeleton.
std::tuple< int, unsigned, unsigned > mapBuiltinToOpcode(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)
Helper function for finding a builtin function attributes by a demangled function name.
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
SPIRVTypeInst lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
This is an optimization pass for GlobalISel generic memory operations.
static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's 2d block io instructions.
static bool generateExtInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static void buildSRetInst(unsigned Opcode, Register SRetReg, Register Op1Reg, Register Op2Reg, SPIRVTypeInst RetType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateGetQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConstructInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic flag instructions (e.g.
static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRV::SamplerFilterMode::SamplerFilterMode getSamplerFilterModeFromBitmask(unsigned Bitmask)
static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic store instruction.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building extended bit operations.
static const Type * getBlockStructType(Register ParamReg, MachineRegisterInfo *MRI)
static bool generateGroupInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConvertInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
FPDecorationId demangledPostfixToDecorationId(const std::string &S)
static SPIRVTypeInst getSamplerType(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim)
static bool generateImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool builtinMayNeedPromotionToVec(uint32_t BuiltinNumber)
static std::tuple< Register, SPIRVTypeInst > buildBoolRegister(MachineIRBuilder &MIRBuilder, SPIRVTypeInst ResultType, SPIRVGlobalRegistry *GR)
Helper function building either a resulting scalar or vector bool register depending on the expected ...
Register createVirtualRegister(SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
static bool generateICarryBorrowInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildScopeReg(Register CLScopeRegister, SPIRV::Scope::Scope Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI)
void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning a SPIRV type to a register, ensuring the register class and ty...
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
static SPIRVTypeInst getInlineSpirvType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
static Register buildConstantIntReg32(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
static unsigned getNumSizeComponents(SPIRVTypeInst imgType)
Helper function for obtaining the number of size components.
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
static bool generateBarrierInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getLayoutType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
static SPIRVTypeInst getVulkanPushConstantType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateKernelClockInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static void setRegClassIfNull(Register Reg, MachineRegisterInfo *MRI, SPIRVGlobalRegistry *GR)
void buildOpName(Register Target, StringRef Name, MachineIRBuilder &MIRBuilder)
static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateWaveInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
static bool generateMulExtendedInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildBarrierInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building barriers, i.e., memory/control ordering operations.
static bool generateAsyncCopy(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder, SPIRVTypeInst VariableType, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, LLT LLType, Register Reg=Register(0), bool isConst=true, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageTy={ SPIRV::LinkageType::Import})
Helper function for building a load instruction for loading a builtin global variable of BuiltinValue...
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
static SPIRV::Scope::Scope getSPIRVScope(SPIRV::CLMemoryScope ClScope)
static bool buildAPFixedPointInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateBlockingPipesInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool generateSampleImageInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateEnqueueInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Type * parseTypeString(StringRef Name, LLVMContext &Context)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
static const Type * getMachineInstrType(MachineInstr *MI)
static bool generateDotOrFMulInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
static SPIRV::SamplerAddressingMode::SamplerAddressingMode getSamplerAddressingModeFromBitmask(unsigned Bitmask)
static bool generateAtomicInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static std::unique_ptr< const SPIRV::IncomingCall > lookupBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, Register ReturnRegister, SPIRVTypeInst ReturnType, const SmallVectorImpl< Register > &Arguments)
Looks up the demangled builtin call in the SPIRVBuiltins.td records using the provided DemangledCall ...
static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static bool buildSelectInst(MachineIRBuilder &MIRBuilder, Register ReturnRegister, Register SourceRegister, SPIRVTypeInst ReturnType, SPIRVGlobalRegistry *GR)
Helper function for building either a vector or scalar select instruction depending on the expected R...
static Register buildMemSemanticsReg(Register SemanticsRegister, Register PtrRegister, unsigned &Semantics, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateSelectInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)
static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic load instruction.
static bool generateIntelSubgroupsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getCoopMatrType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildPipeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, unsigned Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildLoadInst(SPIRVTypeInst BaseType, Register PtrRegister, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, Register DestinationReg=Register(0))
Helper function for building a load instruction loading into the DestinationReg.
static bool generateSpecConstantInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
static bool generateVectorLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool genWorkgroupQuery(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, uint64_t DefaultValue)
static bool generateCoopMatrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SmallVector< Register > getBuiltinCallArguments(const SPIRV::IncomingCall *Call, uint32_t BuiltinNumber, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getNonParameterizedType(const TargetExtType *ExtensionType, const SPIRV::BuiltinType *TypeRecord, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's bindless image instructions.
static bool buildAtomicFloatingRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic floating-type instruction.
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
static bool generateReadImageInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool hasBuiltinTypePrefix(StringRef Name)
static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
static bool generatePipeInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's OpBitwiseFunctionINTEL instruction.
static bool generateAPFixedPointInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic instructions.
static SPIRV::MemorySemantics::MemorySemantics getSPIRVMemSemantics(std::memory_order MemOrder)
static bool generateRelationalInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getPipeType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicInitInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)
Helper function for translating atomic init to OpStore.
static bool generateWriteImageInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateArithmeticInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
static bool generatePredicatedLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateAtomicFloatingInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateAFPInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildNDRange(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static MachineInstr * getBlockStructInstr(Register ParamReg, MachineRegisterInfo *MRI)
static SPIRVTypeInst getSampledImageType(const TargetExtType *OpaqueType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildOpFromWrapper(MachineIRBuilder &MIRBuilder, unsigned Opcode, const SPIRV::IncomingCall *Call, Register TypeReg, ArrayRef< uint32_t > ImmArgs={})
static unsigned getSamplerParamFromBitmask(unsigned Bitmask)
static SPIRVTypeInst getVulkanBufferType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, const SPIRV::DemangledBuiltin *Builtin, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic compare-exchange instruction.
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)
MCRegisterClass TargetRegisterClass
static bool generateBuiltinVar(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...
FPRoundingMode::FPRoundingMode RoundingMode
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
const SmallVectorImpl< Register > & Arguments
const SPIRVTypeInst ReturnType
IncomingCall(const std::string BuiltinName, const DemangledBuiltin *Builtin, const Register ReturnRegister, SPIRVTypeInst ReturnType, const SmallVectorImpl< Register > &Arguments)
const std::string BuiltinName
const Register ReturnRegister
const DemangledBuiltin * Builtin
InstructionSet::InstructionSet Set
StringTable::Offset SpirvTypeLiteral
InstructionSet::InstructionSet Set
FPRoundingMode::FPRoundingMode RoundingMode