20#include "llvm/IR/IntrinsicsSPIRV.h"
25#define DEBUG_TYPE "spirv-builtins"
29#define GET_BuiltinGroup_DECL
30#include "SPIRVGenTables.inc"
34 InstructionSet::InstructionSet
Set;
40#define GET_DemangledBuiltins_DECL
41#define GET_DemangledBuiltins_IMPL
63 InstructionSet::InstructionSet
Set;
67#define GET_NativeBuiltins_DECL
68#define GET_NativeBuiltins_IMPL
86#define GET_GroupBuiltins_DECL
87#define GET_GroupBuiltins_IMPL
97#define GET_IntelSubgroupsBuiltins_DECL
98#define GET_IntelSubgroupsBuiltins_IMPL
105#define GET_AtomicFloatingBuiltins_DECL
106#define GET_AtomicFloatingBuiltins_IMPL
113#define GET_GroupUniformBuiltins_DECL
114#define GET_GroupUniformBuiltins_IMPL
118 InstructionSet::InstructionSet
Set;
123#define GET_GetBuiltins_DECL
124#define GET_GetBuiltins_IMPL
128 InstructionSet::InstructionSet
Set;
132#define GET_ImageQueryBuiltins_DECL
133#define GET_ImageQueryBuiltins_IMPL
141#define GET_IntegerDotProductBuiltins_DECL
142#define GET_IntegerDotProductBuiltins_IMPL
146 InstructionSet::InstructionSet
Set;
157 InstructionSet::InstructionSet
Set;
165#define GET_ConvertBuiltins_DECL
166#define GET_ConvertBuiltins_IMPL
168using namespace InstructionSet;
169#define GET_VectorLoadStoreBuiltins_DECL
170#define GET_VectorLoadStoreBuiltins_IMPL
172#define GET_CLMemoryScope_DECL
173#define GET_CLSamplerAddressingMode_DECL
174#define GET_CLMemoryFenceFlags_DECL
175#define GET_ExtendedBuiltins_DECL
176#include "SPIRVGenTables.inc"
188 StringRef PassPrefix =
"(anonymous namespace)::";
190 std::string BuiltinName = DemangledCall.
str();
195 std::size_t Pos = BuiltinName.find(
">(");
196 if (Pos != std::string::npos) {
197 BuiltinName = BuiltinName.substr(0, BuiltinName.rfind(
'<', Pos));
199 Pos = BuiltinName.find(
'(');
200 if (Pos != std::string::npos)
201 BuiltinName = BuiltinName.substr(0, Pos);
203 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(
' ') + 1);
207 if (BuiltinName.find(PassPrefix) == 0)
208 BuiltinName = BuiltinName.substr(PassPrefix.
size());
209 else if (BuiltinName.find(SpvPrefix) == 0)
210 BuiltinName = BuiltinName.substr(SpvPrefix.
size());
213 if (BuiltinName.rfind(
"__spirv_ocl_", 0) == 0)
214 BuiltinName = BuiltinName.substr(12);
240 static const std::regex SpvWithR(
241 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"
243 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"
244 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
245 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
247 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");
249 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
250 std::ssub_match SubMatch;
251 if (DecorationId && Match.size() > 3) {
256 BuiltinName = SubMatch.str();
273static std::unique_ptr<const SPIRV::IncomingCall>
275 SPIRV::InstructionSet::InstructionSet Set,
282 DemangledCall.
slice(DemangledCall.
find(
'(') + 1, DemangledCall.
find(
')'));
283 BuiltinArgs.
split(BuiltinArgumentTypes,
',', -1,
false);
288 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))
289 return std::make_unique<SPIRV::IncomingCall>(
290 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
295 if (BuiltinArgumentTypes.
size() >= 1) {
296 char FirstArgumentType = BuiltinArgumentTypes[0][0];
301 switch (FirstArgumentType) {
304 if (Set == SPIRV::InstructionSet::OpenCL_std)
306 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
314 if (Set == SPIRV::InstructionSet::OpenCL_std)
316 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
323 if (Set == SPIRV::InstructionSet::OpenCL_std ||
324 Set == SPIRV::InstructionSet::GLSL_std_450)
330 if (!Prefix.empty() &&
331 (Builtin = SPIRV::lookupBuiltin(Prefix + BuiltinName, Set)))
332 return std::make_unique<SPIRV::IncomingCall>(
333 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
340 switch (FirstArgumentType) {
361 if (!Suffix.empty() &&
362 (Builtin = SPIRV::lookupBuiltin(BuiltinName + Suffix, Set)))
363 return std::make_unique<SPIRV::IncomingCall>(
364 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
376 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
377 MI->getOperand(1).isReg());
378 Register BitcastReg =
MI->getOperand(1).getReg();
380 assert(BitcastMI &&
"Definition for source reg not found.");
381 if (BitcastMI->
getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
392 assert(
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
393 DefMI->getOperand(1).isCImm());
394 return DefMI->getOperand(1).getCImm()->getValue().getZExtValue();
406 Register ValueReg =
MI->getOperand(0).getReg();
412 assert(Ty &&
"Type is expected");
424 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
425 return MI->getOperand(1).getGlobal()->getValueType();
427 "Blocks in OpenCL C must be traceable to allocation site");
439static std::tuple<Register, SPIRVTypeInst>
445 if (ResultType->
getOpcode() == SPIRV::OpTypeVector) {
460 return std::make_tuple(ResultRegister, BoolType);
470 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {
481 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
491 if (!DestinationReg.isValid())
496 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
497 return DestinationReg;
506 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
507 SPIRV::LinkageType::Import}) {
515 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
521 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
528 return LoadedRegister;
539static SPIRV::MemorySemantics::MemorySemantics
542 case std::memory_order_relaxed:
543 return SPIRV::MemorySemantics::None;
544 case std::memory_order_acquire:
545 return SPIRV::MemorySemantics::Acquire;
546 case std::memory_order_release:
547 return SPIRV::MemorySemantics::Release;
548 case std::memory_order_acq_rel:
549 return SPIRV::MemorySemantics::AcquireRelease;
550 case std::memory_order_seq_cst:
551 return SPIRV::MemorySemantics::SequentiallyConsistent;
559 case SPIRV::CLMemoryScope::memory_scope_work_item:
560 return SPIRV::Scope::Invocation;
561 case SPIRV::CLMemoryScope::memory_scope_work_group:
562 return SPIRV::Scope::Workgroup;
563 case SPIRV::CLMemoryScope::memory_scope_device:
564 return SPIRV::Scope::Device;
565 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
566 return SPIRV::Scope::CrossDevice;
567 case SPIRV::CLMemoryScope::memory_scope_sub_group:
568 return SPIRV::Scope::Subgroup;
581 SPIRV::Scope::Scope Scope,
585 if (CLScopeRegister.
isValid()) {
587 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(CLScopeRegister, MRI));
590 if (CLScope ==
static_cast<unsigned>(Scope)) {
591 MRI->
setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
592 return CLScopeRegister;
604 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
608 Register PtrRegister,
unsigned &Semantics,
611 if (SemanticsRegister.
isValid()) {
613 std::memory_order Order =
614 static_cast<std::memory_order
>(
getIConstVal(SemanticsRegister, MRI));
618 if (
static_cast<unsigned>(Order) == Semantics) {
619 MRI->
setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);
620 return SemanticsRegister;
633 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
634 for (
unsigned i = 0; i < Sz; ++i)
635 MIB.addUse(
Call->Arguments[i]);
644 if (
Call->isSpirvOp())
648 "Need 2 arguments for atomic init translation");
660 if (
Call->isSpirvOp())
668 Call->Arguments.size() > 1
672 if (
Call->Arguments.size() > 2) {
674 MemSemanticsReg =
Call->Arguments[2];
677 SPIRV::MemorySemantics::SequentiallyConsistent |
695 if (
Call->isSpirvOp())
703 SPIRV::MemorySemantics::SequentiallyConsistent |
718 if (
Call->isSpirvOp())
722 bool IsCmpxchg =
Call->Builtin->Name.contains(
"cmpxchg");
732 SPIRV::OpTypePointer);
735 assert(IsCmpxchg ? ExpectedType == SPIRV::OpTypeInt
736 : ExpectedType == SPIRV::OpTypePointer);
741 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
749 ? SPIRV::MemorySemantics::None
750 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
753 ? SPIRV::MemorySemantics::None
754 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
755 if (
Call->Arguments.size() >= 4) {
757 "Need 5+ args for explicit atomic cmpxchg");
764 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
765 MemSemEqualReg =
Call->Arguments[3];
766 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
767 MemSemUnequalReg =
Call->Arguments[4];
771 if (!MemSemUnequalReg.
isValid())
775 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
776 if (
Call->Arguments.size() >= 6) {
778 "Extra args for explicit atomic cmpxchg");
779 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
782 if (ClScope ==
static_cast<unsigned>(Scope))
783 ScopeReg =
Call->Arguments[5];
794 :
Call->ReturnRegister;
819 if (
Call->isSpirvOp())
828 "Too many args for explicit atomic RMW");
829 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
830 MIRBuilder, GR, MRI);
833 unsigned Semantics = SPIRV::MemorySemantics::None;
837 Semantics, MIRBuilder, GR);
841 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
842 if (Opcode == SPIRV::OpAtomicIAdd) {
843 Opcode = SPIRV::OpAtomicFAddEXT;
844 }
else if (Opcode == SPIRV::OpAtomicISub) {
847 Opcode = SPIRV::OpAtomicFAddEXT;
858 ValueReg = NegValueReg;
877 "Wrong number of atomic floating-type builtin");
897 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
899 if (
Call->isSpirvOp())
905 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
909 Semantics, MIRBuilder, GR);
911 assert((Opcode != SPIRV::OpAtomicFlagClear ||
912 (Semantics != SPIRV::MemorySemantics::Acquire &&
913 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
914 "Invalid memory order argument!");
919 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
937 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
938 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
939 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
940 std::string DiagMsg = std::string(Builtin->
Name) +
941 ": the builtin requires the following SPIR-V "
942 "extension: SPV_INTEL_split_barrier";
946 if (
Call->isSpirvOp())
951 unsigned MemSemantics = SPIRV::MemorySemantics::None;
953 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
954 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
956 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
957 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
959 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
960 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
962 if (Opcode == SPIRV::OpMemoryBarrier)
966 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
967 MemSemantics |= SPIRV::MemorySemantics::Release;
968 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
969 MemSemantics |= SPIRV::MemorySemantics::Acquire;
971 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
974 MemFlags == MemSemantics
978 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
979 SPIRV::Scope::Scope MemScope = Scope;
980 if (
Call->Arguments.size() >= 2) {
982 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
983 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
984 "Extra args for explicitly scoped barrier");
985 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
986 :
Call->Arguments[1];
987 SPIRV::CLMemoryScope CLScope =
988 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
990 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
991 (Opcode == SPIRV::OpMemoryBarrier))
993 if (CLScope ==
static_cast<unsigned>(Scope))
994 ScopeReg =
Call->Arguments[1];
1001 if (Opcode != SPIRV::OpMemoryBarrier)
1003 MIB.
addUse(MemSemanticsReg);
1015 if ((Opcode == SPIRV::OpBitFieldInsert ||
1016 Opcode == SPIRV::OpBitFieldSExtract ||
1017 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1018 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1019 std::string DiagMsg = std::string(Builtin->
Name) +
1020 ": the builtin requires the following SPIR-V "
1021 "extension: SPV_KHR_bit_instructions";
1026 if (
Call->isSpirvOp())
1033 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1045 if (
Call->isSpirvOp())
1062 if (
Call->isSpirvOp())
1069 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1079 if (
Call->isSpirvOp())
1086 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1098 if (
Call->isSpirvOp())
1104 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1114 case SPIRV::OpCommitReadPipe:
1115 case SPIRV::OpCommitWritePipe:
1117 case SPIRV::OpGroupCommitReadPipe:
1118 case SPIRV::OpGroupCommitWritePipe:
1119 case SPIRV::OpGroupReserveReadPipePackets:
1120 case SPIRV::OpGroupReserveWritePipePackets: {
1124 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1128 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1129 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1133 MIB.
addUse(ScopeConstReg);
1134 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1147 case SPIRV::Dim::DIM_1D:
1148 case SPIRV::Dim::DIM_Buffer:
1150 case SPIRV::Dim::DIM_2D:
1151 case SPIRV::Dim::DIM_Cube:
1152 case SPIRV::Dim::DIM_Rect:
1154 case SPIRV::Dim::DIM_3D:
1167 return arrayed ? numComps + 1 : numComps;
1171 switch (BuiltinNumber) {
1172 case SPIRV::OpenCLExtInst::s_min:
1173 case SPIRV::OpenCLExtInst::u_min:
1174 case SPIRV::OpenCLExtInst::s_max:
1175 case SPIRV::OpenCLExtInst::u_max:
1176 case SPIRV::OpenCLExtInst::fmax:
1177 case SPIRV::OpenCLExtInst::fmin:
1178 case SPIRV::OpenCLExtInst::fmax_common:
1179 case SPIRV::OpenCLExtInst::fmin_common:
1180 case SPIRV::OpenCLExtInst::s_clamp:
1181 case SPIRV::OpenCLExtInst::fclamp:
1182 case SPIRV::OpenCLExtInst::u_clamp:
1183 case SPIRV::OpenCLExtInst::mix:
1184 case SPIRV::OpenCLExtInst::step:
1185 case SPIRV::OpenCLExtInst::smoothstep:
1186 case SPIRV::OpenCLExtInst::ldexp:
1187 case SPIRV::OpenCLExtInst::pown:
1188 case SPIRV::OpenCLExtInst::rootn:
1205 unsigned ResultElementCount =
1207 bool MayNeedPromotionToVec =
1210 if (!MayNeedPromotionToVec)
1211 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1218 ArgumentType !=
Call->ReturnType) {
1220 ArgumentType, ResultElementCount, MIRBuilder,
true);
1223 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1226 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1240 SPIRV::lookupExtendedBuiltin(Builtin->
Name, Builtin->
Set)->Number;
1247 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1248 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1249 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1251 ? SPIRV::OpenCLExtInst::fmin
1252 : SPIRV::OpenCLExtInst::fmax;
1260 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1261 Number == SPIRV::OpenCLExtInst::fma) {
1269 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1272 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1280 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1281 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1290 if (ST.isKernel() ||
1291 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1297 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1301 AddNoNan = AddNoNan && ArgTest &
fcNan;
1302 AddNoInf = AddNoInf && ArgTest &
fcInf;
1320 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1324 std::tie(CompareRegister, RelationType) =
1330 Call->Arguments.end());
1331 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1360 Call->ReturnType, GR);
1368 SPIRV::lookupGroupBuiltin(Builtin->
Name);
1371 if (
Call->isSpirvOp()) {
1374 if (GroupBuiltin->
Opcode ==
1375 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1376 Call->Arguments.size() > 4)
1385 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1387 "Group Operation parameter must be an integer constant");
1388 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1395 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1408 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1409 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1413 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1422 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1434 const bool HasBoolReturnTy =
1439 if (HasBoolReturnTy)
1440 std::tie(GroupResultRegister, GroupResultType) =
1443 auto Scope = Builtin->
Name.
starts_with(
"sub_group") ? SPIRV::Scope::Subgroup
1444 : SPIRV::Scope::Workgroup;
1448 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1449 Call->Arguments.size() > 2) {
1457 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1459 unsigned VecLen =
Call->Arguments.size() - 1;
1468 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1469 MIB.addUse(
Call->Arguments[i]);
1478 .
addDef(GroupResultRegister)
1484 if (
Call->Arguments.size() > 0) {
1485 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1490 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1491 MIB.addUse(
Call->Arguments[i]);
1495 if (HasBoolReturnTy)
1497 Call->ReturnType, GR);
1508 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
Name);
1510 if (IntelSubgroups->
IsMedia &&
1511 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1512 std::string DiagMsg = std::string(Builtin->
Name) +
1513 ": the builtin requires the following SPIR-V "
1514 "extension: SPV_INTEL_media_block_io";
1516 }
else if (!IntelSubgroups->
IsMedia &&
1517 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1518 std::string DiagMsg = std::string(Builtin->
Name) +
1519 ": the builtin requires the following SPIR-V "
1520 "extension: SPV_INTEL_subgroups";
1525 if (
Call->isSpirvOp()) {
1526 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1527 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1528 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1534 if (IntelSubgroups->
IsBlock) {
1537 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1543 case SPIRV::OpSubgroupBlockReadINTEL:
1544 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1546 case SPIRV::OpSubgroupBlockWriteINTEL:
1547 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1570 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1581 if (!ST->canUseExtension(
1582 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1583 std::string DiagMsg = std::string(Builtin->
Name) +
1584 ": the builtin requires the following SPIR-V "
1585 "extension: SPV_KHR_uniform_group_instructions";
1589 SPIRV::lookupGroupUniformBuiltin(Builtin->
Name);
1599 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1601 "expect a constant group operation for a uniform group instruction",
1604 if (!ConstOperand.
isCImm())
1614 MIB.addUse(ValueReg);
1625 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1626 std::string DiagMsg = std::string(Builtin->
Name) +
1627 ": the builtin requires the following SPIR-V "
1628 "extension: SPV_KHR_shader_clock";
1634 if (Builtin->
Name ==
"__spirv_ReadClockKHR") {
1641 SPIRV::Scope::Scope ScopeArg =
1643 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1644 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1645 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1686 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1689 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1700 bool IsConstantIndex =
1701 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1705 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1707 if (PointerSize != ResultWidth) {
1709 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1711 MIRBuilder.
getMF());
1712 ToTruncate = DefaultReg;
1716 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1725 if (!IsConstantIndex || PointerSize != ResultWidth) {
1734 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1737 if (!IsConstantIndex) {
1738 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1745 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1760 if (PointerSize != ResultWidth) {
1763 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1765 MIRBuilder.
getMF());
1768 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1770 ToTruncate = SelectionResult;
1772 ToTruncate = Extracted;
1776 if (PointerSize != ResultWidth)
1786 SPIRV::BuiltIn::BuiltIn
Value =
1787 SPIRV::lookupGetBuiltin(Builtin->
Name, Builtin->
Set)->
Value;
1789 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1795 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1802 LLType,
Call->ReturnRegister);
1811 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1814 case SPIRV::OpStore:
1816 case SPIRV::OpAtomicLoad:
1818 case SPIRV::OpAtomicStore:
1820 case SPIRV::OpAtomicCompareExchange:
1821 case SPIRV::OpAtomicCompareExchangeWeak:
1824 case SPIRV::OpAtomicIAdd:
1825 case SPIRV::OpAtomicISub:
1826 case SPIRV::OpAtomicOr:
1827 case SPIRV::OpAtomicXor:
1828 case SPIRV::OpAtomicAnd:
1829 case SPIRV::OpAtomicExchange:
1830 case SPIRV::OpAtomicSMax:
1831 case SPIRV::OpAtomicSMin:
1832 case SPIRV::OpAtomicUMax:
1833 case SPIRV::OpAtomicUMin:
1835 case SPIRV::OpMemoryBarrier:
1837 case SPIRV::OpAtomicFlagTestAndSet:
1838 case SPIRV::OpAtomicFlagClear:
1841 if (
Call->isSpirvOp())
1853 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
Name)->Opcode;
1856 case SPIRV::OpAtomicFAddEXT:
1857 case SPIRV::OpAtomicFMinEXT:
1858 case SPIRV::OpAtomicFMaxEXT:
1871 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1882 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1884 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1885 SPIRV::StorageClass::StorageClass ResSC =
1896 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1907 if (
Call->isSpirvOp())
1912 SPIRV::OpTypeVector;
1914 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1915 bool IsSwapReq =
false;
1920 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1924 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
Name);
1934 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1935 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1937 if (
Call->BuiltinName ==
"dot") {
1938 if (IsFirstSigned && IsSecondSigned)
1940 else if (!IsFirstSigned && !IsSecondSigned)
1943 OC = SPIRV::OpSUDot;
1947 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1948 if (IsFirstSigned && IsSecondSigned)
1949 OC = SPIRV::OpSDotAccSat;
1950 else if (!IsFirstSigned && !IsSecondSigned)
1951 OC = SPIRV::OpUDotAccSat;
1953 OC = SPIRV::OpSUDotAccSat;
1969 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1972 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1978 if (!IsVec && OC != SPIRV::OpFMulS)
1979 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
1988 SPIRV::BuiltIn::BuiltIn
Value =
1989 SPIRV::lookupGetBuiltin(Builtin->
Name, Builtin->
Set)->
Value;
1992 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
1996 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
1997 false, std::nullopt);
2033 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2040 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2042 "overflow builtins");
2046 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2048 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
2050 case SPIRV::OpIAddCarryS:
2051 Opcode = SPIRV::OpIAddCarryV;
2053 case SPIRV::OpISubBorrowS:
2054 Opcode = SPIRV::OpISubBorrowV;
2059 RetType, MIRBuilder, GR);
2080 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2081 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2082 "Expected OpUMulExtended or OpSMulExtended");
2085 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2097 RetType =
Call->ReturnType;
2100 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2102 "multiplication builtins");
2105 "extended multiplication builtins");
2110 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2115 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2117 if (OpType1 != Member0Type)
2144 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2158 SPIRV::BuiltIn::BuiltIn
Value =
2159 SPIRV::lookupGetBuiltin(
Call->Builtin->Name,
Call->Builtin->Set)->
Value;
2160 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2161 Value == SPIRV::BuiltIn::NumWorkgroups ||
2162 Value == SPIRV::BuiltIn::WorkgroupSize ||
2163 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2173 SPIRV::lookupImageQueryBuiltin(Builtin->
Name, Builtin->
Set)->Component;
2177 unsigned NumExpectedRetComponents =
2184 if (NumExpectedRetComponents != NumActualRetComponents) {
2185 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2186 ?
Call->ReturnType->getOperand(1).getImm()
2193 IntTy, NumActualRetComponents, MIRBuilder,
true);
2198 bool UseQuerySize = IsDimBuf || IsMultisampled;
2200 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2207 if (NumExpectedRetComponents == NumActualRetComponents)
2209 if (NumExpectedRetComponents == 1) {
2211 unsigned ExtractedComposite =
2212 Component == 3 ? NumActualRetComponents - 1 : Component;
2213 assert(ExtractedComposite < NumActualRetComponents &&
2214 "Invalid composite index!");
2217 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2220 if (TypeReg != NewTypeReg)
2221 TypeReg = NewTypeReg;
2225 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2229 .
addImm(ExtractedComposite);
2235 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2240 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2241 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2249 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2250 "Image samples query result must be of int type!");
2255 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2258 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2260 (void)ImageDimensionality;
2263 case SPIRV::OpImageQuerySamples:
2264 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2265 "Image must be of 2D dimensionality");
2267 case SPIRV::OpImageQueryLevels:
2268 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2269 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2270 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2271 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2272 "Image must be of 1D/2D/3D/Cube dimensionality");
2284static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2286 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2287 case SPIRV::CLK_ADDRESS_CLAMP:
2288 return SPIRV::SamplerAddressingMode::Clamp;
2289 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2290 return SPIRV::SamplerAddressingMode::ClampToEdge;
2291 case SPIRV::CLK_ADDRESS_REPEAT:
2292 return SPIRV::SamplerAddressingMode::Repeat;
2293 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2294 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2295 case SPIRV::CLK_ADDRESS_NONE:
2296 return SPIRV::SamplerAddressingMode::None;
2303 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2306static SPIRV::SamplerFilterMode::SamplerFilterMode
2308 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2309 return SPIRV::SamplerFilterMode::Linear;
2310 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2311 return SPIRV::SamplerFilterMode::Nearest;
2312 return SPIRV::SamplerFilterMode::Nearest;
2319 if (
Call->isSpirvOp())
2326 if (HasOclSampler) {
2351 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2358 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2363 .
addImm(SPIRV::ImageOperand::Lod)
2365 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2371 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2376 .
addImm(SPIRV::ImageOperand::Lod)
2379 }
else if (HasMsaa) {
2385 .
addImm(SPIRV::ImageOperand::Sample)
2400 if (
Call->isSpirvOp())
2415 if (
Call->Builtin->Name.contains_insensitive(
2416 "__translate_sampler_initializer")) {
2424 }
else if (
Call->Builtin->Name.contains_insensitive(
"__spirv_SampledImage")) {
2431 Call->ReturnRegister.isValid()
2432 ?
Call->ReturnRegister
2440 }
else if (
Call->Builtin->Name.contains_insensitive(
2441 "__spirv_ImageSampleExplicitLod")) {
2443 std::string ReturnType = DemangledCall.
str();
2444 if (DemangledCall.
contains(
"_R")) {
2445 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2446 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2451 ReturnType, MIRBuilder,
true));
2453 std::string DiagMsg =
2454 "Unable to recognize SPIRV type name: " + ReturnType;
2457 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2462 .
addImm(SPIRV::ImageOperand::Lod)
2474 if (!ResTy.
isVector() && CondTy.isVector())
2476 "boolean condition");
2478 Call->Arguments[1],
Call->Arguments[2]);
2486 SPIRV::OpCompositeConstructContinuedINTEL,
2487 Call->Arguments,
Call->ReturnRegister,
2497 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2498 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2499 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2500 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2501 unsigned ArgSz =
Call->Arguments.size();
2502 unsigned LiteralIdx = 0;
2505 case SPIRV::OpCooperativeMatrixLoadKHR:
2506 LiteralIdx = ArgSz > 3 ? 3 : 0;
2508 case SPIRV::OpCooperativeMatrixStoreKHR:
2509 LiteralIdx = ArgSz > 4 ? 4 : 0;
2511 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2512 LiteralIdx = ArgSz > 7 ? 7 : 0;
2514 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2515 LiteralIdx = ArgSz > 8 ? 8 : 0;
2518 case SPIRV::OpCooperativeMatrixMulAddKHR:
2519 LiteralIdx = ArgSz > 3 ? 3 : 0;
2525 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2527 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2544 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2555 IsSet ? TypeReg :
Register(0), ImmArgs);
2564 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2568 case SPIRV::OpSpecConstant: {
2573 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2574 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2575 "Argument should be either an int or floating-point constant");
2578 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2579 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2581 ? SPIRV::OpSpecConstantTrue
2582 : SPIRV::OpSpecConstantFalse;
2588 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2589 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2601 case SPIRV::OpSpecConstantComposite: {
2603 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2604 Call->Arguments,
Call->ReturnRegister,
2619 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2630 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2640 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2658 InputReg =
Call->Arguments[1];
2661 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2669 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2670 MRI->
setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2674 for (
unsigned index = 2; index < 7; index++) {
2693 MRI->
setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2694 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2697 for (
unsigned index = 1; index < 6; index++)
2710 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2722 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2732 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2743 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2753 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2755 unsigned Scope = SPIRV::Scope::Workgroup;
2757 Scope = SPIRV::Scope::Subgroup;
2767 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2769 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2770 unsigned ArgSz =
Call->Arguments.size();
2780 IsSet ? TypeReg :
Register(0), ImmArgs);
2805 const unsigned NumCallArgs =
Call->Arguments.size();
2806 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2807 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2810 bool HasSRetArg = RetTy->
isVoidTy();
2812 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2813 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2814 const unsigned MaxNDRangeArgs = 3;
2815 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2817 const unsigned GlobalWorkSizeArgIdx =
2818 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2819 const unsigned LocalWorkSizeArgIdx =
2820 (NumNDRangeArgs == 1)
2822 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2823 const unsigned GlobalWorkOffsetArgIdx =
2824 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2829 assert(AddressModelBits == 64 || AddressModelBits == 32);
2833 unsigned Dimension = 0;
2834 Call->Builtin->Name.substr(8, 1).getAsInteger(10, Dimension);
2835 assert(Dimension <= 3 && Dimension >= 1);
2842 if (Dimension == 1) {
2845 "Expected scalar integer type");
2847 if (NumNDRangeArgs < MaxNDRangeArgs)
2854 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2856 if (NumNDRangeArgs < MaxNDRangeArgs) {
2862 SpvFieldTy, *ST.getInstrInfo());
2868 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2869 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2877 "Only pointer types are supported for loading values");
2891 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2892 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2893 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2896 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2901 .
addUse(GlobalWorkOffset);
2918 .
addUse(GlobalWorkOffset);
2950 bool IsSpirvOp =
Call->isSpirvOp();
2951 bool HasEvents =
Call->Builtin->Name.contains(
"_events") || IsSpirvOp;
2952 bool HasVarArgs =
Call->Builtin->Name.contains(
"_varargs") || IsSpirvOp;
2954 const unsigned NumArgs =
Call->Arguments.size();
2955 const unsigned BaseArgIdx = 0;
2956 const unsigned IncorrectIdx = NumArgs + 1;
2958 const unsigned QueueIdx = BaseArgIdx;
2959 const unsigned FlagsIdx = BaseArgIdx + 1;
2960 const unsigned NDRangeIdx = BaseArgIdx + 2;
2961 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
2962 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
2963 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
2964 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
2965 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
2966 const unsigned LocalSizeNumElemIdx =
2967 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2968 const unsigned LocalSizeElemPtrIdx =
2969 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2971 [[maybe_unused]]
const unsigned LastArgIdx =
2972 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
2973 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
2979 auto BuildDeviceEventNullPtr = [&]() {
2983 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
2991 auto IsNullEvent = [&](
Register R) {
2993 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
2994 Def->getOperand(1).getCImm()->isZero();
2997 NumEventsReg =
Call->Arguments[NumEventsIdx];
2998 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
2999 RetEventReg =
Call->Arguments[RetEventIdx];
3000 if (IsNullEvent(WaitEventsReg))
3001 WaitEventsReg = BuildDeviceEventNullPtr();
3002 if (IsNullEvent(RetEventReg))
3003 RetEventReg = BuildDeviceEventNullPtr();
3006 Register NullPtr = BuildDeviceEventNullPtr();
3007 WaitEventsReg = NullPtr;
3008 RetEventReg = NullPtr;
3029 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3036 .
addUse(BlockLiteralReg);
3046 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3050 ConstOp.
isCImm() &&
"Expected constant immediate");
3053 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3055 for (
unsigned i = 0; i < NumElem; ++i) {
3061 .
addUse(LocalSizeArrayReg)
3069 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3082 for (
auto &LocalSize : LocalSizes)
3094 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
3097 case SPIRV::OpRetainEvent:
3098 case SPIRV::OpReleaseEvent:
3100 case SPIRV::OpCreateUserEvent:
3101 case SPIRV::OpGetDefaultQueue:
3105 case SPIRV::OpIsValidEvent:
3110 case SPIRV::OpSetUserEventStatus:
3114 case SPIRV::OpCaptureEventProfilingInfo:
3119 case SPIRV::OpBuildNDRange:
3121 case SPIRV::OpEnqueueKernel:
3134 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
3136 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3138 if (
Call->isSpirvOp())
3145 case SPIRV::OpGroupAsyncCopy: {
3147 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3151 unsigned NumArgs =
Call->Arguments.size();
3161 ?
Call->Arguments[3]
3169 case SPIRV::OpGroupWaitEvents:
3185 SPIRV::lookupConvertBuiltin(
Call->Builtin->Name,
Call->Builtin->Set);
3187 if (!Builtin &&
Call->isSpirvOp()) {
3190 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
3195 assert(Builtin &&
"Conversion builtin not found.");
3198 SPIRV::Decoration::SaturatedConversion, {});
3201 bool AnyTypeIsFloat =
3208 if (AnyTypeIsFloat) {
3210 SPIRV::Decoration::FPRoundingMode,
3211 {(unsigned)Builtin->RoundingMode});
3215 std::string NeedExtMsg;
3216 bool IsRightComponentsNumber =
true;
3217 unsigned Opcode = SPIRV::OpNop;
3220 bool IsSourceSigned =
3226 : SPIRV::OpSatConvertSToU;
3228 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3230 SPIRV::OpTypeFloat)) {
3234 &MIRBuilder.
getMF().getSubtarget());
3235 if (!ST->canUseExtension(
3236 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3237 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3238 IsRightComponentsNumber =
3241 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3243 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3247 SPIRV::OpTypeFloat)) {
3253 &MIRBuilder.
getMF().getSubtarget());
3254 if (!ST->canUseExtension(
3255 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3256 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3257 IsRightComponentsNumber =
3260 Opcode = SPIRV::OpConvertFToBF16INTEL;
3263 : SPIRV::OpConvertFToU;
3266 SPIRV::OpTypeFloat)) {
3269 &MIRBuilder.
getMF().getSubtarget());
3270 if (!ST->canUseExtension(
3271 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3272 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3273 IsRightComponentsNumber =
3276 Opcode = SPIRV::OpRoundFToTF32INTEL;
3279 Opcode = SPIRV::OpFConvert;
3284 if (!NeedExtMsg.empty()) {
3285 std::string DiagMsg = std::string(Builtin->
Name) +
3286 ": the builtin requires the following SPIR-V "
3291 if (!IsRightComponentsNumber) {
3292 std::string DiagMsg =
3293 std::string(Builtin->
Name) +
3294 ": result and argument must have the same number of components";
3297 assert(Opcode != SPIRV::OpNop &&
3298 "Conversion between the types not implemented!");
3312 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->Name,
3313 Call->Builtin->Set);
3319 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
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:
3436 SPIRV::lookupNativeBuiltin(
Call->Builtin->Name,
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(
Call->Builtin->Name,
3446 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:
3454 if (
const auto *R = SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->Name))
3455 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3457 case SPIRV::IntelSubgroups:
3458 if (
const auto *R = SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->Name))
3459 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3461 case SPIRV::GroupUniform:
3462 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->Name))
3463 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3465 case SPIRV::IntegerDot:
3467 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->Name))
3468 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3470 case SPIRV::WriteImage:
3471 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3473 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3474 case SPIRV::Construct:
3475 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3477 case SPIRV::KernelClock:
3478 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3480 return std::make_tuple(-1, 0, 0);
3482 return std::make_tuple(-1, 0, 0);
3486 SPIRV::InstructionSet::InstructionSet Set,
3491 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3495 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3496 std::unique_ptr<const IncomingCall>
Call =
3501 return std::nullopt;
3506 if (Args.size() <
Call->Builtin->MinNumArgs) {
3507 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3508 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3509 <<
", got " << Args.size()
3510 <<
"; treating as a normal function\n");
3511 return std::nullopt;
3513 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3514 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3515 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3516 <<
", got " << Args.size()
3517 <<
"; treating as a normal function\n");
3518 return std::nullopt;
3522 switch (
Call->Builtin->Group) {
3523 case SPIRV::Extended:
3525 case SPIRV::Relational:
3529 case SPIRV::Variable:
3533 case SPIRV::AtomicFloating:
3535 case SPIRV::Barrier:
3537 case SPIRV::CastToPtr:
3540 case SPIRV::IntegerDot:
3544 case SPIRV::ICarryBorrow:
3546 case SPIRV::MulExtended:
3548 case SPIRV::Arithmetic:
3550 case SPIRV::GetQuery:
3552 case SPIRV::ImageSizeQuery:
3554 case SPIRV::ImageMiscQuery:
3556 case SPIRV::ReadImage:
3558 case SPIRV::WriteImage:
3560 case SPIRV::SampleImage:
3564 case SPIRV::Construct:
3566 case SPIRV::SpecConstant:
3568 case SPIRV::Enqueue:
3570 case SPIRV::AsyncCopy:
3572 case SPIRV::Convert:
3574 case SPIRV::VectorLoadStore:
3576 case SPIRV::LoadStore:
3578 case SPIRV::IntelSubgroups:
3580 case SPIRV::GroupUniform:
3582 case SPIRV::KernelClock:
3584 case SPIRV::CoopMatr:
3586 case SPIRV::ExtendedBitOps:
3588 case SPIRV::BindlessINTEL:
3590 case SPIRV::TernaryBitwiseINTEL:
3592 case SPIRV::Block2DLoadStore:
3596 case SPIRV::PredicatedLoadStore:
3598 case SPIRV::BlockingPipes:
3600 case SPIRV::ArbitraryPrecisionFixedPoint:
3602 case SPIRV::ImageChannelDataTypes:
3604 case SPIRV::ArbitraryFloatingPoint:
3615 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3616 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3633 unsigned VecElts = 0;
3644 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3656 auto Pos1 = DemangledCall.
find(
'(');
3659 auto Pos2 = DemangledCall.
find(
')');
3662 DemangledCall.
slice(Pos1 + 1, Pos2)
3663 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3671 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3673 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3682#define GET_BuiltinTypes_DECL
3683#define GET_BuiltinTypes_IMPL
3690#define GET_OpenCLTypes_DECL
3691#define GET_OpenCLTypes_IMPL
3693#include "SPIRVGenTables.inc"
3701 if (Name.starts_with(
"void"))
3703 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3705 else if (Name.starts_with(
"float"))
3707 else if (Name.starts_with(
"half"))
3720 unsigned Opcode = TypeRecord->
Opcode;
3735 "Invalid number of parameters for SPIR-V pipe builtin!");
3738 SPIRV::AccessQualifier::AccessQualifier(
3746 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3748 "SPIR-V coop matrices builtin type must have a type parameter!");
3751 SPIRV::AccessQualifier::ReadWrite,
true);
3754 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3763 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3772 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3779 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3780 assert(ParamEType->getNumTypeParameters() == 1 &&
3781 "Inline SPIR-V integral constant builtin must have a type "
3783 assert(ParamEType->getNumIntParameters() == 1 &&
3784 "Inline SPIR-V integral constant builtin must have a "
3787 auto OperandValue = ParamEType->getIntParameter(0);
3788 auto *OperandType = ParamEType->getTypeParameter(0);
3791 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3794 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3796 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3797 assert(ParamEType->getNumTypeParameters() == 0 &&
3798 "Inline SPIR-V literal builtin does not take type "
3800 assert(ParamEType->getNumIntParameters() == 1 &&
3801 "Inline SPIR-V literal builtin must have an integer "
3804 auto OperandValue = ParamEType->getIntParameter(0);
3811 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3823 "Vulkan buffers have exactly one type for the type of the buffer.");
3825 "Vulkan buffer have 2 integer parameters: storage class and is "
3829 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
3840 "Vulkan push constants have exactly one type as argument.");
3854 StringRef NameWithParameters = TypeName;
3861 SPIRV::lookupOpenCLType(NameWithParameters);
3864 NameWithParameters);
3872 "Unknown builtin opaque type!");
3876 if (!NameWithParameters.
contains(
'_'))
3880 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
3884 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
3885 if (HasTypeParameter)
3888 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
3889 unsigned IntParameter = 0;
3890 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
3893 "Invalid format of SPIR-V builtin parameter literal!");
3897 NameWithParameters.
substr(0, BaseNameLength),
3898 TypeParameters, IntParameters);
3903 SPIRV::AccessQualifier::AccessQualifier AccessQual,
3924 if (Name ==
"spirv.Type") {
3926 }
else if (Name ==
"spirv.VulkanBuffer") {
3928 }
else if (Name ==
"spirv.Padding") {
3930 }
else if (Name ==
"spirv.PushConstant") {
3932 }
else if (Name ==
"spirv.Layout") {
3946 switch (TypeRecord->
Opcode) {
3947 case SPIRV::OpTypeImage:
3950 case SPIRV::OpTypePipe:
3953 case SPIRV::OpTypeDeviceEvent:
3956 case SPIRV::OpTypeSampler:
3959 case SPIRV::OpTypeSampledImage:
3962 case SPIRV::OpTypeCooperativeMatrixKHR:
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 * getFloatTy(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.
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
Type * parseBuiltinCallArgumentType(StringRef TypeStr, LLVMContext &Ctx)
bool parseBuiltinTypeStr(SmallVector< StringRef, 10 > &BuiltinArgsTypeStrs, const StringRef DemangledCall, LLVMContext &Ctx)
std::optional< bool > lowerBuiltin(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR, const CallBase &CB)
std::tuple< int, unsigned, unsigned > mapBuiltinToOpcode(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)
Helper function for finding a builtin function attributes by a demangled function name.
Type * parseBuiltinCallArgumentBaseType(const StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)
Parses the provided ArgIdx argument base type in the DemangledCall skeleton.
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.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
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)
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...
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 generateSampleImageInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
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)
static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateWaveInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
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 generateEnqueueInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
static const Type * getMachineInstrType(MachineInstr *MI)
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 Register buildLoadInst(SPIRVTypeInst BaseType, Register PtrRegister, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, LLT LowLevelType, Register DestinationReg=Register(0))
Helper function for building a load instruction loading into the DestinationReg.
static bool generateDotOrFMulInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConvertInst(const StringRef DemangledCall, 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 unsigned getConstFromIntrinsic(Register Reg, MachineRegisterInfo *MRI)
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 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)
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)
static bool generateReadImageInst(const StringRef DemangledCall, 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 Type * parseTypeString(const StringRef Name, LLVMContext &Context)
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)
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
StringRef SpirvTypeLiteral
InstructionSet::InstructionSet Set
FPRoundingMode::FPRoundingMode RoundingMode