22#include "llvm/IR/IntrinsicsSPIRV.h"
27#define DEBUG_TYPE "spirv-builtins"
31#define GET_BuiltinGroup_DECL
32#include "SPIRVGenTables.inc"
36 InstructionSet::InstructionSet
Set;
44#define GET_DemangledBuiltins_DECL
45#define GET_DemangledBuiltins_IMPL
67 InstructionSet::InstructionSet
Set;
71#define GET_NativeBuiltins_DECL
72#define GET_NativeBuiltins_IMPL
88#define GET_GroupBuiltins_DECL
89#define GET_GroupBuiltins_IMPL
99#define GET_IntelSubgroupsBuiltins_DECL
100#define GET_IntelSubgroupsBuiltins_IMPL
107#define GET_AtomicFloatingBuiltins_DECL
108#define GET_AtomicFloatingBuiltins_IMPL
115#define GET_GroupUniformBuiltins_DECL
116#define GET_GroupUniformBuiltins_IMPL
120 InstructionSet::InstructionSet
Set;
125#define GET_GetBuiltins_DECL
126#define GET_GetBuiltins_IMPL
130 InstructionSet::InstructionSet
Set;
134#define GET_ImageQueryBuiltins_DECL
135#define GET_ImageQueryBuiltins_IMPL
143#define GET_IntegerDotProductBuiltins_DECL
144#define GET_IntegerDotProductBuiltins_IMPL
148 InstructionSet::InstructionSet
Set;
159 InstructionSet::InstructionSet
Set;
167#define GET_ConvertBuiltins_DECL
168#define GET_ConvertBuiltins_IMPL
170using namespace InstructionSet;
171#define GET_VectorLoadStoreBuiltins_DECL
172#define GET_VectorLoadStoreBuiltins_IMPL
174#define GET_CLMemoryScope_DECL
175#define GET_CLSamplerAddressingMode_DECL
176#define GET_CLMemoryFenceFlags_DECL
177#define GET_ExtendedBuiltins_DECL
178#include "SPIRVGenTables.inc"
182 return getDemangledBuiltinStr(
Name);
195 StringRef PassPrefix =
"(anonymous namespace)::";
197 std::string BuiltinName = DemangledCall.
str();
202 std::size_t Pos = BuiltinName.find(
">(");
203 if (Pos != std::string::npos) {
204 BuiltinName = BuiltinName.substr(0, BuiltinName.rfind(
'<', Pos));
206 Pos = BuiltinName.find(
'(');
207 if (Pos != std::string::npos)
208 BuiltinName = BuiltinName.substr(0, Pos);
210 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(
' ') + 1);
214 if (BuiltinName.find(PassPrefix) == 0)
215 BuiltinName = BuiltinName.substr(PassPrefix.
size());
216 else if (BuiltinName.find(SpvPrefix) == 0)
217 BuiltinName = BuiltinName.substr(SpvPrefix.
size());
220 if (BuiltinName.rfind(
"__spirv_ocl_", 0) == 0)
221 BuiltinName = BuiltinName.substr(12);
247 static const std::regex SpvWithR(
248 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"
250 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"
251 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
252 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
254 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");
256 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
257 std::ssub_match SubMatch;
258 if (DecorationId && Match.size() > 3) {
263 BuiltinName = SubMatch.str();
280static std::unique_ptr<const SPIRV::IncomingCall>
282 SPIRV::InstructionSet::InstructionSet Set,
289 DemangledCall.
slice(DemangledCall.
find(
'(') + 1, DemangledCall.
find(
')'));
290 BuiltinArgs.
split(BuiltinArgumentTypes,
',', -1,
false);
295 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))
296 return std::make_unique<SPIRV::IncomingCall>(
297 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
302 if (BuiltinArgumentTypes.
size() >= 1) {
303 char FirstArgumentType = BuiltinArgumentTypes[0][0];
310 switch (FirstArgumentType) {
313 if (Set == SPIRV::InstructionSet::OpenCL_std)
315 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
324 if (Set == SPIRV::InstructionSet::OpenCL_std)
326 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
334 if (Set == SPIRV::InstructionSet::OpenCL_std ||
335 Set == SPIRV::InstructionSet::GLSL_std_450)
342 if (!Prefix.empty() &&
343 (Builtin = SPIRV::lookupBuiltin((Prefix + BuiltinName).str(), Set)))
344 return std::make_unique<SPIRV::IncomingCall>(
345 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
347 if (!Suffix.
empty() &&
348 (Builtin = SPIRV::lookupBuiltin((BuiltinName + Suffix).str(), Set)))
349 return std::make_unique<SPIRV::IncomingCall>(
350 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
362 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
363 MI->getOperand(1).isReg());
364 Register BitcastReg =
MI->getOperand(1).getReg();
366 assert(BitcastMI &&
"Definition for source reg not found.");
367 if (BitcastMI->
getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
382 Register ValueReg =
MI->getOperand(0).getReg();
388 assert(Ty &&
"Type is expected");
400 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
401 return MI->getOperand(1).getGlobal()->getValueType();
403 "Blocks in OpenCL C must be traceable to allocation site");
415static std::tuple<Register, SPIRVTypeInst>
436 return std::make_tuple(ResultRegister, BoolType);
457 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
467 if (!DestinationReg.isValid())
472 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
473 return DestinationReg;
482 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
483 SPIRV::LinkageType::Import}) {
491 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
497 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
504 return LoadedRegister;
515static SPIRV::MemorySemantics::MemorySemantics
518 case std::memory_order_relaxed:
519 return SPIRV::MemorySemantics::None;
520 case std::memory_order_acquire:
521 return SPIRV::MemorySemantics::Acquire;
522 case std::memory_order_release:
523 return SPIRV::MemorySemantics::Release;
524 case std::memory_order_acq_rel:
525 return SPIRV::MemorySemantics::AcquireRelease;
526 case std::memory_order_seq_cst:
527 return SPIRV::MemorySemantics::SequentiallyConsistent;
535 case SPIRV::CLMemoryScope::memory_scope_work_item:
536 return SPIRV::Scope::Invocation;
537 case SPIRV::CLMemoryScope::memory_scope_work_group:
538 return SPIRV::Scope::Workgroup;
539 case SPIRV::CLMemoryScope::memory_scope_device:
540 return SPIRV::Scope::Device;
541 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
542 return SPIRV::Scope::CrossDevice;
543 case SPIRV::CLMemoryScope::memory_scope_sub_group:
544 return SPIRV::Scope::Subgroup;
557 SPIRV::Scope::Scope Scope,
561 if (CLScopeRegister.
isValid()) {
566 if (CLScope ==
static_cast<unsigned>(Scope)) {
567 MRI->setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
568 return CLScopeRegister;
576 if (
MRI->getRegClassOrNull(
Reg))
580 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
585static SPIRV::MemorySemantics::MemorySemantics
612 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
613 for (
unsigned i = 0; i < Sz; ++i)
614 MIB.addUse(
Call->Arguments[i]);
623 if (
Call->isSpirvOp())
627 "Need 2 arguments for atomic init translation");
639 if (
Call->isSpirvOp())
646 const SPIRV::MemorySemantics::MemorySemantics Ordering =
647 Call->Arguments.size() >= 2
649 : SPIRV::MemorySemantics::SequentiallyConsistent;
650 const unsigned StorageClassSem =
657 SPIRV::Scope::Device, MIRBuilder, GR,
MRI);
672 if (
Call->isSpirvOp())
679 const SPIRV::MemorySemantics::MemorySemantics Ordering =
680 Call->Arguments.size() >= 3
682 : SPIRV::MemorySemantics::SequentiallyConsistent;
683 const unsigned StorageClassSem =
689 SPIRV::Scope::Device, MIRBuilder, GR,
MRI);
702 if (
Call->isSpirvOp())
706 bool IsCmpxchg =
Call->Builtin->name().contains(
"cmpxchg");
713 LLT DesiredLLT =
MRI->getType(Desired);
723 assert((SpvObjectPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR ||
725 "SPIRV type is expected");
726 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
734 ? SPIRV::MemorySemantics::None
735 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
738 ? SPIRV::MemorySemantics::None
739 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
740 if (
Call->Arguments.size() >= 4) {
742 "Need 5+ args for explicit atomic cmpxchg");
749 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
750 MemSemEqualReg =
Call->Arguments[3];
751 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
752 MemSemUnequalReg =
Call->Arguments[4];
756 if (!MemSemUnequalReg.
isValid())
760 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
761 if (
Call->Arguments.size() >= 6) {
763 "Extra args for explicit atomic cmpxchg");
764 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
767 if (ClScope ==
static_cast<unsigned>(Scope))
768 ScopeReg =
Call->Arguments[5];
774 IsCmpxchg ? ExpectedArg
777 Register Tmp = !IsCmpxchg ?
MRI->createGenericVirtualRegister(DesiredLLT)
778 :
Call->ReturnRegister;
779 if (!
MRI->getRegClassOrNull(Tmp))
803 if (
Call->isSpirvOp())
811 Name.contains(
"atomic_fetch_") || Name.starts_with(
"atomic_exchange");
812 SPIRV::Scope::Scope DefaultScope =
813 IsOCL20 ? SPIRV::Scope::Device : SPIRV::Scope::Workgroup;
818 "Too many args for explicit atomic RMW");
823 SPIRV::MemorySemantics::MemorySemantics Ordering =
824 IsOCL20 ? SPIRV::MemorySemantics::SequentiallyConsistent
825 : SPIRV::MemorySemantics::None;
826 unsigned StorageClassSem = SPIRV::MemorySemantics::None;
827 if (
Call->Arguments.size() >= 3)
829 if (IsOCL20 ||
Call->Arguments.size() >= 3)
837 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
838 if (Opcode == SPIRV::OpAtomicIAdd) {
839 Opcode = SPIRV::OpAtomicFAddEXT;
840 }
else if (Opcode == SPIRV::OpAtomicISub) {
843 Opcode = SPIRV::OpAtomicFAddEXT;
845 MRI->createGenericVirtualRegister(
MRI->getType(ValueReg));
854 ValueReg = NegValueReg;
873 "Wrong number of atomic floating-type builtin");
893 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
895 if (
Call->isSpirvOp())
901 SPIRV::MemorySemantics::MemorySemantics Ordering =
902 SPIRV::MemorySemantics::SequentiallyConsistent;
903 unsigned StorageClassSem = SPIRV::MemorySemantics::None;
904 if (
Call->Arguments.size() >= 2) {
910 assert((Opcode != SPIRV::OpAtomicFlagClear ||
911 (Ordering != SPIRV::MemorySemantics::Acquire &&
912 Ordering != SPIRV::MemorySemantics::AcquireRelease)) &&
913 "Invalid memory order argument!");
920 SPIRV::Scope::Device, MIRBuilder, GR,
MRI);
932 F.getContext().diagnose(
944 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
945 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
946 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
947 std::string DiagMsg = std::string(Builtin->
name()) +
948 ": the builtin requires the following SPIR-V "
949 "extension: SPV_INTEL_split_barrier";
953 if (
Call->isSpirvOp())
957 bool IsSubgroupBarrier = Builtin->
name() ==
"sub_group_barrier";
958 if (IsSubgroupBarrier) {
962 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT) {
965 "sub_group_barrier with non-constant arguments is not supported");
971 unsigned MemSemantics = SPIRV::MemorySemantics::None;
973 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
974 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
976 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
977 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
979 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
980 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
982 if (Opcode == SPIRV::OpMemoryBarrier)
986 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
987 MemSemantics |= SPIRV::MemorySemantics::Release;
988 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
989 MemSemantics |= SPIRV::MemorySemantics::Acquire;
991 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
994 MemFlags == MemSemantics
998 SPIRV::Scope::Scope Scope =
999 IsSubgroupBarrier ? SPIRV::Scope::Subgroup : SPIRV::Scope::Workgroup;
1000 SPIRV::Scope::Scope MemScope = Scope;
1001 if (
Call->Arguments.size() >= 2) {
1003 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
1004 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
1005 "Extra args for explicitly scoped barrier");
1006 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
1007 :
Call->Arguments[1];
1008 SPIRV::CLMemoryScope CLScope =
1011 if (Opcode == SPIRV::OpMemoryBarrier)
1013 if (CLScope ==
static_cast<unsigned>(Scope))
1014 ScopeReg =
Call->Arguments[1];
1021 if (Opcode != SPIRV::OpMemoryBarrier)
1023 MIB.
addUse(MemSemanticsReg);
1035 if ((Opcode == SPIRV::OpBitFieldInsert ||
1036 Opcode == SPIRV::OpBitFieldSExtract ||
1037 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1038 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1039 std::string DiagMsg = std::string(Builtin->
name()) +
1040 ": the builtin requires the following SPIR-V "
1041 "extension: SPV_KHR_bit_instructions";
1046 if (
Call->isSpirvOp())
1053 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1065 if (
Call->isSpirvOp())
1082 if (
Call->isSpirvOp())
1089 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1099 if (
Call->isSpirvOp())
1106 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1118 if (
Call->isSpirvOp())
1124 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1134 case SPIRV::OpCommitReadPipe:
1135 case SPIRV::OpCommitWritePipe:
1137 case SPIRV::OpGroupCommitReadPipe:
1138 case SPIRV::OpGroupCommitWritePipe:
1139 case SPIRV::OpGroupReserveReadPipePackets:
1140 case SPIRV::OpGroupReserveWritePipePackets: {
1144 MRI->setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1148 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1149 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1153 MIB.
addUse(ScopeConstReg);
1154 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1167 case SPIRV::Dim::DIM_1D:
1168 case SPIRV::Dim::DIM_Buffer:
1170 case SPIRV::Dim::DIM_2D:
1171 case SPIRV::Dim::DIM_Cube:
1172 case SPIRV::Dim::DIM_Rect:
1174 case SPIRV::Dim::DIM_3D:
1187 return arrayed ? numComps + 1 : numComps;
1191 switch (BuiltinNumber) {
1192 case SPIRV::OpenCLExtInst::s_min:
1193 case SPIRV::OpenCLExtInst::u_min:
1194 case SPIRV::OpenCLExtInst::s_max:
1195 case SPIRV::OpenCLExtInst::u_max:
1196 case SPIRV::OpenCLExtInst::fmax:
1197 case SPIRV::OpenCLExtInst::fmin:
1198 case SPIRV::OpenCLExtInst::fmax_common:
1199 case SPIRV::OpenCLExtInst::fmin_common:
1200 case SPIRV::OpenCLExtInst::s_clamp:
1201 case SPIRV::OpenCLExtInst::fclamp:
1202 case SPIRV::OpenCLExtInst::u_clamp:
1203 case SPIRV::OpenCLExtInst::mix:
1204 case SPIRV::OpenCLExtInst::step:
1205 case SPIRV::OpenCLExtInst::smoothstep:
1206 case SPIRV::OpenCLExtInst::ldexp:
1207 case SPIRV::OpenCLExtInst::pown:
1208 case SPIRV::OpenCLExtInst::rootn:
1225 unsigned ResultElementCount =
1227 bool MayNeedPromotionToVec =
1230 if (!MayNeedPromotionToVec)
1231 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1238 ArgumentType !=
Call->ReturnType) {
1240 ArgumentType, ResultElementCount, MIRBuilder,
true);
1243 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1246 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1260 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1267 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1268 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1269 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1271 ? SPIRV::OpenCLExtInst::fmin
1272 : SPIRV::OpenCLExtInst::fmax;
1277 if (
Number == SPIRV::OpenCLExtInst::prefetch &&
Call->Arguments.size() >= 2) {
1280 if (PtrTy && PtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR) {
1284 assert(SizeTy &&
"Expected a type for the number of elements");
1290 if (ElemBytes > 1) {
1294 MRI->createGenericVirtualRegister(
MRI->getType(NumElems));
1304 MIRBuilder.
buildInstr(SPIRV::OpUntypedPrefetchKHR)
1316 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1317 Number == SPIRV::OpenCLExtInst::fma) {
1325 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1328 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1336 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1337 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1346 if (ST.isKernel() ||
1347 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1353 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1357 AddNoNan = AddNoNan && ArgTest &
fcNan;
1358 AddNoInf = AddNoInf && ArgTest &
fcInf;
1376 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1380 std::tie(CompareRegister, RelationType) =
1386 Call->Arguments.end());
1387 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1416 Call->ReturnType, GR);
1424 SPIRV::lookupGroupBuiltin(Builtin->
name());
1427 if (
Call->isSpirvOp()) {
1430 if (GroupBuiltin->
Opcode ==
1431 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1432 Call->Arguments.size() > 4)
1441 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1443 "Group Operation parameter must be an integer constant");
1444 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1451 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1464 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1465 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1469 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1471 MRI->setRegClass(Arg0, &SPIRV::iIDRegClass);
1478 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1490 const bool HasBoolReturnTy =
1495 if (HasBoolReturnTy)
1496 std::tie(GroupResultRegister, GroupResultType) =
1500 ? SPIRV::Scope::Subgroup
1501 : SPIRV::Scope::Workgroup;
1505 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1506 Call->Arguments.size() > 2) {
1514 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1516 unsigned VecLen =
Call->Arguments.size() - 1;
1517 VecReg =
MRI->createGenericVirtualRegister(
1519 MRI->setRegClass(VecReg, &SPIRV::viIDRegClass);
1525 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1526 MIB.addUse(
Call->Arguments[i]);
1535 .
addDef(GroupResultRegister)
1541 if (
Call->Arguments.size() > 0) {
1542 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1547 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1548 MIB.addUse(
Call->Arguments[i]);
1552 if (HasBoolReturnTy)
1554 Call->ReturnType, GR);
1565 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1567 if (IntelSubgroups->
IsMedia &&
1568 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1569 std::string DiagMsg = std::string(Builtin->
name()) +
1570 ": the builtin requires the following SPIR-V "
1571 "extension: SPV_INTEL_media_block_io";
1573 }
else if (!IntelSubgroups->
IsMedia &&
1574 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1575 std::string DiagMsg = std::string(Builtin->
name()) +
1576 ": the builtin requires the following SPIR-V "
1577 "extension: SPV_INTEL_subgroups";
1582 if (
Call->isSpirvOp()) {
1583 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1584 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1585 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1591 if (IntelSubgroups->
IsBlock) {
1594 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1600 case SPIRV::OpSubgroupBlockReadINTEL:
1601 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1603 case SPIRV::OpSubgroupBlockWriteINTEL:
1604 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1627 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1638 if (!ST->canUseExtension(
1639 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1640 std::string DiagMsg = std::string(Builtin->
name()) +
1641 ": the builtin requires the following SPIR-V "
1642 "extension: SPV_KHR_uniform_group_instructions";
1646 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1656 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1658 "expect a constant group operation for a uniform group instruction",
1661 if (!ConstOperand.
isCImm())
1671 MIB.addUse(ValueReg);
1682 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1683 std::string DiagMsg = std::string(Builtin->
name()) +
1684 ": the builtin requires the following SPIR-V "
1685 "extension: SPV_KHR_shader_clock";
1691 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1698 SPIRV::Scope::Scope ScopeArg =
1700 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1701 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1702 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1743 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1746 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1757 bool IsConstantIndex =
1758 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1764 if (PointerSize != ResultWidth) {
1765 DefaultReg =
MRI->createGenericVirtualRegister(
LLT::scalar(PointerSize));
1766 MRI->setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1768 MIRBuilder.
getMF());
1769 ToTruncate = DefaultReg;
1773 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1782 if (!IsConstantIndex || PointerSize != ResultWidth) {
1783 Extracted =
MRI->createGenericVirtualRegister(
LLT::scalar(PointerSize));
1784 MRI->setRegClass(Extracted, &SPIRV::iIDRegClass);
1791 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1794 if (!IsConstantIndex) {
1802 MRI->setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1817 if (PointerSize != ResultWidth) {
1820 MRI->setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1822 MIRBuilder.
getMF());
1825 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1827 ToTruncate = SelectionResult;
1829 ToTruncate = Extracted;
1833 if (PointerSize != ResultWidth)
1843 SPIRV::BuiltIn::BuiltIn
Value =
1844 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1846 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1859 LLType,
Call->ReturnRegister);
1868 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1871 case SPIRV::OpStore:
1873 case SPIRV::OpAtomicLoad:
1875 case SPIRV::OpAtomicStore:
1877 case SPIRV::OpAtomicCompareExchange:
1878 case SPIRV::OpAtomicCompareExchangeWeak:
1881 case SPIRV::OpAtomicIAdd:
1882 case SPIRV::OpAtomicISub:
1883 case SPIRV::OpAtomicOr:
1884 case SPIRV::OpAtomicXor:
1885 case SPIRV::OpAtomicAnd:
1886 case SPIRV::OpAtomicExchange:
1887 case SPIRV::OpAtomicSMax:
1888 case SPIRV::OpAtomicSMin:
1889 case SPIRV::OpAtomicUMax:
1890 case SPIRV::OpAtomicUMin:
1891 case SPIRV::OpAtomicFMinEXT:
1892 case SPIRV::OpAtomicFMaxEXT:
1894 case SPIRV::OpMemoryBarrier:
1896 case SPIRV::OpAtomicFlagTestAndSet:
1897 case SPIRV::OpAtomicFlagClear:
1900 if (
Call->isSpirvOp())
1912 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1915 case SPIRV::OpAtomicFAddEXT:
1916 case SPIRV::OpAtomicFMinEXT:
1917 case SPIRV::OpAtomicFMaxEXT:
1930 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1941 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1943 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1944 SPIRV::StorageClass::StorageClass ResSC =
1954 }
else if (Opcode == SPIRV::OpGenericPtrMemSemantics) {
1956 SPIRV::StorageClass::Generic)
1964 MRI->createGenericVirtualRegister(
MRI->getType(
Call->ReturnRegister));
1978 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1989 if (
Call->isSpirvOp())
1995 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1996 bool IsSwapReq =
false;
2001 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) &&
2004 ": the builtin requires the following SPIR-V "
2005 "extension: SPV_KHR_integer_dot_product",
2009 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
2019 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
2020 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
2022 if (
Call->BuiltinName ==
"dot") {
2023 if (IsFirstSigned && IsSecondSigned)
2025 else if (!IsFirstSigned && !IsSecondSigned)
2028 OC = SPIRV::OpSUDot;
2032 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
2033 if (IsFirstSigned && IsSecondSigned)
2034 OC = SPIRV::OpSDotAccSat;
2035 else if (!IsFirstSigned && !IsSecondSigned)
2036 OC = SPIRV::OpUDotAccSat;
2038 OC = SPIRV::OpSUDotAccSat;
2054 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
2057 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
2063 if (!IsVec && OC != SPIRV::OpFMulS)
2064 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
2073 SPIRV::BuiltIn::BuiltIn
Value =
2074 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
2077 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
2081 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
2082 false, std::nullopt);
2093 Register ResReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2095 MRI->setRegClass(ResReg, DstRC);
2096 MRI->setType(ResReg,
MRI->getType(Op1Reg));
2112 const Value *SRetArg,
2119 ElemTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2135 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2142 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2144 "overflow builtins");
2148 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2152 case SPIRV::OpIAddCarryS:
2153 Opcode = SPIRV::OpIAddCarryV;
2155 case SPIRV::OpISubBorrowS:
2156 Opcode = SPIRV::OpISubBorrowV;
2161 RetType, MIRBuilder, GR);
2183 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2184 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2185 "Expected OpUMulExtended or OpSMulExtended");
2188 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2200 RetType =
Call->ReturnType;
2203 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2205 "multiplication builtins");
2208 "extended multiplication builtins");
2213 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2218 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2220 if (OpType1 != Member0Type)
2230 MRI->setRegClass(ResReg, DstRC);
2247 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2261 SPIRV::BuiltIn::BuiltIn
Value =
2262 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2263 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2264 Value == SPIRV::BuiltIn::NumWorkgroups ||
2265 Value == SPIRV::BuiltIn::WorkgroupSize ||
2266 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2276 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2280 unsigned NumExpectedRetComponents =
2287 if (NumExpectedRetComponents != NumActualRetComponents) {
2288 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2289 ?
Call->ReturnType->getOperand(1).getImm()
2296 IntTy, NumActualRetComponents, MIRBuilder,
true);
2301 bool UseQuerySize = IsDimBuf || IsMultisampled;
2303 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2310 if (NumExpectedRetComponents == NumActualRetComponents)
2312 if (NumExpectedRetComponents == 1) {
2314 unsigned ExtractedComposite =
2315 Component == 3 ? NumActualRetComponents - 1 : Component;
2316 assert(ExtractedComposite < NumActualRetComponents &&
2317 "Invalid composite index!");
2323 if (TypeReg != NewTypeReg)
2324 TypeReg = NewTypeReg;
2328 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2332 .
addImm(ExtractedComposite);
2338 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2343 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2344 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2352 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2353 "Image samples query result must be of int type!");
2358 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2361 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2363 (void)ImageDimensionality;
2366 case SPIRV::OpImageQuerySamples:
2367 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2368 "Image must be of 2D dimensionality");
2370 case SPIRV::OpImageQueryLevels:
2371 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2372 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2373 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2374 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2375 "Image must be of 1D/2D/3D/Cube dimensionality");
2387static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2389 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2390 case SPIRV::CLK_ADDRESS_CLAMP:
2391 return SPIRV::SamplerAddressingMode::Clamp;
2392 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2393 return SPIRV::SamplerAddressingMode::ClampToEdge;
2394 case SPIRV::CLK_ADDRESS_REPEAT:
2395 return SPIRV::SamplerAddressingMode::Repeat;
2396 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2397 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2398 case SPIRV::CLK_ADDRESS_NONE:
2399 return SPIRV::SamplerAddressingMode::None;
2406 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2409static SPIRV::SamplerFilterMode::SamplerFilterMode
2411 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2412 return SPIRV::SamplerFilterMode::Linear;
2413 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2414 return SPIRV::SamplerFilterMode::Nearest;
2415 return SPIRV::SamplerFilterMode::Nearest;
2422 if (
Call->isSpirvOp())
2429 if (HasOclSampler) {
2443 Register SampledImage =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2458 MRI->createGenericVirtualRegister(GR->
getRegType(TempType));
2461 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2466 .
addImm(SPIRV::ImageOperand::Lod)
2468 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2474 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2479 .
addImm(SPIRV::ImageOperand::Lod)
2482 }
else if (HasMsaa) {
2488 .
addImm(SPIRV::ImageOperand::Sample)
2503 if (
Call->isSpirvOp())
2518 if (
Call->Builtin->name().contains_insensitive(
2519 "__translate_sampler_initializer")) {
2527 }
else if (
Call->Builtin->name().contains_insensitive(
2528 "__spirv_SampledImage")) {
2535 Call->ReturnRegister.isValid()
2536 ?
Call->ReturnRegister
2537 :
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2544 }
else if (
Call->Builtin->name().contains_insensitive(
2545 "__spirv_ImageSampleExplicitLod")) {
2547 std::string ReturnType = DemangledCall.
str();
2548 if (DemangledCall.
contains(
"_R")) {
2549 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2550 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2555 ReturnType, MIRBuilder,
true));
2557 std::string DiagMsg =
2558 "Unable to recognize SPIRV type name: " + ReturnType;
2561 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2566 .
addImm(SPIRV::ImageOperand::Lod)
2576 LLT ResTy =
MRI->getType(
Call->ReturnRegister);
2577 LLT CondTy =
MRI->getType(
Call->Arguments[0]);
2578 if (!ResTy.
isVector() && CondTy.isVector())
2580 "boolean condition");
2582 Call->Arguments[1],
Call->Arguments[2]);
2590 SPIRV::OpCompositeConstructContinuedINTEL,
2591 Call->Arguments,
Call->ReturnRegister,
2601 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2602 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2603 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2604 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2605 unsigned ArgSz =
Call->Arguments.size();
2606 unsigned LiteralIdx = 0;
2609 case SPIRV::OpCooperativeMatrixLoadKHR:
2610 LiteralIdx = ArgSz > 3 ? 3 : 0;
2612 case SPIRV::OpCooperativeMatrixStoreKHR:
2613 LiteralIdx = ArgSz > 4 ? 4 : 0;
2615 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2616 LiteralIdx = ArgSz > 7 ? 7 : 0;
2618 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2619 LiteralIdx = ArgSz > 8 ? 8 : 0;
2622 case SPIRV::OpCooperativeMatrixMulAddKHR:
2623 LiteralIdx = ArgSz > 3 ? 3 : 0;
2629 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2631 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2648 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2659 IsSet ? TypeReg :
Register(0), ImmArgs);
2668 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2672 case SPIRV::OpSpecConstant: {
2677 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2678 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2679 "Argument should be either an int or floating-point constant");
2682 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2683 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2685 ? SPIRV::OpSpecConstantTrue
2686 : SPIRV::OpSpecConstantFalse;
2692 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2693 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2705 case SPIRV::OpSpecConstantComposite: {
2707 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2708 Call->Arguments,
Call->ReturnRegister,
2723 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2734 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2744 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2758 const LLT ValTy =
MRI->getType(InputReg);
2759 Register ActualRetValReg =
MRI->createGenericVirtualRegister(ValTy);
2762 InputReg =
Call->Arguments[1];
2765 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2766 LLT InputLLT =
MRI->getType(InputReg);
2767 PtrInputReg =
MRI->createGenericVirtualRegister(InputLLT);
2773 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2774 MRI->setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2778 for (
unsigned index = 2; index < 7; index++) {
2797 MRI->setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2798 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2801 for (
unsigned index = 1; index < 6; index++)
2815 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2827 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2837 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2848 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2858 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2860 unsigned Scope = SPIRV::Scope::Workgroup;
2862 Scope = SPIRV::Scope::Subgroup;
2872 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2874 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2875 unsigned ArgSz =
Call->Arguments.size();
2884 IsSet ? TypeReg :
Register(0), ImmArgs);
2909 const unsigned NumCallArgs =
Call->Arguments.size();
2910 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2911 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2914 bool HasSRetArg = RetTy->
isVoidTy();
2916 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2917 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2918 const unsigned MaxNDRangeArgs = 3;
2919 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2921 const unsigned GlobalWorkSizeArgIdx =
2922 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2923 const unsigned LocalWorkSizeArgIdx =
2924 (NumNDRangeArgs == 1)
2926 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2927 const unsigned GlobalWorkOffsetArgIdx =
2928 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2933 assert(AddressModelBits == 64 || AddressModelBits == 32);
2937 unsigned Dimension = 0;
2938 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2939 assert(Dimension <= 3 && Dimension >= 1);
2946 if (Dimension == 1) {
2949 "Expected scalar integer type");
2951 if (NumNDRangeArgs < MaxNDRangeArgs)
2958 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2960 if (NumNDRangeArgs < MaxNDRangeArgs) {
2966 SpvFieldTy, *ST.getInstrInfo());
2972 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2973 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2981 "Only pointer types are supported for loading values");
2985 Reg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2995 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2996 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2997 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
3000 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
3005 .
addUse(GlobalWorkOffset);
3014 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
3022 .
addUse(GlobalWorkOffset);
3040 MRI->setRegClass(InvokeReg, &SPIRV::pIDRegClass);
3045 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3052 .
addUse(BlockLiteralReg);
3063 bool HasNDRange =
Call->Builtin->name().contains(
"_ndrange_impl");
3064 unsigned InvokeIdx = HasNDRange ? 1 : 0;
3065 Register InvokeReg, ParamReg, ParamSizeReg, ParamAlignReg;
3067 InvokeReg, ParamReg, ParamSizeReg, ParamAlignReg);
3105 bool IsSpirvOp =
Call->isSpirvOp();
3106 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
3107 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
3109 const unsigned NumArgs =
Call->Arguments.size();
3110 const unsigned BaseArgIdx = 0;
3111 const unsigned IncorrectIdx = NumArgs + 1;
3113 const unsigned QueueIdx = BaseArgIdx;
3114 const unsigned FlagsIdx = BaseArgIdx + 1;
3115 const unsigned NDRangeIdx = BaseArgIdx + 2;
3116 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
3117 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
3118 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
3119 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
3120 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
3121 const unsigned LocalSizeNumElemIdx =
3122 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
3123 const unsigned LocalSizeElemPtrIdx =
3124 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
3126 [[maybe_unused]]
const unsigned LastArgIdx =
3127 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
3128 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
3134 auto BuildDeviceEventNullPtr = [&]() {
3138 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
3146 auto IsNullEvent = [&](
Register R) {
3148 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3149 Def->getOperand(1).getCImm()->isZero();
3152 NumEventsReg =
Call->Arguments[NumEventsIdx];
3153 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
3154 RetEventReg =
Call->Arguments[RetEventIdx];
3155 if (IsNullEvent(WaitEventsReg))
3156 WaitEventsReg = BuildDeviceEventNullPtr();
3157 if (IsNullEvent(RetEventReg))
3158 RetEventReg = BuildDeviceEventNullPtr();
3161 Register NullPtr = BuildDeviceEventNullPtr();
3162 WaitEventsReg = NullPtr;
3163 RetEventReg = NullPtr;
3166 Register InvokeReg, ParamReg, ParamSizeReg, ParamAlignReg;
3168 InvokeReg, ParamReg, ParamSizeReg, ParamAlignReg);
3173 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3174 MachineInstr *LocalSizeNumElemMI =
MRI->getUniqueVRegDef(LocalSizeNumElem);
3177 ConstOp.
isCImm() &&
"Expected constant immediate");
3180 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3183 bool IsArrayPtr = PointeeTy && PointeeTy->
getOpcode() == SPIRV::OpTypeArray;
3185 for (
unsigned i = 0; i < NumElem; ++i) {
3191 .
addUse(LocalSizeArrayReg);
3200 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3213 for (
auto &LocalSize : LocalSizes)
3225 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3228 case SPIRV::OpRetainEvent:
3229 case SPIRV::OpReleaseEvent:
3231 case SPIRV::OpCreateUserEvent:
3232 case SPIRV::OpGetDefaultQueue:
3236 case SPIRV::OpIsValidEvent:
3241 case SPIRV::OpSetUserEventStatus:
3245 case SPIRV::OpCaptureEventProfilingInfo:
3250 case SPIRV::OpBuildNDRange:
3252 case SPIRV::OpEnqueueKernel:
3254 case SPIRV::OpGetKernelNDrangeSubGroupCount:
3255 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
3256 case SPIRV::OpGetKernelWorkGroupSize:
3257 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
3270 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3272 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3274 if (
Call->isSpirvOp())
3281 case SPIRV::OpGroupAsyncCopy: {
3283 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3287 unsigned NumArgs =
Call->Arguments.size();
3290 if (!EventType || EventType->
getOpcode() != SPIRV::OpTypeEvent) {
3295 EventType && EventType->
getOpcode() == SPIRV::OpTypePointer
3298 if (Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3299 Def->getOperand(1).getCImm()->isZero()) {
3304 "spirv.Event", MIRBuilder,
true);
3310 EventReg = NullEventReg;
3311 }
else if (EventPointeeType &&
3312 EventPointeeType->
getOpcode() == SPIRV::OpTypeEvent) {
3323 EventReg = LoadedReg;
3332 DestPtrTy && DestPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR;
3335 Call->Arguments.size() > 4
3336 ?
Call->Arguments[3]
3341 auto MIB = MIRBuilder
3342 .
buildInstr(IsUntyped ? SPIRV::OpUntypedGroupAsyncCopyKHR
3343 : SPIRV::OpGroupAsyncCopy)
3356 "async copy pointer argument");
3368 case SPIRV::OpGroupWaitEvents:
3382 if (Opcode != SPIRV::OpSConvert && Opcode != SPIRV::OpUConvert &&
3383 Opcode != SPIRV::OpFConvert)
3385 if (
Call->Arguments.size() != 1 ||
3398 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3400 if (!Builtin &&
Call->isSpirvOp()) {
3403 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3410 assert(Builtin &&
"Conversion builtin not found.");
3412 std::string NeedExtMsg;
3413 bool IsRightComponentsNumber =
true;
3414 unsigned Opcode = SPIRV::OpNop;
3417 bool IsSourceSigned =
3423 : SPIRV::OpSatConvertSToU;
3425 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3427 SPIRV::OpTypeFloat)) {
3431 &MIRBuilder.
getMF().getSubtarget());
3432 if (!ST->canUseExtension(
3433 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3434 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3435 IsRightComponentsNumber =
3438 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3440 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3444 SPIRV::OpTypeFloat)) {
3450 &MIRBuilder.
getMF().getSubtarget());
3451 if (!ST->canUseExtension(
3452 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3453 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3454 IsRightComponentsNumber =
3457 Opcode = SPIRV::OpConvertFToBF16INTEL;
3460 : SPIRV::OpConvertFToU;
3463 SPIRV::OpTypeFloat)) {
3466 &MIRBuilder.
getMF().getSubtarget());
3467 if (!ST->canUseExtension(
3468 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3469 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3470 IsRightComponentsNumber =
3473 Opcode = SPIRV::OpRoundFToTF32INTEL;
3476 Opcode = SPIRV::OpFConvert;
3481 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3482 if (!NeedExtMsg.empty()) {
3483 std::string DiagMsg = std::string(BuiltinName) +
3484 ": the builtin requires the following SPIR-V "
3489 if (!IsRightComponentsNumber) {
3490 std::string DiagMsg =
3491 std::string(BuiltinName) +
3492 ": result and argument must have the same number of components";
3495 assert(Opcode != SPIRV::OpNop &&
3496 "Conversion between the types not implemented!");
3504 SPIRV::Decoration::SaturatedConversion, {});
3507 bool AnyTypeIsFloat =
3514 if (AnyTypeIsFloat) {
3516 SPIRV::Decoration::FPRoundingMode,
3517 {(unsigned)Builtin->RoundingMode});
3533 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->name(),
3534 Call->Builtin->Set);
3540 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3544 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3558 const auto *Builtin =
Call->Builtin;
3561 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3567 LLT PtrTy =
MRI->getType(
Call->Arguments[0]);
3568 DestReg =
MRI->createGenericVirtualRegister(PtrTy);
3569 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3572 MIB.addDef(DestReg);
3575 MIB.addDef(
Call->ReturnRegister);
3578 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3581 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3582 DefMI->getOperand(1).isCImm()) {
3589 LLT PtrTy =
MRI->getType(
Call->Arguments[0]);
3604 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3605 bool IsLoad = Opcode == SPIRV::OpLoad;
3609 MIB.addDef(
Call->ReturnRegister);
3617 MIB.addUse(
Call->Arguments[1]);
3619 unsigned NumArgs =
Call->Arguments.size();
3620 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3622 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3635std::tuple<int, unsigned, unsigned>
3637 SPIRV::InstructionSet::InstructionSet Set) {
3640 std::unique_ptr<const IncomingCall>
Call =
3643 return std::make_tuple(-1, 0, 0);
3645 switch (
Call->Builtin->Group) {
3646 case SPIRV::Relational:
3648 case SPIRV::Barrier:
3649 case SPIRV::CastToPtr:
3650 case SPIRV::ImageMiscQuery:
3651 case SPIRV::SpecConstant:
3652 case SPIRV::Enqueue:
3653 case SPIRV::AsyncCopy:
3654 case SPIRV::LoadStore:
3655 case SPIRV::CoopMatr:
3656 case SPIRV::Arithmetic:
3657 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3658 Call->Builtin->Set))
3659 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3661 case SPIRV::Extended:
3662 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3663 Call->Builtin->Set))
3664 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3666 case SPIRV::VectorLoadStore:
3667 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3668 Call->Builtin->name(),
Call->Builtin->Set))
3669 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3672 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3673 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3675 case SPIRV::AtomicFloating:
3677 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3678 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3680 case SPIRV::IntelSubgroups:
3682 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3683 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3685 case SPIRV::GroupUniform:
3686 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3687 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3689 case SPIRV::IntegerDot:
3691 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3692 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3694 case SPIRV::WriteImage:
3695 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3697 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3698 case SPIRV::Construct:
3699 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3701 case SPIRV::KernelClock:
3702 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3704 return std::make_tuple(-1, 0, 0);
3706 return std::make_tuple(-1, 0, 0);
3710 SPIRV::InstructionSet::InstructionSet Set) {
3727 if (
Call->isSpirvOp())
3735 if (
Call->Arguments.size() < ArgBase)
3737 unsigned NumMangledArgs =
Call->Arguments.size() - ArgBase;
3738 unsigned NumArgsToCheck =
3739 std::min<unsigned>(NumMangledArgs, ArgTypeStrs.
size());
3740 for (
unsigned ArgIdx = 0; ArgIdx < NumArgsToCheck; ++ArgIdx) {
3741 StringRef ArgTypeStr = ArgTypeStrs[ArgIdx].trim();
3750 if (!ExpectedType || ExpectedType->
isVoidTy() ||
3758 unsigned ArgTypeOpcode = ArgType->
getOpcode();
3759 if (ArgTypeOpcode != SPIRV::OpTypeInt &&
3760 ArgTypeOpcode != SPIRV::OpTypeFloat &&
3761 ArgTypeOpcode != SPIRV::OpTypeBool &&
3762 ArgTypeOpcode != SPIRV::OpTypeVector)
3766 Type *ExpectedScalarType =
3767 ExpectedVecType ? ExpectedVecType->getElementType() : ExpectedType;
3772 bool ExpectedIsInt = ExpectedScalarType->
isIntegerTy();
3773 unsigned ArgOpcode = ArgScalarType->
getOpcode();
3775 ArgOpcode == SPIRV::OpTypeInt || ArgOpcode == SPIRV::OpTypeBool;
3777 if (ExpectedIsInt != ArgIsInt)
3780 unsigned ExpectedElts =
3781 ExpectedVecType ? ExpectedVecType->getElementCount().getFixedValue()
3790 SPIRV::InstructionSet::InstructionSet Set,
3795 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3799 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3800 std::unique_ptr<const IncomingCall>
Call =
3805 return std::nullopt;
3810 if (Args.size() <
Call->Builtin->MinNumArgs) {
3811 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3812 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3813 <<
", got " << Args.size()
3814 <<
"; treating as a normal function\n");
3815 return std::nullopt;
3817 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3818 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3819 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3820 <<
", got " << Args.size()
3821 <<
"; treating as a normal function\n");
3822 return std::nullopt;
3830 LLVM_DEBUG(
dbgs() <<
"Argument types do not match mangled types for "
3831 <<
"builtin " << DemangledCall
3832 <<
"; treating as a normal function\n");
3833 return std::nullopt;
3837 switch (
Call->Builtin->Group) {
3838 case SPIRV::Extended:
3840 case SPIRV::Relational:
3844 case SPIRV::Variable:
3848 case SPIRV::AtomicFloating:
3850 case SPIRV::Barrier:
3852 case SPIRV::CastToPtr:
3855 case SPIRV::IntegerDot:
3859 case SPIRV::ICarryBorrow:
3861 case SPIRV::MulExtended:
3863 case SPIRV::Arithmetic:
3865 case SPIRV::GetQuery:
3867 case SPIRV::ImageSizeQuery:
3869 case SPIRV::ImageMiscQuery:
3871 case SPIRV::ReadImage:
3873 case SPIRV::WriteImage:
3875 case SPIRV::SampleImage:
3879 case SPIRV::Construct:
3881 case SPIRV::SpecConstant:
3883 case SPIRV::Enqueue:
3885 case SPIRV::AsyncCopy:
3887 case SPIRV::Convert:
3889 case SPIRV::VectorLoadStore:
3891 case SPIRV::LoadStore:
3893 case SPIRV::IntelSubgroups:
3895 case SPIRV::GroupUniform:
3897 case SPIRV::KernelClock:
3899 case SPIRV::CoopMatr:
3901 case SPIRV::ExtendedBitOps:
3903 case SPIRV::BindlessINTEL:
3905 case SPIRV::TernaryBitwiseINTEL:
3907 case SPIRV::Block2DLoadStore:
3911 case SPIRV::PredicatedLoadStore:
3913 case SPIRV::BlockingPipes:
3915 case SPIRV::ArbitraryPrecisionFixedPoint:
3917 case SPIRV::ImageChannelDataTypes:
3919 case SPIRV::ArbitraryFloatingPoint:
3930 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3931 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3948 unsigned VecElts = 0;
3959 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3971 auto Pos1 = DemangledCall.
find(
'(');
3974 auto Pos2 = DemangledCall.
find(
')');
3977 DemangledCall.
slice(Pos1 + 1, Pos2)
3978 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3986 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3988 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3997#define GET_BuiltinTypes_DECL
3998#define GET_BuiltinTypes_IMPL
4005#define GET_OpenCLTypes_DECL
4006#define GET_OpenCLTypes_IMPL
4008#include "SPIRVGenTables.inc"
4016 if (Name.starts_with(
"void"))
4018 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
4020 else if (Name.starts_with(
"bfloat"))
4022 else if (Name.starts_with(
"float"))
4024 else if (Name.starts_with(
"half"))
4026 else if (Name.starts_with(
"double"))
4039 unsigned Opcode = TypeRecord->
Opcode;
4054 "Invalid number of parameters for SPIR-V pipe builtin!");
4057 SPIRV::AccessQualifier::AccessQualifier(
4065 "Invalid number of parameters for SPIR-V coop matrices builtin!");
4067 "SPIR-V coop matrices builtin type must have a type parameter!");
4070 SPIRV::AccessQualifier::ReadWrite,
true);
4073 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
4082 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
4091 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
4098 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
4099 assert(ParamEType->getNumTypeParameters() == 1 &&
4100 "Inline SPIR-V integral constant builtin must have a type "
4102 assert(ParamEType->getNumIntParameters() == 1 &&
4103 "Inline SPIR-V integral constant builtin must have a "
4106 auto OperandValue = ParamEType->getIntParameter(0);
4107 auto *OperandType = ParamEType->getTypeParameter(0);
4110 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
4113 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
4115 }
else if (ParamEType->getName() ==
"spirv.Literal") {
4116 assert(ParamEType->getNumTypeParameters() == 0 &&
4117 "Inline SPIR-V literal builtin does not take type "
4119 assert(ParamEType->getNumIntParameters() == 1 &&
4120 "Inline SPIR-V literal builtin must have an integer "
4123 auto OperandValue = ParamEType->getIntParameter(0);
4130 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
4142 "Vulkan buffers have exactly one type for the type of the buffer.");
4144 "Vulkan buffer have 2 integer parameters: storage class and is "
4148 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
4159 "Vulkan push constants have exactly one type as argument.");
4173 StringRef NameWithParameters = TypeName;
4180 SPIRV::lookupOpenCLType(NameWithParameters);
4183 NameWithParameters);
4184 NameWithParameters =
4192 "Unknown builtin opaque type!");
4196 if (!NameWithParameters.
contains(
'_'))
4200 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
4204 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
4205 if (HasTypeParameter)
4208 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
4209 unsigned IntParameter = 0;
4210 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
4213 "Invalid format of SPIR-V builtin parameter literal!");
4217 NameWithParameters.
substr(0, BaseNameLength),
4218 TypeParameters, IntParameters);
4223 SPIRV::AccessQualifier::AccessQualifier AccessQual,
4244 if (Name ==
"spirv.Type") {
4246 }
else if (Name ==
"spirv.VulkanBuffer") {
4248 }
else if (Name ==
"spirv.Padding") {
4250 }
else if (Name ==
"spirv.PushConstant") {
4252 }
else if (Name ==
"spirv.Layout") {
4266 switch (TypeRecord->
Opcode) {
4267 case SPIRV::OpTypeImage:
4270 case SPIRV::OpTypePipe:
4273 case SPIRV::OpTypeDeviceEvent:
4276 case SPIRV::OpTypeSampler:
4279 case SPIRV::OpTypeSampledImage:
4282 case SPIRV::OpTypeCooperativeMatrixKHR:
4304 return Builtin->
Group == Pipe || Builtin->
Group == CastToPtr ||
4305 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
MachineRegisterInfo & MRI
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.
Diagnostic information for unsupported feature in backend.
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.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
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...
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.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
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
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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.
bool isBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)
Whether lowerBuiltin() recognizes DemangledCall in Set.
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.
uint32_t getMemSemanticsWithStorageClass(const Triple &TT, uint32_t OrderSem, uint32_t StorageClassSem)
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 buildKernelQuery(const SPIRV::IncomingCall *Call, unsigned Opcode, 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)
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
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)
bool isVectorType(SPIRVTypeInst SPVTy)
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 bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool foldNoOpConvert(unsigned Opcode, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRV::MemorySemantics::MemorySemantics getMemOrdering(Register OrderRegister, MachineRegisterInfo *MRI)
Translates an OpenCL memory_order argument into the memory ordering part of the SPIR-V memory semanti...
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 Register buildMemSemanticsReg(SPIRV::MemorySemantics::MemorySemantics Ordering, unsigned StorageClassSem, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Combines the memory ordering with the storage-class part of the memory semantics into a constant regi...
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)
static void buildKernelInvokeOperands(const SPIRV::IncomingCall *Call, unsigned InvokeIdx, unsigned ParamIdx, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, Register &InvokeReg, Register &ParamReg, Register &ParamSizeReg, Register &ParamAlignReg)
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