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];
309 switch (FirstArgumentType) {
312 if (Set == SPIRV::InstructionSet::OpenCL_std)
314 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
322 if (Set == SPIRV::InstructionSet::OpenCL_std)
324 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
331 if (Set == SPIRV::InstructionSet::OpenCL_std ||
332 Set == SPIRV::InstructionSet::GLSL_std_450)
338 if (!Prefix.empty() &&
339 (Builtin = SPIRV::lookupBuiltin(Prefix + BuiltinName, Set)))
340 return std::make_unique<SPIRV::IncomingCall>(
341 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
348 switch (FirstArgumentType) {
369 if (!Suffix.empty() &&
370 (Builtin = SPIRV::lookupBuiltin(BuiltinName + Suffix, Set)))
371 return std::make_unique<SPIRV::IncomingCall>(
372 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
384 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
385 MI->getOperand(1).isReg());
386 Register BitcastReg =
MI->getOperand(1).getReg();
388 assert(BitcastMI &&
"Definition for source reg not found.");
389 if (BitcastMI->
getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
404 Register ValueReg =
MI->getOperand(0).getReg();
410 assert(Ty &&
"Type is expected");
422 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
423 return MI->getOperand(1).getGlobal()->getValueType();
425 "Blocks in OpenCL C must be traceable to allocation site");
437static std::tuple<Register, SPIRVTypeInst>
443 if (ResultType->
getOpcode() == SPIRV::OpTypeVector) {
458 return std::make_tuple(ResultRegister, BoolType);
468 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {
479 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
489 if (!DestinationReg.isValid())
494 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
495 return DestinationReg;
504 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
505 SPIRV::LinkageType::Import}) {
513 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
519 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
526 return LoadedRegister;
537static SPIRV::MemorySemantics::MemorySemantics
540 case std::memory_order_relaxed:
541 return SPIRV::MemorySemantics::None;
542 case std::memory_order_acquire:
543 return SPIRV::MemorySemantics::Acquire;
544 case std::memory_order_release:
545 return SPIRV::MemorySemantics::Release;
546 case std::memory_order_acq_rel:
547 return SPIRV::MemorySemantics::AcquireRelease;
548 case std::memory_order_seq_cst:
549 return SPIRV::MemorySemantics::SequentiallyConsistent;
557 case SPIRV::CLMemoryScope::memory_scope_work_item:
558 return SPIRV::Scope::Invocation;
559 case SPIRV::CLMemoryScope::memory_scope_work_group:
560 return SPIRV::Scope::Workgroup;
561 case SPIRV::CLMemoryScope::memory_scope_device:
562 return SPIRV::Scope::Device;
563 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
564 return SPIRV::Scope::CrossDevice;
565 case SPIRV::CLMemoryScope::memory_scope_sub_group:
566 return SPIRV::Scope::Subgroup;
579 SPIRV::Scope::Scope Scope,
583 if (CLScopeRegister.
isValid()) {
585 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(CLScopeRegister, MRI));
588 if (CLScope ==
static_cast<unsigned>(Scope)) {
589 MRI->
setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
590 return CLScopeRegister;
602 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
606 Register PtrRegister,
unsigned &Semantics,
609 if (SemanticsRegister.
isValid()) {
611 std::memory_order Order =
612 static_cast<std::memory_order
>(
getIConstVal(SemanticsRegister, MRI));
616 if (
static_cast<unsigned>(Order) == Semantics) {
617 MRI->
setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);
618 return SemanticsRegister;
631 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
632 for (
unsigned i = 0; i < Sz; ++i)
633 MIB.addUse(
Call->Arguments[i]);
642 if (
Call->isSpirvOp())
646 "Need 2 arguments for atomic init translation");
658 if (
Call->isSpirvOp())
666 Call->Arguments.size() > 1
670 if (
Call->Arguments.size() > 2) {
672 MemSemanticsReg =
Call->Arguments[2];
675 SPIRV::MemorySemantics::SequentiallyConsistent |
693 if (
Call->isSpirvOp())
701 SPIRV::MemorySemantics::SequentiallyConsistent |
716 if (
Call->isSpirvOp())
720 bool IsCmpxchg =
Call->Builtin->name().contains(
"cmpxchg");
730 SPIRV::OpTypePointer);
733 assert(IsCmpxchg ? ExpectedType == SPIRV::OpTypeInt
734 : ExpectedType == SPIRV::OpTypePointer);
739 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
747 ? SPIRV::MemorySemantics::None
748 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
751 ? SPIRV::MemorySemantics::None
752 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
753 if (
Call->Arguments.size() >= 4) {
755 "Need 5+ args for explicit atomic cmpxchg");
762 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
763 MemSemEqualReg =
Call->Arguments[3];
764 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
765 MemSemUnequalReg =
Call->Arguments[4];
769 if (!MemSemUnequalReg.
isValid())
773 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
774 if (
Call->Arguments.size() >= 6) {
776 "Extra args for explicit atomic cmpxchg");
777 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
780 if (ClScope ==
static_cast<unsigned>(Scope))
781 ScopeReg =
Call->Arguments[5];
787 IsCmpxchg ? ExpectedArg
791 :
Call->ReturnRegister;
816 if (
Call->isSpirvOp())
825 "Too many args for explicit atomic RMW");
826 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
827 MIRBuilder, GR, MRI);
830 unsigned Semantics = SPIRV::MemorySemantics::None;
834 Semantics, MIRBuilder, GR);
838 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
839 if (Opcode == SPIRV::OpAtomicIAdd) {
840 Opcode = SPIRV::OpAtomicFAddEXT;
841 }
else if (Opcode == SPIRV::OpAtomicISub) {
844 Opcode = SPIRV::OpAtomicFAddEXT;
855 ValueReg = NegValueReg;
874 "Wrong number of atomic floating-type builtin");
894 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
896 if (
Call->isSpirvOp())
902 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
906 Semantics, MIRBuilder, GR);
908 assert((Opcode != SPIRV::OpAtomicFlagClear ||
909 (Semantics != SPIRV::MemorySemantics::Acquire &&
910 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
911 "Invalid memory order argument!");
916 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
934 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
935 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
936 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
937 std::string DiagMsg = std::string(Builtin->
name()) +
938 ": the builtin requires the following SPIR-V "
939 "extension: SPV_INTEL_split_barrier";
943 if (
Call->isSpirvOp())
948 unsigned MemSemantics = SPIRV::MemorySemantics::None;
950 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
951 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
953 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
954 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
956 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
957 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
959 if (Opcode == SPIRV::OpMemoryBarrier)
963 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
964 MemSemantics |= SPIRV::MemorySemantics::Release;
965 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
966 MemSemantics |= SPIRV::MemorySemantics::Acquire;
968 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
971 MemFlags == MemSemantics
975 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
976 SPIRV::Scope::Scope MemScope = Scope;
977 if (
Call->Arguments.size() >= 2) {
979 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
980 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
981 "Extra args for explicitly scoped barrier");
982 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
983 :
Call->Arguments[1];
984 SPIRV::CLMemoryScope CLScope =
985 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
987 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
988 (Opcode == SPIRV::OpMemoryBarrier))
990 if (CLScope ==
static_cast<unsigned>(Scope))
991 ScopeReg =
Call->Arguments[1];
998 if (Opcode != SPIRV::OpMemoryBarrier)
1000 MIB.
addUse(MemSemanticsReg);
1012 if ((Opcode == SPIRV::OpBitFieldInsert ||
1013 Opcode == SPIRV::OpBitFieldSExtract ||
1014 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1015 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1016 std::string DiagMsg = std::string(Builtin->
name()) +
1017 ": the builtin requires the following SPIR-V "
1018 "extension: SPV_KHR_bit_instructions";
1023 if (
Call->isSpirvOp())
1030 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1042 if (
Call->isSpirvOp())
1059 if (
Call->isSpirvOp())
1066 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1076 if (
Call->isSpirvOp())
1083 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1095 if (
Call->isSpirvOp())
1101 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1111 case SPIRV::OpCommitReadPipe:
1112 case SPIRV::OpCommitWritePipe:
1114 case SPIRV::OpGroupCommitReadPipe:
1115 case SPIRV::OpGroupCommitWritePipe:
1116 case SPIRV::OpGroupReserveReadPipePackets:
1117 case SPIRV::OpGroupReserveWritePipePackets: {
1121 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1125 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1126 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1130 MIB.
addUse(ScopeConstReg);
1131 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1144 case SPIRV::Dim::DIM_1D:
1145 case SPIRV::Dim::DIM_Buffer:
1147 case SPIRV::Dim::DIM_2D:
1148 case SPIRV::Dim::DIM_Cube:
1149 case SPIRV::Dim::DIM_Rect:
1151 case SPIRV::Dim::DIM_3D:
1164 return arrayed ? numComps + 1 : numComps;
1168 switch (BuiltinNumber) {
1169 case SPIRV::OpenCLExtInst::s_min:
1170 case SPIRV::OpenCLExtInst::u_min:
1171 case SPIRV::OpenCLExtInst::s_max:
1172 case SPIRV::OpenCLExtInst::u_max:
1173 case SPIRV::OpenCLExtInst::fmax:
1174 case SPIRV::OpenCLExtInst::fmin:
1175 case SPIRV::OpenCLExtInst::fmax_common:
1176 case SPIRV::OpenCLExtInst::fmin_common:
1177 case SPIRV::OpenCLExtInst::s_clamp:
1178 case SPIRV::OpenCLExtInst::fclamp:
1179 case SPIRV::OpenCLExtInst::u_clamp:
1180 case SPIRV::OpenCLExtInst::mix:
1181 case SPIRV::OpenCLExtInst::step:
1182 case SPIRV::OpenCLExtInst::smoothstep:
1183 case SPIRV::OpenCLExtInst::ldexp:
1184 case SPIRV::OpenCLExtInst::pown:
1185 case SPIRV::OpenCLExtInst::rootn:
1202 unsigned ResultElementCount =
1204 bool MayNeedPromotionToVec =
1207 if (!MayNeedPromotionToVec)
1208 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1215 ArgumentType !=
Call->ReturnType) {
1217 ArgumentType, ResultElementCount, MIRBuilder,
true);
1220 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1223 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1237 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1244 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1245 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1246 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1248 ? SPIRV::OpenCLExtInst::fmin
1249 : SPIRV::OpenCLExtInst::fmax;
1257 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1258 Number == SPIRV::OpenCLExtInst::fma) {
1266 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1269 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1277 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1278 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1287 if (ST.isKernel() ||
1288 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1294 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1298 AddNoNan = AddNoNan && ArgTest &
fcNan;
1299 AddNoInf = AddNoInf && ArgTest &
fcInf;
1317 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1321 std::tie(CompareRegister, RelationType) =
1327 Call->Arguments.end());
1328 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1357 Call->ReturnType, GR);
1365 SPIRV::lookupGroupBuiltin(Builtin->
name());
1368 if (
Call->isSpirvOp()) {
1371 if (GroupBuiltin->
Opcode ==
1372 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1373 Call->Arguments.size() > 4)
1382 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1384 "Group Operation parameter must be an integer constant");
1385 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1392 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1405 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1406 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1410 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1419 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1431 const bool HasBoolReturnTy =
1436 if (HasBoolReturnTy)
1437 std::tie(GroupResultRegister, GroupResultType) =
1441 ? SPIRV::Scope::Subgroup
1442 : SPIRV::Scope::Workgroup;
1446 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1447 Call->Arguments.size() > 2) {
1455 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1457 unsigned VecLen =
Call->Arguments.size() - 1;
1466 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1467 MIB.addUse(
Call->Arguments[i]);
1476 .
addDef(GroupResultRegister)
1482 if (
Call->Arguments.size() > 0) {
1483 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1488 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1489 MIB.addUse(
Call->Arguments[i]);
1493 if (HasBoolReturnTy)
1495 Call->ReturnType, GR);
1506 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1508 if (IntelSubgroups->
IsMedia &&
1509 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1510 std::string DiagMsg = std::string(Builtin->
name()) +
1511 ": the builtin requires the following SPIR-V "
1512 "extension: SPV_INTEL_media_block_io";
1514 }
else if (!IntelSubgroups->
IsMedia &&
1515 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1516 std::string DiagMsg = std::string(Builtin->
name()) +
1517 ": the builtin requires the following SPIR-V "
1518 "extension: SPV_INTEL_subgroups";
1523 if (
Call->isSpirvOp()) {
1524 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1525 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1526 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1532 if (IntelSubgroups->
IsBlock) {
1535 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1541 case SPIRV::OpSubgroupBlockReadINTEL:
1542 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1544 case SPIRV::OpSubgroupBlockWriteINTEL:
1545 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1568 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1579 if (!ST->canUseExtension(
1580 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1581 std::string DiagMsg = std::string(Builtin->
name()) +
1582 ": the builtin requires the following SPIR-V "
1583 "extension: SPV_KHR_uniform_group_instructions";
1587 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1597 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1599 "expect a constant group operation for a uniform group instruction",
1602 if (!ConstOperand.
isCImm())
1612 MIB.addUse(ValueReg);
1623 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1624 std::string DiagMsg = std::string(Builtin->
name()) +
1625 ": the builtin requires the following SPIR-V "
1626 "extension: SPV_KHR_shader_clock";
1632 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1639 SPIRV::Scope::Scope ScopeArg =
1641 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1642 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1643 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1684 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1687 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1698 bool IsConstantIndex =
1699 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1703 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1705 if (PointerSize != ResultWidth) {
1707 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1709 MIRBuilder.
getMF());
1710 ToTruncate = DefaultReg;
1714 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1723 if (!IsConstantIndex || PointerSize != ResultWidth) {
1732 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1735 if (!IsConstantIndex) {
1736 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1743 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1758 if (PointerSize != ResultWidth) {
1761 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1763 MIRBuilder.
getMF());
1766 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1768 ToTruncate = SelectionResult;
1770 ToTruncate = Extracted;
1774 if (PointerSize != ResultWidth)
1784 SPIRV::BuiltIn::BuiltIn
Value =
1785 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1787 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1793 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1800 LLType,
Call->ReturnRegister);
1809 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1812 case SPIRV::OpStore:
1814 case SPIRV::OpAtomicLoad:
1816 case SPIRV::OpAtomicStore:
1818 case SPIRV::OpAtomicCompareExchange:
1819 case SPIRV::OpAtomicCompareExchangeWeak:
1822 case SPIRV::OpAtomicIAdd:
1823 case SPIRV::OpAtomicISub:
1824 case SPIRV::OpAtomicOr:
1825 case SPIRV::OpAtomicXor:
1826 case SPIRV::OpAtomicAnd:
1827 case SPIRV::OpAtomicExchange:
1828 case SPIRV::OpAtomicSMax:
1829 case SPIRV::OpAtomicSMin:
1830 case SPIRV::OpAtomicUMax:
1831 case SPIRV::OpAtomicUMin:
1833 case SPIRV::OpMemoryBarrier:
1835 case SPIRV::OpAtomicFlagTestAndSet:
1836 case SPIRV::OpAtomicFlagClear:
1839 if (
Call->isSpirvOp())
1851 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1854 case SPIRV::OpAtomicFAddEXT:
1855 case SPIRV::OpAtomicFMinEXT:
1856 case SPIRV::OpAtomicFMaxEXT:
1869 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1880 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1882 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1883 SPIRV::StorageClass::StorageClass ResSC =
1894 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1905 if (
Call->isSpirvOp())
1910 SPIRV::OpTypeVector;
1912 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1913 bool IsSwapReq =
false;
1918 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1922 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
1932 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1933 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1935 if (
Call->BuiltinName ==
"dot") {
1936 if (IsFirstSigned && IsSecondSigned)
1938 else if (!IsFirstSigned && !IsSecondSigned)
1941 OC = SPIRV::OpSUDot;
1945 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1946 if (IsFirstSigned && IsSecondSigned)
1947 OC = SPIRV::OpSDotAccSat;
1948 else if (!IsFirstSigned && !IsSecondSigned)
1949 OC = SPIRV::OpUDotAccSat;
1951 OC = SPIRV::OpSUDotAccSat;
1967 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1970 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1976 if (!IsVec && OC != SPIRV::OpFMulS)
1977 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
1986 SPIRV::BuiltIn::BuiltIn
Value =
1987 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1990 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
1994 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
1995 false, std::nullopt);
2031 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2038 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2040 "overflow builtins");
2044 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2046 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
2048 case SPIRV::OpIAddCarryS:
2049 Opcode = SPIRV::OpIAddCarryV;
2051 case SPIRV::OpISubBorrowS:
2052 Opcode = SPIRV::OpISubBorrowV;
2057 RetType, MIRBuilder, GR);
2078 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2079 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2080 "Expected OpUMulExtended or OpSMulExtended");
2083 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2095 RetType =
Call->ReturnType;
2098 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2100 "multiplication builtins");
2103 "extended multiplication builtins");
2108 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2113 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2115 if (OpType1 != Member0Type)
2142 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2156 SPIRV::BuiltIn::BuiltIn
Value =
2157 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2158 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2159 Value == SPIRV::BuiltIn::NumWorkgroups ||
2160 Value == SPIRV::BuiltIn::WorkgroupSize ||
2161 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2171 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2175 unsigned NumExpectedRetComponents =
2182 if (NumExpectedRetComponents != NumActualRetComponents) {
2183 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2184 ?
Call->ReturnType->getOperand(1).getImm()
2191 IntTy, NumActualRetComponents, MIRBuilder,
true);
2196 bool UseQuerySize = IsDimBuf || IsMultisampled;
2198 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2205 if (NumExpectedRetComponents == NumActualRetComponents)
2207 if (NumExpectedRetComponents == 1) {
2209 unsigned ExtractedComposite =
2210 Component == 3 ? NumActualRetComponents - 1 : Component;
2211 assert(ExtractedComposite < NumActualRetComponents &&
2212 "Invalid composite index!");
2215 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2218 if (TypeReg != NewTypeReg)
2219 TypeReg = NewTypeReg;
2223 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2227 .
addImm(ExtractedComposite);
2233 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2238 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2239 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2247 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2248 "Image samples query result must be of int type!");
2253 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2256 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2258 (void)ImageDimensionality;
2261 case SPIRV::OpImageQuerySamples:
2262 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2263 "Image must be of 2D dimensionality");
2265 case SPIRV::OpImageQueryLevels:
2266 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2267 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2268 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2269 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2270 "Image must be of 1D/2D/3D/Cube dimensionality");
2282static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2284 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2285 case SPIRV::CLK_ADDRESS_CLAMP:
2286 return SPIRV::SamplerAddressingMode::Clamp;
2287 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2288 return SPIRV::SamplerAddressingMode::ClampToEdge;
2289 case SPIRV::CLK_ADDRESS_REPEAT:
2290 return SPIRV::SamplerAddressingMode::Repeat;
2291 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2292 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2293 case SPIRV::CLK_ADDRESS_NONE:
2294 return SPIRV::SamplerAddressingMode::None;
2301 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2304static SPIRV::SamplerFilterMode::SamplerFilterMode
2306 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2307 return SPIRV::SamplerFilterMode::Linear;
2308 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2309 return SPIRV::SamplerFilterMode::Nearest;
2310 return SPIRV::SamplerFilterMode::Nearest;
2317 if (
Call->isSpirvOp())
2324 if (HasOclSampler) {
2349 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2356 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2361 .
addImm(SPIRV::ImageOperand::Lod)
2363 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2369 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2374 .
addImm(SPIRV::ImageOperand::Lod)
2377 }
else if (HasMsaa) {
2383 .
addImm(SPIRV::ImageOperand::Sample)
2398 if (
Call->isSpirvOp())
2413 if (
Call->Builtin->name().contains_insensitive(
2414 "__translate_sampler_initializer")) {
2422 }
else if (
Call->Builtin->name().contains_insensitive(
2423 "__spirv_SampledImage")) {
2430 Call->ReturnRegister.isValid()
2431 ?
Call->ReturnRegister
2439 }
else if (
Call->Builtin->name().contains_insensitive(
2440 "__spirv_ImageSampleExplicitLod")) {
2442 std::string ReturnType = DemangledCall.
str();
2443 if (DemangledCall.
contains(
"_R")) {
2444 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2445 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2450 ReturnType, MIRBuilder,
true));
2452 std::string DiagMsg =
2453 "Unable to recognize SPIRV type name: " + ReturnType;
2456 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2461 .
addImm(SPIRV::ImageOperand::Lod)
2473 if (!ResTy.
isVector() && CondTy.isVector())
2475 "boolean condition");
2477 Call->Arguments[1],
Call->Arguments[2]);
2485 SPIRV::OpCompositeConstructContinuedINTEL,
2486 Call->Arguments,
Call->ReturnRegister,
2496 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2497 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2498 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2499 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2500 unsigned ArgSz =
Call->Arguments.size();
2501 unsigned LiteralIdx = 0;
2504 case SPIRV::OpCooperativeMatrixLoadKHR:
2505 LiteralIdx = ArgSz > 3 ? 3 : 0;
2507 case SPIRV::OpCooperativeMatrixStoreKHR:
2508 LiteralIdx = ArgSz > 4 ? 4 : 0;
2510 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2511 LiteralIdx = ArgSz > 7 ? 7 : 0;
2513 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2514 LiteralIdx = ArgSz > 8 ? 8 : 0;
2517 case SPIRV::OpCooperativeMatrixMulAddKHR:
2518 LiteralIdx = ArgSz > 3 ? 3 : 0;
2524 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2526 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2543 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2554 IsSet ? TypeReg :
Register(0), ImmArgs);
2563 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2567 case SPIRV::OpSpecConstant: {
2572 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2573 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2574 "Argument should be either an int or floating-point constant");
2577 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2578 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2580 ? SPIRV::OpSpecConstantTrue
2581 : SPIRV::OpSpecConstantFalse;
2587 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2588 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2600 case SPIRV::OpSpecConstantComposite: {
2602 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2603 Call->Arguments,
Call->ReturnRegister,
2618 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2629 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2639 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2657 InputReg =
Call->Arguments[1];
2660 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2668 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2669 MRI->
setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2673 for (
unsigned index = 2; index < 7; index++) {
2692 MRI->
setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2693 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2696 for (
unsigned index = 1; index < 6; index++)
2709 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2721 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2731 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2742 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2752 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2754 unsigned Scope = SPIRV::Scope::Workgroup;
2756 Scope = SPIRV::Scope::Subgroup;
2766 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2768 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2769 unsigned ArgSz =
Call->Arguments.size();
2778 IsSet ? TypeReg :
Register(0), ImmArgs);
2803 const unsigned NumCallArgs =
Call->Arguments.size();
2804 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2805 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2808 bool HasSRetArg = RetTy->
isVoidTy();
2810 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2811 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2812 const unsigned MaxNDRangeArgs = 3;
2813 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2815 const unsigned GlobalWorkSizeArgIdx =
2816 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2817 const unsigned LocalWorkSizeArgIdx =
2818 (NumNDRangeArgs == 1)
2820 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2821 const unsigned GlobalWorkOffsetArgIdx =
2822 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2827 assert(AddressModelBits == 64 || AddressModelBits == 32);
2831 unsigned Dimension = 0;
2832 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2833 assert(Dimension <= 3 && Dimension >= 1);
2840 if (Dimension == 1) {
2843 "Expected scalar integer type");
2845 if (NumNDRangeArgs < MaxNDRangeArgs)
2852 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2854 if (NumNDRangeArgs < MaxNDRangeArgs) {
2860 SpvFieldTy, *ST.getInstrInfo());
2866 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2867 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2875 "Only pointer types are supported for loading values");
2889 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2890 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2891 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2894 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2899 .
addUse(GlobalWorkOffset);
2916 .
addUse(GlobalWorkOffset);
2948 bool IsSpirvOp =
Call->isSpirvOp();
2949 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
2950 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
2952 const unsigned NumArgs =
Call->Arguments.size();
2953 const unsigned BaseArgIdx = 0;
2954 const unsigned IncorrectIdx = NumArgs + 1;
2956 const unsigned QueueIdx = BaseArgIdx;
2957 const unsigned FlagsIdx = BaseArgIdx + 1;
2958 const unsigned NDRangeIdx = BaseArgIdx + 2;
2959 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
2960 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
2961 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
2962 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
2963 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
2964 const unsigned LocalSizeNumElemIdx =
2965 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2966 const unsigned LocalSizeElemPtrIdx =
2967 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2969 [[maybe_unused]]
const unsigned LastArgIdx =
2970 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
2971 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
2977 auto BuildDeviceEventNullPtr = [&]() {
2981 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
2989 auto IsNullEvent = [&](
Register R) {
2991 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
2992 Def->getOperand(1).getCImm()->isZero();
2995 NumEventsReg =
Call->Arguments[NumEventsIdx];
2996 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
2997 RetEventReg =
Call->Arguments[RetEventIdx];
2998 if (IsNullEvent(WaitEventsReg))
2999 WaitEventsReg = BuildDeviceEventNullPtr();
3000 if (IsNullEvent(RetEventReg))
3001 RetEventReg = BuildDeviceEventNullPtr();
3004 Register NullPtr = BuildDeviceEventNullPtr();
3005 WaitEventsReg = NullPtr;
3006 RetEventReg = NullPtr;
3027 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3034 .
addUse(BlockLiteralReg);
3044 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3048 ConstOp.
isCImm() &&
"Expected constant immediate");
3051 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3053 for (
unsigned i = 0; i < NumElem; ++i) {
3059 .
addUse(LocalSizeArrayReg)
3067 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3080 for (
auto &LocalSize : LocalSizes)
3092 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3095 case SPIRV::OpRetainEvent:
3096 case SPIRV::OpReleaseEvent:
3098 case SPIRV::OpCreateUserEvent:
3099 case SPIRV::OpGetDefaultQueue:
3103 case SPIRV::OpIsValidEvent:
3108 case SPIRV::OpSetUserEventStatus:
3112 case SPIRV::OpCaptureEventProfilingInfo:
3117 case SPIRV::OpBuildNDRange:
3119 case SPIRV::OpEnqueueKernel:
3132 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3134 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3136 if (
Call->isSpirvOp())
3143 case SPIRV::OpGroupAsyncCopy: {
3145 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3149 unsigned NumArgs =
Call->Arguments.size();
3159 ?
Call->Arguments[3]
3167 case SPIRV::OpGroupWaitEvents:
3183 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3185 if (!Builtin &&
Call->isSpirvOp()) {
3188 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3193 assert(Builtin &&
"Conversion builtin not found.");
3196 SPIRV::Decoration::SaturatedConversion, {});
3199 bool AnyTypeIsFloat =
3206 if (AnyTypeIsFloat) {
3208 SPIRV::Decoration::FPRoundingMode,
3209 {(unsigned)Builtin->RoundingMode});
3213 std::string NeedExtMsg;
3214 bool IsRightComponentsNumber =
true;
3215 unsigned Opcode = SPIRV::OpNop;
3218 bool IsSourceSigned =
3224 : SPIRV::OpSatConvertSToU;
3226 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3228 SPIRV::OpTypeFloat)) {
3232 &MIRBuilder.
getMF().getSubtarget());
3233 if (!ST->canUseExtension(
3234 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3235 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3236 IsRightComponentsNumber =
3239 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3241 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3245 SPIRV::OpTypeFloat)) {
3251 &MIRBuilder.
getMF().getSubtarget());
3252 if (!ST->canUseExtension(
3253 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3254 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3255 IsRightComponentsNumber =
3258 Opcode = SPIRV::OpConvertFToBF16INTEL;
3261 : SPIRV::OpConvertFToU;
3264 SPIRV::OpTypeFloat)) {
3267 &MIRBuilder.
getMF().getSubtarget());
3268 if (!ST->canUseExtension(
3269 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3270 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3271 IsRightComponentsNumber =
3274 Opcode = SPIRV::OpRoundFToTF32INTEL;
3277 Opcode = SPIRV::OpFConvert;
3282 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3283 if (!NeedExtMsg.empty()) {
3284 std::string DiagMsg = std::string(BuiltinName) +
3285 ": the builtin requires the following SPIR-V "
3290 if (!IsRightComponentsNumber) {
3291 std::string DiagMsg =
3292 std::string(BuiltinName) +
3293 ": result and argument must have the same number of components";
3296 assert(Opcode != SPIRV::OpNop &&
3297 "Conversion between the types not implemented!");
3311 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->name(),
3312 Call->Builtin->Set);
3318 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3322 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3336 const auto *Builtin =
Call->Builtin;
3337 auto *MRI = MIRBuilder.
getMRI();
3339 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3345 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3346 DestReg = MRI->createGenericVirtualRegister(PtrTy);
3347 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3350 MIB.addDef(DestReg);
3353 MIB.addDef(
Call->ReturnRegister);
3356 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3359 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3360 DefMI->getOperand(1).isCImm()) {
3367 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3382 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3383 bool IsLoad = Opcode == SPIRV::OpLoad;
3387 MIB.addDef(
Call->ReturnRegister);
3395 MIB.addUse(
Call->Arguments[1]);
3397 unsigned NumArgs =
Call->Arguments.size();
3398 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3400 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3413std::tuple<int, unsigned, unsigned>
3415 SPIRV::InstructionSet::InstructionSet Set) {
3418 std::unique_ptr<const IncomingCall>
Call =
3421 return std::make_tuple(-1, 0, 0);
3423 switch (
Call->Builtin->Group) {
3424 case SPIRV::Relational:
3426 case SPIRV::Barrier:
3427 case SPIRV::CastToPtr:
3428 case SPIRV::ImageMiscQuery:
3429 case SPIRV::SpecConstant:
3430 case SPIRV::Enqueue:
3431 case SPIRV::AsyncCopy:
3432 case SPIRV::LoadStore:
3433 case SPIRV::CoopMatr:
3434 case SPIRV::Arithmetic:
3435 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3436 Call->Builtin->Set))
3437 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3439 case SPIRV::Extended:
3440 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3441 Call->Builtin->Set))
3442 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3444 case SPIRV::VectorLoadStore:
3445 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3446 Call->Builtin->name(),
Call->Builtin->Set))
3447 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3450 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3451 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3453 case SPIRV::AtomicFloating:
3455 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3456 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3458 case SPIRV::IntelSubgroups:
3460 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3461 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3463 case SPIRV::GroupUniform:
3464 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3465 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3467 case SPIRV::IntegerDot:
3469 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3470 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3472 case SPIRV::WriteImage:
3473 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3475 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3476 case SPIRV::Construct:
3477 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3479 case SPIRV::KernelClock:
3480 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3482 return std::make_tuple(-1, 0, 0);
3484 return std::make_tuple(-1, 0, 0);
3488 SPIRV::InstructionSet::InstructionSet Set,
3493 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3497 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3498 std::unique_ptr<const IncomingCall>
Call =
3503 return std::nullopt;
3508 if (Args.size() <
Call->Builtin->MinNumArgs) {
3509 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3510 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3511 <<
", got " << Args.size()
3512 <<
"; treating as a normal function\n");
3513 return std::nullopt;
3515 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3516 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3517 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3518 <<
", got " << Args.size()
3519 <<
"; treating as a normal function\n");
3520 return std::nullopt;
3524 switch (
Call->Builtin->Group) {
3525 case SPIRV::Extended:
3527 case SPIRV::Relational:
3531 case SPIRV::Variable:
3535 case SPIRV::AtomicFloating:
3537 case SPIRV::Barrier:
3539 case SPIRV::CastToPtr:
3542 case SPIRV::IntegerDot:
3546 case SPIRV::ICarryBorrow:
3548 case SPIRV::MulExtended:
3550 case SPIRV::Arithmetic:
3552 case SPIRV::GetQuery:
3554 case SPIRV::ImageSizeQuery:
3556 case SPIRV::ImageMiscQuery:
3558 case SPIRV::ReadImage:
3560 case SPIRV::WriteImage:
3562 case SPIRV::SampleImage:
3566 case SPIRV::Construct:
3568 case SPIRV::SpecConstant:
3570 case SPIRV::Enqueue:
3572 case SPIRV::AsyncCopy:
3574 case SPIRV::Convert:
3576 case SPIRV::VectorLoadStore:
3578 case SPIRV::LoadStore:
3580 case SPIRV::IntelSubgroups:
3582 case SPIRV::GroupUniform:
3584 case SPIRV::KernelClock:
3586 case SPIRV::CoopMatr:
3588 case SPIRV::ExtendedBitOps:
3590 case SPIRV::BindlessINTEL:
3592 case SPIRV::TernaryBitwiseINTEL:
3594 case SPIRV::Block2DLoadStore:
3598 case SPIRV::PredicatedLoadStore:
3600 case SPIRV::BlockingPipes:
3602 case SPIRV::ArbitraryPrecisionFixedPoint:
3604 case SPIRV::ImageChannelDataTypes:
3606 case SPIRV::ArbitraryFloatingPoint:
3617 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3618 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3635 unsigned VecElts = 0;
3646 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3658 auto Pos1 = DemangledCall.
find(
'(');
3661 auto Pos2 = DemangledCall.
find(
')');
3664 DemangledCall.
slice(Pos1 + 1, Pos2)
3665 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3673 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3675 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3684#define GET_BuiltinTypes_DECL
3685#define GET_BuiltinTypes_IMPL
3692#define GET_OpenCLTypes_DECL
3693#define GET_OpenCLTypes_IMPL
3695#include "SPIRVGenTables.inc"
3703 if (Name.starts_with(
"void"))
3705 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3707 else if (Name.starts_with(
"bfloat"))
3709 else if (Name.starts_with(
"float"))
3711 else if (Name.starts_with(
"half"))
3713 else if (Name.starts_with(
"double"))
3726 unsigned Opcode = TypeRecord->
Opcode;
3741 "Invalid number of parameters for SPIR-V pipe builtin!");
3744 SPIRV::AccessQualifier::AccessQualifier(
3752 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3754 "SPIR-V coop matrices builtin type must have a type parameter!");
3757 SPIRV::AccessQualifier::ReadWrite,
true);
3760 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3769 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3778 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3785 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3786 assert(ParamEType->getNumTypeParameters() == 1 &&
3787 "Inline SPIR-V integral constant builtin must have a type "
3789 assert(ParamEType->getNumIntParameters() == 1 &&
3790 "Inline SPIR-V integral constant builtin must have a "
3793 auto OperandValue = ParamEType->getIntParameter(0);
3794 auto *OperandType = ParamEType->getTypeParameter(0);
3797 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3800 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3802 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3803 assert(ParamEType->getNumTypeParameters() == 0 &&
3804 "Inline SPIR-V literal builtin does not take type "
3806 assert(ParamEType->getNumIntParameters() == 1 &&
3807 "Inline SPIR-V literal builtin must have an integer "
3810 auto OperandValue = ParamEType->getIntParameter(0);
3817 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3829 "Vulkan buffers have exactly one type for the type of the buffer.");
3831 "Vulkan buffer have 2 integer parameters: storage class and is "
3835 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
3846 "Vulkan push constants have exactly one type as argument.");
3860 StringRef NameWithParameters = TypeName;
3867 SPIRV::lookupOpenCLType(NameWithParameters);
3870 NameWithParameters);
3871 NameWithParameters =
3879 "Unknown builtin opaque type!");
3883 if (!NameWithParameters.
contains(
'_'))
3887 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
3891 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
3892 if (HasTypeParameter)
3895 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
3896 unsigned IntParameter = 0;
3897 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
3900 "Invalid format of SPIR-V builtin parameter literal!");
3904 NameWithParameters.
substr(0, BaseNameLength),
3905 TypeParameters, IntParameters);
3910 SPIRV::AccessQualifier::AccessQualifier AccessQual,
3931 if (Name ==
"spirv.Type") {
3933 }
else if (Name ==
"spirv.VulkanBuffer") {
3935 }
else if (Name ==
"spirv.Padding") {
3937 }
else if (Name ==
"spirv.PushConstant") {
3939 }
else if (Name ==
"spirv.Layout") {
3953 switch (TypeRecord->
Opcode) {
3954 case SPIRV::OpTypeImage:
3957 case SPIRV::OpTypePipe:
3960 case SPIRV::OpTypeDeviceEvent:
3963 case SPIRV::OpTypeSampler:
3966 case SPIRV::OpTypeSampledImage:
3969 case SPIRV::OpTypeCooperativeMatrixKHR:
3991 return Builtin->
Group == Pipe || Builtin->
Group == CastToPtr ||
3992 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.
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