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>
435 return std::make_tuple(ResultRegister, BoolType);
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);
584static SPIRV::MemorySemantics::MemorySemantics
587 static_cast<std::memory_order
>(
getIConstVal(OrderRegister, MRI)));
611 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
612 for (
unsigned i = 0; i < Sz; ++i)
613 MIB.addUse(
Call->Arguments[i]);
622 if (
Call->isSpirvOp())
626 "Need 2 arguments for atomic init translation");
638 if (
Call->isSpirvOp())
645 const SPIRV::MemorySemantics::MemorySemantics Ordering =
646 Call->Arguments.size() >= 2
648 : SPIRV::MemorySemantics::SequentiallyConsistent;
649 const unsigned StorageClassSem =
656 SPIRV::Scope::Device, MIRBuilder, GR, MRI);
671 if (
Call->isSpirvOp())
678 const SPIRV::MemorySemantics::MemorySemantics Ordering =
679 Call->Arguments.size() >= 3
681 : SPIRV::MemorySemantics::SequentiallyConsistent;
682 const unsigned StorageClassSem =
688 SPIRV::Scope::Device, MIRBuilder, GR, MRI);
701 if (
Call->isSpirvOp())
705 bool IsCmpxchg =
Call->Builtin->name().contains(
"cmpxchg");
722 assert((SpvObjectPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR ||
724 "SPIRV type is expected");
725 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
733 ? SPIRV::MemorySemantics::None
734 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
737 ? SPIRV::MemorySemantics::None
738 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
739 if (
Call->Arguments.size() >= 4) {
741 "Need 5+ args for explicit atomic cmpxchg");
748 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
749 MemSemEqualReg =
Call->Arguments[3];
750 if (
static_cast<unsigned>(MemOrdNeq) == MemSemUnequal)
751 MemSemUnequalReg =
Call->Arguments[4];
755 if (!MemSemUnequalReg.
isValid())
759 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
760 if (
Call->Arguments.size() >= 6) {
762 "Extra args for explicit atomic cmpxchg");
763 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
766 if (ClScope ==
static_cast<unsigned>(Scope))
767 ScopeReg =
Call->Arguments[5];
773 IsCmpxchg ? ExpectedArg
777 :
Call->ReturnRegister;
802 if (
Call->isSpirvOp())
811 "Too many args for explicit atomic RMW");
812 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
813 MIRBuilder, GR, MRI);
816 SPIRV::MemorySemantics::MemorySemantics Ordering =
817 SPIRV::MemorySemantics::None;
818 unsigned StorageClassSem = SPIRV::MemorySemantics::None;
819 if (
Call->Arguments.size() >= 3) {
829 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
830 if (Opcode == SPIRV::OpAtomicIAdd) {
831 Opcode = SPIRV::OpAtomicFAddEXT;
832 }
else if (Opcode == SPIRV::OpAtomicISub) {
835 Opcode = SPIRV::OpAtomicFAddEXT;
846 ValueReg = NegValueReg;
865 "Wrong number of atomic floating-type builtin");
885 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
887 if (
Call->isSpirvOp())
893 SPIRV::MemorySemantics::MemorySemantics Ordering =
894 SPIRV::MemorySemantics::SequentiallyConsistent;
895 unsigned StorageClassSem = SPIRV::MemorySemantics::None;
896 if (
Call->Arguments.size() >= 2) {
902 assert((Opcode != SPIRV::OpAtomicFlagClear ||
903 (Ordering != SPIRV::MemorySemantics::Acquire &&
904 Ordering != SPIRV::MemorySemantics::AcquireRelease)) &&
905 "Invalid memory order argument!");
912 SPIRV::Scope::Device, MIRBuilder, GR, MRI);
930 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
931 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
932 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
933 std::string DiagMsg = std::string(Builtin->
name()) +
934 ": the builtin requires the following SPIR-V "
935 "extension: SPV_INTEL_split_barrier";
939 if (
Call->isSpirvOp())
944 unsigned MemSemantics = SPIRV::MemorySemantics::None;
946 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
947 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
949 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
950 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
952 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
953 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
955 if (Opcode == SPIRV::OpMemoryBarrier)
959 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
960 MemSemantics |= SPIRV::MemorySemantics::Release;
961 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
962 MemSemantics |= SPIRV::MemorySemantics::Acquire;
964 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
967 MemFlags == MemSemantics
971 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
972 SPIRV::Scope::Scope MemScope = Scope;
973 if (
Call->Arguments.size() >= 2) {
975 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
976 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
977 "Extra args for explicitly scoped barrier");
978 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
979 :
Call->Arguments[1];
980 SPIRV::CLMemoryScope CLScope =
981 static_cast<SPIRV::CLMemoryScope
>(
getIConstVal(ScopeArg, MRI));
983 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
984 (Opcode == SPIRV::OpMemoryBarrier))
986 if (CLScope ==
static_cast<unsigned>(Scope))
987 ScopeReg =
Call->Arguments[1];
994 if (Opcode != SPIRV::OpMemoryBarrier)
996 MIB.
addUse(MemSemanticsReg);
1008 if ((Opcode == SPIRV::OpBitFieldInsert ||
1009 Opcode == SPIRV::OpBitFieldSExtract ||
1010 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1011 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1012 std::string DiagMsg = std::string(Builtin->
name()) +
1013 ": the builtin requires the following SPIR-V "
1014 "extension: SPV_KHR_bit_instructions";
1019 if (
Call->isSpirvOp())
1026 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1038 if (
Call->isSpirvOp())
1055 if (
Call->isSpirvOp())
1062 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1072 if (
Call->isSpirvOp())
1079 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1091 if (
Call->isSpirvOp())
1097 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1107 case SPIRV::OpCommitReadPipe:
1108 case SPIRV::OpCommitWritePipe:
1110 case SPIRV::OpGroupCommitReadPipe:
1111 case SPIRV::OpGroupCommitWritePipe:
1112 case SPIRV::OpGroupReserveReadPipePackets:
1113 case SPIRV::OpGroupReserveWritePipePackets: {
1117 MRI->
setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1121 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1122 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1126 MIB.
addUse(ScopeConstReg);
1127 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1140 case SPIRV::Dim::DIM_1D:
1141 case SPIRV::Dim::DIM_Buffer:
1143 case SPIRV::Dim::DIM_2D:
1144 case SPIRV::Dim::DIM_Cube:
1145 case SPIRV::Dim::DIM_Rect:
1147 case SPIRV::Dim::DIM_3D:
1160 return arrayed ? numComps + 1 : numComps;
1164 switch (BuiltinNumber) {
1165 case SPIRV::OpenCLExtInst::s_min:
1166 case SPIRV::OpenCLExtInst::u_min:
1167 case SPIRV::OpenCLExtInst::s_max:
1168 case SPIRV::OpenCLExtInst::u_max:
1169 case SPIRV::OpenCLExtInst::fmax:
1170 case SPIRV::OpenCLExtInst::fmin:
1171 case SPIRV::OpenCLExtInst::fmax_common:
1172 case SPIRV::OpenCLExtInst::fmin_common:
1173 case SPIRV::OpenCLExtInst::s_clamp:
1174 case SPIRV::OpenCLExtInst::fclamp:
1175 case SPIRV::OpenCLExtInst::u_clamp:
1176 case SPIRV::OpenCLExtInst::mix:
1177 case SPIRV::OpenCLExtInst::step:
1178 case SPIRV::OpenCLExtInst::smoothstep:
1179 case SPIRV::OpenCLExtInst::ldexp:
1180 case SPIRV::OpenCLExtInst::pown:
1181 case SPIRV::OpenCLExtInst::rootn:
1198 unsigned ResultElementCount =
1200 bool MayNeedPromotionToVec =
1203 if (!MayNeedPromotionToVec)
1204 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1211 ArgumentType !=
Call->ReturnType) {
1213 ArgumentType, ResultElementCount, MIRBuilder,
true);
1216 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1219 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1233 SPIRV::lookupExtendedBuiltin(Builtin->
name(), Builtin->
Set)->Number;
1240 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1241 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1242 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1244 ? SPIRV::OpenCLExtInst::fmin
1245 : SPIRV::OpenCLExtInst::fmax;
1250 if (
Number == SPIRV::OpenCLExtInst::prefetch &&
Call->Arguments.size() >= 2) {
1253 if (PtrTy && PtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR) {
1257 assert(SizeTy &&
"Expected a type for the number of elements");
1263 if (ElemBytes > 1) {
1277 MIRBuilder.
buildInstr(SPIRV::OpUntypedPrefetchKHR)
1289 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma) &&
1290 Number == SPIRV::OpenCLExtInst::fma) {
1298 MIB = MIRBuilder.
buildInstr(SPIRV::OpExtInst)
1301 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1309 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1310 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1319 if (ST.isKernel() ||
1320 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1326 I !=
E && (AddNoNan || AddNoInf); ++
I) {
1330 AddNoNan = AddNoNan && ArgTest &
fcNan;
1331 AddNoInf = AddNoInf && ArgTest &
fcInf;
1349 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1353 std::tie(CompareRegister, RelationType) =
1359 Call->Arguments.end());
1360 if ((Opcode == SPIRV::OpAny || Opcode == SPIRV::OpAll) &&
1389 Call->ReturnType, GR);
1397 SPIRV::lookupGroupBuiltin(Builtin->
name());
1400 if (
Call->isSpirvOp()) {
1403 if (GroupBuiltin->
Opcode ==
1404 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1405 Call->Arguments.size() > 4)
1414 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1416 "Group Operation parameter must be an integer constant");
1417 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1424 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1437 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1438 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1442 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1451 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1463 const bool HasBoolReturnTy =
1468 if (HasBoolReturnTy)
1469 std::tie(GroupResultRegister, GroupResultType) =
1473 ? SPIRV::Scope::Subgroup
1474 : SPIRV::Scope::Workgroup;
1478 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1479 Call->Arguments.size() > 2) {
1487 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1489 unsigned VecLen =
Call->Arguments.size() - 1;
1498 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1499 MIB.addUse(
Call->Arguments[i]);
1508 .
addDef(GroupResultRegister)
1514 if (
Call->Arguments.size() > 0) {
1515 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1520 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1521 MIB.addUse(
Call->Arguments[i]);
1525 if (HasBoolReturnTy)
1527 Call->ReturnType, GR);
1538 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
name());
1540 if (IntelSubgroups->
IsMedia &&
1541 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1542 std::string DiagMsg = std::string(Builtin->
name()) +
1543 ": the builtin requires the following SPIR-V "
1544 "extension: SPV_INTEL_media_block_io";
1546 }
else if (!IntelSubgroups->
IsMedia &&
1547 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1548 std::string DiagMsg = std::string(Builtin->
name()) +
1549 ": the builtin requires the following SPIR-V "
1550 "extension: SPV_INTEL_subgroups";
1555 if (
Call->isSpirvOp()) {
1556 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1557 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1558 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1564 if (IntelSubgroups->
IsBlock) {
1567 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1573 case SPIRV::OpSubgroupBlockReadINTEL:
1574 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1576 case SPIRV::OpSubgroupBlockWriteINTEL:
1577 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1600 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1611 if (!ST->canUseExtension(
1612 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1613 std::string DiagMsg = std::string(Builtin->
name()) +
1614 ": the builtin requires the following SPIR-V "
1615 "extension: SPV_KHR_uniform_group_instructions";
1619 SPIRV::lookupGroupUniformBuiltin(Builtin->
name());
1629 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1631 "expect a constant group operation for a uniform group instruction",
1634 if (!ConstOperand.
isCImm())
1644 MIB.addUse(ValueReg);
1655 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1656 std::string DiagMsg = std::string(Builtin->
name()) +
1657 ": the builtin requires the following SPIR-V "
1658 "extension: SPV_KHR_shader_clock";
1664 if (Builtin->
name() ==
"__spirv_ReadClockKHR") {
1671 SPIRV::Scope::Scope ScopeArg =
1673 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1674 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1675 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1716 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1719 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1730 bool IsConstantIndex =
1731 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1735 if (IsConstantIndex &&
getIConstVal(IndexRegister, MRI) >= 3) {
1737 if (PointerSize != ResultWidth) {
1739 MRI->
setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1741 MIRBuilder.
getMF());
1742 ToTruncate = DefaultReg;
1746 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1755 if (!IsConstantIndex || PointerSize != ResultWidth) {
1764 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1767 if (!IsConstantIndex) {
1768 updateRegType(Extracted,
nullptr, PointerSizeType, GR, MIRBuilder, *MRI);
1775 MRI->
setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1790 if (PointerSize != ResultWidth) {
1793 MRI->
setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1795 MIRBuilder.
getMF());
1798 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1800 ToTruncate = SelectionResult;
1802 ToTruncate = Extracted;
1806 if (PointerSize != ResultWidth)
1816 SPIRV::BuiltIn::BuiltIn
Value =
1817 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
1819 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1832 LLType,
Call->ReturnRegister);
1841 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1844 case SPIRV::OpStore:
1846 case SPIRV::OpAtomicLoad:
1848 case SPIRV::OpAtomicStore:
1850 case SPIRV::OpAtomicCompareExchange:
1851 case SPIRV::OpAtomicCompareExchangeWeak:
1854 case SPIRV::OpAtomicIAdd:
1855 case SPIRV::OpAtomicISub:
1856 case SPIRV::OpAtomicOr:
1857 case SPIRV::OpAtomicXor:
1858 case SPIRV::OpAtomicAnd:
1859 case SPIRV::OpAtomicExchange:
1860 case SPIRV::OpAtomicSMax:
1861 case SPIRV::OpAtomicSMin:
1862 case SPIRV::OpAtomicUMax:
1863 case SPIRV::OpAtomicUMin:
1865 case SPIRV::OpMemoryBarrier:
1867 case SPIRV::OpAtomicFlagTestAndSet:
1868 case SPIRV::OpAtomicFlagClear:
1871 if (
Call->isSpirvOp())
1883 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
name())->Opcode;
1886 case SPIRV::OpAtomicFAddEXT:
1887 case SPIRV::OpAtomicFMinEXT:
1888 case SPIRV::OpAtomicFMaxEXT:
1901 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1912 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
1914 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1915 SPIRV::StorageClass::StorageClass ResSC =
1926 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1937 if (
Call->isSpirvOp())
1943 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1944 bool IsSwapReq =
false;
1949 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) &&
1952 ": the builtin requires the following SPIR-V "
1953 "extension: SPV_KHR_integer_dot_product",
1957 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
name());
1967 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1968 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1970 if (
Call->BuiltinName ==
"dot") {
1971 if (IsFirstSigned && IsSecondSigned)
1973 else if (!IsFirstSigned && !IsSecondSigned)
1976 OC = SPIRV::OpSUDot;
1980 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1981 if (IsFirstSigned && IsSecondSigned)
1982 OC = SPIRV::OpSDotAccSat;
1983 else if (!IsFirstSigned && !IsSecondSigned)
1984 OC = SPIRV::OpUDotAccSat;
1986 OC = SPIRV::OpSUDotAccSat;
2002 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
2005 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
2011 if (!IsVec && OC != SPIRV::OpFMulS)
2012 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
2021 SPIRV::BuiltIn::BuiltIn
Value =
2022 SPIRV::lookupGetBuiltin(Builtin->
name(), Builtin->
Set)->
Value;
2025 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
2029 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
2030 false, std::nullopt);
2060 const Value *SRetArg,
2067 ElemTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2083 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2090 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
2092 "overflow builtins");
2096 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2100 case SPIRV::OpIAddCarryS:
2101 Opcode = SPIRV::OpIAddCarryV;
2103 case SPIRV::OpISubBorrowS:
2104 Opcode = SPIRV::OpISubBorrowV;
2109 RetType, MIRBuilder, GR);
2131 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2132 assert((Opcode == SPIRV::OpUMulExtended || Opcode == SPIRV::OpSMulExtended) &&
2133 "Expected OpUMulExtended or OpSMulExtended");
2136 !
Call->ReturnType ||
Call->ReturnType->getOpcode() == SPIRV::OpTypeVoid;
2148 RetType =
Call->ReturnType;
2151 if (!RetType || RetType->
getOpcode() != SPIRV::OpTypeStruct)
2153 "multiplication builtins");
2156 "extended multiplication builtins");
2161 if (!Member0Type || !Member1Type || Member0Type != Member1Type)
2166 if (!OpType1 || !OpType2 || OpType1 != OpType2)
2168 if (OpType1 != Member0Type)
2195 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2209 SPIRV::BuiltIn::BuiltIn
Value =
2210 SPIRV::lookupGetBuiltin(
Call->Builtin->name(),
Call->Builtin->Set)->
Value;
2211 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
2212 Value == SPIRV::BuiltIn::NumWorkgroups ||
2213 Value == SPIRV::BuiltIn::WorkgroupSize ||
2214 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2224 SPIRV::lookupImageQueryBuiltin(Builtin->
name(), Builtin->
Set)->Component;
2228 unsigned NumExpectedRetComponents =
2235 if (NumExpectedRetComponents != NumActualRetComponents) {
2236 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2237 ?
Call->ReturnType->getOperand(1).getImm()
2244 IntTy, NumActualRetComponents, MIRBuilder,
true);
2249 bool UseQuerySize = IsDimBuf || IsMultisampled;
2251 UseQuerySize ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2258 if (NumExpectedRetComponents == NumActualRetComponents)
2260 if (NumExpectedRetComponents == 1) {
2262 unsigned ExtractedComposite =
2263 Component == 3 ? NumActualRetComponents - 1 : Component;
2264 assert(ExtractedComposite < NumActualRetComponents &&
2265 "Invalid composite index!");
2271 if (TypeReg != NewTypeReg)
2272 TypeReg = NewTypeReg;
2276 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2280 .
addImm(ExtractedComposite);
2286 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2291 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2292 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2300 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2301 "Image samples query result must be of int type!");
2306 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2309 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2311 (void)ImageDimensionality;
2314 case SPIRV::OpImageQuerySamples:
2315 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2316 "Image must be of 2D dimensionality");
2318 case SPIRV::OpImageQueryLevels:
2319 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2320 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2321 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2322 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2323 "Image must be of 1D/2D/3D/Cube dimensionality");
2335static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2337 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2338 case SPIRV::CLK_ADDRESS_CLAMP:
2339 return SPIRV::SamplerAddressingMode::Clamp;
2340 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2341 return SPIRV::SamplerAddressingMode::ClampToEdge;
2342 case SPIRV::CLK_ADDRESS_REPEAT:
2343 return SPIRV::SamplerAddressingMode::Repeat;
2344 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2345 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2346 case SPIRV::CLK_ADDRESS_NONE:
2347 return SPIRV::SamplerAddressingMode::None;
2354 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2357static SPIRV::SamplerFilterMode::SamplerFilterMode
2359 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2360 return SPIRV::SamplerFilterMode::Linear;
2361 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2362 return SPIRV::SamplerFilterMode::Nearest;
2363 return SPIRV::SamplerFilterMode::Nearest;
2370 if (
Call->isSpirvOp())
2377 if (HasOclSampler) {
2409 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2414 .
addImm(SPIRV::ImageOperand::Lod)
2416 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2422 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2427 .
addImm(SPIRV::ImageOperand::Lod)
2430 }
else if (HasMsaa) {
2436 .
addImm(SPIRV::ImageOperand::Sample)
2451 if (
Call->isSpirvOp())
2466 if (
Call->Builtin->name().contains_insensitive(
2467 "__translate_sampler_initializer")) {
2475 }
else if (
Call->Builtin->name().contains_insensitive(
2476 "__spirv_SampledImage")) {
2483 Call->ReturnRegister.isValid()
2484 ?
Call->ReturnRegister
2492 }
else if (
Call->Builtin->name().contains_insensitive(
2493 "__spirv_ImageSampleExplicitLod")) {
2495 std::string ReturnType = DemangledCall.
str();
2496 if (DemangledCall.
contains(
"_R")) {
2497 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2498 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2503 ReturnType, MIRBuilder,
true));
2505 std::string DiagMsg =
2506 "Unable to recognize SPIRV type name: " + ReturnType;
2509 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2514 .
addImm(SPIRV::ImageOperand::Lod)
2526 if (!ResTy.
isVector() && CondTy.isVector())
2528 "boolean condition");
2530 Call->Arguments[1],
Call->Arguments[2]);
2538 SPIRV::OpCompositeConstructContinuedINTEL,
2539 Call->Arguments,
Call->ReturnRegister,
2549 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2550 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2551 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2552 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2553 unsigned ArgSz =
Call->Arguments.size();
2554 unsigned LiteralIdx = 0;
2557 case SPIRV::OpCooperativeMatrixLoadKHR:
2558 LiteralIdx = ArgSz > 3 ? 3 : 0;
2560 case SPIRV::OpCooperativeMatrixStoreKHR:
2561 LiteralIdx = ArgSz > 4 ? 4 : 0;
2563 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2564 LiteralIdx = ArgSz > 7 ? 7 : 0;
2566 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2567 LiteralIdx = ArgSz > 8 ? 8 : 0;
2570 case SPIRV::OpCooperativeMatrixMulAddKHR:
2571 LiteralIdx = ArgSz > 3 ? 3 : 0;
2577 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2579 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2596 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2607 IsSet ? TypeReg :
Register(0), ImmArgs);
2616 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2620 case SPIRV::OpSpecConstant: {
2625 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2626 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2627 "Argument should be either an int or floating-point constant");
2630 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2631 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2633 ? SPIRV::OpSpecConstantTrue
2634 : SPIRV::OpSpecConstantFalse;
2640 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2641 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2653 case SPIRV::OpSpecConstantComposite: {
2655 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2656 Call->Arguments,
Call->ReturnRegister,
2671 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2682 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2692 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2710 InputReg =
Call->Arguments[1];
2713 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2721 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2722 MRI->
setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2726 for (
unsigned index = 2; index < 7; index++) {
2745 MRI->
setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2746 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2749 for (
unsigned index = 1; index < 6; index++)
2763 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2775 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2785 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2796 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2806 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2808 unsigned Scope = SPIRV::Scope::Workgroup;
2810 Scope = SPIRV::Scope::Subgroup;
2820 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
2822 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2823 unsigned ArgSz =
Call->Arguments.size();
2832 IsSet ? TypeReg :
Register(0), ImmArgs);
2857 const unsigned NumCallArgs =
Call->Arguments.size();
2858 const unsigned MaxCallArgs =
Call->Builtin->MaxNumArgs;
2859 const unsigned IncorrectArgIdx = MaxCallArgs + 1;
2862 bool HasSRetArg = RetTy->
isVoidTy();
2864 const unsigned SRetArgIdx = HasSRetArg ? 0 : IncorrectArgIdx;
2865 const unsigned ArgBase = HasSRetArg ? 1 : 0;
2866 const unsigned MaxNDRangeArgs = 3;
2867 const unsigned NumNDRangeArgs = NumCallArgs - ArgBase;
2869 const unsigned GlobalWorkSizeArgIdx =
2870 NumNDRangeArgs < MaxNDRangeArgs ? ArgBase : ArgBase + 1;
2871 const unsigned LocalWorkSizeArgIdx =
2872 (NumNDRangeArgs == 1)
2874 : (NumNDRangeArgs == MaxNDRangeArgs ? ArgBase + 2 : ArgBase + 1);
2875 const unsigned GlobalWorkOffsetArgIdx =
2876 NumNDRangeArgs == MaxNDRangeArgs ? ArgBase : IncorrectArgIdx;
2881 assert(AddressModelBits == 64 || AddressModelBits == 32);
2885 unsigned Dimension = 0;
2886 Call->Builtin->name().substr(8, 1).getAsInteger(10, Dimension);
2887 assert(Dimension <= 3 && Dimension >= 1);
2894 if (Dimension == 1) {
2897 "Expected scalar integer type");
2899 if (NumNDRangeArgs < MaxNDRangeArgs)
2906 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadOnly,
true);
2908 if (NumNDRangeArgs < MaxNDRangeArgs) {
2914 SpvFieldTy, *ST.getInstrInfo());
2920 auto CreateDataRegister = [&](
unsigned Idx) ->
Register {
2921 Register Reg = (Idx == IncorrectArgIdx) ? ConstZero :
Call->Arguments[Idx];
2929 "Only pointer types are supported for loading values");
2943 Register GlobalWorkSize = CreateDataRegister(GlobalWorkSizeArgIdx);
2944 Register LocalWorkSize = CreateDataRegister(LocalWorkSizeArgIdx);
2945 Register GlobalWorkOffset = CreateDataRegister(GlobalWorkOffsetArgIdx);
2948 return MIRBuilder.
buildInstr(SPIRV::OpBuildNDRange)
2953 .
addUse(GlobalWorkOffset);
2970 .
addUse(GlobalWorkOffset);
3002 bool IsSpirvOp =
Call->isSpirvOp();
3003 bool HasEvents =
Call->Builtin->name().contains(
"_events") || IsSpirvOp;
3004 bool HasVarArgs =
Call->Builtin->name().contains(
"_varargs") || IsSpirvOp;
3006 const unsigned NumArgs =
Call->Arguments.size();
3007 const unsigned BaseArgIdx = 0;
3008 const unsigned IncorrectIdx = NumArgs + 1;
3010 const unsigned QueueIdx = BaseArgIdx;
3011 const unsigned FlagsIdx = BaseArgIdx + 1;
3012 const unsigned NDRangeIdx = BaseArgIdx + 2;
3013 const unsigned NumEventsIdx = HasEvents ? BaseArgIdx + 3 : IncorrectIdx;
3014 const unsigned WaitEventsIdx = HasEvents ? BaseArgIdx + 4 : IncorrectIdx;
3015 const unsigned RetEventIdx = HasEvents ? BaseArgIdx + 5 : IncorrectIdx;
3016 const unsigned InvokeIdx = BaseArgIdx + 3 + (HasEvents ? 3 : 0);
3017 const unsigned ParamIdx = BaseArgIdx + 4 + (HasEvents ? 3 : 0);
3018 const unsigned LocalSizeNumElemIdx =
3019 HasVarArgs ? (BaseArgIdx + 5 + (HasEvents ? 3 : 0)) : IncorrectIdx;
3020 const unsigned LocalSizeElemPtrIdx =
3021 HasVarArgs ? (BaseArgIdx + 6 + (HasEvents ? 3 : 0)) : IncorrectIdx;
3023 [[maybe_unused]]
const unsigned LastArgIdx =
3024 (BaseArgIdx + 4 + (HasEvents ? 3 : 0) + (HasVarArgs ? 2 : 0));
3025 assert(LastArgIdx < NumArgs &&
"Incorrect number arguments");
3031 auto BuildDeviceEventNullPtr = [&]() {
3035 DeviceEventTy, MIRBuilder, SPIRV::StorageClass::Generic);
3043 auto IsNullEvent = [&](
Register R) {
3045 return Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3046 Def->getOperand(1).getCImm()->isZero();
3049 NumEventsReg =
Call->Arguments[NumEventsIdx];
3050 WaitEventsReg =
Call->Arguments[WaitEventsIdx];
3051 RetEventReg =
Call->Arguments[RetEventIdx];
3052 if (IsNullEvent(WaitEventsReg))
3053 WaitEventsReg = BuildDeviceEventNullPtr();
3054 if (IsNullEvent(RetEventReg))
3055 RetEventReg = BuildDeviceEventNullPtr();
3058 Register NullPtr = BuildDeviceEventNullPtr();
3059 WaitEventsReg = NullPtr;
3060 RetEventReg = NullPtr;
3081 Int8Ty, MIRBuilder, SPIRV::StorageClass::Generic);
3088 .
addUse(BlockLiteralReg);
3098 Register LocalSizeNumElem =
Call->Arguments[LocalSizeNumElemIdx];
3102 ConstOp.
isCImm() &&
"Expected constant immediate");
3105 Register LocalSizeArrayReg =
Call->Arguments[LocalSizeElemPtrIdx];
3107 for (
unsigned i = 0; i < NumElem; ++i) {
3113 .
addUse(LocalSizeArrayReg)
3121 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
3134 for (
auto &LocalSize : LocalSizes)
3146 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3149 case SPIRV::OpRetainEvent:
3150 case SPIRV::OpReleaseEvent:
3152 case SPIRV::OpCreateUserEvent:
3153 case SPIRV::OpGetDefaultQueue:
3157 case SPIRV::OpIsValidEvent:
3162 case SPIRV::OpSetUserEventStatus:
3166 case SPIRV::OpCaptureEventProfilingInfo:
3171 case SPIRV::OpBuildNDRange:
3173 case SPIRV::OpEnqueueKernel:
3186 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3188 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
3190 if (
Call->isSpirvOp())
3197 case SPIRV::OpGroupAsyncCopy: {
3199 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
3203 unsigned NumArgs =
Call->Arguments.size();
3206 if (!EventType || EventType->
getOpcode() != SPIRV::OpTypeEvent) {
3211 EventType && EventType->
getOpcode() == SPIRV::OpTypePointer
3214 if (Def->getOpcode() == TargetOpcode::G_CONSTANT &&
3215 Def->getOperand(1).getCImm()->isZero()) {
3220 "spirv.Event", MIRBuilder,
true);
3226 EventReg = NullEventReg;
3227 }
else if (EventPointeeType &&
3228 EventPointeeType->
getOpcode() == SPIRV::OpTypeEvent) {
3239 EventReg = LoadedReg;
3248 DestPtrTy && DestPtrTy->
getOpcode() == SPIRV::OpTypeUntypedPointerKHR;
3251 Call->Arguments.size() > 4
3252 ?
Call->Arguments[3]
3257 auto MIB = MIRBuilder
3258 .
buildInstr(IsUntyped ? SPIRV::OpUntypedGroupAsyncCopyKHR
3259 : SPIRV::OpGroupAsyncCopy)
3272 "async copy pointer argument");
3284 case SPIRV::OpGroupWaitEvents:
3298 if (Opcode != SPIRV::OpSConvert && Opcode != SPIRV::OpUConvert &&
3299 Opcode != SPIRV::OpFConvert)
3301 if (
Call->Arguments.size() != 1 ||
3314 SPIRV::lookupConvertBuiltin(
Call->Builtin->name(),
Call->Builtin->Set);
3316 if (!Builtin &&
Call->isSpirvOp()) {
3319 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3326 assert(Builtin &&
"Conversion builtin not found.");
3328 std::string NeedExtMsg;
3329 bool IsRightComponentsNumber =
true;
3330 unsigned Opcode = SPIRV::OpNop;
3333 bool IsSourceSigned =
3339 : SPIRV::OpSatConvertSToU;
3341 Opcode = IsSourceSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3343 SPIRV::OpTypeFloat)) {
3347 &MIRBuilder.
getMF().getSubtarget());
3348 if (!ST->canUseExtension(
3349 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3350 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3351 IsRightComponentsNumber =
3354 Opcode = SPIRV::OpConvertBF16ToFINTEL;
3356 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
3360 SPIRV::OpTypeFloat)) {
3366 &MIRBuilder.
getMF().getSubtarget());
3367 if (!ST->canUseExtension(
3368 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
3369 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
3370 IsRightComponentsNumber =
3373 Opcode = SPIRV::OpConvertFToBF16INTEL;
3376 : SPIRV::OpConvertFToU;
3379 SPIRV::OpTypeFloat)) {
3382 &MIRBuilder.
getMF().getSubtarget());
3383 if (!ST->canUseExtension(
3384 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
3385 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
3386 IsRightComponentsNumber =
3389 Opcode = SPIRV::OpRoundFToTF32INTEL;
3392 Opcode = SPIRV::OpFConvert;
3397 StringRef BuiltinName = SPIRV::getConvertBuiltinStr(Builtin->
Name);
3398 if (!NeedExtMsg.empty()) {
3399 std::string DiagMsg = std::string(BuiltinName) +
3400 ": the builtin requires the following SPIR-V "
3405 if (!IsRightComponentsNumber) {
3406 std::string DiagMsg =
3407 std::string(BuiltinName) +
3408 ": result and argument must have the same number of components";
3411 assert(Opcode != SPIRV::OpNop &&
3412 "Conversion between the types not implemented!");
3420 SPIRV::Decoration::SaturatedConversion, {});
3423 bool AnyTypeIsFloat =
3430 if (AnyTypeIsFloat) {
3432 SPIRV::Decoration::FPRoundingMode,
3433 {(unsigned)Builtin->RoundingMode});
3449 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->name(),
3450 Call->Builtin->Set);
3456 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3460 StringRef BuiltinName = SPIRV::getVectorLoadStoreBuiltinStr(Builtin->
Name);
3474 const auto *Builtin =
Call->Builtin;
3475 auto *MRI = MIRBuilder.
getMRI();
3477 SPIRV::lookupNativeBuiltin(Builtin->name(), Builtin->Set)->Opcode;
3483 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3484 DestReg = MRI->createGenericVirtualRegister(PtrTy);
3485 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3488 MIB.addDef(DestReg);
3491 MIB.addDef(
Call->ReturnRegister);
3494 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3497 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3498 DefMI->getOperand(1).isCImm()) {
3505 LLT PtrTy = MRI->getType(
Call->Arguments[0]);
3520 SPIRV::lookupNativeBuiltin(Builtin->
name(), Builtin->
Set)->Opcode;
3521 bool IsLoad = Opcode == SPIRV::OpLoad;
3525 MIB.addDef(
Call->ReturnRegister);
3533 MIB.addUse(
Call->Arguments[1]);
3535 unsigned NumArgs =
Call->Arguments.size();
3536 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3538 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3551std::tuple<int, unsigned, unsigned>
3553 SPIRV::InstructionSet::InstructionSet Set) {
3556 std::unique_ptr<const IncomingCall>
Call =
3559 return std::make_tuple(-1, 0, 0);
3561 switch (
Call->Builtin->Group) {
3562 case SPIRV::Relational:
3564 case SPIRV::Barrier:
3565 case SPIRV::CastToPtr:
3566 case SPIRV::ImageMiscQuery:
3567 case SPIRV::SpecConstant:
3568 case SPIRV::Enqueue:
3569 case SPIRV::AsyncCopy:
3570 case SPIRV::LoadStore:
3571 case SPIRV::CoopMatr:
3572 case SPIRV::Arithmetic:
3573 if (
const auto *R = SPIRV::lookupNativeBuiltin(
Call->Builtin->name(),
3574 Call->Builtin->Set))
3575 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3577 case SPIRV::Extended:
3578 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->name(),
3579 Call->Builtin->Set))
3580 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3582 case SPIRV::VectorLoadStore:
3583 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
3584 Call->Builtin->name(),
Call->Builtin->Set))
3585 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3588 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->name()))
3589 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3591 case SPIRV::AtomicFloating:
3593 SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->name()))
3594 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3596 case SPIRV::IntelSubgroups:
3598 SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->name()))
3599 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3601 case SPIRV::GroupUniform:
3602 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->name()))
3603 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3605 case SPIRV::IntegerDot:
3607 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->name()))
3608 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3610 case SPIRV::WriteImage:
3611 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3613 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3614 case SPIRV::Construct:
3615 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3617 case SPIRV::KernelClock:
3618 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3620 return std::make_tuple(-1, 0, 0);
3622 return std::make_tuple(-1, 0, 0);
3636 if (
Call->isSpirvOp())
3644 if (
Call->Arguments.size() < ArgBase)
3646 unsigned NumMangledArgs =
Call->Arguments.size() - ArgBase;
3647 unsigned NumArgsToCheck =
3648 std::min<unsigned>(NumMangledArgs, ArgTypeStrs.
size());
3649 for (
unsigned ArgIdx = 0; ArgIdx < NumArgsToCheck; ++ArgIdx) {
3650 StringRef ArgTypeStr = ArgTypeStrs[ArgIdx].trim();
3659 if (!ExpectedType || ExpectedType->
isVoidTy() ||
3667 unsigned ArgTypeOpcode = ArgType->
getOpcode();
3668 if (ArgTypeOpcode != SPIRV::OpTypeInt &&
3669 ArgTypeOpcode != SPIRV::OpTypeFloat &&
3670 ArgTypeOpcode != SPIRV::OpTypeBool &&
3671 ArgTypeOpcode != SPIRV::OpTypeVector)
3675 Type *ExpectedScalarType =
3676 ExpectedVecType ? ExpectedVecType->getElementType() : ExpectedType;
3681 bool ExpectedIsInt = ExpectedScalarType->
isIntegerTy();
3682 unsigned ArgOpcode = ArgScalarType->
getOpcode();
3684 ArgOpcode == SPIRV::OpTypeInt || ArgOpcode == SPIRV::OpTypeBool;
3686 if (ExpectedIsInt != ArgIsInt)
3689 unsigned ExpectedElts =
3690 ExpectedVecType ? ExpectedVecType->getElementCount().getFixedValue()
3699 SPIRV::InstructionSet::InstructionSet Set,
3704 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3708 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3709 std::unique_ptr<const IncomingCall>
Call =
3714 return std::nullopt;
3719 if (Args.size() <
Call->Builtin->MinNumArgs) {
3720 LLVM_DEBUG(
dbgs() <<
"Too few arguments for builtin " << DemangledCall
3721 <<
": expected at least " <<
Call->Builtin->MinNumArgs
3722 <<
", got " << Args.size()
3723 <<
"; treating as a normal function\n");
3724 return std::nullopt;
3726 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs) {
3727 LLVM_DEBUG(
dbgs() <<
"Too many arguments for builtin " << DemangledCall
3728 <<
": expected at most " <<
Call->Builtin->MaxNumArgs
3729 <<
", got " << Args.size()
3730 <<
"; treating as a normal function\n");
3731 return std::nullopt;
3739 LLVM_DEBUG(
dbgs() <<
"Argument types do not match mangled types for "
3740 <<
"builtin " << DemangledCall
3741 <<
"; treating as a normal function\n");
3742 return std::nullopt;
3746 switch (
Call->Builtin->Group) {
3747 case SPIRV::Extended:
3749 case SPIRV::Relational:
3753 case SPIRV::Variable:
3757 case SPIRV::AtomicFloating:
3759 case SPIRV::Barrier:
3761 case SPIRV::CastToPtr:
3764 case SPIRV::IntegerDot:
3768 case SPIRV::ICarryBorrow:
3770 case SPIRV::MulExtended:
3772 case SPIRV::Arithmetic:
3774 case SPIRV::GetQuery:
3776 case SPIRV::ImageSizeQuery:
3778 case SPIRV::ImageMiscQuery:
3780 case SPIRV::ReadImage:
3782 case SPIRV::WriteImage:
3784 case SPIRV::SampleImage:
3788 case SPIRV::Construct:
3790 case SPIRV::SpecConstant:
3792 case SPIRV::Enqueue:
3794 case SPIRV::AsyncCopy:
3796 case SPIRV::Convert:
3798 case SPIRV::VectorLoadStore:
3800 case SPIRV::LoadStore:
3802 case SPIRV::IntelSubgroups:
3804 case SPIRV::GroupUniform:
3806 case SPIRV::KernelClock:
3808 case SPIRV::CoopMatr:
3810 case SPIRV::ExtendedBitOps:
3812 case SPIRV::BindlessINTEL:
3814 case SPIRV::TernaryBitwiseINTEL:
3816 case SPIRV::Block2DLoadStore:
3820 case SPIRV::PredicatedLoadStore:
3822 case SPIRV::BlockingPipes:
3824 case SPIRV::ArbitraryPrecisionFixedPoint:
3826 case SPIRV::ImageChannelDataTypes:
3828 case SPIRV::ArbitraryFloatingPoint:
3839 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3840 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3857 unsigned VecElts = 0;
3868 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3880 auto Pos1 = DemangledCall.
find(
'(');
3883 auto Pos2 = DemangledCall.
find(
')');
3886 DemangledCall.
slice(Pos1 + 1, Pos2)
3887 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3895 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3897 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3906#define GET_BuiltinTypes_DECL
3907#define GET_BuiltinTypes_IMPL
3914#define GET_OpenCLTypes_DECL
3915#define GET_OpenCLTypes_IMPL
3917#include "SPIRVGenTables.inc"
3925 if (Name.starts_with(
"void"))
3927 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3929 else if (Name.starts_with(
"bfloat"))
3931 else if (Name.starts_with(
"float"))
3933 else if (Name.starts_with(
"half"))
3935 else if (Name.starts_with(
"double"))
3948 unsigned Opcode = TypeRecord->
Opcode;
3963 "Invalid number of parameters for SPIR-V pipe builtin!");
3966 SPIRV::AccessQualifier::AccessQualifier(
3974 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3976 "SPIR-V coop matrices builtin type must have a type parameter!");
3979 SPIRV::AccessQualifier::ReadWrite,
true);
3982 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3991 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
4000 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
4007 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
4008 assert(ParamEType->getNumTypeParameters() == 1 &&
4009 "Inline SPIR-V integral constant builtin must have a type "
4011 assert(ParamEType->getNumIntParameters() == 1 &&
4012 "Inline SPIR-V integral constant builtin must have a "
4015 auto OperandValue = ParamEType->getIntParameter(0);
4016 auto *OperandType = ParamEType->getTypeParameter(0);
4019 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
4022 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
4024 }
else if (ParamEType->getName() ==
"spirv.Literal") {
4025 assert(ParamEType->getNumTypeParameters() == 0 &&
4026 "Inline SPIR-V literal builtin does not take type "
4028 assert(ParamEType->getNumIntParameters() == 1 &&
4029 "Inline SPIR-V literal builtin must have an integer "
4032 auto OperandValue = ParamEType->getIntParameter(0);
4039 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
4051 "Vulkan buffers have exactly one type for the type of the buffer.");
4053 "Vulkan buffer have 2 integer parameters: storage class and is "
4057 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
4068 "Vulkan push constants have exactly one type as argument.");
4082 StringRef NameWithParameters = TypeName;
4089 SPIRV::lookupOpenCLType(NameWithParameters);
4092 NameWithParameters);
4093 NameWithParameters =
4101 "Unknown builtin opaque type!");
4105 if (!NameWithParameters.
contains(
'_'))
4109 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
4113 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
4114 if (HasTypeParameter)
4117 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
4118 unsigned IntParameter = 0;
4119 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
4122 "Invalid format of SPIR-V builtin parameter literal!");
4126 NameWithParameters.
substr(0, BaseNameLength),
4127 TypeParameters, IntParameters);
4132 SPIRV::AccessQualifier::AccessQualifier AccessQual,
4153 if (Name ==
"spirv.Type") {
4155 }
else if (Name ==
"spirv.VulkanBuffer") {
4157 }
else if (Name ==
"spirv.Padding") {
4159 }
else if (Name ==
"spirv.PushConstant") {
4161 }
else if (Name ==
"spirv.Layout") {
4175 switch (TypeRecord->
Opcode) {
4176 case SPIRV::OpTypeImage:
4179 case SPIRV::OpTypePipe:
4182 case SPIRV::OpTypeDeviceEvent:
4185 case SPIRV::OpTypeSampler:
4188 case SPIRV::OpTypeSampledImage:
4191 case SPIRV::OpTypeCooperativeMatrixKHR:
4213 return Builtin->
Group == Pipe || Builtin->
Group == CastToPtr ||
4214 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 LLVM_READONLY 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
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.
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 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)
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)
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