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];
792 :
Call->ReturnRegister;
817 if (
Call->isSpirvOp())
826 "Too many args for explicit atomic RMW");
827 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
828 MIRBuilder, GR, MRI);
831 unsigned Semantics = SPIRV::MemorySemantics::None;
835 Semantics, MIRBuilder, GR);
839 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
840 if (Opcode == SPIRV::OpAtomicIAdd) {
841 Opcode = SPIRV::OpAtomicFAddEXT;
842 }
else if (Opcode == SPIRV::OpAtomicISub) {
845 Opcode = SPIRV::OpAtomicFAddEXT;
856 ValueReg = NegValueReg;
875 "Wrong number of atomic floating-type builtin");
895 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
897 if (
Call->isSpirvOp())
903 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
907 Semantics, MIRBuilder, GR);
909 assert((Opcode != SPIRV::OpAtomicFlagClear ||
910 (Semantics != SPIRV::MemorySemantics::Acquire &&
911 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
912 "Invalid memory order argument!");
917 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
935 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
936 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
937 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
938 std::string DiagMsg = std::string(Builtin->
name()) +
939 ": the builtin requires the following SPIR-V "
940 "extension: SPV_INTEL_split_barrier";
944 if (
Call->isSpirvOp())
949 unsigned MemSemantics = SPIRV::MemorySemantics::None;
951 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
952 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
954 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
955 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
957 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
958 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
960 if (Opcode == SPIRV::OpMemoryBarrier)
964 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
965 MemSemantics |= SPIRV::MemorySemantics::Release;
966 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
967 MemSemantics |= SPIRV::MemorySemantics::Acquire;
969 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
972 MemFlags == MemSemantics
976 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
977 SPIRV::Scope::Scope MemScope = Scope;
978 if (
Call->Arguments.size() >= 2) {
980 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
981 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
982 "Extra args for explicitly scoped barrier");
983 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
984 :
Call->Arguments[1];
985 SPIRV::CLMemoryScope CLScope =
986 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
988 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
989 (Opcode == SPIRV::OpMemoryBarrier))
991 if (CLScope ==
static_cast<unsigned>(Scope))
992 ScopeReg =
Call->Arguments[1];
999 if (Opcode != SPIRV::OpMemoryBarrier)
1001 MIB.
addUse(MemSemanticsReg);
1013 if ((Opcode == SPIRV::OpBitFieldInsert ||
1014 Opcode == SPIRV::OpBitFieldSExtract ||
1015 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1016 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1017 std::string DiagMsg = std::string(Builtin->
name()) +
1018 ": the builtin requires the following SPIR-V "
1019 "extension: SPV_KHR_bit_instructions";
1024 if (
Call->isSpirvOp())
1031 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1043 if (
Call->isSpirvOp())
1060 if (
Call->isSpirvOp())
1067 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1077 if (
Call->isSpirvOp())
1084 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1096 if (
Call->isSpirvOp())
1102 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1112 case SPIRV::OpCommitReadPipe:
1113 case SPIRV::OpCommitWritePipe:
1115 case SPIRV::OpGroupCommitReadPipe:
1116 case SPIRV::OpGroupCommitWritePipe:
1117 case SPIRV::OpGroupReserveReadPipePackets:
1118 case SPIRV::OpGroupReserveWritePipePackets: {
1122 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1126 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1127 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1131 MIB.
addUse(ScopeConstReg);
1132 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1145 case SPIRV::Dim::DIM_1D:
1146 case SPIRV::Dim::DIM_Buffer:
1148 case SPIRV::Dim::DIM_2D:
1149 case SPIRV::Dim::DIM_Cube:
1150 case SPIRV::Dim::DIM_Rect:
1152 case SPIRV::Dim::DIM_3D:
1165 return arrayed ? numComps + 1 : numComps;
1169 switch (BuiltinNumber) {
1170 case SPIRV::OpenCLExtInst::s_min:
1171 case SPIRV::OpenCLExtInst::u_min:
1172 case SPIRV::OpenCLExtInst::s_max:
1173 case SPIRV::OpenCLExtInst::u_max:
1174 case SPIRV::OpenCLExtInst::fmax:
1175 case SPIRV::OpenCLExtInst::fmin:
1176 case SPIRV::OpenCLExtInst::fmax_common:
1177 case SPIRV::OpenCLExtInst::fmin_common:
1178 case SPIRV::OpenCLExtInst::s_clamp:
1179 case SPIRV::OpenCLExtInst::fclamp:
1180 case SPIRV::OpenCLExtInst::u_clamp:
1181 case SPIRV::OpenCLExtInst::mix:
1182 case SPIRV::OpenCLExtInst::step:
1183 case SPIRV::OpenCLExtInst::smoothstep:
1184 case SPIRV::OpenCLExtInst::ldexp:
1185 case SPIRV::OpenCLExtInst::pown:
1186 case SPIRV::OpenCLExtInst::rootn:
1203 unsigned ResultElementCount =
1205 bool MayNeedPromotionToVec =
1208 if (!MayNeedPromotionToVec)
1209 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1216 ArgumentType !=
Call->ReturnType) {
1218 ArgumentType, ResultElementCount, MIRBuilder,
true);
1221 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1224 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1238 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1245 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1246 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1247 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1249 ? SPIRV::OpenCLExtInst::fmin
1250 : SPIRV::OpenCLExtInst::fmax;
1258 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1259 Number == SPIRV::OpenCLExtInst::fma) {
1267 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1270 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1278 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1279 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1288 if (ST.isKernel() ||
1289 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1295 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1299 AddNoNan = AddNoNan && ArgTest &
fcNan;
1300 AddNoInf = AddNoInf && ArgTest &
fcInf;
1318 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1322 std::tie(CompareRegister, RelationType) =
1328 Call->Arguments.end());
1329 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1358 Call->ReturnType, GR);
1366 SPIRV::lookupGroupBuiltin(Builtin->
name());
1369 if (
Call->isSpirvOp()) {
1372 if (GroupBuiltin->
Opcode ==
1373 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1374 Call->Arguments.size() > 4)
1383 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1385 "Group Operation parameter must be an integer constant");
1386 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1393 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1406 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1407 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1411 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1420 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1432 const bool HasBoolReturnTy =
1437 if (HasBoolReturnTy)
1438 std::tie(GroupResultRegister, GroupResultType) =
1442 ? SPIRV::Scope::Subgroup
1443 : SPIRV::Scope::Workgroup;
1447 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1448 Call->Arguments.size() > 2) {
1456 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1458 unsigned VecLen =
Call->Arguments.size() - 1;
1467 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1468 MIB.addUse(
Call->Arguments[i]);
1477 .
addDef(GroupResultRegister)
1483 if (
Call->Arguments.size() > 0) {
1484 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1489 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1490 MIB.addUse(
Call->Arguments[i]);
1494 if (HasBoolReturnTy)
1496 Call->ReturnType, GR);
1507 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1509 if (IntelSubgroups->
IsMedia &&
1510 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1511 std::string DiagMsg = std::string(Builtin->
name()) +
1512 ": the builtin requires the following SPIR-V "
1513 "extension: SPV_INTEL_media_block_io";
1515 }
else if (!IntelSubgroups->
IsMedia &&
1516 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1517 std::string DiagMsg = std::string(Builtin->
name()) +
1518 ": the builtin requires the following SPIR-V "
1519 "extension: SPV_INTEL_subgroups";
1524 if (
Call->isSpirvOp()) {
1525 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1526 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1527 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1533 if (IntelSubgroups->
IsBlock) {
1536 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1542 case SPIRV::OpSubgroupBlockReadINTEL:
1543 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1545 case SPIRV::OpSubgroupBlockWriteINTEL:
1546 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1569 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1580 if (!ST->canUseExtension(
1581 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1582 std::string DiagMsg = std::string(Builtin->
name()) +
1583 ": the builtin requires the following SPIR-V "
1584 "extension: SPV_KHR_uniform_group_instructions";
1588 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1598 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1600 "expect a constant group operation for a uniform group instruction",
1603 if (!ConstOperand.
isCImm())
1613 MIB.addUse(ValueReg);
1624 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1625 std::string DiagMsg = std::string(Builtin->
name()) +
1626 ": the builtin requires the following SPIR-V "
1627 "extension: SPV_KHR_shader_clock";
1633 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1640 SPIRV::Scope::Scope ScopeArg =
1642 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1643 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1644 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1685 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1688 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1699 bool IsConstantIndex =
1700 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1704 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1706 if (PointerSize != ResultWidth) {
1708 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1710 MIRBuilder.
getMF());
1711 ToTruncate = DefaultReg;
1715 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1724 if (!IsConstantIndex || PointerSize != ResultWidth) {
1733 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1736 if (!IsConstantIndex) {
1737 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1744 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1759 if (PointerSize != ResultWidth) {
1762 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1764 MIRBuilder.
getMF());
1767 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1769 ToTruncate = SelectionResult;
1771 ToTruncate = Extracted;
1775 if (PointerSize != ResultWidth)
1785 SPIRV::BuiltIn::BuiltIn
Value =
1786 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1788 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1794 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1801 LLType,
Call->ReturnRegister);
1810 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1813 case SPIRV::OpStore:
1815 case SPIRV::OpAtomicLoad:
1817 case SPIRV::OpAtomicStore:
1819 case SPIRV::OpAtomicCompareExchange:
1820 case SPIRV::OpAtomicCompareExchangeWeak:
1823 case SPIRV::OpAtomicIAdd:
1824 case SPIRV::OpAtomicISub:
1825 case SPIRV::OpAtomicOr:
1826 case SPIRV::OpAtomicXor:
1827 case SPIRV::OpAtomicAnd:
1828 case SPIRV::OpAtomicExchange:
1829 case SPIRV::OpAtomicSMax:
1830 case SPIRV::OpAtomicSMin:
1831 case SPIRV::OpAtomicUMax:
1832 case SPIRV::OpAtomicUMin:
1834 case SPIRV::OpMemoryBarrier:
1836 case SPIRV::OpAtomicFlagTestAndSet:
1837 case SPIRV::OpAtomicFlagClear:
1840 if (
Call->isSpirvOp())
1852 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1855 case SPIRV::OpAtomicFAddEXT:
1856 case SPIRV::OpAtomicFMinEXT:
1857 case SPIRV::OpAtomicFMaxEXT:
1870 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1881 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1883 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1884 SPIRV::StorageClass::StorageClass ResSC =
1895 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1906 if (
Call->isSpirvOp())
1911 SPIRV::OpTypeVector;
1913 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1914 bool IsSwapReq =
false;
1919 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1923 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
1933 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1934 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1936 if (
Call->BuiltinName ==
"dot") {
1937 if (IsFirstSigned && IsSecondSigned)
1939 else if (!IsFirstSigned && !IsSecondSigned)
1942 OC = SPIRV::OpSUDot;
1946 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1947 if (IsFirstSigned && IsSecondSigned)
1948 OC = SPIRV::OpSDotAccSat;
1949 else if (!IsFirstSigned && !IsSecondSigned)
1950 OC = SPIRV::OpUDotAccSat;
1952 OC = SPIRV::OpSUDotAccSat;
1968 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1971 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1977 if (!IsVec && OC != SPIRV::OpFMulS)
1978 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
1987 SPIRV::BuiltIn::BuiltIn
Value =
1988 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1991 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
1995 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
1996 false, std::nullopt);
2032 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2039 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2041 "overflow builtins");
2045 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2047 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
2049 case SPIRV::OpIAddCarryS:
2050 Opcode = SPIRV::OpIAddCarryV;
2052 case SPIRV::OpISubBorrowS:
2053 Opcode = SPIRV::OpISubBorrowV;
2058 RetType, MIRBuilder, GR);
2079 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2080 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2081 "Expected OpUMulExtended or OpSMulExtended");
2084 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2096 RetType =
Call->ReturnType;
2099 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2101 "multiplication builtins");
2104 "extended multiplication builtins");
2109 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2114 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2116 if (OpType1 != Member0Type)
2143 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2157 SPIRV::BuiltIn::BuiltIn
Value =
2158 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2159 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2160 Value == SPIRV::BuiltIn::NumWorkgroups ||
2161 Value == SPIRV::BuiltIn::WorkgroupSize ||
2162 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2172 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2176 unsigned NumExpectedRetComponents =
2183 if (NumExpectedRetComponents != NumActualRetComponents) {
2184 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2185 ?
Call->ReturnType->getOperand(1).getImm()
2192 IntTy, NumActualRetComponents, MIRBuilder,
true);
2197 bool UseQuerySize = IsDimBuf || IsMultisampled;
2199 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2206 if (NumExpectedRetComponents == NumActualRetComponents)
2208 if (NumExpectedRetComponents == 1) {
2210 unsigned ExtractedComposite =
2211 Component == 3 ? NumActualRetComponents - 1 : Component;
2212 assert(ExtractedComposite < NumActualRetComponents &&
2213 "Invalid composite index!");
2216 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2219 if (TypeReg != NewTypeReg)
2220 TypeReg = NewTypeReg;
2224 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2228 .
addImm(ExtractedComposite);
2234 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2239 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2240 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2248 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2249 "Image samples query result must be of int type!");
2254 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2257 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2259 (void)ImageDimensionality;
2262 case SPIRV::OpImageQuerySamples:
2263 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2264 "Image must be of 2D dimensionality");
2266 case SPIRV::OpImageQueryLevels:
2267 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2268 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2269 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2270 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2271 "Image must be of 1D/2D/3D/Cube dimensionality");
2283static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2285 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2286 case SPIRV::CLK_ADDRESS_CLAMP:
2287 return SPIRV::SamplerAddressingMode::Clamp;
2288 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2289 return SPIRV::SamplerAddressingMode::ClampToEdge;
2290 case SPIRV::CLK_ADDRESS_REPEAT:
2291 return SPIRV::SamplerAddressingMode::Repeat;
2292 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2293 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2294 case SPIRV::CLK_ADDRESS_NONE:
2295 return SPIRV::SamplerAddressingMode::None;
2302 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2305static SPIRV::SamplerFilterMode::SamplerFilterMode
2307 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2308 return SPIRV::SamplerFilterMode::Linear;
2309 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2310 return SPIRV::SamplerFilterMode::Nearest;
2311 return SPIRV::SamplerFilterMode::Nearest;
2318 if (
Call->isSpirvOp())
2325 if (HasOclSampler) {
2350 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2357 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2362 .
addImm(SPIRV::ImageOperand::Lod)
2364 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2370 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2375 .
addImm(SPIRV::ImageOperand::Lod)
2378 }
else if (HasMsaa) {
2384 .
addImm(SPIRV::ImageOperand::Sample)
2399 if (
Call->isSpirvOp())
2414 if (
Call->Builtin->name().contains_insensitive(
2415 "__translate_sampler_initializer")) {
2423 }
else if (
Call->Builtin->name().contains_insensitive(
2424 "__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();
2779 IsSet ? TypeReg :
Register(0), ImmArgs);
2804 const unsigned NumCallArgs =
Call->Arguments.size();
2805 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2806 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2809 bool HasSRetArg = RetTy->
isVoidTy();
2811 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2812 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2813 const unsigned MaxNDRangeArgs = 3;
2814 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2816 const unsigned GlobalWorkSizeArgIdx =
2817 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2818 const unsigned LocalWorkSizeArgIdx =
2819 (NumNDRangeArgs == 1)
2821 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2822 const unsigned GlobalWorkOffsetArgIdx =
2823 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2828 assert(AddressModelBits == 64 || AddressModelBits == 32);
2832 unsigned Dimension = 0;
2833 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2834 assert(Dimension <= 3 && Dimension >= 1);
2841 if (Dimension == 1) {
2844 "Expected scalar integer type");
2846 if (NumNDRangeArgs < MaxNDRangeArgs)
2853 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2855 if (NumNDRangeArgs < MaxNDRangeArgs) {
2861 SpvFieldTy, *ST.getInstrInfo());
2867 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2868 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2876 "Only pointer types are supported for loading values");
2890 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2891 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2892 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2895 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2900 .
addUse(GlobalWorkOffset);
2917 .
addUse(GlobalWorkOffset);
2949 bool IsSpirvOp =
Call->isSpirvOp();
2950 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
2951 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
2953 const unsigned NumArgs =
Call->Arguments.size();
2954 const unsigned BaseArgIdx = 0;
2955 const unsigned IncorrectIdx = NumArgs + 1;
2957 const unsigned QueueIdx = BaseArgIdx;
2958 const unsigned FlagsIdx = BaseArgIdx + 1;
2959 const unsigned NDRangeIdx = BaseArgIdx + 2;
2960 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
2961 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
2962 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
2963 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
2964 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
2965 const unsigned LocalSizeNumElemIdx =
2966 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2967 const unsigned LocalSizeElemPtrIdx =
2968 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2970 [[maybe_unused]]
const unsigned LastArgIdx =
2971 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
2972 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
2978 auto BuildDeviceEventNullPtr = [&]() {
2982 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
2990 auto IsNullEvent = [&](
Register R) {
2992 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
2993 Def->getOperand(1).getCImm()->isZero();
2996 NumEventsReg =
Call->Arguments[NumEventsIdx];
2997 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
2998 RetEventReg =
Call->Arguments[RetEventIdx];
2999 if (IsNullEvent(WaitEventsReg))
3000 WaitEventsReg = BuildDeviceEventNullPtr();
3001 if (IsNullEvent(RetEventReg))
3002 RetEventReg = BuildDeviceEventNullPtr();
3005 Register NullPtr = BuildDeviceEventNullPtr();
3006 WaitEventsReg = NullPtr;
3007 RetEventReg = NullPtr;
3028 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3035 .
addUse(BlockLiteralReg);
3045 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3049 ConstOp.
isCImm() &&
"Expected constant immediate");
3052 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3054 for (
unsigned i = 0; i < NumElem; ++i) {
3060 .
addUse(LocalSizeArrayReg)
3068 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3081 for (
auto &LocalSize : LocalSizes)
3093 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3096 case SPIRV::OpRetainEvent:
3097 case SPIRV::OpReleaseEvent:
3099 case SPIRV::OpCreateUserEvent:
3100 case SPIRV::OpGetDefaultQueue:
3104 case SPIRV::OpIsValidEvent:
3109 case SPIRV::OpSetUserEventStatus:
3113 case SPIRV::OpCaptureEventProfilingInfo:
3118 case SPIRV::OpBuildNDRange:
3120 case SPIRV::OpEnqueueKernel:
3133 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3135 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3137 if (
Call->isSpirvOp())
3144 case SPIRV::OpGroupAsyncCopy: {
3146 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3150 unsigned NumArgs =
Call->Arguments.size();
3160 ?
Call->Arguments[3]
3168 case SPIRV::OpGroupWaitEvents:
3184 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3186 if (!Builtin &&
Call->isSpirvOp()) {
3189 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3194 assert(Builtin &&
"Conversion builtin not found.");
3197 SPIRV::Decoration::SaturatedConversion, {});
3200 bool AnyTypeIsFloat =
3207 if (AnyTypeIsFloat) {
3209 SPIRV::Decoration::FPRoundingMode,
3210 {(unsigned)Builtin->RoundingMode});
3214 std::string NeedExtMsg;
3215 bool IsRightComponentsNumber =
true;
3216 unsigned Opcode = SPIRV::OpNop;
3219 bool IsSourceSigned =
3225 : SPIRV::OpSatConvertSToU;
3227 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3229 SPIRV::OpTypeFloat)) {
3233 &MIRBuilder.
getMF().getSubtarget());
3234 if (!ST->canUseExtension(
3235 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3236 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3237 IsRightComponentsNumber =
3240 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3242 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3246 SPIRV::OpTypeFloat)) {
3252 &MIRBuilder.
getMF().getSubtarget());
3253 if (!ST->canUseExtension(
3254 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3255 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3256 IsRightComponentsNumber =
3259 Opcode = SPIRV::OpConvertFToBF16INTEL;
3262 : SPIRV::OpConvertFToU;
3265 SPIRV::OpTypeFloat)) {
3268 &MIRBuilder.
getMF().getSubtarget());
3269 if (!ST->canUseExtension(
3270 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3271 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3272 IsRightComponentsNumber =
3275 Opcode = SPIRV::OpRoundFToTF32INTEL;
3278 Opcode = SPIRV::OpFConvert;
3283 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3284 if (!NeedExtMsg.empty()) {
3285 std::string DiagMsg = std::string(BuiltinName) +
3286 ": the builtin requires the following SPIR-V "
3291 if (!IsRightComponentsNumber) {
3292 std::string DiagMsg =
3293 std::string(BuiltinName) +
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))
3323 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3337 const auto *Builtin =
Call->Builtin;
3338 auto *MRI = MIRBuilder.
getMRI();
3340 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3346 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3347 DestReg = MRI->createGenericVirtualRegister(PtrTy);
3348 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3351 MIB.addDef(DestReg);
3354 MIB.addDef(
Call->ReturnRegister);
3357 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3360 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3361 DefMI->getOperand(1).isCImm()) {
3368 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3383 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3384 bool IsLoad = Opcode == SPIRV::OpLoad;
3388 MIB.addDef(
Call->ReturnRegister);
3396 MIB.addUse(
Call->Arguments[1]);
3398 unsigned NumArgs =
Call->Arguments.size();
3399 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3401 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3414std::tuple<int, unsigned, unsigned>
3416 SPIRV::InstructionSet::InstructionSet Set) {
3419 std::unique_ptr<const IncomingCall>
Call =
3422 return std::make_tuple(-1, 0, 0);
3424 switch (
Call->Builtin->Group) {
3425 case SPIRV::Relational:
3427 case SPIRV::Barrier:
3428 case SPIRV::CastToPtr:
3429 case SPIRV::ImageMiscQuery:
3430 case SPIRV::SpecConstant:
3431 case SPIRV::Enqueue:
3432 case SPIRV::AsyncCopy:
3433 case SPIRV::LoadStore:
3434 case SPIRV::CoopMatr:
3435 case SPIRV::Arithmetic:
3436 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3437 Call->Builtin->Set))
3438 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3440 case SPIRV::Extended:
3441 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3442 Call->Builtin->Set))
3443 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3445 case SPIRV::VectorLoadStore:
3446 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3447 Call->Builtin->name(),
Call->Builtin->Set))
3448 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3451 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3452 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3454 case SPIRV::AtomicFloating:
3456 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3457 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3459 case SPIRV::IntelSubgroups:
3461 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3462 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3464 case SPIRV::GroupUniform:
3465 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3466 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3468 case SPIRV::IntegerDot:
3470 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3471 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3473 case SPIRV::WriteImage:
3474 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3476 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3477 case SPIRV::Construct:
3478 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3480 case SPIRV::KernelClock:
3481 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3483 return std::make_tuple(-1, 0, 0);
3485 return std::make_tuple(-1, 0, 0);
3489 SPIRV::InstructionSet::InstructionSet Set,
3494 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3498 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3499 std::unique_ptr<const IncomingCall>
Call =
3504 return std::nullopt;
3509 if (Args.size() <
Call->Builtin->MinNumArgs) {
3510 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3511 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3512 <<
", got " << Args.size()
3513 <<
"; treating as a normal function\n");
3514 return std::nullopt;
3516 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3517 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3518 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3519 <<
", got " << Args.size()
3520 <<
"; treating as a normal function\n");
3521 return std::nullopt;
3525 switch (
Call->Builtin->Group) {
3526 case SPIRV::Extended:
3528 case SPIRV::Relational:
3532 case SPIRV::Variable:
3536 case SPIRV::AtomicFloating:
3538 case SPIRV::Barrier:
3540 case SPIRV::CastToPtr:
3543 case SPIRV::IntegerDot:
3547 case SPIRV::ICarryBorrow:
3549 case SPIRV::MulExtended:
3551 case SPIRV::Arithmetic:
3553 case SPIRV::GetQuery:
3555 case SPIRV::ImageSizeQuery:
3557 case SPIRV::ImageMiscQuery:
3559 case SPIRV::ReadImage:
3561 case SPIRV::WriteImage:
3563 case SPIRV::SampleImage:
3567 case SPIRV::Construct:
3569 case SPIRV::SpecConstant:
3571 case SPIRV::Enqueue:
3573 case SPIRV::AsyncCopy:
3575 case SPIRV::Convert:
3577 case SPIRV::VectorLoadStore:
3579 case SPIRV::LoadStore:
3581 case SPIRV::IntelSubgroups:
3583 case SPIRV::GroupUniform:
3585 case SPIRV::KernelClock:
3587 case SPIRV::CoopMatr:
3589 case SPIRV::ExtendedBitOps:
3591 case SPIRV::BindlessINTEL:
3593 case SPIRV::TernaryBitwiseINTEL:
3595 case SPIRV::Block2DLoadStore:
3599 case SPIRV::PredicatedLoadStore:
3601 case SPIRV::BlockingPipes:
3603 case SPIRV::ArbitraryPrecisionFixedPoint:
3605 case SPIRV::ImageChannelDataTypes:
3607 case SPIRV::ArbitraryFloatingPoint:
3618 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3619 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3636 unsigned VecElts = 0;
3647 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3659 auto Pos1 = DemangledCall.
find(
'(');
3662 auto Pos2 = DemangledCall.
find(
')');
3665 DemangledCall.
slice(Pos1 + 1, Pos2)
3666 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3674 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3676 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3685#define GET_BuiltinTypes_DECL
3686#define GET_BuiltinTypes_IMPL
3693#define GET_OpenCLTypes_DECL
3694#define GET_OpenCLTypes_IMPL
3696#include "SPIRVGenTables.inc"
3704 if (Name.starts_with(
"void"))
3706 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3708 else if (Name.starts_with(
"bfloat"))
3710 else if (Name.starts_with(
"float"))
3712 else if (Name.starts_with(
"half"))
3714 else if (Name.starts_with(
"double"))
3727 unsigned Opcode = TypeRecord->
Opcode;
3742 "Invalid number of parameters for SPIR-V pipe builtin!");
3745 SPIRV::AccessQualifier::AccessQualifier(
3753 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3755 "SPIR-V coop matrices builtin type must have a type parameter!");
3758 SPIRV::AccessQualifier::ReadWrite,
true);
3761 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3770 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3779 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3786 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3787 assert(ParamEType->getNumTypeParameters() == 1 &&
3788 "Inline SPIR-V integral constant builtin must have a type "
3790 assert(ParamEType->getNumIntParameters() == 1 &&
3791 "Inline SPIR-V integral constant builtin must have a "
3794 auto OperandValue = ParamEType->getIntParameter(0);
3795 auto *OperandType = ParamEType->getTypeParameter(0);
3798 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3801 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3803 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3804 assert(ParamEType->getNumTypeParameters() == 0 &&
3805 "Inline SPIR-V literal builtin does not take type "
3807 assert(ParamEType->getNumIntParameters() == 1 &&
3808 "Inline SPIR-V literal builtin must have an integer "
3811 auto OperandValue = ParamEType->getIntParameter(0);
3818 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3830 "Vulkan buffers have exactly one type for the type of the buffer.");
3832 "Vulkan buffer have 2 integer parameters: storage class and is "
3836 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
3847 "Vulkan push constants have exactly one type as argument.");
3861 StringRef NameWithParameters = TypeName;
3868 SPIRV::lookupOpenCLType(NameWithParameters);
3871 NameWithParameters);
3872 NameWithParameters =
3880 "Unknown builtin opaque type!");
3884 if (!NameWithParameters.
contains(
'_'))
3888 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
3892 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
3893 if (HasTypeParameter)
3896 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
3897 unsigned IntParameter = 0;
3898 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
3901 "Invalid format of SPIR-V builtin parameter literal!");
3905 NameWithParameters.
substr(0, BaseNameLength),
3906 TypeParameters, IntParameters);
3911 SPIRV::AccessQualifier::AccessQualifier AccessQual,
3932 if (Name ==
"spirv.Type") {
3934 }
else if (Name ==
"spirv.VulkanBuffer") {
3936 }
else if (Name ==
"spirv.Padding") {
3938 }
else if (Name ==
"spirv.PushConstant") {
3940 }
else if (Name ==
"spirv.Layout") {
3954 switch (TypeRecord->
Opcode) {
3955 case SPIRV::OpTypeImage:
3958 case SPIRV::OpTypePipe:
3961 case SPIRV::OpTypeDeviceEvent:
3964 case SPIRV::OpTypeSampler:
3967 case SPIRV::OpTypeSampledImage:
3970 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 * 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.
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.
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...
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 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)
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 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
StringTable::Offset SpirvTypeLiteral
InstructionSet::InstructionSet Set
FPRoundingMode::FPRoundingMode RoundingMode