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>
230 template <
typename PickOpcodeFn>
233 PickOpcodeFn &&PickOpcode)
const;
252 bool IsSigned,
unsigned Opcode)
const;
254 bool IsSigned)
const;
260 bool IsSigned)
const;
299 GL::GLSLExtInst GLInst)
const;
304 GL::GLSLExtInst GLInst)
const;
326 bool selectCounterHandleFromBinding(
Register &ResVReg,
339 bool selectResourceNonUniformIndex(
Register &ResVReg,
351 std::pair<Register, bool>
353 const SPIRVType *ResType =
nullptr)
const;
356 bool isScalarOrVectorIntConstantZero(
Register Reg)
const;
366 SPIRV::StorageClass::StorageClass SC)
const;
373 SPIRV::StorageClass::StorageClass SC,
385 bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
388 bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
393 void decorateUsesAsNonUniform(
Register &NonUniformReg)
const;
397bool sampledTypeIsSignedInteger(
const llvm::Type *HandleType) {
399 if (
TET->getTargetExtName() ==
"spirv.Image") {
402 assert(
TET->getTargetExtName() ==
"spirv.SignedImage");
403 return TET->getTypeParameter(0)->isIntegerTy();
407#define GET_GLOBALISEL_IMPL
408#include "SPIRVGenGlobalISel.inc"
409#undef GET_GLOBALISEL_IMPL
415 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
418#include
"SPIRVGenGlobalISel.inc"
421#include
"SPIRVGenGlobalISel.inc"
433 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
437void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
438 if (HasVRegsReset == &MF)
443 for (
unsigned I = 0,
E =
MRI.getNumVirtRegs();
I !=
E; ++
I) {
445 LLT RegType =
MRI.getType(
Reg);
453 for (
const auto &
MBB : MF) {
454 for (
const auto &
MI :
MBB) {
457 if (
MI.getOpcode() != SPIRV::ASSIGN_TYPE)
461 LLT DstType =
MRI.getType(DstReg);
463 LLT SrcType =
MRI.getType(SrcReg);
464 if (DstType != SrcType)
465 MRI.setType(DstReg,
MRI.getType(SrcReg));
467 const TargetRegisterClass *DstRC =
MRI.getRegClassOrNull(DstReg);
468 const TargetRegisterClass *SrcRC =
MRI.getRegClassOrNull(SrcReg);
469 if (DstRC != SrcRC && SrcRC)
470 MRI.setRegClass(DstReg, SrcRC);
486 case TargetOpcode::G_CONSTANT:
487 case TargetOpcode::G_FCONSTANT:
488 case TargetOpcode::G_IMPLICIT_DEF:
490 case TargetOpcode::G_INTRINSIC:
491 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
492 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
494 Intrinsic::spv_const_composite;
495 case TargetOpcode::G_BUILD_VECTOR:
496 case TargetOpcode::G_SPLAT_VECTOR: {
507 case SPIRV::OpConstantTrue:
508 case SPIRV::OpConstantFalse:
509 case SPIRV::OpConstantI:
510 case SPIRV::OpConstantF:
511 case SPIRV::OpConstantComposite:
512 case SPIRV::OpConstantCompositeContinuedINTEL:
513 case SPIRV::OpConstantSampler:
514 case SPIRV::OpConstantNull:
516 case SPIRV::OpConstantFunctionPointerINTEL:
542 case Intrinsic::spv_all:
543 case Intrinsic::spv_alloca:
544 case Intrinsic::spv_any:
545 case Intrinsic::spv_bitcast:
546 case Intrinsic::spv_const_composite:
547 case Intrinsic::spv_cross:
548 case Intrinsic::spv_degrees:
549 case Intrinsic::spv_distance:
550 case Intrinsic::spv_extractelt:
551 case Intrinsic::spv_extractv:
552 case Intrinsic::spv_faceforward:
553 case Intrinsic::spv_fdot:
554 case Intrinsic::spv_firstbitlow:
555 case Intrinsic::spv_firstbitshigh:
556 case Intrinsic::spv_firstbituhigh:
557 case Intrinsic::spv_frac:
558 case Intrinsic::spv_gep:
559 case Intrinsic::spv_global_offset:
560 case Intrinsic::spv_global_size:
561 case Intrinsic::spv_group_id:
562 case Intrinsic::spv_insertelt:
563 case Intrinsic::spv_insertv:
564 case Intrinsic::spv_isinf:
565 case Intrinsic::spv_isnan:
566 case Intrinsic::spv_lerp:
567 case Intrinsic::spv_length:
568 case Intrinsic::spv_normalize:
569 case Intrinsic::spv_num_subgroups:
570 case Intrinsic::spv_num_workgroups:
571 case Intrinsic::spv_ptrcast:
572 case Intrinsic::spv_radians:
573 case Intrinsic::spv_reflect:
574 case Intrinsic::spv_refract:
575 case Intrinsic::spv_resource_getpointer:
576 case Intrinsic::spv_resource_handlefrombinding:
577 case Intrinsic::spv_resource_handlefromimplicitbinding:
578 case Intrinsic::spv_resource_nonuniformindex:
579 case Intrinsic::spv_resource_sample:
580 case Intrinsic::spv_rsqrt:
581 case Intrinsic::spv_saturate:
582 case Intrinsic::spv_sdot:
583 case Intrinsic::spv_sign:
584 case Intrinsic::spv_smoothstep:
585 case Intrinsic::spv_step:
586 case Intrinsic::spv_subgroup_id:
587 case Intrinsic::spv_subgroup_local_invocation_id:
588 case Intrinsic::spv_subgroup_max_size:
589 case Intrinsic::spv_subgroup_size:
590 case Intrinsic::spv_thread_id:
591 case Intrinsic::spv_thread_id_in_group:
592 case Intrinsic::spv_udot:
593 case Intrinsic::spv_undef:
594 case Intrinsic::spv_value_md:
595 case Intrinsic::spv_workgroup_size:
607 case SPIRV::OpTypeVoid:
608 case SPIRV::OpTypeBool:
609 case SPIRV::OpTypeInt:
610 case SPIRV::OpTypeFloat:
611 case SPIRV::OpTypeVector:
612 case SPIRV::OpTypeMatrix:
613 case SPIRV::OpTypeImage:
614 case SPIRV::OpTypeSampler:
615 case SPIRV::OpTypeSampledImage:
616 case SPIRV::OpTypeArray:
617 case SPIRV::OpTypeRuntimeArray:
618 case SPIRV::OpTypeStruct:
619 case SPIRV::OpTypeOpaque:
620 case SPIRV::OpTypePointer:
621 case SPIRV::OpTypeFunction:
622 case SPIRV::OpTypeEvent:
623 case SPIRV::OpTypeDeviceEvent:
624 case SPIRV::OpTypeReserveId:
625 case SPIRV::OpTypeQueue:
626 case SPIRV::OpTypePipe:
627 case SPIRV::OpTypeForwardPointer:
628 case SPIRV::OpTypePipeStorage:
629 case SPIRV::OpTypeNamedBarrier:
630 case SPIRV::OpTypeAccelerationStructureNV:
631 case SPIRV::OpTypeCooperativeMatrixNV:
632 case SPIRV::OpTypeCooperativeMatrixKHR:
642 if (
MI.getNumDefs() == 0)
645 for (
const auto &MO :
MI.all_defs()) {
647 if (
Reg.isPhysical()) {
651 for (
const auto &
UseMI :
MRI.use_nodbg_instructions(
Reg)) {
652 if (
UseMI.getOpcode() != SPIRV::OpName) {
659 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE ||
MI.isFakeUse() ||
660 MI.isLifetimeMarker()) {
663 <<
"Not dead: Opcode is LOCAL_ESCAPE, fake use, or lifetime marker.\n");
674 if (
MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
675 MI.getOpcode() == TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS) {
678 LLVM_DEBUG(
dbgs() <<
"Dead: Intrinsic with no real side effects.\n");
683 if (
MI.mayStore() ||
MI.isCall() ||
684 (
MI.mayLoad() &&
MI.hasOrderedMemoryRef()) ||
MI.isPosition() ||
685 MI.isDebugInstr() ||
MI.isTerminator() ||
MI.isJumpTableDebugInfo()) {
686 LLVM_DEBUG(
dbgs() <<
"Not dead: instruction has side effects.\n");
697 LLVM_DEBUG(
dbgs() <<
"Dead: known opcode with no side effects\n");
704void SPIRVInstructionSelector::removeOpNamesForDeadMI(MachineInstr &
MI)
const {
706 for (
const auto &MO :
MI.all_defs()) {
710 SmallVector<MachineInstr *, 4> UselessOpNames;
711 for (MachineInstr &
UseMI :
MRI->use_nodbg_instructions(
Reg)) {
713 "There is still a use of the dead function.");
716 for (MachineInstr *OpNameMI : UselessOpNames) {
718 OpNameMI->eraseFromParent();
723void SPIRVInstructionSelector::removeDeadInstruction(MachineInstr &
MI)
const {
726 removeOpNamesForDeadMI(
MI);
727 MI.eraseFromParent();
730bool SPIRVInstructionSelector::select(MachineInstr &
I) {
731 resetVRegsType(*
I.getParent()->getParent());
733 assert(
I.getParent() &&
"Instruction should be in a basic block!");
734 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
739 removeDeadInstruction(
I);
746 if (Opcode == SPIRV::ASSIGN_TYPE) {
747 Register DstReg =
I.getOperand(0).getReg();
748 Register SrcReg =
I.getOperand(1).getReg();
749 auto *
Def =
MRI->getVRegDef(SrcReg);
751 Def->getOpcode() != TargetOpcode::G_CONSTANT &&
752 Def->getOpcode() != TargetOpcode::G_FCONSTANT) {
754 if (
Def->getOpcode() == TargetOpcode::G_SELECT) {
755 Register SelectDstReg =
Def->getOperand(0).getReg();
759 Def->removeFromParent();
760 MRI->replaceRegWith(DstReg, SelectDstReg);
762 I.removeFromParent();
764 Res = selectImpl(
I, *CoverageInfo);
766 if (!Res &&
Def->getOpcode() != TargetOpcode::G_CONSTANT) {
767 dbgs() <<
"Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
771 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
778 MRI->setRegClass(SrcReg,
MRI->getRegClass(DstReg));
779 MRI->replaceRegWith(SrcReg, DstReg);
781 I.removeFromParent();
783 }
else if (
I.getNumDefs() == 1) {
790 if (DeadMIs.contains(&
I)) {
794 removeDeadInstruction(
I);
798 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
799 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
805 bool HasDefs =
I.getNumDefs() > 0;
808 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
809 I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
810 if (spvSelect(ResVReg, ResType,
I)) {
812 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
815 I.removeFromParent();
823 case TargetOpcode::G_CONSTANT:
824 case TargetOpcode::G_FCONSTANT:
826 case TargetOpcode::G_SADDO:
827 case TargetOpcode::G_SSUBO:
834 MachineInstr &
I)
const {
835 const TargetRegisterClass *DstRC =
MRI->getRegClassOrNull(DestReg);
836 const TargetRegisterClass *SrcRC =
MRI->getRegClassOrNull(SrcReg);
837 if (DstRC != SrcRC && SrcRC)
838 MRI->setRegClass(DestReg, SrcRC);
839 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
840 TII.get(TargetOpcode::COPY))
846bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
848 MachineInstr &
I)
const {
849 const unsigned Opcode =
I.getOpcode();
851 return selectImpl(
I, *CoverageInfo);
853 case TargetOpcode::G_CONSTANT:
854 case TargetOpcode::G_FCONSTANT:
855 return selectConst(ResVReg, ResType,
I);
856 case TargetOpcode::G_GLOBAL_VALUE:
857 return selectGlobalValue(ResVReg,
I);
858 case TargetOpcode::G_IMPLICIT_DEF:
859 return selectOpUndef(ResVReg, ResType,
I);
860 case TargetOpcode::G_FREEZE:
861 return selectFreeze(ResVReg, ResType,
I);
863 case TargetOpcode::G_INTRINSIC:
864 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
865 case TargetOpcode::G_INTRINSIC_CONVERGENT:
866 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
867 return selectIntrinsic(ResVReg, ResType,
I);
868 case TargetOpcode::G_BITREVERSE:
869 return selectBitreverse(ResVReg, ResType,
I);
871 case TargetOpcode::G_BUILD_VECTOR:
872 return selectBuildVector(ResVReg, ResType,
I);
873 case TargetOpcode::G_SPLAT_VECTOR:
874 return selectSplatVector(ResVReg, ResType,
I);
876 case TargetOpcode::G_SHUFFLE_VECTOR: {
877 MachineBasicBlock &BB = *
I.getParent();
878 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
881 .
addUse(
I.getOperand(1).getReg())
882 .
addUse(
I.getOperand(2).getReg());
883 for (
auto V :
I.getOperand(3).getShuffleMask())
887 case TargetOpcode::G_MEMMOVE:
888 case TargetOpcode::G_MEMCPY:
889 case TargetOpcode::G_MEMSET:
890 return selectMemOperation(ResVReg,
I);
892 case TargetOpcode::G_ICMP:
893 return selectICmp(ResVReg, ResType,
I);
894 case TargetOpcode::G_FCMP:
895 return selectFCmp(ResVReg, ResType,
I);
897 case TargetOpcode::G_FRAME_INDEX:
898 return selectFrameIndex(ResVReg, ResType,
I);
900 case TargetOpcode::G_LOAD:
901 return selectLoad(ResVReg, ResType,
I);
902 case TargetOpcode::G_STORE:
903 return selectStore(
I);
905 case TargetOpcode::G_BR:
906 return selectBranch(
I);
907 case TargetOpcode::G_BRCOND:
908 return selectBranchCond(
I);
910 case TargetOpcode::G_PHI:
911 return selectPhi(ResVReg, ResType,
I);
913 case TargetOpcode::G_FPTOSI:
914 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
915 case TargetOpcode::G_FPTOUI:
916 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
918 case TargetOpcode::G_FPTOSI_SAT:
919 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
920 case TargetOpcode::G_FPTOUI_SAT:
921 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
923 case TargetOpcode::G_SITOFP:
924 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
925 case TargetOpcode::G_UITOFP:
926 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
928 case TargetOpcode::G_CTPOP:
929 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
930 case TargetOpcode::G_SMIN:
931 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
932 case TargetOpcode::G_UMIN:
933 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
935 case TargetOpcode::G_SMAX:
936 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
937 case TargetOpcode::G_UMAX:
938 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
940 case TargetOpcode::G_SCMP:
941 return selectSUCmp(ResVReg, ResType,
I,
true);
942 case TargetOpcode::G_UCMP:
943 return selectSUCmp(ResVReg, ResType,
I,
false);
944 case TargetOpcode::G_LROUND:
945 case TargetOpcode::G_LLROUND: {
947 MRI->createVirtualRegister(
MRI->getRegClass(ResVReg),
"lround");
948 MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
950 regForLround, *(
I.getParent()->getParent()));
952 I, CL::round, GL::Round);
954 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConvertFToS))
960 case TargetOpcode::G_STRICT_FMA:
961 case TargetOpcode::G_FMA: {
964 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFmaKHR))
967 .
addUse(
I.getOperand(1).getReg())
968 .
addUse(
I.getOperand(2).getReg())
969 .
addUse(
I.getOperand(3).getReg())
973 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
976 case TargetOpcode::G_STRICT_FLDEXP:
977 return selectExtInst(ResVReg, ResType,
I, CL::ldexp);
979 case TargetOpcode::G_FPOW:
980 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
981 case TargetOpcode::G_FPOWI:
982 return selectExtInst(ResVReg, ResType,
I, CL::pown);
984 case TargetOpcode::G_FEXP:
985 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
986 case TargetOpcode::G_FEXP2:
987 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
988 case TargetOpcode::G_FMODF:
989 return selectModf(ResVReg, ResType,
I);
991 case TargetOpcode::G_FLOG:
992 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
993 case TargetOpcode::G_FLOG2:
994 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
995 case TargetOpcode::G_FLOG10:
996 return selectLog10(ResVReg, ResType,
I);
998 case TargetOpcode::G_FABS:
999 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
1000 case TargetOpcode::G_ABS:
1001 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
1003 case TargetOpcode::G_FMINNUM:
1004 case TargetOpcode::G_FMINIMUM:
1005 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
1006 case TargetOpcode::G_FMAXNUM:
1007 case TargetOpcode::G_FMAXIMUM:
1008 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
1010 case TargetOpcode::G_FCOPYSIGN:
1011 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
1013 case TargetOpcode::G_FCEIL:
1014 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
1015 case TargetOpcode::G_FFLOOR:
1016 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
1018 case TargetOpcode::G_FCOS:
1019 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
1020 case TargetOpcode::G_FSIN:
1021 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
1022 case TargetOpcode::G_FTAN:
1023 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
1024 case TargetOpcode::G_FACOS:
1025 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
1026 case TargetOpcode::G_FASIN:
1027 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
1028 case TargetOpcode::G_FATAN:
1029 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
1030 case TargetOpcode::G_FATAN2:
1031 return selectExtInst(ResVReg, ResType,
I, CL::atan2, GL::Atan2);
1032 case TargetOpcode::G_FCOSH:
1033 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
1034 case TargetOpcode::G_FSINH:
1035 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
1036 case TargetOpcode::G_FTANH:
1037 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
1039 case TargetOpcode::G_STRICT_FSQRT:
1040 case TargetOpcode::G_FSQRT:
1041 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
1043 case TargetOpcode::G_CTTZ:
1044 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1045 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
1046 case TargetOpcode::G_CTLZ:
1047 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1048 return selectExtInst(ResVReg, ResType,
I, CL::clz);
1050 case TargetOpcode::G_INTRINSIC_ROUND:
1051 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
1052 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1053 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
1054 case TargetOpcode::G_INTRINSIC_TRUNC:
1055 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
1056 case TargetOpcode::G_FRINT:
1057 case TargetOpcode::G_FNEARBYINT:
1058 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
1060 case TargetOpcode::G_SMULH:
1061 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
1062 case TargetOpcode::G_UMULH:
1063 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
1065 case TargetOpcode::G_SADDSAT:
1066 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
1067 case TargetOpcode::G_UADDSAT:
1068 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
1069 case TargetOpcode::G_SSUBSAT:
1070 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
1071 case TargetOpcode::G_USUBSAT:
1072 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
1074 case TargetOpcode::G_FFREXP:
1075 return selectFrexp(ResVReg, ResType,
I);
1077 case TargetOpcode::G_UADDO:
1078 return selectOverflowArith(ResVReg, ResType,
I,
1079 ResType->
getOpcode() == SPIRV::OpTypeVector
1080 ? SPIRV::OpIAddCarryV
1081 : SPIRV::OpIAddCarryS);
1082 case TargetOpcode::G_USUBO:
1083 return selectOverflowArith(ResVReg, ResType,
I,
1084 ResType->
getOpcode() == SPIRV::OpTypeVector
1085 ? SPIRV::OpISubBorrowV
1086 : SPIRV::OpISubBorrowS);
1087 case TargetOpcode::G_UMULO:
1088 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpUMulExtended);
1089 case TargetOpcode::G_SMULO:
1090 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpSMulExtended);
1092 case TargetOpcode::G_SEXT:
1093 return selectExt(ResVReg, ResType,
I,
true);
1094 case TargetOpcode::G_ANYEXT:
1095 case TargetOpcode::G_ZEXT:
1096 return selectExt(ResVReg, ResType,
I,
false);
1097 case TargetOpcode::G_TRUNC:
1098 return selectTrunc(ResVReg, ResType,
I);
1099 case TargetOpcode::G_FPTRUNC:
1100 case TargetOpcode::G_FPEXT:
1101 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
1103 case TargetOpcode::G_PTRTOINT:
1104 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
1105 case TargetOpcode::G_INTTOPTR:
1106 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
1107 case TargetOpcode::G_BITCAST:
1108 return selectBitcast(ResVReg, ResType,
I);
1109 case TargetOpcode::G_ADDRSPACE_CAST:
1110 return selectAddrSpaceCast(ResVReg, ResType,
I);
1111 case TargetOpcode::G_PTR_ADD: {
1113 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1117 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1118 (*II).getOpcode() == TargetOpcode::COPY ||
1119 (*II).getOpcode() == SPIRV::OpVariable) &&
1122 bool IsGVInit =
false;
1124 UseIt =
MRI->use_instr_begin(
I.getOperand(0).getReg()),
1125 UseEnd =
MRI->use_instr_end();
1126 UseIt != UseEnd; UseIt = std::next(UseIt)) {
1127 if ((*UseIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1128 (*UseIt).getOpcode() == SPIRV::OpSpecConstantOp ||
1129 (*UseIt).getOpcode() == SPIRV::OpVariable) {
1139 if (GVPointeeType && ResPointeeType && GVPointeeType != ResPointeeType) {
1142 Register NewVReg =
MRI->createGenericVirtualRegister(
MRI->getType(GV));
1143 MRI->setRegClass(NewVReg,
MRI->getRegClass(GV));
1152 "incompatible result and operand types in a bitcast");
1154 MachineInstrBuilder MIB =
1155 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitcast))
1162 ? SPIRV::OpInBoundsAccessChain
1163 : SPIRV::OpInBoundsPtrAccessChain))
1167 .
addUse(
I.getOperand(2).getReg())
1170 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1174 static_cast<uint32_t
>(SPIRV::Opcode::InBoundsPtrAccessChain))
1176 .
addUse(
I.getOperand(2).getReg())
1184 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1187 .
addImm(
static_cast<uint32_t
>(
1188 SPIRV::Opcode::InBoundsPtrAccessChain))
1191 .
addUse(
I.getOperand(2).getReg());
1195 case TargetOpcode::G_ATOMICRMW_OR:
1196 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
1197 case TargetOpcode::G_ATOMICRMW_ADD:
1198 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
1199 case TargetOpcode::G_ATOMICRMW_AND:
1200 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
1201 case TargetOpcode::G_ATOMICRMW_MAX:
1202 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
1203 case TargetOpcode::G_ATOMICRMW_MIN:
1204 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
1205 case TargetOpcode::G_ATOMICRMW_SUB:
1206 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
1207 case TargetOpcode::G_ATOMICRMW_XOR:
1208 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
1209 case TargetOpcode::G_ATOMICRMW_UMAX:
1210 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
1211 case TargetOpcode::G_ATOMICRMW_UMIN:
1212 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
1213 case TargetOpcode::G_ATOMICRMW_XCHG:
1214 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
1215 case TargetOpcode::G_ATOMIC_CMPXCHG:
1216 return selectAtomicCmpXchg(ResVReg, ResType,
I);
1218 case TargetOpcode::G_ATOMICRMW_FADD:
1219 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
1220 case TargetOpcode::G_ATOMICRMW_FSUB:
1222 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
1223 ResType->
getOpcode() == SPIRV::OpTypeVector
1225 : SPIRV::OpFNegate);
1226 case TargetOpcode::G_ATOMICRMW_FMIN:
1227 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
1228 case TargetOpcode::G_ATOMICRMW_FMAX:
1229 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
1231 case TargetOpcode::G_FENCE:
1232 return selectFence(
I);
1234 case TargetOpcode::G_STACKSAVE:
1235 return selectStackSave(ResVReg, ResType,
I);
1236 case TargetOpcode::G_STACKRESTORE:
1237 return selectStackRestore(
I);
1239 case TargetOpcode::G_UNMERGE_VALUES:
1245 case TargetOpcode::G_TRAP:
1246 case TargetOpcode::G_UBSANTRAP:
1247 case TargetOpcode::DBG_LABEL:
1249 case TargetOpcode::G_DEBUGTRAP:
1250 return selectDebugTrap(ResVReg, ResType,
I);
1257bool SPIRVInstructionSelector::selectDebugTrap(
Register ResVReg,
1259 MachineInstr &
I)
const {
1260 unsigned Opcode = SPIRV::OpNop;
1262 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
1266bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1269 GL::GLSLExtInst GLInst)
const {
1271 SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) {
1272 std::string DiagMsg;
1273 raw_string_ostream OS(DiagMsg);
1274 I.print(OS,
true,
false,
false,
false);
1275 DiagMsg +=
" is only supported with the GLSL extended instruction set.\n";
1278 return selectExtInst(ResVReg, ResType,
I,
1279 {{SPIRV::InstructionSet::GLSL_std_450, GLInst}});
1282bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1285 CL::OpenCLExtInst CLInst)
const {
1286 return selectExtInst(ResVReg, ResType,
I,
1287 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
1290bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1293 CL::OpenCLExtInst CLInst,
1294 GL::GLSLExtInst GLInst)
const {
1295 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1296 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1297 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
1300bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1305 for (
const auto &Ex : Insts) {
1306 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1307 uint32_t Opcode = Ex.second;
1310 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1313 .
addImm(
static_cast<uint32_t
>(Set))
1316 const unsigned NumOps =
I.getNumOperands();
1319 I.getOperand(Index).getType() ==
1320 MachineOperand::MachineOperandType::MO_IntrinsicID)
1323 MIB.
add(
I.getOperand(Index));
1329bool SPIRVInstructionSelector::selectExtInstForLRound(
1331 CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst)
const {
1332 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1333 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1334 return selectExtInstForLRound(ResVReg, ResType,
I, ExtInsts);
1337bool SPIRVInstructionSelector::selectExtInstForLRound(
1340 for (
const auto &Ex : Insts) {
1341 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1342 uint32_t Opcode = Ex.second;
1345 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1348 .
addImm(
static_cast<uint32_t
>(Set))
1350 const unsigned NumOps =
I.getNumOperands();
1353 I.getOperand(Index).getType() ==
1354 MachineOperand::MachineOperandType::MO_IntrinsicID)
1357 MIB.
add(
I.getOperand(Index));
1365bool SPIRVInstructionSelector::selectFrexp(
Register ResVReg,
1367 MachineInstr &
I)
const {
1368 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CL::frexp},
1369 {SPIRV::InstructionSet::GLSL_std_450, GL::Frexp}};
1370 for (
const auto &Ex : ExtInsts) {
1371 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1372 uint32_t Opcode = Ex.second;
1376 MachineIRBuilder MIRBuilder(
I);
1379 PointeeTy, MIRBuilder, SPIRV::StorageClass::Function);
1384 auto MIB =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
1385 TII.get(SPIRV::OpVariable))
1388 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
1392 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1395 .
addImm(
static_cast<uint32_t
>(Ex.first))
1397 .
add(
I.getOperand(2))
1402 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1403 .
addDef(
I.getOperand(1).getReg())
1412bool SPIRVInstructionSelector::selectOpWithSrcs(
Register ResVReg,
1415 std::vector<Register> Srcs,
1416 unsigned Opcode)
const {
1417 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1426bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
1429 unsigned Opcode)
const {
1431 Register SrcReg =
I.getOperand(1).getReg();
1434 MRI->def_instr_begin(SrcReg);
1435 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
1436 unsigned DefOpCode = DefIt->getOpcode();
1437 if (DefOpCode == SPIRV::ASSIGN_TYPE || DefOpCode == TargetOpcode::COPY) {
1440 if (
auto *VRD =
getVRegDef(*
MRI, DefIt->getOperand(1).getReg()))
1441 DefOpCode = VRD->getOpcode();
1443 if (DefOpCode == TargetOpcode::G_GLOBAL_VALUE ||
1444 DefOpCode == TargetOpcode::G_CONSTANT ||
1445 DefOpCode == SPIRV::OpVariable || DefOpCode == SPIRV::OpConstantI) {
1451 uint32_t SpecOpcode = 0;
1453 case SPIRV::OpConvertPtrToU:
1454 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertPtrToU);
1456 case SPIRV::OpConvertUToPtr:
1457 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertUToPtr);
1461 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1462 TII.get(SPIRV::OpSpecConstantOp))
1470 return selectOpWithSrcs(ResVReg, ResType,
I, {
I.getOperand(1).getReg()},
1474bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
1476 MachineInstr &
I)
const {
1477 Register OpReg =
I.getOperand(1).getReg();
1481 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
1489 if (
MemOp->isVolatile())
1490 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1491 if (
MemOp->isNonTemporal())
1492 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1493 if (
MemOp->getAlign().value())
1494 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
1500 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
1501 if (
auto *MD =
MemOp->getAAInfo().Scope) {
1505 static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
1507 if (
auto *MD =
MemOp->getAAInfo().NoAlias) {
1511 static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
1515 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
1517 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
1529 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1531 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1533 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
1537bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
1539 MachineInstr &
I)
const {
1541 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1546 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1547 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1549 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1551 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1553 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1557 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1558 return generateImageReadOrFetch(ResVReg, ResType, NewHandleReg, IdxReg,
1559 I.getDebugLoc(),
I);
1563 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1567 if (!
I.getNumMemOperands()) {
1568 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1570 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1573 MachineIRBuilder MIRBuilder(
I);
1579bool SPIRVInstructionSelector::selectStore(MachineInstr &
I)
const {
1581 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
1582 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1587 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1588 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1590 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1593 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1597 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1598 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1599 auto BMI =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1600 TII.get(SPIRV::OpImageWrite))
1606 if (sampledTypeIsSignedInteger(LLVMHandleType))
1609 return BMI.constrainAllUses(
TII,
TRI, RBI);
1614 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
1617 if (!
I.getNumMemOperands()) {
1618 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1620 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1623 MachineIRBuilder MIRBuilder(
I);
1629bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
1631 MachineInstr &
I)
const {
1632 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1634 "llvm.stacksave intrinsic: this instruction requires the following "
1635 "SPIR-V extension: SPV_INTEL_variable_length_array",
1638 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
1644bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &
I)
const {
1645 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1647 "llvm.stackrestore intrinsic: this instruction requires the following "
1648 "SPIR-V extension: SPV_INTEL_variable_length_array",
1650 if (!
I.getOperand(0).isReg())
1653 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
1654 .
addUse(
I.getOperand(0).getReg())
1659SPIRVInstructionSelector::getOrCreateMemSetGlobal(MachineInstr &
I)
const {
1660 MachineIRBuilder MIRBuilder(
I);
1661 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1668 GlobalVariable *GV =
new GlobalVariable(*CurFunction.
getParent(), LLVMArrTy,
1672 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1673 Type *ArrTy = ArrayType::get(ValTy, Num);
1675 ArrTy, MIRBuilder, SPIRV::StorageClass::UniformConstant);
1678 ArrTy, MIRBuilder, SPIRV::AccessQualifier::None,
false);
1685 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
1688 .
addImm(SPIRV::StorageClass::UniformConstant)
1690 if (!MIBVar.constrainAllUses(
TII,
TRI, RBI))
1700bool SPIRVInstructionSelector::selectCopyMemory(MachineInstr &
I,
1703 Register DstReg =
I.getOperand(0).getReg();
1713 "Unable to determine pointee type size for OpCopyMemory");
1714 const DataLayout &
DL =
I.getMF()->getFunction().getDataLayout();
1715 if (CopySize !=
DL.getTypeStoreSize(
const_cast<Type *
>(LLVMPointeeTy)))
1717 "OpCopyMemory requires the size to match the pointee type size");
1718 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemory))
1721 if (
I.getNumMemOperands()) {
1722 MachineIRBuilder MIRBuilder(
I);
1728bool SPIRVInstructionSelector::selectCopyMemorySized(MachineInstr &
I,
1731 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
1732 .
addUse(
I.getOperand(0).getReg())
1734 .
addUse(
I.getOperand(2).getReg());
1735 if (
I.getNumMemOperands()) {
1736 MachineIRBuilder MIRBuilder(
I);
1742bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
1743 MachineInstr &
I)
const {
1744 Register SrcReg =
I.getOperand(1).getReg();
1746 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
1747 Register VarReg = getOrCreateMemSetGlobal(
I);
1750 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1752 ValTy,
I, SPIRV::StorageClass::UniformConstant);
1754 Result &= selectOpWithSrcs(SrcReg, SourceTy,
I, {VarReg}, SPIRV::OpBitcast);
1757 Result &= selectCopyMemory(
I, SrcReg);
1759 Result &= selectCopyMemorySized(
I, SrcReg);
1761 if (ResVReg.
isValid() && ResVReg !=
I.getOperand(0).getReg())
1762 Result &= BuildCOPY(ResVReg,
I.getOperand(0).getReg(),
I);
1766bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
1770 unsigned NegateOpcode)
const {
1773 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1776 auto ScopeConstant = buildI32Constant(Scope,
I);
1777 Register ScopeReg = ScopeConstant.first;
1778 Result &= ScopeConstant.second;
1780 Register Ptr =
I.getOperand(1).getReg();
1786 auto MemSemConstant = buildI32Constant(MemSem ,
I);
1787 Register MemSemReg = MemSemConstant.first;
1788 Result &= MemSemConstant.second;
1790 Register ValueReg =
I.getOperand(2).getReg();
1791 if (NegateOpcode != 0) {
1794 Result &= selectOpWithSrcs(TmpReg, ResType,
I, {ValueReg}, NegateOpcode);
1799 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(NewOpcode))
1809bool SPIRVInstructionSelector::selectUnmergeValues(MachineInstr &
I)
const {
1810 unsigned ArgI =
I.getNumOperands() - 1;
1812 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
1815 if (!SrcType || SrcType->
getOpcode() != SPIRV::OpTypeVector)
1817 "cannot select G_UNMERGE_VALUES with a non-vector argument");
1823 unsigned CurrentIndex = 0;
1824 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1825 Register ResVReg =
I.getOperand(i).getReg();
1828 LLT ResLLT =
MRI->getType(ResVReg);
1834 ResType = ScalarType;
1840 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1843 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
1849 for (
unsigned j = 0;
j < NumElements; ++
j) {
1850 MIB.
addImm(CurrentIndex + j);
1852 CurrentIndex += NumElements;
1856 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1868bool SPIRVInstructionSelector::selectFence(MachineInstr &
I)
const {
1871 auto MemSemConstant = buildI32Constant(MemSem,
I);
1872 Register MemSemReg = MemSemConstant.first;
1873 bool Result = MemSemConstant.second;
1875 uint32_t
Scope =
static_cast<uint32_t
>(
1877 auto ScopeConstant = buildI32Constant(Scope,
I);
1878 Register ScopeReg = ScopeConstant.first;
1879 Result &= ScopeConstant.second;
1882 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
1888bool SPIRVInstructionSelector::selectOverflowArith(
Register ResVReg,
1891 unsigned Opcode)
const {
1892 Type *ResTy =
nullptr;
1896 "Not enough info to select the arithmetic with overflow instruction");
1899 "with overflow instruction");
1905 MachineIRBuilder MIRBuilder(
I);
1907 ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
1908 assert(
I.getNumDefs() > 1 &&
"Not enought operands");
1914 Register ZeroReg = buildZerosVal(ResType,
I);
1917 MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
1919 if (ResName.
size() > 0)
1924 BuildMI(BB, MIRBuilder.getInsertPt(),
I.getDebugLoc(),
TII.get(Opcode))
1927 for (
unsigned i =
I.getNumDefs(); i <
I.getNumOperands(); ++i)
1928 MIB.
addUse(
I.getOperand(i).getReg());
1933 MRI->setRegClass(HigherVReg, &SPIRV::iIDRegClass);
1934 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1936 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1937 .
addDef(i == 1 ? HigherVReg :
I.getOperand(i).getReg())
1945 .
addDef(
I.getOperand(1).getReg())
1952bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
1954 MachineInstr &
I)
const {
1959 Register Ptr =
I.getOperand(2).getReg();
1962 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1965 auto ScopeConstant = buildI32Constant(Scope,
I);
1966 ScopeReg = ScopeConstant.first;
1967 Result &= ScopeConstant.second;
1969 unsigned ScSem =
static_cast<uint32_t
>(
1972 unsigned MemSemEq =
static_cast<uint32_t
>(
getMemSemantics(AO)) | ScSem;
1973 auto MemSemEqConstant = buildI32Constant(MemSemEq,
I);
1974 MemSemEqReg = MemSemEqConstant.first;
1975 Result &= MemSemEqConstant.second;
1977 unsigned MemSemNeq =
static_cast<uint32_t
>(
getMemSemantics(FO)) | ScSem;
1978 if (MemSemEq == MemSemNeq)
1979 MemSemNeqReg = MemSemEqReg;
1981 auto MemSemNeqConstant = buildI32Constant(MemSemEq,
I);
1982 MemSemNeqReg = MemSemNeqConstant.first;
1983 Result &= MemSemNeqConstant.second;
1986 ScopeReg =
I.getOperand(5).getReg();
1987 MemSemEqReg =
I.getOperand(6).getReg();
1988 MemSemNeqReg =
I.getOperand(7).getReg();
1992 Register Val =
I.getOperand(4).getReg();
1997 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
2024 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpCompositeInsert))
2035 case SPIRV::StorageClass::DeviceOnlyINTEL:
2036 case SPIRV::StorageClass::HostOnlyINTEL:
2045 bool IsGRef =
false;
2046 bool IsAllowedRefs =
2047 llvm::all_of(
MRI->use_instructions(ResVReg), [&IsGRef](
auto const &It) {
2048 unsigned Opcode = It.getOpcode();
2049 if (Opcode == SPIRV::OpConstantComposite ||
2050 Opcode == SPIRV::OpVariable ||
2051 isSpvIntrinsic(It, Intrinsic::spv_init_global))
2052 return IsGRef = true;
2053 return Opcode == SPIRV::OpName;
2055 return IsAllowedRefs && IsGRef;
2058Register SPIRVInstructionSelector::getUcharPtrTypeReg(
2059 MachineInstr &
I, SPIRV::StorageClass::StorageClass SC)
const {
2061 Type::getInt8Ty(
I.getMF()->getFunction().getContext()),
I, SC));
2065SPIRVInstructionSelector::buildSpecConstantOp(MachineInstr &
I,
Register Dest,
2067 uint32_t Opcode)
const {
2068 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2069 TII.get(SPIRV::OpSpecConstantOp))
2077SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &
I,
Register SrcPtr,
2081 Register Tmp =
MRI->createVirtualRegister(&SPIRV::pIDRegClass);
2083 SPIRV::StorageClass::Generic),
2085 MachineFunction *MF =
I.getParent()->getParent();
2087 MachineInstrBuilder MIB = buildSpecConstantOp(
2089 static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric));
2099bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
2101 MachineInstr &
I)
const {
2105 Register SrcPtr =
I.getOperand(1).getReg();
2109 if (SrcPtrTy->
getOpcode() != SPIRV::OpTypePointer ||
2110 ResType->
getOpcode() != SPIRV::OpTypePointer)
2111 return BuildCOPY(ResVReg, SrcPtr,
I);
2121 unsigned SpecOpcode =
2123 ?
static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric)
2126 ? static_cast<uint32_t>(
SPIRV::Opcode::GenericCastToPtr)
2133 return buildSpecConstantOp(
I, ResVReg, SrcPtr,
2134 getUcharPtrTypeReg(
I, DstSC), SpecOpcode)
2135 .constrainAllUses(
TII,
TRI, RBI);
2137 MachineInstrBuilder MIB = buildConstGenericPtr(
I, SrcPtr, SrcPtrTy);
2139 buildSpecConstantOp(
2141 getUcharPtrTypeReg(
I, DstSC),
2142 static_cast<uint32_t
>(SPIRV::Opcode::GenericCastToPtr))
2143 .constrainAllUses(
TII,
TRI, RBI);
2149 return BuildCOPY(ResVReg, SrcPtr,
I);
2151 if ((SrcSC == SPIRV::StorageClass::Function &&
2152 DstSC == SPIRV::StorageClass::Private) ||
2153 (DstSC == SPIRV::StorageClass::Function &&
2154 SrcSC == SPIRV::StorageClass::Private))
2155 return BuildCOPY(ResVReg, SrcPtr,
I);
2159 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
2162 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
2183 return selectUnOp(ResVReg, ResType,
I,
2184 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
2186 return selectUnOp(ResVReg, ResType,
I,
2187 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
2189 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
2191 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
2201 return SPIRV::OpFOrdEqual;
2203 return SPIRV::OpFOrdGreaterThanEqual;
2205 return SPIRV::OpFOrdGreaterThan;
2207 return SPIRV::OpFOrdLessThanEqual;
2209 return SPIRV::OpFOrdLessThan;
2211 return SPIRV::OpFOrdNotEqual;
2213 return SPIRV::OpOrdered;
2215 return SPIRV::OpFUnordEqual;
2217 return SPIRV::OpFUnordGreaterThanEqual;
2219 return SPIRV::OpFUnordGreaterThan;
2221 return SPIRV::OpFUnordLessThanEqual;
2223 return SPIRV::OpFUnordLessThan;
2225 return SPIRV::OpFUnordNotEqual;
2227 return SPIRV::OpUnordered;
2237 return SPIRV::OpIEqual;
2239 return SPIRV::OpINotEqual;
2241 return SPIRV::OpSGreaterThanEqual;
2243 return SPIRV::OpSGreaterThan;
2245 return SPIRV::OpSLessThanEqual;
2247 return SPIRV::OpSLessThan;
2249 return SPIRV::OpUGreaterThanEqual;
2251 return SPIRV::OpUGreaterThan;
2253 return SPIRV::OpULessThanEqual;
2255 return SPIRV::OpULessThan;
2264 return SPIRV::OpPtrEqual;
2266 return SPIRV::OpPtrNotEqual;
2277 return SPIRV::OpLogicalEqual;
2279 return SPIRV::OpLogicalNotEqual;
2313bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
2316 unsigned OpAnyOrAll)
const {
2317 assert(
I.getNumOperands() == 3);
2318 assert(
I.getOperand(2).isReg());
2320 Register InputRegister =
I.getOperand(2).getReg();
2327 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
2328 if (IsBoolTy && !IsVectorTy) {
2329 assert(ResVReg ==
I.getOperand(0).getReg());
2330 return BuildCOPY(ResVReg, InputRegister,
I);
2334 unsigned SpirvNotEqualId =
2335 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
2342 IsBoolTy ? InputRegister
2351 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
2371bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
2373 MachineInstr &
I)
const {
2374 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
2377bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
2379 MachineInstr &
I)
const {
2380 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
2384bool SPIRVInstructionSelector::selectFloatDot(
Register ResVReg,
2386 MachineInstr &
I)
const {
2387 assert(
I.getNumOperands() == 4);
2388 assert(
I.getOperand(2).isReg());
2389 assert(
I.getOperand(3).isReg());
2396 "dot product requires a vector of at least 2 components");
2404 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpDot))
2407 .
addUse(
I.getOperand(2).getReg())
2408 .
addUse(
I.getOperand(3).getReg())
2412bool SPIRVInstructionSelector::selectIntegerDot(
Register ResVReg,
2416 assert(
I.getNumOperands() == 4);
2417 assert(
I.getOperand(2).isReg());
2418 assert(
I.getOperand(3).isReg());
2421 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2425 .
addUse(
I.getOperand(2).getReg())
2426 .
addUse(
I.getOperand(3).getReg())
2432bool SPIRVInstructionSelector::selectIntegerDotExpansion(
2434 assert(
I.getNumOperands() == 4);
2435 assert(
I.getOperand(2).isReg());
2436 assert(
I.getOperand(3).isReg());
2440 Register Vec0 =
I.getOperand(2).getReg();
2441 Register Vec1 =
I.getOperand(3).getReg();
2454 "dot product requires a vector of at least 2 components");
2468 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2491bool SPIRVInstructionSelector::selectOpIsInf(
Register ResVReg,
2493 MachineInstr &
I)
const {
2495 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsInf))
2498 .
addUse(
I.getOperand(2).getReg())
2502bool SPIRVInstructionSelector::selectOpIsNan(
Register ResVReg,
2504 MachineInstr &
I)
const {
2506 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsNan))
2509 .
addUse(
I.getOperand(2).getReg())
2513template <
bool Signed>
2514bool SPIRVInstructionSelector::selectDot4AddPacked(
Register ResVReg,
2516 MachineInstr &
I)
const {
2517 assert(
I.getNumOperands() == 5);
2518 assert(
I.getOperand(2).isReg());
2519 assert(
I.getOperand(3).isReg());
2520 assert(
I.getOperand(4).isReg());
2523 Register Acc =
I.getOperand(2).getReg();
2527 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2547template <
bool Signed>
2548bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
2550 assert(
I.getNumOperands() == 5);
2551 assert(
I.getOperand(2).isReg());
2552 assert(
I.getOperand(3).isReg());
2553 assert(
I.getOperand(4).isReg());
2558 Register Acc =
I.getOperand(2).getReg();
2564 Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
2568 for (
unsigned i = 0; i < 4; i++) {
2570 Register AElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2581 Register BElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2601 Register MaskMul =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2613 i < 3 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
2629bool SPIRVInstructionSelector::selectSaturate(
Register ResVReg,
2631 MachineInstr &
I)
const {
2632 assert(
I.getNumOperands() == 3);
2633 assert(
I.getOperand(2).isReg());
2635 Register VZero = buildZerosValF(ResType,
I);
2636 Register VOne = buildOnesValF(ResType,
I);
2638 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2641 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2643 .
addUse(
I.getOperand(2).getReg())
2649bool SPIRVInstructionSelector::selectSign(
Register ResVReg,
2651 MachineInstr &
I)
const {
2652 assert(
I.getNumOperands() == 3);
2653 assert(
I.getOperand(2).isReg());
2655 Register InputRegister =
I.getOperand(2).getReg();
2657 auto &
DL =
I.getDebugLoc();
2667 bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth;
2669 auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign;
2671 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass)
2678 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2683 if (NeedsConversion) {
2684 auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert;
2695bool SPIRVInstructionSelector::selectWaveOpInst(
Register ResVReg,
2698 unsigned Opcode)
const {
2702 auto BMI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2708 for (
unsigned J = 2; J <
I.getNumOperands(); J++) {
2709 BMI.addUse(
I.getOperand(J).getReg());
2715bool SPIRVInstructionSelector::selectWaveActiveCountBits(
2721 bool Result = selectWaveOpInst(BallotReg, BallotType,
I,
2722 SPIRV::OpGroupNonUniformBallot);
2726 TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
2731 .
addImm(SPIRV::GroupOperation::Reduce)
2738bool SPIRVInstructionSelector::selectWavePrefixBitCount(
2741 assert(
I.getNumOperands() == 3);
2743 auto Op =
I.getOperand(2);
2755 if (InputType->
getOpcode() != SPIRV::OpTypeBool)
2766 Register BallotVReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2777 BuildMI(BB,
I,
DL,
TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
2781 .
addImm(SPIRV::GroupOperation::ExclusiveScan)
2788bool SPIRVInstructionSelector::selectWaveReduceMax(
Register ResVReg,
2791 bool IsUnsigned)
const {
2792 return selectWaveReduce(
2793 ResVReg, ResType,
I, IsUnsigned,
2794 [&](
Register InputRegister,
bool IsUnsigned) {
2795 const bool IsFloatTy =
2797 const unsigned IntOp = IsUnsigned ? SPIRV::OpGroupNonUniformUMax
2798 : SPIRV::OpGroupNonUniformSMax;
2799 return IsFloatTy ? SPIRV::OpGroupNonUniformFMax : IntOp;
2803bool SPIRVInstructionSelector::selectWaveReduceMin(
Register ResVReg,
2806 bool IsUnsigned)
const {
2807 return selectWaveReduce(
2808 ResVReg, ResType,
I, IsUnsigned,
2809 [&](
Register InputRegister,
bool IsUnsigned) {
2810 const bool IsFloatTy =
2812 const unsigned IntOp = IsUnsigned ? SPIRV::OpGroupNonUniformUMin
2813 : SPIRV::OpGroupNonUniformSMin;
2814 return IsFloatTy ? SPIRV::OpGroupNonUniformFMin : IntOp;
2818bool SPIRVInstructionSelector::selectWaveReduceSum(
Register ResVReg,
2820 MachineInstr &
I)
const {
2821 return selectWaveReduce(ResVReg, ResType,
I,
false,
2822 [&](
Register InputRegister,
bool IsUnsigned) {
2824 InputRegister, SPIRV::OpTypeFloat);
2825 return IsFloatTy ? SPIRV::OpGroupNonUniformFAdd
2826 : SPIRV::OpGroupNonUniformIAdd;
2830template <
typename PickOpcodeFn>
2831bool SPIRVInstructionSelector::selectWaveReduce(
2833 bool IsUnsigned, PickOpcodeFn &&PickOpcode)
const {
2834 assert(
I.getNumOperands() == 3);
2835 assert(
I.getOperand(2).isReg());
2837 Register InputRegister =
I.getOperand(2).getReg();
2844 const unsigned Opcode = PickOpcode(InputRegister, IsUnsigned);
2845 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2850 .
addImm(SPIRV::GroupOperation::Reduce)
2851 .
addUse(
I.getOperand(2).getReg())
2855bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
2857 MachineInstr &
I)
const {
2859 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
2862 .
addUse(
I.getOperand(1).getReg())
2866bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
2868 MachineInstr &
I)
const {
2874 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
2876 Register OpReg =
I.getOperand(1).getReg();
2877 if (MachineInstr *Def =
MRI->getVRegDef(OpReg)) {
2878 if (
Def->getOpcode() == TargetOpcode::COPY)
2879 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
2881 switch (
Def->getOpcode()) {
2882 case SPIRV::ASSIGN_TYPE:
2883 if (MachineInstr *AssignToDef =
2884 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
2885 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2886 Reg =
Def->getOperand(2).getReg();
2889 case SPIRV::OpUndef:
2890 Reg =
Def->getOperand(1).getReg();
2893 unsigned DestOpCode;
2895 DestOpCode = SPIRV::OpConstantNull;
2897 DestOpCode = TargetOpcode::COPY;
2900 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
2901 .
addDef(
I.getOperand(0).getReg())
2908bool SPIRVInstructionSelector::selectBuildVector(
Register ResVReg,
2910 MachineInstr &
I)
const {
2912 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2914 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2918 if (
I.getNumExplicitOperands() -
I.getNumExplicitDefs() !=
N)
2923 for (
unsigned i =
I.getNumExplicitDefs();
2924 i <
I.getNumExplicitOperands() && IsConst; ++i)
2928 if (!IsConst &&
N < 2)
2930 "There must be at least two constituent operands in a vector");
2933 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2934 TII.get(IsConst ? SPIRV::OpConstantComposite
2935 : SPIRV::OpCompositeConstruct))
2938 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
2939 MIB.
addUse(
I.getOperand(i).getReg());
2943bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
2945 MachineInstr &
I)
const {
2947 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2949 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2955 if (!
I.getOperand(
OpIdx).isReg())
2962 if (!IsConst &&
N < 2)
2964 "There must be at least two constituent operands in a vector");
2967 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2968 TII.get(IsConst ? SPIRV::OpConstantComposite
2969 : SPIRV::OpCompositeConstruct))
2972 for (
unsigned i = 0; i <
N; ++i)
2977bool SPIRVInstructionSelector::selectDiscard(
Register ResVReg,
2979 MachineInstr &
I)
const {
2984 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
2986 Opcode = SPIRV::OpDemoteToHelperInvocation;
2988 Opcode = SPIRV::OpKill;
2990 if (MachineInstr *NextI =
I.getNextNode()) {
2992 NextI->removeFromParent();
2997 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
3001bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
3004 MachineInstr &
I)
const {
3005 Register Cmp0 =
I.getOperand(2).getReg();
3006 Register Cmp1 =
I.getOperand(3).getReg();
3009 "CMP operands should have the same type");
3010 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
3019bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
3021 MachineInstr &
I)
const {
3022 auto Pred =
I.getOperand(1).getPredicate();
3025 Register CmpOperand =
I.getOperand(2).getReg();
3032 return selectCmp(ResVReg, ResType, CmpOpc,
I);
3035std::pair<Register, bool>
3036SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &
I,
3042 auto ConstInt = ConstantInt::get(LLVMTy, Val);
3050 ?
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
3053 :
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
3056 .
addImm(APInt(32, Val).getZExtValue());
3058 GR.
add(ConstInt,
MI);
3063bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
3065 MachineInstr &
I)
const {
3067 return selectCmp(ResVReg, ResType, CmpOp,
I);
3071 MachineInstr &
I)
const {
3074 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3079bool SPIRVInstructionSelector::isScalarOrVectorIntConstantZero(
3085 if (!CompType || CompType->
getOpcode() != SPIRV::OpTypeInt)
3093 if (
Def->getOpcode() == SPIRV::OpConstantNull)
3096 if (
Def->getOpcode() == TargetOpcode::G_CONSTANT ||
3097 Def->getOpcode() == SPIRV::OpConstantI)
3106 MachineInstr *
Def =
MRI->getVRegDef(
Reg);
3110 if (
Def->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
3111 (
Def->getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
3113 Intrinsic::spv_const_composite)) {
3114 unsigned StartOp =
Def->getOpcode() == TargetOpcode::G_BUILD_VECTOR ? 1 : 2;
3115 for (
unsigned i = StartOp; i <
Def->getNumOperands(); ++i) {
3116 if (!IsZero(
Def->getOperand(i).getReg()))
3126 MachineInstr &
I)
const {
3130 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3136 MachineInstr &
I)
const {
3140 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3147 MachineInstr &
I)
const {
3151 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
3156bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
3158 MachineInstr &
I)
const {
3159 Register SelectFirstArg =
I.getOperand(2).getReg();
3160 Register SelectSecondArg =
I.getOperand(3).getReg();
3169 SPIRV::OpTypeVector;
3176 Opcode = IsScalarBool ? SPIRV::OpSelectVFSCond : SPIRV::OpSelectVFVCond;
3177 }
else if (IsPtrTy) {
3178 Opcode = IsScalarBool ? SPIRV::OpSelectVPSCond : SPIRV::OpSelectVPVCond;
3180 Opcode = IsScalarBool ? SPIRV::OpSelectVISCond : SPIRV::OpSelectVIVCond;
3184 Opcode = IsScalarBool ? SPIRV::OpSelectSFSCond : SPIRV::OpSelectVFVCond;
3185 }
else if (IsPtrTy) {
3186 Opcode = IsScalarBool ? SPIRV::OpSelectSPSCond : SPIRV::OpSelectVPVCond;
3188 Opcode = IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
3191 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3194 .
addUse(
I.getOperand(1).getReg())
3200bool SPIRVInstructionSelector::selectSelectDefaultArgs(
Register ResVReg,
3203 bool IsSigned)
const {
3205 Register ZeroReg = buildZerosVal(ResType,
I);
3206 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
3210 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
3211 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3214 .
addUse(
I.getOperand(1).getReg())
3220bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
3222 MachineInstr &
I,
bool IsSigned,
3223 unsigned Opcode)
const {
3224 Register SrcReg =
I.getOperand(1).getReg();
3230 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
3235 selectSelectDefaultArgs(SrcReg, TmpType,
I,
false);
3237 return selectOpWithSrcs(ResVReg, ResType,
I, {SrcReg}, Opcode);
3240bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
3242 MachineInstr &
I,
bool IsSigned)
const {
3243 Register SrcReg =
I.getOperand(1).getReg();
3245 return selectSelectDefaultArgs(ResVReg, ResType,
I, IsSigned);
3248 if (SrcType == ResType)
3249 return BuildCOPY(ResVReg, SrcReg,
I);
3251 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3252 return selectUnOp(ResVReg, ResType,
I, Opcode);
3255bool SPIRVInstructionSelector::selectSUCmp(
Register ResVReg,
3258 bool IsSigned)
const {
3259 MachineIRBuilder MIRBuilder(
I);
3260 MachineRegisterInfo *
MRI = MIRBuilder.getMRI();
3275 TII.get(IsSigned ? SPIRV::OpSLessThanEqual
3276 : SPIRV::OpULessThanEqual))
3279 .
addUse(
I.getOperand(1).getReg())
3280 .
addUse(
I.getOperand(2).getReg())
3286 TII.get(IsSigned ? SPIRV::OpSLessThan : SPIRV::OpULessThan))
3289 .
addUse(
I.getOperand(1).getReg())
3290 .
addUse(
I.getOperand(2).getReg())
3298 unsigned SelectOpcode =
3299 N > 1 ? SPIRV::OpSelectVIVCond : SPIRV::OpSelectSISCond;
3304 .
addUse(buildOnesVal(
true, ResType,
I))
3305 .
addUse(buildZerosVal(ResType,
I))
3312 .
addUse(buildOnesVal(
false, ResType,
I))
3316bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
3323 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
3324 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
3326 Register One = buildOnesVal(
false, IntTy,
I);
3342bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
3344 MachineInstr &
I)
const {
3345 Register IntReg =
I.getOperand(1).getReg();
3348 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
3349 if (ArgType == ResType)
3350 return BuildCOPY(ResVReg, IntReg,
I);
3352 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3353 return selectUnOp(ResVReg, ResType,
I, Opcode);
3356bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
3358 MachineInstr &
I)
const {
3359 unsigned Opcode =
I.getOpcode();
3360 unsigned TpOpcode = ResType->
getOpcode();
3362 if (TpOpcode == SPIRV::OpTypePointer || TpOpcode == SPIRV::OpTypeEvent) {
3363 assert(Opcode == TargetOpcode::G_CONSTANT &&
3364 I.getOperand(1).getCImm()->isZero());
3365 MachineBasicBlock &DepMBB =
I.getMF()->front();
3368 }
else if (Opcode == TargetOpcode::G_FCONSTANT) {
3375 return Reg == ResVReg ?
true : BuildCOPY(ResVReg,
Reg,
I);
3378bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
3380 MachineInstr &
I)
const {
3381 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3387bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
3389 MachineInstr &
I)
const {
3391 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
3395 .
addUse(
I.getOperand(3).getReg())
3397 .
addUse(
I.getOperand(2).getReg());
3398 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
3403bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
3405 MachineInstr &
I)
const {
3406 Type *MaybeResTy =
nullptr;
3412 "Expected aggregate type for extractv instruction");
3414 SPIRV::AccessQualifier::ReadWrite,
false);
3418 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
3421 .
addUse(
I.getOperand(2).getReg());
3422 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
3427bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
3429 MachineInstr &
I)
const {
3431 return selectInsertVal(ResVReg, ResType,
I);
3433 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
3436 .
addUse(
I.getOperand(2).getReg())
3437 .
addUse(
I.getOperand(3).getReg())
3438 .
addUse(
I.getOperand(4).getReg())
3442bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
3444 MachineInstr &
I)
const {
3446 return selectExtractVal(ResVReg, ResType,
I);
3448 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
3451 .
addUse(
I.getOperand(2).getReg())
3452 .
addUse(
I.getOperand(3).getReg())
3456bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
3458 MachineInstr &
I)
const {
3459 const bool IsGEPInBounds =
I.getOperand(2).getImm();
3465 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
3466 : SPIRV::OpAccessChain)
3467 : (IsGEPInBounds ?
SPIRV::OpInBoundsPtrAccessChain
3468 :
SPIRV::OpPtrAccessChain);
3470 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3474 .
addUse(
I.getOperand(3).getReg());
3476 (Opcode == SPIRV::OpPtrAccessChain ||
3477 Opcode == SPIRV::OpInBoundsPtrAccessChain ||
3479 "Cannot translate GEP to OpAccessChain. First index must be 0.");
3482 const unsigned StartingIndex =
3483 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
3486 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
3487 Res.addUse(
I.getOperand(i).getReg());
3488 return Res.constrainAllUses(
TII,
TRI, RBI);
3492bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
3495 unsigned Lim =
I.getNumExplicitOperands();
3496 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
3497 Register OpReg =
I.getOperand(i).getReg();
3498 MachineInstr *OpDefine =
MRI->getVRegDef(OpReg);
3500 SmallPtrSet<SPIRVType *, 4> Visited;
3501 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
3502 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
3503 OpDefine->
getOpcode() == TargetOpcode::G_INTTOPTR ||
3510 MachineFunction *MF =
I.getMF();
3522 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3523 TII.get(SPIRV::OpSpecConstantOp))
3526 .
addImm(
static_cast<uint32_t
>(SPIRV::Opcode::Bitcast))
3528 GR.
add(OpDefine, MIB);
3536bool SPIRVInstructionSelector::selectDerivativeInst(
3538 const unsigned DPdOpCode)
const {
3541 errorIfInstrOutsideShader(
I);
3546 Register SrcReg =
I.getOperand(2).getReg();
3551 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DPdOpCode))
3554 .
addUse(
I.getOperand(2).getReg());
3556 MachineIRBuilder MIRBuilder(
I);
3559 if (componentCount != 1)
3563 const TargetRegisterClass *RegClass = GR.
getRegClass(SrcType);
3564 Register ConvertToVReg =
MRI->createVirtualRegister(RegClass);
3565 Register DpdOpVReg =
MRI->createVirtualRegister(RegClass);
3568 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3579 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3587bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
3589 MachineInstr &
I)
const {
3593 case Intrinsic::spv_load:
3594 return selectLoad(ResVReg, ResType,
I);
3595 case Intrinsic::spv_store:
3596 return selectStore(
I);
3597 case Intrinsic::spv_extractv:
3598 return selectExtractVal(ResVReg, ResType,
I);
3599 case Intrinsic::spv_insertv:
3600 return selectInsertVal(ResVReg, ResType,
I);
3601 case Intrinsic::spv_extractelt:
3602 return selectExtractElt(ResVReg, ResType,
I);
3603 case Intrinsic::spv_insertelt:
3604 return selectInsertElt(ResVReg, ResType,
I);
3605 case Intrinsic::spv_gep:
3606 return selectGEP(ResVReg, ResType,
I);
3607 case Intrinsic::spv_bitcast: {
3608 Register OpReg =
I.getOperand(2).getReg();
3613 return selectOpWithSrcs(ResVReg, ResType,
I, {OpReg}, SPIRV::OpBitcast);
3615 case Intrinsic::spv_unref_global:
3616 case Intrinsic::spv_init_global: {
3617 MachineInstr *
MI =
MRI->getVRegDef(
I.getOperand(1).getReg());
3618 MachineInstr *Init =
I.getNumExplicitOperands() > 2
3619 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
3622 Register GVarVReg =
MI->getOperand(0).getReg();
3623 bool Res = selectGlobalValue(GVarVReg, *
MI, Init);
3627 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
3629 MI->removeFromParent();
3633 case Intrinsic::spv_undef: {
3634 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3639 case Intrinsic::spv_const_composite: {
3641 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
3647 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
3649 MachineIRBuilder MIR(
I);
3651 MIR, SPIRV::OpConstantComposite, 3,
3652 SPIRV::OpConstantCompositeContinuedINTEL, CompositeArgs, ResVReg,
3654 for (
auto *Instr : Instructions) {
3655 Instr->setDebugLoc(
I.getDebugLoc());
3661 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
3667 case Intrinsic::spv_assign_name: {
3668 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
3669 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
3670 for (
unsigned i =
I.getNumExplicitDefs() + 2;
3671 i <
I.getNumExplicitOperands(); ++i) {
3672 MIB.
addImm(
I.getOperand(i).getImm());
3676 case Intrinsic::spv_switch: {
3677 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
3678 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3679 if (
I.getOperand(i).isReg())
3680 MIB.
addReg(
I.getOperand(i).getReg());
3681 else if (
I.getOperand(i).isCImm())
3682 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
3683 else if (
I.getOperand(i).isMBB())
3684 MIB.
addMBB(
I.getOperand(i).getMBB());
3690 case Intrinsic::spv_loop_merge: {
3691 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoopMerge));
3692 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3693 if (
I.getOperand(i).isMBB())
3694 MIB.
addMBB(
I.getOperand(i).getMBB());
3700 case Intrinsic::spv_selection_merge: {
3702 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSelectionMerge));
3703 assert(
I.getOperand(1).isMBB() &&
3704 "operand 1 to spv_selection_merge must be a basic block");
3705 MIB.
addMBB(
I.getOperand(1).getMBB());
3706 MIB.
addImm(getSelectionOperandForImm(
I.getOperand(2).getImm()));
3709 case Intrinsic::spv_cmpxchg:
3710 return selectAtomicCmpXchg(ResVReg, ResType,
I);
3711 case Intrinsic::spv_unreachable:
3712 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable))
3714 case Intrinsic::spv_alloca:
3715 return selectFrameIndex(ResVReg, ResType,
I);
3716 case Intrinsic::spv_alloca_array:
3717 return selectAllocaArray(ResVReg, ResType,
I);
3718 case Intrinsic::spv_assume:
3720 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
3721 .
addUse(
I.getOperand(1).getReg())
3724 case Intrinsic::spv_expect:
3726 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
3729 .
addUse(
I.getOperand(2).getReg())
3730 .
addUse(
I.getOperand(3).getReg())
3733 case Intrinsic::arithmetic_fence:
3736 TII.get(SPIRV::OpArithmeticFenceEXT))
3739 .
addUse(
I.getOperand(2).getReg())
3742 return BuildCOPY(ResVReg,
I.getOperand(2).getReg(),
I);
3744 case Intrinsic::spv_thread_id:
3750 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalInvocationId, ResVReg,
3752 case Intrinsic::spv_thread_id_in_group:
3758 return loadVec3BuiltinInputID(SPIRV::BuiltIn::LocalInvocationId, ResVReg,
3760 case Intrinsic::spv_group_id:
3766 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
3768 case Intrinsic::spv_flattened_thread_id_in_group:
3775 return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
3777 case Intrinsic::spv_workgroup_size:
3778 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupSize, ResVReg,
3780 case Intrinsic::spv_global_size:
3781 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalSize, ResVReg, ResType,
3783 case Intrinsic::spv_global_offset:
3784 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalOffset, ResVReg,
3786 case Intrinsic::spv_num_workgroups:
3787 return loadVec3BuiltinInputID(SPIRV::BuiltIn::NumWorkgroups, ResVReg,
3789 case Intrinsic::spv_subgroup_size:
3790 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupSize, ResVReg, ResType,
3792 case Intrinsic::spv_num_subgroups:
3793 return loadBuiltinInputID(SPIRV::BuiltIn::NumSubgroups, ResVReg, ResType,
3795 case Intrinsic::spv_subgroup_id:
3796 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupId, ResVReg, ResType,
I);
3797 case Intrinsic::spv_subgroup_local_invocation_id:
3798 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupLocalInvocationId,
3799 ResVReg, ResType,
I);
3800 case Intrinsic::spv_subgroup_max_size:
3801 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupMaxSize, ResVReg, ResType,
3803 case Intrinsic::spv_fdot:
3804 return selectFloatDot(ResVReg, ResType,
I);
3805 case Intrinsic::spv_udot:
3806 case Intrinsic::spv_sdot:
3807 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3809 return selectIntegerDot(ResVReg, ResType,
I,
3810 IID == Intrinsic::spv_sdot);
3811 return selectIntegerDotExpansion(ResVReg, ResType,
I);
3812 case Intrinsic::spv_dot4add_i8packed:
3813 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3815 return selectDot4AddPacked<true>(ResVReg, ResType,
I);
3816 return selectDot4AddPackedExpansion<true>(ResVReg, ResType,
I);
3817 case Intrinsic::spv_dot4add_u8packed:
3818 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3820 return selectDot4AddPacked<false>(ResVReg, ResType,
I);
3821 return selectDot4AddPackedExpansion<false>(ResVReg, ResType,
I);
3822 case Intrinsic::spv_all:
3823 return selectAll(ResVReg, ResType,
I);
3824 case Intrinsic::spv_any:
3825 return selectAny(ResVReg, ResType,
I);
3826 case Intrinsic::spv_cross:
3827 return selectExtInst(ResVReg, ResType,
I, CL::cross, GL::Cross);
3828 case Intrinsic::spv_distance:
3829 return selectExtInst(ResVReg, ResType,
I, CL::distance, GL::Distance);
3830 case Intrinsic::spv_lerp:
3831 return selectExtInst(ResVReg, ResType,
I, CL::mix, GL::FMix);
3832 case Intrinsic::spv_length:
3833 return selectExtInst(ResVReg, ResType,
I, CL::length, GL::Length);
3834 case Intrinsic::spv_degrees:
3835 return selectExtInst(ResVReg, ResType,
I, CL::degrees, GL::Degrees);
3836 case Intrinsic::spv_faceforward:
3837 return selectExtInst(ResVReg, ResType,
I, GL::FaceForward);
3838 case Intrinsic::spv_frac:
3839 return selectExtInst(ResVReg, ResType,
I, CL::fract, GL::Fract);
3840 case Intrinsic::spv_isinf:
3841 return selectOpIsInf(ResVReg, ResType,
I);
3842 case Intrinsic::spv_isnan:
3843 return selectOpIsNan(ResVReg, ResType,
I);
3844 case Intrinsic::spv_normalize:
3845 return selectExtInst(ResVReg, ResType,
I, CL::normalize, GL::Normalize);
3846 case Intrinsic::spv_refract:
3847 return selectExtInst(ResVReg, ResType,
I, GL::Refract);
3848 case Intrinsic::spv_reflect:
3849 return selectExtInst(ResVReg, ResType,
I, GL::Reflect);
3850 case Intrinsic::spv_rsqrt:
3851 return selectExtInst(ResVReg, ResType,
I, CL::rsqrt, GL::InverseSqrt);
3852 case Intrinsic::spv_sign:
3853 return selectSign(ResVReg, ResType,
I);
3854 case Intrinsic::spv_smoothstep:
3855 return selectExtInst(ResVReg, ResType,
I, CL::smoothstep, GL::SmoothStep);
3856 case Intrinsic::spv_firstbituhigh:
3857 return selectFirstBitHigh(ResVReg, ResType,
I,
false);
3858 case Intrinsic::spv_firstbitshigh:
3859 return selectFirstBitHigh(ResVReg, ResType,
I,
true);
3860 case Intrinsic::spv_firstbitlow:
3861 return selectFirstBitLow(ResVReg, ResType,
I);
3862 case Intrinsic::spv_group_memory_barrier_with_group_sync: {
3864 auto MemSemConstant =
3865 buildI32Constant(SPIRV::MemorySemantics::SequentiallyConsistent,
I);
3866 Register MemSemReg = MemSemConstant.first;
3867 Result &= MemSemConstant.second;
3868 auto ScopeConstant = buildI32Constant(SPIRV::Scope::Workgroup,
I);
3869 Register ScopeReg = ScopeConstant.first;
3870 Result &= ScopeConstant.second;
3873 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpControlBarrier))
3879 case Intrinsic::spv_generic_cast_to_ptr_explicit: {
3880 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 1).getReg();
3881 SPIRV::StorageClass::StorageClass ResSC =
3885 "Generic storage class");
3887 TII.get(SPIRV::OpGenericCastToPtrExplicit))
3894 case Intrinsic::spv_lifetime_start:
3895 case Intrinsic::spv_lifetime_end: {
3896 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
3897 : SPIRV::OpLifetimeStop;
3898 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
3899 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
3907 case Intrinsic::spv_saturate:
3908 return selectSaturate(ResVReg, ResType,
I);
3909 case Intrinsic::spv_nclamp:
3910 return selectExtInst(ResVReg, ResType,
I, CL::fclamp, GL::NClamp);
3911 case Intrinsic::spv_uclamp:
3912 return selectExtInst(ResVReg, ResType,
I, CL::u_clamp, GL::UClamp);
3913 case Intrinsic::spv_sclamp:
3914 return selectExtInst(ResVReg, ResType,
I, CL::s_clamp, GL::SClamp);
3915 case Intrinsic::spv_subgroup_prefix_bit_count:
3916 return selectWavePrefixBitCount(ResVReg, ResType,
I);
3917 case Intrinsic::spv_wave_active_countbits:
3918 return selectWaveActiveCountBits(ResVReg, ResType,
I);
3919 case Intrinsic::spv_wave_all:
3920 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAll);
3921 case Intrinsic::spv_wave_any:
3922 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAny);
3923 case Intrinsic::spv_subgroup_ballot:
3924 return selectWaveOpInst(ResVReg, ResType,
I,
3925 SPIRV::OpGroupNonUniformBallot);
3926 case Intrinsic::spv_wave_is_first_lane:
3927 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformElect);
3928 case Intrinsic::spv_wave_reduce_umax:
3929 return selectWaveReduceMax(ResVReg, ResType,
I,
true);
3930 case Intrinsic::spv_wave_reduce_max:
3931 return selectWaveReduceMax(ResVReg, ResType,
I,
false);
3932 case Intrinsic::spv_wave_reduce_umin:
3933 return selectWaveReduceMin(ResVReg, ResType,
I,
true);
3934 case Intrinsic::spv_wave_reduce_min:
3935 return selectWaveReduceMin(ResVReg, ResType,
I,
false);
3936 case Intrinsic::spv_wave_reduce_sum:
3937 return selectWaveReduceSum(ResVReg, ResType,
I);
3938 case Intrinsic::spv_wave_readlane:
3939 return selectWaveOpInst(ResVReg, ResType,
I,
3940 SPIRV::OpGroupNonUniformShuffle);
3941 case Intrinsic::spv_step:
3942 return selectExtInst(ResVReg, ResType,
I, CL::step, GL::Step);
3943 case Intrinsic::spv_radians:
3944 return selectExtInst(ResVReg, ResType,
I, CL::radians, GL::Radians);
3948 case Intrinsic::instrprof_increment:
3949 case Intrinsic::instrprof_increment_step:
3950 case Intrinsic::instrprof_value_profile:
3953 case Intrinsic::spv_value_md:
3955 case Intrinsic::spv_resource_handlefrombinding: {
3956 return selectHandleFromBinding(ResVReg, ResType,
I);
3958 case Intrinsic::spv_resource_counterhandlefrombinding:
3959 return selectCounterHandleFromBinding(ResVReg, ResType,
I);
3960 case Intrinsic::spv_resource_updatecounter:
3961 return selectUpdateCounter(ResVReg, ResType,
I);
3962 case Intrinsic::spv_resource_store_typedbuffer: {
3963 return selectImageWriteIntrinsic(
I);
3965 case Intrinsic::spv_resource_load_typedbuffer: {
3966 return selectReadImageIntrinsic(ResVReg, ResType,
I);
3968 case Intrinsic::spv_resource_sample:
3969 case Intrinsic::spv_resource_sample_clamp: {
3970 return selectSampleIntrinsic(ResVReg, ResType,
I);
3972 case Intrinsic::spv_resource_getpointer: {
3973 return selectResourceGetPointer(ResVReg, ResType,
I);
3975 case Intrinsic::spv_pushconstant_getpointer: {
3976 return selectPushConstantGetPointer(ResVReg, ResType,
I);
3978 case Intrinsic::spv_discard: {
3979 return selectDiscard(ResVReg, ResType,
I);
3981 case Intrinsic::spv_resource_nonuniformindex: {
3982 return selectResourceNonUniformIndex(ResVReg, ResType,
I);
3984 case Intrinsic::spv_unpackhalf2x16: {
3985 return selectExtInst(ResVReg, ResType,
I, GL::UnpackHalf2x16);
3987 case Intrinsic::spv_packhalf2x16: {
3988 return selectExtInst(ResVReg, ResType,
I, GL::PackHalf2x16);
3990 case Intrinsic::spv_ddx:
3991 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdx);
3992 case Intrinsic::spv_ddy:
3993 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdy);
3994 case Intrinsic::spv_ddx_coarse:
3995 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdxCoarse);
3996 case Intrinsic::spv_ddy_coarse:
3997 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdyCoarse);
3998 case Intrinsic::spv_ddx_fine:
3999 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdxFine);
4000 case Intrinsic::spv_ddy_fine:
4001 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdyFine);
4002 case Intrinsic::spv_fwidth:
4003 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpFwidth);
4005 std::string DiagMsg;
4006 raw_string_ostream OS(DiagMsg);
4008 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
4015bool SPIRVInstructionSelector::selectHandleFromBinding(
Register &ResVReg,
4017 MachineInstr &
I)
const {
4020 if (ResType->
getOpcode() == SPIRV::OpTypeImage)
4027bool SPIRVInstructionSelector::selectCounterHandleFromBinding(
4030 assert(Intr.getIntrinsicID() ==
4031 Intrinsic::spv_resource_counterhandlefrombinding);
4034 Register MainHandleReg = Intr.getOperand(2).getReg();
4036 assert(MainHandleDef->getIntrinsicID() ==
4037 Intrinsic::spv_resource_handlefrombinding);
4041 uint32_t ArraySize =
getIConstVal(MainHandleDef->getOperand(4).getReg(),
MRI);
4042 Register IndexReg = MainHandleDef->getOperand(5).getReg();
4043 std::string CounterName =
4048 MachineIRBuilder MIRBuilder(
I);
4049 Register CounterVarReg = buildPointerToResource(
4051 Binding, ArraySize, IndexReg, CounterName, MIRBuilder);
4053 return BuildCOPY(ResVReg, CounterVarReg,
I);
4056bool SPIRVInstructionSelector::selectUpdateCounter(
Register &ResVReg,
4058 MachineInstr &
I)
const {
4060 assert(Intr.getIntrinsicID() == Intrinsic::spv_resource_updatecounter);
4062 Register CounterHandleReg = Intr.getOperand(2).getReg();
4063 Register IncrReg = Intr.getOperand(3).getReg();
4071 assert(CounterVarPointeeType &&
4072 CounterVarPointeeType->
getOpcode() == SPIRV::OpTypeStruct &&
4073 "Counter variable must be a struct");
4075 SPIRV::StorageClass::StorageBuffer &&
4076 "Counter variable must be in the storage buffer storage class");
4078 "Counter variable must have exactly 1 member in the struct");
4082 "Counter variable struct must have a single i32 member");
4086 MachineIRBuilder MIRBuilder(
I);
4088 Type::getInt32Ty(
I.getMF()->getFunction().getContext());
4091 LLVMIntType, MIRBuilder, SPIRV::StorageClass::StorageBuffer);
4093 auto Zero = buildI32Constant(0,
I);
4099 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4100 TII.get(SPIRV::OpAccessChain))
4103 .
addUse(CounterHandleReg)
4111 auto Scope = buildI32Constant(SPIRV::Scope::Device,
I);
4114 auto Semantics = buildI32Constant(SPIRV::MemorySemantics::None,
I);
4115 if (!Semantics.second)
4119 auto Incr = buildI32Constant(
static_cast<uint32_t
>(IncrVal),
I);
4124 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAtomicIAdd))
4135 return BuildCOPY(ResVReg, AtomicRes,
I);
4143 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIAddS))
4150bool SPIRVInstructionSelector::selectReadImageIntrinsic(
4159 Register ImageReg =
I.getOperand(2).getReg();
4161 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
4167 Register IdxReg =
I.getOperand(3).getReg();
4169 MachineInstr &Pos =
I;
4171 return generateImageReadOrFetch(ResVReg, ResType, NewImageReg, IdxReg, Loc,
4175bool SPIRVInstructionSelector::selectSampleIntrinsic(
Register &ResVReg,
4177 MachineInstr &
I)
const {
4178 Register ImageReg =
I.getOperand(2).getReg();
4179 Register SamplerReg =
I.getOperand(3).getReg();
4180 Register CoordinateReg =
I.getOperand(4).getReg();
4181 std::optional<Register> OffsetReg;
4182 std::optional<Register> ClampReg;
4184 if (
I.getNumOperands() > 5)
4185 OffsetReg =
I.getOperand(5).getReg();
4186 if (
I.getNumOperands() > 6)
4187 ClampReg =
I.getOperand(6).getReg();
4192 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
4200 MRI->createVirtualRegister(
MRI->getRegClass(SamplerReg));
4201 if (!loadHandleBeforePosition(
4206 MachineIRBuilder MIRBuilder(
I);
4212 bool Succeed =
BuildMI(*
I.getParent(),
I, Loc,
TII.get(SPIRV::OpSampledImage))
4222 BuildMI(*
I.getParent(),
I, Loc,
TII.get(SPIRV::OpImageSampleImplicitLod))
4228 uint32_t ImageOperands = 0;
4229 if (OffsetReg && !isScalarOrVectorIntConstantZero(*OffsetReg)) {
4230 ImageOperands |= 0x8;
4234 ImageOperands |= 0x80;
4237 if (ImageOperands != 0) {
4238 MIB.
addImm(ImageOperands);
4239 if (ImageOperands & 0x8)
4241 if (ImageOperands & 0x80)
4248bool SPIRVInstructionSelector::generateImageReadOrFetch(
4253 "ImageReg is not an image type.");
4255 bool IsSignedInteger =
4260 bool IsFetch = (SampledOp.getImm() == 1);
4263 if (ResultSize == 4) {
4266 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
4272 if (IsSignedInteger)
4277 SPIRVType *ReadType = widenTypeToVec4(ResType, Pos);
4281 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
4286 if (IsSignedInteger)
4288 bool Succeed = BMI.constrainAllUses(
TII,
TRI, RBI);
4292 if (ResultSize == 1) {
4294 TII.get(SPIRV::OpCompositeExtract))
4301 return extractSubvector(ResVReg, ResType, ReadReg, Pos);
4304bool SPIRVInstructionSelector::selectResourceGetPointer(
4306 Register ResourcePtr =
I.getOperand(2).getReg();
4308 if (RegType->
getOpcode() == SPIRV::OpTypeImage) {
4317 MachineIRBuilder MIRBuilder(
I);
4319 Register IndexReg =
I.getOperand(3).getReg();
4322 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4323 TII.get(SPIRV::OpAccessChain))
4332bool SPIRVInstructionSelector::selectPushConstantGetPointer(
4334 MRI->replaceRegWith(ResVReg,
I.getOperand(2).getReg());
4338bool SPIRVInstructionSelector::selectResourceNonUniformIndex(
4340 Register ObjReg =
I.getOperand(2).getReg();
4341 if (!BuildCOPY(ResVReg, ObjReg,
I))
4351 decorateUsesAsNonUniform(ResVReg);
4355void SPIRVInstructionSelector::decorateUsesAsNonUniform(
4358 while (WorkList.
size() > 0) {
4362 bool IsDecorated =
false;
4363 for (MachineInstr &Use :
MRI->use_instructions(CurrentReg)) {
4364 if (
Use.getOpcode() == SPIRV::OpDecorate &&
4365 Use.getOperand(1).getImm() == SPIRV::Decoration::NonUniformEXT) {
4371 if (
Use.getOperand(0).isReg() &&
Use.getOperand(0).isDef()) {
4373 if (ResultReg == CurrentReg)
4381 SPIRV::Decoration::NonUniformEXT, {});
4386bool SPIRVInstructionSelector::extractSubvector(
4388 MachineInstr &InsertionPoint)
const {
4390 [[maybe_unused]] uint64_t InputSize =
4393 assert(InputSize > 1 &&
"The input must be a vector.");
4394 assert(ResultSize > 1 &&
"The result must be a vector.");
4395 assert(ResultSize < InputSize &&
4396 "Cannot extract more element than there are in the input.");
4399 const TargetRegisterClass *ScalarRegClass = GR.
getRegClass(ScalarType);
4400 for (uint64_t
I = 0;
I < ResultSize;
I++) {
4401 Register ComponentReg =
MRI->createVirtualRegister(ScalarRegClass);
4404 TII.get(SPIRV::OpCompositeExtract))
4415 MachineInstrBuilder MIB =
BuildMI(*InsertionPoint.
getParent(), InsertionPoint,
4417 TII.get(SPIRV::OpCompositeConstruct))
4421 for (
Register ComponentReg : ComponentRegisters)
4422 MIB.
addUse(ComponentReg);
4426bool SPIRVInstructionSelector::selectImageWriteIntrinsic(
4427 MachineInstr &
I)
const {
4434 Register ImageReg =
I.getOperand(1).getReg();
4436 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
4442 Register CoordinateReg =
I.getOperand(2).getReg();
4443 Register DataReg =
I.getOperand(3).getReg();
4446 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4447 TII.get(SPIRV::OpImageWrite))
4454Register SPIRVInstructionSelector::buildPointerToResource(
4455 const SPIRVType *SpirvResType, SPIRV::StorageClass::StorageClass SC,
4456 uint32_t Set, uint32_t
Binding, uint32_t ArraySize,
Register IndexReg,
4457 StringRef Name, MachineIRBuilder MIRBuilder)
const {
4459 if (ArraySize == 1) {
4463 "SpirvResType did not have an explicit layout.");
4468 const Type *VarType = ArrayType::get(
const_cast<Type *
>(ResType), ArraySize);
4472 VarPointerType, Set,
Binding, Name, MIRBuilder);
4487bool SPIRVInstructionSelector::selectFirstBitSet16(
4489 unsigned ExtendOpcode,
unsigned BitSetOpcode)
const {
4491 bool Result = selectOpWithSrcs(ExtReg, ResType,
I, {
I.getOperand(2).getReg()},
4495 selectFirstBitSet32(ResVReg, ResType,
I, ExtReg, BitSetOpcode);
4498bool SPIRVInstructionSelector::selectFirstBitSet32(
4500 Register SrcReg,
unsigned BitSetOpcode)
const {
4501 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4504 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4510bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
4512 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4519 assert(ComponentCount < 5 &&
"Vec 5+ will generate invalid SPIR-V ops");
4521 MachineIRBuilder MIRBuilder(
I);
4529 std::vector<Register> PartialRegs;
4532 unsigned CurrentComponent = 0;
4533 for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
4539 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4540 TII.get(SPIRV::OpVectorShuffle))
4545 .
addImm(CurrentComponent)
4546 .
addImm(CurrentComponent + 1);
4554 if (!selectFirstBitSet64(SubVecBitSetReg, Vec2ResType,
I, BitSetResult,
4555 BitSetOpcode, SwapPrimarySide))
4558 PartialRegs.push_back(SubVecBitSetReg);
4562 if (CurrentComponent != ComponentCount) {
4568 if (!selectOpWithSrcs(FinalElemReg, I64Type,
I, {SrcReg, ConstIntLastIdx},
4569 SPIRV::OpVectorExtractDynamic))
4575 if (!selectFirstBitSet64(FinalElemBitSetReg,
BaseType,
I, FinalElemReg,
4576 BitSetOpcode, SwapPrimarySide))
4579 PartialRegs.push_back(FinalElemBitSetReg);
4584 return selectOpWithSrcs(ResVReg, ResType,
I, std::move(PartialRegs),
4585 SPIRV::OpCompositeConstruct);
4588bool SPIRVInstructionSelector::selectFirstBitSet64(
4590 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4603 if (ComponentCount > 2) {
4604 return selectFirstBitSet64Overflow(ResVReg, ResType,
I, SrcReg,
4605 BitSetOpcode, SwapPrimarySide);
4609 MachineIRBuilder MIRBuilder(
I);
4611 BaseType, 2 * ComponentCount, MIRBuilder,
false);
4615 if (!selectOpWithSrcs(BitcastReg, PostCastType,
I, {SrcReg},
4621 if (!selectFirstBitSet32(FBSReg, PostCastType,
I, BitcastReg, BitSetOpcode))
4628 bool IsScalarRes = ResType->
getOpcode() != SPIRV::OpTypeVector;
4631 if (!selectOpWithSrcs(HighReg, ResType,
I, {FBSReg, ConstIntZero},
4632 SPIRV::OpVectorExtractDynamic))
4634 if (!selectOpWithSrcs(LowReg, ResType,
I, {FBSReg, ConstIntOne},
4635 SPIRV::OpVectorExtractDynamic))
4639 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4640 TII.get(SPIRV::OpVectorShuffle))
4648 for (
unsigned J = 0; J < ComponentCount * 2; J += 2) {
4655 MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4656 TII.get(SPIRV::OpVectorShuffle))
4664 for (
unsigned J = 1; J < ComponentCount * 2; J += 2) {
4685 SelectOp = SPIRV::OpSelectSISCond;
4686 AddOp = SPIRV::OpIAddS;
4694 SelectOp = SPIRV::OpSelectVIVCond;
4695 AddOp = SPIRV::OpIAddV;
4705 if (SwapPrimarySide) {
4706 PrimaryReg = LowReg;
4707 SecondaryReg = HighReg;
4708 PrimaryShiftReg = Reg0;
4709 SecondaryShiftReg = Reg32;
4714 if (!selectOpWithSrcs(BReg, BoolType,
I, {PrimaryReg, NegOneReg},
4720 if (!selectOpWithSrcs(TmpReg, ResType,
I, {
BReg, SecondaryReg, PrimaryReg},
4726 if (!selectOpWithSrcs(ValReg, ResType,
I,
4727 {
BReg, SecondaryShiftReg, PrimaryShiftReg}, SelectOp))
4730 return selectOpWithSrcs(ResVReg, ResType,
I, {ValReg, TmpReg}, AddOp);
4733bool SPIRVInstructionSelector::selectFirstBitHigh(
Register ResVReg,
4736 bool IsSigned)
const {
4738 Register OpReg =
I.getOperand(2).getReg();
4741 unsigned ExtendOpcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
4742 unsigned BitSetOpcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
4746 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4748 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4750 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4754 "spv_firstbituhigh and spv_firstbitshigh only support 16,32,64 bits.");
4758bool SPIRVInstructionSelector::selectFirstBitLow(
Register ResVReg,
4760 MachineInstr &
I)
const {
4762 Register OpReg =
I.getOperand(2).getReg();
4767 unsigned ExtendOpcode = SPIRV::OpUConvert;
4768 unsigned BitSetOpcode = GL::FindILsb;
4772 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4774 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4776 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4783bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
4785 MachineInstr &
I)
const {
4789 bool Res =
BuildMI(BB,
I,
I.getDebugLoc(),
4790 TII.get(SPIRV::OpVariableLengthArrayINTEL))
4793 .
addUse(
I.getOperand(2).getReg())
4796 unsigned Alignment =
I.getOperand(3).getImm();
4802bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
4804 MachineInstr &
I)
const {
4808 bool Res =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
4809 TII.get(SPIRV::OpVariable))
4812 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
4815 unsigned Alignment =
I.getOperand(2).getImm();
4822bool SPIRVInstructionSelector::selectBranch(MachineInstr &
I)
const {
4827 const MachineInstr *PrevI =
I.getPrevNode();
4829 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
4830 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4833 .
addMBB(
I.getOperand(0).getMBB())
4837 .
addMBB(
I.getOperand(0).getMBB())
4841bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &
I)
const {
4852 const MachineInstr *NextI =
I.getNextNode();
4854 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
4860 MachineBasicBlock *NextMBB =
I.getMF()->getBlockNumbered(NextMBBNum);
4861 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4862 .
addUse(
I.getOperand(0).getReg())
4863 .
addMBB(
I.getOperand(1).getMBB())
4868bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
4870 MachineInstr &
I)
const {
4871 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
4874 const unsigned NumOps =
I.getNumOperands();
4875 for (
unsigned i = 1; i <
NumOps; i += 2) {
4876 MIB.
addUse(
I.getOperand(i + 0).getReg());
4877 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
4885bool SPIRVInstructionSelector::selectGlobalValue(
4886 Register ResVReg, MachineInstr &
I,
const MachineInstr *Init)
const {
4888 MachineIRBuilder MIRBuilder(
I);
4889 const GlobalValue *GV =
I.
getOperand(1).getGlobal();
4892 std::string GlobalIdent;
4894 unsigned &
ID = UnnamedGlobalIDs[GV];
4896 ID = UnnamedGlobalIDs.size();
4897 GlobalIdent =
"__unnamed_" + Twine(
ID).str();
4924 GVFun ? SPIRV::StorageClass::CodeSectionINTEL
4931 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4934 MRI->setRegClass(FuncVReg, &SPIRV::pIDRegClass);
4935 MachineInstrBuilder MIB1 =
4936 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
4939 MachineInstrBuilder MIB2 =
4941 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
4945 GR.
add(ConstVal, MIB2);
4951 MachineInstrBuilder MIB3 =
4952 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
4955 GR.
add(ConstVal, MIB3);
4958 assert(NewReg != ResVReg);
4959 return BuildCOPY(ResVReg, NewReg,
I);
4969 const std::optional<SPIRV::LinkageType::LinkageType> LnkType =
4978 GlobalVar->isConstant(), LnkType, MIRBuilder,
true);
4983 if (
GlobalVar->isExternallyInitialized() &&
4984 STI.getTargetTriple().getVendor() ==
Triple::AMD) {
4985 constexpr unsigned ReadWriteINTEL = 3u;
4988 MachineInstrBuilder MIB(*MF, --MIRBuilder.
getInsertPt());
4994bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
4996 MachineInstr &
I)
const {
4998 return selectExtInst(ResVReg, ResType,
I, CL::log10);
5006 MachineIRBuilder MIRBuilder(
I);
5012 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
5015 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
5017 .
add(
I.getOperand(1))
5022 ResType->
getOpcode() == SPIRV::OpTypeFloat);
5025 ResType->
getOpcode() == SPIRV::OpTypeVector
5032 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
5033 ? SPIRV::OpVectorTimesScalar
5043bool SPIRVInstructionSelector::selectModf(
Register ResVReg,
5045 MachineInstr &
I)
const {
5061 MachineIRBuilder MIRBuilder(
I);
5064 ResType, MIRBuilder, SPIRV::StorageClass::Function);
5076 MachineBasicBlock &EntryBB =
I.getMF()->front();
5080 BuildMI(EntryBB, VarPos,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
5083 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function));
5089 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
5092 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::OpenCL_std))
5095 .
add(
I.getOperand(
I.getNumExplicitDefs()))
5099 Register IntegralPartReg =
I.getOperand(1).getReg();
5100 if (IntegralPartReg.
isValid()) {
5102 auto LoadMIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
5111 assert(
false &&
"GLSL::Modf is deprecated.");
5122bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
5123 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
5124 const SPIRVType *ResType, MachineInstr &
I)
const {
5125 MachineIRBuilder MIRBuilder(
I);
5129 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
5141 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
5145 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
5146 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
5152 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
5159 assert(
I.getOperand(2).isReg());
5160 const uint32_t ThreadId =
foldImm(
I.getOperand(2),
MRI);
5164 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
5174bool SPIRVInstructionSelector::loadBuiltinInputID(
5175 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
5176 const SPIRVType *ResType, MachineInstr &
I)
const {
5177 MachineIRBuilder MIRBuilder(
I);
5179 ResType, MIRBuilder, SPIRV::StorageClass::Input);
5194 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
5198 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
5207 MachineInstr &
I)
const {
5208 MachineIRBuilder MIRBuilder(
I);
5209 if (
Type->getOpcode() != SPIRV::OpTypeVector)
5213 if (VectorSize == 4)
5221bool SPIRVInstructionSelector::loadHandleBeforePosition(
5223 MachineInstr &Pos)
const {
5226 Intrinsic::spv_resource_handlefrombinding);
5234 bool IsStructuredBuffer = ResType->
getOpcode() == SPIRV::OpTypePointer;
5235 MachineIRBuilder MIRBuilder(HandleDef);
5237 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::UniformConstant;
5239 if (IsStructuredBuffer) {
5244 Register VarReg = buildPointerToResource(VarType, SC, Set,
Binding, ArraySize,
5245 IndexReg, Name, MIRBuilder);
5249 uint32_t LoadOpcode =
5250 IsStructuredBuffer ? SPIRV::OpCopyObject : SPIRV::OpLoad;
5253 TII.get(LoadOpcode))
5260void SPIRVInstructionSelector::errorIfInstrOutsideShader(
5261 MachineInstr &
I)
const {
5263 std::string DiagMsg;
5264 raw_string_ostream OS(DiagMsg);
5265 I.print(OS,
true,
false,
false,
false);
5266 DiagMsg +=
" is only supported in shaders.\n";
5272InstructionSelector *
5276 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.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
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)
SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
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
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
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)
void addStringImm(const StringRef &Str, MCInst &Inst)
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...