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>
236 bool IsSigned,
unsigned Opcode)
const;
238 bool IsSigned)
const;
244 bool IsSigned)
const;
283 GL::GLSLExtInst GLInst)
const;
288 GL::GLSLExtInst GLInst)
const;
320 std::pair<Register, bool>
322 const SPIRVType *ResType =
nullptr)
const;
334 SPIRV::StorageClass::StorageClass SC)
const;
341 SPIRV::StorageClass::StorageClass SC,
353 bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
356 bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
363bool sampledTypeIsSignedInteger(
const llvm::Type *HandleType) {
365 if (
TET->getTargetExtName() ==
"spirv.Image") {
368 assert(
TET->getTargetExtName() ==
"spirv.SignedImage");
369 return TET->getTypeParameter(0)->isIntegerTy();
373#define GET_GLOBALISEL_IMPL
374#include "SPIRVGenGlobalISel.inc"
375#undef GET_GLOBALISEL_IMPL
381 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
384#include
"SPIRVGenGlobalISel.inc"
387#include
"SPIRVGenGlobalISel.inc"
399 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
403void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
404 if (HasVRegsReset == &MF)
409 for (
unsigned I = 0,
E =
MRI.getNumVirtRegs();
I !=
E; ++
I) {
411 LLT RegType =
MRI.getType(
Reg);
419 for (
const auto &
MBB : MF) {
420 for (
const auto &
MI :
MBB) {
423 if (
MI.getOpcode() != SPIRV::ASSIGN_TYPE)
427 LLT DstType =
MRI.getType(DstReg);
429 LLT SrcType =
MRI.getType(SrcReg);
430 if (DstType != SrcType)
431 MRI.setType(DstReg,
MRI.getType(SrcReg));
433 const TargetRegisterClass *DstRC =
MRI.getRegClassOrNull(DstReg);
434 const TargetRegisterClass *SrcRC =
MRI.getRegClassOrNull(SrcReg);
435 if (DstRC != SrcRC && SrcRC)
436 MRI.setRegClass(DstReg, SrcRC);
452 case TargetOpcode::G_CONSTANT:
453 case TargetOpcode::G_FCONSTANT:
455 case TargetOpcode::G_INTRINSIC:
456 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
457 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
459 Intrinsic::spv_const_composite;
460 case TargetOpcode::G_BUILD_VECTOR:
461 case TargetOpcode::G_SPLAT_VECTOR: {
472 case SPIRV::OpConstantTrue:
473 case SPIRV::OpConstantFalse:
474 case SPIRV::OpConstantI:
475 case SPIRV::OpConstantF:
476 case SPIRV::OpConstantComposite:
477 case SPIRV::OpConstantCompositeContinuedINTEL:
478 case SPIRV::OpConstantSampler:
479 case SPIRV::OpConstantNull:
481 case SPIRV::OpConstantFunctionPointerINTEL:
497 for (
const auto &MO :
MI.all_defs()) {
499 if (
Reg.isPhysical() || !
MRI.use_nodbg_empty(
Reg))
502 if (
MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE ||
MI.isFakeUse() ||
503 MI.isLifetimeMarker())
507 if (
MI.mayStore() ||
MI.isCall() ||
508 (
MI.mayLoad() &&
MI.hasOrderedMemoryRef()) ||
MI.isPosition() ||
509 MI.isDebugInstr() ||
MI.isTerminator() ||
MI.isJumpTableDebugInfo())
514bool SPIRVInstructionSelector::select(MachineInstr &
I) {
515 resetVRegsType(*
I.getParent()->getParent());
517 assert(
I.getParent() &&
"Instruction should be in a basic block!");
518 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
523 if (Opcode == SPIRV::ASSIGN_TYPE) {
524 Register DstReg =
I.getOperand(0).getReg();
525 Register SrcReg =
I.getOperand(1).getReg();
526 auto *
Def =
MRI->getVRegDef(SrcReg);
528 Def->getOpcode() != TargetOpcode::G_CONSTANT &&
529 Def->getOpcode() != TargetOpcode::G_FCONSTANT) {
531 if (
Def->getOpcode() == TargetOpcode::G_SELECT) {
532 Register SelectDstReg =
Def->getOperand(0).getReg();
536 Def->removeFromParent();
537 MRI->replaceRegWith(DstReg, SelectDstReg);
539 I.removeFromParent();
541 Res = selectImpl(
I, *CoverageInfo);
543 if (!Res &&
Def->getOpcode() != TargetOpcode::G_CONSTANT) {
544 dbgs() <<
"Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
548 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
555 MRI->setRegClass(SrcReg,
MRI->getRegClass(DstReg));
556 MRI->replaceRegWith(SrcReg, DstReg);
558 I.removeFromParent();
560 }
else if (
I.getNumDefs() == 1) {
567 if (DeadMIs.contains(&
I)) {
577 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
578 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
584 bool HasDefs =
I.getNumDefs() > 0;
587 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
588 I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
589 if (spvSelect(ResVReg, ResType,
I)) {
591 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
594 I.removeFromParent();
602 case TargetOpcode::G_CONSTANT:
603 case TargetOpcode::G_FCONSTANT:
605 case TargetOpcode::G_SADDO:
606 case TargetOpcode::G_SSUBO:
613 MachineInstr &
I)
const {
614 const TargetRegisterClass *DstRC =
MRI->getRegClassOrNull(DestReg);
615 const TargetRegisterClass *SrcRC =
MRI->getRegClassOrNull(SrcReg);
616 if (DstRC != SrcRC && SrcRC)
617 MRI->setRegClass(DestReg, SrcRC);
618 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
619 TII.get(TargetOpcode::COPY))
625bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
627 MachineInstr &
I)
const {
628 const unsigned Opcode =
I.getOpcode();
630 return selectImpl(
I, *CoverageInfo);
632 case TargetOpcode::G_CONSTANT:
633 case TargetOpcode::G_FCONSTANT:
634 return selectConst(ResVReg, ResType,
I);
635 case TargetOpcode::G_GLOBAL_VALUE:
636 return selectGlobalValue(ResVReg,
I);
637 case TargetOpcode::G_IMPLICIT_DEF:
638 return selectOpUndef(ResVReg, ResType,
I);
639 case TargetOpcode::G_FREEZE:
640 return selectFreeze(ResVReg, ResType,
I);
642 case TargetOpcode::G_INTRINSIC:
643 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
644 case TargetOpcode::G_INTRINSIC_CONVERGENT:
645 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
646 return selectIntrinsic(ResVReg, ResType,
I);
647 case TargetOpcode::G_BITREVERSE:
648 return selectBitreverse(ResVReg, ResType,
I);
650 case TargetOpcode::G_BUILD_VECTOR:
651 return selectBuildVector(ResVReg, ResType,
I);
652 case TargetOpcode::G_SPLAT_VECTOR:
653 return selectSplatVector(ResVReg, ResType,
I);
655 case TargetOpcode::G_SHUFFLE_VECTOR: {
656 MachineBasicBlock &BB = *
I.getParent();
657 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
660 .
addUse(
I.getOperand(1).getReg())
661 .
addUse(
I.getOperand(2).getReg());
662 for (
auto V :
I.getOperand(3).getShuffleMask())
666 case TargetOpcode::G_MEMMOVE:
667 case TargetOpcode::G_MEMCPY:
668 case TargetOpcode::G_MEMSET:
669 return selectMemOperation(ResVReg,
I);
671 case TargetOpcode::G_ICMP:
672 return selectICmp(ResVReg, ResType,
I);
673 case TargetOpcode::G_FCMP:
674 return selectFCmp(ResVReg, ResType,
I);
676 case TargetOpcode::G_FRAME_INDEX:
677 return selectFrameIndex(ResVReg, ResType,
I);
679 case TargetOpcode::G_LOAD:
680 return selectLoad(ResVReg, ResType,
I);
681 case TargetOpcode::G_STORE:
682 return selectStore(
I);
684 case TargetOpcode::G_BR:
685 return selectBranch(
I);
686 case TargetOpcode::G_BRCOND:
687 return selectBranchCond(
I);
689 case TargetOpcode::G_PHI:
690 return selectPhi(ResVReg, ResType,
I);
692 case TargetOpcode::G_FPTOSI:
693 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
694 case TargetOpcode::G_FPTOUI:
695 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
697 case TargetOpcode::G_FPTOSI_SAT:
698 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
699 case TargetOpcode::G_FPTOUI_SAT:
700 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
702 case TargetOpcode::G_SITOFP:
703 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
704 case TargetOpcode::G_UITOFP:
705 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
707 case TargetOpcode::G_CTPOP:
708 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
709 case TargetOpcode::G_SMIN:
710 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
711 case TargetOpcode::G_UMIN:
712 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
714 case TargetOpcode::G_SMAX:
715 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
716 case TargetOpcode::G_UMAX:
717 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
719 case TargetOpcode::G_SCMP:
720 return selectSUCmp(ResVReg, ResType,
I,
true);
721 case TargetOpcode::G_UCMP:
722 return selectSUCmp(ResVReg, ResType,
I,
false);
723 case TargetOpcode::G_LROUND:
724 case TargetOpcode::G_LLROUND: {
726 MRI->createVirtualRegister(
MRI->getRegClass(ResVReg),
"lround");
727 MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
729 regForLround, *(
I.getParent()->getParent()));
731 I, CL::round, GL::Round);
733 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConvertFToS))
739 case TargetOpcode::G_STRICT_FMA:
740 case TargetOpcode::G_FMA:
741 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
743 case TargetOpcode::G_STRICT_FLDEXP:
744 return selectExtInst(ResVReg, ResType,
I, CL::ldexp);
746 case TargetOpcode::G_FPOW:
747 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
748 case TargetOpcode::G_FPOWI:
749 return selectExtInst(ResVReg, ResType,
I, CL::pown);
751 case TargetOpcode::G_FEXP:
752 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
753 case TargetOpcode::G_FEXP2:
754 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
755 case TargetOpcode::G_FMODF:
756 return selectModf(ResVReg, ResType,
I);
758 case TargetOpcode::G_FLOG:
759 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
760 case TargetOpcode::G_FLOG2:
761 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
762 case TargetOpcode::G_FLOG10:
763 return selectLog10(ResVReg, ResType,
I);
765 case TargetOpcode::G_FABS:
766 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
767 case TargetOpcode::G_ABS:
768 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
770 case TargetOpcode::G_FMINNUM:
771 case TargetOpcode::G_FMINIMUM:
772 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
773 case TargetOpcode::G_FMAXNUM:
774 case TargetOpcode::G_FMAXIMUM:
775 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
777 case TargetOpcode::G_FCOPYSIGN:
778 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
780 case TargetOpcode::G_FCEIL:
781 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
782 case TargetOpcode::G_FFLOOR:
783 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
785 case TargetOpcode::G_FCOS:
786 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
787 case TargetOpcode::G_FSIN:
788 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
789 case TargetOpcode::G_FTAN:
790 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
791 case TargetOpcode::G_FACOS:
792 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
793 case TargetOpcode::G_FASIN:
794 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
795 case TargetOpcode::G_FATAN:
796 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
797 case TargetOpcode::G_FATAN2:
798 return selectExtInst(ResVReg, ResType,
I, CL::atan2, GL::Atan2);
799 case TargetOpcode::G_FCOSH:
800 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
801 case TargetOpcode::G_FSINH:
802 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
803 case TargetOpcode::G_FTANH:
804 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
806 case TargetOpcode::G_STRICT_FSQRT:
807 case TargetOpcode::G_FSQRT:
808 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
810 case TargetOpcode::G_CTTZ:
811 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
812 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
813 case TargetOpcode::G_CTLZ:
814 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
815 return selectExtInst(ResVReg, ResType,
I, CL::clz);
817 case TargetOpcode::G_INTRINSIC_ROUND:
818 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
819 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
820 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
821 case TargetOpcode::G_INTRINSIC_TRUNC:
822 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
823 case TargetOpcode::G_FRINT:
824 case TargetOpcode::G_FNEARBYINT:
825 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
827 case TargetOpcode::G_SMULH:
828 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
829 case TargetOpcode::G_UMULH:
830 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
832 case TargetOpcode::G_SADDSAT:
833 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
834 case TargetOpcode::G_UADDSAT:
835 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
836 case TargetOpcode::G_SSUBSAT:
837 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
838 case TargetOpcode::G_USUBSAT:
839 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
841 case TargetOpcode::G_FFREXP:
842 return selectFrexp(ResVReg, ResType,
I);
844 case TargetOpcode::G_UADDO:
845 return selectOverflowArith(ResVReg, ResType,
I,
846 ResType->
getOpcode() == SPIRV::OpTypeVector
847 ? SPIRV::OpIAddCarryV
848 : SPIRV::OpIAddCarryS);
849 case TargetOpcode::G_USUBO:
850 return selectOverflowArith(ResVReg, ResType,
I,
851 ResType->
getOpcode() == SPIRV::OpTypeVector
852 ? SPIRV::OpISubBorrowV
853 : SPIRV::OpISubBorrowS);
854 case TargetOpcode::G_UMULO:
855 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpUMulExtended);
856 case TargetOpcode::G_SMULO:
857 return selectOverflowArith(ResVReg, ResType,
I, SPIRV::OpSMulExtended);
859 case TargetOpcode::G_SEXT:
860 return selectExt(ResVReg, ResType,
I,
true);
861 case TargetOpcode::G_ANYEXT:
862 case TargetOpcode::G_ZEXT:
863 return selectExt(ResVReg, ResType,
I,
false);
864 case TargetOpcode::G_TRUNC:
865 return selectTrunc(ResVReg, ResType,
I);
866 case TargetOpcode::G_FPTRUNC:
867 case TargetOpcode::G_FPEXT:
868 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
870 case TargetOpcode::G_PTRTOINT:
871 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
872 case TargetOpcode::G_INTTOPTR:
873 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
874 case TargetOpcode::G_BITCAST:
875 return selectBitcast(ResVReg, ResType,
I);
876 case TargetOpcode::G_ADDRSPACE_CAST:
877 return selectAddrSpaceCast(ResVReg, ResType,
I);
878 case TargetOpcode::G_PTR_ADD: {
880 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
884 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
885 (*II).getOpcode() == TargetOpcode::COPY ||
886 (*II).getOpcode() == SPIRV::OpVariable) &&
889 bool IsGVInit =
false;
891 UseIt =
MRI->use_instr_begin(
I.getOperand(0).getReg()),
892 UseEnd =
MRI->use_instr_end();
893 UseIt != UseEnd; UseIt = std::next(UseIt)) {
894 if ((*UseIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
895 (*UseIt).getOpcode() == SPIRV::OpVariable) {
905 if (GVPointeeType && ResPointeeType && GVPointeeType != ResPointeeType) {
908 Register NewVReg =
MRI->createGenericVirtualRegister(
MRI->getType(GV));
909 MRI->setRegClass(NewVReg,
MRI->getRegClass(GV));
918 "incompatible result and operand types in a bitcast");
920 MachineInstrBuilder MIB =
921 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitcast))
928 ? SPIRV::OpInBoundsAccessChain
929 : SPIRV::OpInBoundsPtrAccessChain))
933 .
addUse(
I.getOperand(2).getReg())
936 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
940 static_cast<uint32_t
>(SPIRV::Opcode::InBoundsPtrAccessChain))
942 .
addUse(
I.getOperand(2).getReg())
950 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
953 .
addImm(
static_cast<uint32_t
>(
954 SPIRV::Opcode::InBoundsPtrAccessChain))
957 .
addUse(
I.getOperand(2).getReg());
961 case TargetOpcode::G_ATOMICRMW_OR:
962 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
963 case TargetOpcode::G_ATOMICRMW_ADD:
964 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
965 case TargetOpcode::G_ATOMICRMW_AND:
966 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
967 case TargetOpcode::G_ATOMICRMW_MAX:
968 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
969 case TargetOpcode::G_ATOMICRMW_MIN:
970 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
971 case TargetOpcode::G_ATOMICRMW_SUB:
972 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
973 case TargetOpcode::G_ATOMICRMW_XOR:
974 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
975 case TargetOpcode::G_ATOMICRMW_UMAX:
976 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
977 case TargetOpcode::G_ATOMICRMW_UMIN:
978 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
979 case TargetOpcode::G_ATOMICRMW_XCHG:
980 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
981 case TargetOpcode::G_ATOMIC_CMPXCHG:
982 return selectAtomicCmpXchg(ResVReg, ResType,
I);
984 case TargetOpcode::G_ATOMICRMW_FADD:
985 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
986 case TargetOpcode::G_ATOMICRMW_FSUB:
988 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
990 case TargetOpcode::G_ATOMICRMW_FMIN:
991 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
992 case TargetOpcode::G_ATOMICRMW_FMAX:
993 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
995 case TargetOpcode::G_FENCE:
996 return selectFence(
I);
998 case TargetOpcode::G_STACKSAVE:
999 return selectStackSave(ResVReg, ResType,
I);
1000 case TargetOpcode::G_STACKRESTORE:
1001 return selectStackRestore(
I);
1003 case TargetOpcode::G_UNMERGE_VALUES:
1009 case TargetOpcode::G_TRAP:
1010 case TargetOpcode::G_UBSANTRAP:
1011 case TargetOpcode::DBG_LABEL:
1013 case TargetOpcode::G_DEBUGTRAP:
1014 return selectDebugTrap(ResVReg, ResType,
I);
1021bool SPIRVInstructionSelector::selectDebugTrap(
Register ResVReg,
1023 MachineInstr &
I)
const {
1024 unsigned Opcode = SPIRV::OpNop;
1026 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
1030bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1033 GL::GLSLExtInst GLInst)
const {
1035 SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) {
1036 std::string DiagMsg;
1037 raw_string_ostream OS(DiagMsg);
1038 I.print(OS,
true,
false,
false,
false);
1039 DiagMsg +=
" is only supported with the GLSL extended instruction set.\n";
1042 return selectExtInst(ResVReg, ResType,
I,
1043 {{SPIRV::InstructionSet::GLSL_std_450, GLInst}});
1046bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1049 CL::OpenCLExtInst CLInst)
const {
1050 return selectExtInst(ResVReg, ResType,
I,
1051 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
1054bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1057 CL::OpenCLExtInst CLInst,
1058 GL::GLSLExtInst GLInst)
const {
1059 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1060 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1061 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
1064bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
1069 for (
const auto &Ex : Insts) {
1070 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1071 uint32_t Opcode = Ex.second;
1074 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1077 .
addImm(
static_cast<uint32_t
>(Set))
1080 const unsigned NumOps =
I.getNumOperands();
1083 I.getOperand(Index).getType() ==
1084 MachineOperand::MachineOperandType::MO_IntrinsicID)
1087 MIB.
add(
I.getOperand(Index));
1093bool SPIRVInstructionSelector::selectExtInstForLRound(
1095 CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst)
const {
1096 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
1097 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
1098 return selectExtInstForLRound(ResVReg, ResType,
I, ExtInsts);
1101bool SPIRVInstructionSelector::selectExtInstForLRound(
1104 for (
const auto &Ex : Insts) {
1105 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1106 uint32_t Opcode = Ex.second;
1109 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1112 .
addImm(
static_cast<uint32_t
>(Set))
1114 const unsigned NumOps =
I.getNumOperands();
1117 I.getOperand(Index).getType() ==
1118 MachineOperand::MachineOperandType::MO_IntrinsicID)
1121 MIB.
add(
I.getOperand(Index));
1129bool SPIRVInstructionSelector::selectFrexp(
Register ResVReg,
1131 MachineInstr &
I)
const {
1132 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CL::frexp},
1133 {SPIRV::InstructionSet::GLSL_std_450, GL::Frexp}};
1134 for (
const auto &Ex : ExtInsts) {
1135 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
1136 uint32_t Opcode = Ex.second;
1140 MachineIRBuilder MIRBuilder(
I);
1143 PointeeTy, MIRBuilder, SPIRV::StorageClass::Function);
1148 auto MIB =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
1149 TII.get(SPIRV::OpVariable))
1152 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
1156 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1159 .
addImm(
static_cast<uint32_t
>(Ex.first))
1161 .
add(
I.getOperand(2))
1166 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1167 .
addDef(
I.getOperand(1).getReg())
1176bool SPIRVInstructionSelector::selectOpWithSrcs(
Register ResVReg,
1179 std::vector<Register> Srcs,
1180 unsigned Opcode)
const {
1181 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1190bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
1193 unsigned Opcode)
const {
1195 Register SrcReg =
I.getOperand(1).getReg();
1198 MRI->def_instr_begin(SrcReg);
1199 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
1200 if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1201 (*DefIt).getOpcode() == SPIRV::OpVariable) {
1207 uint32_t SpecOpcode = 0;
1209 case SPIRV::OpConvertPtrToU:
1210 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertPtrToU);
1212 case SPIRV::OpConvertUToPtr:
1213 SpecOpcode =
static_cast<uint32_t
>(SPIRV::Opcode::ConvertUToPtr);
1217 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1218 TII.get(SPIRV::OpSpecConstantOp))
1226 return selectOpWithSrcs(ResVReg, ResType,
I, {
I.getOperand(1).getReg()},
1230bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
1232 MachineInstr &
I)
const {
1233 Register OpReg =
I.getOperand(1).getReg();
1237 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
1245 if (
MemOp->isVolatile())
1246 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1247 if (
MemOp->isNonTemporal())
1248 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1249 if (
MemOp->getAlign().value())
1250 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
1256 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
1257 if (
auto *MD =
MemOp->getAAInfo().Scope) {
1261 static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
1263 if (
auto *MD =
MemOp->getAAInfo().NoAlias) {
1267 static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
1271 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
1273 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
1285 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
1287 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
1289 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
1293bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
1295 MachineInstr &
I)
const {
1302 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1303 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1305 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1307 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1309 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1313 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1314 return generateImageRead(ResVReg, ResType, NewHandleReg, IdxReg,
1315 I.getDebugLoc(),
I);
1319 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
1323 if (!
I.getNumMemOperands()) {
1324 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1326 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1329 MachineIRBuilder MIRBuilder(
I);
1335bool SPIRVInstructionSelector::selectStore(MachineInstr &
I)
const {
1337 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
1343 IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1344 Register HandleReg = IntPtrDef->getOperand(2).getReg();
1346 MRI->createVirtualRegister(
MRI->getRegClass(HandleReg));
1349 if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef,
I)) {
1353 Register IdxReg = IntPtrDef->getOperand(3).getReg();
1354 if (HandleType->
getOpcode() == SPIRV::OpTypeImage) {
1355 auto BMI =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1356 TII.get(SPIRV::OpImageWrite))
1362 if (sampledTypeIsSignedInteger(LLVMHandleType))
1365 return BMI.constrainAllUses(
TII,
TRI, RBI);
1370 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
1373 if (!
I.getNumMemOperands()) {
1374 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
1376 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
1379 MachineIRBuilder MIRBuilder(
I);
1385bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
1387 MachineInstr &
I)
const {
1388 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1390 "llvm.stacksave intrinsic: this instruction requires the following "
1391 "SPIR-V extension: SPV_INTEL_variable_length_array",
1394 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
1400bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &
I)
const {
1401 if (!STI.
canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
1403 "llvm.stackrestore intrinsic: this instruction requires the following "
1404 "SPIR-V extension: SPV_INTEL_variable_length_array",
1406 if (!
I.getOperand(0).isReg())
1409 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
1410 .
addUse(
I.getOperand(0).getReg())
1414bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
1415 MachineInstr &
I)
const {
1417 Register SrcReg =
I.getOperand(1).getReg();
1419 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
1420 MachineIRBuilder MIRBuilder(
I);
1421 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
1424 Type *ValTy = Type::getInt8Ty(
I.getMF()->getFunction().getContext());
1425 Type *ArrTy = ArrayType::get(ValTy, Num);
1427 ArrTy, MIRBuilder, SPIRV::StorageClass::UniformConstant);
1430 ArrTy, MIRBuilder, SPIRV::AccessQualifier::None,
false);
1437 GlobalVariable *GV =
new GlobalVariable(*CurFunction.
getParent(), LLVMArrTy,
1442 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
1445 .
addImm(SPIRV::StorageClass::UniformConstant)
1454 ValTy,
I, SPIRV::StorageClass::UniformConstant);
1456 selectOpWithSrcs(SrcReg, SourceTy,
I, {VarReg}, SPIRV::OpBitcast);
1458 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
1459 .
addUse(
I.getOperand(0).getReg())
1461 .
addUse(
I.getOperand(2).getReg());
1462 if (
I.getNumMemOperands()) {
1463 MachineIRBuilder MIRBuilder(
I);
1472bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
1476 unsigned NegateOpcode)
const {
1479 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1482 auto ScopeConstant = buildI32Constant(Scope,
I);
1483 Register ScopeReg = ScopeConstant.first;
1484 Result &= ScopeConstant.second;
1492 auto MemSemConstant = buildI32Constant(MemSem ,
I);
1493 Register MemSemReg = MemSemConstant.first;
1494 Result &= MemSemConstant.second;
1496 Register ValueReg =
I.getOperand(2).getReg();
1497 if (NegateOpcode != 0) {
1500 Result &= selectOpWithSrcs(TmpReg, ResType,
I, {ValueReg}, NegateOpcode);
1505 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(NewOpcode))
1515bool SPIRVInstructionSelector::selectUnmergeValues(MachineInstr &
I)
const {
1516 unsigned ArgI =
I.getNumOperands() - 1;
1518 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
1521 if (!DefType || DefType->
getOpcode() != SPIRV::OpTypeVector)
1523 "cannot select G_UNMERGE_VALUES with a non-vector argument");
1529 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1530 Register ResVReg =
I.getOperand(i).getReg();
1534 ResType = ScalarType;
1540 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1544 .
addImm(
static_cast<int64_t
>(i));
1550bool SPIRVInstructionSelector::selectFence(MachineInstr &
I)
const {
1553 auto MemSemConstant = buildI32Constant(MemSem,
I);
1554 Register MemSemReg = MemSemConstant.first;
1555 bool Result = MemSemConstant.second;
1557 uint32_t
Scope =
static_cast<uint32_t
>(
1559 auto ScopeConstant = buildI32Constant(Scope,
I);
1560 Register ScopeReg = ScopeConstant.first;
1561 Result &= ScopeConstant.second;
1564 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
1570bool SPIRVInstructionSelector::selectOverflowArith(
Register ResVReg,
1573 unsigned Opcode)
const {
1574 Type *ResTy =
nullptr;
1578 "Not enough info to select the arithmetic with overflow instruction");
1581 "with overflow instruction");
1587 MachineIRBuilder MIRBuilder(
I);
1589 ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
1590 assert(
I.getNumDefs() > 1 &&
"Not enought operands");
1596 Register ZeroReg = buildZerosVal(ResType,
I);
1599 MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
1601 if (ResName.
size() > 0)
1606 BuildMI(BB, MIRBuilder.getInsertPt(),
I.getDebugLoc(),
TII.get(Opcode))
1609 for (
unsigned i =
I.getNumDefs(); i <
I.getNumOperands(); ++i)
1610 MIB.
addUse(
I.getOperand(i).getReg());
1615 MRI->setRegClass(HigherVReg, &SPIRV::iIDRegClass);
1616 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
1618 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1619 .
addDef(i == 1 ? HigherVReg :
I.getOperand(i).getReg())
1627 .
addDef(
I.getOperand(1).getReg())
1634bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
1636 MachineInstr &
I)
const {
1644 const MachineMemOperand *MemOp = *
I.memoperands_begin();
1647 auto ScopeConstant = buildI32Constant(Scope,
I);
1648 ScopeReg = ScopeConstant.first;
1649 Result &= ScopeConstant.second;
1651 unsigned ScSem =
static_cast<uint32_t
>(
1654 unsigned MemSemEq =
static_cast<uint32_t
>(
getMemSemantics(AO)) | ScSem;
1655 auto MemSemEqConstant = buildI32Constant(MemSemEq,
I);
1656 MemSemEqReg = MemSemEqConstant.first;
1657 Result &= MemSemEqConstant.second;
1659 unsigned MemSemNeq =
static_cast<uint32_t
>(
getMemSemantics(FO)) | ScSem;
1660 if (MemSemEq == MemSemNeq)
1661 MemSemNeqReg = MemSemEqReg;
1663 auto MemSemNeqConstant = buildI32Constant(MemSemEq,
I);
1664 MemSemNeqReg = MemSemNeqConstant.first;
1665 Result &= MemSemNeqConstant.second;
1668 ScopeReg =
I.getOperand(5).getReg();
1669 MemSemEqReg =
I.getOperand(6).getReg();
1670 MemSemNeqReg =
I.getOperand(7).getReg();
1674 Register Val =
I.getOperand(4).getReg();
1679 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
1706 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpCompositeInsert))
1717 case SPIRV::StorageClass::DeviceOnlyINTEL:
1718 case SPIRV::StorageClass::HostOnlyINTEL:
1727 bool IsGRef =
false;
1728 bool IsAllowedRefs =
1729 llvm::all_of(
MRI->use_instructions(ResVReg), [&IsGRef](
auto const &It) {
1730 unsigned Opcode = It.getOpcode();
1731 if (Opcode == SPIRV::OpConstantComposite ||
1732 Opcode == SPIRV::OpVariable ||
1733 isSpvIntrinsic(It, Intrinsic::spv_init_global))
1734 return IsGRef = true;
1735 return Opcode == SPIRV::OpName;
1737 return IsAllowedRefs && IsGRef;
1740Register SPIRVInstructionSelector::getUcharPtrTypeReg(
1741 MachineInstr &
I, SPIRV::StorageClass::StorageClass SC)
const {
1743 Type::getInt8Ty(
I.getMF()->getFunction().getContext()),
I, SC));
1747SPIRVInstructionSelector::buildSpecConstantOp(MachineInstr &
I,
Register Dest,
1749 uint32_t Opcode)
const {
1750 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1751 TII.get(SPIRV::OpSpecConstantOp))
1759SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &
I,
Register SrcPtr,
1763 Register Tmp =
MRI->createVirtualRegister(&SPIRV::pIDRegClass);
1765 SPIRV::StorageClass::Generic),
1767 MachineFunction *MF =
I.getParent()->getParent();
1769 MachineInstrBuilder MIB = buildSpecConstantOp(
1771 static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric));
1781bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
1783 MachineInstr &
I)
const {
1787 Register SrcPtr =
I.getOperand(1).getReg();
1791 if (SrcPtrTy->
getOpcode() != SPIRV::OpTypePointer ||
1792 ResType->
getOpcode() != SPIRV::OpTypePointer)
1793 return BuildCOPY(ResVReg, SrcPtr,
I);
1803 unsigned SpecOpcode =
1805 ?
static_cast<uint32_t
>(SPIRV::Opcode::PtrCastToGeneric)
1808 ? static_cast<uint32_t>(
SPIRV::Opcode::GenericCastToPtr)
1815 return buildSpecConstantOp(
I, ResVReg, SrcPtr,
1816 getUcharPtrTypeReg(
I, DstSC), SpecOpcode)
1817 .constrainAllUses(
TII,
TRI, RBI);
1819 MachineInstrBuilder MIB = buildConstGenericPtr(
I, SrcPtr, SrcPtrTy);
1821 buildSpecConstantOp(
1823 getUcharPtrTypeReg(
I, DstSC),
1824 static_cast<uint32_t
>(SPIRV::Opcode::GenericCastToPtr))
1825 .constrainAllUses(
TII,
TRI, RBI);
1831 return BuildCOPY(ResVReg, SrcPtr,
I);
1833 if ((SrcSC == SPIRV::StorageClass::Function &&
1834 DstSC == SPIRV::StorageClass::Private) ||
1835 (DstSC == SPIRV::StorageClass::Function &&
1836 SrcSC == SPIRV::StorageClass::Private))
1837 return BuildCOPY(ResVReg, SrcPtr,
I);
1841 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1844 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1865 return selectUnOp(ResVReg, ResType,
I,
1866 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
1868 return selectUnOp(ResVReg, ResType,
I,
1869 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
1871 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1873 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1883 return SPIRV::OpFOrdEqual;
1885 return SPIRV::OpFOrdGreaterThanEqual;
1887 return SPIRV::OpFOrdGreaterThan;
1889 return SPIRV::OpFOrdLessThanEqual;
1891 return SPIRV::OpFOrdLessThan;
1893 return SPIRV::OpFOrdNotEqual;
1895 return SPIRV::OpOrdered;
1897 return SPIRV::OpFUnordEqual;
1899 return SPIRV::OpFUnordGreaterThanEqual;
1901 return SPIRV::OpFUnordGreaterThan;
1903 return SPIRV::OpFUnordLessThanEqual;
1905 return SPIRV::OpFUnordLessThan;
1907 return SPIRV::OpFUnordNotEqual;
1909 return SPIRV::OpUnordered;
1919 return SPIRV::OpIEqual;
1921 return SPIRV::OpINotEqual;
1923 return SPIRV::OpSGreaterThanEqual;
1925 return SPIRV::OpSGreaterThan;
1927 return SPIRV::OpSLessThanEqual;
1929 return SPIRV::OpSLessThan;
1931 return SPIRV::OpUGreaterThanEqual;
1933 return SPIRV::OpUGreaterThan;
1935 return SPIRV::OpULessThanEqual;
1937 return SPIRV::OpULessThan;
1946 return SPIRV::OpPtrEqual;
1948 return SPIRV::OpPtrNotEqual;
1959 return SPIRV::OpLogicalEqual;
1961 return SPIRV::OpLogicalNotEqual;
1995bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
1998 unsigned OpAnyOrAll)
const {
1999 assert(
I.getNumOperands() == 3);
2000 assert(
I.getOperand(2).isReg());
2002 Register InputRegister =
I.getOperand(2).getReg();
2009 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
2010 if (IsBoolTy && !IsVectorTy) {
2011 assert(ResVReg ==
I.getOperand(0).getReg());
2012 return BuildCOPY(ResVReg, InputRegister,
I);
2016 unsigned SpirvNotEqualId =
2017 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
2024 IsBoolTy ? InputRegister
2033 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
2053bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
2055 MachineInstr &
I)
const {
2056 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
2059bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
2061 MachineInstr &
I)
const {
2062 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
2066bool SPIRVInstructionSelector::selectFloatDot(
Register ResVReg,
2068 MachineInstr &
I)
const {
2069 assert(
I.getNumOperands() == 4);
2070 assert(
I.getOperand(2).isReg());
2071 assert(
I.getOperand(3).isReg());
2078 "dot product requires a vector of at least 2 components");
2086 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpDot))
2089 .
addUse(
I.getOperand(2).getReg())
2090 .
addUse(
I.getOperand(3).getReg())
2094bool SPIRVInstructionSelector::selectIntegerDot(
Register ResVReg,
2098 assert(
I.getNumOperands() == 4);
2099 assert(
I.getOperand(2).isReg());
2100 assert(
I.getOperand(3).isReg());
2103 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2107 .
addUse(
I.getOperand(2).getReg())
2108 .
addUse(
I.getOperand(3).getReg())
2114bool SPIRVInstructionSelector::selectIntegerDotExpansion(
2116 assert(
I.getNumOperands() == 4);
2117 assert(
I.getOperand(2).isReg());
2118 assert(
I.getOperand(3).isReg());
2122 Register Vec0 =
I.getOperand(2).getReg();
2123 Register Vec1 =
I.getOperand(3).getReg();
2136 "dot product requires a vector of at least 2 components");
2150 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2173bool SPIRVInstructionSelector::selectOpIsInf(
Register ResVReg,
2175 MachineInstr &
I)
const {
2177 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsInf))
2180 .
addUse(
I.getOperand(2).getReg())
2184bool SPIRVInstructionSelector::selectOpIsNan(
Register ResVReg,
2186 MachineInstr &
I)
const {
2188 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpIsNan))
2191 .
addUse(
I.getOperand(2).getReg())
2195template <
bool Signed>
2196bool SPIRVInstructionSelector::selectDot4AddPacked(
Register ResVReg,
2198 MachineInstr &
I)
const {
2199 assert(
I.getNumOperands() == 5);
2200 assert(
I.getOperand(2).isReg());
2201 assert(
I.getOperand(3).isReg());
2202 assert(
I.getOperand(4).isReg());
2205 Register Acc =
I.getOperand(2).getReg();
2209 auto DotOp =
Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
2229template <
bool Signed>
2230bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
2232 assert(
I.getNumOperands() == 5);
2233 assert(
I.getOperand(2).isReg());
2234 assert(
I.getOperand(3).isReg());
2235 assert(
I.getOperand(4).isReg());
2240 Register Acc =
I.getOperand(2).getReg();
2246 Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;
2250 for (
unsigned i = 0; i < 4; i++) {
2252 Register AElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2263 Register BElt =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2283 Register MaskMul =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2295 i < 3 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
2311bool SPIRVInstructionSelector::selectSaturate(
Register ResVReg,
2313 MachineInstr &
I)
const {
2314 assert(
I.getNumOperands() == 3);
2315 assert(
I.getOperand(2).isReg());
2317 Register VZero = buildZerosValF(ResType,
I);
2318 Register VOne = buildOnesValF(ResType,
I);
2320 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2323 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2325 .
addUse(
I.getOperand(2).getReg())
2331bool SPIRVInstructionSelector::selectSign(
Register ResVReg,
2333 MachineInstr &
I)
const {
2334 assert(
I.getNumOperands() == 3);
2335 assert(
I.getOperand(2).isReg());
2337 Register InputRegister =
I.getOperand(2).getReg();
2339 auto &
DL =
I.getDebugLoc();
2349 bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth;
2351 auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign;
2353 ?
MRI->createVirtualRegister(&SPIRV::IDRegClass)
2360 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
2365 if (NeedsConversion) {
2366 auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert;
2377bool SPIRVInstructionSelector::selectWaveOpInst(
Register ResVReg,
2380 unsigned Opcode)
const {
2384 auto BMI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2390 for (
unsigned J = 2; J <
I.getNumOperands(); J++) {
2391 BMI.addUse(
I.getOperand(J).getReg());
2397bool SPIRVInstructionSelector::selectWaveActiveCountBits(
2403 bool Result = selectWaveOpInst(BallotReg, BallotType,
I,
2404 SPIRV::OpGroupNonUniformBallot);
2408 TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
2413 .
addImm(SPIRV::GroupOperation::Reduce)
2420bool SPIRVInstructionSelector::selectWaveReduceMax(
Register ResVReg,
2423 bool IsUnsigned)
const {
2424 assert(
I.getNumOperands() == 3);
2425 assert(
I.getOperand(2).isReg());
2427 Register InputRegister =
I.getOperand(2).getReg();
2436 auto IntegerOpcodeType =
2437 IsUnsigned ? SPIRV::OpGroupNonUniformUMax : SPIRV::OpGroupNonUniformSMax;
2438 auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMax : IntegerOpcodeType;
2439 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2444 .
addImm(SPIRV::GroupOperation::Reduce)
2445 .
addUse(
I.getOperand(2).getReg())
2449bool SPIRVInstructionSelector::selectWaveReduceSum(
Register ResVReg,
2451 MachineInstr &
I)
const {
2452 assert(
I.getNumOperands() == 3);
2453 assert(
I.getOperand(2).isReg());
2455 Register InputRegister =
I.getOperand(2).getReg();
2465 IsFloatTy ? SPIRV::OpGroupNonUniformFAdd : SPIRV::OpGroupNonUniformIAdd;
2466 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2471 .
addImm(SPIRV::GroupOperation::Reduce)
2472 .
addUse(
I.getOperand(2).getReg());
2475bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
2477 MachineInstr &
I)
const {
2479 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
2482 .
addUse(
I.getOperand(1).getReg())
2486bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
2488 MachineInstr &
I)
const {
2494 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
2496 Register OpReg =
I.getOperand(1).getReg();
2497 if (MachineInstr *Def =
MRI->getVRegDef(OpReg)) {
2498 if (
Def->getOpcode() == TargetOpcode::COPY)
2499 Def =
MRI->getVRegDef(
Def->getOperand(1).getReg());
2501 switch (
Def->getOpcode()) {
2502 case SPIRV::ASSIGN_TYPE:
2503 if (MachineInstr *AssignToDef =
2504 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
2505 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2506 Reg =
Def->getOperand(2).getReg();
2509 case SPIRV::OpUndef:
2510 Reg =
Def->getOperand(1).getReg();
2513 unsigned DestOpCode;
2515 DestOpCode = SPIRV::OpConstantNull;
2517 DestOpCode = TargetOpcode::COPY;
2520 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
2521 .
addDef(
I.getOperand(0).getReg())
2528bool SPIRVInstructionSelector::selectBuildVector(
Register ResVReg,
2530 MachineInstr &
I)
const {
2532 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2534 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2538 if (
I.getNumExplicitOperands() -
I.getNumExplicitDefs() !=
N)
2543 for (
unsigned i =
I.getNumExplicitDefs();
2544 i <
I.getNumExplicitOperands() && IsConst; ++i)
2548 if (!IsConst &&
N < 2)
2550 "There must be at least two constituent operands in a vector");
2553 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2554 TII.get(IsConst ? SPIRV::OpConstantComposite
2555 : SPIRV::OpCompositeConstruct))
2558 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
2559 MIB.
addUse(
I.getOperand(i).getReg());
2563bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
2565 MachineInstr &
I)
const {
2567 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2569 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
2575 if (!
I.getOperand(
OpIdx).isReg())
2582 if (!IsConst &&
N < 2)
2584 "There must be at least two constituent operands in a vector");
2587 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
2588 TII.get(IsConst ? SPIRV::OpConstantComposite
2589 : SPIRV::OpCompositeConstruct))
2592 for (
unsigned i = 0; i <
N; ++i)
2597bool SPIRVInstructionSelector::selectDiscard(
Register ResVReg,
2599 MachineInstr &
I)
const {
2604 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
2606 Opcode = SPIRV::OpDemoteToHelperInvocation;
2608 Opcode = SPIRV::OpKill;
2610 if (MachineInstr *NextI =
I.getNextNode()) {
2612 NextI->removeFromParent();
2617 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2621bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
2624 MachineInstr &
I)
const {
2625 Register Cmp0 =
I.getOperand(2).getReg();
2626 Register Cmp1 =
I.getOperand(3).getReg();
2629 "CMP operands should have the same type");
2630 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
2639bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
2641 MachineInstr &
I)
const {
2642 auto Pred =
I.getOperand(1).getPredicate();
2645 Register CmpOperand =
I.getOperand(2).getReg();
2652 return selectCmp(ResVReg, ResType, CmpOpc,
I);
2655std::pair<Register, bool>
2656SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &
I,
2662 auto ConstInt = ConstantInt::get(LLVMTy, Val);
2670 ?
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2673 :
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
2676 .
addImm(APInt(32, Val).getZExtValue());
2678 GR.
add(ConstInt,
MI);
2683bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
2685 MachineInstr &
I)
const {
2687 return selectCmp(ResVReg, ResType, CmpOp,
I);
2691 MachineInstr &
I)
const {
2694 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2700 MachineInstr &
I)
const {
2704 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2710 MachineInstr &
I)
const {
2714 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2721 MachineInstr &
I)
const {
2725 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
2730bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
2732 MachineInstr &
I)
const {
2733 Register SelectFirstArg =
I.getOperand(2).getReg();
2734 Register SelectSecondArg =
I.getOperand(3).getReg();
2743 SPIRV::OpTypeVector;
2750 Opcode = IsScalarBool ? SPIRV::OpSelectVFSCond : SPIRV::OpSelectVFVCond;
2751 }
else if (IsPtrTy) {
2752 Opcode = IsScalarBool ? SPIRV::OpSelectVPSCond : SPIRV::OpSelectVPVCond;
2754 Opcode = IsScalarBool ? SPIRV::OpSelectVISCond : SPIRV::OpSelectVIVCond;
2758 Opcode = IsScalarBool ? SPIRV::OpSelectSFSCond : SPIRV::OpSelectVFVCond;
2759 }
else if (IsPtrTy) {
2760 Opcode = IsScalarBool ? SPIRV::OpSelectSPSCond : SPIRV::OpSelectVPVCond;
2762 Opcode = IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
2765 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
2768 .
addUse(
I.getOperand(1).getReg())
2774bool SPIRVInstructionSelector::selectSelectDefaultArgs(
Register ResVReg,
2777 bool IsSigned)
const {
2779 Register ZeroReg = buildZerosVal(ResType,
I);
2780 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
2784 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
2785 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
2788 .
addUse(
I.getOperand(1).getReg())
2794bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
2796 MachineInstr &
I,
bool IsSigned,
2797 unsigned Opcode)
const {
2798 Register SrcReg =
I.getOperand(1).getReg();
2804 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
2809 selectSelectDefaultArgs(SrcReg, TmpType,
I,
false);
2811 return selectOpWithSrcs(ResVReg, ResType,
I, {SrcReg}, Opcode);
2814bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
2816 MachineInstr &
I,
bool IsSigned)
const {
2817 Register SrcReg =
I.getOperand(1).getReg();
2819 return selectSelectDefaultArgs(ResVReg, ResType,
I, IsSigned);
2822 if (SrcType == ResType)
2823 return BuildCOPY(ResVReg, SrcReg,
I);
2825 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
2826 return selectUnOp(ResVReg, ResType,
I, Opcode);
2829bool SPIRVInstructionSelector::selectSUCmp(
Register ResVReg,
2832 bool IsSigned)
const {
2833 MachineIRBuilder MIRBuilder(
I);
2834 MachineRegisterInfo *
MRI = MIRBuilder.getMRI();
2849 TII.get(IsSigned ? SPIRV::OpSLessThanEqual
2850 : SPIRV::OpULessThanEqual))
2853 .
addUse(
I.getOperand(1).getReg())
2854 .
addUse(
I.getOperand(2).getReg())
2860 TII.get(IsSigned ? SPIRV::OpSLessThan : SPIRV::OpULessThan))
2863 .
addUse(
I.getOperand(1).getReg())
2864 .
addUse(
I.getOperand(2).getReg())
2872 unsigned SelectOpcode =
2873 N > 1 ? SPIRV::OpSelectVIVCond : SPIRV::OpSelectSISCond;
2878 .
addUse(buildOnesVal(
true, ResType,
I))
2879 .
addUse(buildZerosVal(ResType,
I))
2886 .
addUse(buildOnesVal(
false, ResType,
I))
2890bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
2897 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
2898 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
2900 Register One = buildOnesVal(
false, IntTy,
I);
2916bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
2918 MachineInstr &
I)
const {
2919 Register IntReg =
I.getOperand(1).getReg();
2922 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
2923 if (ArgType == ResType)
2924 return BuildCOPY(ResVReg, IntReg,
I);
2926 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
2927 return selectUnOp(ResVReg, ResType,
I, Opcode);
2930bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
2932 MachineInstr &
I)
const {
2933 unsigned Opcode =
I.getOpcode();
2934 unsigned TpOpcode = ResType->
getOpcode();
2936 if (TpOpcode == SPIRV::OpTypePointer || TpOpcode == SPIRV::OpTypeEvent) {
2937 assert(Opcode == TargetOpcode::G_CONSTANT &&
2938 I.getOperand(1).getCImm()->isZero());
2939 MachineBasicBlock &DepMBB =
I.getMF()->front();
2942 }
else if (Opcode == TargetOpcode::G_FCONSTANT) {
2949 return Reg == ResVReg ?
true : BuildCOPY(ResVReg,
Reg,
I);
2952bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
2954 MachineInstr &
I)
const {
2955 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
2961bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
2963 MachineInstr &
I)
const {
2965 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
2969 .
addUse(
I.getOperand(3).getReg())
2971 .
addUse(
I.getOperand(2).getReg());
2972 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
2977bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
2979 MachineInstr &
I)
const {
2981 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2984 .
addUse(
I.getOperand(2).getReg());
2985 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
2990bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
2992 MachineInstr &
I)
const {
2994 return selectInsertVal(ResVReg, ResType,
I);
2996 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
2999 .
addUse(
I.getOperand(2).getReg())
3000 .
addUse(
I.getOperand(3).getReg())
3001 .
addUse(
I.getOperand(4).getReg())
3005bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
3007 MachineInstr &
I)
const {
3009 return selectExtractVal(ResVReg, ResType,
I);
3011 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
3014 .
addUse(
I.getOperand(2).getReg())
3015 .
addUse(
I.getOperand(3).getReg())
3019bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
3021 MachineInstr &
I)
const {
3022 const bool IsGEPInBounds =
I.getOperand(2).getImm();
3028 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
3029 : SPIRV::OpAccessChain)
3030 : (IsGEPInBounds ?
SPIRV::OpInBoundsPtrAccessChain
3031 :
SPIRV::OpPtrAccessChain);
3033 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
3037 .
addUse(
I.getOperand(3).getReg());
3039 const unsigned StartingIndex =
3040 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
3043 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
3044 Res.addUse(
I.getOperand(i).getReg());
3045 return Res.constrainAllUses(
TII,
TRI, RBI);
3049bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
3052 unsigned Lim =
I.getNumExplicitOperands();
3053 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
3054 Register OpReg =
I.getOperand(i).getReg();
3055 MachineInstr *OpDefine =
MRI->getVRegDef(OpReg);
3057 SmallPtrSet<SPIRVType *, 4> Visited;
3058 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
3059 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
3066 MachineFunction *MF =
I.getMF();
3078 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3079 TII.get(SPIRV::OpSpecConstantOp))
3082 .
addImm(
static_cast<uint32_t
>(SPIRV::Opcode::Bitcast))
3084 GR.
add(OpDefine, MIB);
3092bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
3094 MachineInstr &
I)
const {
3098 case Intrinsic::spv_load:
3099 return selectLoad(ResVReg, ResType,
I);
3100 case Intrinsic::spv_store:
3101 return selectStore(
I);
3102 case Intrinsic::spv_extractv:
3103 return selectExtractVal(ResVReg, ResType,
I);
3104 case Intrinsic::spv_insertv:
3105 return selectInsertVal(ResVReg, ResType,
I);
3106 case Intrinsic::spv_extractelt:
3107 return selectExtractElt(ResVReg, ResType,
I);
3108 case Intrinsic::spv_insertelt:
3109 return selectInsertElt(ResVReg, ResType,
I);
3110 case Intrinsic::spv_gep:
3111 return selectGEP(ResVReg, ResType,
I);
3112 case Intrinsic::spv_unref_global:
3113 case Intrinsic::spv_init_global: {
3114 MachineInstr *
MI =
MRI->getVRegDef(
I.getOperand(1).getReg());
3115 MachineInstr *Init =
I.getNumExplicitOperands() > 2
3116 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
3119 Register GVarVReg =
MI->getOperand(0).getReg();
3120 bool Res = selectGlobalValue(GVarVReg, *
MI, Init);
3124 if (
MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
3126 MI->removeFromParent();
3130 case Intrinsic::spv_undef: {
3131 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
3136 case Intrinsic::spv_const_composite: {
3138 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
3144 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
3146 MachineIRBuilder MIR(
I);
3148 MIR, SPIRV::OpConstantComposite, 3,
3149 SPIRV::OpConstantCompositeContinuedINTEL, CompositeArgs, ResVReg,
3151 for (
auto *Instr : Instructions) {
3152 Instr->setDebugLoc(
I.getDebugLoc());
3158 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
3164 case Intrinsic::spv_assign_name: {
3165 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
3166 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
3167 for (
unsigned i =
I.getNumExplicitDefs() + 2;
3168 i <
I.getNumExplicitOperands(); ++i) {
3169 MIB.
addImm(
I.getOperand(i).getImm());
3173 case Intrinsic::spv_switch: {
3174 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
3175 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3176 if (
I.getOperand(i).isReg())
3177 MIB.
addReg(
I.getOperand(i).getReg());
3178 else if (
I.getOperand(i).isCImm())
3179 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
3180 else if (
I.getOperand(i).isMBB())
3181 MIB.
addMBB(
I.getOperand(i).getMBB());
3187 case Intrinsic::spv_loop_merge: {
3188 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoopMerge));
3189 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
3190 if (
I.getOperand(i).isMBB())
3191 MIB.
addMBB(
I.getOperand(i).getMBB());
3197 case Intrinsic::spv_selection_merge: {
3199 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSelectionMerge));
3200 assert(
I.getOperand(1).isMBB() &&
3201 "operand 1 to spv_selection_merge must be a basic block");
3202 MIB.
addMBB(
I.getOperand(1).getMBB());
3203 MIB.
addImm(getSelectionOperandForImm(
I.getOperand(2).getImm()));
3206 case Intrinsic::spv_cmpxchg:
3207 return selectAtomicCmpXchg(ResVReg, ResType,
I);
3208 case Intrinsic::spv_unreachable:
3209 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable))
3211 case Intrinsic::spv_alloca:
3212 return selectFrameIndex(ResVReg, ResType,
I);
3213 case Intrinsic::spv_alloca_array:
3214 return selectAllocaArray(ResVReg, ResType,
I);
3215 case Intrinsic::spv_assume:
3217 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
3218 .
addUse(
I.getOperand(1).getReg())
3221 case Intrinsic::spv_expect:
3223 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
3226 .
addUse(
I.getOperand(2).getReg())
3227 .
addUse(
I.getOperand(3).getReg())
3230 case Intrinsic::arithmetic_fence:
3233 TII.get(SPIRV::OpArithmeticFenceEXT))
3236 .
addUse(
I.getOperand(2).getReg())
3239 return BuildCOPY(ResVReg,
I.getOperand(2).getReg(),
I);
3241 case Intrinsic::spv_thread_id:
3247 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalInvocationId, ResVReg,
3249 case Intrinsic::spv_thread_id_in_group:
3255 return loadVec3BuiltinInputID(SPIRV::BuiltIn::LocalInvocationId, ResVReg,
3257 case Intrinsic::spv_group_id:
3263 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
3265 case Intrinsic::spv_flattened_thread_id_in_group:
3272 return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
3274 case Intrinsic::spv_workgroup_size:
3275 return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupSize, ResVReg,
3277 case Intrinsic::spv_global_size:
3278 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalSize, ResVReg, ResType,
3280 case Intrinsic::spv_global_offset:
3281 return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalOffset, ResVReg,
3283 case Intrinsic::spv_num_workgroups:
3284 return loadVec3BuiltinInputID(SPIRV::BuiltIn::NumWorkgroups, ResVReg,
3286 case Intrinsic::spv_subgroup_size:
3287 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupSize, ResVReg, ResType,
3289 case Intrinsic::spv_num_subgroups:
3290 return loadBuiltinInputID(SPIRV::BuiltIn::NumSubgroups, ResVReg, ResType,
3292 case Intrinsic::spv_subgroup_id:
3293 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupId, ResVReg, ResType,
I);
3294 case Intrinsic::spv_subgroup_local_invocation_id:
3295 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupLocalInvocationId,
3296 ResVReg, ResType,
I);
3297 case Intrinsic::spv_subgroup_max_size:
3298 return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupMaxSize, ResVReg, ResType,
3300 case Intrinsic::spv_fdot:
3301 return selectFloatDot(ResVReg, ResType,
I);
3302 case Intrinsic::spv_udot:
3303 case Intrinsic::spv_sdot:
3304 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3306 return selectIntegerDot(ResVReg, ResType,
I,
3307 IID == Intrinsic::spv_sdot);
3308 return selectIntegerDotExpansion(ResVReg, ResType,
I);
3309 case Intrinsic::spv_dot4add_i8packed:
3310 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3312 return selectDot4AddPacked<true>(ResVReg, ResType,
I);
3313 return selectDot4AddPackedExpansion<true>(ResVReg, ResType,
I);
3314 case Intrinsic::spv_dot4add_u8packed:
3315 if (STI.
canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
3317 return selectDot4AddPacked<false>(ResVReg, ResType,
I);
3318 return selectDot4AddPackedExpansion<false>(ResVReg, ResType,
I);
3319 case Intrinsic::spv_all:
3320 return selectAll(ResVReg, ResType,
I);
3321 case Intrinsic::spv_any:
3322 return selectAny(ResVReg, ResType,
I);
3323 case Intrinsic::spv_cross:
3324 return selectExtInst(ResVReg, ResType,
I, CL::cross, GL::Cross);
3325 case Intrinsic::spv_distance:
3326 return selectExtInst(ResVReg, ResType,
I, CL::distance, GL::Distance);
3327 case Intrinsic::spv_lerp:
3328 return selectExtInst(ResVReg, ResType,
I, CL::mix, GL::FMix);
3329 case Intrinsic::spv_length:
3330 return selectExtInst(ResVReg, ResType,
I, CL::length, GL::Length);
3331 case Intrinsic::spv_degrees:
3332 return selectExtInst(ResVReg, ResType,
I, CL::degrees, GL::Degrees);
3333 case Intrinsic::spv_faceforward:
3334 return selectExtInst(ResVReg, ResType,
I, GL::FaceForward);
3335 case Intrinsic::spv_frac:
3336 return selectExtInst(ResVReg, ResType,
I, CL::fract, GL::Fract);
3337 case Intrinsic::spv_isinf:
3338 return selectOpIsInf(ResVReg, ResType,
I);
3339 case Intrinsic::spv_isnan:
3340 return selectOpIsNan(ResVReg, ResType,
I);
3341 case Intrinsic::spv_normalize:
3342 return selectExtInst(ResVReg, ResType,
I, CL::normalize, GL::Normalize);
3343 case Intrinsic::spv_refract:
3344 return selectExtInst(ResVReg, ResType,
I, GL::Refract);
3345 case Intrinsic::spv_reflect:
3346 return selectExtInst(ResVReg, ResType,
I, GL::Reflect);
3347 case Intrinsic::spv_rsqrt:
3348 return selectExtInst(ResVReg, ResType,
I, CL::rsqrt, GL::InverseSqrt);
3349 case Intrinsic::spv_sign:
3350 return selectSign(ResVReg, ResType,
I);
3351 case Intrinsic::spv_smoothstep:
3352 return selectExtInst(ResVReg, ResType,
I, CL::smoothstep, GL::SmoothStep);
3353 case Intrinsic::spv_firstbituhigh:
3354 return selectFirstBitHigh(ResVReg, ResType,
I,
false);
3355 case Intrinsic::spv_firstbitshigh:
3356 return selectFirstBitHigh(ResVReg, ResType,
I,
true);
3357 case Intrinsic::spv_firstbitlow:
3358 return selectFirstBitLow(ResVReg, ResType,
I);
3359 case Intrinsic::spv_group_memory_barrier_with_group_sync: {
3361 auto MemSemConstant =
3362 buildI32Constant(SPIRV::MemorySemantics::SequentiallyConsistent,
I);
3363 Register MemSemReg = MemSemConstant.first;
3364 Result &= MemSemConstant.second;
3365 auto ScopeConstant = buildI32Constant(SPIRV::Scope::Workgroup,
I);
3366 Register ScopeReg = ScopeConstant.first;
3367 Result &= ScopeConstant.second;
3370 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpControlBarrier))
3376 case Intrinsic::spv_generic_cast_to_ptr_explicit: {
3377 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 1).getReg();
3378 SPIRV::StorageClass::StorageClass ResSC =
3382 "Generic storage class");
3384 TII.get(SPIRV::OpGenericCastToPtrExplicit))
3391 case Intrinsic::spv_lifetime_start:
3392 case Intrinsic::spv_lifetime_end: {
3393 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
3394 : SPIRV::OpLifetimeStop;
3395 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
3396 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
3404 case Intrinsic::spv_saturate:
3405 return selectSaturate(ResVReg, ResType,
I);
3406 case Intrinsic::spv_nclamp:
3407 return selectExtInst(ResVReg, ResType,
I, CL::fclamp, GL::NClamp);
3408 case Intrinsic::spv_uclamp:
3409 return selectExtInst(ResVReg, ResType,
I, CL::u_clamp, GL::UClamp);
3410 case Intrinsic::spv_sclamp:
3411 return selectExtInst(ResVReg, ResType,
I, CL::s_clamp, GL::SClamp);
3412 case Intrinsic::spv_wave_active_countbits:
3413 return selectWaveActiveCountBits(ResVReg, ResType,
I);
3414 case Intrinsic::spv_wave_all:
3415 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAll);
3416 case Intrinsic::spv_wave_any:
3417 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformAny);
3418 case Intrinsic::spv_wave_is_first_lane:
3419 return selectWaveOpInst(ResVReg, ResType,
I, SPIRV::OpGroupNonUniformElect);
3420 case Intrinsic::spv_wave_reduce_umax:
3421 return selectWaveReduceMax(ResVReg, ResType,
I,
true);
3422 case Intrinsic::spv_wave_reduce_max:
3423 return selectWaveReduceMax(ResVReg, ResType,
I,
false);
3424 case Intrinsic::spv_wave_reduce_sum:
3425 return selectWaveReduceSum(ResVReg, ResType,
I);
3426 case Intrinsic::spv_wave_readlane:
3427 return selectWaveOpInst(ResVReg, ResType,
I,
3428 SPIRV::OpGroupNonUniformShuffle);
3429 case Intrinsic::spv_step:
3430 return selectExtInst(ResVReg, ResType,
I, CL::step, GL::Step);
3431 case Intrinsic::spv_radians:
3432 return selectExtInst(ResVReg, ResType,
I, CL::radians, GL::Radians);
3436 case Intrinsic::instrprof_increment:
3437 case Intrinsic::instrprof_increment_step:
3438 case Intrinsic::instrprof_value_profile:
3441 case Intrinsic::spv_value_md:
3443 case Intrinsic::spv_resource_handlefrombinding: {
3444 return selectHandleFromBinding(ResVReg, ResType,
I);
3446 case Intrinsic::spv_resource_store_typedbuffer: {
3447 return selectImageWriteIntrinsic(
I);
3449 case Intrinsic::spv_resource_load_typedbuffer: {
3450 return selectReadImageIntrinsic(ResVReg, ResType,
I);
3452 case Intrinsic::spv_resource_getpointer: {
3453 return selectResourceGetPointer(ResVReg, ResType,
I);
3455 case Intrinsic::spv_discard: {
3456 return selectDiscard(ResVReg, ResType,
I);
3459 std::string DiagMsg;
3460 raw_string_ostream OS(DiagMsg);
3462 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
3469bool SPIRVInstructionSelector::selectHandleFromBinding(
Register &ResVReg,
3471 MachineInstr &
I)
const {
3474 if (ResType->
getOpcode() == SPIRV::OpTypeImage)
3481bool SPIRVInstructionSelector::selectReadImageIntrinsic(
3490 Register ImageReg =
I.getOperand(2).getReg();
3492 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
3498 Register IdxReg =
I.getOperand(3).getReg();
3500 MachineInstr &Pos =
I;
3502 return generateImageRead(ResVReg, ResType, NewImageReg, IdxReg, Loc, Pos);
3505bool SPIRVInstructionSelector::generateImageRead(
Register &ResVReg,
3509 MachineInstr &Pos)
const {
3512 "ImageReg is not an image type.");
3513 bool IsSignedInteger =
3517 if (ResultSize == 4) {
3524 if (IsSignedInteger)
3529 SPIRVType *ReadType = widenTypeToVec4(ResType, Pos);
3536 if (IsSignedInteger)
3542 if (ResultSize == 1) {
3544 TII.get(SPIRV::OpCompositeExtract))
3551 return extractSubvector(ResVReg, ResType, ReadReg, Pos);
3554bool SPIRVInstructionSelector::selectResourceGetPointer(
3556 Register ResourcePtr =
I.getOperand(2).getReg();
3558 if (RegType->
getOpcode() == SPIRV::OpTypeImage) {
3567 MachineIRBuilder MIRBuilder(
I);
3569 Register IndexReg =
I.getOperand(3).getReg();
3572 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3573 TII.get(SPIRV::OpAccessChain))
3582bool SPIRVInstructionSelector::extractSubvector(
3584 MachineInstr &InsertionPoint)
const {
3586 [[maybe_unused]] uint64_t InputSize =
3589 assert(InputSize > 1 &&
"The input must be a vector.");
3590 assert(ResultSize > 1 &&
"The result must be a vector.");
3591 assert(ResultSize < InputSize &&
3592 "Cannot extract more element than there are in the input.");
3595 const TargetRegisterClass *ScalarRegClass = GR.
getRegClass(ScalarType);
3596 for (uint64_t
I = 0;
I < ResultSize;
I++) {
3597 Register ComponentReg =
MRI->createVirtualRegister(ScalarRegClass);
3600 TII.get(SPIRV::OpCompositeExtract))
3611 MachineInstrBuilder MIB =
BuildMI(*InsertionPoint.
getParent(), InsertionPoint,
3613 TII.get(SPIRV::OpCompositeConstruct))
3617 for (
Register ComponentReg : ComponentRegisters)
3618 MIB.
addUse(ComponentReg);
3622bool SPIRVInstructionSelector::selectImageWriteIntrinsic(
3623 MachineInstr &
I)
const {
3630 Register ImageReg =
I.getOperand(1).getReg();
3632 Register NewImageReg =
MRI->createVirtualRegister(
MRI->getRegClass(ImageReg));
3638 Register CoordinateReg =
I.getOperand(2).getReg();
3639 Register DataReg =
I.getOperand(3).getReg();
3642 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3643 TII.get(SPIRV::OpImageWrite))
3650Register SPIRVInstructionSelector::buildPointerToResource(
3651 const SPIRVType *SpirvResType, SPIRV::StorageClass::StorageClass SC,
3652 uint32_t Set, uint32_t
Binding, uint32_t ArraySize,
Register IndexReg,
3653 bool IsNonUniform, StringRef Name, MachineIRBuilder MIRBuilder)
const {
3655 if (ArraySize == 1) {
3659 "SpirvResType did not have an explicit layout.");
3664 const Type *VarType = ArrayType::get(
const_cast<Type *
>(ResType), ArraySize);
3668 VarPointerType, Set,
Binding, Name, MIRBuilder);
3677 buildOpDecorate(IndexReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
3678 buildOpDecorate(AcReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
3690bool SPIRVInstructionSelector::selectFirstBitSet16(
3692 unsigned ExtendOpcode,
unsigned BitSetOpcode)
const {
3694 bool Result = selectOpWithSrcs(ExtReg, ResType,
I, {
I.getOperand(2).getReg()},
3698 selectFirstBitSet32(ResVReg, ResType,
I, ExtReg, BitSetOpcode);
3701bool SPIRVInstructionSelector::selectFirstBitSet32(
3703 Register SrcReg,
unsigned BitSetOpcode)
const {
3704 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
3707 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
3713bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
3715 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
3722 assert(ComponentCount < 5 &&
"Vec 5+ will generate invalid SPIR-V ops");
3724 MachineIRBuilder MIRBuilder(
I);
3732 std::vector<Register> PartialRegs;
3735 unsigned CurrentComponent = 0;
3736 for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
3742 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3743 TII.get(SPIRV::OpVectorShuffle))
3748 .
addImm(CurrentComponent)
3749 .
addImm(CurrentComponent + 1);
3757 if (!selectFirstBitSet64(SubVecBitSetReg, Vec2ResType,
I, BitSetResult,
3758 BitSetOpcode, SwapPrimarySide))
3761 PartialRegs.push_back(SubVecBitSetReg);
3765 if (CurrentComponent != ComponentCount) {
3771 if (!selectOpWithSrcs(FinalElemReg, I64Type,
I, {SrcReg, ConstIntLastIdx},
3772 SPIRV::OpVectorExtractDynamic))
3778 if (!selectFirstBitSet64(FinalElemBitSetReg,
BaseType,
I, FinalElemReg,
3779 BitSetOpcode, SwapPrimarySide))
3782 PartialRegs.push_back(FinalElemBitSetReg);
3787 return selectOpWithSrcs(ResVReg, ResType,
I, std::move(PartialRegs),
3788 SPIRV::OpCompositeConstruct);
3791bool SPIRVInstructionSelector::selectFirstBitSet64(
3793 Register SrcReg,
unsigned BitSetOpcode,
bool SwapPrimarySide)
const {
3806 if (ComponentCount > 2) {
3807 return selectFirstBitSet64Overflow(ResVReg, ResType,
I, SrcReg,
3808 BitSetOpcode, SwapPrimarySide);
3812 MachineIRBuilder MIRBuilder(
I);
3814 BaseType, 2 * ComponentCount, MIRBuilder,
false);
3818 if (!selectOpWithSrcs(BitcastReg, PostCastType,
I, {SrcReg},
3824 if (!selectFirstBitSet32(FBSReg, PostCastType,
I, BitcastReg, BitSetOpcode))
3831 bool IsScalarRes = ResType->
getOpcode() != SPIRV::OpTypeVector;
3834 if (!selectOpWithSrcs(HighReg, ResType,
I, {FBSReg, ConstIntZero},
3835 SPIRV::OpVectorExtractDynamic))
3837 if (!selectOpWithSrcs(LowReg, ResType,
I, {FBSReg, ConstIntOne},
3838 SPIRV::OpVectorExtractDynamic))
3842 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3843 TII.get(SPIRV::OpVectorShuffle))
3851 for (
unsigned J = 0; J < ComponentCount * 2; J += 2) {
3858 MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
3859 TII.get(SPIRV::OpVectorShuffle))
3867 for (
unsigned J = 1; J < ComponentCount * 2; J += 2) {
3888 SelectOp = SPIRV::OpSelectSISCond;
3889 AddOp = SPIRV::OpIAddS;
3897 SelectOp = SPIRV::OpSelectVIVCond;
3898 AddOp = SPIRV::OpIAddV;
3908 if (SwapPrimarySide) {
3909 PrimaryReg = LowReg;
3910 SecondaryReg = HighReg;
3911 PrimaryShiftReg = Reg0;
3912 SecondaryShiftReg = Reg32;
3917 if (!selectOpWithSrcs(BReg, BoolType,
I, {PrimaryReg, NegOneReg},
3923 if (!selectOpWithSrcs(TmpReg, ResType,
I, {
BReg, SecondaryReg, PrimaryReg},
3929 if (!selectOpWithSrcs(ValReg, ResType,
I,
3930 {
BReg, SecondaryShiftReg, PrimaryShiftReg}, SelectOp))
3933 return selectOpWithSrcs(ResVReg, ResType,
I, {ValReg, TmpReg}, AddOp);
3936bool SPIRVInstructionSelector::selectFirstBitHigh(
Register ResVReg,
3939 bool IsSigned)
const {
3941 Register OpReg =
I.getOperand(2).getReg();
3944 unsigned ExtendOpcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
3945 unsigned BitSetOpcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;
3949 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
3951 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
3953 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
3957 "spv_firstbituhigh and spv_firstbitshigh only support 16,32,64 bits.");
3961bool SPIRVInstructionSelector::selectFirstBitLow(
Register ResVReg,
3963 MachineInstr &
I)
const {
3965 Register OpReg =
I.getOperand(2).getReg();
3970 unsigned ExtendOpcode = SPIRV::OpUConvert;
3971 unsigned BitSetOpcode = GL::FindILsb;
3975 return selectFirstBitSet16(ResVReg, ResType,
I, ExtendOpcode, BitSetOpcode);
3977 return selectFirstBitSet32(ResVReg, ResType,
I, OpReg, BitSetOpcode);
3979 return selectFirstBitSet64(ResVReg, ResType,
I, OpReg, BitSetOpcode,
3986bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
3988 MachineInstr &
I)
const {
3992 bool Res =
BuildMI(BB,
I,
I.getDebugLoc(),
3993 TII.get(SPIRV::OpVariableLengthArrayINTEL))
3996 .
addUse(
I.getOperand(2).getReg())
3999 unsigned Alignment =
I.getOperand(3).getImm();
4005bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
4007 MachineInstr &
I)
const {
4011 bool Res =
BuildMI(*It->getParent(), It, It->getDebugLoc(),
4012 TII.get(SPIRV::OpVariable))
4015 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function))
4018 unsigned Alignment =
I.getOperand(2).getImm();
4025bool SPIRVInstructionSelector::selectBranch(MachineInstr &
I)
const {
4030 const MachineInstr *PrevI =
I.getPrevNode();
4032 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
4033 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4036 .
addMBB(
I.getOperand(0).getMBB())
4040 .
addMBB(
I.getOperand(0).getMBB())
4044bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &
I)
const {
4055 const MachineInstr *NextI =
I.getNextNode();
4057 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
4063 MachineBasicBlock *NextMBB =
I.getMF()->getBlockNumbered(NextMBBNum);
4064 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
4065 .
addUse(
I.getOperand(0).getReg())
4066 .
addMBB(
I.getOperand(1).getMBB())
4071bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
4073 MachineInstr &
I)
const {
4074 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
4077 const unsigned NumOps =
I.getNumOperands();
4078 for (
unsigned i = 1; i <
NumOps; i += 2) {
4079 MIB.
addUse(
I.getOperand(i + 0).getReg());
4080 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
4088bool SPIRVInstructionSelector::selectGlobalValue(
4089 Register ResVReg, MachineInstr &
I,
const MachineInstr *Init)
const {
4091 MachineIRBuilder MIRBuilder(
I);
4092 const GlobalValue *GV =
I.
getOperand(1).getGlobal();
4095 std::string GlobalIdent;
4097 unsigned &
ID = UnnamedGlobalIDs[GV];
4099 ID = UnnamedGlobalIDs.size();
4100 GlobalIdent =
"__unnamed_" + Twine(
ID).str();
4127 GVFun ? SPIRV::StorageClass::CodeSectionINTEL
4134 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4137 MRI->setRegClass(FuncVReg, &SPIRV::pIDRegClass);
4138 MachineInstrBuilder MIB1 =
4139 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
4142 MachineInstrBuilder MIB2 =
4144 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
4148 GR.
add(ConstVal, MIB2);
4154 MachineInstrBuilder MIB3 =
4155 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
4158 GR.
add(ConstVal, MIB3);
4161 assert(NewReg != ResVReg);
4162 return BuildCOPY(ResVReg, NewReg,
I);
4174 SPIRV::LinkageType::LinkageType LnkType =
4176 ? SPIRV::LinkageType::Import
4179 ? SPIRV::LinkageType::LinkOnceODR
4180 : SPIRV::LinkageType::Export);
4188 GlobalVar->isConstant(), HasLnkTy, LnkType, MIRBuilder,
true);
4192bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
4194 MachineInstr &
I)
const {
4196 return selectExtInst(ResVReg, ResType,
I, CL::log10);
4204 MachineIRBuilder MIRBuilder(
I);
4210 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4213 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::GLSL_std_450))
4215 .
add(
I.getOperand(1))
4220 ResType->
getOpcode() == SPIRV::OpTypeFloat);
4223 ResType->
getOpcode() == SPIRV::OpTypeVector
4230 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
4231 ? SPIRV::OpVectorTimesScalar
4241bool SPIRVInstructionSelector::selectModf(
Register ResVReg,
4243 MachineInstr &
I)
const {
4259 MachineIRBuilder MIRBuilder(
I);
4262 ResType, MIRBuilder, SPIRV::StorageClass::Function);
4274 MachineBasicBlock &EntryBB =
I.getMF()->front();
4278 BuildMI(EntryBB, VarPos,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
4281 .
addImm(
static_cast<uint32_t
>(SPIRV::StorageClass::Function));
4287 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
4290 .
addImm(
static_cast<uint32_t
>(SPIRV::InstructionSet::OpenCL_std))
4293 .
add(
I.getOperand(
I.getNumExplicitDefs()))
4297 Register IntegralPartReg =
I.getOperand(1).getReg();
4298 if (IntegralPartReg.
isValid()) {
4300 auto LoadMIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4309 assert(
false &&
"GLSL::Modf is deprecated.");
4320bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
4321 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4322 const SPIRVType *ResType, MachineInstr &
I)
const {
4323 MachineIRBuilder MIRBuilder(
I);
4327 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
4339 SPIRV::StorageClass::Input,
nullptr,
true,
false,
4340 SPIRV::LinkageType::Import, MIRBuilder,
false);
4343 MachineRegisterInfo *
MRI = MIRBuilder.
getMRI();
4344 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
4350 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4357 assert(
I.getOperand(2).isReg());
4358 const uint32_t ThreadId =
foldImm(
I.getOperand(2),
MRI);
4362 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
4372bool SPIRVInstructionSelector::loadBuiltinInputID(
4373 SPIRV::BuiltIn::BuiltIn BuiltInValue,
Register ResVReg,
4374 const SPIRVType *ResType, MachineInstr &
I)
const {
4375 MachineIRBuilder MIRBuilder(
I);
4377 ResType, MIRBuilder, SPIRV::StorageClass::Input);
4392 SPIRV::StorageClass::Input,
nullptr,
true,
false,
4393 SPIRV::LinkageType::Import, MIRBuilder,
false);
4396 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
4405 MachineInstr &
I)
const {
4406 MachineIRBuilder MIRBuilder(
I);
4407 if (
Type->getOpcode() != SPIRV::OpTypeVector)
4411 if (VectorSize == 4)
4419bool SPIRVInstructionSelector::loadHandleBeforePosition(
4421 MachineInstr &Pos)
const {
4424 Intrinsic::spv_resource_handlefrombinding);
4431 bool IsNonUniform =
false;
4435 bool IsStructuredBuffer = ResType->
getOpcode() == SPIRV::OpTypePointer;
4436 MachineIRBuilder MIRBuilder(HandleDef);
4438 SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::UniformConstant;
4440 if (IsStructuredBuffer) {
4446 buildPointerToResource(VarType, SC, Set,
Binding, ArraySize, IndexReg,
4447 IsNonUniform, Name, MIRBuilder);
4455 uint32_t LoadOpcode =
4456 IsStructuredBuffer ? SPIRV::OpCopyObject : SPIRV::OpLoad;
4459 TII.get(LoadOpcode))
4467InstructionSelector *
4471 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 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
bool hasPrivateLinkage() const
bool hasHiddenVisibility() const
bool isDeclarationForLinker() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
bool hasInternalLinkage() const
bool hasLinkOnceODRLinkage() const
@ 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
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)
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
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
Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, bool HasLinkageTy, SPIRV::LinkageType::LinkageType LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)
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.
#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
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.
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...
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...
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
static LLVM_ABI const fltSemantics & IEEEhalf() LLVM_READNONE