32#include "llvm/IR/IntrinsicsSPIRV.h"
56#define DEBUG_TYPE "spirv-isel"
59namespace CL = SPIRV::OpenCLExtInst;
60namespace GL = SPIRV::GLSLExtInst;
63 std::vector<std::pair<SPIRV::InstructionSet::InstructionSet, uint32_t>>;
67#define GET_GLOBALISEL_PREDICATE_BITSET
68#include "SPIRVGenGlobalISel.inc"
69#undef GET_GLOBALISEL_PREDICATE_BITSET
96#define GET_GLOBALISEL_PREDICATES_DECL
97#include "SPIRVGenGlobalISel.inc"
98#undef GET_GLOBALISEL_PREDICATES_DECL
100#define GET_GLOBALISEL_TEMPORARIES_DECL
101#include "SPIRVGenGlobalISel.inc"
102#undef GET_GLOBALISEL_TEMPORARIES_DECL
121 unsigned Opcode)
const;
123 unsigned Opcode)
const;
140 unsigned NegateOpcode = 0)
const;
196 bool IsSigned)
const;
198 bool IsSigned,
unsigned Opcode)
const;
200 bool IsSigned)
const;
240 GL::GLSLExtInst GLInst)
const;
259 const SPIRVType *ResType =
nullptr)
const;
273#define GET_GLOBALISEL_IMPL
274#include "SPIRVGenGlobalISel.inc"
275#undef GET_GLOBALISEL_IMPL
281 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
283#include
"SPIRVGenGlobalISel.inc"
286#include
"SPIRVGenGlobalISel.inc"
297 GR.setCurrentFunc(MF);
298 InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
303 if (HasVRegsReset == &MF)
308 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
310 LLT Ty =
MRI.getType(Reg);
316 for (
const auto &
MBB : MF) {
317 for (
const auto &
MI :
MBB) {
318 if (
MI.getOpcode() != SPIRV::ASSIGN_TYPE)
321 LLT DstType =
MRI.getType(DstReg);
323 LLT SrcType =
MRI.getType(SrcReg);
324 if (DstType != SrcType)
325 MRI.setType(DstReg,
MRI.getType(SrcReg));
329 if (DstRC != SrcRC && SrcRC)
330 MRI.setRegClass(DstReg, SrcRC);
341 resetVRegsType(*
I.getParent()->getParent());
343 assert(
I.getParent() &&
"Instruction should be in a basic block!");
344 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
349 if (Opcode == SPIRV::ASSIGN_TYPE) {
350 Register DstReg =
I.getOperand(0).getReg();
351 Register SrcReg =
I.getOperand(1).getReg();
352 auto *
Def =
MRI->getVRegDef(SrcReg);
354 if (
MRI->getType(DstReg).isPointer())
356 bool Res = selectImpl(
I, *CoverageInfo);
357 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
361 MRI->setRegClass(DstReg, &SPIRV::iIDRegClass);
362 MRI->replaceRegWith(SrcReg, DstReg);
363 I.removeFromParent();
365 }
else if (
I.getNumDefs() == 1) {
372 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
373 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
379 bool HasDefs =
I.getNumDefs() > 0;
381 SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) :
nullptr;
382 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
383 if (spvSelect(ResVReg, ResType,
I)) {
385 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
387 I.removeFromParent();
393bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
396 const unsigned Opcode =
I.getOpcode();
398 return selectImpl(
I, *CoverageInfo);
400 case TargetOpcode::G_CONSTANT:
401 return selectConst(ResVReg, ResType,
I.getOperand(1).getCImm()->getValue(),
403 case TargetOpcode::G_GLOBAL_VALUE:
404 return selectGlobalValue(ResVReg,
I);
405 case TargetOpcode::G_IMPLICIT_DEF:
406 return selectOpUndef(ResVReg, ResType,
I);
407 case TargetOpcode::G_FREEZE:
408 return selectFreeze(ResVReg, ResType,
I);
410 case TargetOpcode::G_INTRINSIC:
411 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
412 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
413 return selectIntrinsic(ResVReg, ResType,
I);
414 case TargetOpcode::G_BITREVERSE:
415 return selectBitreverse(ResVReg, ResType,
I);
417 case TargetOpcode::G_BUILD_VECTOR:
418 return selectBuildVector(ResVReg, ResType,
I);
419 case TargetOpcode::G_SPLAT_VECTOR:
420 return selectSplatVector(ResVReg, ResType,
I);
422 case TargetOpcode::G_SHUFFLE_VECTOR: {
424 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
426 .
addUse(GR.getSPIRVTypeID(ResType))
427 .
addUse(
I.getOperand(1).getReg())
428 .
addUse(
I.getOperand(2).getReg());
429 for (
auto V :
I.getOperand(3).getShuffleMask())
433 case TargetOpcode::G_MEMMOVE:
434 case TargetOpcode::G_MEMCPY:
435 case TargetOpcode::G_MEMSET:
436 return selectMemOperation(ResVReg,
I);
438 case TargetOpcode::G_ICMP:
439 return selectICmp(ResVReg, ResType,
I);
440 case TargetOpcode::G_FCMP:
441 return selectFCmp(ResVReg, ResType,
I);
443 case TargetOpcode::G_FRAME_INDEX:
444 return selectFrameIndex(ResVReg, ResType,
I);
446 case TargetOpcode::G_LOAD:
447 return selectLoad(ResVReg, ResType,
I);
448 case TargetOpcode::G_STORE:
449 return selectStore(
I);
451 case TargetOpcode::G_BR:
452 return selectBranch(
I);
453 case TargetOpcode::G_BRCOND:
454 return selectBranchCond(
I);
456 case TargetOpcode::G_PHI:
457 return selectPhi(ResVReg, ResType,
I);
459 case TargetOpcode::G_FPTOSI:
460 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
461 case TargetOpcode::G_FPTOUI:
462 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
464 case TargetOpcode::G_SITOFP:
465 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
466 case TargetOpcode::G_UITOFP:
467 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
469 case TargetOpcode::G_CTPOP:
470 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
471 case TargetOpcode::G_SMIN:
472 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
473 case TargetOpcode::G_UMIN:
474 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
476 case TargetOpcode::G_SMAX:
477 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
478 case TargetOpcode::G_UMAX:
479 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
481 case TargetOpcode::G_FMA:
482 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
484 case TargetOpcode::G_FPOW:
485 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
486 case TargetOpcode::G_FPOWI:
487 return selectExtInst(ResVReg, ResType,
I, CL::pown);
489 case TargetOpcode::G_FEXP:
490 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
491 case TargetOpcode::G_FEXP2:
492 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
494 case TargetOpcode::G_FLOG:
495 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
496 case TargetOpcode::G_FLOG2:
497 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
498 case TargetOpcode::G_FLOG10:
499 return selectLog10(ResVReg, ResType,
I);
501 case TargetOpcode::G_FABS:
502 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
503 case TargetOpcode::G_ABS:
504 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
506 case TargetOpcode::G_FMINNUM:
507 case TargetOpcode::G_FMINIMUM:
508 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
509 case TargetOpcode::G_FMAXNUM:
510 case TargetOpcode::G_FMAXIMUM:
511 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
513 case TargetOpcode::G_FCOPYSIGN:
514 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
516 case TargetOpcode::G_FCEIL:
517 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
518 case TargetOpcode::G_FFLOOR:
519 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
521 case TargetOpcode::G_FCOS:
522 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
523 case TargetOpcode::G_FSIN:
524 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
525 case TargetOpcode::G_FTAN:
526 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
527 case TargetOpcode::G_FACOS:
528 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
529 case TargetOpcode::G_FASIN:
530 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
531 case TargetOpcode::G_FATAN:
532 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
533 case TargetOpcode::G_FCOSH:
534 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
535 case TargetOpcode::G_FSINH:
536 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
537 case TargetOpcode::G_FTANH:
538 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
540 case TargetOpcode::G_FSQRT:
541 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
543 case TargetOpcode::G_CTTZ:
544 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
545 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
546 case TargetOpcode::G_CTLZ:
547 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
548 return selectExtInst(ResVReg, ResType,
I, CL::clz);
550 case TargetOpcode::G_INTRINSIC_ROUND:
551 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
552 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
553 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
554 case TargetOpcode::G_INTRINSIC_TRUNC:
555 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
556 case TargetOpcode::G_FRINT:
557 case TargetOpcode::G_FNEARBYINT:
558 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
560 case TargetOpcode::G_SMULH:
561 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
562 case TargetOpcode::G_UMULH:
563 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
565 case TargetOpcode::G_SADDSAT:
566 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
567 case TargetOpcode::G_UADDSAT:
568 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
569 case TargetOpcode::G_SSUBSAT:
570 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
571 case TargetOpcode::G_USUBSAT:
572 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
574 case TargetOpcode::G_SEXT:
575 return selectExt(ResVReg, ResType,
I,
true);
576 case TargetOpcode::G_ANYEXT:
577 case TargetOpcode::G_ZEXT:
578 return selectExt(ResVReg, ResType,
I,
false);
579 case TargetOpcode::G_TRUNC:
580 return selectTrunc(ResVReg, ResType,
I);
581 case TargetOpcode::G_FPTRUNC:
582 case TargetOpcode::G_FPEXT:
583 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
585 case TargetOpcode::G_PTRTOINT:
586 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
587 case TargetOpcode::G_INTTOPTR:
588 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
589 case TargetOpcode::G_BITCAST:
590 return selectBitcast(ResVReg, ResType,
I);
591 case TargetOpcode::G_ADDRSPACE_CAST:
592 return selectAddrSpaceCast(ResVReg, ResType,
I);
593 case TargetOpcode::G_PTR_ADD: {
598 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
602 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
603 (*II).getOpcode() == TargetOpcode::COPY ||
604 (*II).getOpcode() == SPIRV::OpVariable) &&
606 Register Idx = buildZerosVal(GR.getOrCreateSPIRVIntegerType(32,
I,
TII),
I);
608 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
610 .
addUse(GR.getSPIRVTypeID(ResType))
612 SPIRV::Opcode::InBoundsPtrAccessChain))
615 .
addUse(
I.getOperand(2).getReg());
619 case TargetOpcode::G_ATOMICRMW_OR:
620 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
621 case TargetOpcode::G_ATOMICRMW_ADD:
622 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
623 case TargetOpcode::G_ATOMICRMW_AND:
624 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
625 case TargetOpcode::G_ATOMICRMW_MAX:
626 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
627 case TargetOpcode::G_ATOMICRMW_MIN:
628 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
629 case TargetOpcode::G_ATOMICRMW_SUB:
630 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
631 case TargetOpcode::G_ATOMICRMW_XOR:
632 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
633 case TargetOpcode::G_ATOMICRMW_UMAX:
634 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
635 case TargetOpcode::G_ATOMICRMW_UMIN:
636 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
637 case TargetOpcode::G_ATOMICRMW_XCHG:
638 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
639 case TargetOpcode::G_ATOMIC_CMPXCHG:
640 return selectAtomicCmpXchg(ResVReg, ResType,
I);
642 case TargetOpcode::G_ATOMICRMW_FADD:
643 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
644 case TargetOpcode::G_ATOMICRMW_FSUB:
646 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
648 case TargetOpcode::G_ATOMICRMW_FMIN:
649 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
650 case TargetOpcode::G_ATOMICRMW_FMAX:
651 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
653 case TargetOpcode::G_FENCE:
654 return selectFence(
I);
656 case TargetOpcode::G_STACKSAVE:
657 return selectStackSave(ResVReg, ResType,
I);
658 case TargetOpcode::G_STACKRESTORE:
659 return selectStackRestore(
I);
661 case TargetOpcode::G_UNMERGE_VALUES:
669bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
672 CL::OpenCLExtInst CLInst)
const {
673 return selectExtInst(ResVReg, ResType,
I,
674 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
677bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
680 CL::OpenCLExtInst CLInst,
681 GL::GLSLExtInst GLInst)
const {
682 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
683 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
684 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
687bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
692 for (
const auto &Ex : Insts) {
693 SPIRV::InstructionSet::InstructionSet
Set = Ex.first;
695 if (STI.canUseExtInstSet(Set)) {
697 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
699 .
addUse(GR.getSPIRVTypeID(ResType))
702 const unsigned NumOps =
I.getNumOperands();
703 for (
unsigned i = 1; i < NumOps; ++i)
704 MIB.add(
I.getOperand(i));
705 return MIB.constrainAllUses(
TII,
TRI, RBI);
711bool SPIRVInstructionSelector::selectUnOpWithSrc(
Register ResVReg,
715 unsigned Opcode)
const {
716 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
718 .
addUse(GR.getSPIRVTypeID(ResType))
723bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
726 unsigned Opcode)
const {
727 if (STI.isOpenCLEnv() &&
I.getOperand(1).isReg()) {
728 Register SrcReg =
I.getOperand(1).getReg();
731 MRI->def_instr_begin(SrcReg);
732 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
733 if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
741 case SPIRV::OpConvertPtrToU:
742 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertPtrToU);
744 case SPIRV::OpConvertUToPtr:
745 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertUToPtr);
749 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
750 TII.get(SPIRV::OpSpecConstantOp))
752 .
addUse(GR.getSPIRVTypeID(ResType))
758 return selectUnOpWithSrc(ResVReg, ResType,
I,
I.getOperand(1).getReg(),
762bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
765 Register OpReg =
I.getOperand(1).getReg();
766 SPIRVType *OpType = OpReg.
isValid() ? GR.getSPIRVTypeForVReg(OpReg) :
nullptr;
767 if (!GR.isBitcastCompatible(ResType, OpType))
769 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
773 const SyncScopeIDs &SSIDs) {
775 return SPIRV::Scope::Invocation;
777 return SPIRV::Scope::Device;
778 else if (Ord == SSIDs.WorkGroupSSID)
779 return SPIRV::Scope::Workgroup;
780 else if (Ord == SSIDs.AllSVMDevicesSSID)
781 return SPIRV::Scope::CrossDevice;
782 else if (Ord == SSIDs.SubGroupSSID)
783 return SPIRV::Scope::Subgroup;
792 return SPIRV::Scope::Device;
798 if (
MemOp->isVolatile())
799 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
800 if (
MemOp->isNonTemporal())
801 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
802 if (
MemOp->getAlign().value())
803 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
805 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
807 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
814 if (Flags & MachineMemOperand::Flags::MOVolatile)
815 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
816 if (Flags & MachineMemOperand::Flags::MONonTemporal)
817 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
819 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
823bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
826 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
828 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
830 .
addUse(GR.getSPIRVTypeID(ResType))
832 if (!
I.getNumMemOperands()) {
833 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
835 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
840 return MIB.constrainAllUses(
TII,
TRI, RBI);
843bool SPIRVInstructionSelector::selectStore(
MachineInstr &
I)
const {
844 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
845 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
848 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
851 if (!
I.getNumMemOperands()) {
852 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
854 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
859 return MIB.constrainAllUses(
TII,
TRI, RBI);
862bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
865 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
867 "llvm.stacksave intrinsic: this instruction requires the following "
868 "SPIR-V extension: SPV_INTEL_variable_length_array",
871 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
873 .
addUse(GR.getSPIRVTypeID(ResType))
877bool SPIRVInstructionSelector::selectStackRestore(
MachineInstr &
I)
const {
878 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
880 "llvm.stackrestore intrinsic: this instruction requires the following "
881 "SPIR-V extension: SPV_INTEL_variable_length_array",
883 if (!
I.getOperand(0).isReg())
886 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
887 .
addUse(
I.getOperand(0).getReg())
891bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
894 Register SrcReg =
I.getOperand(1).getReg();
895 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
896 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
899 SPIRVType *ValTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
900 SPIRVType *ArrTy = GR.getOrCreateSPIRVArrayType(ValTy, Num,
I,
TII);
902 SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType(
903 ArrTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
913 GR.add(GV, GR.CurMF, VarReg);
916 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
918 .
addUse(GR.getSPIRVTypeID(VarTy))
919 .
addImm(SPIRV::StorageClass::UniformConstant)
922 SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
923 ValTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
925 selectUnOpWithSrc(SrcReg, SourceTy,
I, VarReg, SPIRV::OpBitcast);
927 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
928 .
addUse(
I.getOperand(0).getReg())
930 .
addUse(
I.getOperand(2).getReg());
931 if (
I.getNumMemOperands())
934 if (ResVReg.
isValid() && ResVReg != MIB->getOperand(0).getReg())
935 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY), ResVReg)
936 .
addUse(MIB->getOperand(0).getReg());
940bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
944 unsigned NegateOpcode)
const {
949 Register ScopeReg = buildI32Constant(Scope,
I);
957 Register MemSemReg = buildI32Constant(MemSem ,
I);
960 Register ValueReg =
I.getOperand(2).getReg();
961 if (NegateOpcode != 0) {
963 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
964 Result |= selectUnOpWithSrc(TmpReg, ResType,
I, ValueReg, NegateOpcode);
970 .
addUse(GR.getSPIRVTypeID(ResType))
979bool SPIRVInstructionSelector::selectUnmergeValues(
MachineInstr &
I)
const {
980 unsigned ArgI =
I.getNumOperands() - 1;
982 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
984 SrcReg.
isValid() ? GR.getSPIRVTypeForVReg(SrcReg) :
nullptr;
985 if (!DefType || DefType->
getOpcode() != SPIRV::OpTypeVector)
987 "cannot select G_UNMERGE_VALUES with a non-vector argument");
993 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
994 Register ResVReg =
I.getOperand(i).getReg();
995 SPIRVType *ResType = GR.getSPIRVTypeForVReg(ResVReg);
998 ResType = ScalarType;
999 MRI->setRegClass(ResVReg, &SPIRV::iIDRegClass);
1000 MRI->setType(ResVReg,
LLT::scalar(GR.getScalarOrVectorBitWidth(ResType)));
1001 GR.assignSPIRVTypeToVReg(ResType, ResVReg, *GR.CurMF);
1004 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1006 .
addUse(GR.getSPIRVTypeID(ResType))
1008 .
addImm(
static_cast<int64_t
>(i));
1009 Res |= MIB.constrainAllUses(
TII,
TRI, RBI);
1014bool SPIRVInstructionSelector::selectFence(
MachineInstr &
I)
const {
1017 Register MemSemReg = buildI32Constant(MemSem,
I);
1020 Register ScopeReg = buildI32Constant(Scope,
I);
1022 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
1028bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
1035 if (!isa<GIntrinsic>(
I)) {
1040 ScopeReg = buildI32Constant(Scope,
I);
1042 unsigned ScSem =
static_cast<uint32_t>(
1046 MemSemEqReg = buildI32Constant(MemSemEq,
I);
1050 MemSemEq == MemSemNeq ? MemSemEqReg : buildI32Constant(MemSemNeq,
I);
1052 ScopeReg =
I.getOperand(5).getReg();
1053 MemSemEqReg =
I.getOperand(6).getReg();
1054 MemSemNeqReg =
I.getOperand(7).getReg();
1058 Register Val =
I.getOperand(4).getReg();
1059 SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
1060 Register ACmpRes =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1063 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
1065 .
addUse(GR.getSPIRVTypeID(SpvValTy))
1073 Register CmpSuccReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1077 .
addUse(GR.getSPIRVTypeID(BoolTy))
1081 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1084 .
addUse(GR.getSPIRVTypeID(ResType))
1086 .
addUse(GR.getOrCreateUndef(
I, ResType,
TII))
1091 .
addUse(GR.getSPIRVTypeID(ResType))
1101 case SPIRV::StorageClass::Workgroup:
1102 case SPIRV::StorageClass::CrossWorkgroup:
1103 case SPIRV::StorageClass::Function:
1112 case SPIRV::StorageClass::DeviceOnlyINTEL:
1113 case SPIRV::StorageClass::HostOnlyINTEL:
1125bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
1130 auto UIs =
MRI->use_instructions(ResVReg);
1131 if (!UIs.empty() && ++UIs.begin() == UIs.end() &&
1132 (UIs.begin()->getOpcode() == SPIRV::OpConstantComposite ||
1133 UIs.begin()->getOpcode() == SPIRV::OpVariable ||
1135 Register NewReg =
I.getOperand(1).getReg();
1137 SPIRVType *SpvBaseTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
1138 ResType = GR.getOrCreateSPIRVPointerType(SpvBaseTy,
I,
TII,
1139 SPIRV::StorageClass::Generic);
1141 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1143 .
addUse(GR.getSPIRVTypeID(ResType))
1149 Register SrcPtr =
I.getOperand(1).getReg();
1150 SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);
1151 SPIRV::StorageClass::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtr);
1152 SPIRV::StorageClass::StorageClass DstSC = GR.getPointerStorageClass(ResVReg);
1156 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1157 TII.get(TargetOpcode::COPY))
1164 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1167 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1170 Register Tmp =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1171 SPIRVType *GenericPtrTy = GR.getOrCreateSPIRVPointerType(
1172 GR.getPointeeType(SrcPtrTy),
I,
TII, SPIRV::StorageClass::Generic);
1177 .
addUse(GR.getSPIRVTypeID(GenericPtrTy))
1182 .
addUse(GR.getSPIRVTypeID(ResType))
1190 return selectUnOp(ResVReg, ResType,
I,
1191 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
1193 return selectUnOp(ResVReg, ResType,
I,
1194 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
1196 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1198 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1208 return SPIRV::OpFOrdEqual;
1210 return SPIRV::OpFOrdGreaterThanEqual;
1212 return SPIRV::OpFOrdGreaterThan;
1214 return SPIRV::OpFOrdLessThanEqual;
1216 return SPIRV::OpFOrdLessThan;
1218 return SPIRV::OpFOrdNotEqual;
1220 return SPIRV::OpOrdered;
1222 return SPIRV::OpFUnordEqual;
1224 return SPIRV::OpFUnordGreaterThanEqual;
1226 return SPIRV::OpFUnordGreaterThan;
1228 return SPIRV::OpFUnordLessThanEqual;
1230 return SPIRV::OpFUnordLessThan;
1232 return SPIRV::OpFUnordNotEqual;
1234 return SPIRV::OpUnordered;
1244 return SPIRV::OpIEqual;
1246 return SPIRV::OpINotEqual;
1248 return SPIRV::OpSGreaterThanEqual;
1250 return SPIRV::OpSGreaterThan;
1252 return SPIRV::OpSLessThanEqual;
1254 return SPIRV::OpSLessThan;
1256 return SPIRV::OpUGreaterThanEqual;
1258 return SPIRV::OpUGreaterThan;
1260 return SPIRV::OpULessThanEqual;
1262 return SPIRV::OpULessThan;
1271 return SPIRV::OpPtrEqual;
1273 return SPIRV::OpPtrNotEqual;
1284 return SPIRV::OpLogicalEqual;
1286 return SPIRV::OpLogicalNotEqual;
1320bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
1323 unsigned OpAnyOrAll)
const {
1324 assert(
I.getNumOperands() == 3);
1325 assert(
I.getOperand(2).isReg());
1327 Register InputRegister =
I.getOperand(2).getReg();
1328 SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);
1333 bool IsBoolTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeBool);
1334 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
1335 if (IsBoolTy && !IsVectorTy) {
1336 assert(ResVReg ==
I.getOperand(0).getReg());
1337 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1338 TII.get(TargetOpcode::COPY))
1344 bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
1345 unsigned SpirvNotEqualId =
1346 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
1347 SPIRVType *SpvBoolScalarTy = GR.getOrCreateSPIRVBoolType(
I,
TII);
1352 NotEqualReg = IsBoolTy ? InputRegister
1353 :
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1355 SpvBoolTy = GR.getOrCreateSPIRVVectorType(SpvBoolTy, NumElts,
I,
TII);
1360 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
1362 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SpirvNotEqualId))
1364 .
addUse(GR.getSPIRVTypeID(SpvBoolTy))
1373 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(OpAnyOrAll))
1375 .
addUse(GR.getSPIRVTypeID(SpvBoolScalarTy))
1380bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
1383 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
1386bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
1389 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
1392bool SPIRVInstructionSelector::selectFmix(
Register ResVReg,
1396 assert(
I.getNumOperands() == 5);
1397 assert(
I.getOperand(2).isReg());
1398 assert(
I.getOperand(3).isReg());
1399 assert(
I.getOperand(4).isReg());
1402 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1404 .
addUse(GR.getSPIRVTypeID(ResType))
1405 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1407 .
addUse(
I.getOperand(2).getReg())
1408 .
addUse(
I.getOperand(3).getReg())
1409 .
addUse(
I.getOperand(4).getReg())
1413bool SPIRVInstructionSelector::selectLength(
Register ResVReg,
1417 assert(
I.getNumOperands() == 3);
1418 assert(
I.getOperand(2).isReg());
1421 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1423 .
addUse(GR.getSPIRVTypeID(ResType))
1424 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1426 .
addUse(
I.getOperand(2).getReg())
1430bool SPIRVInstructionSelector::selectFrac(
Register ResVReg,
1434 assert(
I.getNumOperands() == 3);
1435 assert(
I.getOperand(2).isReg());
1438 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1440 .
addUse(GR.getSPIRVTypeID(ResType))
1441 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1443 .
addUse(
I.getOperand(2).getReg())
1447bool SPIRVInstructionSelector::selectNormalize(
Register ResVReg,
1451 assert(
I.getNumOperands() == 3);
1452 assert(
I.getOperand(2).isReg());
1455 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1457 .
addUse(GR.getSPIRVTypeID(ResType))
1458 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1460 .
addUse(
I.getOperand(2).getReg())
1464bool SPIRVInstructionSelector::selectRsqrt(
Register ResVReg,
1468 assert(
I.getNumOperands() == 3);
1469 assert(
I.getOperand(2).isReg());
1472 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1474 .
addUse(GR.getSPIRVTypeID(ResType))
1475 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1477 .
addUse(
I.getOperand(2).getReg())
1483bool SPIRVInstructionSelector::selectSaturate(
Register ResVReg,
1486 assert(
I.getNumOperands() == 3);
1487 assert(
I.getOperand(2).isReg());
1489 Register VZero = buildZerosValF(ResType,
I);
1490 Register VOne = buildOnesValF(ResType,
I);
1492 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1494 .
addUse(GR.getSPIRVTypeID(ResType))
1495 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1497 .
addUse(
I.getOperand(2).getReg())
1503bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
1507 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
1509 .
addUse(GR.getSPIRVTypeID(ResType))
1510 .
addUse(
I.getOperand(1).getReg())
1514bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
1522 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
1524 Register OpReg =
I.getOperand(1).getReg();
1527 switch (
Def->getOpcode()) {
1528 case SPIRV::ASSIGN_TYPE:
1530 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
1531 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1532 Reg =
Def->getOperand(2).getReg();
1535 case SPIRV::OpUndef:
1536 Reg =
Def->getOperand(1).getReg();
1539 unsigned DestOpCode;
1540 if (
Reg.isValid()) {
1541 DestOpCode = SPIRV::OpConstantNull;
1543 DestOpCode = TargetOpcode::COPY;
1546 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
1547 .
addDef(
I.getOperand(0).getReg())
1560 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1565 unsigned N = OpDef->
getOpcode() == TargetOpcode::G_CONSTANT
1574 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1586 case TargetOpcode::G_CONSTANT:
1587 case TargetOpcode::G_FCONSTANT:
1589 case TargetOpcode::G_INTRINSIC:
1590 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1591 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
1592 return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
1593 Intrinsic::spv_const_composite;
1594 case TargetOpcode::G_BUILD_VECTOR:
1595 case TargetOpcode::G_SPLAT_VECTOR: {
1619bool SPIRVInstructionSelector::selectBuildVector(
Register ResVReg,
1623 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1624 N = GR.getScalarOrVectorComponentCount(ResType);
1625 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
1629 if (
I.getNumExplicitOperands() -
I.getNumExplicitDefs() !=
N)
1634 for (
unsigned i =
I.getNumExplicitDefs();
1635 i <
I.getNumExplicitOperands() && IsConst; ++i)
1639 if (!IsConst &&
N < 2)
1641 "There must be at least two constituent operands in a vector");
1643 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1644 TII.get(IsConst ? SPIRV::OpConstantComposite
1645 : SPIRV::OpCompositeConstruct))
1647 .
addUse(GR.getSPIRVTypeID(ResType));
1648 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
1649 MIB.
addUse(
I.getOperand(i).getReg());
1653bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
1657 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1658 N = GR.getScalarOrVectorComponentCount(ResType);
1659 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
1664 unsigned OpIdx =
I.getNumExplicitDefs();
1665 if (!
I.getOperand(OpIdx).isReg())
1669 Register OpReg =
I.getOperand(OpIdx).getReg();
1672 if (!IsConst &&
N < 2)
1674 "There must be at least two constituent operands in a vector");
1676 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1677 TII.get(IsConst ? SPIRV::OpConstantComposite
1678 : SPIRV::OpCompositeConstruct))
1680 .
addUse(GR.getSPIRVTypeID(ResType));
1681 for (
unsigned i = 0; i <
N; ++i)
1686bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
1690 Register Cmp0 =
I.getOperand(2).getReg();
1691 Register Cmp1 =
I.getOperand(3).getReg();
1692 assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
1693 GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
1694 "CMP operands should have the same type");
1695 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
1697 .
addUse(GR.getSPIRVTypeID(ResType))
1703bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
1706 auto Pred =
I.getOperand(1).getPredicate();
1709 Register CmpOperand =
I.getOperand(2).getReg();
1710 if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
1712 else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
1716 return selectCmp(ResVReg, ResType, CmpOpc,
I);
1722 assert(
I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
1723 "Expected G_FCONSTANT");
1724 const ConstantFP *FPImm =
I.getOperand(1).getFPImm();
1731 assert(
I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1732 "Expected G_CONSTANT");
1733 addNumImm(
I.getOperand(1).getCImm()->getValue(), MIB);
1741 ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32,
I,
TII);
1743 auto ConstInt = ConstantInt::get(LLVMTy, Val);
1744 Register NewReg = GR.find(ConstInt, GR.CurMF);
1747 GR.add(ConstInt, GR.CurMF, NewReg);
1751 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1753 .
addUse(GR.getSPIRVTypeID(SpvI32Ty));
1755 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1757 .
addUse(GR.getSPIRVTypeID(SpvI32Ty))
1765bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
1769 return selectCmp(ResVReg, ResType, CmpOp,
I);
1775 bool ZeroAsNull = STI.isOpenCLEnv();
1776 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1777 return GR.getOrCreateConstVector(0UL,
I, ResType,
TII, ZeroAsNull);
1778 return GR.getOrCreateConstInt(0,
I, ResType,
TII, ZeroAsNull);
1784 bool ZeroAsNull = STI.isOpenCLEnv();
1786 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1787 return GR.getOrCreateConstVector(VZero,
I, ResType,
TII, ZeroAsNull);
1788 return GR.getOrCreateConstFP(VZero,
I, ResType,
TII, ZeroAsNull);
1794 bool ZeroAsNull = STI.isOpenCLEnv();
1796 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1797 return GR.getOrCreateConstVector(VOne,
I, ResType,
TII, ZeroAsNull);
1798 return GR.getOrCreateConstFP(VOne,
I, ResType,
TII, ZeroAsNull);
1804 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1807 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1812bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
1815 bool IsSigned)
const {
1817 Register ZeroReg = buildZerosVal(ResType,
I);
1818 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
1820 GR.isScalarOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool);
1822 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectSIVCond;
1823 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1825 .
addUse(GR.getSPIRVTypeID(ResType))
1826 .
addUse(
I.getOperand(1).getReg())
1832bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
1835 unsigned Opcode)
const {
1836 Register SrcReg =
I.getOperand(1).getReg();
1839 if (GR.isScalarOrVectorOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
1840 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1842 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1844 TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts,
I,
TII);
1846 SrcReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1847 selectSelect(SrcReg, TmpType,
I,
false);
1849 return selectUnOpWithSrc(ResVReg, ResType,
I, SrcReg, Opcode);
1852bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
1855 Register SrcReg =
I.getOperand(1).getReg();
1856 if (GR.isScalarOrVectorOfType(SrcReg, SPIRV::OpTypeBool))
1857 return selectSelect(ResVReg, ResType,
I, IsSigned);
1859 SPIRVType *SrcType = GR.getSPIRVTypeForVReg(SrcReg);
1860 if (SrcType == ResType)
1861 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1862 TII.get(TargetOpcode::COPY))
1867 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1868 return selectUnOp(ResVReg, ResType,
I, Opcode);
1871bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
1877 Register BitIntReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
1878 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
1879 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
1881 Register One = buildOnesVal(
false, IntTy,
I);
1885 .
addUse(GR.getSPIRVTypeID(IntTy))
1889 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpINotEqual))
1891 .
addUse(GR.getSPIRVTypeID(BoolTy))
1897bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
1900 Register IntReg =
I.getOperand(1).getReg();
1901 const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
1902 if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool))
1903 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
1904 if (ArgType == ResType)
1905 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1906 TII.get(TargetOpcode::COPY))
1910 bool IsSigned = GR.isScalarOrVectorSigned(ResType);
1911 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1912 return selectUnOp(ResVReg, ResType,
I, Opcode);
1915bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
1919 unsigned TyOpcode = ResType->
getOpcode();
1920 assert(TyOpcode != SPIRV::OpTypePointer ||
Imm.isZero());
1922 if ((TyOpcode == SPIRV::OpTypePointer || TyOpcode == SPIRV::OpTypeEvent) &&
1924 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1926 .
addUse(GR.getSPIRVTypeID(ResType))
1928 if (TyOpcode == SPIRV::OpTypeInt) {
1929 assert(
Imm.getBitWidth() <= 64 &&
"Unsupported integer width!");
1933 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
1938 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1940 .
addUse(GR.getSPIRVTypeID(ResType));
1947bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
1950 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1952 .
addUse(GR.getSPIRVTypeID(ResType))
1959 if (TypeInst->
getOpcode() == SPIRV::ASSIGN_TYPE) {
1962 return ImmInst->
getOpcode() == TargetOpcode::G_CONSTANT;
1964 return TypeInst->
getOpcode() == SPIRV::OpConstantI;
1969 if (TypeInst->
getOpcode() == SPIRV::OpConstantI)
1976bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
1980 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
1982 .
addUse(GR.getSPIRVTypeID(ResType))
1984 .
addUse(
I.getOperand(3).getReg())
1986 .
addUse(
I.getOperand(2).getReg());
1987 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
1992bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
1996 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1998 .
addUse(GR.getSPIRVTypeID(ResType))
1999 .
addUse(
I.getOperand(2).getReg());
2000 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
2005bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
2009 return selectInsertVal(ResVReg, ResType,
I);
2011 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
2013 .
addUse(GR.getSPIRVTypeID(ResType))
2014 .
addUse(
I.getOperand(2).getReg())
2015 .
addUse(
I.getOperand(3).getReg())
2016 .
addUse(
I.getOperand(4).getReg())
2020bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
2024 return selectExtractVal(ResVReg, ResType,
I);
2026 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
2028 .
addUse(GR.getSPIRVTypeID(ResType))
2029 .
addUse(
I.getOperand(2).getReg())
2030 .
addUse(
I.getOperand(3).getReg())
2034bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
2037 const bool IsGEPInBounds =
I.getOperand(2).getImm();
2042 const unsigned Opcode = STI.isVulkanEnv()
2043 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
2044 : SPIRV::OpAccessChain)
2045 : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
2046 : SPIRV::OpPtrAccessChain);
2048 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
2050 .
addUse(GR.getSPIRVTypeID(ResType))
2052 .
addUse(
I.getOperand(3).getReg());
2054 const unsigned StartingIndex =
2055 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
2058 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
2059 Res.addUse(
I.getOperand(i).getReg());
2060 return Res.constrainAllUses(
TII,
TRI, RBI);
2064bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
2067 unsigned Lim =
I.getNumExplicitOperands();
2068 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
2069 Register OpReg =
I.getOperand(i).getReg();
2071 SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
2073 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
2074 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
2075 GR.isAggregateType(OpType)) {
2082 Register WrapReg = GR.find(OpDefine, MF);
2088 WrapReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2089 GR.add(OpDefine, MF, WrapReg);
2093 GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF);
2097 .
addUse(GR.getSPIRVTypeID(OpType))
2107bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
2113 case Intrinsic::spv_load:
2114 return selectLoad(ResVReg, ResType,
I);
2115 case Intrinsic::spv_store:
2116 return selectStore(
I);
2117 case Intrinsic::spv_extractv:
2118 return selectExtractVal(ResVReg, ResType,
I);
2119 case Intrinsic::spv_insertv:
2120 return selectInsertVal(ResVReg, ResType,
I);
2121 case Intrinsic::spv_extractelt:
2122 return selectExtractElt(ResVReg, ResType,
I);
2123 case Intrinsic::spv_insertelt:
2124 return selectInsertElt(ResVReg, ResType,
I);
2125 case Intrinsic::spv_gep:
2126 return selectGEP(ResVReg, ResType,
I);
2127 case Intrinsic::spv_unref_global:
2128 case Intrinsic::spv_init_global: {
2131 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
2134 return selectGlobalValue(
MI->getOperand(0).getReg(), *
MI,
Init);
2136 case Intrinsic::spv_undef: {
2137 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
2139 .
addUse(GR.getSPIRVTypeID(ResType));
2142 case Intrinsic::spv_const_composite: {
2144 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
2146 unsigned Opcode = SPIRV::OpConstantNull;
2149 Opcode = SPIRV::OpConstantComposite;
2150 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
2153 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2155 .
addUse(GR.getSPIRVTypeID(ResType));
2158 for (
Register OpReg : CompositeArgs)
2163 case Intrinsic::spv_assign_name: {
2164 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
2165 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
2166 for (
unsigned i =
I.getNumExplicitDefs() + 2;
2167 i <
I.getNumExplicitOperands(); ++i) {
2168 MIB.
addImm(
I.getOperand(i).getImm());
2172 case Intrinsic::spv_switch: {
2173 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
2174 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
2175 if (
I.getOperand(i).isReg())
2176 MIB.
addReg(
I.getOperand(i).getReg());
2177 else if (
I.getOperand(i).isCImm())
2178 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
2179 else if (
I.getOperand(i).isMBB())
2180 MIB.
addMBB(
I.getOperand(i).getMBB());
2186 case Intrinsic::spv_cmpxchg:
2187 return selectAtomicCmpXchg(ResVReg, ResType,
I);
2188 case Intrinsic::spv_unreachable:
2189 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable));
2191 case Intrinsic::spv_alloca:
2192 return selectFrameIndex(ResVReg, ResType,
I);
2193 case Intrinsic::spv_alloca_array:
2194 return selectAllocaArray(ResVReg, ResType,
I);
2195 case Intrinsic::spv_assume:
2196 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
2197 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
2198 .
addUse(
I.getOperand(1).getReg());
2200 case Intrinsic::spv_expect:
2201 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
2202 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
2204 .
addUse(GR.getSPIRVTypeID(ResType))
2205 .
addUse(
I.getOperand(2).getReg())
2206 .
addUse(
I.getOperand(3).getReg());
2208 case Intrinsic::spv_thread_id:
2209 return selectSpvThreadId(ResVReg, ResType,
I);
2210 case Intrinsic::spv_all:
2211 return selectAll(ResVReg, ResType,
I);
2212 case Intrinsic::spv_any:
2213 return selectAny(ResVReg, ResType,
I);
2214 case Intrinsic::spv_lerp:
2215 return selectFmix(ResVReg, ResType,
I);
2216 case Intrinsic::spv_length:
2217 return selectLength(ResVReg, ResType,
I);
2218 case Intrinsic::spv_frac:
2219 return selectFrac(ResVReg, ResType,
I);
2220 case Intrinsic::spv_normalize:
2221 return selectNormalize(ResVReg, ResType,
I);
2222 case Intrinsic::spv_rsqrt:
2223 return selectRsqrt(ResVReg, ResType,
I);
2224 case Intrinsic::spv_lifetime_start:
2225 case Intrinsic::spv_lifetime_end: {
2226 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
2227 : SPIRV::OpLifetimeStop;
2228 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
2229 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
2234 case Intrinsic::spv_saturate:
2235 return selectSaturate(ResVReg, ResType,
I);
2237 std::string DiagMsg;
2240 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
2247bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
2254 TII.get(SPIRV::OpVariableLengthArrayINTEL))
2256 .
addUse(GR.getSPIRVTypeID(ResType))
2257 .
addUse(
I.getOperand(2).getReg())
2261bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
2269 bool IsHeader =
false;
2271 for (; It != E && It !=
I; ++It) {
2272 Opcode = It->getOpcode();
2273 if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
2275 }
else if (IsHeader &&
2276 !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
2281 return BuildMI(*
MBB, It, It->getDebugLoc(),
TII.get(SPIRV::OpVariable))
2283 .
addUse(GR.getSPIRVTypeID(ResType))
2288bool SPIRVInstructionSelector::selectBranch(
MachineInstr &
I)
const {
2295 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
2296 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2299 .
addMBB(
I.getOperand(0).getMBB())
2303 .
addMBB(
I.getOperand(0).getMBB())
2307bool SPIRVInstructionSelector::selectBranchCond(
MachineInstr &
I)
const {
2320 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
2327 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2328 .
addUse(
I.getOperand(0).getReg())
2329 .
addMBB(
I.getOperand(1).getMBB())
2334bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
2337 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
2339 .
addUse(GR.getSPIRVTypeID(ResType));
2340 const unsigned NumOps =
I.getNumOperands();
2341 for (
unsigned i = 1; i < NumOps; i += 2) {
2342 MIB.
addUse(
I.getOperand(i + 0).getReg());
2343 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
2348bool SPIRVInstructionSelector::selectGlobalValue(
2358 SPIRV::AccessQualifier::ReadWrite,
false);
2359 PointerBaseType = GR.getOrCreateSPIRVArrayType(
2362 PointerBaseType = GR.getOrCreateSPIRVType(
2363 GVType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2365 SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(
2366 PointerBaseType,
I,
TII,
2369 std::string GlobalIdent;
2371 unsigned &
ID = UnnamedGlobalIDs[GV];
2373 ID = UnnamedGlobalIDs.size();
2374 GlobalIdent =
"__unnamed_" +
Twine(
ID).
str();
2389 if (isa<Function>(GV)) {
2392 Register NewReg = GR.find(ConstVal, GR.CurMF);
2395 GR.add(ConstVal, GR.CurMF, NewReg);
2397 STI.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)
2398 ? dyn_cast<Function>(GV)
2406 MRI->setRegClass(FuncVReg, &SPIRV::iIDRegClass);
2409 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
2411 .
addUse(GR.getSPIRVTypeID(ResType))
2417 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2419 .
addUse(GR.getSPIRVTypeID(ResType))
2422 assert(NewReg != ResVReg);
2423 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
2428 auto GlobalVar = cast<GlobalVariable>(GV);
2431 bool HasInit =
GlobalVar->hasInitializer() &&
2432 !isa<UndefValue>(
GlobalVar->getInitializer());
2435 if (HasInit && !
Init)
2439 SPIRV::StorageClass::StorageClass Storage =
2442 Storage != SPIRV::StorageClass::Function;
2443 SPIRV::LinkageType::LinkageType LnkType =
2445 ? SPIRV::LinkageType::Import
2447 STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
2448 ? SPIRV::LinkageType::LinkOnceODR
2449 : SPIRV::LinkageType::Export);
2451 Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
2453 HasLnkTy, LnkType, MIRBuilder,
true);
2454 return Reg.isValid();
2457bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
2460 if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
2461 return selectExtInst(ResVReg, ResType,
I, CL::log10);
2473 Register VarReg =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2475 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2477 .
addUse(GR.getSPIRVTypeID(ResType))
2478 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
2480 .
add(
I.getOperand(1))
2485 ResType->
getOpcode() == SPIRV::OpTypeFloat);
2488 ResType->
getOpcode() == SPIRV::OpTypeVector
2492 GR.buildConstantFP(
APFloat(0.30103f), MIRBuilder, SpirvScalarType);
2495 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
2496 ? SPIRV::OpVectorTimesScalar
2500 .
addUse(GR.getSPIRVTypeID(ResType))
2508bool SPIRVInstructionSelector::selectSpvThreadId(
Register ResVReg,
2516 const SPIRVType *U32Type = GR.getOrCreateSPIRVIntegerType(32, MIRBuilder);
2518 GR.getOrCreateSPIRVVectorType(U32Type, 3, MIRBuilder);
2519 const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
2520 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
2524 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
2525 MIRBuilder.getMRI()->setType(NewRegister,
LLT::pointer(0, 32));
2526 GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());
2529 Register Variable = GR.buildGlobalVariable(
2530 NewRegister, PtrType,
2532 SPIRV::StorageClass::Input,
nullptr,
true,
true,
2533 SPIRV::LinkageType::Import, MIRBuilder,
false);
2537 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2538 MIRBuilder.getMRI()->setType(LoadedRegister,
LLT::pointer(0, 32));
2539 GR.assignSPIRVTypeToVReg(Vec3Ty, LoadedRegister, MIRBuilder.getMF());
2542 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
2544 .
addUse(GR.getSPIRVTypeID(Vec3Ty))
2549 assert(
I.getOperand(2).isReg());
2550 Register ThreadIdReg =
I.getOperand(2).getReg();
2556 assert(Const &&
Const->getOpcode() == TargetOpcode::G_CONSTANT);
2562 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2564 .
addUse(GR.getSPIRVTypeID(ResType))
2575 return new SPIRVInstructionSelector(TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
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
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< std::pair< SPIRV::InstructionSet::InstructionSet, uint32_t > > ExtInstList
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static APFloat getOneFP(const Type *LLVMFloatTy)
static bool isUSMStorageClass(SPIRV::StorageClass::StorageClass SC)
static APFloat getZeroFP(const Type *LLVMFloatTy)
static void addMemoryOperands(MachineMemOperand *MemOp, MachineInstrBuilder &MIB)
static unsigned getFCmpOpcode(unsigned PredNum)
bool isTypeFoldingSupported(unsigned Opcode)
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
static unsigned getBoolCmpOpcode(unsigned PredNum)
static unsigned getICmpOpcode(unsigned PredNum)
static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef, SmallPtrSet< SPIRVType *, 4 > &Visited)
static int64_t foldImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
static bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
static SPIRV::Scope::Scope getScope(SyncScope::ID Ord, const SyncScopeIDs &SSIDs)
static unsigned getPtrCmpOpcode(unsigned Pred)
static unsigned getArrayComponentCount(MachineRegisterInfo *MRI, const SPIRVType *ResType)
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() const
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
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)
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This class represents an Operation in the Expression.
const Function & getFunction() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
static std::string getGlobalIdentifier(StringRef Name, GlobalValue::LinkageTypes Linkage, StringRef FileName)
Return the modified name for a global value suitable to be used as the key for a global lookup (e....
bool hasAvailableExternallyLinkage() const
@ InternalLinkage
Rename collisions when linking (static functions).
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
static 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
This is an important class for using LLVM in a threaded context.
SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator SkipPHIsAndLabels(iterator I)
Return the first instruction in MBB after I that is not a PHI or a label.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Helper class to build MachineInstr.
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.
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.
unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Analysis providing profile information.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isValid() 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.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isArrayTy() const
True if this is an instance of ArrayType.
Type * getArrayElementType() const
uint64_t getArrayNumElements() const
@ HalfTyID
16-bit floating point type
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
TypeID getTypeID() const
Return the type id for the type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsConst[]
Key for Kernel::Arg::Metadata::mIsConst.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
Reg
All possible values of the reg field in the ModR/M byte.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
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.
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Type * toTypedPointer(Type *Ty)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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.
InstructionSelector * createSPIRVInstructionSelector(const SPIRVTargetMachine &TM, const SPIRVSubtarget &Subtarget, const RegisterBankInfo &RBI)
constexpr unsigned BitWidth
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)