32#include "llvm/IR/IntrinsicsSPIRV.h"
36#define DEBUG_TYPE "spirv-isel"
43 std::vector<std::pair<SPIRV::InstructionSet::InstructionSet, uint32_t>>;
47llvm::SPIRV::SelectionControl::SelectionControl
48getSelectionOperandForImm(
int Imm) {
50 return SPIRV::SelectionControl::Flatten;
52 return SPIRV::SelectionControl::DontFlatten;
54 return SPIRV::SelectionControl::None;
58#define GET_GLOBALISEL_PREDICATE_BITSET
59#include "SPIRVGenGlobalISel.inc"
60#undef GET_GLOBALISEL_PREDICATE_BITSET
87#define GET_GLOBALISEL_PREDICATES_DECL
88#include "SPIRVGenGlobalISel.inc"
89#undef GET_GLOBALISEL_PREDICATES_DECL
91#define GET_GLOBALISEL_TEMPORARIES_DECL
92#include "SPIRVGenGlobalISel.inc"
93#undef GET_GLOBALISEL_TEMPORARIES_DECL
117 unsigned BitSetOpcode)
const;
121 unsigned BitSetOpcode)
const;
125 unsigned BitSetOpcode,
bool SwapPrimarySide)
const;
129 unsigned BitSetOpcode,
130 bool SwapPrimarySide)
const;
137 unsigned Opcode)
const;
140 unsigned Opcode)
const;
160 unsigned NegateOpcode = 0)
const;
220 template <
bool Signed>
223 template <
bool Signed>
244 bool IsSigned,
unsigned Opcode)
const;
246 bool IsSigned)
const;
252 bool IsSigned)
const;
291 GL::GLSLExtInst GLInst)
const;
296 GL::GLSLExtInst GLInst)
const;
318 bool selectCounterHandleFromBinding(
Register &ResVReg,
329 bool selectResourceNonUniformIndex(
Register &ResVReg,
341 std::pair<Register, bool>
343 const SPIRVType *ResType =
nullptr)
const;
355 SPIRV::StorageClass::StorageClass SC)
const;
362 SPIRV::StorageClass::StorageClass SC,
374 bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
377 bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
382 void decorateUsesAsNonUniform(
Register &NonUniformReg)
const;
386bool sampledTypeIsSignedInteger(
const llvm::Type *HandleType) {
388 if (
TET->getTargetExtName() ==
"spirv.Image") {
391 assert(
TET->getTargetExtName() ==
"spirv.SignedImage");
392 return TET->getTypeParameter(0)->isIntegerTy();
396#define GET_GLOBALISEL_IMPL
397#include "SPIRVGenGlobalISel.inc"
398#undef GET_GLOBALISEL_IMPL
404 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
407#include
"SPIRVGenGlobalISel.inc"
410#include
"SPIRVGenGlobalISel.inc"
422 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
426void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
427 if (HasVRegsReset == &MF)
432 for (
unsigned I = 0,
E =
MRI.getNumVirtRegs();
I !=
E; ++
I) {
434 LLT RegType =
MRI.getType(
Reg);
442 for (
const auto &
MBB : MF) {
443 for (
const auto &
MI :
MBB) {
446 if (
MI.getOpcode() != SPIRV::ASSIGN_TYPE)
450 LLT DstType =
MRI.getType(DstReg);
452 LLT SrcType =
MRI.getType(SrcReg);
453 if (DstType != SrcType)
454 MRI.setType(DstReg,
MRI.getType(SrcReg));
456 const TargetRegisterClass *DstRC =
MRI.getRegClassOrNull(DstReg);
457 const TargetRegisterClass *SrcRC =
MRI.getRegClassOrNull(SrcReg);
458 if (DstRC != SrcRC && SrcRC)
459 MRI.setRegClass(DstReg, SrcRC);
475 case TargetOpcode::G_CONSTANT:
476 case TargetOpcode::G_FCONSTANT:
477 case TargetOpcode::G_IMPLICIT_DEF:
479 case TargetOpcode::G_INTRINSIC:
480 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
481 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
483 Intrinsic::spv_const_composite;
484 case TargetOpcode::G_BUILD_VECTOR:
485 case TargetOpcode::G_SPLAT_VECTOR: {
496 case SPIRV::OpConstantTrue:
497 case SPIRV::OpConstantFalse:
498 case SPIRV::OpConstantI:
499 case SPIRV::OpConstantF:
500 case SPIRV::OpConstantComposite:
501 case SPIRV::OpConstantCompositeContinuedINTEL:
502 case SPIRV::OpConstantSampler:
503 case SPIRV::OpConstantNull:
505 case SPIRV::OpConstantFunctionPointerINTEL:
531 case Intrinsic::spv_all:
532 case Intrinsic::spv_alloca:
533 case Intrinsic::spv_any:
534 case Intrinsic::spv_bitcast:
535 case Intrinsic::spv_const_composite:
536 case Intrinsic::spv_cross:
537 case Intrinsic::spv_degrees:
538 case Intrinsic::spv_distance:
539 case Intrinsic::spv_extractelt:
540 case Intrinsic::spv_extractv:
541 case Intrinsic::spv_faceforward:
542 case Intrinsic::spv_fdot:
543 case Intrinsic::spv_firstbitlow:
544 case Intrinsic::spv_firstbitshigh:
545 case Intrinsic::spv_firstbituhigh:
546 case Intrinsic::spv_frac:
547 case Intrinsic::spv_gep:
548 case Intrinsic::spv_global_offset:
549 case Intrinsic::spv_global_size:
550 case Intrinsic::spv_group_id:
551 case Intrinsic::spv_insertelt:
552 case Intrinsic::spv_insertv:
553 case Intrinsic::spv_isinf:
554 case Intrinsic::spv_isnan:
555 case Intrinsic::spv_lerp:
556 case Intrinsic::spv_length:
557 case Intrinsic::spv_normalize:
558 case Intrinsic::spv_num_subgroups:
559 case Intrinsic::spv_num_workgroups:
560 case Intrinsic::spv_ptrcast:
561 case Intrinsic::spv_radians:
562 case Intrinsic::spv_reflect:
563 case Intrinsic::spv_refract:
564 case Intrinsic::spv_resource_getpointer:
565 case Intrinsic::spv_resource_handlefrombinding:
566 case Intrinsic::spv_resource_handlefromimplicitbinding:
567 case Intrinsic::spv_resource_nonuniformindex:
568 case Intrinsic::spv_rsqrt:
569 case Intrinsic::spv_saturate:
570 case Intrinsic::spv_sdot:
571 case Intrinsic::spv_sign:
572 case Intrinsic::spv_smoothstep:
573 case Intrinsic::spv_step:
574 case Intrinsic::spv_subgroup_id:
575 case Intrinsic::spv_subgroup_local_invocation_id:
576 case Intrinsic::spv_subgroup_max_size:
577 case Intrinsic::spv_subgroup_size:
578 case Intrinsic::spv_thread_id:
579 case Intrinsic::spv_thread_id_in_group:
580 case Intrinsic::spv_udot:
581 case Intrinsic::spv_undef:
582 case Intrinsic::spv_value_md:
583 case Intrinsic::spv_workgroup_size:
595 case SPIRV::OpTypeVoid:
596 case SPIRV::OpTypeBool:
597 case SPIRV::OpTypeInt:
598 case SPIRV::OpTypeFloat:
599 case SPIRV::OpTypeVector:
600 case SPIRV::OpTypeMatrix:
601 case SPIRV::OpTypeImage:
602 case SPIRV::OpTypeSampler:
603 case SPIRV::OpTypeSampledImage:
604 case SPIRV::OpTypeArray:
605 case SPIRV::OpTypeRuntimeArray:
606 case SPIRV::OpTypeStruct:
607 case SPIRV::OpTypeOpaque:
608 case SPIRV::OpTypePointer:
609 case SPIRV::OpTypeFunction:
610 case SPIRV::OpTypeEvent:
611 case SPIRV::OpTypeDeviceEvent:
612 case SPIRV::OpTypeReserveId:
613 case SPIRV::OpTypeQueue:
614 case SPIRV::OpTypePipe:
615 case SPIRV::OpTypeForwardPointer:
616 case SPIRV::OpTypePipeStorage:
617 case SPIRV::OpTypeNamedBarrier:
618 case SPIRV::OpTypeAccelerationStructureNV:
619 case SPIRV::OpTypeCooperativeMatrixNV:
620 case SPIRV::OpTypeCooperativeMatrixKHR:
630 if (
MI.getNumDefs() == 0)
633 for (
const auto &MO :
MI.all_defs()) {
635 if (
Reg.isPhysical()) {
639 for (
const auto &
UseMI :
MRI.use_nodbg_instructions(
Reg)) {
640 if (
UseMI.getOpcode() != SPIRV::OpName) {
647 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE ||
MI.isFakeUse() ||
648 MI.isLifetimeMarker()) {
651 <<
"Not dead: Opcode is LOCAL_ESCAPE, fake use, or lifetime marker.\n");
662 if (
MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
663 MI.getOpcode() == TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS) {
666 LLVM_DEBUG(
dbgs() <<
"Dead: Intrinsic with no real side effects.\n");
671 if (
MI.mayStore() ||
MI.isCall() ||
672 (
MI.mayLoad() &&
MI.hasOrderedMemoryRef()) ||
MI.isPosition() ||
673 MI.isDebugInstr() ||
MI.isTerminator() ||
MI.isJumpTableDebugInfo()) {
674 LLVM_DEBUG(
dbgs() <<
"Not dead: instruction has side effects.\n");
685 LLVM_DEBUG(
dbgs() <<
"Dead: known opcode with no side effects\n");
692void SPIRVInstructionSelector::removeOpNamesForDeadMI(MachineInstr &
MI)
const {
694 for (
const auto &MO :
MI.all_defs()) {
698 SmallVector<MachineInstr *, 4> UselessOpNames;
699 for (MachineInstr &
UseMI :
MRI->use_nodbg_instructions(
Reg)) {
701 "There is still a use of the dead function.");
704 for (MachineInstr *OpNameMI : UselessOpNames) {
706 OpNameMI->eraseFromParent();
711void SPIRVInstructionSelector::removeDeadInstruction(MachineInstr &
MI)
const {
714 removeOpNamesForDeadMI(
MI);
715 MI.eraseFromParent();
718bool SPIRVInstructionSelector::select(MachineInstr &
I) {
719 resetVRegsType(*
I.getParent()->getParent());
721 assert(
I.getParent() &&
"Instruction should be in a basic block!");
722 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
727 removeDeadInstruction(
I);
734 if (Opcode == SPIRV::ASSIGN_TYPE) {
735 Register DstReg =
I.getOperand(0).getReg();
736 Register SrcReg =
I.getOperand(1).getReg();
737 auto *
Def =
MRI->getVRegDef(SrcReg);
739 Def->getOpcode() != TargetOpcode::G_CONSTANT &&
740 Def->getOpcode() != TargetOpcode::G_FCONSTANT) {
742 if (
Def->getOpcode() == TargetOpcode::G_SELECT) {
743 Register SelectDstReg =
Def->getOperand(0).getReg();
747 Def->removeFromParent();
748 MRI->replaceRegWith(DstReg, SelectDstReg);
750 I.removeFromParent();
752 Res = selectImpl(
I, *CoverageInfo);
754 if (!Res &&
Def->getOpcode() != TargetOpcode::G_CONSTANT) {
755 dbgs() <<
"Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
759 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
766 MRI->setRegClass(SrcReg,
MRI->getRegClass(DstReg));
767 MRI->replaceRegWith(SrcReg, DstReg);
769 I.removeFromParent();
771 }
else if (
I.getNumDefs() == 1) {
778 if (DeadMIs.contains(&
I)) {
782 removeDeadInstruction(
I);
786 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
787 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
793 bool HasDefs =
I.getNumDefs() > 0;
796 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
797 I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
798 if (spvSelect(ResVReg, ResType,
I)) {
800 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
803 I.removeFromParent();
811 case TargetOpcode::G_CONSTANT:
812 case TargetOpcode::G_FCONSTANT:
814 case TargetOpcode::G_SADDO:
815 case TargetOpcode::G_SSUBO:
822 MachineInstr &
I)
const {
823 const TargetRegisterClass *DstRC =
MRI->getRegClassOrNull(DestReg);
824 const TargetRegisterClass *SrcRC =
MRI->getRegClassOrNull(SrcReg);
825 if (DstRC != SrcRC && SrcRC)
826 MRI->setRegClass(DestReg, SrcRC);
827 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
828 TII.get(TargetOpcode::COPY))
834bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
836 MachineInstr &
I)
const {
837 const unsigned Opcode =
I.getOpcode();
839 return selectImpl(
I, *CoverageInfo);
841 case TargetOpcode::G_CONSTANT:
842 case TargetOpcode::G_FCONSTANT:
843 return selectConst(ResVReg, ResType,
I);
844 case TargetOpcode::G_GLOBAL_VALUE:
845 return selectGlobalValue(ResVReg,
I);
846 case TargetOpcode::G_IMPLICIT_DEF:
847 return selectOpUndef(ResVReg, ResType,
I);
848 case TargetOpcode::G_FREEZE:
849 return selectFreeze(ResVReg, ResType,
I);
851 case TargetOpcode::G_INTRINSIC:
852 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
853 case TargetOpcode::G_INTRINSIC_CONVERGENT:
854 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
855 return selectIntrinsic(ResVReg, ResType,
I);
856 case TargetOpcode::G_BITREVERSE:
857 return selectBitreverse(ResVReg, ResType,
I);
859 case TargetOpcode::G_BUILD_VECTOR:
860 return selectBuildVector(ResVReg, ResType,
I);
861 case TargetOpcode::G_SPLAT_VECTOR:
862 return selectSplatVector(ResVReg, ResType,
I);
864 case TargetOpcode::G_SHUFFLE_VECTOR: {
865 MachineBasicBlock &BB = *
I.getParent();
866 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
869 .
addUse(
I.getOperand(1).getReg())
870 .
addUse(
I.getOperand(2).getReg());
871 for (
auto V :
I.getOperand(3).getShuffleMask())
875 case TargetOpcode::G_MEMMOVE:
876 case TargetOpcode::G_MEMCPY:
877 case TargetOpcode::G_MEMSET:
878 return selectMemOperation(ResVReg,
I);
880 case TargetOpcode::G_ICMP:
881 return selectICmp(ResVReg, ResType,
I);
882 case TargetOpcode::G_FCMP:
883 return selectFCmp(ResVReg, ResType,
I);
885 case TargetOpcode::G_FRAME_INDEX:
886 return selectFrameIndex(ResVReg, ResType,
I);
888 case TargetOpcode::G_LOAD:
889 return selectLoad(ResVReg, ResType,
I);
890 case TargetOpcode::G_STORE:
891 return selectStore(
I);
893 case TargetOpcode::G_BR:
894 return selectBranch(
I);
895 case TargetOpcode::G_BRCOND:
896 return selectBranchCond(
I);
898 case TargetOpcode::G_PHI:
899 return selectPhi(ResVReg, ResType,
I);
901 case TargetOpcode::G_FPTOSI:
902 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
903 case TargetOpcode::G_FPTOUI:
904 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
906 case TargetOpcode::G_FPTOSI_SAT:
907 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
908 case TargetOpcode::G_FPTOUI_SAT:
909 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
911 case TargetOpcode::G_SITOFP:
912 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
913 case TargetOpcode::G_UITOFP:
914 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
916 case TargetOpcode::G_CTPOP:
917 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
918 case TargetOpcode::G_SMIN:
919 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
920 case TargetOpcode::G_UMIN:
921 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
923 case TargetOpcode::G_SMAX:
924 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
925 case TargetOpcode::G_UMAX:
926 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
928 case TargetOpcode::G_SCMP:
929 return selectSUCmp(ResVReg, ResType,
I,
true);
930 case TargetOpcode::G_UCMP:
931 return selectSUCmp(ResVReg, ResType,
I,
false);
932 case TargetOpcode::G_LROUND:
933 case TargetOpcode::G_LLROUND: {
935 MRI->createVirtualRegister(
MRI->getRegClass(ResVReg),
"lround");
936 MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
938 regForLround, *(
I.getParent()->getParent()));
940 I, CL::round, GL::Round);
942 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConvertFToS))
948 case TargetOpcode::G_STRICT_FMA:
949 case TargetOpcode::G_FMA:
950 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
952 case TargetOpcode::G_STRICT_FLDEXP:
953 return selectExtInst(ResVReg, ResType,
I, CL::ldexp);
955 case TargetOpcode::G_FPOW:
956 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
957 case TargetOpcode::G_FPOWI:
958 return selectExtInst(ResVReg, ResType,
I, CL::pown);
960 case TargetOpcode::G_FEXP:
961 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
962 case TargetOpcode::G_FEXP2:
963 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
964 case TargetOpcode::G_FMODF:
965 return selectModf(ResVReg, ResType,
I);
967 case TargetOpcode::G_FLOG:
968 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
969 case TargetOpcode::G_FLOG2:
970 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
971 case TargetOpcode::G_FLOG10:
972 return selectLog10(ResVReg, ResType,
I);
974 case TargetOpcode::G_FABS:
975 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
976 case TargetOpcode::G_ABS:
977 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
979 case TargetOpcode::G_FMINNUM:
980 case TargetOpcode::G_FMINIMUM:
981 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
982 case TargetOpcode::G_FMAXNUM:
983 case TargetOpcode::G_FMAXIMUM:
984 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
986 case TargetOpcode::G_FCOPYSIGN:
987 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
989 case TargetOpcode::G_FCEIL:
990 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
991 case TargetOpcode::G_FFLOOR:
992 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
994 case TargetOpcode::G_FCOS:
995 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
996 case TargetOpcode::G_FSIN:
997 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
998 case TargetOpcode::G_FTAN:
999 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
1000 case TargetOpcode::G_FACOS:
1001 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
1002 case TargetOpcode::G_FASIN:
1003 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
1004 case TargetOpcode::G_FATAN:
1005 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
1006 case TargetOpcode::G_FATAN2:
1007 return selectExtInst(ResVReg, ResType,
I, CL::atan2, GL::Atan2);
1008 case TargetOpcode::G_FCOSH:
1009 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
1010 case TargetOpcode::G_FSINH:
1011 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
1012 case TargetOpcode::G_FTANH:
1013 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
1015 case TargetOpcode::G_STRICT_FSQRT:
1016 case TargetOpcode::G_FSQRT:
1017 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
1019 case TargetOpcode::G_CTTZ:
1020 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1021 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
1022 case TargetOpcode::G_CTLZ:
1023 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1024 return selectExtInst(ResVReg, ResType,
I, CL::clz);
1026 case TargetOpcode::G_INTRINSIC_ROUND:
1027 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
1028 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1029 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
1030 case TargetOpcode::G_INTRINSIC_TRUNC:
1031 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
1032 case TargetOpcode::G_FRINT:
1033 case TargetOpcode::G_FNEARBYINT:
1034 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
1036 case TargetOpcode::G_SMULH:
1037 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
1038 case TargetOpcode::G_UMULH:
1039 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
1041 case TargetOpcode::G_SADDSAT:
1042 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
1043 case TargetOpcode::G_UADDSAT:
1044 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
1045 case TargetOpcode::G_SSUBSAT:
1046 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
1047 case TargetOpcode::G_USUBSAT:
1048 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
1050 case TargetOpcode::G_FFREXP:
1051 return selectFrexp(ResVReg, ResType,
I);
1053 case TargetOpcode::G_UADDO:
1054 return selectOverflowArith(ResVReg, ResType,
I,
1055 ResType->
getOpcode() == SPIRV::OpTypeVector
1056 ? SPIRV::OpIAddCarryV
1057 : SPIRV::OpIAddCarryS);
1058 case TargetOpcode::G_USUBO:
1059 return selectOverflowArith(ResVReg, ResType,
I,
1060 ResType->
getOpcode() == SPIRV::OpTypeVector
1061 ? SPIRV::OpISubBorrowV
1062 : SPIRV::OpISubBorrowS);
1063 case TargetOpcode::G_UMULO:
1064 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpUMulExtended);
1065 case TargetOpcode::G_SMULO:
1066 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpSMulExtended);
1068 case TargetOpcode::G_SEXT:
1069 return selectExt(ResVReg, ResType,
I,
true);
1070 case TargetOpcode::G_ANYEXT:
1071 case TargetOpcode::G_ZEXT:
1072 return selectExt(ResVReg, ResType,
I,
false);
1073 case TargetOpcode::G_TRUNC:
1074 return selectTrunc(ResVReg, ResType,
I);
1075 case TargetOpcode::G_FPTRUNC:
1076 case TargetOpcode::G_FPEXT:
1077 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
1079 case TargetOpcode::G_PTRTOINT:
1080 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
1081 case TargetOpcode::G_INTTOPTR:
1082 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
1083 case TargetOpcode::G_BITCAST:
1084 return selectBitcast(ResVReg, ResType,
I);
1085 case TargetOpcode::G_ADDRSPACE_CAST:
1086 return selectAddrSpaceCast(ResVReg, ResType,
I);
1087 case TargetOpcode::G_PTR_ADD: {
1089 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1093 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1094 (*II).getOpcode() == TargetOpcode::COPY ||
1095 (*II).getOpcode() == SPIRV::OpVariable) &&
1098 bool IsGVInit =
false;
1100 UseIt =
MRI->use_instr_begin(
I.getOperand(0).getReg()),
1101 UseEnd =
MRI->use_instr_end();
1102 UseIt != UseEnd; UseIt = std::next(UseIt)) {
1103 if ((*UseIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1104 (*UseIt).getOpcode() == SPIRV::OpSpecConstantOp ||
1105 (*UseIt).getOpcode() == SPIRV::OpVariable) {
1115 if (GVPointeeType && ResPointeeType && GVPointeeType != ResPointeeType) {
1118 Register NewVReg =
MRI->createGenericVirtualRegister(
MRI->getType(GV));
1119 MRI->setRegClass(NewVReg,
MRI->getRegClass(GV));
1128 "incompatible result and operand types in a bitcast");
1130 MachineInstrBuilder MIB =
1131 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitcast))
1138 ? SPIRV::OpInBoundsAccessChain
1139 : SPIRV::OpInBoundsPtrAccessChain))
1143 .
addUse(
I.getOperand(2).getReg())
1146 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1150 static_cast<uint32_t
>(SPIRV::Opcode::InBoundsPtrAccessChain))
1152 .
addUse(
I.getOperand(2).getReg())
1160 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1163 .
addImm(
static_cast<uint32_t
>(
1164 SPIRV::Opcode::InBoundsPtrAccessChain))
1167 .
addUse(
I.getOperand(2).getReg());
1171 case TargetOpcode::G_ATOMICRMW_OR:
1172 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
1173 case TargetOpcode::G_ATOMICRMW_ADD:
1174 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
1175 case TargetOpcode::G_ATOMICRMW_AND:
1176 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
1177 case TargetOpcode::G_ATOMICRMW_MAX:
1178 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
1179 case TargetOpcode::G_ATOMICRMW_MIN:
1180 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
1181 case TargetOpcode::G_ATOMICRMW_SUB:
1182 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
1183 case TargetOpcode::G_ATOMICRMW_XOR:
1184 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
1185 case TargetOpcode::G_ATOMICRMW_UMAX:
1186 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
1187 case TargetOpcode::G_ATOMICRMW_UMIN:
1188 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
1189 case TargetOpcode::G_ATOMICRMW_XCHG:
1190 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
1191 case TargetOpcode::G_ATOMIC_CMPXCHG:
1192 return selectAtomicCmpXchg(ResVReg, ResType,
I);
1194 case TargetOpcode::G_ATOMICRMW_FADD:
1195 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
1196 case TargetOpcode::G_ATOMICRMW_FSUB:
1198 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
1199 ResType->
getOpcode() == SPIRV::OpTypeVector
1201 : SPIRV::OpFNegate);
1202 case TargetOpcode::G_ATOMICRMW_FMIN:
1203 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
1204 case TargetOpcode::G_ATOMICRMW_FMAX:
1205 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
1207 case TargetOpcode::G_FENCE:
1208 return selectFence(
I);
1210 case TargetOpcode::G_STACKSAVE:
1211 return selectStackSave(ResVReg, ResType,
I);
1212 case TargetOpcode::G_STACKRESTORE:
1213 return selectStackRestore(
I);
1215 case TargetOpcode::G_UNMERGE_VALUES:
1221 case TargetOpcode::G_TRAP:
1222 case TargetOpcode::G_UBSANTRAP:
1223 case TargetOpcode::DBG_LABEL:
1225 case TargetOpcode::G_DEBUGTRAP:
1226 return selectDebugTrap(ResVReg, ResType,
I);
1233bool SPIRVInstructionSelector::selectDebugTrap(
Register ResVReg,
1235 MachineInstr &
I)
const {
1236 unsigned Opcode = SPIRV::OpNop;
1238 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
1242bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1245 GL::GLSLExtInst GLInst)
const {
1247 SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) {
1248 std::string DiagMsg;
1249 raw_string_ostream OS(DiagMsg);
1250 I.print(OS,
true,
false,
false,
false);
1251 DiagMsg +=
" is only supported with the GLSL extended instruction set.\n";
1254 return selectExtInst(ResVReg, ResType,
I,
1255 {{SPIRV::InstructionSet::GLSL_std_450, GLInst}});
1258bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1261 CL::OpenCLExtInst CLInst)
const {
1262 return selectExtInst(ResVReg, ResType,
I,
1263 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
1266bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1269 CL::OpenCLExtInst CLInst,
1270 GL::GLSLExtInst GLInst)
const {
1271 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1272 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1273 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
1276bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1281 for (
const auto &Ex : Insts) {
1282 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1283 uint32_t Opcode = Ex.second;
1286 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1289 .
addImm(
static_cast<uint32_t
>(Set))
1292 const unsigned NumOps =
I.getNumOperands();
1295 I.getOperand(Index).getType() ==
1296 MachineOperand::MachineOperandType::MO_IntrinsicID)
1299 MIB.
add(
I.getOperand(Index));
1305bool SPIRVInstructionSelector::selectExtInstForLRound(
1307 CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst)
const {
1308 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1309 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1310 return selectExtInstForLRound(ResVReg, ResType,
I, ExtInsts);
1313bool SPIRVInstructionSelector::selectExtInstForLRound(
1316 for (
const auto &Ex : Insts) {
1317 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1318 uint32_t Opcode = Ex.second;
1321 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1324 .
addImm(
static_cast<uint32_t
>(Set))
1326 const unsigned NumOps =
I.getNumOperands();
1329 I.getOperand(Index).getType() ==
1330 MachineOperand::MachineOperandType::MO_IntrinsicID)
1333 MIB.
add(
I.getOperand(Index));
1341bool SPIRVInstructionSelector::selectFrexp(
Register ResVReg,
1343 MachineInstr &
I)
const {
1344 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CL::frexp},
1345 {SPIRV::InstructionSet::GLSL_std_450, GL::Frexp}};
1346 for (
const auto &Ex : ExtInsts) {
1347 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1348 uint32_t Opcode = Ex.second;
1352 MachineIRBuilder MIRBuilder(
I);
1355 PointeeTy, MIRBuilder, SPIRV::StorageClass::Function);
1360 auto MIB =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
1361 TII.get(SPIRV::OpVariable))
1364 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
1368 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1371 .
addImm(
static_cast<uint32_t
>(Ex.first))
1373 .
add(
I.getOperand(2))
1378 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1379 .
addDef(
I.getOperand(1).getReg())
1388bool SPIRVInstructionSelector::selectOpWithSrcs(
Register ResVReg,
1391 std::vector<Register> Srcs,
1392 unsigned Opcode)
const {
1393 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1402bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
1405 unsigned Opcode)
const {
1407 Register SrcReg =
I.getOperand(1).getReg();
1410 MRI->def_instr_begin(SrcReg);
1411 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
1412 unsigned DefOpCode = DefIt->getOpcode();
1413 if (DefOpCode == SPIRV::ASSIGN_TYPE || DefOpCode == TargetOpcode::COPY) {
1416 if (
auto *VRD =
getVRegDef(*
MRI, DefIt->getOperand(1).getReg()))
1417 DefOpCode = VRD->getOpcode();
1419 if (DefOpCode == TargetOpcode::G_GLOBAL_VALUE ||
1420 DefOpCode == TargetOpcode::G_CONSTANT ||
1421 DefOpCode == SPIRV::OpVariable || DefOpCode == SPIRV::OpConstantI) {
1427 uint32_t SpecOpcode = 0;
1429 case SPIRV::OpConvertPtrToU:
1430 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertPtrToU);
1432 case SPIRV::OpConvertUToPtr:
1433 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertUToPtr);
1437 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1438 TII.get(SPIRV::OpSpecConstantOp))
1446 return selectOpWithSrcs(ResVReg, ResType,
I, {
I.getOperand(1).getReg()},
1450bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
1452 MachineInstr &
I)
const {
1453 Register OpReg =
I.getOperand(1).getReg();
1457 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
1465 if (
MemOp->isVolatile())
1466 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1467 if (
MemOp->isNonTemporal())
1468 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1469 if (
MemOp->getAlign().value())
1470 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
1476 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
1477 if (
auto *MD =
MemOp->getAAInfo().Scope) {
1481 static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
1483 if (
auto *MD =
MemOp->getAAInfo().NoAlias) {
1487 static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
1491 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
1493 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
1505 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1507 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1509 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
1513bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
1515 MachineInstr &
I)
const {
1517 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1522 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1523 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1525 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1527 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1529 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1533 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1534 return generateImageReadOrFetch(ResVReg, ResType, NewHandleReg, IdxReg,
1535 I.getDebugLoc(),
I);
1539 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1543 if (!
I.getNumMemOperands()) {
1544 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1546 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1549 MachineIRBuilder MIRBuilder(
I);
1555bool SPIRVInstructionSelector::selectStore(MachineInstr &
I)
const {
1557 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
1558 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1563 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1564 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1566 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1569 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1573 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1574 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1575 auto BMI =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1576 TII.get(SPIRV::OpImageWrite))
1582 if (sampledTypeIsSignedInteger(LLVMHandleType))
1585 return BMI.constrainAllUses(
TII,
TRI, RBI);
1590 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
1593 if (!
I.getNumMemOperands()) {
1594 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1596 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1599 MachineIRBuilder MIRBuilder(
I);
1605bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
1607 MachineInstr &
I)
const {
1608 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1610 "llvm.stacksave intrinsic: this instruction requires the following "
1611 "SPIR-V extension: SPV_INTEL_variable_length_array",
1614 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
1620bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &
I)
const {
1621 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1623 "llvm.stackrestore intrinsic: this instruction requires the following "
1624 "SPIR-V extension: SPV_INTEL_variable_length_array",
1626 if (!
I.getOperand(0).isReg())
1629 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
1630 .
addUse(
I.getOperand(0).getReg())
1635SPIRVInstructionSelector::getOrCreateMemSetGlobal(MachineInstr &
I)
const {
1636 MachineIRBuilder MIRBuilder(
I);
1637 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1644 GlobalVariable *GV =
new GlobalVariable(*CurFunction.
getParent(), LLVMArrTy,
1648 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1649 Type *ArrTy = ArrayType::get(ValTy, Num);
1651 ArrTy, MIRBuilder, SPIRV::StorageClass::UniformConstant);
1654 ArrTy, MIRBuilder, SPIRV::AccessQualifier::None,
false);
1661 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
1664 .
addImm(SPIRV::StorageClass::UniformConstant)
1666 if (!MIBVar.constrainAllUses(
TII,
TRI, RBI))
1676bool SPIRVInstructionSelector::selectCopyMemory(MachineInstr &
I,
1679 Register DstReg =
I.getOperand(0).getReg();
1689 "Unable to determine pointee type size for OpCopyMemory");
1690 const DataLayout &
DL =
I.getMF()->getFunction().getDataLayout();
1691 if (CopySize !=
DL.getTypeStoreSize(
const_cast<Type *
>(LLVMPointeeTy)))
1693 "OpCopyMemory requires the size to match the pointee type size");
1694 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemory))
1697 if (
I.getNumMemOperands()) {
1698 MachineIRBuilder MIRBuilder(
I);
1704bool SPIRVInstructionSelector::selectCopyMemorySized(MachineInstr &
I,
1707 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
1708 .
addUse(
I.getOperand(0).getReg())
1710 .
addUse(
I.getOperand(2).getReg());
1711 if (
I.getNumMemOperands()) {
1712 MachineIRBuilder MIRBuilder(
I);
1718bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
1719 MachineInstr &
I)
const {
1720 Register SrcReg =
I.getOperand(1).getReg();
1722 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
1723 Register VarReg = getOrCreateMemSetGlobal(
I);
1726 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1728 ValTy,
I, SPIRV::StorageClass::UniformConstant);
1730 Result &= selectOpWithSrcs(SrcReg, SourceTy,
I, {VarReg}, SPIRV::OpBitcast);
1733 Result &= selectCopyMemory(
I, SrcReg);
1735 Result &= selectCopyMemorySized(
I, SrcReg);
1737 if (ResVReg.
isValid() && ResVReg !=
I.getOperand(0).getReg())
1738 Result &= BuildCOPY(ResVReg,
I.getOperand(0).getReg(),
I);
1742bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
1746 unsigned NegateOpcode)
const {
1749 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1752 auto ScopeConstant = buildI32Constant(Scope,
I);
1753 Register ScopeReg = ScopeConstant.first;
1754 Result &= ScopeConstant.second;
1756 Register Ptr =
I.getOperand(1).getReg();
1762 auto MemSemConstant = buildI32Constant(MemSem ,
I);
1763 Register MemSemReg = MemSemConstant.first;
1764 Result &= MemSemConstant.second;
1766 Register ValueReg =
I.getOperand(2).getReg();
1767 if (NegateOpcode != 0) {
1770 Result &= selectOpWithSrcs(TmpReg, ResType,
I, {ValueReg}, NegateOpcode);
1775 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(NewOpcode))
1785bool SPIRVInstructionSelector::selectUnmergeValues(MachineInstr &
I)
const {
1786 unsigned ArgI =
I.getNumOperands() - 1;
1788 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
1791 if (!SrcType || SrcType->
getOpcode() != SPIRV::OpTypeVector)
1793 "cannot select G_UNMERGE_VALUES with a non-vector argument");
1799 unsigned CurrentIndex = 0;
1800 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1801 Register ResVReg =
I.getOperand(i).getReg();
1804 LLT ResLLT =
MRI->getType(ResVReg);
1810 ResType = ScalarType;
1816 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1819 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
1825 for (
unsigned j = 0;
j < NumElements; ++
j) {
1826 MIB.
addImm(CurrentIndex + j);
1828 CurrentIndex += NumElements;
1832 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1844bool SPIRVInstructionSelector::selectFence(MachineInstr &
I)
const {
1847 auto MemSemConstant = buildI32Constant(MemSem,
I);
1848 Register MemSemReg = MemSemConstant.first;
1849 bool Result = MemSemConstant.second;
1851 uint32_t
Scope =
static_cast<uint32_t
>(
1853 auto ScopeConstant = buildI32Constant(Scope,
I);
1854 Register ScopeReg = ScopeConstant.first;
1855 Result &= ScopeConstant.second;
1858 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
1864bool SPIRVInstructionSelector::selectOverflowArith(
Register ResVReg,
1867 unsigned Opcode)
const {
1868 Type *ResTy =
nullptr;
1872 "Not enough info to select the arithmetic with overflow instruction");
1875 "with overflow instruction");
1881 MachineIRBuilder MIRBuilder(
I);
1883 ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
1884 assert(
I.getNumDefs() > 1 &&
"Not enought operands");
1890 Register ZeroReg = buildZerosVal(ResType,
I);
1893 MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
1895 if (ResName.
size() > 0)
1900 BuildMI(BB, MIRBuilder.getInsertPt(),
I.getDebugLoc(),
TII.get(Opcode))
1903 for (
unsigned i =
I.getNumDefs(); i <
I.getNumOperands(); ++i)
1904 MIB.
addUse(
I.getOperand(i).getReg());
1909 MRI->setRegClass(HigherVReg, &SPIRV::iIDRegClass);
1910 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1912 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1913 .
addDef(i == 1 ? HigherVReg :
I.getOperand(i).getReg())
1921 .
addDef(
I.getOperand(1).getReg())
1928bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
1930 MachineInstr &
I)
const {
1935 Register Ptr =
I.getOperand(2).getReg();
1938 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1941 auto ScopeConstant = buildI32Constant(Scope,
I);
1942 ScopeReg = ScopeConstant.first;
1943 Result &= ScopeConstant.second;
1945 unsigned ScSem =
static_cast<uint32_t
>(
1948 unsigned MemSemEq =
static_cast<uint32_t
>(
getMemSemantics(AO)) | ScSem;
1949 auto MemSemEqConstant = buildI32Constant(MemSemEq,
I);
1950 MemSemEqReg = MemSemEqConstant.first;
1951 Result &= MemSemEqConstant.second;
1953 unsigned MemSemNeq =
static_cast<uint32_t
>(
getMemSemantics(FO)) | ScSem;
1954 if (MemSemEq == MemSemNeq)
1955 MemSemNeqReg = MemSemEqReg;
1957 auto MemSemNeqConstant = buildI32Constant(MemSemEq,
I);
1958 MemSemNeqReg = MemSemNeqConstant.first;
1959 Result &= MemSemNeqConstant.second;
1962 ScopeReg =
I.getOperand(5).getReg();
1963 MemSemEqReg =
I.getOperand(6).getReg();
1964 MemSemNeqReg =
I.getOperand(7).getReg();
1968 Register Val =
I.getOperand(4).getReg();
1973 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
2000 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpCompositeInsert))
2011 case SPIRV::StorageClass::DeviceOnlyINTEL:
2012 case SPIRV::StorageClass::HostOnlyINTEL:
2021 bool IsGRef =
false;
2022 bool IsAllowedRefs =
2023 llvm::all_of(
MRI->use_instructions(ResVReg), [&IsGRef](
auto const &It) {
2024 unsigned Opcode = It.getOpcode();
2025 if (Opcode == SPIRV::OpConstantComposite ||
2026 Opcode == SPIRV::OpVariable ||
2027 isSpvIntrinsic(It, Intrinsic::spv_init_global))
2028 return IsGRef = true;
2029 return Opcode == SPIRV::OpName;
2031 return IsAllowedRefs && IsGRef;
2034Register SPIRVInstructionSelector::getUcharPtrTypeReg(
2035 MachineInstr &
I, SPIRV::StorageClass::StorageClass SC)
const {
2037 Type::getInt8Ty(
I.getMF()->getFunction().getContext()),
I, SC));
2041SPIRVInstructionSelector::buildSpecConstantOp(MachineInstr &
I,
Register Dest,
2043 uint32_t Opcode)
const {
2044 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2045 TII.get(SPIRV::OpSpecConstantOp))
2053SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &
I,
Register SrcPtr,
2057 Register Tmp =
MRI->createVirtualRegister(&SPIRV::pIDRegClass);
2059 SPIRV::StorageClass::Generic),
2061 MachineFunction *MF =
I.getParent()->getParent();
2063 MachineInstrBuilder MIB = buildSpecConstantOp(
2065 static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric));
2075bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
2077 MachineInstr &
I)
const {
2081 Register SrcPtr =
I.getOperand(1).getReg();
2085 if (SrcPtrTy->
getOpcode() != SPIRV::OpTypePointer ||
2086 ResType->
getOpcode() != SPIRV::OpTypePointer)
2087 return BuildCOPY(ResVReg, SrcPtr,
I);
2097 unsigned SpecOpcode =
2099 ?
static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric)
2102 ? static_cast<uint32_t>(
SPIRV::Opcode::GenericCastToPtr)
2109 return buildSpecConstantOp(
I, ResVReg, SrcPtr,
2110 getUcharPtrTypeReg(
I, DstSC), SpecOpcode)
2111 .constrainAllUses(
TII,
TRI, RBI);
2113 MachineInstrBuilder MIB = buildConstGenericPtr(
I, SrcPtr, SrcPtrTy);
2115 buildSpecConstantOp(
2117 getUcharPtrTypeReg(
I, DstSC),
2118 static_cast<uint32_t
>(SPIRV::Opcode::GenericCastToPtr))
2119 .constrainAllUses(
TII,
TRI, RBI);
2125 return BuildCOPY(ResVReg, SrcPtr,
I);
2127 if ((SrcSC == SPIRV::StorageClass::Function &&
2128 DstSC == SPIRV::StorageClass::Private) ||
2129 (DstSC == SPIRV::StorageClass::Function &&
2130 SrcSC == SPIRV::StorageClass::Private))
2131 return BuildCOPY(ResVReg, SrcPtr,
I);
2135 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
2138 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
2159 return selectUnOp(ResVReg, ResType,
I,
2160 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
2162 return selectUnOp(ResVReg, ResType,
I,
2163 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
2165 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
2167 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
2177 return SPIRV::OpFOrdEqual;
2179 return SPIRV::OpFOrdGreaterThanEqual;
2181 return SPIRV::OpFOrdGreaterThan;
2183 return SPIRV::OpFOrdLessThanEqual;
2185 return SPIRV::OpFOrdLessThan;
2187 return SPIRV::OpFOrdNotEqual;
2189 return SPIRV::OpOrdered;
2191 return SPIRV::OpFUnordEqual;
2193 return SPIRV::OpFUnordGreaterThanEqual;
2195 return SPIRV::OpFUnordGreaterThan;
2197 return SPIRV::OpFUnordLessThanEqual;
2199 return SPIRV::OpFUnordLessThan;
2201 return SPIRV::OpFUnordNotEqual;
2203 return SPIRV::OpUnordered;
2213 return SPIRV::OpIEqual;
2215 return SPIRV::OpINotEqual;
2217 return SPIRV::OpSGreaterThanEqual;
2219 return SPIRV::OpSGreaterThan;
2221 return SPIRV::OpSLessThanEqual;
2223 return SPIRV::OpSLessThan;
2225 return SPIRV::OpUGreaterThanEqual;
2227 return SPIRV::OpUGreaterThan;
2229 return SPIRV::OpULessThanEqual;
2231 return SPIRV::OpULessThan;
2240 return SPIRV::OpPtrEqual;
2242 return SPIRV::OpPtrNotEqual;
2253 return SPIRV::OpLogicalEqual;
2255 return SPIRV::OpLogicalNotEqual;
2289bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
2292 unsigned OpAnyOrAll)
const {
2293 assert(
I.getNumOperands() == 3);
2294 assert(
I.getOperand(2).isReg());
2296 Register InputRegister =
I.getOperand(2).getReg();
2303 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
2304 if (IsBoolTy && !IsVectorTy) {
2305 assert(ResVReg ==
I.getOperand(0).getReg());
2306 return BuildCOPY(ResVReg, InputRegister,
I);
2310 unsigned SpirvNotEqualId =
2311 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
2318 IsBoolTy ? InputRegister
2327 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
2347bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
2349 MachineInstr &
I)
const {
2350 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
2353bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
2355 MachineInstr &
I)
const {
2356 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
2360bool SPIRVInstructionSelector::selectFloatDot(
Register ResVReg,
2362 MachineInstr &
I)
const {
2363 assert(
I.getNumOperands() == 4);
2364 assert(
I.getOperand(2).isReg());
2365 assert(
I.getOperand(3).isReg());
2372 "dot product requires a vector of at least 2 components");
2380 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpDot))
2383 .
addUse(
I.getOperand(2).getReg())
2384 .
addUse(
I.getOperand(3).getReg())
2388bool SPIRVInstructionSelector::selectIntegerDot(
Register ResVReg,
2392 assert(
I.getNumOperands() == 4);
2393 assert(
I.getOperand(2).isReg());
2394 assert(
I.getOperand(3).isReg());
2397 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2401 .
addUse(
I.getOperand(2).getReg())
2402 .
addUse(
I.getOperand(3).getReg())
2408bool SPIRVInstructionSelector::selectIntegerDotExpansion(
2410 assert(
I.getNumOperands() == 4);
2411 assert(
I.getOperand(2).isReg());
2412 assert(
I.getOperand(3).isReg());
2416 Register Vec0 =
I.getOperand(2).getReg();
2417 Register Vec1 =
I.getOperand(3).getReg();
2430 "dot product requires a vector of at least 2 components");
2444 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2467bool SPIRVInstructionSelector::selectOpIsInf(
Register ResVReg,
2469 MachineInstr &
I)
const {
2471 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsInf))
2474 .
addUse(
I.getOperand(2).getReg())
2478bool SPIRVInstructionSelector::selectOpIsNan(
Register ResVReg,
2480 MachineInstr &
I)
const {
2482 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsNan))
2485 .
addUse(
I.getOperand(2).getReg())
2489template <
bool Signed>
2490bool SPIRVInstructionSelector::selectDot4AddPacked(
Register ResVReg,
2492 MachineInstr &
I)
const {
2493 assert(
I.getNumOperands() == 5);
2494 assert(
I.getOperand(2).isReg());
2495 assert(
I.getOperand(3).isReg());
2496 assert(
I.getOperand(4).isReg());
2499 Register Acc =
I.getOperand(2).getReg();
2503 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2523template <
bool Signed>
2524bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
2526 assert(
I.getNumOperands() == 5);
2527 assert(
I.getOperand(2).isReg());
2528 assert(
I.getOperand(3).isReg());
2529 assert(
I.getOperand(4).isReg());
2534 Register Acc =
I.getOperand(2).getReg();
2540 Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
2544 for (
unsigned i = 0; i < 4; i++) {
2546 Register AElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2557 Register BElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2577 Register MaskMul =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2589 i < 3 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
2605bool SPIRVInstructionSelector::selectSaturate(
Register ResVReg,
2607 MachineInstr &
I)
const {
2608 assert(
I.getNumOperands() == 3);
2609 assert(
I.getOperand(2).isReg());
2611 Register VZero = buildZerosValF(ResType,
I);
2612 Register VOne = buildOnesValF(ResType,
I);
2614 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2617 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2619 .
addUse(
I.getOperand(2).getReg())
2625bool SPIRVInstructionSelector::selectSign(
Register ResVReg,
2627 MachineInstr &
I)
const {
2628 assert(
I.getNumOperands() == 3);
2629 assert(
I.getOperand(2).isReg());
2631 Register InputRegister =
I.getOperand(2).getReg();
2633 auto &
DL =
I.getDebugLoc();
2643 bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth;
2645 auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign;
2647 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass)
2654 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2659 if (NeedsConversion) {
2660 auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert;
2671bool SPIRVInstructionSelector::selectWaveOpInst(
Register ResVReg,
2674 unsigned Opcode)
const {
2678 auto BMI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2684 for (
unsigned J = 2; J <
I.getNumOperands(); J++) {
2685 BMI.addUse(
I.getOperand(J).getReg());
2691bool SPIRVInstructionSelector::selectWaveActiveCountBits(
2697 bool Result = selectWaveOpInst(BallotReg, BallotType,
I,
2698 SPIRV::OpGroupNonUniformBallot);
2702 TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
2707 .
addImm(SPIRV::GroupOperation::Reduce)
2714bool SPIRVInstructionSelector::selectWaveReduceMax(
Register ResVReg,
2717 bool IsUnsigned)
const {
2718 assert(
I.getNumOperands() == 3);
2719 assert(
I.getOperand(2).isReg());
2721 Register InputRegister =
I.getOperand(2).getReg();
2730 auto IntegerOpcodeType =
2731 IsUnsigned ? SPIRV::OpGroupNonUniformUMax : SPIRV::OpGroupNonUniformSMax;
2732 auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMax : IntegerOpcodeType;
2733 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2738 .
addImm(SPIRV::GroupOperation::Reduce)
2739 .
addUse(
I.getOperand(2).getReg())
2743bool SPIRVInstructionSelector::selectWaveReduceMin(
Register ResVReg,
2746 bool IsUnsigned)
const {
2747 assert(
I.getNumOperands() == 3);
2748 assert(
I.getOperand(2).isReg());
2750 Register InputRegister =
I.getOperand(2).getReg();
2759 auto IntegerOpcodeType =
2760 IsUnsigned ? SPIRV::OpGroupNonUniformUMin : SPIRV::OpGroupNonUniformSMin;
2761 auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMin : IntegerOpcodeType;
2762 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2767 .
addImm(SPIRV::GroupOperation::Reduce)
2768 .
addUse(
I.getOperand(2).getReg())
2772bool SPIRVInstructionSelector::selectWaveReduceSum(
Register ResVReg,
2774 MachineInstr &
I)
const {
2775 assert(
I.getNumOperands() == 3);
2776 assert(
I.getOperand(2).isReg());
2778 Register InputRegister =
I.getOperand(2).getReg();
2788 IsFloatTy ? SPIRV::OpGroupNonUniformFAdd : SPIRV::OpGroupNonUniformIAdd;
2789 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2794 .
addImm(SPIRV::GroupOperation::Reduce)
2795 .
addUse(
I.getOperand(2).getReg());
2798bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
2800 MachineInstr &
I)
const {
2802 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
2805 .
addUse(
I.getOperand(1).getReg())
2809bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
2811 MachineInstr &
I)
const {
2817 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
2819 Register OpReg =
I.getOperand(1).getReg();
2820 if (MachineInstr *Def =
MRI->getVRegDef(OpReg)) {
2821 if (
Def->getOpcode() == TargetOpcode::COPY)
2822 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
2824 switch (
Def->getOpcode()) {
2825 case SPIRV::ASSIGN_TYPE:
2826 if (MachineInstr *AssignToDef =
2827 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
2828 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2829 Reg =
Def->getOperand(2).getReg();
2832 case SPIRV::OpUndef:
2833 Reg =
Def->getOperand(1).getReg();
2836 unsigned DestOpCode;
2838 DestOpCode = SPIRV::OpConstantNull;
2840 DestOpCode = TargetOpcode::COPY;
2843 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
2844 .
addDef(
I.getOperand(0).getReg())
2851bool SPIRVInstructionSelector::selectBuildVector(
Register ResVReg,
2853 MachineInstr &
I)
const {
2855 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2857 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2861 if (
I.getNumExplicitOperands() -
I.getNumExplicitDefs() !=
N)
2866 for (
unsigned i =
I.getNumExplicitDefs();
2867 i <
I.getNumExplicitOperands() && IsConst; ++i)
2871 if (!IsConst &&
N < 2)
2873 "There must be at least two constituent operands in a vector");
2876 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2877 TII.get(IsConst ? SPIRV::OpConstantComposite
2878 : SPIRV::OpCompositeConstruct))
2881 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
2882 MIB.
addUse(
I.getOperand(i).getReg());
2886bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
2888 MachineInstr &
I)
const {
2890 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2892 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2898 if (!
I.getOperand(
OpIdx).isReg())
2905 if (!IsConst &&
N < 2)
2907 "There must be at least two constituent operands in a vector");
2910 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2911 TII.get(IsConst ? SPIRV::OpConstantComposite
2912 : SPIRV::OpCompositeConstruct))
2915 for (
unsigned i = 0; i <
N; ++i)
2920bool SPIRVInstructionSelector::selectDiscard(
Register ResVReg,
2922 MachineInstr &
I)
const {
2927 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
2929 Opcode = SPIRV::OpDemoteToHelperInvocation;
2931 Opcode = SPIRV::OpKill;
2933 if (MachineInstr *NextI =
I.getNextNode()) {
2935 NextI->removeFromParent();
2940 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2944bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
2947 MachineInstr &
I)
const {
2948 Register Cmp0 =
I.getOperand(2).getReg();
2949 Register Cmp1 =
I.getOperand(3).getReg();
2952 "CMP operands should have the same type");
2953 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
2962bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
2964 MachineInstr &
I)
const {
2965 auto Pred =
I.getOperand(1).getPredicate();
2968 Register CmpOperand =
I.getOperand(2).getReg();
2975 return selectCmp(ResVReg, ResType, CmpOpc,
I);
2978std::pair<Register, bool>
2979SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &
I,
2985 auto ConstInt = ConstantInt::get(LLVMTy, Val);
2993 ?
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2996 :
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
2999 .
addImm(APInt(32, Val).getZExtValue());
3001 GR.
add(ConstInt,
MI);
3006bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
3008 MachineInstr &
I)
const {
3010 return selectCmp(ResVReg, ResType, CmpOp,
I);
3014 MachineInstr &
I)
const {
3017 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3023 MachineInstr &
I)
const {
3027 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3033 MachineInstr &
I)
const {
3037 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3044 MachineInstr &
I)
const {
3048 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3053bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
3055 MachineInstr &
I)
const {
3056 Register SelectFirstArg =
I.getOperand(2).getReg();
3057 Register SelectSecondArg =
I.getOperand(3).getReg();
3066 SPIRV::OpTypeVector;
3073 Opcode = IsScalarBool ? SPIRV::OpSelectVFSCond : SPIRV::OpSelectVFVCond;
3074 }
else if (IsPtrTy) {
3075 Opcode = IsScalarBool ? SPIRV::OpSelectVPSCond : SPIRV::OpSelectVPVCond;
3077 Opcode = IsScalarBool ? SPIRV::OpSelectVISCond : SPIRV::OpSelectVIVCond;
3081 Opcode = IsScalarBool ? SPIRV::OpSelectSFSCond : SPIRV::OpSelectVFVCond;
3082 }
else if (IsPtrTy) {
3083 Opcode = IsScalarBool ? SPIRV::OpSelectSPSCond : SPIRV::OpSelectVPVCond;
3085 Opcode = IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
3088 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3091 .
addUse(
I.getOperand(1).getReg())
3097bool SPIRVInstructionSelector::selectSelectDefaultArgs(
Register ResVReg,
3100 bool IsSigned)
const {
3102 Register ZeroReg = buildZerosVal(ResType,
I);
3103 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
3107 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
3108 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3111 .
addUse(
I.getOperand(1).getReg())
3117bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
3119 MachineInstr &
I,
bool IsSigned,
3120 unsigned Opcode)
const {
3121 Register SrcReg =
I.getOperand(1).getReg();
3127 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
3132 selectSelectDefaultArgs(SrcReg, TmpType,
I,
false);
3134 return selectOpWithSrcs(ResVReg, ResType,
I, {SrcReg}, Opcode);
3137bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
3139 MachineInstr &
I,
bool IsSigned)
const {
3140 Register SrcReg =
I.getOperand(1).getReg();
3142 return selectSelectDefaultArgs(ResVReg, ResType,
I, IsSigned);
3145 if (SrcType == ResType)
3146 return BuildCOPY(ResVReg, SrcReg,
I);
3148 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3149 return selectUnOp(ResVReg, ResType,
I, Opcode);
3152bool SPIRVInstructionSelector::selectSUCmp(
Register ResVReg,
3155 bool IsSigned)
const {
3156 MachineIRBuilder MIRBuilder(
I);
3157 MachineRegisterInfo *
MRI = MIRBuilder.getMRI();
3172 TII.get(IsSigned ? SPIRV::OpSLessThanEqual
3173 : SPIRV::OpULessThanEqual))
3176 .
addUse(
I.getOperand(1).getReg())
3177 .
addUse(
I.getOperand(2).getReg())
3183 TII.get(IsSigned ? SPIRV::OpSLessThan : SPIRV::OpULessThan))
3186 .
addUse(
I.getOperand(1).getReg())
3187 .
addUse(
I.getOperand(2).getReg())
3195 unsigned SelectOpcode =
3196 N > 1 ? SPIRV::OpSelectVIVCond : SPIRV::OpSelectSISCond;
3201 .
addUse(buildOnesVal(
true, ResType,
I))
3202 .
addUse(buildZerosVal(ResType,
I))
3209 .
addUse(buildOnesVal(
false, ResType,
I))
3213bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
3220 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
3221 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
3223 Register One = buildOnesVal(
false, IntTy,
I);
3239bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
3241 MachineInstr &
I)
const {
3242 Register IntReg =
I.getOperand(1).getReg();
3245 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
3246 if (ArgType == ResType)
3247 return BuildCOPY(ResVReg, IntReg,
I);
3249 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3250 return selectUnOp(ResVReg, ResType,
I, Opcode);
3253bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
3255 MachineInstr &
I)
const {
3256 unsigned Opcode =
I.getOpcode();
3257 unsigned TpOpcode = ResType->
getOpcode();
3259 if (TpOpcode == SPIRV::OpTypePointer || TpOpcode == SPIRV::OpTypeEvent) {
3260 assert(Opcode == TargetOpcode::G_CONSTANT &&
3261 I.getOperand(1).getCImm()->isZero());
3262 MachineBasicBlock &DepMBB =
I.getMF()->front();
3265 }
else if (Opcode == TargetOpcode::G_FCONSTANT) {
3272 return Reg == ResVReg ?
true : BuildCOPY(ResVReg,
Reg,
I);
3275bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
3277 MachineInstr &
I)
const {
3278 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3284bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
3286 MachineInstr &
I)
const {
3288 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
3292 .
addUse(
I.getOperand(3).getReg())
3294 .
addUse(
I.getOperand(2).getReg());
3295 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
3300bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
3302 MachineInstr &
I)
const {
3303 Type *MaybeResTy =
nullptr;
3309 "Expected aggregate type for extractv instruction");
3311 SPIRV::AccessQualifier::ReadWrite,
false);
3315 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
3318 .
addUse(
I.getOperand(2).getReg());
3319 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
3324bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
3326 MachineInstr &
I)
const {
3328 return selectInsertVal(ResVReg, ResType,
I);
3330 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
3333 .
addUse(
I.getOperand(2).getReg())
3334 .
addUse(
I.getOperand(3).getReg())
3335 .
addUse(
I.getOperand(4).getReg())
3339bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
3341 MachineInstr &
I)
const {
3343 return selectExtractVal(ResVReg, ResType,
I);
3345 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
3348 .
addUse(
I.getOperand(2).getReg())
3349 .
addUse(
I.getOperand(3).getReg())
3353bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
3355 MachineInstr &
I)
const {
3356 const bool IsGEPInBounds =
I.getOperand(2).getImm();
3362 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
3363 : SPIRV::OpAccessChain)
3364 : (IsGEPInBounds ?
SPIRV::OpInBoundsPtrAccessChain
3365 :
SPIRV::OpPtrAccessChain);
3367 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3371 .
addUse(
I.getOperand(3).getReg());
3373 (Opcode == SPIRV::OpPtrAccessChain ||
3374 Opcode == SPIRV::OpInBoundsPtrAccessChain ||
3376 "Cannot translate GEP to OpAccessChain. First index must be 0.");
3379 const unsigned StartingIndex =
3380 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
3383 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
3384 Res.addUse(
I.getOperand(i).getReg());
3385 return Res.constrainAllUses(
TII,
TRI, RBI);
3389bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
3392 unsigned Lim =
I.getNumExplicitOperands();
3393 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
3394 Register OpReg =
I.getOperand(i).getReg();
3395 MachineInstr *OpDefine =
MRI->getVRegDef(OpReg);
3397 SmallPtrSet<SPIRVType *, 4> Visited;
3398 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
3399 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
3400 OpDefine->
getOpcode() == TargetOpcode::G_INTTOPTR ||
3407 MachineFunction *MF =
I.getMF();
3419 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3420 TII.get(SPIRV::OpSpecConstantOp))
3423 .
addImm(
static_cast<uint32_t
>(SPIRV::Opcode::Bitcast))
3425 GR.
add(OpDefine, MIB);
3433bool SPIRVInstructionSelector::selectDerivativeInst(
3435 const unsigned DPdOpCode)
const {
3438 errorIfInstrOutsideShader(
I);
3443 Register SrcReg =
I.getOperand(2).getReg();
3448 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DPdOpCode))
3451 .
addUse(
I.getOperand(2).getReg());
3453 MachineIRBuilder MIRBuilder(
I);
3456 if (componentCount != 1)
3460 const TargetRegisterClass *RegClass = GR.
getRegClass(SrcType);
3461 Register ConvertToVReg =
MRI->createVirtualRegister(RegClass);
3462 Register DpdOpVReg =
MRI->createVirtualRegister(RegClass);
3465 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3476 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3484bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
3486 MachineInstr &
I)
const {
3490 case Intrinsic::spv_load:
3491 return selectLoad(ResVReg, ResType,
I);
3492 case Intrinsic::spv_store:
3493 return selectStore(
I);
3494 case Intrinsic::spv_extractv:
3495 return selectExtractVal(ResVReg, ResType,
I);
3496 case Intrinsic::spv_insertv:
3497 return selectInsertVal(ResVReg, ResType,
I);
3498 case Intrinsic::spv_extractelt:
3499 return selectExtractElt(ResVReg, ResType,
I);
3500 case Intrinsic::spv_insertelt:
3501 return selectInsertElt(ResVReg, ResType,
I);
3502 case Intrinsic::spv_gep:
3503 return selectGEP(ResVReg, ResType,
I);
3504 case Intrinsic::spv_bitcast: {
3505 Register OpReg =
I.getOperand(2).getReg();
3510 return selectOpWithSrcs(ResVReg, ResType,
I, {OpReg}, SPIRV::OpBitcast);
3512 case Intrinsic::spv_unref_global:
3513 case Intrinsic::spv_init_global: {
3514 MachineInstr *
MI =
MRI->getVRegDef(
I.getOperand(1).getReg());
3515 MachineInstr *Init =
I.getNumExplicitOperands() > 2
3516 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
3519 Register GVarVReg =
MI->getOperand(0).getReg();
3520 bool Res = selectGlobalValue(GVarVReg, *
MI, Init);
3524 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
3526 MI->removeFromParent();
3530 case Intrinsic::spv_undef: {
3531 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3536 case Intrinsic::spv_const_composite: {
3538 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
3544 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
3546 MachineIRBuilder MIR(
I);
3548 MIR, SPIRV::OpConstantComposite, 3,
3549 SPIRV::OpConstantCompositeContinuedINTEL, CompositeArgs, ResVReg,
3551 for (
auto *Instr : Instructions) {
3552 Instr->setDebugLoc(
I.getDebugLoc());
3558 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
3564 case Intrinsic::spv_assign_name: {
3565 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
3566 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
3567 for (
unsigned i =
I.getNumExplicitDefs() + 2;
3568 i <
I.getNumExplicitOperands(); ++i) {
3569 MIB.
addImm(
I.getOperand(i).getImm());
3573 case Intrinsic::spv_switch: {
3574 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
3575 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3576 if (
I.getOperand(i).isReg())
3577 MIB.
addReg(
I.getOperand(i).getReg());
3578 else if (
I.getOperand(i).isCImm())
3579 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
3580 else if (
I.getOperand(i).isMBB())
3581 MIB.
addMBB(
I.getOperand(i).getMBB());
3587 case Intrinsic::spv_loop_merge: {
3588 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoopMerge));
3589 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3590 if (
I.getOperand(i).isMBB())
3591 MIB.
addMBB(
I.getOperand(i).getMBB());
3597 case Intrinsic::spv_selection_merge: {
3599 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSelectionMerge));
3600 assert(
I.getOperand(1).isMBB() &&
3601 "operand 1 to spv_selection_merge must be a basic block");
3602 MIB.
addMBB(
I.getOperand(1).getMBB());
3603 MIB.
addImm(getSelectionOperandForImm(
I.getOperand(2).getImm()));
3606 case Intrinsic::spv_cmpxchg:
3607 return selectAtomicCmpXchg(ResVReg, ResType,
I);
3608 case Intrinsic::spv_unreachable:
3609 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable))
3611 case Intrinsic::spv_alloca:
3612 return selectFrameIndex(ResVReg, ResType,
I);
3613 case Intrinsic::spv_alloca_array:
3614 return selectAllocaArray(ResVReg, ResType,
I);
3615 case Intrinsic::spv_assume:
3617 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
3618 .
addUse(
I.getOperand(1).getReg())
3621 case Intrinsic::spv_expect:
3623 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
3626 .
addUse(
I.getOperand(2).getReg())
3627 .
addUse(
I.getOperand(3).getReg())
3630 case Intrinsic::arithmetic_fence:
3633 TII.get(SPIRV::OpArithmeticFenceEXT))
3636 .
addUse(
I.getOperand(2).getReg())
3639 return BuildCOPY(ResVReg,
I.getOperand(2).getReg(),
I);
3641 case Intrinsic::spv_thread_id:
3647 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalInvocationId, ResVReg,
3649 case Intrinsic::spv_thread_id_in_group:
3655 return loadVec3BuiltinInputID(SPIRV::BuiltIn::LocalInvocationId, ResVReg,
3657 case Intrinsic::spv_group_id:
3663 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
3665 case Intrinsic::spv_flattened_thread_id_in_group:
3672 return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
3674 case Intrinsic::spv_workgroup_size:
3675 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupSize, ResVReg,
3677 case Intrinsic::spv_global_size:
3678 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalSize, ResVReg, ResType,
3680 case Intrinsic::spv_global_offset:
3681 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalOffset, ResVReg,
3683 case Intrinsic::spv_num_workgroups:
3684 return loadVec3BuiltinInputID(SPIRV::BuiltIn::NumWorkgroups, ResVReg,
3686 case Intrinsic::spv_subgroup_size:
3687 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupSize, ResVReg, ResType,
3689 case Intrinsic::spv_num_subgroups:
3690 return loadBuiltinInputID(SPIRV::BuiltIn::NumSubgroups, ResVReg, ResType,
3692 case Intrinsic::spv_subgroup_id:
3693 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupId, ResVReg, ResType,
I);
3694 case Intrinsic::spv_subgroup_local_invocation_id:
3695 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupLocalInvocationId,
3696 ResVReg, ResType,
I);
3697 case Intrinsic::spv_subgroup_max_size:
3698 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupMaxSize, ResVReg, ResType,
3700 case Intrinsic::spv_fdot:
3701 return selectFloatDot(ResVReg, ResType,
I);
3702 case Intrinsic::spv_udot:
3703 case Intrinsic::spv_sdot:
3704 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3706 return selectIntegerDot(ResVReg, ResType,
I,
3707 IID == Intrinsic::spv_sdot);
3708 return selectIntegerDotExpansion(ResVReg, ResType,
I);
3709 case Intrinsic::spv_dot4add_i8packed:
3710 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3712 return selectDot4AddPacked<true>(ResVReg, ResType,
I);
3713 return selectDot4AddPackedExpansion<true>(ResVReg, ResType,
I);
3714 case Intrinsic::spv_dot4add_u8packed:
3715 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3717 return selectDot4AddPacked<false>(ResVReg, ResType,
I);
3718 return selectDot4AddPackedExpansion<false>(ResVReg, ResType,
I);
3719 case Intrinsic::spv_all:
3720 return selectAll(ResVReg, ResType,
I);
3721 case Intrinsic::spv_any:
3722 return selectAny(ResVReg, ResType,
I);
3723 case Intrinsic::spv_cross:
3724 return selectExtInst(ResVReg, ResType,
I, CL::cross, GL::Cross);
3725 case Intrinsic::spv_distance:
3726 return selectExtInst(ResVReg, ResType,
I, CL::distance, GL::Distance);
3727 case Intrinsic::spv_lerp:
3728 return selectExtInst(ResVReg, ResType,
I, CL::mix, GL::FMix);
3729 case Intrinsic::spv_length:
3730 return selectExtInst(ResVReg, ResType,
I, CL::length, GL::Length);
3731 case Intrinsic::spv_degrees:
3732 return selectExtInst(ResVReg, ResType,
I, CL::degrees, GL::Degrees);
3733 case Intrinsic::spv_faceforward:
3734 return selectExtInst(ResVReg, ResType,
I, GL::FaceForward);
3735 case Intrinsic::spv_frac:
3736 return selectExtInst(ResVReg, ResType,
I, CL::fract, GL::Fract);
3737 case Intrinsic::spv_isinf:
3738 return selectOpIsInf(ResVReg, ResType,
I);
3739 case Intrinsic::spv_isnan:
3740 return selectOpIsNan(ResVReg, ResType,
I);
3741 case Intrinsic::spv_normalize:
3742 return selectExtInst(ResVReg, ResType,
I, CL::normalize, GL::Normalize);
3743 case Intrinsic::spv_refract:
3744 return selectExtInst(ResVReg, ResType,
I, GL::Refract);
3745 case Intrinsic::spv_reflect:
3746 return selectExtInst(ResVReg, ResType,
I, GL::Reflect);
3747 case Intrinsic::spv_rsqrt:
3748 return selectExtInst(ResVReg, ResType,
I, CL::rsqrt, GL::InverseSqrt);
3749 case Intrinsic::spv_sign:
3750 return selectSign(ResVReg, ResType,
I);
3751 case Intrinsic::spv_smoothstep:
3752 return selectExtInst(ResVReg, ResType,
I, CL::smoothstep, GL::SmoothStep);
3753 case Intrinsic::spv_firstbituhigh:
3754 return selectFirstBitHigh(ResVReg, ResType,
I,
false);
3755 case Intrinsic::spv_firstbitshigh:
3756 return selectFirstBitHigh(ResVReg, ResType,
I,
true);
3757 case Intrinsic::spv_firstbitlow:
3758 return selectFirstBitLow(ResVReg, ResType,
I);
3759 case Intrinsic::spv_group_memory_barrier_with_group_sync: {
3761 auto MemSemConstant =
3762 buildI32Constant(SPIRV::MemorySemantics::SequentiallyConsistent,
I);
3763 Register MemSemReg = MemSemConstant.first;
3764 Result &= MemSemConstant.second;
3765 auto ScopeConstant = buildI32Constant(SPIRV::Scope::Workgroup,
I);
3766 Register ScopeReg = ScopeConstant.first;
3767 Result &= ScopeConstant.second;
3770 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpControlBarrier))
3776 case Intrinsic::spv_generic_cast_to_ptr_explicit: {
3777 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 1).getReg();
3778 SPIRV::StorageClass::StorageClass ResSC =
3782 "Generic storage class");
3784 TII.get(SPIRV::OpGenericCastToPtrExplicit))
3791 case Intrinsic::spv_lifetime_start:
3792 case Intrinsic::spv_lifetime_end: {
3793 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
3794 : SPIRV::OpLifetimeStop;
3795 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
3796 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
3804 case Intrinsic::spv_saturate:
3805 return selectSaturate(ResVReg, ResType,
I);
3806 case Intrinsic::spv_nclamp:
3807 return selectExtInst(ResVReg, ResType,
I, CL::fclamp, GL::NClamp);
3808 case Intrinsic::spv_uclamp:
3809 return selectExtInst(ResVReg, ResType,
I, CL::u_clamp, GL::UClamp);
3810 case Intrinsic::spv_sclamp:
3811 return selectExtInst(ResVReg, ResType,
I, CL::s_clamp, GL::SClamp);
3812 case Intrinsic::spv_wave_active_countbits:
3813 return selectWaveActiveCountBits(ResVReg, ResType,
I);
3814 case Intrinsic::spv_wave_all:
3815 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAll);
3816 case Intrinsic::spv_wave_any:
3817 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAny);
3818 case Intrinsic::spv_wave_ballot:
3819 return selectWaveOpInst(ResVReg, ResType,
I,
3820 SPIRV::OpGroupNonUniformBallot);
3821 case Intrinsic::spv_wave_is_first_lane:
3822 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformElect);
3823 case Intrinsic::spv_wave_reduce_umax:
3824 return selectWaveReduceMax(ResVReg, ResType,
I,
true);
3825 case Intrinsic::spv_wave_reduce_max:
3826 return selectWaveReduceMax(ResVReg, ResType,
I,
false);
3827 case Intrinsic::spv_wave_reduce_umin:
3828 return selectWaveReduceMin(ResVReg, ResType,
I,
true);
3829 case Intrinsic::spv_wave_reduce_min:
3830 return selectWaveReduceMin(ResVReg, ResType,
I,
false);
3831 case Intrinsic::spv_wave_reduce_sum:
3832 return selectWaveReduceSum(ResVReg, ResType,
I);
3833 case Intrinsic::spv_wave_readlane:
3834 return selectWaveOpInst(ResVReg, ResType,
I,
3835 SPIRV::OpGroupNonUniformShuffle);
3836 case Intrinsic::spv_step:
3837 return selectExtInst(ResVReg, ResType,
I, CL::step, GL::Step);
3838 case Intrinsic::spv_radians:
3839 return selectExtInst(ResVReg, ResType,
I, CL::radians, GL::Radians);
3843 case Intrinsic::instrprof_increment:
3844 case Intrinsic::instrprof_increment_step:
3845 case Intrinsic::instrprof_value_profile:
3848 case Intrinsic::spv_value_md:
3850 case Intrinsic::spv_resource_handlefrombinding: {
3851 return selectHandleFromBinding(ResVReg, ResType,
I);
3853 case Intrinsic::spv_resource_counterhandlefrombinding:
3854 return selectCounterHandleFromBinding(ResVReg, ResType,
I);
3855 case Intrinsic::spv_resource_updatecounter:
3856 return selectUpdateCounter(ResVReg, ResType,
I);
3857 case Intrinsic::spv_resource_store_typedbuffer: {
3858 return selectImageWriteIntrinsic(
I);
3860 case Intrinsic::spv_resource_load_typedbuffer: {
3861 return selectReadImageIntrinsic(ResVReg, ResType,
I);
3863 case Intrinsic::spv_resource_getpointer: {
3864 return selectResourceGetPointer(ResVReg, ResType,
I);
3866 case Intrinsic::spv_pushconstant_getpointer: {
3867 return selectPushConstantGetPointer(ResVReg, ResType,
I);
3869 case Intrinsic::spv_discard: {
3870 return selectDiscard(ResVReg, ResType,
I);
3872 case Intrinsic::spv_resource_nonuniformindex: {
3873 return selectResourceNonUniformIndex(ResVReg, ResType,
I);
3875 case Intrinsic::spv_unpackhalf2x16: {
3876 return selectExtInst(ResVReg, ResType,
I, GL::UnpackHalf2x16);
3878 case Intrinsic::spv_ddx:
3879 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdx);
3880 case Intrinsic::spv_ddy:
3881 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdy);
3882 case Intrinsic::spv_ddx_coarse:
3883 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdxCoarse);
3884 case Intrinsic::spv_ddy_coarse:
3885 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdyCoarse);
3886 case Intrinsic::spv_ddx_fine:
3887 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdxFine);
3888 case Intrinsic::spv_ddy_fine:
3889 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdyFine);
3890 case Intrinsic::spv_fwidth:
3891 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpFwidth);
3893 std::string DiagMsg;
3894 raw_string_ostream OS(DiagMsg);
3896 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
3903bool SPIRVInstructionSelector::selectHandleFromBinding(
Register &ResVReg,
3905 MachineInstr &
I)
const {
3908 if (ResType->
getOpcode() == SPIRV::OpTypeImage)
3915bool SPIRVInstructionSelector::selectCounterHandleFromBinding(
3918 assert(Intr.getIntrinsicID() ==
3919 Intrinsic::spv_resource_counterhandlefrombinding);
3922 Register MainHandleReg = Intr.getOperand(2).getReg();
3924 assert(MainHandleDef->getIntrinsicID() ==
3925 Intrinsic::spv_resource_handlefrombinding);
3929 uint32_t ArraySize =
getIConstVal(MainHandleDef->getOperand(4).getReg(),
MRI);
3930 Register IndexReg = MainHandleDef->getOperand(5).getReg();
3931 std::string CounterName =
3936 MachineIRBuilder MIRBuilder(
I);
3937 Register CounterVarReg = buildPointerToResource(
3939 Binding, ArraySize, IndexReg, CounterName, MIRBuilder);
3941 return BuildCOPY(ResVReg, CounterVarReg,
I);
3944bool SPIRVInstructionSelector::selectUpdateCounter(
Register &ResVReg,
3946 MachineInstr &
I)
const {
3948 assert(Intr.getIntrinsicID() == Intrinsic::spv_resource_updatecounter);
3950 Register CounterHandleReg = Intr.getOperand(2).getReg();
3951 Register IncrReg = Intr.getOperand(3).getReg();
3959 assert(CounterVarPointeeType &&
3960 CounterVarPointeeType->
getOpcode() == SPIRV::OpTypeStruct &&
3961 "Counter variable must be a struct");
3963 SPIRV::StorageClass::StorageBuffer &&
3964 "Counter variable must be in the storage buffer storage class");
3966 "Counter variable must have exactly 1 member in the struct");
3970 "Counter variable struct must have a single i32 member");
3974 MachineIRBuilder MIRBuilder(
I);
3976 Type::getInt32Ty(
I.getMF()->getFunction().getContext());
3979 LLVMIntType, MIRBuilder, SPIRV::StorageClass::StorageBuffer);
3981 auto Zero = buildI32Constant(0,
I);
3987 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3988 TII.get(SPIRV::OpAccessChain))
3991 .
addUse(CounterHandleReg)
3999 auto Scope = buildI32Constant(SPIRV::Scope::Device,
I);
4002 auto Semantics = buildI32Constant(SPIRV::MemorySemantics::None,
I);
4003 if (!Semantics.second)
4007 auto Incr = buildI32Constant(
static_cast<uint32_t
>(IncrVal),
I);
4012 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAtomicIAdd))
4023 return BuildCOPY(ResVReg, AtomicRes,
I);
4031 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIAddS))
4038bool SPIRVInstructionSelector::selectReadImageIntrinsic(
4047 Register ImageReg =
I.getOperand(2).getReg();
4049 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
4055 Register IdxReg =
I.getOperand(3).getReg();
4057 MachineInstr &Pos =
I;
4059 return generateImageReadOrFetch(ResVReg, ResType, NewImageReg, IdxReg, Loc,
4063bool SPIRVInstructionSelector::generateImageReadOrFetch(
4068 "ImageReg is not an image type.");
4070 bool IsSignedInteger =
4075 bool IsFetch = (SampledOp.getImm() == 1);
4078 if (ResultSize == 4) {
4081 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
4087 if (IsSignedInteger)
4092 SPIRVType *ReadType = widenTypeToVec4(ResType, Pos);
4096 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
4101 if (IsSignedInteger)
4107 if (ResultSize == 1) {
4109 TII.get(SPIRV::OpCompositeExtract))
4116 return extractSubvector(ResVReg, ResType, ReadReg, Pos);
4119bool SPIRVInstructionSelector::selectResourceGetPointer(
4121 Register ResourcePtr =
I.getOperand(2).getReg();
4123 if (RegType->
getOpcode() == SPIRV::OpTypeImage) {
4132 MachineIRBuilder MIRBuilder(
I);
4134 Register IndexReg =
I.getOperand(3).getReg();
4137 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4138 TII.get(SPIRV::OpAccessChain))
4147bool SPIRVInstructionSelector::selectPushConstantGetPointer(
4149 MRI->replaceRegWith(ResVReg,
I.getOperand(2).getReg());
4153bool SPIRVInstructionSelector::selectResourceNonUniformIndex(
4155 Register ObjReg =
I.getOperand(2).getReg();
4156 if (!BuildCOPY(ResVReg, ObjReg,
I))
4166 decorateUsesAsNonUniform(ResVReg);
4170void SPIRVInstructionSelector::decorateUsesAsNonUniform(
4173 while (WorkList.
size() > 0) {
4177 bool IsDecorated =
false;
4178 for (MachineInstr &Use :
MRI->use_instructions(CurrentReg)) {
4179 if (
Use.getOpcode() == SPIRV::OpDecorate &&
4180 Use.getOperand(1).getImm() == SPIRV::Decoration::NonUniformEXT) {
4186 if (
Use.getOperand(0).isReg() &&
Use.getOperand(0).isDef()) {
4188 if (ResultReg == CurrentReg)
4196 SPIRV::Decoration::NonUniformEXT, {});
4201bool SPIRVInstructionSelector::extractSubvector(
4203 MachineInstr &InsertionPoint)
const {
4205 [[maybe_unused]] uint64_t InputSize =
4208 assert(InputSize > 1 &&
"The input must be a vector.");
4209 assert(ResultSize > 1 &&
"The result must be a vector.");
4210 assert(ResultSize < InputSize &&
4211 "Cannot extract more element than there are in the input.");
4214 const TargetRegisterClass *ScalarRegClass = GR.
getRegClass(ScalarType);
4215 for (uint64_t
I = 0;
I < ResultSize;
I++) {
4216 Register ComponentReg =
MRI->createVirtualRegister(ScalarRegClass);
4219 TII.get(SPIRV::OpCompositeExtract))
4230 MachineInstrBuilder MIB =
BuildMI(*InsertionPoint.
getParent(), InsertionPoint,
4232 TII.get(SPIRV::OpCompositeConstruct))
4236 for (
Register ComponentReg : ComponentRegisters)
4237 MIB.
addUse(ComponentReg);
4241bool SPIRVInstructionSelector::selectImageWriteIntrinsic(
4242 MachineInstr &
I)
const {
4249 Register ImageReg =
I.getOperand(1).getReg();
4251 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
4257 Register CoordinateReg =
I.getOperand(2).getReg();
4258 Register DataReg =
I.getOperand(3).getReg();
4261 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4262 TII.get(SPIRV::OpImageWrite))
4269Register SPIRVInstructionSelector::buildPointerToResource(
4270 const SPIRVType *SpirvResType, SPIRV::StorageClass::StorageClass SC,
4271 uint32_t Set, uint32_t
Binding, uint32_t ArraySize,
Register IndexReg,
4272 StringRef Name, MachineIRBuilder MIRBuilder)
const {
4274 if (ArraySize == 1) {
4278 "SpirvResType did not have an explicit layout.");
4283 const Type *VarType = ArrayType::get(
const_cast<Type *
>(ResType), ArraySize);
4287 VarPointerType, Set,
Binding, Name, MIRBuilder);
4302bool SPIRVInstructionSelector::selectFirstBitSet16(
4304 unsigned ExtendOpcode,
unsigned BitSetOpcode)
const {
4306 bool Result = selectOpWithSrcs(ExtReg, ResType,
I, {
I.getOperand(2).getReg()},
4310 selectFirstBitSet32(ResVReg, ResType,
I, ExtReg, BitSetOpcode);
4313bool SPIRVInstructionSelector::selectFirstBitSet32(
4315 Register SrcReg,
unsigned BitSetOpcode)
const {
4316 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4319 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4325bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
4327 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4334 assert(ComponentCount < 5 &&
"Vec 5+ will generate invalid SPIR-V ops");
4336 MachineIRBuilder MIRBuilder(
I);
4344 std::vector<Register> PartialRegs;
4347 unsigned CurrentComponent = 0;
4348 for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
4354 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4355 TII.get(SPIRV::OpVectorShuffle))
4360 .
addImm(CurrentComponent)
4361 .
addImm(CurrentComponent + 1);
4369 if (!selectFirstBitSet64(SubVecBitSetReg, Vec2ResType,
I, BitSetResult,
4370 BitSetOpcode, SwapPrimarySide))
4373 PartialRegs.push_back(SubVecBitSetReg);
4377 if (CurrentComponent != ComponentCount) {
4383 if (!selectOpWithSrcs(FinalElemReg, I64Type,
I, {SrcReg, ConstIntLastIdx},
4384 SPIRV::OpVectorExtractDynamic))
4390 if (!selectFirstBitSet64(FinalElemBitSetReg,
BaseType,
I, FinalElemReg,
4391 BitSetOpcode, SwapPrimarySide))
4394 PartialRegs.push_back(FinalElemBitSetReg);
4399 return selectOpWithSrcs(ResVReg, ResType,
I, std::move(PartialRegs),
4400 SPIRV::OpCompositeConstruct);
4403bool SPIRVInstructionSelector::selectFirstBitSet64(
4405 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4418 if (ComponentCount > 2) {
4419 return selectFirstBitSet64Overflow(ResVReg, ResType,
I, SrcReg,
4420 BitSetOpcode, SwapPrimarySide);
4424 MachineIRBuilder MIRBuilder(
I);
4426 BaseType, 2 * ComponentCount, MIRBuilder,
false);
4430 if (!selectOpWithSrcs(BitcastReg, PostCastType,
I, {SrcReg},
4436 if (!selectFirstBitSet32(FBSReg, PostCastType,
I, BitcastReg, BitSetOpcode))
4443 bool IsScalarRes = ResType->
getOpcode() != SPIRV::OpTypeVector;
4446 if (!selectOpWithSrcs(HighReg, ResType,
I, {FBSReg, ConstIntZero},
4447 SPIRV::OpVectorExtractDynamic))
4449 if (!selectOpWithSrcs(LowReg, ResType,
I, {FBSReg, ConstIntOne},
4450 SPIRV::OpVectorExtractDynamic))
4454 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4455 TII.get(SPIRV::OpVectorShuffle))
4463 for (
unsigned J = 0; J < ComponentCount * 2; J += 2) {
4470 MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4471 TII.get(SPIRV::OpVectorShuffle))
4479 for (
unsigned J = 1; J < ComponentCount * 2; J += 2) {
4500 SelectOp = SPIRV::OpSelectSISCond;
4501 AddOp = SPIRV::OpIAddS;
4509 SelectOp = SPIRV::OpSelectVIVCond;
4510 AddOp = SPIRV::OpIAddV;
4520 if (SwapPrimarySide) {
4521 PrimaryReg = LowReg;
4522 SecondaryReg = HighReg;
4523 PrimaryShiftReg = Reg0;
4524 SecondaryShiftReg = Reg32;
4529 if (!selectOpWithSrcs(BReg, BoolType,
I, {PrimaryReg, NegOneReg},
4535 if (!selectOpWithSrcs(TmpReg, ResType,
I, {
BReg, SecondaryReg, PrimaryReg},
4541 if (!selectOpWithSrcs(ValReg, ResType,
I,
4542 {
BReg, SecondaryShiftReg, PrimaryShiftReg}, SelectOp))
4545 return selectOpWithSrcs(ResVReg, ResType,
I, {ValReg, TmpReg}, AddOp);
4548bool SPIRVInstructionSelector::selectFirstBitHigh(
Register ResVReg,
4551 bool IsSigned)
const {
4553 Register OpReg =
I.getOperand(2).getReg();
4556 unsigned ExtendOpcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
4557 unsigned BitSetOpcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
4561 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4563 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4565 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4569 "spv_firstbituhigh and spv_firstbitshigh only support 16,32,64 bits.");
4573bool SPIRVInstructionSelector::selectFirstBitLow(
Register ResVReg,
4575 MachineInstr &
I)
const {
4577 Register OpReg =
I.getOperand(2).getReg();
4582 unsigned ExtendOpcode = SPIRV::OpUConvert;
4583 unsigned BitSetOpcode = GL::FindILsb;
4587 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4589 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4591 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4598bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
4600 MachineInstr &
I)
const {
4604 bool Res =
BuildMI(BB,
I,
I.getDebugLoc(),
4605 TII.get(SPIRV::OpVariableLengthArrayINTEL))
4608 .
addUse(
I.getOperand(2).getReg())
4611 unsigned Alignment =
I.getOperand(3).getImm();
4617bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
4619 MachineInstr &
I)
const {
4623 bool Res =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
4624 TII.get(SPIRV::OpVariable))
4627 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
4630 unsigned Alignment =
I.getOperand(2).getImm();
4637bool SPIRVInstructionSelector::selectBranch(MachineInstr &
I)
const {
4642 const MachineInstr *PrevI =
I.getPrevNode();
4644 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
4645 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4648 .
addMBB(
I.getOperand(0).getMBB())
4652 .
addMBB(
I.getOperand(0).getMBB())
4656bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &
I)
const {
4667 const MachineInstr *NextI =
I.getNextNode();
4669 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
4675 MachineBasicBlock *NextMBB =
I.getMF()->getBlockNumbered(NextMBBNum);
4676 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4677 .
addUse(
I.getOperand(0).getReg())
4678 .
addMBB(
I.getOperand(1).getMBB())
4683bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
4685 MachineInstr &
I)
const {
4686 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
4689 const unsigned NumOps =
I.getNumOperands();
4690 for (
unsigned i = 1; i <
NumOps; i += 2) {
4691 MIB.
addUse(
I.getOperand(i + 0).getReg());
4692 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
4700bool SPIRVInstructionSelector::selectGlobalValue(
4701 Register ResVReg, MachineInstr &
I,
const MachineInstr *Init)
const {
4703 MachineIRBuilder MIRBuilder(
I);
4704 const GlobalValue *GV =
I.
getOperand(1).getGlobal();
4707 std::string GlobalIdent;
4709 unsigned &
ID = UnnamedGlobalIDs[GV];
4711 ID = UnnamedGlobalIDs.size();
4712 GlobalIdent =
"__unnamed_" + Twine(
ID).str();
4739 GVFun ? SPIRV::StorageClass::CodeSectionINTEL
4746 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4749 MRI->setRegClass(FuncVReg, &SPIRV::pIDRegClass);
4750 MachineInstrBuilder MIB1 =
4751 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
4754 MachineInstrBuilder MIB2 =
4756 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
4760 GR.
add(ConstVal, MIB2);
4766 MachineInstrBuilder MIB3 =
4767 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
4770 GR.
add(ConstVal, MIB3);
4773 assert(NewReg != ResVReg);
4774 return BuildCOPY(ResVReg, NewReg,
I);
4784 const std::optional<SPIRV::LinkageType::LinkageType> LnkType =
4793 GlobalVar->isConstant(), LnkType, MIRBuilder,
true);
4797bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
4799 MachineInstr &
I)
const {
4801 return selectExtInst(ResVReg, ResType,
I, CL::log10);
4809 MachineIRBuilder MIRBuilder(
I);
4815 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4818 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4820 .
add(
I.getOperand(1))
4825 ResType->
getOpcode() == SPIRV::OpTypeFloat);
4828 ResType->
getOpcode() == SPIRV::OpTypeVector
4835 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
4836 ? SPIRV::OpVectorTimesScalar
4846bool SPIRVInstructionSelector::selectModf(
Register ResVReg,
4848 MachineInstr &
I)
const {
4864 MachineIRBuilder MIRBuilder(
I);
4867 ResType, MIRBuilder, SPIRV::StorageClass::Function);
4879 MachineBasicBlock &EntryBB =
I.getMF()->front();
4883 BuildMI(EntryBB, VarPos,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
4886 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function));
4892 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4895 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::OpenCL_std))
4898 .
add(
I.getOperand(
I.getNumExplicitDefs()))
4902 Register IntegralPartReg =
I.getOperand(1).getReg();
4903 if (IntegralPartReg.
isValid()) {
4905 auto LoadMIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4914 assert(
false &&
"GLSL::Modf is deprecated.");
4925bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
4926 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4927 const SPIRVType *ResType, MachineInstr &
I)
const {
4928 MachineIRBuilder MIRBuilder(
I);
4932 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
4944 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
4948 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4949 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
4955 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4962 assert(
I.getOperand(2).isReg());
4963 const uint32_t ThreadId =
foldImm(
I.getOperand(2),
MRI);
4967 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
4977bool SPIRVInstructionSelector::loadBuiltinInputID(
4978 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4979 const SPIRVType *ResType, MachineInstr &
I)
const {
4980 MachineIRBuilder MIRBuilder(
I);
4982 ResType, MIRBuilder, SPIRV::StorageClass::Input);
4997 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
5001 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
5010 MachineInstr &
I)
const {
5011 MachineIRBuilder MIRBuilder(
I);
5012 if (
Type->getOpcode() != SPIRV::OpTypeVector)
5016 if (VectorSize == 4)
5024bool SPIRVInstructionSelector::loadHandleBeforePosition(
5026 MachineInstr &Pos)
const {
5029 Intrinsic::spv_resource_handlefrombinding);
5037 bool IsStructuredBuffer = ResType->
getOpcode() == SPIRV::OpTypePointer;
5038 MachineIRBuilder MIRBuilder(HandleDef);
5040 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::UniformConstant;
5042 if (IsStructuredBuffer) {
5047 Register VarReg = buildPointerToResource(VarType, SC, Set,
Binding, ArraySize,
5048 IndexReg, Name, MIRBuilder);
5052 uint32_t LoadOpcode =
5053 IsStructuredBuffer ? SPIRV::OpCopyObject : SPIRV::OpLoad;
5056 TII.get(LoadOpcode))
5063void SPIRVInstructionSelector::errorIfInstrOutsideShader(
5064 MachineInstr &
I)
const {
5066 std::string DiagMsg;
5067 raw_string_ostream OS(DiagMsg);
5068 I.print(OS,
true,
false,
false,
false);
5069 DiagMsg +=
" is only supported in shaders.\n";
5075InstructionSelector *
5079 return new SPIRVInstructionSelector(TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DXIL Resource Implicit Binding
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
LLVMTypeRef LLVMIntType(unsigned NumBits)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size)
static APFloat getOneFP(const Type *LLVMFloatTy)
static bool isUSMStorageClass(SPIRV::StorageClass::StorageClass SC)
static bool isASCastInGVar(MachineRegisterInfo *MRI, Register ResVReg)
static bool mayApplyGenericSelection(unsigned Opcode)
static APFloat getZeroFP(const Type *LLVMFloatTy)
std::vector< std::pair< SPIRV::InstructionSet::InstructionSet, uint32_t > > ExtInstList
static bool intrinsicHasSideEffects(Intrinsic::ID ID)
static unsigned getBoolCmpOpcode(unsigned PredNum)
static unsigned getICmpOpcode(unsigned PredNum)
static bool isOpcodeWithNoSideEffects(unsigned Opcode)
static void addMemoryOperands(MachineMemOperand *MemOp, MachineInstrBuilder &MIB, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry &GR)
static bool isConstReg(MachineRegisterInfo *MRI, MachineInstr *OpDef, SmallPtrSet< SPIRVType *, 4 > &Visited)
static unsigned getPtrCmpOpcode(unsigned Pred)
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static const fltSemantics & IEEEsingle()
static const fltSemantics & IEEEdouble()
static const fltSemantics & IEEEhalf()
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
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.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Represents a call to an intrinsic.
Intrinsic::ID getIntrinsicID() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
@ InternalLinkage
Rename collisions when linking (static functions).
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isPointer() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
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.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
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.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MONonTemporal
The memory access is non-temporal.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
defusechain_instr_iterator< false, true, false, true > def_instr_iterator
def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the specified register,...
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.
Analysis providing profile information.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getResultType(Register VReg, MachineFunction *MF=nullptr)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
MachineInstr * getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
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)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name, MachineIRBuilder &MIRBuilder)
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)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
void recordFunctionPointer(const MachineOperand *MO, const Function *F)
bool isAggregateType(SPIRVType *Type) const
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
MachineFunction * setCurrentFunc(MachineFunction &MF)
Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
bool erase(const MachineInstr *MI)
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
bool isPhysicalSPIRV() const
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const
bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const
bool isLogicalSPIRV() const
bool canUseExtension(SPIRV::Extension::Extension E) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
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.
constexpr size_t size() const
size - Get the string size.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
The instances of the Type class are immutable: once they are created, they are never changed.
@ HalfTyID
16-bit floating point type
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
bool isAggregateType() const
Return true if the type is an aggregate type.
TypeID getTypeID() const
Return the type id for the type.
Value * getOperand(unsigned i) const
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
NodeAddr< InstrNode * > Instr
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isTypeFoldingSupported(unsigned Opcode)
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)
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, const MachineInstr *ResType)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
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)
MachineBasicBlock::iterator getFirstValidInstructionInsertPoint(MachineBasicBlock &BB)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I)
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * toTypedPointer(Type *Ty)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
const MachineInstr SPIRVType
constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MachineInstr * passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
std::optional< SPIRV::LinkageType::LinkageType > getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
InstructionSelector * createSPIRVInstructionSelector(const SPIRVTargetMachine &TM, const SPIRVSubtarget &Subtarget, const RegisterBankInfo &RBI)
std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI)
int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool hasInitializer(const GlobalVariable *GV)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)
LLVM_ABI bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn't have oth...