20#include "llvm/IR/IntrinsicsSPIRV.h"
25#define DEBUG_TYPE "spirv-builtins"
29#define GET_BuiltinGroup_DECL
30#include "SPIRVGenTables.inc"
34 InstructionSet::InstructionSet
Set;
40#define GET_DemangledBuiltins_DECL
41#define GET_DemangledBuiltins_IMPL
63 InstructionSet::InstructionSet
Set;
67#define GET_NativeBuiltins_DECL
68#define GET_NativeBuiltins_IMPL
86#define GET_GroupBuiltins_DECL
87#define GET_GroupBuiltins_IMPL
97#define GET_IntelSubgroupsBuiltins_DECL
98#define GET_IntelSubgroupsBuiltins_IMPL
105#define GET_AtomicFloatingBuiltins_DECL
106#define GET_AtomicFloatingBuiltins_IMPL
113#define GET_GroupUniformBuiltins_DECL
114#define GET_GroupUniformBuiltins_IMPL
118 InstructionSet::InstructionSet
Set;
123#define GET_GetBuiltins_DECL
124#define GET_GetBuiltins_IMPL
128 InstructionSet::InstructionSet
Set;
132#define GET_ImageQueryBuiltins_DECL
133#define GET_ImageQueryBuiltins_IMPL
141#define GET_IntegerDotProductBuiltins_DECL
142#define GET_IntegerDotProductBuiltins_IMPL
146 InstructionSet::InstructionSet
Set;
157 InstructionSet::InstructionSet
Set;
165#define GET_ConvertBuiltins_DECL
166#define GET_ConvertBuiltins_IMPL
168using namespace InstructionSet;
169#define GET_VectorLoadStoreBuiltins_DECL
170#define GET_VectorLoadStoreBuiltins_IMPL
172#define GET_CLMemoryScope_DECL
173#define GET_CLSamplerAddressingMode_DECL
174#define GET_CLMemoryFenceFlags_DECL
175#define GET_ExtendedBuiltins_DECL
176#include "SPIRVGenTables.inc"
188 StringRef PassPrefix =
"(anonymous namespace)::";
190 std::string BuiltinName = DemangledCall.
str();
195 std::size_t Pos = BuiltinName.find(
">(");
196 if (Pos != std::string::npos) {
197 BuiltinName = BuiltinName.substr(0, BuiltinName.rfind(
'<', Pos));
199 Pos = BuiltinName.find(
'(');
200 if (Pos != std::string::npos)
201 BuiltinName = BuiltinName.substr(0, Pos);
203 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(
' ') + 1);
207 if (BuiltinName.find(PassPrefix) == 0)
208 BuiltinName = BuiltinName.substr(PassPrefix.
size());
209 else if (BuiltinName.find(SpvPrefix) == 0)
210 BuiltinName = BuiltinName.substr(SpvPrefix.
size());
213 if (BuiltinName.rfind(
"__spirv_ocl_", 0) == 0)
214 BuiltinName = BuiltinName.substr(12);
240 static const std::regex SpvWithR(
241 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"
243 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"
244 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"
245 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"
247 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");
249 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {
250 std::ssub_match SubMatch;
251 if (DecorationId && Match.size() > 3) {
256 BuiltinName = SubMatch.str();
273static std::unique_ptr<const SPIRV::IncomingCall>
275 SPIRV::InstructionSet::InstructionSet Set,
282 DemangledCall.
slice(DemangledCall.
find(
'(') + 1, DemangledCall.
find(
')'));
283 BuiltinArgs.
split(BuiltinArgumentTypes,
',', -1,
false);
288 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))
289 return std::make_unique<SPIRV::IncomingCall>(
290 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
295 if (BuiltinArgumentTypes.
size() >= 1) {
296 char FirstArgumentType = BuiltinArgumentTypes[0][0];
301 switch (FirstArgumentType) {
304 if (Set == SPIRV::InstructionSet::OpenCL_std)
306 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
314 if (Set == SPIRV::InstructionSet::OpenCL_std)
316 else if (Set == SPIRV::InstructionSet::GLSL_std_450)
323 if (Set == SPIRV::InstructionSet::OpenCL_std ||
324 Set == SPIRV::InstructionSet::GLSL_std_450)
330 if (!Prefix.empty() &&
331 (Builtin = SPIRV::lookupBuiltin(Prefix + BuiltinName, Set)))
332 return std::make_unique<SPIRV::IncomingCall>(
333 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
340 switch (FirstArgumentType) {
361 if (!Suffix.empty() &&
362 (Builtin = SPIRV::lookupBuiltin(BuiltinName + Suffix, Set)))
363 return std::make_unique<SPIRV::IncomingCall>(
364 BuiltinName, Builtin, ReturnRegister, ReturnType,
Arguments);
379 assert(
MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&
380 MI->getOperand(1).isReg());
381 Register BitcastReg =
MI->getOperand(1).getReg();
395 assert(
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
396 DefMI->getOperand(1).isCImm());
397 return DefMI->getOperand(1).getCImm()->getValue().getZExtValue();
409 Register ValueReg =
MI->getOperand(0).getReg();
415 assert(Ty &&
"Type is expected");
427 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)
428 return MI->getOperand(1).getGlobal()->getType();
430 "Blocks in OpenCL C must be traceable to allocation site");
442static std::tuple<Register, SPIRVType *>
448 if (ResultType->
getOpcode() == SPIRV::OpTypeVector) {
463 return std::make_tuple(ResultRegister, BoolType);
474 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {
485 return MIRBuilder.
buildSelect(ReturnRegister, SourceRegister, TrueConst,
495 if (!DestinationReg.isValid())
500 MIRBuilder.
buildLoad(DestinationReg, PtrRegister, PtrInfo,
Align());
501 return DestinationReg;
510 const std::optional<SPIRV::LinkageType::LinkageType> &LinkageTy = {
511 SPIRV::LinkageType::Import}) {
519 VariableType, MIRBuilder, SPIRV::StorageClass::Input);
525 SPIRV::StorageClass::Input,
nullptr, isConst, LinkageTy,
532 return LoadedRegister;
542static SPIRV::MemorySemantics::MemorySemantics
545 case std::memory_order_relaxed:
546 return SPIRV::MemorySemantics::None;
547 case std::memory_order_acquire:
548 return SPIRV::MemorySemantics::Acquire;
549 case std::memory_order_release:
550 return SPIRV::MemorySemantics::Release;
551 case std::memory_order_acq_rel:
552 return SPIRV::MemorySemantics::AcquireRelease;
553 case std::memory_order_seq_cst:
554 return SPIRV::MemorySemantics::SequentiallyConsistent;
562 case SPIRV::CLMemoryScope::memory_scope_work_item:
563 return SPIRV::Scope::Invocation;
564 case SPIRV::CLMemoryScope::memory_scope_work_group:
565 return SPIRV::Scope::Workgroup;
566 case SPIRV::CLMemoryScope::memory_scope_device:
567 return SPIRV::Scope::Device;
568 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:
569 return SPIRV::Scope::CrossDevice;
570 case SPIRV::CLMemoryScope::memory_scope_sub_group:
571 return SPIRV::Scope::Subgroup;
584 SPIRV::Scope::Scope Scope,
588 if (CLScopeRegister.
isValid()) {
593 if (CLScope ==
static_cast<unsigned>(Scope)) {
594 MRI->setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);
595 return CLScopeRegister;
603 if (
MRI->getRegClassOrNull(
Reg))
607 SpvType ? GR->
getRegClass(SpvType) : &SPIRV::iIDRegClass);
611 Register PtrRegister,
unsigned &Semantics,
614 if (SemanticsRegister.
isValid()) {
616 std::memory_order Order =
621 if (
static_cast<unsigned>(Order) == Semantics) {
622 MRI->setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);
623 return SemanticsRegister;
636 unsigned Sz =
Call->Arguments.size() - ImmArgs.size();
637 for (
unsigned i = 0; i < Sz; ++i)
638 MIB.addUse(
Call->Arguments[i]);
647 if (
Call->isSpirvOp())
651 "Need 2 arguments for atomic init translation");
663 if (
Call->isSpirvOp())
671 Call->Arguments.size() > 1
675 if (
Call->Arguments.size() > 2) {
677 MemSemanticsReg =
Call->Arguments[2];
680 SPIRV::MemorySemantics::SequentiallyConsistent |
698 if (
Call->isSpirvOp())
706 SPIRV::MemorySemantics::SequentiallyConsistent |
721 if (
Call->isSpirvOp())
725 bool IsCmpxchg =
Call->Builtin->Name.contains(
"cmpxchg");
732 LLT DesiredLLT =
MRI->getType(Desired);
735 SPIRV::OpTypePointer);
738 assert(IsCmpxchg ? ExpectedType == SPIRV::OpTypeInt
739 : ExpectedType == SPIRV::OpTypePointer);
744 auto StorageClass =
static_cast<SPIRV::StorageClass::StorageClass
>(
752 ? SPIRV::MemorySemantics::None
753 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
756 ? SPIRV::MemorySemantics::None
757 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;
758 if (
Call->Arguments.size() >= 4) {
760 "Need 5+ args for explicit atomic cmpxchg");
767 if (
static_cast<unsigned>(MemOrdEq) == MemSemEqual)
768 MemSemEqualReg =
Call->Arguments[3];
769 if (
static_cast<unsigned>(MemOrdNeq) == MemSemEqual)
770 MemSemUnequalReg =
Call->Arguments[4];
774 if (!MemSemUnequalReg.
isValid())
778 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;
779 if (
Call->Arguments.size() >= 6) {
781 "Extra args for explicit atomic cmpxchg");
782 auto ClScope =
static_cast<SPIRV::CLMemoryScope
>(
785 if (ClScope ==
static_cast<unsigned>(Scope))
786 ScopeReg =
Call->Arguments[5];
796 Register Tmp = !IsCmpxchg ?
MRI->createGenericVirtualRegister(DesiredLLT)
797 :
Call->ReturnRegister;
798 if (!
MRI->getRegClassOrNull(Tmp))
822 if (
Call->isSpirvOp())
831 "Too many args for explicit atomic RMW");
832 ScopeRegister =
buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,
833 MIRBuilder, GR,
MRI);
836 unsigned Semantics = SPIRV::MemorySemantics::None;
840 Semantics, MIRBuilder, GR);
844 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {
845 if (Opcode == SPIRV::OpAtomicIAdd) {
846 Opcode = SPIRV::OpAtomicFAddEXT;
847 }
else if (Opcode == SPIRV::OpAtomicISub) {
850 Opcode = SPIRV::OpAtomicFAddEXT;
852 MRI->createGenericVirtualRegister(
MRI->getType(ValueReg));
861 ValueReg = NegValueReg;
880 "Wrong number of atomic floating-type builtin");
900 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;
902 if (
Call->isSpirvOp())
908 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;
912 Semantics, MIRBuilder, GR);
914 assert((Opcode != SPIRV::OpAtomicFlagClear ||
915 (Semantics != SPIRV::MemorySemantics::Acquire &&
916 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&
917 "Invalid memory order argument!");
940 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||
941 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&
942 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
943 std::string DiagMsg = std::string(Builtin->
Name) +
944 ": the builtin requires the following SPIR-V "
945 "extension: SPV_INTEL_split_barrier";
949 if (
Call->isSpirvOp())
954 unsigned MemSemantics = SPIRV::MemorySemantics::None;
956 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)
957 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;
959 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)
960 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;
962 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)
963 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;
965 if (Opcode == SPIRV::OpMemoryBarrier)
969 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)
970 MemSemantics |= SPIRV::MemorySemantics::Release;
971 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)
972 MemSemantics |= SPIRV::MemorySemantics::Acquire;
974 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;
977 MemFlags == MemSemantics
981 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;
982 SPIRV::Scope::Scope MemScope = Scope;
983 if (
Call->Arguments.size() >= 2) {
985 ((Opcode != SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 2) ||
986 (Opcode == SPIRV::OpMemoryBarrier &&
Call->Arguments.size() == 3)) &&
987 "Extra args for explicitly scoped barrier");
988 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ?
Call->Arguments[2]
989 :
Call->Arguments[1];
990 SPIRV::CLMemoryScope CLScope =
993 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||
994 (Opcode == SPIRV::OpMemoryBarrier))
996 if (CLScope ==
static_cast<unsigned>(Scope))
997 ScopeReg =
Call->Arguments[1];
1004 if (Opcode != SPIRV::OpMemoryBarrier)
1006 MIB.
addUse(MemSemanticsReg);
1018 if ((Opcode == SPIRV::OpBitFieldInsert ||
1019 Opcode == SPIRV::OpBitFieldSExtract ||
1020 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&
1021 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1022 std::string DiagMsg = std::string(Builtin->
Name) +
1023 ": the builtin requires the following SPIR-V "
1024 "extension: SPV_KHR_bit_instructions";
1029 if (
Call->isSpirvOp())
1036 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1048 if (
Call->isSpirvOp())
1065 if (
Call->isSpirvOp())
1072 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1082 if (
Call->isSpirvOp())
1089 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1101 if (
Call->isSpirvOp())
1107 for (
unsigned i = 0; i <
Call->Arguments.size(); ++i)
1117 case SPIRV::OpCommitReadPipe:
1118 case SPIRV::OpCommitWritePipe:
1120 case SPIRV::OpGroupCommitReadPipe:
1121 case SPIRV::OpGroupCommitWritePipe:
1122 case SPIRV::OpGroupReserveReadPipePackets:
1123 case SPIRV::OpGroupReserveWritePipePackets: {
1127 MRI->setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);
1131 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||
1132 Opcode == SPIRV::OpGroupReserveWritePipePackets)
1136 MIB.
addUse(ScopeConstReg);
1137 for (
unsigned int i = 0; i <
Call->Arguments.size(); ++i)
1150 case SPIRV::Dim::DIM_1D:
1151 case SPIRV::Dim::DIM_Buffer:
1153 case SPIRV::Dim::DIM_2D:
1154 case SPIRV::Dim::DIM_Cube:
1155 case SPIRV::Dim::DIM_Rect:
1157 case SPIRV::Dim::DIM_3D:
1170 return arrayed ? numComps + 1 : numComps;
1174 switch (BuiltinNumber) {
1175 case SPIRV::OpenCLExtInst::s_min:
1176 case SPIRV::OpenCLExtInst::u_min:
1177 case SPIRV::OpenCLExtInst::s_max:
1178 case SPIRV::OpenCLExtInst::u_max:
1179 case SPIRV::OpenCLExtInst::fmax:
1180 case SPIRV::OpenCLExtInst::fmin:
1181 case SPIRV::OpenCLExtInst::fmax_common:
1182 case SPIRV::OpenCLExtInst::fmin_common:
1183 case SPIRV::OpenCLExtInst::s_clamp:
1184 case SPIRV::OpenCLExtInst::fclamp:
1185 case SPIRV::OpenCLExtInst::u_clamp:
1186 case SPIRV::OpenCLExtInst::mix:
1187 case SPIRV::OpenCLExtInst::step:
1188 case SPIRV::OpenCLExtInst::smoothstep:
1205 unsigned ResultElementCount =
1207 bool MayNeedPromotionToVec =
1210 if (!MayNeedPromotionToVec)
1211 return {
Call->Arguments.begin(),
Call->Arguments.end()};
1217 if (ArgumentType !=
Call->ReturnType) {
1219 auto VecSplat = MIRBuilder.
buildInstr(SPIRV::OpCompositeConstruct)
1222 for (
unsigned I = 0;
I != ResultElementCount; ++
I)
1236 SPIRV::lookupExtendedBuiltin(Builtin->
Name, Builtin->
Set)->Number;
1243 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&
1244 (
Number == SPIRV::OpenCLExtInst::fmin_common ||
1245 Number == SPIRV::OpenCLExtInst::fmax_common)) {
1247 ? SPIRV::OpenCLExtInst::fmin
1248 : SPIRV::OpenCLExtInst::fmax;
1260 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
1267 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||
1268 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {
1282 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1286 std::tie(CompareRegister, RelationType) =
1299 Call->ReturnType, GR);
1307 SPIRV::lookupGroupBuiltin(Builtin->
Name);
1310 if (
Call->isSpirvOp()) {
1313 if (GroupBuiltin->
Opcode ==
1314 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&
1315 Call->Arguments.size() > 4)
1324 if (!
MI ||
MI->getOpcode() != TargetOpcode::G_CONSTANT)
1326 "Group Operation parameter must be an integer constant");
1327 uint64_t GrpOp =
MI->getOperand(1).getCImm()->getValue().getZExtValue();
1334 for (
unsigned i = 2; i <
Call->Arguments.size(); ++i)
1347 if (ArgInstruction->
getOpcode() == TargetOpcode::G_CONSTANT) {
1348 if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool)
1352 if (BoolRegType->
getOpcode() == SPIRV::OpTypeInt) {
1354 MRI->setRegClass(Arg0, &SPIRV::iIDRegClass);
1361 }
else if (BoolRegType->
getOpcode() != SPIRV::OpTypeBool) {
1373 const bool HasBoolReturnTy =
1378 if (HasBoolReturnTy)
1379 std::tie(GroupResultRegister, GroupResultType) =
1382 auto Scope = Builtin->
Name.
starts_with(
"sub_group") ? SPIRV::Scope::Subgroup
1383 : SPIRV::Scope::Workgroup;
1387 if (GroupBuiltin->
Opcode == SPIRV::OpGroupBroadcast &&
1388 Call->Arguments.size() > 2) {
1396 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeInt)
1398 unsigned VecLen =
Call->Arguments.size() - 1;
1399 VecReg =
MRI->createGenericVirtualRegister(
1401 MRI->setRegClass(VecReg, &SPIRV::vIDRegClass);
1407 for (
unsigned i = 1; i <
Call->Arguments.size(); i++) {
1408 MIB.addUse(
Call->Arguments[i]);
1417 .
addDef(GroupResultRegister)
1423 if (
Call->Arguments.size() > 0) {
1424 MIB.addUse(Arg0.
isValid() ? Arg0 :
Call->Arguments[0]);
1429 for (
unsigned i = 1; i <
Call->Arguments.size(); i++)
1430 MIB.addUse(
Call->Arguments[i]);
1434 if (HasBoolReturnTy)
1436 Call->ReturnType, GR);
1447 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->
Name);
1449 if (IntelSubgroups->
IsMedia &&
1450 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1451 std::string DiagMsg = std::string(Builtin->
Name) +
1452 ": the builtin requires the following SPIR-V "
1453 "extension: SPV_INTEL_media_block_io";
1455 }
else if (!IntelSubgroups->
IsMedia &&
1456 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1457 std::string DiagMsg = std::string(Builtin->
Name) +
1458 ": the builtin requires the following SPIR-V "
1459 "extension: SPV_INTEL_subgroups";
1464 if (
Call->isSpirvOp()) {
1465 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&
1466 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&
1467 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;
1473 if (IntelSubgroups->
IsBlock) {
1476 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {
1482 case SPIRV::OpSubgroupBlockReadINTEL:
1483 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;
1485 case SPIRV::OpSubgroupBlockWriteINTEL:
1486 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;
1509 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1520 if (!ST->canUseExtension(
1521 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1522 std::string DiagMsg = std::string(Builtin->
Name) +
1523 ": the builtin requires the following SPIR-V "
1524 "extension: SPV_KHR_uniform_group_instructions";
1528 SPIRV::lookupGroupUniformBuiltin(Builtin->
Name);
1538 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)
1540 "expect a constant group operation for a uniform group instruction",
1543 if (!ConstOperand.
isCImm())
1553 MIB.addUse(ValueReg);
1564 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {
1565 std::string DiagMsg = std::string(Builtin->
Name) +
1566 ": the builtin requires the following SPIR-V "
1567 "extension: SPV_KHR_shader_clock";
1573 if (Builtin->
Name ==
"__spirv_ReadClockKHR") {
1580 SPIRV::Scope::Scope ScopeArg =
1582 .
EndsWith(
"device", SPIRV::Scope::Scope::Device)
1583 .
EndsWith(
"work_group", SPIRV::Scope::Scope::Workgroup)
1584 .
EndsWith(
"sub_group", SPIRV::Scope::Scope::Subgroup);
1625 SPIRV::BuiltIn::BuiltIn BuiltinValue,
1628 const unsigned ResultWidth =
Call->ReturnType->getOperand(1).getImm();
1639 bool IsConstantIndex =
1640 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;
1646 if (PointerSize != ResultWidth) {
1647 DefaultReg =
MRI->createGenericVirtualRegister(
LLT::scalar(PointerSize));
1648 MRI->setRegClass(DefaultReg, &SPIRV::iIDRegClass);
1650 MIRBuilder.
getMF());
1651 ToTruncate = DefaultReg;
1655 MIRBuilder.
buildCopy(DefaultReg, NewRegister);
1664 if (!IsConstantIndex || PointerSize != ResultWidth) {
1665 Extracted =
MRI->createGenericVirtualRegister(
LLT::scalar(PointerSize));
1666 MRI->setRegClass(Extracted, &SPIRV::iIDRegClass);
1673 ExtractInst.
addUse(LoadedVector).
addUse(IndexRegister);
1676 if (!IsConstantIndex) {
1684 MRI->setRegClass(CompareRegister, &SPIRV::iIDRegClass);
1699 if (PointerSize != ResultWidth) {
1702 MRI->setRegClass(SelectionResult, &SPIRV::iIDRegClass);
1704 MIRBuilder.
getMF());
1707 MIRBuilder.
buildSelect(SelectionResult, CompareRegister, Extracted,
1709 ToTruncate = SelectionResult;
1711 ToTruncate = Extracted;
1715 if (PointerSize != ResultWidth)
1725 SPIRV::BuiltIn::BuiltIn
Value =
1726 SPIRV::lookupGetBuiltin(Builtin->
Name, Builtin->
Set)->
Value;
1728 if (
Value == SPIRV::BuiltIn::GlobalInvocationId)
1734 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)
1741 LLType,
Call->ReturnRegister);
1750 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1753 case SPIRV::OpStore:
1755 case SPIRV::OpAtomicLoad:
1757 case SPIRV::OpAtomicStore:
1759 case SPIRV::OpAtomicCompareExchange:
1760 case SPIRV::OpAtomicCompareExchangeWeak:
1763 case SPIRV::OpAtomicIAdd:
1764 case SPIRV::OpAtomicISub:
1765 case SPIRV::OpAtomicOr:
1766 case SPIRV::OpAtomicXor:
1767 case SPIRV::OpAtomicAnd:
1768 case SPIRV::OpAtomicExchange:
1770 case SPIRV::OpMemoryBarrier:
1772 case SPIRV::OpAtomicFlagTestAndSet:
1773 case SPIRV::OpAtomicFlagClear:
1776 if (
Call->isSpirvOp())
1788 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->
Name)->Opcode;
1791 case SPIRV::OpAtomicFAddEXT:
1792 case SPIRV::OpAtomicFMinEXT:
1793 case SPIRV::OpAtomicFMaxEXT:
1806 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1817 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1819 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {
1820 SPIRV::StorageClass::StorageClass ResSC =
1831 MIRBuilder.
buildInstr(TargetOpcode::G_ADDRSPACE_CAST)
1842 if (
Call->isSpirvOp())
1847 SPIRV::OpTypeVector;
1849 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;
1850 bool IsSwapReq =
false;
1855 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
1859 SPIRV::lookupIntegerDotProductBuiltin(Builtin->
Name);
1869 bool IsFirstSigned = TypeStrs[0].trim()[0] !=
'u';
1870 bool IsSecondSigned = TypeStrs[1].trim()[0] !=
'u';
1872 if (
Call->BuiltinName ==
"dot") {
1873 if (IsFirstSigned && IsSecondSigned)
1875 else if (!IsFirstSigned && !IsSecondSigned)
1878 OC = SPIRV::OpSUDot;
1882 }
else if (
Call->BuiltinName ==
"dot_acc_sat") {
1883 if (IsFirstSigned && IsSecondSigned)
1884 OC = SPIRV::OpSDotAccSat;
1885 else if (!IsFirstSigned && !IsSecondSigned)
1886 OC = SPIRV::OpUDotAccSat;
1888 OC = SPIRV::OpSUDotAccSat;
1904 for (
size_t i = 2; i <
Call->Arguments.size(); ++i)
1907 for (
size_t i = 0; i <
Call->Arguments.size(); ++i)
1913 if (!IsVec && OC != SPIRV::OpFMulS)
1914 MIB.
addImm(SPIRV::PackedVectorFormat4x8Bit);
1923 SPIRV::BuiltIn::BuiltIn
Value =
1924 SPIRV::lookupGetBuiltin(Builtin->
Name, Builtin->
Set)->
Value;
1927 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);
1931 MIRBuilder,
Call->ReturnType, GR,
Value, LLType,
Call->ReturnRegister,
1932 false, std::nullopt);
1946 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
1953 if (RetType->
getOpcode() != SPIRV::OpTypeStruct)
1955 "overflow builtins");
1959 if (!OpType1 || !OpType2 || OpType1 != OpType2)
1961 if (OpType1->
getOpcode() == SPIRV::OpTypeVector)
1963 case SPIRV::OpIAddCarryS:
1964 Opcode = SPIRV::OpIAddCarryV;
1966 case SPIRV::OpISubBorrowS:
1967 Opcode = SPIRV::OpISubBorrowV;
1972 Register ResReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1974 MRI->getRegClassOrNull(
Call->Arguments[1])) {
1975 MRI->setRegClass(ResReg, DstRC);
1976 MRI->setType(ResReg,
MRI->getType(
Call->Arguments[1]));
1994 SPIRV::BuiltIn::BuiltIn
Value =
1995 SPIRV::lookupGetBuiltin(
Call->Builtin->Name,
Call->Builtin->Set)->
Value;
1996 const bool IsDefaultOne = (
Value == SPIRV::BuiltIn::GlobalSize ||
1997 Value == SPIRV::BuiltIn::NumWorkgroups ||
1998 Value == SPIRV::BuiltIn::WorkgroupSize ||
1999 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);
2009 SPIRV::lookupImageQueryBuiltin(Builtin->
Name, Builtin->
Set)->Component;
2013 unsigned NumExpectedRetComponents =
2014 Call->ReturnType->getOpcode() == SPIRV::OpTypeVector
2015 ?
Call->ReturnType->getOperand(2).getImm()
2022 if (NumExpectedRetComponents != NumActualRetComponents) {
2023 unsigned Bitwidth =
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt
2024 ?
Call->ReturnType->getOperand(1).getImm()
2031 IntTy, NumActualRetComponents, MIRBuilder,
true);
2036 IsDimBuf ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;
2043 if (NumExpectedRetComponents == NumActualRetComponents)
2045 if (NumExpectedRetComponents == 1) {
2047 unsigned ExtractedComposite =
2048 Component == 3 ? NumActualRetComponents - 1 : Component;
2049 assert(ExtractedComposite < NumActualRetComponents &&
2050 "Invalid composite index!");
2053 if (QueryResultType->
getOpcode() == SPIRV::OpTypeVector) {
2055 if (TypeReg != NewTypeReg &&
2057 TypeReg = NewTypeReg;
2059 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2063 .
addImm(ExtractedComposite);
2064 if (NewType !=
nullptr)
2069 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpVectorShuffle)
2074 for (
unsigned i = 0; i < NumExpectedRetComponents; ++i)
2075 MIB.
addImm(i < NumActualRetComponents ? i : 0xffffffff);
2083 assert(
Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&
2084 "Image samples query result must be of int type!");
2089 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2092 SPIRV::Dim::Dim ImageDimensionality =
static_cast<SPIRV::Dim::Dim
>(
2094 (void)ImageDimensionality;
2097 case SPIRV::OpImageQuerySamples:
2098 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&
2099 "Image must be of 2D dimensionality");
2101 case SPIRV::OpImageQueryLevels:
2102 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||
2103 ImageDimensionality == SPIRV::Dim::DIM_2D ||
2104 ImageDimensionality == SPIRV::Dim::DIM_3D ||
2105 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&
2106 "Image must be of 1D/2D/3D/Cube dimensionality");
2118static SPIRV::SamplerAddressingMode::SamplerAddressingMode
2120 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {
2121 case SPIRV::CLK_ADDRESS_CLAMP:
2122 return SPIRV::SamplerAddressingMode::Clamp;
2123 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:
2124 return SPIRV::SamplerAddressingMode::ClampToEdge;
2125 case SPIRV::CLK_ADDRESS_REPEAT:
2126 return SPIRV::SamplerAddressingMode::Repeat;
2127 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:
2128 return SPIRV::SamplerAddressingMode::RepeatMirrored;
2129 case SPIRV::CLK_ADDRESS_NONE:
2130 return SPIRV::SamplerAddressingMode::None;
2137 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;
2140static SPIRV::SamplerFilterMode::SamplerFilterMode
2142 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)
2143 return SPIRV::SamplerFilterMode::Linear;
2144 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)
2145 return SPIRV::SamplerFilterMode::Nearest;
2146 return SPIRV::SamplerFilterMode::Nearest;
2153 if (
Call->isSpirvOp())
2160 if (HasOclSampler) {
2174 Register SampledImage =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2185 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {
2189 MRI->createGenericVirtualRegister(GR->
getRegType(TempType));
2192 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2197 .
addImm(SPIRV::ImageOperand::Lod)
2199 MIRBuilder.
buildInstr(SPIRV::OpCompositeExtract)
2205 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2210 .
addImm(SPIRV::ImageOperand::Lod)
2213 }
else if (HasMsaa) {
2219 .
addImm(SPIRV::ImageOperand::Sample)
2234 if (
Call->isSpirvOp())
2249 if (
Call->Builtin->Name.contains_insensitive(
2250 "__translate_sampler_initializer")) {
2257 return Sampler.isValid();
2258 }
else if (
Call->Builtin->Name.contains_insensitive(
"__spirv_SampledImage")) {
2265 Call->ReturnRegister.isValid()
2266 ?
Call->ReturnRegister
2267 :
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2274 }
else if (
Call->Builtin->Name.contains_insensitive(
2275 "__spirv_ImageSampleExplicitLod")) {
2277 std::string ReturnType = DemangledCall.
str();
2278 if (DemangledCall.
contains(
"_R")) {
2279 ReturnType = ReturnType.substr(ReturnType.find(
"_R") + 2);
2280 ReturnType = ReturnType.substr(0, ReturnType.find(
'('));
2287 std::string DiagMsg =
2288 "Unable to recognize SPIRV type name: " + ReturnType;
2291 MIRBuilder.
buildInstr(SPIRV::OpImageSampleExplicitLod)
2296 .
addImm(SPIRV::ImageOperand::Lod)
2306 Call->Arguments[1],
Call->Arguments[2]);
2314 SPIRV::OpCompositeConstructContinuedINTEL,
2315 Call->Arguments,
Call->ReturnRegister,
2325 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2326 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&
2327 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&
2328 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;
2329 unsigned ArgSz =
Call->Arguments.size();
2330 unsigned LiteralIdx = 0;
2333 case SPIRV::OpCooperativeMatrixLoadKHR:
2334 LiteralIdx = ArgSz > 3 ? 3 : 0;
2336 case SPIRV::OpCooperativeMatrixStoreKHR:
2337 LiteralIdx = ArgSz > 4 ? 4 : 0;
2339 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2340 LiteralIdx = ArgSz > 7 ? 7 : 0;
2342 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2343 LiteralIdx = ArgSz > 8 ? 8 : 0;
2346 case SPIRV::OpCooperativeMatrixMulAddKHR:
2347 LiteralIdx = ArgSz > 3 ? 3 : 0;
2353 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2355 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)
2372 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {
2383 IsSet ? TypeReg :
Register(0), ImmArgs);
2392 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2396 case SPIRV::OpSpecConstant: {
2406 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
2407 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&
2408 "Argument should be either an int or floating-point constant");
2411 if (
Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {
2412 assert(ConstOperand.
isCImm() &&
"Int constant operand is expected");
2414 ? SPIRV::OpSpecConstantTrue
2415 : SPIRV::OpSpecConstantFalse;
2421 if (
Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {
2422 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)
2429 case SPIRV::OpSpecConstantComposite: {
2431 SPIRV::OpSpecConstantCompositeContinuedINTEL,
2432 Call->Arguments,
Call->ReturnRegister,
2447 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2458 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2468 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2482 const LLT ValTy =
MRI->getType(InputReg);
2483 Register ActualRetValReg =
MRI->createGenericVirtualRegister(ValTy);
2486 InputReg =
Call->Arguments[1];
2489 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {
2490 LLT InputLLT =
MRI->getType(InputReg);
2491 PtrInputReg =
MRI->createGenericVirtualRegister(InputLLT);
2497 MIRBuilder.
buildLoad(PtrInputReg, InputReg, *MMO1);
2498 MRI->setRegClass(PtrInputReg, &SPIRV::iIDRegClass);
2502 for (
unsigned index = 2; index < 7; index++) {
2517 unsigned Size = ValTy.getSizeInBytes();
2521 MRI->setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);
2522 MIRBuilder.
buildStore(ActualRetValReg,
Call->Arguments[0], *MMO);
2525 for (
unsigned index = 1; index < 6; index++)
2538 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2550 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2560 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2571 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2581 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2583 unsigned Scope = SPIRV::Scope::Workgroup;
2585 Scope = SPIRV::Scope::Subgroup;
2595 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2597 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;
2598 unsigned ArgSz =
Call->Arguments.size();
2608 IsSet ? TypeReg :
Register(0), ImmArgs);
2621 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2625 unsigned NumArgs =
Call->Arguments.size();
2627 Register GlobalWorkSize =
Call->Arguments[NumArgs < 4 ? 1 : 2];
2629 NumArgs == 2 ?
Register(0) :
Call->Arguments[NumArgs < 4 ? 2 : 3];
2634 if (SpvTy->
getOpcode() == SPIRV::OpTypePointer) {
2640 unsigned Size =
Call->Builtin->Name ==
"ndrange_3D" ? 3 : 2;
2645 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
2646 GlobalWorkSize =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2655 SpvFieldTy, *ST.getInstrInfo());
2660 LocalWorkSize = Const;
2661 if (!GlobalWorkOffset.
isValid())
2662 GlobalWorkOffset = Const;
2670 .
addUse(GlobalWorkOffset);
2684 SPIRV::AccessQualifier::ReadWrite,
true);
2692 bool IsSpirvOp =
Call->isSpirvOp();
2693 bool HasEvents =
Call->Builtin->Name.contains(
"events") || IsSpirvOp;
2700 if (
Call->Builtin->Name.contains(
"_varargs") || IsSpirvOp) {
2701 const unsigned LocalSizeArrayIdx = HasEvents ? 9 : 6;
2709 assert(LocalSizeTy &&
"Local size type is expected");
2715 Int32Ty, MIRBuilder, SPIRV::StorageClass::Function);
2716 for (
unsigned I = 0;
I < LocalSizeNum; ++
I) {
2718 MRI->setType(
Reg, LLType);
2732 auto MIB = MIRBuilder.
buildInstr(SPIRV::OpEnqueueKernel)
2737 const unsigned BlockFIdx = HasEvents ? 6 : 3;
2738 for (
unsigned i = 0; i < BlockFIdx; i++)
2739 MIB.addUse(
Call->Arguments[i]);
2746 MIB.addUse(NullPtr);
2747 MIB.addUse(NullPtr);
2755 Register BlockLiteralReg =
Call->Arguments[BlockFIdx + 1];
2757 MIB.addUse(BlockLiteralReg);
2767 for (
unsigned i = 0; i < LocalSizes.
size(); i++)
2768 MIB.addUse(LocalSizes[i]);
2778 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2781 case SPIRV::OpRetainEvent:
2782 case SPIRV::OpReleaseEvent:
2784 case SPIRV::OpCreateUserEvent:
2785 case SPIRV::OpGetDefaultQueue:
2789 case SPIRV::OpIsValidEvent:
2794 case SPIRV::OpSetUserEventStatus:
2798 case SPIRV::OpCaptureEventProfilingInfo:
2803 case SPIRV::OpBuildNDRange:
2805 case SPIRV::OpEnqueueKernel:
2818 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2820 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;
2822 if (
Call->isSpirvOp())
2829 case SPIRV::OpGroupAsyncCopy: {
2831 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent
2835 unsigned NumArgs =
Call->Arguments.size();
2845 ?
Call->Arguments[3]
2848 if (NewType !=
nullptr)
2853 case SPIRV::OpGroupWaitEvents:
2869 SPIRV::lookupConvertBuiltin(
Call->Builtin->Name,
Call->Builtin->Set);
2871 if (!Builtin &&
Call->isSpirvOp()) {
2874 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
2879 assert(Builtin &&
"Conversion builtin not found.");
2882 SPIRV::Decoration::SaturatedConversion, {});
2885 SPIRV::Decoration::FPRoundingMode,
2886 {(unsigned)Builtin->RoundingMode});
2888 std::string NeedExtMsg;
2889 bool IsRightComponentsNumber =
true;
2890 unsigned Opcode = SPIRV::OpNop;
2897 : SPIRV::OpSatConvertSToU;
2900 : SPIRV::OpSConvert;
2902 SPIRV::OpTypeFloat)) {
2906 &MIRBuilder.
getMF().getSubtarget());
2907 if (!ST->canUseExtension(
2908 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
2909 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
2910 IsRightComponentsNumber =
2913 Opcode = SPIRV::OpConvertBF16ToFINTEL;
2915 bool IsSourceSigned =
2917 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;
2921 SPIRV::OpTypeFloat)) {
2927 &MIRBuilder.
getMF().getSubtarget());
2928 if (!ST->canUseExtension(
2929 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))
2930 NeedExtMsg =
"SPV_INTEL_bfloat16_conversion";
2931 IsRightComponentsNumber =
2934 Opcode = SPIRV::OpConvertFToBF16INTEL;
2937 : SPIRV::OpConvertFToU;
2940 SPIRV::OpTypeFloat)) {
2943 &MIRBuilder.
getMF().getSubtarget());
2944 if (!ST->canUseExtension(
2945 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))
2946 NeedExtMsg =
"SPV_INTEL_tensor_float32_conversion";
2947 IsRightComponentsNumber =
2950 Opcode = SPIRV::OpRoundFToTF32INTEL;
2953 Opcode = SPIRV::OpFConvert;
2958 if (!NeedExtMsg.empty()) {
2959 std::string DiagMsg = std::string(Builtin->
Name) +
2960 ": the builtin requires the following SPIR-V "
2965 if (!IsRightComponentsNumber) {
2966 std::string DiagMsg =
2967 std::string(Builtin->
Name) +
2968 ": result and argument must have the same number of components";
2971 assert(Opcode != SPIRV::OpNop &&
2972 "Conversion between the types not implemented!");
2986 SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->Name,
2987 Call->Builtin->Set);
2993 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
3010 const auto *Builtin =
Call->Builtin;
3013 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;
3019 LLT PtrTy =
MRI->getType(
Call->Arguments[0]);
3020 DestReg =
MRI->createGenericVirtualRegister(PtrTy);
3021 MRI->setRegClass(DestReg, &SPIRV::pIDRegClass);
3024 MIB.addDef(DestReg);
3027 MIB.addDef(
Call->ReturnRegister);
3030 for (
unsigned i = IsVoid ? 1 : 0; i <
Call->Arguments.size(); ++i) {
3033 if (
DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&
3034 DefMI->getOperand(1).isCImm()) {
3041 LLT PtrTy =
MRI->getType(
Call->Arguments[0]);
3056 SPIRV::lookupNativeBuiltin(Builtin->
Name, Builtin->
Set)->Opcode;
3057 bool IsLoad = Opcode == SPIRV::OpLoad;
3061 MIB.addDef(
Call->ReturnRegister);
3069 MIB.addUse(
Call->Arguments[1]);
3071 unsigned NumArgs =
Call->Arguments.size();
3072 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)
3074 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)
3087std::tuple<int, unsigned, unsigned>
3089 SPIRV::InstructionSet::InstructionSet Set) {
3092 std::unique_ptr<const IncomingCall>
Call =
3095 return std::make_tuple(-1, 0, 0);
3097 switch (
Call->Builtin->Group) {
3098 case SPIRV::Relational:
3100 case SPIRV::Barrier:
3101 case SPIRV::CastToPtr:
3102 case SPIRV::ImageMiscQuery:
3103 case SPIRV::SpecConstant:
3104 case SPIRV::Enqueue:
3105 case SPIRV::AsyncCopy:
3106 case SPIRV::LoadStore:
3107 case SPIRV::CoopMatr:
3109 SPIRV::lookupNativeBuiltin(
Call->Builtin->Name,
Call->Builtin->Set))
3110 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3112 case SPIRV::Extended:
3113 if (
const auto *R = SPIRV::lookupExtendedBuiltin(
Call->Builtin->Name,
3114 Call->Builtin->Set))
3115 return std::make_tuple(
Call->Builtin->Group, 0, R->Number);
3117 case SPIRV::VectorLoadStore:
3118 if (
const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(
Call->Builtin->Name,
3119 Call->Builtin->Set))
3120 return std::make_tuple(SPIRV::Extended, 0, R->Number);
3123 if (
const auto *R = SPIRV::lookupGroupBuiltin(
Call->Builtin->Name))
3124 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3126 case SPIRV::AtomicFloating:
3127 if (
const auto *R = SPIRV::lookupAtomicFloatingBuiltin(
Call->Builtin->Name))
3128 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3130 case SPIRV::IntelSubgroups:
3131 if (
const auto *R = SPIRV::lookupIntelSubgroupsBuiltin(
Call->Builtin->Name))
3132 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3134 case SPIRV::GroupUniform:
3135 if (
const auto *R = SPIRV::lookupGroupUniformBuiltin(
Call->Builtin->Name))
3136 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3138 case SPIRV::IntegerDot:
3140 SPIRV::lookupIntegerDotProductBuiltin(
Call->Builtin->Name))
3141 return std::make_tuple(
Call->Builtin->Group, R->Opcode, 0);
3143 case SPIRV::WriteImage:
3144 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpImageWrite, 0);
3146 return std::make_tuple(
Call->Builtin->Group, TargetOpcode::G_SELECT, 0);
3147 case SPIRV::Construct:
3148 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpCompositeConstruct,
3150 case SPIRV::KernelClock:
3151 return std::make_tuple(
Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);
3153 return std::make_tuple(-1, 0, 0);
3155 return std::make_tuple(-1, 0, 0);
3159 SPIRV::InstructionSet::InstructionSet Set,
3164 LLVM_DEBUG(
dbgs() <<
"Lowering builtin call: " << DemangledCall <<
"\n");
3168 assert(SpvType &&
"Inconsistent return register: expected valid type info");
3169 std::unique_ptr<const IncomingCall>
Call =
3174 return std::nullopt;
3178 assert(Args.size() >=
Call->Builtin->MinNumArgs &&
3179 "Too few arguments to generate the builtin");
3180 if (
Call->Builtin->MaxNumArgs && Args.size() >
Call->Builtin->MaxNumArgs)
3181 LLVM_DEBUG(
dbgs() <<
"More arguments provided than required!\n");
3184 switch (
Call->Builtin->Group) {
3185 case SPIRV::Extended:
3187 case SPIRV::Relational:
3191 case SPIRV::Variable:
3195 case SPIRV::AtomicFloating:
3197 case SPIRV::Barrier:
3199 case SPIRV::CastToPtr:
3202 case SPIRV::IntegerDot:
3206 case SPIRV::ICarryBorrow:
3208 case SPIRV::GetQuery:
3210 case SPIRV::ImageSizeQuery:
3212 case SPIRV::ImageMiscQuery:
3214 case SPIRV::ReadImage:
3216 case SPIRV::WriteImage:
3218 case SPIRV::SampleImage:
3222 case SPIRV::Construct:
3224 case SPIRV::SpecConstant:
3226 case SPIRV::Enqueue:
3228 case SPIRV::AsyncCopy:
3230 case SPIRV::Convert:
3232 case SPIRV::VectorLoadStore:
3234 case SPIRV::LoadStore:
3236 case SPIRV::IntelSubgroups:
3238 case SPIRV::GroupUniform:
3240 case SPIRV::KernelClock:
3242 case SPIRV::CoopMatr:
3244 case SPIRV::ExtendedBitOps:
3246 case SPIRV::BindlessINTEL:
3248 case SPIRV::TernaryBitwiseINTEL:
3250 case SPIRV::Block2DLoadStore:
3254 case SPIRV::PredicatedLoadStore:
3256 case SPIRV::BlockingPipes:
3258 case SPIRV::ArbitraryPrecisionFixedPoint:
3260 case SPIRV::ImageChannelDataTypes:
3262 case SPIRV::ArbitraryFloatingPoint:
3273 [[maybe_unused]]
bool IsOCLBuiltinType = TypeStr.
consume_front(
"ocl_");
3274 assert(IsOCLBuiltinType &&
"Invalid OpenCL builtin prefix");
3291 unsigned VecElts = 0;
3302 TypeStr = TypeStr.
substr(0, TypeStr.
find(
']'));
3314 auto Pos1 = DemangledCall.
find(
'(');
3317 auto Pos2 = DemangledCall.
find(
')');
3320 DemangledCall.
slice(Pos1 + 1, Pos2)
3321 .
split(BuiltinArgsTypeStrs,
',', -1,
false);
3329 if (ArgIdx >= BuiltinArgsTypeStrs.
size())
3331 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();
3340#define GET_BuiltinTypes_DECL
3341#define GET_BuiltinTypes_IMPL
3348#define GET_OpenCLTypes_DECL
3349#define GET_OpenCLTypes_IMPL
3351#include "SPIRVGenTables.inc"
3359 if (Name.starts_with(
"void"))
3361 else if (Name.starts_with(
"int") || Name.starts_with(
"uint"))
3363 else if (Name.starts_with(
"float"))
3365 else if (Name.starts_with(
"half"))
3378 unsigned Opcode = TypeRecord->
Opcode;
3393 "Invalid number of parameters for SPIR-V pipe builtin!");
3396 SPIRV::AccessQualifier::AccessQualifier(
3404 "Invalid number of parameters for SPIR-V coop matrices builtin!");
3406 "SPIR-V coop matrices builtin type must have a type parameter!");
3409 SPIRV::AccessQualifier::ReadWrite,
true);
3412 MIRBuilder, ExtensionType, ElemType, ExtensionType->
getIntParameter(0),
3421 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);
3430 "Inline SPIR-V type builtin takes an opcode, size, and alignment "
3437 if (ParamEType->getName() ==
"spirv.IntegralConstant") {
3438 assert(ParamEType->getNumTypeParameters() == 1 &&
3439 "Inline SPIR-V integral constant builtin must have a type "
3441 assert(ParamEType->getNumIntParameters() == 1 &&
3442 "Inline SPIR-V integral constant builtin must have a "
3445 auto OperandValue = ParamEType->getIntParameter(0);
3446 auto *OperandType = ParamEType->getTypeParameter(0);
3449 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3452 OperandValue, MIRBuilder, OperandSPIRVType,
true)));
3454 }
else if (ParamEType->getName() ==
"spirv.Literal") {
3455 assert(ParamEType->getNumTypeParameters() == 0 &&
3456 "Inline SPIR-V literal builtin does not take type "
3458 assert(ParamEType->getNumIntParameters() == 1 &&
3459 "Inline SPIR-V literal builtin must have an integer "
3462 auto OperandValue = ParamEType->getIntParameter(0);
3469 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
true);
3481 "Vulkan buffers have exactly one type for the type of the buffer.");
3483 "Vulkan buffer have 2 integer parameters: storage class and is "
3487 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
3497 "Vulkan push constants have exactly one type as argument.");
3511 StringRef NameWithParameters = TypeName;
3518 SPIRV::lookupOpenCLType(NameWithParameters);
3521 NameWithParameters);
3529 "Unknown builtin opaque type!");
3533 if (!NameWithParameters.
contains(
'_'))
3537 unsigned BaseNameLength = NameWithParameters.
find(
'_') - 1;
3541 bool HasTypeParameter = !
isDigit(Parameters[0][0]);
3542 if (HasTypeParameter)
3545 for (
unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {
3546 unsigned IntParameter = 0;
3547 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);
3550 "Invalid format of SPIR-V builtin parameter literal!");
3554 NameWithParameters.
substr(0, BaseNameLength),
3555 TypeParameters, IntParameters);
3559 SPIRV::AccessQualifier::AccessQualifier AccessQual,
3581 if (Name ==
"spirv.Type") {
3583 }
else if (Name ==
"spirv.VulkanBuffer") {
3585 }
else if (Name ==
"spirv.Padding") {
3587 }
else if (Name ==
"spirv.PushConstant") {
3589 }
else if (Name ==
"spirv.Layout") {
3603 switch (TypeRecord->
Opcode) {
3604 case SPIRV::OpTypeImage:
3607 case SPIRV::OpTypePipe:
3610 case SPIRV::OpTypeDeviceEvent:
3613 case SPIRV::OpTypeSampler:
3616 case SPIRV::OpTypeSampledImage:
3619 case SPIRV::OpTypeCooperativeMatrixKHR:
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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.
ArrayRef - 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...
@ 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.
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".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
This is an important class for using LLVM in a threaded context.
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
LLVMContext & getContext() const
MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_SELECT Tst, Op0, Op1.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)
Build and insert a G_INTRINSIC instruction.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void copyIRFlags(const Instruction &I)
Copy all flags to MachineInst MIFlags.
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 GlobalValue * getGlobal() const
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.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateVulkanPushConstantType(MachineIRBuilder &MIRBuilder, Type *ElemType)
SPIRVType * getOrCreatePaddingType(MachineIRBuilder &MIRBuilder)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
Register buildGlobalVariable(Register Reg, SPIRVType *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)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
SPIRVType * getOrCreateUnknownType(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode, const ArrayRef< MCOperand > Operands)
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
unsigned getPointerSize() const
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType, SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr=false)
SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)
SPIRVType * getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr=false)
Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)
SPIRVType * getImageType(const TargetExtType *ExtensionType, const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR, bool ZeroAsNull=true)
LLT getRegType(SPIRVType *SpvType) const
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)
Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
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.
StringRef - 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
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
bool contains_insensitive(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - 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 struct types.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
ArrayRef< Type * > type_params() const
Return the type parameters for this particular target extension type.
unsigned getNumIntParameters() const
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Type * getTypeParameter(unsigned i) const
unsigned getNumTypeParameters() const
unsigned getIntParameter(unsigned i) const
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI StringRef getStructName() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
LLVM_ABI Value(Type *Ty, unsigned scid)
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents a version number in the form major[.minor[.subminor[.build]]].
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
LLVM_C_ABI LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount)
Create a vector type that contains a defined type and has a specific number of elements.
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
Type * parseBuiltinCallArgumentType(StringRef TypeStr, LLVMContext &Ctx)
bool parseBuiltinTypeStr(SmallVector< StringRef, 10 > &BuiltinArgsTypeStrs, const StringRef DemangledCall, LLVMContext &Ctx)
std::optional< bool > lowerBuiltin(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR, const CallBase &CB)
std::tuple< int, unsigned, unsigned > mapBuiltinToOpcode(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)
Helper function for finding a builtin function attributes by a demangled function name.
Type * parseBuiltinCallArgumentBaseType(const StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)
Parses the provided ArgIdx argument base type in the DemangledCall skeleton.
TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)
Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...
SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's 2d block io instructions.
static SPIRVType * getVulkanBufferType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateExtInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)
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 SPIRVType * getInlineSpirvType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateConstructInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic flag instructions (e.g.
static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRV::SamplerFilterMode::SamplerFilterMode getSamplerFilterModeFromBitmask(unsigned Bitmask)
static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic store instruction.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building extended bit operations.
static const Type * getBlockStructType(Register ParamReg, MachineRegisterInfo *MRI)
static bool generateGroupInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
FPDecorationId demangledPostfixToDecorationId(const std::string &S)
void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...
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 bool generateICarryBorrowInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildScopeReg(Register CLScopeRegister, SPIRV::Scope::Scope Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI)
static std::tuple< Register, SPIRVType * > buildBoolRegister(MachineIRBuilder &MIRBuilder, const SPIRVType *ResultType, SPIRVGlobalRegistry *GR)
Helper function building either a resulting scalar or vector bool register depending on the expected ...
static unsigned getNumSizeComponents(SPIRVType *imgType)
Helper function for obtaining the number of size components.
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
static Register buildConstantIntReg32(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVType * getSampledImageType(const TargetExtType *OpaqueType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
static bool generateSampleImageInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateBarrierInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
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 SPIRVType * getCoopMatrType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildImageChannelDataTypeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateKernelClockInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static void setRegClassIfNull(Register Reg, MachineRegisterInfo *MRI, SPIRVGlobalRegistry *GR)
static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateWaveInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
static bool buildBarrierInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building barriers, i.e., memory/control ordering operations.
static bool generateAsyncCopy(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVType * getVulkanPushConstantType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRV::Scope::Scope getSPIRVScope(SPIRV::CLMemoryScope ClScope)
static bool buildAPFixedPointInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVType * getSamplerType(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateBlockingPipesInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static Register buildLoadInst(SPIRVType *BaseType, Register PtrRegister, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, LLT LowLevelType, Register DestinationReg=Register(0))
Helper function for building a load instruction loading into the DestinationReg.
static bool generateEnqueueInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
static bool buildSelectInst(MachineIRBuilder &MIRBuilder, Register ReturnRegister, Register SourceRegister, const SPIRVType *ReturnType, SPIRVGlobalRegistry *GR)
Helper function for building either a vector or scalar select instruction depending on the expected R...
static const Type * getMachineInstrType(MachineInstr *MI)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
static SPIRV::SamplerAddressingMode::SamplerAddressingMode getSamplerAddressingModeFromBitmask(unsigned Bitmask)
static bool generateAtomicInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
const MachineInstr SPIRVType
static SPIRVType * getLayoutType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateDotOrFMulInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder, SPIRVType *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...
static bool generateConvertInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static 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 Register buildMemSemanticsReg(Register SemanticsRegister, Register PtrRegister, unsigned &Semantics, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static unsigned getConstFromIntrinsic(Register Reg, MachineRegisterInfo *MRI)
static bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateSelectInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)
static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic load instruction.
static bool generateIntelSubgroupsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildPipeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, unsigned Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateSpecConstantInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVType * getOrCreateSPIRVDeviceEventPointer(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
static bool generateVectorLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool genWorkgroupQuery(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, uint64_t DefaultValue)
static bool generateCoopMatrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SmallVector< Register > getBuiltinCallArguments(const SPIRV::IncomingCall *Call, uint32_t BuiltinNumber, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's bindless image instructions.
static std::unique_ptr< const SPIRV::IncomingCall > lookupBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, Register ReturnRegister, const SPIRVType *ReturnType, const SmallVectorImpl< Register > &Arguments)
Looks up the demangled builtin call in the SPIRVBuiltins.td records using the provided DemangledCall ...
static bool buildAtomicFloatingRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic floating-type instruction.
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
constexpr unsigned BitWidth
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateReadImageInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool hasBuiltinTypePrefix(StringRef Name)
static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
static bool generatePipeInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building Intel's OpBitwiseFunctionINTEL instruction.
static bool generateAPFixedPointInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building atomic instructions.
static SPIRV::MemorySemantics::MemorySemantics getSPIRVMemSemantics(std::memory_order MemOrder)
static bool generateRelationalInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static 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 SPIRVType * getPipeType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static Type * parseTypeString(const StringRef Name, LLVMContext &Context)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
static bool generatePredicatedLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateAtomicFloatingInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool generateAFPInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static bool buildNDRange(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static SPIRVType * getNonParameterizedType(const TargetExtType *ExtensionType, const SPIRV::BuiltinType *TypeRecord, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
static MachineInstr * getBlockStructInstr(Register ParamReg, MachineRegisterInfo *MRI)
static bool buildOpFromWrapper(MachineIRBuilder &MIRBuilder, unsigned Opcode, const SPIRV::IncomingCall *Call, Register TypeReg, ArrayRef< uint32_t > ImmArgs={})
static unsigned getSamplerParamFromBitmask(unsigned Bitmask)
static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, const SPIRV::DemangledBuiltin *Builtin, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Helper function for building an atomic compare-exchange instruction.
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)
static bool generateBuiltinVar(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
This class contains a discriminated union of information about pointers in memory operands,...
FPRoundingMode::FPRoundingMode RoundingMode
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
InstructionSet::InstructionSet Set
const SmallVectorImpl< Register > & Arguments
const std::string BuiltinName
const SPIRVType * ReturnType
const Register ReturnRegister
const DemangledBuiltin * Builtin
IncomingCall(const std::string BuiltinName, const DemangledBuiltin *Builtin, const Register ReturnRegister, const SPIRVType *ReturnType, const SmallVectorImpl< Register > &Arguments)
InstructionSet::InstructionSet Set
StringRef SpirvTypeLiteral
InstructionSet::InstructionSet Set
FPRoundingMode::FPRoundingMode RoundingMode