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
115 unsigned BitSetOpcode)
const;
119 unsigned BitSetOpcode)
const;
123 unsigned BitSetOpcode,
bool SwapPrimarySide)
const;
127 unsigned BitSetOpcode,
128 bool SwapPrimarySide)
const;
135 unsigned Opcode)
const;
138 unsigned Opcode)
const;
155 unsigned NegateOpcode = 0)
const;
215 template <
bool Signed>
218 template <
bool Signed>
239 bool IsSigned,
unsigned Opcode)
const;
241 bool IsSigned)
const;
247 bool IsSigned)
const;
286 GL::GLSLExtInst GLInst)
const;
291 GL::GLSLExtInst GLInst)
const;
313 bool selectCounterHandleFromBinding(
Register &ResVReg,
322 bool selectResourceNonUniformIndex(
Register &ResVReg,
334 std::pair<Register, bool>
336 const SPIRVType *ResType =
nullptr)
const;
348 SPIRV::StorageClass::StorageClass SC)
const;
355 SPIRV::StorageClass::StorageClass SC,
367 bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
370 bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
375 void decorateUsesAsNonUniform(
Register &NonUniformReg)
const;
379bool sampledTypeIsSignedInteger(
const llvm::Type *HandleType) {
381 if (
TET->getTargetExtName() ==
"spirv.Image") {
384 assert(
TET->getTargetExtName() ==
"spirv.SignedImage");
385 return TET->getTypeParameter(0)->isIntegerTy();
389#define GET_GLOBALISEL_IMPL
390#include "SPIRVGenGlobalISel.inc"
391#undef GET_GLOBALISEL_IMPL
397 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
400#include
"SPIRVGenGlobalISel.inc"
403#include
"SPIRVGenGlobalISel.inc"
415 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
419void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
420 if (HasVRegsReset == &MF)
425 for (
unsigned I = 0,
E =
MRI.getNumVirtRegs();
I !=
E; ++
I) {
427 LLT RegType =
MRI.getType(
Reg);
435 for (
const auto &
MBB : MF) {
436 for (
const auto &
MI :
MBB) {
439 if (
MI.getOpcode() != SPIRV::ASSIGN_TYPE)
443 LLT DstType =
MRI.getType(DstReg);
445 LLT SrcType =
MRI.getType(SrcReg);
446 if (DstType != SrcType)
447 MRI.setType(DstReg,
MRI.getType(SrcReg));
449 const TargetRegisterClass *DstRC =
MRI.getRegClassOrNull(DstReg);
450 const TargetRegisterClass *SrcRC =
MRI.getRegClassOrNull(SrcReg);
451 if (DstRC != SrcRC && SrcRC)
452 MRI.setRegClass(DstReg, SrcRC);
468 case TargetOpcode::G_CONSTANT:
469 case TargetOpcode::G_FCONSTANT:
471 case TargetOpcode::G_INTRINSIC:
472 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
473 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
475 Intrinsic::spv_const_composite;
476 case TargetOpcode::G_BUILD_VECTOR:
477 case TargetOpcode::G_SPLAT_VECTOR: {
488 case SPIRV::OpConstantTrue:
489 case SPIRV::OpConstantFalse:
490 case SPIRV::OpConstantI:
491 case SPIRV::OpConstantF:
492 case SPIRV::OpConstantComposite:
493 case SPIRV::OpConstantCompositeContinuedINTEL:
494 case SPIRV::OpConstantSampler:
495 case SPIRV::OpConstantNull:
497 case SPIRV::OpConstantFunctionPointerINTEL:
513 for (
const auto &MO :
MI.all_defs()) {
515 if (
Reg.isPhysical() || !
MRI.use_nodbg_empty(
Reg))
518 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE ||
MI.isFakeUse() ||
519 MI.isLifetimeMarker())
523 if (
MI.mayStore() ||
MI.isCall() ||
524 (
MI.mayLoad() &&
MI.hasOrderedMemoryRef()) ||
MI.isPosition() ||
525 MI.isDebugInstr() ||
MI.isTerminator() ||
MI.isJumpTableDebugInfo())
530bool SPIRVInstructionSelector::select(MachineInstr &
I) {
531 resetVRegsType(*
I.getParent()->getParent());
533 assert(
I.getParent() &&
"Instruction should be in a basic block!");
534 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
539 if (Opcode == SPIRV::ASSIGN_TYPE) {
540 Register DstReg =
I.getOperand(0).getReg();
541 Register SrcReg =
I.getOperand(1).getReg();
542 auto *
Def =
MRI->getVRegDef(SrcReg);
544 Def->getOpcode() != TargetOpcode::G_CONSTANT &&
545 Def->getOpcode() != TargetOpcode::G_FCONSTANT) {
547 if (
Def->getOpcode() == TargetOpcode::G_SELECT) {
548 Register SelectDstReg =
Def->getOperand(0).getReg();
552 Def->removeFromParent();
553 MRI->replaceRegWith(DstReg, SelectDstReg);
555 I.removeFromParent();
557 Res = selectImpl(
I, *CoverageInfo);
559 if (!Res &&
Def->getOpcode() != TargetOpcode::G_CONSTANT) {
560 dbgs() <<
"Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
564 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
571 MRI->setRegClass(SrcReg,
MRI->getRegClass(DstReg));
572 MRI->replaceRegWith(SrcReg, DstReg);
574 I.removeFromParent();
576 }
else if (
I.getNumDefs() == 1) {
583 if (DeadMIs.contains(&
I)) {
593 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
594 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
600 bool HasDefs =
I.getNumDefs() > 0;
603 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
604 I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
605 if (spvSelect(ResVReg, ResType,
I)) {
607 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
610 I.removeFromParent();
618 case TargetOpcode::G_CONSTANT:
619 case TargetOpcode::G_FCONSTANT:
621 case TargetOpcode::G_SADDO:
622 case TargetOpcode::G_SSUBO:
629 MachineInstr &
I)
const {
630 const TargetRegisterClass *DstRC =
MRI->getRegClassOrNull(DestReg);
631 const TargetRegisterClass *SrcRC =
MRI->getRegClassOrNull(SrcReg);
632 if (DstRC != SrcRC && SrcRC)
633 MRI->setRegClass(DestReg, SrcRC);
634 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
635 TII.get(TargetOpcode::COPY))
641bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
643 MachineInstr &
I)
const {
644 const unsigned Opcode =
I.getOpcode();
646 return selectImpl(
I, *CoverageInfo);
648 case TargetOpcode::G_CONSTANT:
649 case TargetOpcode::G_FCONSTANT:
650 return selectConst(ResVReg, ResType,
I);
651 case TargetOpcode::G_GLOBAL_VALUE:
652 return selectGlobalValue(ResVReg,
I);
653 case TargetOpcode::G_IMPLICIT_DEF:
654 return selectOpUndef(ResVReg, ResType,
I);
655 case TargetOpcode::G_FREEZE:
656 return selectFreeze(ResVReg, ResType,
I);
658 case TargetOpcode::G_INTRINSIC:
659 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
660 case TargetOpcode::G_INTRINSIC_CONVERGENT:
661 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
662 return selectIntrinsic(ResVReg, ResType,
I);
663 case TargetOpcode::G_BITREVERSE:
664 return selectBitreverse(ResVReg, ResType,
I);
666 case TargetOpcode::G_BUILD_VECTOR:
667 return selectBuildVector(ResVReg, ResType,
I);
668 case TargetOpcode::G_SPLAT_VECTOR:
669 return selectSplatVector(ResVReg, ResType,
I);
671 case TargetOpcode::G_SHUFFLE_VECTOR: {
672 MachineBasicBlock &BB = *
I.getParent();
673 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
676 .
addUse(
I.getOperand(1).getReg())
677 .
addUse(
I.getOperand(2).getReg());
678 for (
auto V :
I.getOperand(3).getShuffleMask())
682 case TargetOpcode::G_MEMMOVE:
683 case TargetOpcode::G_MEMCPY:
684 case TargetOpcode::G_MEMSET:
685 return selectMemOperation(ResVReg,
I);
687 case TargetOpcode::G_ICMP:
688 return selectICmp(ResVReg, ResType,
I);
689 case TargetOpcode::G_FCMP:
690 return selectFCmp(ResVReg, ResType,
I);
692 case TargetOpcode::G_FRAME_INDEX:
693 return selectFrameIndex(ResVReg, ResType,
I);
695 case TargetOpcode::G_LOAD:
696 return selectLoad(ResVReg, ResType,
I);
697 case TargetOpcode::G_STORE:
698 return selectStore(
I);
700 case TargetOpcode::G_BR:
701 return selectBranch(
I);
702 case TargetOpcode::G_BRCOND:
703 return selectBranchCond(
I);
705 case TargetOpcode::G_PHI:
706 return selectPhi(ResVReg, ResType,
I);
708 case TargetOpcode::G_FPTOSI:
709 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
710 case TargetOpcode::G_FPTOUI:
711 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
713 case TargetOpcode::G_FPTOSI_SAT:
714 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
715 case TargetOpcode::G_FPTOUI_SAT:
716 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
718 case TargetOpcode::G_SITOFP:
719 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
720 case TargetOpcode::G_UITOFP:
721 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
723 case TargetOpcode::G_CTPOP:
724 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
725 case TargetOpcode::G_SMIN:
726 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
727 case TargetOpcode::G_UMIN:
728 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
730 case TargetOpcode::G_SMAX:
731 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
732 case TargetOpcode::G_UMAX:
733 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
735 case TargetOpcode::G_SCMP:
736 return selectSUCmp(ResVReg, ResType,
I,
true);
737 case TargetOpcode::G_UCMP:
738 return selectSUCmp(ResVReg, ResType,
I,
false);
739 case TargetOpcode::G_LROUND:
740 case TargetOpcode::G_LLROUND: {
742 MRI->createVirtualRegister(
MRI->getRegClass(ResVReg),
"lround");
743 MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
745 regForLround, *(
I.getParent()->getParent()));
747 I, CL::round, GL::Round);
749 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConvertFToS))
755 case TargetOpcode::G_STRICT_FMA:
756 case TargetOpcode::G_FMA:
757 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
759 case TargetOpcode::G_STRICT_FLDEXP:
760 return selectExtInst(ResVReg, ResType,
I, CL::ldexp);
762 case TargetOpcode::G_FPOW:
763 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
764 case TargetOpcode::G_FPOWI:
765 return selectExtInst(ResVReg, ResType,
I, CL::pown);
767 case TargetOpcode::G_FEXP:
768 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
769 case TargetOpcode::G_FEXP2:
770 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
771 case TargetOpcode::G_FMODF:
772 return selectModf(ResVReg, ResType,
I);
774 case TargetOpcode::G_FLOG:
775 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
776 case TargetOpcode::G_FLOG2:
777 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
778 case TargetOpcode::G_FLOG10:
779 return selectLog10(ResVReg, ResType,
I);
781 case TargetOpcode::G_FABS:
782 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
783 case TargetOpcode::G_ABS:
784 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
786 case TargetOpcode::G_FMINNUM:
787 case TargetOpcode::G_FMINIMUM:
788 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
789 case TargetOpcode::G_FMAXNUM:
790 case TargetOpcode::G_FMAXIMUM:
791 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
793 case TargetOpcode::G_FCOPYSIGN:
794 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
796 case TargetOpcode::G_FCEIL:
797 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
798 case TargetOpcode::G_FFLOOR:
799 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
801 case TargetOpcode::G_FCOS:
802 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
803 case TargetOpcode::G_FSIN:
804 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
805 case TargetOpcode::G_FTAN:
806 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
807 case TargetOpcode::G_FACOS:
808 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
809 case TargetOpcode::G_FASIN:
810 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
811 case TargetOpcode::G_FATAN:
812 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
813 case TargetOpcode::G_FATAN2:
814 return selectExtInst(ResVReg, ResType,
I, CL::atan2, GL::Atan2);
815 case TargetOpcode::G_FCOSH:
816 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
817 case TargetOpcode::G_FSINH:
818 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
819 case TargetOpcode::G_FTANH:
820 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
822 case TargetOpcode::G_STRICT_FSQRT:
823 case TargetOpcode::G_FSQRT:
824 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
826 case TargetOpcode::G_CTTZ:
827 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
828 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
829 case TargetOpcode::G_CTLZ:
830 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
831 return selectExtInst(ResVReg, ResType,
I, CL::clz);
833 case TargetOpcode::G_INTRINSIC_ROUND:
834 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
835 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
836 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
837 case TargetOpcode::G_INTRINSIC_TRUNC:
838 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
839 case TargetOpcode::G_FRINT:
840 case TargetOpcode::G_FNEARBYINT:
841 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
843 case TargetOpcode::G_SMULH:
844 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
845 case TargetOpcode::G_UMULH:
846 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
848 case TargetOpcode::G_SADDSAT:
849 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
850 case TargetOpcode::G_UADDSAT:
851 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
852 case TargetOpcode::G_SSUBSAT:
853 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
854 case TargetOpcode::G_USUBSAT:
855 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
857 case TargetOpcode::G_FFREXP:
858 return selectFrexp(ResVReg, ResType,
I);
860 case TargetOpcode::G_UADDO:
861 return selectOverflowArith(ResVReg, ResType,
I,
862 ResType->
getOpcode() == SPIRV::OpTypeVector
863 ? SPIRV::OpIAddCarryV
864 : SPIRV::OpIAddCarryS);
865 case TargetOpcode::G_USUBO:
866 return selectOverflowArith(ResVReg, ResType,
I,
867 ResType->
getOpcode() == SPIRV::OpTypeVector
868 ? SPIRV::OpISubBorrowV
869 : SPIRV::OpISubBorrowS);
870 case TargetOpcode::G_UMULO:
871 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpUMulExtended);
872 case TargetOpcode::G_SMULO:
873 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpSMulExtended);
875 case TargetOpcode::G_SEXT:
876 return selectExt(ResVReg, ResType,
I,
true);
877 case TargetOpcode::G_ANYEXT:
878 case TargetOpcode::G_ZEXT:
879 return selectExt(ResVReg, ResType,
I,
false);
880 case TargetOpcode::G_TRUNC:
881 return selectTrunc(ResVReg, ResType,
I);
882 case TargetOpcode::G_FPTRUNC:
883 case TargetOpcode::G_FPEXT:
884 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
886 case TargetOpcode::G_PTRTOINT:
887 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
888 case TargetOpcode::G_INTTOPTR:
889 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
890 case TargetOpcode::G_BITCAST:
891 return selectBitcast(ResVReg, ResType,
I);
892 case TargetOpcode::G_ADDRSPACE_CAST:
893 return selectAddrSpaceCast(ResVReg, ResType,
I);
894 case TargetOpcode::G_PTR_ADD: {
896 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
900 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
901 (*II).getOpcode() == TargetOpcode::COPY ||
902 (*II).getOpcode() == SPIRV::OpVariable) &&
905 bool IsGVInit =
false;
907 UseIt =
MRI->use_instr_begin(
I.getOperand(0).getReg()),
908 UseEnd =
MRI->use_instr_end();
909 UseIt != UseEnd; UseIt = std::next(UseIt)) {
910 if ((*UseIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
911 (*UseIt).getOpcode() == SPIRV::OpVariable) {
921 if (GVPointeeType && ResPointeeType && GVPointeeType != ResPointeeType) {
924 Register NewVReg =
MRI->createGenericVirtualRegister(
MRI->getType(GV));
925 MRI->setRegClass(NewVReg,
MRI->getRegClass(GV));
934 "incompatible result and operand types in a bitcast");
936 MachineInstrBuilder MIB =
937 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitcast))
944 ? SPIRV::OpInBoundsAccessChain
945 : SPIRV::OpInBoundsPtrAccessChain))
949 .
addUse(
I.getOperand(2).getReg())
952 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
956 static_cast<uint32_t
>(SPIRV::Opcode::InBoundsPtrAccessChain))
958 .
addUse(
I.getOperand(2).getReg())
966 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
969 .
addImm(
static_cast<uint32_t
>(
970 SPIRV::Opcode::InBoundsPtrAccessChain))
973 .
addUse(
I.getOperand(2).getReg());
977 case TargetOpcode::G_ATOMICRMW_OR:
978 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
979 case TargetOpcode::G_ATOMICRMW_ADD:
980 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
981 case TargetOpcode::G_ATOMICRMW_AND:
982 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
983 case TargetOpcode::G_ATOMICRMW_MAX:
984 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
985 case TargetOpcode::G_ATOMICRMW_MIN:
986 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
987 case TargetOpcode::G_ATOMICRMW_SUB:
988 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
989 case TargetOpcode::G_ATOMICRMW_XOR:
990 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
991 case TargetOpcode::G_ATOMICRMW_UMAX:
992 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
993 case TargetOpcode::G_ATOMICRMW_UMIN:
994 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
995 case TargetOpcode::G_ATOMICRMW_XCHG:
996 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
997 case TargetOpcode::G_ATOMIC_CMPXCHG:
998 return selectAtomicCmpXchg(ResVReg, ResType,
I);
1000 case TargetOpcode::G_ATOMICRMW_FADD:
1001 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
1002 case TargetOpcode::G_ATOMICRMW_FSUB:
1004 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
1006 case TargetOpcode::G_ATOMICRMW_FMIN:
1007 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
1008 case TargetOpcode::G_ATOMICRMW_FMAX:
1009 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
1011 case TargetOpcode::G_FENCE:
1012 return selectFence(
I);
1014 case TargetOpcode::G_STACKSAVE:
1015 return selectStackSave(ResVReg, ResType,
I);
1016 case TargetOpcode::G_STACKRESTORE:
1017 return selectStackRestore(
I);
1019 case TargetOpcode::G_UNMERGE_VALUES:
1025 case TargetOpcode::G_TRAP:
1026 case TargetOpcode::G_UBSANTRAP:
1027 case TargetOpcode::DBG_LABEL:
1029 case TargetOpcode::G_DEBUGTRAP:
1030 return selectDebugTrap(ResVReg, ResType,
I);
1037bool SPIRVInstructionSelector::selectDebugTrap(
Register ResVReg,
1039 MachineInstr &
I)
const {
1040 unsigned Opcode = SPIRV::OpNop;
1042 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
1046bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1049 GL::GLSLExtInst GLInst)
const {
1051 SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) {
1052 std::string DiagMsg;
1053 raw_string_ostream OS(DiagMsg);
1054 I.print(OS,
true,
false,
false,
false);
1055 DiagMsg +=
" is only supported with the GLSL extended instruction set.\n";
1058 return selectExtInst(ResVReg, ResType,
I,
1059 {{SPIRV::InstructionSet::GLSL_std_450, GLInst}});
1062bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1065 CL::OpenCLExtInst CLInst)
const {
1066 return selectExtInst(ResVReg, ResType,
I,
1067 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
1070bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1073 CL::OpenCLExtInst CLInst,
1074 GL::GLSLExtInst GLInst)
const {
1075 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1076 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1077 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
1080bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1085 for (
const auto &Ex : Insts) {
1086 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1087 uint32_t Opcode = Ex.second;
1090 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1093 .
addImm(
static_cast<uint32_t
>(Set))
1096 const unsigned NumOps =
I.getNumOperands();
1099 I.getOperand(Index).getType() ==
1100 MachineOperand::MachineOperandType::MO_IntrinsicID)
1103 MIB.
add(
I.getOperand(Index));
1109bool SPIRVInstructionSelector::selectExtInstForLRound(
1111 CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst)
const {
1112 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1113 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1114 return selectExtInstForLRound(ResVReg, ResType,
I, ExtInsts);
1117bool SPIRVInstructionSelector::selectExtInstForLRound(
1120 for (
const auto &Ex : Insts) {
1121 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1122 uint32_t Opcode = Ex.second;
1125 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1128 .
addImm(
static_cast<uint32_t
>(Set))
1130 const unsigned NumOps =
I.getNumOperands();
1133 I.getOperand(Index).getType() ==
1134 MachineOperand::MachineOperandType::MO_IntrinsicID)
1137 MIB.
add(
I.getOperand(Index));
1145bool SPIRVInstructionSelector::selectFrexp(
Register ResVReg,
1147 MachineInstr &
I)
const {
1148 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CL::frexp},
1149 {SPIRV::InstructionSet::GLSL_std_450, GL::Frexp}};
1150 for (
const auto &Ex : ExtInsts) {
1151 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1152 uint32_t Opcode = Ex.second;
1156 MachineIRBuilder MIRBuilder(
I);
1159 PointeeTy, MIRBuilder, SPIRV::StorageClass::Function);
1164 auto MIB =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
1165 TII.get(SPIRV::OpVariable))
1168 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
1172 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1175 .
addImm(
static_cast<uint32_t
>(Ex.first))
1177 .
add(
I.getOperand(2))
1182 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1183 .
addDef(
I.getOperand(1).getReg())
1192bool SPIRVInstructionSelector::selectOpWithSrcs(
Register ResVReg,
1195 std::vector<Register> Srcs,
1196 unsigned Opcode)
const {
1197 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1206bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
1209 unsigned Opcode)
const {
1211 Register SrcReg =
I.getOperand(1).getReg();
1214 MRI->def_instr_begin(SrcReg);
1215 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
1216 unsigned DefOpCode = DefIt->getOpcode();
1217 if (DefOpCode == SPIRV::ASSIGN_TYPE) {
1220 if (
auto *VRD =
getVRegDef(*
MRI, DefIt->getOperand(1).getReg()))
1221 DefOpCode = VRD->getOpcode();
1223 if (DefOpCode == TargetOpcode::G_GLOBAL_VALUE ||
1224 DefOpCode == TargetOpcode::G_CONSTANT ||
1225 DefOpCode == SPIRV::OpVariable || DefOpCode == SPIRV::OpConstantI) {
1231 uint32_t SpecOpcode = 0;
1233 case SPIRV::OpConvertPtrToU:
1234 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertPtrToU);
1236 case SPIRV::OpConvertUToPtr:
1237 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertUToPtr);
1241 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1242 TII.get(SPIRV::OpSpecConstantOp))
1250 return selectOpWithSrcs(ResVReg, ResType,
I, {
I.getOperand(1).getReg()},
1254bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
1256 MachineInstr &
I)
const {
1257 Register OpReg =
I.getOperand(1).getReg();
1261 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
1269 if (
MemOp->isVolatile())
1270 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1271 if (
MemOp->isNonTemporal())
1272 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1273 if (
MemOp->getAlign().value())
1274 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
1280 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
1281 if (
auto *MD =
MemOp->getAAInfo().Scope) {
1285 static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
1287 if (
auto *MD =
MemOp->getAAInfo().NoAlias) {
1291 static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
1295 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
1297 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
1309 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1311 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1313 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
1317bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
1319 MachineInstr &
I)
const {
1321 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1326 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1327 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1329 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1331 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1333 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1337 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1338 return generateImageReadOrFetch(ResVReg, ResType, NewHandleReg, IdxReg,
1339 I.getDebugLoc(),
I);
1343 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1347 if (!
I.getNumMemOperands()) {
1348 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1350 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1353 MachineIRBuilder MIRBuilder(
I);
1359bool SPIRVInstructionSelector::selectStore(MachineInstr &
I)
const {
1361 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
1362 Register Ptr =
I.getOperand(1 + OpOffset).getReg();
1367 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1368 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1370 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1373 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1377 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1378 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1379 auto BMI =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1380 TII.get(SPIRV::OpImageWrite))
1386 if (sampledTypeIsSignedInteger(LLVMHandleType))
1389 return BMI.constrainAllUses(
TII,
TRI, RBI);
1394 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
1397 if (!
I.getNumMemOperands()) {
1398 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1400 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1403 MachineIRBuilder MIRBuilder(
I);
1409bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
1411 MachineInstr &
I)
const {
1412 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1414 "llvm.stacksave intrinsic: this instruction requires the following "
1415 "SPIR-V extension: SPV_INTEL_variable_length_array",
1418 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
1424bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &
I)
const {
1425 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1427 "llvm.stackrestore intrinsic: this instruction requires the following "
1428 "SPIR-V extension: SPV_INTEL_variable_length_array",
1430 if (!
I.getOperand(0).isReg())
1433 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
1434 .
addUse(
I.getOperand(0).getReg())
1438bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
1439 MachineInstr &
I)
const {
1441 Register SrcReg =
I.getOperand(1).getReg();
1443 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
1444 MachineIRBuilder MIRBuilder(
I);
1445 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1448 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1449 Type *ArrTy = ArrayType::get(ValTy, Num);
1451 ArrTy, MIRBuilder, SPIRV::StorageClass::UniformConstant);
1454 ArrTy, MIRBuilder, SPIRV::AccessQualifier::None,
false);
1461 GlobalVariable *GV =
new GlobalVariable(*CurFunction.
getParent(), LLVMArrTy,
1466 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
1469 .
addImm(SPIRV::StorageClass::UniformConstant)
1478 ValTy,
I, SPIRV::StorageClass::UniformConstant);
1480 selectOpWithSrcs(SrcReg, SourceTy,
I, {VarReg}, SPIRV::OpBitcast);
1482 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
1483 .
addUse(
I.getOperand(0).getReg())
1485 .
addUse(
I.getOperand(2).getReg());
1486 if (
I.getNumMemOperands()) {
1487 MachineIRBuilder MIRBuilder(
I);
1496bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
1500 unsigned NegateOpcode)
const {
1503 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1506 auto ScopeConstant = buildI32Constant(Scope,
I);
1507 Register ScopeReg = ScopeConstant.first;
1508 Result &= ScopeConstant.second;
1510 Register Ptr =
I.getOperand(1).getReg();
1516 auto MemSemConstant = buildI32Constant(MemSem ,
I);
1517 Register MemSemReg = MemSemConstant.first;
1518 Result &= MemSemConstant.second;
1520 Register ValueReg =
I.getOperand(2).getReg();
1521 if (NegateOpcode != 0) {
1524 Result &= selectOpWithSrcs(TmpReg, ResType,
I, {ValueReg}, NegateOpcode);
1529 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(NewOpcode))
1539bool SPIRVInstructionSelector::selectUnmergeValues(MachineInstr &
I)
const {
1540 unsigned ArgI =
I.getNumOperands() - 1;
1542 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
1545 if (!DefType || DefType->
getOpcode() != SPIRV::OpTypeVector)
1547 "cannot select G_UNMERGE_VALUES with a non-vector argument");
1553 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1554 Register ResVReg =
I.getOperand(i).getReg();
1558 ResType = ScalarType;
1564 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1568 .
addImm(
static_cast<int64_t
>(i));
1574bool SPIRVInstructionSelector::selectFence(MachineInstr &
I)
const {
1577 auto MemSemConstant = buildI32Constant(MemSem,
I);
1578 Register MemSemReg = MemSemConstant.first;
1579 bool Result = MemSemConstant.second;
1581 uint32_t
Scope =
static_cast<uint32_t
>(
1583 auto ScopeConstant = buildI32Constant(Scope,
I);
1584 Register ScopeReg = ScopeConstant.first;
1585 Result &= ScopeConstant.second;
1588 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
1594bool SPIRVInstructionSelector::selectOverflowArith(
Register ResVReg,
1597 unsigned Opcode)
const {
1598 Type *ResTy =
nullptr;
1602 "Not enough info to select the arithmetic with overflow instruction");
1605 "with overflow instruction");
1611 MachineIRBuilder MIRBuilder(
I);
1613 ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
1614 assert(
I.getNumDefs() > 1 &&
"Not enought operands");
1620 Register ZeroReg = buildZerosVal(ResType,
I);
1623 MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
1625 if (ResName.
size() > 0)
1630 BuildMI(BB, MIRBuilder.getInsertPt(),
I.getDebugLoc(),
TII.get(Opcode))
1633 for (
unsigned i =
I.getNumDefs(); i <
I.getNumOperands(); ++i)
1634 MIB.
addUse(
I.getOperand(i).getReg());
1639 MRI->setRegClass(HigherVReg, &SPIRV::iIDRegClass);
1640 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1642 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1643 .
addDef(i == 1 ? HigherVReg :
I.getOperand(i).getReg())
1651 .
addDef(
I.getOperand(1).getReg())
1658bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
1660 MachineInstr &
I)
const {
1665 Register Ptr =
I.getOperand(2).getReg();
1668 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1671 auto ScopeConstant = buildI32Constant(Scope,
I);
1672 ScopeReg = ScopeConstant.first;
1673 Result &= ScopeConstant.second;
1675 unsigned ScSem =
static_cast<uint32_t
>(
1678 unsigned MemSemEq =
static_cast<uint32_t
>(
getMemSemantics(AO)) | ScSem;
1679 auto MemSemEqConstant = buildI32Constant(MemSemEq,
I);
1680 MemSemEqReg = MemSemEqConstant.first;
1681 Result &= MemSemEqConstant.second;
1683 unsigned MemSemNeq =
static_cast<uint32_t
>(
getMemSemantics(FO)) | ScSem;
1684 if (MemSemEq == MemSemNeq)
1685 MemSemNeqReg = MemSemEqReg;
1687 auto MemSemNeqConstant = buildI32Constant(MemSemEq,
I);
1688 MemSemNeqReg = MemSemNeqConstant.first;
1689 Result &= MemSemNeqConstant.second;
1692 ScopeReg =
I.getOperand(5).getReg();
1693 MemSemEqReg =
I.getOperand(6).getReg();
1694 MemSemNeqReg =
I.getOperand(7).getReg();
1698 Register Val =
I.getOperand(4).getReg();
1703 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
1730 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpCompositeInsert))
1741 case SPIRV::StorageClass::DeviceOnlyINTEL:
1742 case SPIRV::StorageClass::HostOnlyINTEL:
1751 bool IsGRef =
false;
1752 bool IsAllowedRefs =
1753 llvm::all_of(
MRI->use_instructions(ResVReg), [&IsGRef](
auto const &It) {
1754 unsigned Opcode = It.getOpcode();
1755 if (Opcode == SPIRV::OpConstantComposite ||
1756 Opcode == SPIRV::OpVariable ||
1757 isSpvIntrinsic(It, Intrinsic::spv_init_global))
1758 return IsGRef = true;
1759 return Opcode == SPIRV::OpName;
1761 return IsAllowedRefs && IsGRef;
1764Register SPIRVInstructionSelector::getUcharPtrTypeReg(
1765 MachineInstr &
I, SPIRV::StorageClass::StorageClass SC)
const {
1767 Type::getInt8Ty(
I.getMF()->getFunction().getContext()),
I, SC));
1771SPIRVInstructionSelector::buildSpecConstantOp(MachineInstr &
I,
Register Dest,
1773 uint32_t Opcode)
const {
1774 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1775 TII.get(SPIRV::OpSpecConstantOp))
1783SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &
I,
Register SrcPtr,
1787 Register Tmp =
MRI->createVirtualRegister(&SPIRV::pIDRegClass);
1789 SPIRV::StorageClass::Generic),
1791 MachineFunction *MF =
I.getParent()->getParent();
1793 MachineInstrBuilder MIB = buildSpecConstantOp(
1795 static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric));
1805bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
1807 MachineInstr &
I)
const {
1811 Register SrcPtr =
I.getOperand(1).getReg();
1815 if (SrcPtrTy->
getOpcode() != SPIRV::OpTypePointer ||
1816 ResType->
getOpcode() != SPIRV::OpTypePointer)
1817 return BuildCOPY(ResVReg, SrcPtr,
I);
1827 unsigned SpecOpcode =
1829 ?
static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric)
1832 ? static_cast<uint32_t>(
SPIRV::Opcode::GenericCastToPtr)
1839 return buildSpecConstantOp(
I, ResVReg, SrcPtr,
1840 getUcharPtrTypeReg(
I, DstSC), SpecOpcode)
1841 .constrainAllUses(
TII,
TRI, RBI);
1843 MachineInstrBuilder MIB = buildConstGenericPtr(
I, SrcPtr, SrcPtrTy);
1845 buildSpecConstantOp(
1847 getUcharPtrTypeReg(
I, DstSC),
1848 static_cast<uint32_t
>(SPIRV::Opcode::GenericCastToPtr))
1849 .constrainAllUses(
TII,
TRI, RBI);
1855 return BuildCOPY(ResVReg, SrcPtr,
I);
1857 if ((SrcSC == SPIRV::StorageClass::Function &&
1858 DstSC == SPIRV::StorageClass::Private) ||
1859 (DstSC == SPIRV::StorageClass::Function &&
1860 SrcSC == SPIRV::StorageClass::Private))
1861 return BuildCOPY(ResVReg, SrcPtr,
I);
1865 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1868 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1889 return selectUnOp(ResVReg, ResType,
I,
1890 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
1892 return selectUnOp(ResVReg, ResType,
I,
1893 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
1895 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1897 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1907 return SPIRV::OpFOrdEqual;
1909 return SPIRV::OpFOrdGreaterThanEqual;
1911 return SPIRV::OpFOrdGreaterThan;
1913 return SPIRV::OpFOrdLessThanEqual;
1915 return SPIRV::OpFOrdLessThan;
1917 return SPIRV::OpFOrdNotEqual;
1919 return SPIRV::OpOrdered;
1921 return SPIRV::OpFUnordEqual;
1923 return SPIRV::OpFUnordGreaterThanEqual;
1925 return SPIRV::OpFUnordGreaterThan;
1927 return SPIRV::OpFUnordLessThanEqual;
1929 return SPIRV::OpFUnordLessThan;
1931 return SPIRV::OpFUnordNotEqual;
1933 return SPIRV::OpUnordered;
1943 return SPIRV::OpIEqual;
1945 return SPIRV::OpINotEqual;
1947 return SPIRV::OpSGreaterThanEqual;
1949 return SPIRV::OpSGreaterThan;
1951 return SPIRV::OpSLessThanEqual;
1953 return SPIRV::OpSLessThan;
1955 return SPIRV::OpUGreaterThanEqual;
1957 return SPIRV::OpUGreaterThan;
1959 return SPIRV::OpULessThanEqual;
1961 return SPIRV::OpULessThan;
1970 return SPIRV::OpPtrEqual;
1972 return SPIRV::OpPtrNotEqual;
1983 return SPIRV::OpLogicalEqual;
1985 return SPIRV::OpLogicalNotEqual;
2019bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
2022 unsigned OpAnyOrAll)
const {
2023 assert(
I.getNumOperands() == 3);
2024 assert(
I.getOperand(2).isReg());
2026 Register InputRegister =
I.getOperand(2).getReg();
2033 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
2034 if (IsBoolTy && !IsVectorTy) {
2035 assert(ResVReg ==
I.getOperand(0).getReg());
2036 return BuildCOPY(ResVReg, InputRegister,
I);
2040 unsigned SpirvNotEqualId =
2041 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
2048 IsBoolTy ? InputRegister
2057 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
2077bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
2079 MachineInstr &
I)
const {
2080 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
2083bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
2085 MachineInstr &
I)
const {
2086 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
2090bool SPIRVInstructionSelector::selectFloatDot(
Register ResVReg,
2092 MachineInstr &
I)
const {
2093 assert(
I.getNumOperands() == 4);
2094 assert(
I.getOperand(2).isReg());
2095 assert(
I.getOperand(3).isReg());
2102 "dot product requires a vector of at least 2 components");
2110 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpDot))
2113 .
addUse(
I.getOperand(2).getReg())
2114 .
addUse(
I.getOperand(3).getReg())
2118bool SPIRVInstructionSelector::selectIntegerDot(
Register ResVReg,
2122 assert(
I.getNumOperands() == 4);
2123 assert(
I.getOperand(2).isReg());
2124 assert(
I.getOperand(3).isReg());
2127 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2131 .
addUse(
I.getOperand(2).getReg())
2132 .
addUse(
I.getOperand(3).getReg())
2138bool SPIRVInstructionSelector::selectIntegerDotExpansion(
2140 assert(
I.getNumOperands() == 4);
2141 assert(
I.getOperand(2).isReg());
2142 assert(
I.getOperand(3).isReg());
2146 Register Vec0 =
I.getOperand(2).getReg();
2147 Register Vec1 =
I.getOperand(3).getReg();
2160 "dot product requires a vector of at least 2 components");
2174 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2197bool SPIRVInstructionSelector::selectOpIsInf(
Register ResVReg,
2199 MachineInstr &
I)
const {
2201 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsInf))
2204 .
addUse(
I.getOperand(2).getReg())
2208bool SPIRVInstructionSelector::selectOpIsNan(
Register ResVReg,
2210 MachineInstr &
I)
const {
2212 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsNan))
2215 .
addUse(
I.getOperand(2).getReg())
2219template <
bool Signed>
2220bool SPIRVInstructionSelector::selectDot4AddPacked(
Register ResVReg,
2222 MachineInstr &
I)
const {
2223 assert(
I.getNumOperands() == 5);
2224 assert(
I.getOperand(2).isReg());
2225 assert(
I.getOperand(3).isReg());
2226 assert(
I.getOperand(4).isReg());
2229 Register Acc =
I.getOperand(2).getReg();
2233 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2253template <
bool Signed>
2254bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
2256 assert(
I.getNumOperands() == 5);
2257 assert(
I.getOperand(2).isReg());
2258 assert(
I.getOperand(3).isReg());
2259 assert(
I.getOperand(4).isReg());
2264 Register Acc =
I.getOperand(2).getReg();
2270 Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
2274 for (
unsigned i = 0; i < 4; i++) {
2276 Register AElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2287 Register BElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2307 Register MaskMul =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2319 i < 3 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
2335bool SPIRVInstructionSelector::selectSaturate(
Register ResVReg,
2337 MachineInstr &
I)
const {
2338 assert(
I.getNumOperands() == 3);
2339 assert(
I.getOperand(2).isReg());
2341 Register VZero = buildZerosValF(ResType,
I);
2342 Register VOne = buildOnesValF(ResType,
I);
2344 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2347 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2349 .
addUse(
I.getOperand(2).getReg())
2355bool SPIRVInstructionSelector::selectSign(
Register ResVReg,
2357 MachineInstr &
I)
const {
2358 assert(
I.getNumOperands() == 3);
2359 assert(
I.getOperand(2).isReg());
2361 Register InputRegister =
I.getOperand(2).getReg();
2363 auto &
DL =
I.getDebugLoc();
2373 bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth;
2375 auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign;
2377 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass)
2384 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2389 if (NeedsConversion) {
2390 auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert;
2401bool SPIRVInstructionSelector::selectWaveOpInst(
Register ResVReg,
2404 unsigned Opcode)
const {
2408 auto BMI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2414 for (
unsigned J = 2; J <
I.getNumOperands(); J++) {
2415 BMI.addUse(
I.getOperand(J).getReg());
2421bool SPIRVInstructionSelector::selectWaveActiveCountBits(
2427 bool Result = selectWaveOpInst(BallotReg, BallotType,
I,
2428 SPIRV::OpGroupNonUniformBallot);
2432 TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
2437 .
addImm(SPIRV::GroupOperation::Reduce)
2444bool SPIRVInstructionSelector::selectWaveReduceMax(
Register ResVReg,
2447 bool IsUnsigned)
const {
2448 assert(
I.getNumOperands() == 3);
2449 assert(
I.getOperand(2).isReg());
2451 Register InputRegister =
I.getOperand(2).getReg();
2460 auto IntegerOpcodeType =
2461 IsUnsigned ? SPIRV::OpGroupNonUniformUMax : SPIRV::OpGroupNonUniformSMax;
2462 auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMax : IntegerOpcodeType;
2463 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2468 .
addImm(SPIRV::GroupOperation::Reduce)
2469 .
addUse(
I.getOperand(2).getReg())
2473bool SPIRVInstructionSelector::selectWaveReduceMin(
Register ResVReg,
2476 bool IsUnsigned)
const {
2477 assert(
I.getNumOperands() == 3);
2478 assert(
I.getOperand(2).isReg());
2480 Register InputRegister =
I.getOperand(2).getReg();
2489 auto IntegerOpcodeType =
2490 IsUnsigned ? SPIRV::OpGroupNonUniformUMin : SPIRV::OpGroupNonUniformSMin;
2491 auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMin : IntegerOpcodeType;
2492 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2497 .
addImm(SPIRV::GroupOperation::Reduce)
2498 .
addUse(
I.getOperand(2).getReg())
2502bool SPIRVInstructionSelector::selectWaveReduceSum(
Register ResVReg,
2504 MachineInstr &
I)
const {
2505 assert(
I.getNumOperands() == 3);
2506 assert(
I.getOperand(2).isReg());
2508 Register InputRegister =
I.getOperand(2).getReg();
2518 IsFloatTy ? SPIRV::OpGroupNonUniformFAdd : SPIRV::OpGroupNonUniformIAdd;
2519 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2524 .
addImm(SPIRV::GroupOperation::Reduce)
2525 .
addUse(
I.getOperand(2).getReg());
2528bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
2530 MachineInstr &
I)
const {
2532 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
2535 .
addUse(
I.getOperand(1).getReg())
2539bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
2541 MachineInstr &
I)
const {
2547 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
2549 Register OpReg =
I.getOperand(1).getReg();
2550 if (MachineInstr *Def =
MRI->getVRegDef(OpReg)) {
2551 if (
Def->getOpcode() == TargetOpcode::COPY)
2552 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
2554 switch (
Def->getOpcode()) {
2555 case SPIRV::ASSIGN_TYPE:
2556 if (MachineInstr *AssignToDef =
2557 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
2558 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2559 Reg =
Def->getOperand(2).getReg();
2562 case SPIRV::OpUndef:
2563 Reg =
Def->getOperand(1).getReg();
2566 unsigned DestOpCode;
2568 DestOpCode = SPIRV::OpConstantNull;
2570 DestOpCode = TargetOpcode::COPY;
2573 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
2574 .
addDef(
I.getOperand(0).getReg())
2581bool SPIRVInstructionSelector::selectBuildVector(
Register ResVReg,
2583 MachineInstr &
I)
const {
2585 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2587 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2591 if (
I.getNumExplicitOperands() -
I.getNumExplicitDefs() !=
N)
2596 for (
unsigned i =
I.getNumExplicitDefs();
2597 i <
I.getNumExplicitOperands() && IsConst; ++i)
2601 if (!IsConst &&
N < 2)
2603 "There must be at least two constituent operands in a vector");
2606 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2607 TII.get(IsConst ? SPIRV::OpConstantComposite
2608 : SPIRV::OpCompositeConstruct))
2611 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
2612 MIB.
addUse(
I.getOperand(i).getReg());
2616bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
2618 MachineInstr &
I)
const {
2620 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2622 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2628 if (!
I.getOperand(
OpIdx).isReg())
2635 if (!IsConst &&
N < 2)
2637 "There must be at least two constituent operands in a vector");
2640 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2641 TII.get(IsConst ? SPIRV::OpConstantComposite
2642 : SPIRV::OpCompositeConstruct))
2645 for (
unsigned i = 0; i <
N; ++i)
2650bool SPIRVInstructionSelector::selectDiscard(
Register ResVReg,
2652 MachineInstr &
I)
const {
2657 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
2659 Opcode = SPIRV::OpDemoteToHelperInvocation;
2661 Opcode = SPIRV::OpKill;
2663 if (MachineInstr *NextI =
I.getNextNode()) {
2665 NextI->removeFromParent();
2670 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2674bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
2677 MachineInstr &
I)
const {
2678 Register Cmp0 =
I.getOperand(2).getReg();
2679 Register Cmp1 =
I.getOperand(3).getReg();
2682 "CMP operands should have the same type");
2683 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
2692bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
2694 MachineInstr &
I)
const {
2695 auto Pred =
I.getOperand(1).getPredicate();
2698 Register CmpOperand =
I.getOperand(2).getReg();
2705 return selectCmp(ResVReg, ResType, CmpOpc,
I);
2708std::pair<Register, bool>
2709SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &
I,
2715 auto ConstInt = ConstantInt::get(LLVMTy, Val);
2723 ?
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2726 :
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
2729 .
addImm(APInt(32, Val).getZExtValue());
2731 GR.
add(ConstInt,
MI);
2736bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
2738 MachineInstr &
I)
const {
2740 return selectCmp(ResVReg, ResType, CmpOp,
I);
2744 MachineInstr &
I)
const {
2747 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2753 MachineInstr &
I)
const {
2757 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2763 MachineInstr &
I)
const {
2767 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2774 MachineInstr &
I)
const {
2778 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2783bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
2785 MachineInstr &
I)
const {
2786 Register SelectFirstArg =
I.getOperand(2).getReg();
2787 Register SelectSecondArg =
I.getOperand(3).getReg();
2796 SPIRV::OpTypeVector;
2803 Opcode = IsScalarBool ? SPIRV::OpSelectVFSCond : SPIRV::OpSelectVFVCond;
2804 }
else if (IsPtrTy) {
2805 Opcode = IsScalarBool ? SPIRV::OpSelectVPSCond : SPIRV::OpSelectVPVCond;
2807 Opcode = IsScalarBool ? SPIRV::OpSelectVISCond : SPIRV::OpSelectVIVCond;
2811 Opcode = IsScalarBool ? SPIRV::OpSelectSFSCond : SPIRV::OpSelectVFVCond;
2812 }
else if (IsPtrTy) {
2813 Opcode = IsScalarBool ? SPIRV::OpSelectSPSCond : SPIRV::OpSelectVPVCond;
2815 Opcode = IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
2818 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
2821 .
addUse(
I.getOperand(1).getReg())
2827bool SPIRVInstructionSelector::selectSelectDefaultArgs(
Register ResVReg,
2830 bool IsSigned)
const {
2832 Register ZeroReg = buildZerosVal(ResType,
I);
2833 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
2837 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
2838 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
2841 .
addUse(
I.getOperand(1).getReg())
2847bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
2849 MachineInstr &
I,
bool IsSigned,
2850 unsigned Opcode)
const {
2851 Register SrcReg =
I.getOperand(1).getReg();
2857 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
2862 selectSelectDefaultArgs(SrcReg, TmpType,
I,
false);
2864 return selectOpWithSrcs(ResVReg, ResType,
I, {SrcReg}, Opcode);
2867bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
2869 MachineInstr &
I,
bool IsSigned)
const {
2870 Register SrcReg =
I.getOperand(1).getReg();
2872 return selectSelectDefaultArgs(ResVReg, ResType,
I, IsSigned);
2875 if (SrcType == ResType)
2876 return BuildCOPY(ResVReg, SrcReg,
I);
2878 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
2879 return selectUnOp(ResVReg, ResType,
I, Opcode);
2882bool SPIRVInstructionSelector::selectSUCmp(
Register ResVReg,
2885 bool IsSigned)
const {
2886 MachineIRBuilder MIRBuilder(
I);
2887 MachineRegisterInfo *
MRI = MIRBuilder.getMRI();
2902 TII.get(IsSigned ? SPIRV::OpSLessThanEqual
2903 : SPIRV::OpULessThanEqual))
2906 .
addUse(
I.getOperand(1).getReg())
2907 .
addUse(
I.getOperand(2).getReg())
2913 TII.get(IsSigned ? SPIRV::OpSLessThan : SPIRV::OpULessThan))
2916 .
addUse(
I.getOperand(1).getReg())
2917 .
addUse(
I.getOperand(2).getReg())
2925 unsigned SelectOpcode =
2926 N > 1 ? SPIRV::OpSelectVIVCond : SPIRV::OpSelectSISCond;
2931 .
addUse(buildOnesVal(
true, ResType,
I))
2932 .
addUse(buildZerosVal(ResType,
I))
2939 .
addUse(buildOnesVal(
false, ResType,
I))
2943bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
2950 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
2951 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
2953 Register One = buildOnesVal(
false, IntTy,
I);
2969bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
2971 MachineInstr &
I)
const {
2972 Register IntReg =
I.getOperand(1).getReg();
2975 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
2976 if (ArgType == ResType)
2977 return BuildCOPY(ResVReg, IntReg,
I);
2979 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
2980 return selectUnOp(ResVReg, ResType,
I, Opcode);
2983bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
2985 MachineInstr &
I)
const {
2986 unsigned Opcode =
I.getOpcode();
2987 unsigned TpOpcode = ResType->
getOpcode();
2989 if (TpOpcode == SPIRV::OpTypePointer || TpOpcode == SPIRV::OpTypeEvent) {
2990 assert(Opcode == TargetOpcode::G_CONSTANT &&
2991 I.getOperand(1).getCImm()->isZero());
2992 MachineBasicBlock &DepMBB =
I.getMF()->front();
2995 }
else if (Opcode == TargetOpcode::G_FCONSTANT) {
3002 return Reg == ResVReg ?
true : BuildCOPY(ResVReg,
Reg,
I);
3005bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
3007 MachineInstr &
I)
const {
3008 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3014bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
3016 MachineInstr &
I)
const {
3018 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
3022 .
addUse(
I.getOperand(3).getReg())
3024 .
addUse(
I.getOperand(2).getReg());
3025 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
3030bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
3032 MachineInstr &
I)
const {
3034 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
3037 .
addUse(
I.getOperand(2).getReg());
3038 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
3043bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
3045 MachineInstr &
I)
const {
3047 return selectInsertVal(ResVReg, ResType,
I);
3049 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
3052 .
addUse(
I.getOperand(2).getReg())
3053 .
addUse(
I.getOperand(3).getReg())
3054 .
addUse(
I.getOperand(4).getReg())
3058bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
3060 MachineInstr &
I)
const {
3062 return selectExtractVal(ResVReg, ResType,
I);
3064 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
3067 .
addUse(
I.getOperand(2).getReg())
3068 .
addUse(
I.getOperand(3).getReg())
3072bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
3074 MachineInstr &
I)
const {
3075 const bool IsGEPInBounds =
I.getOperand(2).getImm();
3081 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
3082 : SPIRV::OpAccessChain)
3083 : (IsGEPInBounds ?
SPIRV::OpInBoundsPtrAccessChain
3084 :
SPIRV::OpPtrAccessChain);
3086 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3090 .
addUse(
I.getOperand(3).getReg());
3092 const unsigned StartingIndex =
3093 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
3096 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
3097 Res.addUse(
I.getOperand(i).getReg());
3098 return Res.constrainAllUses(
TII,
TRI, RBI);
3102bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
3105 unsigned Lim =
I.getNumExplicitOperands();
3106 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
3107 Register OpReg =
I.getOperand(i).getReg();
3108 MachineInstr *OpDefine =
MRI->getVRegDef(OpReg);
3110 SmallPtrSet<SPIRVType *, 4> Visited;
3111 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
3112 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
3113 OpDefine->
getOpcode() == TargetOpcode::G_INTTOPTR ||
3120 MachineFunction *MF =
I.getMF();
3132 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3133 TII.get(SPIRV::OpSpecConstantOp))
3136 .
addImm(
static_cast<uint32_t
>(SPIRV::Opcode::Bitcast))
3138 GR.
add(OpDefine, MIB);
3146bool SPIRVInstructionSelector::selectDerivativeInst(
3148 const unsigned DPdOpCode)
const {
3151 errorIfInstrOutsideShader(
I);
3156 Register SrcReg =
I.getOperand(2).getReg();
3161 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DPdOpCode))
3164 .
addUse(
I.getOperand(2).getReg());
3166 MachineIRBuilder MIRBuilder(
I);
3169 if (componentCount != 1)
3173 const TargetRegisterClass *RegClass = GR.
getRegClass(SrcType);
3174 Register ConvertToVReg =
MRI->createVirtualRegister(RegClass);
3175 Register DpdOpVReg =
MRI->createVirtualRegister(RegClass);
3178 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3189 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpFConvert))
3197bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
3199 MachineInstr &
I)
const {
3203 case Intrinsic::spv_load:
3204 return selectLoad(ResVReg, ResType,
I);
3205 case Intrinsic::spv_store:
3206 return selectStore(
I);
3207 case Intrinsic::spv_extractv:
3208 return selectExtractVal(ResVReg, ResType,
I);
3209 case Intrinsic::spv_insertv:
3210 return selectInsertVal(ResVReg, ResType,
I);
3211 case Intrinsic::spv_extractelt:
3212 return selectExtractElt(ResVReg, ResType,
I);
3213 case Intrinsic::spv_insertelt:
3214 return selectInsertElt(ResVReg, ResType,
I);
3215 case Intrinsic::spv_gep:
3216 return selectGEP(ResVReg, ResType,
I);
3217 case Intrinsic::spv_bitcast: {
3218 Register OpReg =
I.getOperand(2).getReg();
3223 return selectOpWithSrcs(ResVReg, ResType,
I, {OpReg}, SPIRV::OpBitcast);
3225 case Intrinsic::spv_unref_global:
3226 case Intrinsic::spv_init_global: {
3227 MachineInstr *
MI =
MRI->getVRegDef(
I.getOperand(1).getReg());
3228 MachineInstr *Init =
I.getNumExplicitOperands() > 2
3229 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
3232 Register GVarVReg =
MI->getOperand(0).getReg();
3233 bool Res = selectGlobalValue(GVarVReg, *
MI, Init);
3237 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
3239 MI->removeFromParent();
3243 case Intrinsic::spv_undef: {
3244 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3249 case Intrinsic::spv_const_composite: {
3251 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
3257 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
3259 MachineIRBuilder MIR(
I);
3261 MIR, SPIRV::OpConstantComposite, 3,
3262 SPIRV::OpConstantCompositeContinuedINTEL, CompositeArgs, ResVReg,
3264 for (
auto *Instr : Instructions) {
3265 Instr->setDebugLoc(
I.getDebugLoc());
3271 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
3277 case Intrinsic::spv_assign_name: {
3278 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
3279 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
3280 for (
unsigned i =
I.getNumExplicitDefs() + 2;
3281 i <
I.getNumExplicitOperands(); ++i) {
3282 MIB.
addImm(
I.getOperand(i).getImm());
3286 case Intrinsic::spv_switch: {
3287 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
3288 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3289 if (
I.getOperand(i).isReg())
3290 MIB.
addReg(
I.getOperand(i).getReg());
3291 else if (
I.getOperand(i).isCImm())
3292 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
3293 else if (
I.getOperand(i).isMBB())
3294 MIB.
addMBB(
I.getOperand(i).getMBB());
3300 case Intrinsic::spv_loop_merge: {
3301 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoopMerge));
3302 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3303 if (
I.getOperand(i).isMBB())
3304 MIB.
addMBB(
I.getOperand(i).getMBB());
3310 case Intrinsic::spv_selection_merge: {
3312 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSelectionMerge));
3313 assert(
I.getOperand(1).isMBB() &&
3314 "operand 1 to spv_selection_merge must be a basic block");
3315 MIB.
addMBB(
I.getOperand(1).getMBB());
3316 MIB.
addImm(getSelectionOperandForImm(
I.getOperand(2).getImm()));
3319 case Intrinsic::spv_cmpxchg:
3320 return selectAtomicCmpXchg(ResVReg, ResType,
I);
3321 case Intrinsic::spv_unreachable:
3322 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable))
3324 case Intrinsic::spv_alloca:
3325 return selectFrameIndex(ResVReg, ResType,
I);
3326 case Intrinsic::spv_alloca_array:
3327 return selectAllocaArray(ResVReg, ResType,
I);
3328 case Intrinsic::spv_assume:
3330 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
3331 .
addUse(
I.getOperand(1).getReg())
3334 case Intrinsic::spv_expect:
3336 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
3339 .
addUse(
I.getOperand(2).getReg())
3340 .
addUse(
I.getOperand(3).getReg())
3343 case Intrinsic::arithmetic_fence:
3346 TII.get(SPIRV::OpArithmeticFenceEXT))
3349 .
addUse(
I.getOperand(2).getReg())
3352 return BuildCOPY(ResVReg,
I.getOperand(2).getReg(),
I);
3354 case Intrinsic::spv_thread_id:
3360 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalInvocationId, ResVReg,
3362 case Intrinsic::spv_thread_id_in_group:
3368 return loadVec3BuiltinInputID(SPIRV::BuiltIn::LocalInvocationId, ResVReg,
3370 case Intrinsic::spv_group_id:
3376 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
3378 case Intrinsic::spv_flattened_thread_id_in_group:
3385 return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
3387 case Intrinsic::spv_workgroup_size:
3388 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupSize, ResVReg,
3390 case Intrinsic::spv_global_size:
3391 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalSize, ResVReg, ResType,
3393 case Intrinsic::spv_global_offset:
3394 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalOffset, ResVReg,
3396 case Intrinsic::spv_num_workgroups:
3397 return loadVec3BuiltinInputID(SPIRV::BuiltIn::NumWorkgroups, ResVReg,
3399 case Intrinsic::spv_subgroup_size:
3400 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupSize, ResVReg, ResType,
3402 case Intrinsic::spv_num_subgroups:
3403 return loadBuiltinInputID(SPIRV::BuiltIn::NumSubgroups, ResVReg, ResType,
3405 case Intrinsic::spv_subgroup_id:
3406 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupId, ResVReg, ResType,
I);
3407 case Intrinsic::spv_subgroup_local_invocation_id:
3408 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupLocalInvocationId,
3409 ResVReg, ResType,
I);
3410 case Intrinsic::spv_subgroup_max_size:
3411 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupMaxSize, ResVReg, ResType,
3413 case Intrinsic::spv_fdot:
3414 return selectFloatDot(ResVReg, ResType,
I);
3415 case Intrinsic::spv_udot:
3416 case Intrinsic::spv_sdot:
3417 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3419 return selectIntegerDot(ResVReg, ResType,
I,
3420 IID == Intrinsic::spv_sdot);
3421 return selectIntegerDotExpansion(ResVReg, ResType,
I);
3422 case Intrinsic::spv_dot4add_i8packed:
3423 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3425 return selectDot4AddPacked<true>(ResVReg, ResType,
I);
3426 return selectDot4AddPackedExpansion<true>(ResVReg, ResType,
I);
3427 case Intrinsic::spv_dot4add_u8packed:
3428 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3430 return selectDot4AddPacked<false>(ResVReg, ResType,
I);
3431 return selectDot4AddPackedExpansion<false>(ResVReg, ResType,
I);
3432 case Intrinsic::spv_all:
3433 return selectAll(ResVReg, ResType,
I);
3434 case Intrinsic::spv_any:
3435 return selectAny(ResVReg, ResType,
I);
3436 case Intrinsic::spv_cross:
3437 return selectExtInst(ResVReg, ResType,
I, CL::cross, GL::Cross);
3438 case Intrinsic::spv_distance:
3439 return selectExtInst(ResVReg, ResType,
I, CL::distance, GL::Distance);
3440 case Intrinsic::spv_lerp:
3441 return selectExtInst(ResVReg, ResType,
I, CL::mix, GL::FMix);
3442 case Intrinsic::spv_length:
3443 return selectExtInst(ResVReg, ResType,
I, CL::length, GL::Length);
3444 case Intrinsic::spv_degrees:
3445 return selectExtInst(ResVReg, ResType,
I, CL::degrees, GL::Degrees);
3446 case Intrinsic::spv_faceforward:
3447 return selectExtInst(ResVReg, ResType,
I, GL::FaceForward);
3448 case Intrinsic::spv_frac:
3449 return selectExtInst(ResVReg, ResType,
I, CL::fract, GL::Fract);
3450 case Intrinsic::spv_isinf:
3451 return selectOpIsInf(ResVReg, ResType,
I);
3452 case Intrinsic::spv_isnan:
3453 return selectOpIsNan(ResVReg, ResType,
I);
3454 case Intrinsic::spv_normalize:
3455 return selectExtInst(ResVReg, ResType,
I, CL::normalize, GL::Normalize);
3456 case Intrinsic::spv_refract:
3457 return selectExtInst(ResVReg, ResType,
I, GL::Refract);
3458 case Intrinsic::spv_reflect:
3459 return selectExtInst(ResVReg, ResType,
I, GL::Reflect);
3460 case Intrinsic::spv_rsqrt:
3461 return selectExtInst(ResVReg, ResType,
I, CL::rsqrt, GL::InverseSqrt);
3462 case Intrinsic::spv_sign:
3463 return selectSign(ResVReg, ResType,
I);
3464 case Intrinsic::spv_smoothstep:
3465 return selectExtInst(ResVReg, ResType,
I, CL::smoothstep, GL::SmoothStep);
3466 case Intrinsic::spv_firstbituhigh:
3467 return selectFirstBitHigh(ResVReg, ResType,
I,
false);
3468 case Intrinsic::spv_firstbitshigh:
3469 return selectFirstBitHigh(ResVReg, ResType,
I,
true);
3470 case Intrinsic::spv_firstbitlow:
3471 return selectFirstBitLow(ResVReg, ResType,
I);
3472 case Intrinsic::spv_group_memory_barrier_with_group_sync: {
3474 auto MemSemConstant =
3475 buildI32Constant(SPIRV::MemorySemantics::SequentiallyConsistent,
I);
3476 Register MemSemReg = MemSemConstant.first;
3477 Result &= MemSemConstant.second;
3478 auto ScopeConstant = buildI32Constant(SPIRV::Scope::Workgroup,
I);
3479 Register ScopeReg = ScopeConstant.first;
3480 Result &= ScopeConstant.second;
3483 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpControlBarrier))
3489 case Intrinsic::spv_generic_cast_to_ptr_explicit: {
3490 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 1).getReg();
3491 SPIRV::StorageClass::StorageClass ResSC =
3495 "Generic storage class");
3497 TII.get(SPIRV::OpGenericCastToPtrExplicit))
3504 case Intrinsic::spv_lifetime_start:
3505 case Intrinsic::spv_lifetime_end: {
3506 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
3507 : SPIRV::OpLifetimeStop;
3508 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
3509 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
3517 case Intrinsic::spv_saturate:
3518 return selectSaturate(ResVReg, ResType,
I);
3519 case Intrinsic::spv_nclamp:
3520 return selectExtInst(ResVReg, ResType,
I, CL::fclamp, GL::NClamp);
3521 case Intrinsic::spv_uclamp:
3522 return selectExtInst(ResVReg, ResType,
I, CL::u_clamp, GL::UClamp);
3523 case Intrinsic::spv_sclamp:
3524 return selectExtInst(ResVReg, ResType,
I, CL::s_clamp, GL::SClamp);
3525 case Intrinsic::spv_wave_active_countbits:
3526 return selectWaveActiveCountBits(ResVReg, ResType,
I);
3527 case Intrinsic::spv_wave_all:
3528 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAll);
3529 case Intrinsic::spv_wave_any:
3530 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAny);
3531 case Intrinsic::spv_wave_is_first_lane:
3532 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformElect);
3533 case Intrinsic::spv_wave_reduce_umax:
3534 return selectWaveReduceMax(ResVReg, ResType,
I,
true);
3535 case Intrinsic::spv_wave_reduce_max:
3536 return selectWaveReduceMax(ResVReg, ResType,
I,
false);
3537 case Intrinsic::spv_wave_reduce_umin:
3538 return selectWaveReduceMin(ResVReg, ResType,
I,
true);
3539 case Intrinsic::spv_wave_reduce_min:
3540 return selectWaveReduceMin(ResVReg, ResType,
I,
false);
3541 case Intrinsic::spv_wave_reduce_sum:
3542 return selectWaveReduceSum(ResVReg, ResType,
I);
3543 case Intrinsic::spv_wave_readlane:
3544 return selectWaveOpInst(ResVReg, ResType,
I,
3545 SPIRV::OpGroupNonUniformShuffle);
3546 case Intrinsic::spv_step:
3547 return selectExtInst(ResVReg, ResType,
I, CL::step, GL::Step);
3548 case Intrinsic::spv_radians:
3549 return selectExtInst(ResVReg, ResType,
I, CL::radians, GL::Radians);
3553 case Intrinsic::instrprof_increment:
3554 case Intrinsic::instrprof_increment_step:
3555 case Intrinsic::instrprof_value_profile:
3558 case Intrinsic::spv_value_md:
3560 case Intrinsic::spv_resource_handlefrombinding: {
3561 return selectHandleFromBinding(ResVReg, ResType,
I);
3563 case Intrinsic::spv_resource_counterhandlefrombinding:
3564 return selectCounterHandleFromBinding(ResVReg, ResType,
I);
3565 case Intrinsic::spv_resource_updatecounter:
3566 return selectUpdateCounter(ResVReg, ResType,
I);
3567 case Intrinsic::spv_resource_store_typedbuffer: {
3568 return selectImageWriteIntrinsic(
I);
3570 case Intrinsic::spv_resource_load_typedbuffer: {
3571 return selectReadImageIntrinsic(ResVReg, ResType,
I);
3573 case Intrinsic::spv_resource_getpointer: {
3574 return selectResourceGetPointer(ResVReg, ResType,
I);
3576 case Intrinsic::spv_discard: {
3577 return selectDiscard(ResVReg, ResType,
I);
3579 case Intrinsic::spv_resource_nonuniformindex: {
3580 return selectResourceNonUniformIndex(ResVReg, ResType,
I);
3582 case Intrinsic::spv_unpackhalf2x16: {
3583 return selectExtInst(ResVReg, ResType,
I, GL::UnpackHalf2x16);
3585 case Intrinsic::spv_ddx_coarse:
3586 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdxCoarse);
3587 case Intrinsic::spv_ddy_coarse:
3588 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpDPdyCoarse);
3589 case Intrinsic::spv_fwidth:
3590 return selectDerivativeInst(ResVReg, ResType,
I, SPIRV::OpFwidth);
3592 std::string DiagMsg;
3593 raw_string_ostream OS(DiagMsg);
3595 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
3602bool SPIRVInstructionSelector::selectHandleFromBinding(
Register &ResVReg,
3604 MachineInstr &
I)
const {
3607 if (ResType->
getOpcode() == SPIRV::OpTypeImage)
3614bool SPIRVInstructionSelector::selectCounterHandleFromBinding(
3617 assert(Intr.getIntrinsicID() ==
3618 Intrinsic::spv_resource_counterhandlefrombinding);
3621 Register MainHandleReg = Intr.getOperand(2).getReg();
3623 assert(MainHandleDef->getIntrinsicID() ==
3624 Intrinsic::spv_resource_handlefrombinding);
3628 uint32_t ArraySize =
getIConstVal(MainHandleDef->getOperand(4).getReg(),
MRI);
3629 Register IndexReg = MainHandleDef->getOperand(5).getReg();
3630 std::string CounterName =
3635 MachineIRBuilder MIRBuilder(
I);
3636 Register CounterVarReg = buildPointerToResource(
3638 Binding, ArraySize, IndexReg, CounterName, MIRBuilder);
3640 return BuildCOPY(ResVReg, CounterVarReg,
I);
3643bool SPIRVInstructionSelector::selectUpdateCounter(
Register &ResVReg,
3645 MachineInstr &
I)
const {
3647 assert(Intr.getIntrinsicID() == Intrinsic::spv_resource_updatecounter);
3649 Register CounterHandleReg = Intr.getOperand(2).getReg();
3650 Register IncrReg = Intr.getOperand(3).getReg();
3658 assert(CounterVarPointeeType &&
3659 CounterVarPointeeType->
getOpcode() == SPIRV::OpTypeStruct &&
3660 "Counter variable must be a struct");
3662 SPIRV::StorageClass::StorageBuffer &&
3663 "Counter variable must be in the storage buffer storage class");
3665 "Counter variable must have exactly 1 member in the struct");
3669 "Counter variable struct must have a single i32 member");
3673 MachineIRBuilder MIRBuilder(
I);
3675 Type::getInt32Ty(
I.getMF()->getFunction().getContext());
3678 LLVMIntType, MIRBuilder, SPIRV::StorageClass::StorageBuffer);
3680 auto Zero = buildI32Constant(0,
I);
3686 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3687 TII.get(SPIRV::OpAccessChain))
3690 .
addUse(CounterHandleReg)
3698 auto Scope = buildI32Constant(SPIRV::Scope::Device,
I);
3701 auto Semantics = buildI32Constant(SPIRV::MemorySemantics::None,
I);
3702 if (!Semantics.second)
3706 auto Incr = buildI32Constant(
static_cast<uint32_t
>(IncrVal),
I);
3711 if (!
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAtomicIAdd))
3722 return BuildCOPY(ResVReg, AtomicRes,
I);
3730 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIAddS))
3737bool SPIRVInstructionSelector::selectReadImageIntrinsic(
3746 Register ImageReg =
I.getOperand(2).getReg();
3748 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
3754 Register IdxReg =
I.getOperand(3).getReg();
3756 MachineInstr &Pos =
I;
3758 return generateImageReadOrFetch(ResVReg, ResType, NewImageReg, IdxReg, Loc,
3762bool SPIRVInstructionSelector::generateImageReadOrFetch(
3767 "ImageReg is not an image type.");
3769 bool IsSignedInteger =
3774 bool IsFetch = (SampledOp.getImm() == 1);
3777 if (ResultSize == 4) {
3780 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
3786 if (IsSignedInteger)
3791 SPIRVType *ReadType = widenTypeToVec4(ResType, Pos);
3795 TII.get(IsFetch ? SPIRV::OpImageFetch : SPIRV::OpImageRead))
3800 if (IsSignedInteger)
3806 if (ResultSize == 1) {
3808 TII.get(SPIRV::OpCompositeExtract))
3815 return extractSubvector(ResVReg, ResType, ReadReg, Pos);
3818bool SPIRVInstructionSelector::selectResourceGetPointer(
3820 Register ResourcePtr =
I.getOperand(2).getReg();
3822 if (RegType->
getOpcode() == SPIRV::OpTypeImage) {
3831 MachineIRBuilder MIRBuilder(
I);
3833 Register IndexReg =
I.getOperand(3).getReg();
3836 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3837 TII.get(SPIRV::OpAccessChain))
3846bool SPIRVInstructionSelector::selectResourceNonUniformIndex(
3848 Register ObjReg =
I.getOperand(2).getReg();
3849 if (!BuildCOPY(ResVReg, ObjReg,
I))
3859 decorateUsesAsNonUniform(ResVReg);
3863void SPIRVInstructionSelector::decorateUsesAsNonUniform(
3866 while (WorkList.
size() > 0) {
3870 bool IsDecorated =
false;
3871 for (MachineInstr &Use :
MRI->use_instructions(CurrentReg)) {
3872 if (
Use.getOpcode() == SPIRV::OpDecorate &&
3873 Use.getOperand(1).getImm() == SPIRV::Decoration::NonUniformEXT) {
3879 if (
Use.getOperand(0).isReg() &&
Use.getOperand(0).isDef()) {
3881 if (ResultReg == CurrentReg)
3889 SPIRV::Decoration::NonUniformEXT, {});
3894bool SPIRVInstructionSelector::extractSubvector(
3896 MachineInstr &InsertionPoint)
const {
3898 [[maybe_unused]] uint64_t InputSize =
3901 assert(InputSize > 1 &&
"The input must be a vector.");
3902 assert(ResultSize > 1 &&
"The result must be a vector.");
3903 assert(ResultSize < InputSize &&
3904 "Cannot extract more element than there are in the input.");
3907 const TargetRegisterClass *ScalarRegClass = GR.
getRegClass(ScalarType);
3908 for (uint64_t
I = 0;
I < ResultSize;
I++) {
3909 Register ComponentReg =
MRI->createVirtualRegister(ScalarRegClass);
3912 TII.get(SPIRV::OpCompositeExtract))
3923 MachineInstrBuilder MIB =
BuildMI(*InsertionPoint.
getParent(), InsertionPoint,
3925 TII.get(SPIRV::OpCompositeConstruct))
3929 for (
Register ComponentReg : ComponentRegisters)
3930 MIB.
addUse(ComponentReg);
3934bool SPIRVInstructionSelector::selectImageWriteIntrinsic(
3935 MachineInstr &
I)
const {
3942 Register ImageReg =
I.getOperand(1).getReg();
3944 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
3950 Register CoordinateReg =
I.getOperand(2).getReg();
3951 Register DataReg =
I.getOperand(3).getReg();
3954 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3955 TII.get(SPIRV::OpImageWrite))
3962Register SPIRVInstructionSelector::buildPointerToResource(
3963 const SPIRVType *SpirvResType, SPIRV::StorageClass::StorageClass SC,
3964 uint32_t Set, uint32_t
Binding, uint32_t ArraySize,
Register IndexReg,
3965 StringRef Name, MachineIRBuilder MIRBuilder)
const {
3967 if (ArraySize == 1) {
3971 "SpirvResType did not have an explicit layout.");
3976 const Type *VarType = ArrayType::get(
const_cast<Type *
>(ResType), ArraySize);
3980 VarPointerType, Set,
Binding, Name, MIRBuilder);
3995bool SPIRVInstructionSelector::selectFirstBitSet16(
3997 unsigned ExtendOpcode,
unsigned BitSetOpcode)
const {
3999 bool Result = selectOpWithSrcs(ExtReg, ResType,
I, {
I.getOperand(2).getReg()},
4003 selectFirstBitSet32(ResVReg, ResType,
I, ExtReg, BitSetOpcode);
4006bool SPIRVInstructionSelector::selectFirstBitSet32(
4008 Register SrcReg,
unsigned BitSetOpcode)
const {
4009 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4012 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4018bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
4020 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4027 assert(ComponentCount < 5 &&
"Vec 5+ will generate invalid SPIR-V ops");
4029 MachineIRBuilder MIRBuilder(
I);
4037 std::vector<Register> PartialRegs;
4040 unsigned CurrentComponent = 0;
4041 for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
4047 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4048 TII.get(SPIRV::OpVectorShuffle))
4053 .
addImm(CurrentComponent)
4054 .
addImm(CurrentComponent + 1);
4062 if (!selectFirstBitSet64(SubVecBitSetReg, Vec2ResType,
I, BitSetResult,
4063 BitSetOpcode, SwapPrimarySide))
4066 PartialRegs.push_back(SubVecBitSetReg);
4070 if (CurrentComponent != ComponentCount) {
4076 if (!selectOpWithSrcs(FinalElemReg, I64Type,
I, {SrcReg, ConstIntLastIdx},
4077 SPIRV::OpVectorExtractDynamic))
4083 if (!selectFirstBitSet64(FinalElemBitSetReg,
BaseType,
I, FinalElemReg,
4084 BitSetOpcode, SwapPrimarySide))
4087 PartialRegs.push_back(FinalElemBitSetReg);
4092 return selectOpWithSrcs(ResVReg, ResType,
I, std::move(PartialRegs),
4093 SPIRV::OpCompositeConstruct);
4096bool SPIRVInstructionSelector::selectFirstBitSet64(
4098 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
4111 if (ComponentCount > 2) {
4112 return selectFirstBitSet64Overflow(ResVReg, ResType,
I, SrcReg,
4113 BitSetOpcode, SwapPrimarySide);
4117 MachineIRBuilder MIRBuilder(
I);
4119 BaseType, 2 * ComponentCount, MIRBuilder,
false);
4123 if (!selectOpWithSrcs(BitcastReg, PostCastType,
I, {SrcReg},
4129 if (!selectFirstBitSet32(FBSReg, PostCastType,
I, BitcastReg, BitSetOpcode))
4136 bool IsScalarRes = ResType->
getOpcode() != SPIRV::OpTypeVector;
4139 if (!selectOpWithSrcs(HighReg, ResType,
I, {FBSReg, ConstIntZero},
4140 SPIRV::OpVectorExtractDynamic))
4142 if (!selectOpWithSrcs(LowReg, ResType,
I, {FBSReg, ConstIntOne},
4143 SPIRV::OpVectorExtractDynamic))
4147 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4148 TII.get(SPIRV::OpVectorShuffle))
4156 for (
unsigned J = 0; J < ComponentCount * 2; J += 2) {
4163 MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
4164 TII.get(SPIRV::OpVectorShuffle))
4172 for (
unsigned J = 1; J < ComponentCount * 2; J += 2) {
4193 SelectOp = SPIRV::OpSelectSISCond;
4194 AddOp = SPIRV::OpIAddS;
4202 SelectOp = SPIRV::OpSelectVIVCond;
4203 AddOp = SPIRV::OpIAddV;
4213 if (SwapPrimarySide) {
4214 PrimaryReg = LowReg;
4215 SecondaryReg = HighReg;
4216 PrimaryShiftReg = Reg0;
4217 SecondaryShiftReg = Reg32;
4222 if (!selectOpWithSrcs(BReg, BoolType,
I, {PrimaryReg, NegOneReg},
4228 if (!selectOpWithSrcs(TmpReg, ResType,
I, {
BReg, SecondaryReg, PrimaryReg},
4234 if (!selectOpWithSrcs(ValReg, ResType,
I,
4235 {
BReg, SecondaryShiftReg, PrimaryShiftReg}, SelectOp))
4238 return selectOpWithSrcs(ResVReg, ResType,
I, {ValReg, TmpReg}, AddOp);
4241bool SPIRVInstructionSelector::selectFirstBitHigh(
Register ResVReg,
4244 bool IsSigned)
const {
4246 Register OpReg =
I.getOperand(2).getReg();
4249 unsigned ExtendOpcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
4250 unsigned BitSetOpcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
4254 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4256 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4258 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4262 "spv_firstbituhigh and spv_firstbitshigh only support 16,32,64 bits.");
4266bool SPIRVInstructionSelector::selectFirstBitLow(
Register ResVReg,
4268 MachineInstr &
I)
const {
4270 Register OpReg =
I.getOperand(2).getReg();
4275 unsigned ExtendOpcode = SPIRV::OpUConvert;
4276 unsigned BitSetOpcode = GL::FindILsb;
4280 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
4282 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
4284 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
4291bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
4293 MachineInstr &
I)
const {
4297 bool Res =
BuildMI(BB,
I,
I.getDebugLoc(),
4298 TII.get(SPIRV::OpVariableLengthArrayINTEL))
4301 .
addUse(
I.getOperand(2).getReg())
4304 unsigned Alignment =
I.getOperand(3).getImm();
4310bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
4312 MachineInstr &
I)
const {
4316 bool Res =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
4317 TII.get(SPIRV::OpVariable))
4320 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
4323 unsigned Alignment =
I.getOperand(2).getImm();
4330bool SPIRVInstructionSelector::selectBranch(MachineInstr &
I)
const {
4335 const MachineInstr *PrevI =
I.getPrevNode();
4337 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
4338 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4341 .
addMBB(
I.getOperand(0).getMBB())
4345 .
addMBB(
I.getOperand(0).getMBB())
4349bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &
I)
const {
4360 const MachineInstr *NextI =
I.getNextNode();
4362 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
4368 MachineBasicBlock *NextMBB =
I.getMF()->getBlockNumbered(NextMBBNum);
4369 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4370 .
addUse(
I.getOperand(0).getReg())
4371 .
addMBB(
I.getOperand(1).getMBB())
4376bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
4378 MachineInstr &
I)
const {
4379 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
4382 const unsigned NumOps =
I.getNumOperands();
4383 for (
unsigned i = 1; i <
NumOps; i += 2) {
4384 MIB.
addUse(
I.getOperand(i + 0).getReg());
4385 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
4393bool SPIRVInstructionSelector::selectGlobalValue(
4394 Register ResVReg, MachineInstr &
I,
const MachineInstr *Init)
const {
4396 MachineIRBuilder MIRBuilder(
I);
4397 const GlobalValue *GV =
I.
getOperand(1).getGlobal();
4400 std::string GlobalIdent;
4402 unsigned &
ID = UnnamedGlobalIDs[GV];
4404 ID = UnnamedGlobalIDs.size();
4405 GlobalIdent =
"__unnamed_" + Twine(
ID).str();
4432 GVFun ? SPIRV::StorageClass::CodeSectionINTEL
4439 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4442 MRI->setRegClass(FuncVReg, &SPIRV::pIDRegClass);
4443 MachineInstrBuilder MIB1 =
4444 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
4447 MachineInstrBuilder MIB2 =
4449 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
4453 GR.
add(ConstVal, MIB2);
4459 MachineInstrBuilder MIB3 =
4460 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
4463 GR.
add(ConstVal, MIB3);
4466 assert(NewReg != ResVReg);
4467 return BuildCOPY(ResVReg, NewReg,
I);
4477 const std::optional<SPIRV::LinkageType::LinkageType> LnkType =
4486 GlobalVar->isConstant(), LnkType, MIRBuilder,
true);
4490bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
4492 MachineInstr &
I)
const {
4494 return selectExtInst(ResVReg, ResType,
I, CL::log10);
4502 MachineIRBuilder MIRBuilder(
I);
4508 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4511 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4513 .
add(
I.getOperand(1))
4518 ResType->
getOpcode() == SPIRV::OpTypeFloat);
4521 ResType->
getOpcode() == SPIRV::OpTypeVector
4528 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
4529 ? SPIRV::OpVectorTimesScalar
4539bool SPIRVInstructionSelector::selectModf(
Register ResVReg,
4541 MachineInstr &
I)
const {
4557 MachineIRBuilder MIRBuilder(
I);
4560 ResType, MIRBuilder, SPIRV::StorageClass::Function);
4572 MachineBasicBlock &EntryBB =
I.getMF()->front();
4576 BuildMI(EntryBB, VarPos,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
4579 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function));
4585 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4588 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::OpenCL_std))
4591 .
add(
I.getOperand(
I.getNumExplicitDefs()))
4595 Register IntegralPartReg =
I.getOperand(1).getReg();
4596 if (IntegralPartReg.
isValid()) {
4598 auto LoadMIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4607 assert(
false &&
"GLSL::Modf is deprecated.");
4618bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
4619 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4620 const SPIRVType *ResType, MachineInstr &
I)
const {
4621 MachineIRBuilder MIRBuilder(
I);
4625 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
4637 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
4641 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4642 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
4648 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4655 assert(
I.getOperand(2).isReg());
4656 const uint32_t ThreadId =
foldImm(
I.getOperand(2),
MRI);
4660 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
4670bool SPIRVInstructionSelector::loadBuiltinInputID(
4671 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4672 const SPIRVType *ResType, MachineInstr &
I)
const {
4673 MachineIRBuilder MIRBuilder(
I);
4675 ResType, MIRBuilder, SPIRV::StorageClass::Input);
4690 SPIRV::StorageClass::Input,
nullptr,
true, std::nullopt, MIRBuilder,
4694 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4703 MachineInstr &
I)
const {
4704 MachineIRBuilder MIRBuilder(
I);
4705 if (
Type->getOpcode() != SPIRV::OpTypeVector)
4709 if (VectorSize == 4)
4717bool SPIRVInstructionSelector::loadHandleBeforePosition(
4719 MachineInstr &Pos)
const {
4722 Intrinsic::spv_resource_handlefrombinding);
4730 bool IsStructuredBuffer = ResType->
getOpcode() == SPIRV::OpTypePointer;
4731 MachineIRBuilder MIRBuilder(HandleDef);
4733 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::UniformConstant;
4735 if (IsStructuredBuffer) {
4740 Register VarReg = buildPointerToResource(VarType, SC, Set,
Binding, ArraySize,
4741 IndexReg, Name, MIRBuilder);
4745 uint32_t LoadOpcode =
4746 IsStructuredBuffer ? SPIRV::OpCopyObject : SPIRV::OpLoad;
4749 TII.get(LoadOpcode))
4756void SPIRVInstructionSelector::errorIfInstrOutsideShader(
4757 MachineInstr &
I)
const {
4759 std::string DiagMsg;
4760 raw_string_ostream OS(DiagMsg);
4761 I.print(OS,
true,
false,
false,
false);
4762 DiagMsg +=
" is only supported in shaders.\n";
4768InstructionSelector *
4772 return new SPIRVInstructionSelector(TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
#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
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 unsigned getBoolCmpOpcode(unsigned PredNum)
static unsigned getICmpOpcode(unsigned PredNum)
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 isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isPointer() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MONonTemporal
The memory access is non-temporal.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
defusechain_instr_iterator< false, true, false, true > def_instr_iterator
def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the specified register,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
Analysis providing profile information.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
Register getOrCreateConstInt(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getResultType(Register VReg, MachineFunction *MF=nullptr)
SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)
MachineInstr * getOrAddMemAliasingINTELInst(MachineIRBuilder &MIRBuilder, const MDNode *AliasingListMD)
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
SPIRVType * changePointerStorageClass(SPIRVType *PtrType, SPIRV::StorageClass::StorageClass SC, MachineInstr &I)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
unsigned getScalarOrVectorComponentCount(Register VReg) const
SPIRVType * getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I, const SPIRVInstrInfo &TII)
bool isScalarOrVectorSigned(const SPIRVType *Type) const
Register getOrCreateGlobalVariableWithBinding(const SPIRVType *VarType, uint32_t Set, uint32_t Binding, StringRef Name, MachineIRBuilder &MIRBuilder)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
unsigned getPointerSize() const
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)
SPIRVType * getPointeeType(SPIRVType *PtrType)
void invalidateMachineInstr(MachineInstr *MI)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
bool isScalarOfType(Register VReg, unsigned TypeOpcode) const
bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name)
void addGlobalObject(const Value *V, const MachineFunction *MF, Register R)
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
void recordFunctionPointer(const MachineOperand *MO, const Function *F)
bool isAggregateType(SPIRVType *Type) const
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)
MachineFunction * setCurrentFunc(MachineFunction &MF)
Register getOrCreateConstVector(uint64_t Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
Type * getDeducedGlobalValueType(const GlobalValue *Global)
LLT getRegType(SPIRVType *SpvType) const
SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const
Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII, bool ZeroAsNull=true)
Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const
const SPIRVType * retrieveScalarOrVectorIntType(const SPIRVType *Type) const
bool erase(const MachineInstr *MI)
bool add(SPIRV::IRHandle Handle, const MachineInstr *MI)
Register find(SPIRV::IRHandle Handle, const MachineFunction *MF)
bool isPhysicalSPIRV() const
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const
bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const
bool isLogicalSPIRV() const
bool canUseExtension(SPIRV::Extension::Extension E) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
The instances of the Type class are immutable: once they are created, they are never changed.
@ HalfTyID
16-bit floating point type
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
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.
LLVM_C_ABI LLVMTypeRef LLVMIntType(unsigned NumBits)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
NodeAddr< InstrNode * > Instr
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
int64_t getIConstValSext(Register ConstReg, const MachineRegisterInfo *MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isTypeFoldingSupported(unsigned Opcode)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
LLVM_ABI void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
unsigned getArrayComponentCount(const MachineRegisterInfo *MRI, const MachineInstr *ResType)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
MachineBasicBlock::iterator getFirstValidInstructionInsertPoint(MachineBasicBlock &BB)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I)
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
Type * toTypedPointer(Type *Ty)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
const MachineInstr SPIRVType
constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MachineInstr * passCopy(MachineInstr *Def, const MachineRegisterInfo *MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
std::optional< SPIRV::LinkageType::LinkageType > getSpirvLinkageTypeFor(const SPIRVSubtarget &ST, const GlobalValue &GV)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
InstructionSelector * createSPIRVInstructionSelector(const SPIRVTargetMachine &TM, const SPIRVSubtarget &Subtarget, const RegisterBankInfo &RBI)
std::string getStringValueFromReg(Register Reg, MachineRegisterInfo &MRI)
int64_t foldImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool hasInitializer(const GlobalVariable *GV)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)
LLVM_ABI bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Check whether an instruction MI is dead: it only defines dead virtual registers, and doesn't have oth...