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
87#define GET_GroupBuiltins_DECL
88#define GET_GroupBuiltins_IMPL
98#define GET_IntelSubgroupsBuiltins_DECL
99#define GET_IntelSubgroupsBuiltins_IMPL
106#define GET_AtomicFloatingBuiltins_DECL
107#define GET_AtomicFloatingBuiltins_IMPL
114#define GET_GroupUniformBuiltins_DECL
115#define GET_GroupUniformBuiltins_IMPL
119 InstructionSet::InstructionSet
Set;
124#define GET_GetBuiltins_DECL
125#define GET_GetBuiltins_IMPL
129 InstructionSet::InstructionSet
Set;
133#define GET_ImageQueryBuiltins_DECL
134#define GET_ImageQueryBuiltins_IMPL
142#define GET_IntegerDotProductBuiltins_DECL
143#define GET_IntegerDotProductBuiltins_IMPL
147 InstructionSet::InstructionSet
Set;
158 InstructionSet::InstructionSet
Set;
166#define GET_ConvertBuiltins_DECL
167#define GET_ConvertBuiltins_IMPL
169using namespace InstructionSet;
170#define GET_VectorLoadStoreBuiltins_DECL
171#define GET_VectorLoadStoreBuiltins_IMPL
173#define GET_CLMemoryScope_DECL
174#define GET_CLSamplerAddressingMode_DECL
175#define GET_CLMemoryFenceFlags_DECL
176#define GET_ExtendedBuiltins_DECL
177#include "SPIRVGenTables.inc"
181 return getDemangledBuiltinStr(
Name);
194 StringRef PassPrefix =
"(anonymous namespace)::";
196 std::string BuiltinName = DemangledCall.
str();
201 std::size_t Pos = BuiltinName.find(
">(");
202 if (Pos != std::string::npos) {
203 BuiltinName = BuiltinName.substr(0, BuiltinName.rfind(
'<', Pos));
205 Pos = BuiltinName.find(
'(');
206 if (Pos != std::string::npos)
207 BuiltinName = BuiltinName.substr(0, Pos);
209 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(
' ') + 1);
213 if (BuiltinName.find(PassPrefix) == 0)
214 BuiltinName = BuiltinName.substr(PassPrefix.
size());
215 else if (BuiltinName.find(SpvPrefix) == 0)
216 BuiltinName = BuiltinName.substr(SpvPrefix.
size());
219 if (BuiltinName.rfind(
"__spirv_ocl_", 0) == 0)
220 BuiltinName = BuiltinName.substr(12);
246 static const std::regex SpvWithR(
247 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"
249 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"
250 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
251 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
253 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");
255 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
256 std::ssub_match SubMatch;
257 if (DecorationId && Match.size() > 3) {
262 BuiltinName = SubMatch.str();
279static std::unique_ptr<const SPIRV::IncomingCall>
281 SPIRV::InstructionSet::InstructionSet Set,
288 DemangledCall.
slice(DemangledCall.
find(
'(') + 1, DemangledCall.
find(
')'));
289 BuiltinArgs.
split(BuiltinArgumentTypes,
',', -1,
false);
294 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))
295 return std::make_unique<SPIRV::IncomingCall>(
296 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
301 if (BuiltinArgumentTypes.
size() >= 1) {
302 char FirstArgumentType = BuiltinArgumentTypes[0][0];
309 switch (FirstArgumentType) {
312 if (Set == SPIRV::InstructionSet::OpenCL_std)
314 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
323 if (Set == SPIRV::InstructionSet::OpenCL_std)
325 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
333 if (Set == SPIRV::InstructionSet::OpenCL_std ||
334 Set == SPIRV::InstructionSet::GLSL_std_450)
341 if (!Prefix.empty() &&
342 (Builtin = SPIRV::lookupBuiltin((Prefix + BuiltinName).str(), Set)))
343 return std::make_unique<SPIRV::IncomingCall>(
344 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
346 if (!Suffix.
empty() &&
347 (Builtin = SPIRV::lookupBuiltin((BuiltinName + Suffix).str(), Set)))
348 return std::make_unique<SPIRV::IncomingCall>(
349 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
361 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
362 MI->getOperand(1).isReg());
363 Register BitcastReg =
MI->getOperand(1).getReg();
365 assert(BitcastMI &&
"Definition for source reg not found.");
366 if (BitcastMI->
getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
381 Register ValueReg =
MI->getOperand(0).getReg();
387 assert(Ty &&
"Type is expected");
399 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
400 return MI->getOperand(1).getGlobal()->getValueType();
402 "Blocks in OpenCL C must be traceable to allocation site");
414static std::tuple<Register, SPIRVTypeInst>
420 if (ResultType->
getOpcode() == SPIRV::OpTypeVector) {
435 return std::make_tuple(ResultRegister, BoolType);
445 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {
456 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
466 if (!DestinationReg.isValid())
471 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
472 return DestinationReg;
481 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
482 SPIRV::LinkageType::Import}) {
490 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
496 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
503 return LoadedRegister;
514static SPIRV::MemorySemantics::MemorySemantics
517 case std::memory_order_relaxed:
518 return SPIRV::MemorySemantics::None;
519 case std::memory_order_acquire:
520 return SPIRV::MemorySemantics::Acquire;
521 case std::memory_order_release:
522 return SPIRV::MemorySemantics::Release;
523 case std::memory_order_acq_rel:
524 return SPIRV::MemorySemantics::AcquireRelease;
525 case std::memory_order_seq_cst:
526 return SPIRV::MemorySemantics::SequentiallyConsistent;
534 case SPIRV::CLMemoryScope::memory_scope_work_item:
535 return SPIRV::Scope::Invocation;
536 case SPIRV::CLMemoryScope::memory_scope_work_group:
537 return SPIRV::Scope::Workgroup;
538 case SPIRV::CLMemoryScope::memory_scope_device:
539 return SPIRV::Scope::Device;
540 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
541 return SPIRV::Scope::CrossDevice;
542 case SPIRV::CLMemoryScope::memory_scope_sub_group:
543 return SPIRV::Scope::Subgroup;
556 SPIRV::Scope::Scope Scope,
560 if (CLScopeRegister.
isValid()) {
562 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(CLScopeRegister, MRI));
565 if (CLScope ==
static_cast<unsigned>(Scope)) {
566 MRI->
setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
567 return CLScopeRegister;
579 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
583 Register PtrRegister,
unsigned &Semantics,
586 if (SemanticsRegister.
isValid()) {
588 std::memory_order Order =
589 static_cast<std::memory_order
>(
getIConstVal(SemanticsRegister, MRI));
593 if (
static_cast<unsigned>(Order) == Semantics) {
594 MRI->
setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);
595 return SemanticsRegister;
608 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
609 for (
unsigned i = 0; i < Sz; ++i)
610 MIB.addUse(
Call->Arguments[i]);
619 if (
Call->isSpirvOp())
623 "Need 2 arguments for atomic init translation");
635 if (
Call->isSpirvOp())
643 Call->Arguments.size() > 1
647 if (
Call->Arguments.size() > 2) {
649 MemSemanticsReg =
Call->Arguments[2];
652 SPIRV::MemorySemantics::SequentiallyConsistent |
670 if (
Call->isSpirvOp())
678 SPIRV::MemorySemantics::SequentiallyConsistent |
693 if (
Call->isSpirvOp())
697 bool IsCmpxchg =
Call->Builtin->name().contains(
"cmpxchg");
714 assert((SpvObjectPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR ||
716 "SPIRV type is expected");
717 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
725 ? SPIRV::MemorySemantics::None
726 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
729 ? SPIRV::MemorySemantics::None
730 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
731 if (
Call->Arguments.size() >= 4) {
733 "Need 5+ args for explicit atomic cmpxchg");
740 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
741 MemSemEqualReg =
Call->Arguments[3];
742 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
743 MemSemUnequalReg =
Call->Arguments[4];
747 if (!MemSemUnequalReg.
isValid())
751 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
752 if (
Call->Arguments.size() >= 6) {
754 "Extra args for explicit atomic cmpxchg");
755 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
758 if (ClScope ==
static_cast<unsigned>(Scope))
759 ScopeReg =
Call->Arguments[5];
765 IsCmpxchg ? ExpectedArg
769 :
Call->ReturnRegister;
794 if (
Call->isSpirvOp())
803 "Too many args for explicit atomic RMW");
804 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
805 MIRBuilder, GR, MRI);
808 unsigned Semantics = SPIRV::MemorySemantics::None;
812 Semantics, MIRBuilder, GR);
816 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
817 if (Opcode == SPIRV::OpAtomicIAdd) {
818 Opcode = SPIRV::OpAtomicFAddEXT;
819 }
else if (Opcode == SPIRV::OpAtomicISub) {
822 Opcode = SPIRV::OpAtomicFAddEXT;
833 ValueReg = NegValueReg;
852 "Wrong number of atomic floating-type builtin");
872 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
874 if (
Call->isSpirvOp())
880 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
884 Semantics, MIRBuilder, GR);
886 assert((Opcode != SPIRV::OpAtomicFlagClear ||
887 (Semantics != SPIRV::MemorySemantics::Acquire &&
888 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
889 "Invalid memory order argument!");
894 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);
912 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
913 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
914 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
915 std::string DiagMsg = std::string(Builtin->
name()) +
916 ": the builtin requires the following SPIR-V "
917 "extension: SPV_INTEL_split_barrier";
921 if (
Call->isSpirvOp())
926 unsigned MemSemantics = SPIRV::MemorySemantics::None;
928 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
929 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
931 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
932 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
934 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
935 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
937 if (Opcode == SPIRV::OpMemoryBarrier)
941 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
942 MemSemantics |= SPIRV::MemorySemantics::Release;
943 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
944 MemSemantics |= SPIRV::MemorySemantics::Acquire;
946 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
949 MemFlags == MemSemantics
953 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
954 SPIRV::Scope::Scope MemScope = Scope;
955 if (
Call->Arguments.size() >= 2) {
957 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
958 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
959 "Extra args for explicitly scoped barrier");
960 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
961 :
Call->Arguments[1];
962 SPIRV::CLMemoryScope CLScope =
963 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
965 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
966 (Opcode == SPIRV::OpMemoryBarrier))
968 if (CLScope ==
static_cast<unsigned>(Scope))
969 ScopeReg =
Call->Arguments[1];
976 if (Opcode != SPIRV::OpMemoryBarrier)
978 MIB.
addUse(MemSemanticsReg);
990 if ((Opcode == SPIRV::OpBitFieldInsert ||
991 Opcode == SPIRV::OpBitFieldSExtract ||
992 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
993 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
994 std::string DiagMsg = std::string(Builtin->
name()) +
995 ": the builtin requires the following SPIR-V "
996 "extension: SPV_KHR_bit_instructions";
1001 if (
Call->isSpirvOp())
1008 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1020 if (
Call->isSpirvOp())
1037 if (
Call->isSpirvOp())
1044 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1054 if (
Call->isSpirvOp())
1061 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1073 if (
Call->isSpirvOp())
1079 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1089 case SPIRV::OpCommitReadPipe:
1090 case SPIRV::OpCommitWritePipe:
1092 case SPIRV::OpGroupCommitReadPipe:
1093 case SPIRV::OpGroupCommitWritePipe:
1094 case SPIRV::OpGroupReserveReadPipePackets:
1095 case SPIRV::OpGroupReserveWritePipePackets: {
1099 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1103 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1104 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1108 MIB.
addUse(ScopeConstReg);
1109 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1122 case SPIRV::Dim::DIM_1D:
1123 case SPIRV::Dim::DIM_Buffer:
1125 case SPIRV::Dim::DIM_2D:
1126 case SPIRV::Dim::DIM_Cube:
1127 case SPIRV::Dim::DIM_Rect:
1129 case SPIRV::Dim::DIM_3D:
1142 return arrayed ? numComps + 1 : numComps;
1146 switch (BuiltinNumber) {
1147 case SPIRV::OpenCLExtInst::s_min:
1148 case SPIRV::OpenCLExtInst::u_min:
1149 case SPIRV::OpenCLExtInst::s_max:
1150 case SPIRV::OpenCLExtInst::u_max:
1151 case SPIRV::OpenCLExtInst::fmax:
1152 case SPIRV::OpenCLExtInst::fmin:
1153 case SPIRV::OpenCLExtInst::fmax_common:
1154 case SPIRV::OpenCLExtInst::fmin_common:
1155 case SPIRV::OpenCLExtInst::s_clamp:
1156 case SPIRV::OpenCLExtInst::fclamp:
1157 case SPIRV::OpenCLExtInst::u_clamp:
1158 case SPIRV::OpenCLExtInst::mix:
1159 case SPIRV::OpenCLExtInst::step:
1160 case SPIRV::OpenCLExtInst::smoothstep:
1161 case SPIRV::OpenCLExtInst::ldexp:
1162 case SPIRV::OpenCLExtInst::pown:
1163 case SPIRV::OpenCLExtInst::rootn:
1180 unsigned ResultElementCount =
1182 bool MayNeedPromotionToVec =
1185 if (!MayNeedPromotionToVec)
1186 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1193 ArgumentType !=
Call->ReturnType) {
1195 ArgumentType, ResultElementCount, MIRBuilder,
true);
1198 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1201 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1215 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1222 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1223 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1224 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1226 ? SPIRV::OpenCLExtInst::fmin
1227 : SPIRV::OpenCLExtInst::fmax;
1232 if (
Number == SPIRV::OpenCLExtInst::prefetch &&
Call->Arguments.size() >= 2) {
1235 if (PtrTy && PtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR) {
1239 assert(SizeTy &&
"Expected a type for the number of elements");
1245 if (ElemBytes > 1) {
1259 MIRBuilder.
buildInstr(SPIRV::OpUntypedPrefetchKHR)
1271 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1272 Number == SPIRV::OpenCLExtInst::fma) {
1280 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1283 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1291 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1292 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1301 if (ST.isKernel() ||
1302 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1308 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1312 AddNoNan = AddNoNan && ArgTest &
fcNan;
1313 AddNoInf = AddNoInf && ArgTest &
fcInf;
1331 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1335 std::tie(CompareRegister, RelationType) =
1341 Call->Arguments.end());
1342 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1371 Call->ReturnType, GR);
1379 SPIRV::lookupGroupBuiltin(Builtin->
name());
1382 if (
Call->isSpirvOp()) {
1385 if (GroupBuiltin->
Opcode ==
1386 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1387 Call->Arguments.size() > 4)
1396 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1398 "Group Operation parameter must be an integer constant");
1399 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1406 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1419 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1420 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1424 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1433 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1445 const bool HasBoolReturnTy =
1450 if (HasBoolReturnTy)
1451 std::tie(GroupResultRegister, GroupResultType) =
1455 ? SPIRV::Scope::Subgroup
1456 : SPIRV::Scope::Workgroup;
1460 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1461 Call->Arguments.size() > 2) {
1469 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1471 unsigned VecLen =
Call->Arguments.size() - 1;
1480 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1481 MIB.addUse(
Call->Arguments[i]);
1490 .
addDef(GroupResultRegister)
1496 if (
Call->Arguments.size() > 0) {
1497 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1502 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1503 MIB.addUse(
Call->Arguments[i]);
1507 if (HasBoolReturnTy)
1509 Call->ReturnType, GR);
1520 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1522 if (IntelSubgroups->
IsMedia &&
1523 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1524 std::string DiagMsg = std::string(Builtin->
name()) +
1525 ": the builtin requires the following SPIR-V "
1526 "extension: SPV_INTEL_media_block_io";
1528 }
else if (!IntelSubgroups->
IsMedia &&
1529 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1530 std::string DiagMsg = std::string(Builtin->
name()) +
1531 ": the builtin requires the following SPIR-V "
1532 "extension: SPV_INTEL_subgroups";
1537 if (
Call->isSpirvOp()) {
1538 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1539 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1540 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1546 if (IntelSubgroups->
IsBlock) {
1549 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1555 case SPIRV::OpSubgroupBlockReadINTEL:
1556 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1558 case SPIRV::OpSubgroupBlockWriteINTEL:
1559 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1582 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1593 if (!ST->canUseExtension(
1594 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1595 std::string DiagMsg = std::string(Builtin->
name()) +
1596 ": the builtin requires the following SPIR-V "
1597 "extension: SPV_KHR_uniform_group_instructions";
1601 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1611 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1613 "expect a constant group operation for a uniform group instruction",
1616 if (!ConstOperand.
isCImm())
1626 MIB.addUse(ValueReg);
1637 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1638 std::string DiagMsg = std::string(Builtin->
name()) +
1639 ": the builtin requires the following SPIR-V "
1640 "extension: SPV_KHR_shader_clock";
1646 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1653 SPIRV::Scope::Scope ScopeArg =
1655 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1656 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1657 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1698 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1701 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1712 bool IsConstantIndex =
1713 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1717 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1719 if (PointerSize != ResultWidth) {
1721 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1723 MIRBuilder.
getMF());
1724 ToTruncate = DefaultReg;
1728 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1737 if (!IsConstantIndex || PointerSize != ResultWidth) {
1746 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1749 if (!IsConstantIndex) {
1750 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1757 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1772 if (PointerSize != ResultWidth) {
1775 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1777 MIRBuilder.
getMF());
1780 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1782 ToTruncate = SelectionResult;
1784 ToTruncate = Extracted;
1788 if (PointerSize != ResultWidth)
1798 SPIRV::BuiltIn::BuiltIn
Value =
1799 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1801 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1807 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1814 LLType,
Call->ReturnRegister);
1823 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1826 case SPIRV::OpStore:
1828 case SPIRV::OpAtomicLoad:
1830 case SPIRV::OpAtomicStore:
1832 case SPIRV::OpAtomicCompareExchange:
1833 case SPIRV::OpAtomicCompareExchangeWeak:
1836 case SPIRV::OpAtomicIAdd:
1837 case SPIRV::OpAtomicISub:
1838 case SPIRV::OpAtomicOr:
1839 case SPIRV::OpAtomicXor:
1840 case SPIRV::OpAtomicAnd:
1841 case SPIRV::OpAtomicExchange:
1842 case SPIRV::OpAtomicSMax:
1843 case SPIRV::OpAtomicSMin:
1844 case SPIRV::OpAtomicUMax:
1845 case SPIRV::OpAtomicUMin:
1847 case SPIRV::OpMemoryBarrier:
1849 case SPIRV::OpAtomicFlagTestAndSet:
1850 case SPIRV::OpAtomicFlagClear:
1853 if (
Call->isSpirvOp())
1865 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1868 case SPIRV::OpAtomicFAddEXT:
1869 case SPIRV::OpAtomicFMinEXT:
1870 case SPIRV::OpAtomicFMaxEXT:
1883 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1894 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1896 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1897 SPIRV::StorageClass::StorageClass ResSC =
1908 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1919 if (
Call->isSpirvOp())
1924 SPIRV::OpTypeVector;
1926 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1927 bool IsSwapReq =
false;
1932 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1936 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
1946 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1947 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1949 if (
Call->BuiltinName ==
"dot") {
1950 if (IsFirstSigned && IsSecondSigned)
1952 else if (!IsFirstSigned && !IsSecondSigned)
1955 OC = SPIRV::OpSUDot;
1959 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1960 if (IsFirstSigned && IsSecondSigned)
1961 OC = SPIRV::OpSDotAccSat;
1962 else if (!IsFirstSigned && !IsSecondSigned)
1963 OC = SPIRV::OpUDotAccSat;
1965 OC = SPIRV::OpSUDotAccSat;
1981 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1984 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1990 if (!IsVec && OC != SPIRV::OpFMulS)
1991 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
2000 SPIRV::BuiltIn::BuiltIn
Value =
2001 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
2004 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
2008 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
2009 false, std::nullopt);
2039 const Value *SRetArg,
2046 ElemTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2062 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2069 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2071 "overflow builtins");
2075 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2077 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
2079 case SPIRV::OpIAddCarryS:
2080 Opcode = SPIRV::OpIAddCarryV;
2082 case SPIRV::OpISubBorrowS:
2083 Opcode = SPIRV::OpISubBorrowV;
2088 RetType, MIRBuilder, GR);
2110 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2111 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2112 "Expected OpUMulExtended or OpSMulExtended");
2115 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2127 RetType =
Call->ReturnType;
2130 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2132 "multiplication builtins");
2135 "extended multiplication builtins");
2140 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2145 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2147 if (OpType1 != Member0Type)
2174 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2188 SPIRV::BuiltIn::BuiltIn
Value =
2189 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2190 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2191 Value == SPIRV::BuiltIn::NumWorkgroups ||
2192 Value == SPIRV::BuiltIn::WorkgroupSize ||
2193 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2203 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2207 unsigned NumExpectedRetComponents =
2214 if (NumExpectedRetComponents != NumActualRetComponents) {
2215 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2216 ?
Call->ReturnType->getOperand(1).getImm()
2223 IntTy, NumActualRetComponents, MIRBuilder,
true);
2228 bool UseQuerySize = IsDimBuf || IsMultisampled;
2230 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2237 if (NumExpectedRetComponents == NumActualRetComponents)
2239 if (NumExpectedRetComponents == 1) {
2241 unsigned ExtractedComposite =
2242 Component == 3 ? NumActualRetComponents - 1 : Component;
2243 assert(ExtractedComposite < NumActualRetComponents &&
2244 "Invalid composite index!");
2247 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2250 if (TypeReg != NewTypeReg)
2251 TypeReg = NewTypeReg;
2255 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2259 .
addImm(ExtractedComposite);
2265 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2270 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2271 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2279 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2280 "Image samples query result must be of int type!");
2285 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2288 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2290 (void)ImageDimensionality;
2293 case SPIRV::OpImageQuerySamples:
2294 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2295 "Image must be of 2D dimensionality");
2297 case SPIRV::OpImageQueryLevels:
2298 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2299 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2300 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2301 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2302 "Image must be of 1D/2D/3D/Cube dimensionality");
2314static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2316 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2317 case SPIRV::CLK_ADDRESS_CLAMP:
2318 return SPIRV::SamplerAddressingMode::Clamp;
2319 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2320 return SPIRV::SamplerAddressingMode::ClampToEdge;
2321 case SPIRV::CLK_ADDRESS_REPEAT:
2322 return SPIRV::SamplerAddressingMode::Repeat;
2323 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2324 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2325 case SPIRV::CLK_ADDRESS_NONE:
2326 return SPIRV::SamplerAddressingMode::None;
2333 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2336static SPIRV::SamplerFilterMode::SamplerFilterMode
2338 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2339 return SPIRV::SamplerFilterMode::Linear;
2340 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2341 return SPIRV::SamplerFilterMode::Nearest;
2342 return SPIRV::SamplerFilterMode::Nearest;
2349 if (
Call->isSpirvOp())
2356 if (HasOclSampler) {
2381 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2388 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2393 .
addImm(SPIRV::ImageOperand::Lod)
2395 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2401 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2406 .
addImm(SPIRV::ImageOperand::Lod)
2409 }
else if (HasMsaa) {
2415 .
addImm(SPIRV::ImageOperand::Sample)
2430 if (
Call->isSpirvOp())
2445 if (
Call->Builtin->name().contains_insensitive(
2446 "__translate_sampler_initializer")) {
2454 }
else if (
Call->Builtin->name().contains_insensitive(
2455 "__spirv_SampledImage")) {
2462 Call->ReturnRegister.isValid()
2463 ?
Call->ReturnRegister
2471 }
else if (
Call->Builtin->name().contains_insensitive(
2472 "__spirv_ImageSampleExplicitLod")) {
2474 std::string ReturnType = DemangledCall.
str();
2475 if (DemangledCall.
contains(
"_R")) {
2476 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2477 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2482 ReturnType, MIRBuilder,
true));
2484 std::string DiagMsg =
2485 "Unable to recognize SPIRV type name: " + ReturnType;
2488 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2493 .
addImm(SPIRV::ImageOperand::Lod)
2505 if (!ResTy.
isVector() && CondTy.isVector())
2507 "boolean condition");
2509 Call->Arguments[1],
Call->Arguments[2]);
2517 SPIRV::OpCompositeConstructContinuedINTEL,
2518 Call->Arguments,
Call->ReturnRegister,
2528 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2529 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2530 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2531 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2532 unsigned ArgSz =
Call->Arguments.size();
2533 unsigned LiteralIdx = 0;
2536 case SPIRV::OpCooperativeMatrixLoadKHR:
2537 LiteralIdx = ArgSz > 3 ? 3 : 0;
2539 case SPIRV::OpCooperativeMatrixStoreKHR:
2540 LiteralIdx = ArgSz > 4 ? 4 : 0;
2542 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2543 LiteralIdx = ArgSz > 7 ? 7 : 0;
2545 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2546 LiteralIdx = ArgSz > 8 ? 8 : 0;
2549 case SPIRV::OpCooperativeMatrixMulAddKHR:
2550 LiteralIdx = ArgSz > 3 ? 3 : 0;
2556 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2558 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2575 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2586 IsSet ? TypeReg :
Register(0), ImmArgs);
2595 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2599 case SPIRV::OpSpecConstant: {
2604 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2605 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2606 "Argument should be either an int or floating-point constant");
2609 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2610 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2612 ? SPIRV::OpSpecConstantTrue
2613 : SPIRV::OpSpecConstantFalse;
2619 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2620 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2632 case SPIRV::OpSpecConstantComposite: {
2634 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2635 Call->Arguments,
Call->ReturnRegister,
2650 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2661 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2671 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2689 InputReg =
Call->Arguments[1];
2692 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2700 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2701 MRI->
setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2705 for (
unsigned index = 2; index < 7; index++) {
2724 MRI->
setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2725 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2728 for (
unsigned index = 1; index < 6; index++)
2742 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2754 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2764 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2775 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2785 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2787 unsigned Scope = SPIRV::Scope::Workgroup;
2789 Scope = SPIRV::Scope::Subgroup;
2799 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2801 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2802 unsigned ArgSz =
Call->Arguments.size();
2811 IsSet ? TypeReg :
Register(0), ImmArgs);
2836 const unsigned NumCallArgs =
Call->Arguments.size();
2837 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2838 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2841 bool HasSRetArg = RetTy->
isVoidTy();
2843 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2844 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2845 const unsigned MaxNDRangeArgs = 3;
2846 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2848 const unsigned GlobalWorkSizeArgIdx =
2849 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2850 const unsigned LocalWorkSizeArgIdx =
2851 (NumNDRangeArgs == 1)
2853 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2854 const unsigned GlobalWorkOffsetArgIdx =
2855 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2860 assert(AddressModelBits == 64 || AddressModelBits == 32);
2864 unsigned Dimension = 0;
2865 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2866 assert(Dimension <= 3 && Dimension >= 1);
2873 if (Dimension == 1) {
2876 "Expected scalar integer type");
2878 if (NumNDRangeArgs < MaxNDRangeArgs)
2885 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2887 if (NumNDRangeArgs < MaxNDRangeArgs) {
2893 SpvFieldTy, *ST.getInstrInfo());
2899 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2900 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2908 "Only pointer types are supported for loading values");
2922 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2923 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2924 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2927 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2932 .
addUse(GlobalWorkOffset);
2949 .
addUse(GlobalWorkOffset);
2981 bool IsSpirvOp =
Call->isSpirvOp();
2982 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
2983 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
2985 const unsigned NumArgs =
Call->Arguments.size();
2986 const unsigned BaseArgIdx = 0;
2987 const unsigned IncorrectIdx = NumArgs + 1;
2989 const unsigned QueueIdx = BaseArgIdx;
2990 const unsigned FlagsIdx = BaseArgIdx + 1;
2991 const unsigned NDRangeIdx = BaseArgIdx + 2;
2992 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
2993 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
2994 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
2995 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
2996 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
2997 const unsigned LocalSizeNumElemIdx =
2998 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
2999 const unsigned LocalSizeElemPtrIdx =
3000 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
3002 [[maybe_unused]]
const unsigned LastArgIdx =
3003 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
3004 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
3010 auto BuildDeviceEventNullPtr = [&]() {
3014 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
3022 auto IsNullEvent = [&](
Register R) {
3024 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3025 Def->getOperand(1).getCImm()->isZero();
3028 NumEventsReg =
Call->Arguments[NumEventsIdx];
3029 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
3030 RetEventReg =
Call->Arguments[RetEventIdx];
3031 if (IsNullEvent(WaitEventsReg))
3032 WaitEventsReg = BuildDeviceEventNullPtr();
3033 if (IsNullEvent(RetEventReg))
3034 RetEventReg = BuildDeviceEventNullPtr();
3037 Register NullPtr = BuildDeviceEventNullPtr();
3038 WaitEventsReg = NullPtr;
3039 RetEventReg = NullPtr;
3060 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3067 .
addUse(BlockLiteralReg);
3077 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3081 ConstOp.
isCImm() &&
"Expected constant immediate");
3084 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3086 for (
unsigned i = 0; i < NumElem; ++i) {
3092 .
addUse(LocalSizeArrayReg)
3100 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3113 for (
auto &LocalSize : LocalSizes)
3125 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3128 case SPIRV::OpRetainEvent:
3129 case SPIRV::OpReleaseEvent:
3131 case SPIRV::OpCreateUserEvent:
3132 case SPIRV::OpGetDefaultQueue:
3136 case SPIRV::OpIsValidEvent:
3141 case SPIRV::OpSetUserEventStatus:
3145 case SPIRV::OpCaptureEventProfilingInfo:
3150 case SPIRV::OpBuildNDRange:
3152 case SPIRV::OpEnqueueKernel:
3165 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3167 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3169 if (
Call->isSpirvOp())
3176 case SPIRV::OpGroupAsyncCopy: {
3178 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3182 unsigned NumArgs =
Call->Arguments.size();
3185 if (!EventType || EventType->
getOpcode() != SPIRV::OpTypeEvent) {
3189 if (Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3190 Def->getOperand(1).getCImm()->isZero()) {
3195 "spirv.Event", MIRBuilder,
true);
3201 EventReg = NullEventReg;
3210 DestPtrTy && DestPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR;
3213 Call->Arguments.size() > 4
3214 ?
Call->Arguments[3]
3219 auto MIB = MIRBuilder
3220 .
buildInstr(IsUntyped ? SPIRV::OpUntypedGroupAsyncCopyKHR
3221 : SPIRV::OpGroupAsyncCopy)
3234 "async copy pointer argument");
3246 case SPIRV::OpGroupWaitEvents:
3262 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3264 if (!Builtin &&
Call->isSpirvOp()) {
3267 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3272 assert(Builtin &&
"Conversion builtin not found.");
3275 SPIRV::Decoration::SaturatedConversion, {});
3278 bool AnyTypeIsFloat =
3285 if (AnyTypeIsFloat) {
3287 SPIRV::Decoration::FPRoundingMode,
3288 {(unsigned)Builtin->RoundingMode});
3292 std::string NeedExtMsg;
3293 bool IsRightComponentsNumber =
true;
3294 unsigned Opcode = SPIRV::OpNop;
3297 bool IsSourceSigned =
3303 : SPIRV::OpSatConvertSToU;
3305 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3307 SPIRV::OpTypeFloat)) {
3311 &MIRBuilder.
getMF().getSubtarget());
3312 if (!ST->canUseExtension(
3313 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3314 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3315 IsRightComponentsNumber =
3318 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3320 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3324 SPIRV::OpTypeFloat)) {
3330 &MIRBuilder.
getMF().getSubtarget());
3331 if (!ST->canUseExtension(
3332 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3333 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3334 IsRightComponentsNumber =
3337 Opcode = SPIRV::OpConvertFToBF16INTEL;
3340 : SPIRV::OpConvertFToU;
3343 SPIRV::OpTypeFloat)) {
3346 &MIRBuilder.
getMF().getSubtarget());
3347 if (!ST->canUseExtension(
3348 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3349 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3350 IsRightComponentsNumber =
3353 Opcode = SPIRV::OpRoundFToTF32INTEL;
3356 Opcode = SPIRV::OpFConvert;
3361 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3362 if (!NeedExtMsg.empty()) {
3363 std::string DiagMsg = std::string(BuiltinName) +
3364 ": the builtin requires the following SPIR-V "
3369 if (!IsRightComponentsNumber) {
3370 std::string DiagMsg =
3371 std::string(BuiltinName) +
3372 ": result and argument must have the same number of components";
3375 assert(Opcode != SPIRV::OpNop &&
3376 "Conversion between the types not implemented!");
3390 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->name(),
3391 Call->Builtin->Set);
3397 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3401 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3415 const auto *Builtin =
Call->Builtin;
3416 auto *MRI = MIRBuilder.
getMRI();
3418 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3424 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3425 DestReg = MRI->createGenericVirtualRegister(PtrTy);
3426 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3429 MIB.addDef(DestReg);
3432 MIB.addDef(
Call->ReturnRegister);
3435 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3438 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3439 DefMI->getOperand(1).isCImm()) {
3446 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3461 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3462 bool IsLoad = Opcode == SPIRV::OpLoad;
3466 MIB.addDef(
Call->ReturnRegister);
3474 MIB.addUse(
Call->Arguments[1]);
3476 unsigned NumArgs =
Call->Arguments.size();
3477 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3479 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3492std::tuple<int, unsigned, unsigned>
3494 SPIRV::InstructionSet::InstructionSet Set) {
3497 std::unique_ptr<const IncomingCall>
Call =
3500 return std::make_tuple(-1, 0, 0);
3502 switch (
Call->Builtin->Group) {
3503 case SPIRV::Relational:
3505 case SPIRV::Barrier:
3506 case SPIRV::CastToPtr:
3507 case SPIRV::ImageMiscQuery:
3508 case SPIRV::SpecConstant:
3509 case SPIRV::Enqueue:
3510 case SPIRV::AsyncCopy:
3511 case SPIRV::LoadStore:
3512 case SPIRV::CoopMatr:
3513 case SPIRV::Arithmetic:
3514 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3515 Call->Builtin->Set))
3516 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3518 case SPIRV::Extended:
3519 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3520 Call->Builtin->Set))
3521 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3523 case SPIRV::VectorLoadStore:
3524 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3525 Call->Builtin->name(),
Call->Builtin->Set))
3526 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3529 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3530 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3532 case SPIRV::AtomicFloating:
3534 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3535 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3537 case SPIRV::IntelSubgroups:
3539 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3540 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3542 case SPIRV::GroupUniform:
3543 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3544 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3546 case SPIRV::IntegerDot:
3548 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3549 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3551 case SPIRV::WriteImage:
3552 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3554 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3555 case SPIRV::Construct:
3556 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3558 case SPIRV::KernelClock:
3559 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3561 return std::make_tuple(-1, 0, 0);
3563 return std::make_tuple(-1, 0, 0);
3577 if (
Call->isSpirvOp())
3585 if (
Call->Arguments.size() < ArgBase)
3587 unsigned NumMangledArgs =
Call->Arguments.size() - ArgBase;
3588 unsigned NumArgsToCheck =
3589 std::min<unsigned>(NumMangledArgs, ArgTypeStrs.
size());
3590 for (
unsigned ArgIdx = 0; ArgIdx < NumArgsToCheck; ++ArgIdx) {
3591 StringRef ArgTypeStr = ArgTypeStrs[ArgIdx].trim();
3600 if (!ExpectedType || ExpectedType->
isVoidTy() ||
3608 unsigned ArgTypeOpcode = ArgType->
getOpcode();
3609 if (ArgTypeOpcode != SPIRV::OpTypeInt &&
3610 ArgTypeOpcode != SPIRV::OpTypeFloat &&
3611 ArgTypeOpcode != SPIRV::OpTypeBool &&
3612 ArgTypeOpcode != SPIRV::OpTypeVector)
3616 Type *ExpectedScalarType =
3617 ExpectedVecType ? ExpectedVecType->getElementType() : ExpectedType;
3622 bool ExpectedIsInt = ExpectedScalarType->
isIntegerTy();
3623 unsigned ArgOpcode = ArgScalarType->
getOpcode();
3625 ArgOpcode == SPIRV::OpTypeInt || ArgOpcode == SPIRV::OpTypeBool;
3627 if (ExpectedIsInt != ArgIsInt)
3630 unsigned ExpectedElts =
3631 ExpectedVecType ? ExpectedVecType->getElementCount().getFixedValue()
3640 SPIRV::InstructionSet::InstructionSet Set,
3645 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3649 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3650 std::unique_ptr<const IncomingCall>
Call =
3655 return std::nullopt;
3660 if (Args.size() <
Call->Builtin->MinNumArgs) {
3661 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3662 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3663 <<
", got " << Args.size()
3664 <<
"; treating as a normal function\n");
3665 return std::nullopt;
3667 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3668 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3669 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3670 <<
", got " << Args.size()
3671 <<
"; treating as a normal function\n");
3672 return std::nullopt;
3680 LLVM_DEBUG(
dbgs() <<
"Argument types do not match mangled types for "
3681 <<
"builtin " << DemangledCall
3682 <<
"; treating as a normal function\n");
3683 return std::nullopt;
3687 switch (
Call->Builtin->Group) {
3688 case SPIRV::Extended:
3690 case SPIRV::Relational:
3694 case SPIRV::Variable:
3698 case SPIRV::AtomicFloating:
3700 case SPIRV::Barrier:
3702 case SPIRV::CastToPtr:
3705 case SPIRV::IntegerDot:
3709 case SPIRV::ICarryBorrow:
3711 case SPIRV::MulExtended:
3713 case SPIRV::Arithmetic:
3715 case SPIRV::GetQuery:
3717 case SPIRV::ImageSizeQuery:
3719 case SPIRV::ImageMiscQuery:
3721 case SPIRV::ReadImage:
3723 case SPIRV::WriteImage:
3725 case SPIRV::SampleImage:
3729 case SPIRV::Construct:
3731 case SPIRV::SpecConstant:
3733 case SPIRV::Enqueue:
3735 case SPIRV::AsyncCopy:
3737 case SPIRV::Convert:
3739 case SPIRV::VectorLoadStore:
3741 case SPIRV::LoadStore:
3743 case SPIRV::IntelSubgroups:
3745 case SPIRV::GroupUniform:
3747 case SPIRV::KernelClock:
3749 case SPIRV::CoopMatr:
3751 case SPIRV::ExtendedBitOps:
3753 case SPIRV::BindlessINTEL:
3755 case SPIRV::TernaryBitwiseINTEL:
3757 case SPIRV::Block2DLoadStore:
3761 case SPIRV::PredicatedLoadStore:
3763 case SPIRV::BlockingPipes:
3765 case SPIRV::ArbitraryPrecisionFixedPoint:
3767 case SPIRV::ImageChannelDataTypes:
3769 case SPIRV::ArbitraryFloatingPoint:
3780 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3781 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3798 unsigned VecElts = 0;
3809 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3821 auto Pos1 = DemangledCall.
find(
'(');
3824 auto Pos2 = DemangledCall.
find(
')');
3827 DemangledCall.
slice(Pos1 + 1, Pos2)
3828 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3836 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3838 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3847#define GET_BuiltinTypes_DECL
3848#define GET_BuiltinTypes_IMPL
3855#define GET_OpenCLTypes_DECL
3856#define GET_OpenCLTypes_IMPL
3858#include "SPIRVGenTables.inc"
3866 if (Name.starts_with(
"void"))
3868 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3870 else if (Name.starts_with(
"bfloat"))
3872 else if (Name.starts_with(
"float"))
3874 else if (Name.starts_with(
"half"))
3876 else if (Name.starts_with(
"double"))
3889 unsigned Opcode = TypeRecord->
Opcode;
3904 "Invalid number of parameters for SPIR-V pipe builtin!");
3907 SPIRV::AccessQualifier::AccessQualifier(
3915 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3917 "SPIR-V coop matrices builtin type must have a type parameter!");
3920 SPIRV::AccessQualifier::ReadWrite,
true);
3923 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3932 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3941 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3948 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3949 assert(ParamEType->getNumTypeParameters() == 1 &&
3950 "Inline SPIR-V integral constant builtin must have a type "
3952 assert(ParamEType->getNumIntParameters() == 1 &&
3953 "Inline SPIR-V integral constant builtin must have a "
3956 auto OperandValue = ParamEType->getIntParameter(0);
3957 auto *OperandType = ParamEType->getTypeParameter(0);
3960 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3963 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3965 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3966 assert(ParamEType->getNumTypeParameters() == 0 &&
3967 "Inline SPIR-V literal builtin does not take type "
3969 assert(ParamEType->getNumIntParameters() == 1 &&
3970 "Inline SPIR-V literal builtin must have an integer "
3973 auto OperandValue = ParamEType->getIntParameter(0);
3980 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3992 "Vulkan buffers have exactly one type for the type of the buffer.");
3994 "Vulkan buffer have 2 integer parameters: storage class and is "
3998 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
4009 "Vulkan push constants have exactly one type as argument.");
4023 StringRef NameWithParameters = TypeName;
4030 SPIRV::lookupOpenCLType(NameWithParameters);
4033 NameWithParameters);
4034 NameWithParameters =
4042 "Unknown builtin opaque type!");
4046 if (!NameWithParameters.
contains(
'_'))
4050 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
4054 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
4055 if (HasTypeParameter)
4058 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
4059 unsigned IntParameter = 0;
4060 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
4063 "Invalid format of SPIR-V builtin parameter literal!");
4067 NameWithParameters.
substr(0, BaseNameLength),
4068 TypeParameters, IntParameters);
4073 SPIRV::AccessQualifier::AccessQualifier AccessQual,
4094 if (Name ==
"spirv.Type") {
4096 }
else if (Name ==
"spirv.VulkanBuffer") {
4098 }
else if (Name ==
"spirv.Padding") {
4100 }
else if (Name ==
"spirv.PushConstant") {
4102 }
else if (Name ==
"spirv.Layout") {
4116 switch (TypeRecord->
Opcode) {
4117 case SPIRV::OpTypeImage:
4120 case SPIRV::OpTypePipe:
4123 case SPIRV::OpTypeDeviceEvent:
4126 case SPIRV::OpTypeSampler:
4129 case SPIRV::OpTypeSampledImage:
4132 case SPIRV::OpTypeCooperativeMatrixKHR:
4154 return Builtin->
Group == Pipe || Builtin->
Group == CastToPtr ||
4155 Builtin->
Group == BlockingPipes;
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Promote Memory to Register
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
static const fltSemantics & IEEEsingle()
APInt bitcastToAPInt() const
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
uint64_t getZExtValue() const
Get zero extended value.
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI FPClassTest getParamNoFPClass(unsigned i) const
Extract a test mask for disallowed floating-point value classes for the parameter.
LLVM_ABI FPClassTest getRetNoFPClass() const
Extract a test mask for disallowed floating-point value classes for the return value.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
bool hasStructRetAttr() const
Determine if the call returns a structure through first pointer argument.
@ 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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC, bool ForceTyped=false)
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)
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)
unsigned getDeducedPointeeByteSize(const Value *PtrVal)
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
Type * findDeducedElementType(const Value *Val)
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVTypeInst SpvType, bool EmitIR, bool ZeroAsNull=true)
SPIRVTypeInst getOrCreateVulkanPushConstantType(MachineIRBuilder &MIRBuilder, Type *ElemType)
SPIRVTypeInst getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static constexpr size_t npos
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
bool contains_insensitive(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
Get the string size.
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
A switch()-like statement whose cases are string literals.
StringSwitch & EndsWith(StringLiteral S, T Value)
Class to represent target extensions types, which are generally unintrospectable from target-independ...
ArrayRef< Type * > type_params() const
Return the type parameters for this particular target extension type.
unsigned getNumIntParameters() const
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Type * getTypeParameter(unsigned i) const
unsigned getNumTypeParameters() const
unsigned getIntParameter(unsigned i) const
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI StringRef getStructName() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isTargetExtTy() const
Return true if this is a target extension type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getBFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents a version number in the form major[.minor[.subminor[.build]]].
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
LLVM_C_ABI LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount)
Create a vector type that contains a defined type and has a specific number of elements.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool parseBuiltinTypeStr(SmallVector< StringRef, 10 > &BuiltinArgsTypeStrs, StringRef DemangledCall, LLVMContext &Ctx)
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
Type * parseBuiltinCallArgumentType(StringRef TypeStr, LLVMContext &Ctx)
bool isPipeOrAddressSpaceCastBuiltin(StringRef Name)
Returns true if Name is a pipe or address-space-cast OpenCL builtin.
std::optional< bool > lowerBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR, const CallBase &CB)
Type * parseBuiltinCallArgumentBaseType(StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)
Parses the provided ArgIdx argument base type in the DemangledCall skeleton.
std::tuple< int, unsigned, unsigned > mapBuiltinToOpcode(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)
Helper function for finding a builtin function attributes by a demangled function name.
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
static bool demangledArgTypesMatchIR(const SPIRV::IncomingCall *Call, StringRef DemangledCall, SPIRVGlobalRegistry *GR, LLVMContext &Ctx, const CallBase &CB)
Checks that scalar/vector numeric arguments of Call match the types implied by their mangling in Dema...
SPIRVTypeInst lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
This is an optimization pass for GlobalISel generic memory operations.
static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's 2d block io instructions.
static bool generateExtInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static void buildSRetInst(unsigned Opcode, Register SRetReg, Register Op1Reg, Register Op2Reg, SPIRVTypeInst RetType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst deduceSRetPointeeType(Register SRetReg, const Value *SRetArg, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateGetQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConstructInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic flag instructions (e.g.
static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRV::SamplerFilterMode::SamplerFilterMode getSamplerFilterModeFromBitmask(unsigned Bitmask)
static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic store instruction.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building extended bit operations.
static const Type * getBlockStructType(Register ParamReg, MachineRegisterInfo *MRI)
static bool generateGroupInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConvertInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
FPDecorationId demangledPostfixToDecorationId(const std::string &S)
static SPIRVTypeInst getSamplerType(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim)
static bool generateImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool builtinMayNeedPromotionToVec(uint32_t BuiltinNumber)
static std::tuple< Register, SPIRVTypeInst > buildBoolRegister(MachineIRBuilder &MIRBuilder, SPIRVTypeInst ResultType, SPIRVGlobalRegistry *GR)
Helper function building either a resulting scalar or vector bool register depending on the expected ...
Register createVirtualRegister(SPIRVTypeInst SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
static Register buildScopeReg(Register CLScopeRegister, SPIRV::Scope::Scope Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI)
void updateRegType(Register Reg, Type *Ty, SPIRVTypeInst SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning a SPIRV type to a register, ensuring the register class and ty...
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
static SPIRVTypeInst getInlineSpirvType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
static Register buildConstantIntReg32(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
static unsigned getNumSizeComponents(SPIRVTypeInst imgType)
Helper function for obtaining the number of size components.
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
static bool generateBarrierInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getLayoutType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
static bool generateAPFixedPointInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static bool generateMulExtendedInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static SPIRVTypeInst getVulkanPushConstantType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateKernelClockInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static void setRegClassIfNull(Register Reg, MachineRegisterInfo *MRI, SPIRVGlobalRegistry *GR)
void buildOpName(Register Target, StringRef Name, MachineIRBuilder &MIRBuilder)
static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateWaveInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
static bool buildNDRange(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static bool generateEnqueueInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
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 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 generateBlockingPipesInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool generateSampleImageInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Type * parseTypeString(StringRef Name, LLVMContext &Context)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
static const Type * getMachineInstrType(MachineInstr *MI)
static bool generateDotOrFMulInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
static SPIRV::SamplerAddressingMode::SamplerAddressingMode getSamplerAddressingModeFromBitmask(unsigned Bitmask)
static bool generateAtomicInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static std::unique_ptr< const SPIRV::IncomingCall > lookupBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, Register ReturnRegister, SPIRVTypeInst ReturnType, const SmallVectorImpl< Register > &Arguments)
Looks up the demangled builtin call in the SPIRVBuiltins.td records using the provided DemangledCall ...
static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
static bool buildSelectInst(MachineIRBuilder &MIRBuilder, Register ReturnRegister, Register SourceRegister, SPIRVTypeInst ReturnType, SPIRVGlobalRegistry *GR)
Helper function for building either a vector or scalar select instruction depending on the expected R...
static Register buildMemSemanticsReg(Register SemanticsRegister, Register PtrRegister, unsigned &Semantics, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateSelectInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)
static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic load instruction.
static bool generateIntelSubgroupsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getCoopMatrType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildPipeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, unsigned Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildLoadInst(SPIRVTypeInst BaseType, Register PtrRegister, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, Register DestinationReg=Register(0))
Helper function for building a load instruction loading into the DestinationReg.
static bool generateSpecConstantInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
@ Mul
Product of integers.
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
static bool generateVectorLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool genWorkgroupQuery(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, uint64_t DefaultValue)
static bool generateCoopMatrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SmallVector< Register > getBuiltinCallArguments(const SPIRV::IncomingCall *Call, uint32_t BuiltinNumber, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getNonParameterizedType(const TargetExtType *ExtensionType, const SPIRV::BuiltinType *TypeRecord, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's bindless image instructions.
static bool buildAtomicFloatingRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic floating-type instruction.
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
static bool generateReadImageInst(StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool hasBuiltinTypePrefix(StringRef Name)
static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
static bool buildAPFixedPointInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
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 buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic instructions.
static SPIRV::MemorySemantics::MemorySemantics getSPIRVMemSemantics(std::memory_order MemOrder)
static bool generateRelationalInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVTypeInst getPipeType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicInitInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)
Helper function for translating atomic init to OpStore.
static bool generateWriteImageInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateAsyncCopy(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
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 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 bool generateICarryBorrowInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
static SPIRVTypeInst getVulkanBufferType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, const SPIRV::DemangledBuiltin *Builtin, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic compare-exchange instruction.
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)
MCRegisterClass TargetRegisterClass
static bool generateBuiltinVar(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...
FPRoundingMode::FPRoundingMode RoundingMode
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
const SmallVectorImpl< Register > & Arguments
const SPIRVTypeInst ReturnType
IncomingCall(const std::string BuiltinName, const DemangledBuiltin *Builtin, const Register ReturnRegister, SPIRVTypeInst ReturnType, const SmallVectorImpl< Register > &Arguments)
const std::string BuiltinName
const Register ReturnRegister
const DemangledBuiltin * Builtin
InstructionSet::InstructionSet Set
StringTable::Offset SpirvTypeLiteral
InstructionSet::InstructionSet Set
FPRoundingMode::FPRoundingMode RoundingMode