32#include "llvm/IR/IntrinsicsSPIRV.h"
57#define DEBUG_TYPE "spirv-isel"
60namespace CL = SPIRV::OpenCLExtInst;
61namespace GL = SPIRV::GLSLExtInst;
64 std::vector<std::pair<SPIRV::InstructionSet::InstructionSet, uint32_t>>;
68#define GET_GLOBALISEL_PREDICATE_BITSET
69#include "SPIRVGenGlobalISel.inc"
70#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
119 unsigned Opcode)
const;
121 unsigned Opcode)
const;
138 unsigned NegateOpcode = 0)
const;
185 bool IsSigned)
const;
187 bool IsSigned,
unsigned Opcode)
const;
189 bool IsSigned)
const;
229 GL::GLSLExtInst GLInst)
const;
242 const SPIRVType *ResType =
nullptr)
const;
255#define GET_GLOBALISEL_IMPL
256#include "SPIRVGenGlobalISel.inc"
257#undef GET_GLOBALISEL_IMPL
263 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
265#include
"SPIRVGenGlobalISel.inc"
268#include
"SPIRVGenGlobalISel.inc"
279 GR.setCurrentFunc(MF);
280 InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
289 assert(
I.getParent() &&
"Instruction should be in a basic block!");
290 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
295 if (Opcode == SPIRV::ASSIGN_TYPE) {
296 Register DstReg =
I.getOperand(0).getReg();
297 Register SrcReg =
I.getOperand(1).getReg();
298 auto *
Def =
MRI->getVRegDef(SrcReg);
300 if (
MRI->getType(DstReg).isPointer())
302 bool Res = selectImpl(
I, *CoverageInfo);
303 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
307 MRI->replaceRegWith(SrcReg, DstReg);
308 I.removeFromParent();
310 }
else if (
I.getNumDefs() == 1) {
317 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
318 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
324 bool HasDefs =
I.getNumDefs() > 0;
326 SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) :
nullptr;
327 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
328 if (spvSelect(ResVReg, ResType,
I)) {
330 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
332 I.removeFromParent();
338bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
341 const unsigned Opcode =
I.getOpcode();
343 return selectImpl(
I, *CoverageInfo);
345 case TargetOpcode::G_CONSTANT:
346 return selectConst(ResVReg, ResType,
I.getOperand(1).getCImm()->getValue(),
348 case TargetOpcode::G_GLOBAL_VALUE:
349 return selectGlobalValue(ResVReg,
I);
350 case TargetOpcode::G_IMPLICIT_DEF:
351 return selectOpUndef(ResVReg, ResType,
I);
352 case TargetOpcode::G_FREEZE:
353 return selectFreeze(ResVReg, ResType,
I);
355 case TargetOpcode::G_INTRINSIC:
356 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
357 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
358 return selectIntrinsic(ResVReg, ResType,
I);
359 case TargetOpcode::G_BITREVERSE:
360 return selectBitreverse(ResVReg, ResType,
I);
362 case TargetOpcode::G_BUILD_VECTOR:
363 return selectConstVector(ResVReg, ResType,
I);
364 case TargetOpcode::G_SPLAT_VECTOR:
365 return selectSplatVector(ResVReg, ResType,
I);
367 case TargetOpcode::G_SHUFFLE_VECTOR: {
369 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
371 .
addUse(GR.getSPIRVTypeID(ResType))
372 .
addUse(
I.getOperand(1).getReg())
373 .
addUse(
I.getOperand(2).getReg());
374 for (
auto V :
I.getOperand(3).getShuffleMask())
378 case TargetOpcode::G_MEMMOVE:
379 case TargetOpcode::G_MEMCPY:
380 case TargetOpcode::G_MEMSET:
381 return selectMemOperation(ResVReg,
I);
383 case TargetOpcode::G_ICMP:
384 return selectICmp(ResVReg, ResType,
I);
385 case TargetOpcode::G_FCMP:
386 return selectFCmp(ResVReg, ResType,
I);
388 case TargetOpcode::G_FRAME_INDEX:
389 return selectFrameIndex(ResVReg, ResType,
I);
391 case TargetOpcode::G_LOAD:
392 return selectLoad(ResVReg, ResType,
I);
393 case TargetOpcode::G_STORE:
394 return selectStore(
I);
396 case TargetOpcode::G_BR:
397 return selectBranch(
I);
398 case TargetOpcode::G_BRCOND:
399 return selectBranchCond(
I);
401 case TargetOpcode::G_PHI:
402 return selectPhi(ResVReg, ResType,
I);
404 case TargetOpcode::G_FPTOSI:
405 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
406 case TargetOpcode::G_FPTOUI:
407 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
409 case TargetOpcode::G_SITOFP:
410 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
411 case TargetOpcode::G_UITOFP:
412 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
414 case TargetOpcode::G_CTPOP:
415 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
416 case TargetOpcode::G_SMIN:
417 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
418 case TargetOpcode::G_UMIN:
419 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
421 case TargetOpcode::G_SMAX:
422 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
423 case TargetOpcode::G_UMAX:
424 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
426 case TargetOpcode::G_FMA:
427 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
429 case TargetOpcode::G_FPOW:
430 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
431 case TargetOpcode::G_FPOWI:
432 return selectExtInst(ResVReg, ResType,
I, CL::pown);
434 case TargetOpcode::G_FEXP:
435 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
436 case TargetOpcode::G_FEXP2:
437 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
439 case TargetOpcode::G_FLOG:
440 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
441 case TargetOpcode::G_FLOG2:
442 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
443 case TargetOpcode::G_FLOG10:
444 return selectLog10(ResVReg, ResType,
I);
446 case TargetOpcode::G_FABS:
447 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
448 case TargetOpcode::G_ABS:
449 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
451 case TargetOpcode::G_FMINNUM:
452 case TargetOpcode::G_FMINIMUM:
453 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
454 case TargetOpcode::G_FMAXNUM:
455 case TargetOpcode::G_FMAXIMUM:
456 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
458 case TargetOpcode::G_FCOPYSIGN:
459 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
461 case TargetOpcode::G_FCEIL:
462 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
463 case TargetOpcode::G_FFLOOR:
464 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
466 case TargetOpcode::G_FCOS:
467 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
468 case TargetOpcode::G_FSIN:
469 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
471 case TargetOpcode::G_FSQRT:
472 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
474 case TargetOpcode::G_CTTZ:
475 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
476 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
477 case TargetOpcode::G_CTLZ:
478 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
479 return selectExtInst(ResVReg, ResType,
I, CL::clz);
481 case TargetOpcode::G_INTRINSIC_ROUND:
482 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
483 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
484 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
485 case TargetOpcode::G_INTRINSIC_TRUNC:
486 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
487 case TargetOpcode::G_FRINT:
488 case TargetOpcode::G_FNEARBYINT:
489 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
491 case TargetOpcode::G_SMULH:
492 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
493 case TargetOpcode::G_UMULH:
494 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
496 case TargetOpcode::G_SEXT:
497 return selectExt(ResVReg, ResType,
I,
true);
498 case TargetOpcode::G_ANYEXT:
499 case TargetOpcode::G_ZEXT:
500 return selectExt(ResVReg, ResType,
I,
false);
501 case TargetOpcode::G_TRUNC:
502 return selectTrunc(ResVReg, ResType,
I);
503 case TargetOpcode::G_FPTRUNC:
504 case TargetOpcode::G_FPEXT:
505 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
507 case TargetOpcode::G_PTRTOINT:
508 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
509 case TargetOpcode::G_INTTOPTR:
510 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
511 case TargetOpcode::G_BITCAST:
512 return selectBitcast(ResVReg, ResType,
I);
513 case TargetOpcode::G_ADDRSPACE_CAST:
514 return selectAddrSpaceCast(ResVReg, ResType,
I);
515 case TargetOpcode::G_PTR_ADD: {
520 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
524 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
525 (*II).getOpcode() == TargetOpcode::COPY ||
526 (*II).getOpcode() == SPIRV::OpVariable) &&
528 Register Idx = buildZerosVal(GR.getOrCreateSPIRVIntegerType(32,
I,
TII),
I);
530 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
532 .
addUse(GR.getSPIRVTypeID(ResType))
534 SPIRV::Opcode::InBoundsPtrAccessChain))
537 .
addUse(
I.getOperand(2).getReg());
541 case TargetOpcode::G_ATOMICRMW_OR:
542 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
543 case TargetOpcode::G_ATOMICRMW_ADD:
544 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
545 case TargetOpcode::G_ATOMICRMW_AND:
546 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
547 case TargetOpcode::G_ATOMICRMW_MAX:
548 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
549 case TargetOpcode::G_ATOMICRMW_MIN:
550 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
551 case TargetOpcode::G_ATOMICRMW_SUB:
552 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
553 case TargetOpcode::G_ATOMICRMW_XOR:
554 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
555 case TargetOpcode::G_ATOMICRMW_UMAX:
556 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
557 case TargetOpcode::G_ATOMICRMW_UMIN:
558 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
559 case TargetOpcode::G_ATOMICRMW_XCHG:
560 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
561 case TargetOpcode::G_ATOMIC_CMPXCHG:
562 return selectAtomicCmpXchg(ResVReg, ResType,
I);
564 case TargetOpcode::G_ATOMICRMW_FADD:
565 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
566 case TargetOpcode::G_ATOMICRMW_FSUB:
568 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
570 case TargetOpcode::G_ATOMICRMW_FMIN:
571 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
572 case TargetOpcode::G_ATOMICRMW_FMAX:
573 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
575 case TargetOpcode::G_FENCE:
576 return selectFence(
I);
578 case TargetOpcode::G_STACKSAVE:
579 return selectStackSave(ResVReg, ResType,
I);
580 case TargetOpcode::G_STACKRESTORE:
581 return selectStackRestore(
I);
583 case TargetOpcode::G_UNMERGE_VALUES:
591bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
594 CL::OpenCLExtInst CLInst)
const {
595 return selectExtInst(ResVReg, ResType,
I,
596 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
599bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
602 CL::OpenCLExtInst CLInst,
603 GL::GLSLExtInst GLInst)
const {
604 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
605 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
606 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
609bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
614 for (
const auto &Ex : Insts) {
615 SPIRV::InstructionSet::InstructionSet Set = Ex.first;
617 if (STI.canUseExtInstSet(Set)) {
619 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
621 .
addUse(GR.getSPIRVTypeID(ResType))
624 const unsigned NumOps =
I.getNumOperands();
625 for (
unsigned i = 1; i < NumOps; ++i)
626 MIB.add(
I.getOperand(i));
627 return MIB.constrainAllUses(
TII,
TRI, RBI);
633bool SPIRVInstructionSelector::selectUnOpWithSrc(
Register ResVReg,
637 unsigned Opcode)
const {
638 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
640 .
addUse(GR.getSPIRVTypeID(ResType))
645bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
648 unsigned Opcode)
const {
649 if (STI.isOpenCLEnv() &&
I.getOperand(1).isReg()) {
650 Register SrcReg =
I.getOperand(1).getReg();
653 MRI->def_instr_begin(SrcReg);
654 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
655 if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
663 case SPIRV::OpConvertPtrToU:
664 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertPtrToU);
666 case SPIRV::OpConvertUToPtr:
667 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertUToPtr);
671 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
672 TII.get(SPIRV::OpSpecConstantOp))
674 .
addUse(GR.getSPIRVTypeID(ResType))
680 return selectUnOpWithSrc(ResVReg, ResType,
I,
I.getOperand(1).getReg(),
684bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
687 Register OpReg =
I.getOperand(1).getReg();
688 SPIRVType *OpType = OpReg.
isValid() ? GR.getSPIRVTypeForVReg(OpReg) :
nullptr;
689 if (!GR.isBitcastCompatible(ResType, OpType))
691 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
697 return SPIRV::Scope::Invocation;
699 return SPIRV::Scope::Device;
701 return SPIRV::Scope::Workgroup;
703 return SPIRV::Scope::CrossDevice;
705 return SPIRV::Scope::Subgroup;
714 return SPIRV::Scope::Device;
720 if (
MemOp->isVolatile())
721 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
722 if (
MemOp->isNonTemporal())
723 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
724 if (
MemOp->getAlign().value())
725 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
727 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
729 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
736 if (Flags & MachineMemOperand::Flags::MOVolatile)
737 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
738 if (Flags & MachineMemOperand::Flags::MONonTemporal)
739 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
741 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
745bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
748 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
750 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
752 .
addUse(GR.getSPIRVTypeID(ResType))
754 if (!
I.getNumMemOperands()) {
755 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
757 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
762 return MIB.constrainAllUses(
TII,
TRI, RBI);
765bool SPIRVInstructionSelector::selectStore(
MachineInstr &
I)
const {
766 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
767 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
770 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
773 if (!
I.getNumMemOperands()) {
774 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
776 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
781 return MIB.constrainAllUses(
TII,
TRI, RBI);
784bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
787 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
789 "llvm.stacksave intrinsic: this instruction requires the following "
790 "SPIR-V extension: SPV_INTEL_variable_length_array",
793 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
795 .
addUse(GR.getSPIRVTypeID(ResType))
799bool SPIRVInstructionSelector::selectStackRestore(
MachineInstr &
I)
const {
800 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
802 "llvm.stackrestore intrinsic: this instruction requires the following "
803 "SPIR-V extension: SPV_INTEL_variable_length_array",
805 if (!
I.getOperand(0).isReg())
808 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
809 .
addUse(
I.getOperand(0).getReg())
813bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
816 Register SrcReg =
I.getOperand(1).getReg();
817 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
818 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
821 SPIRVType *ValTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
822 SPIRVType *ArrTy = GR.getOrCreateSPIRVArrayType(ValTy, Num,
I,
TII);
824 SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType(
825 ArrTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
835 GR.add(GV, GR.CurMF, VarReg);
838 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
840 .
addUse(GR.getSPIRVTypeID(VarTy))
841 .
addImm(SPIRV::StorageClass::UniformConstant)
844 SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
845 ValTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
847 selectUnOpWithSrc(SrcReg, SourceTy,
I, VarReg, SPIRV::OpBitcast);
849 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
850 .
addUse(
I.getOperand(0).getReg())
852 .
addUse(
I.getOperand(2).getReg());
853 if (
I.getNumMemOperands())
856 if (ResVReg.
isValid() && ResVReg != MIB->getOperand(0).getReg())
857 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY), ResVReg)
858 .
addUse(MIB->getOperand(0).getReg());
862bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
866 unsigned NegateOpcode)
const {
871 Register ScopeReg = buildI32Constant(Scope,
I);
879 Register MemSemReg = buildI32Constant(MemSem ,
I);
882 Register ValueReg =
I.getOperand(2).getReg();
883 if (NegateOpcode != 0) {
885 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
886 Result |= selectUnOpWithSrc(TmpReg, ResType,
I, ValueReg, NegateOpcode);
892 .
addUse(GR.getSPIRVTypeID(ResType))
901bool SPIRVInstructionSelector::selectUnmergeValues(
MachineInstr &
I)
const {
902 unsigned ArgI =
I.getNumOperands() - 1;
904 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
906 SrcReg.
isValid() ? GR.getSPIRVTypeForVReg(SrcReg) :
nullptr;
907 if (!DefType || DefType->
getOpcode() != SPIRV::OpTypeVector)
909 "cannot select G_UNMERGE_VALUES with a non-vector argument");
915 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
916 Register ResVReg =
I.getOperand(i).getReg();
917 SPIRVType *ResType = GR.getSPIRVTypeForVReg(ResVReg);
920 ResType = ScalarType;
921 MRI->setRegClass(ResVReg, &SPIRV::IDRegClass);
922 MRI->setType(ResVReg,
LLT::scalar(GR.getScalarOrVectorBitWidth(ResType)));
923 GR.assignSPIRVTypeToVReg(ResType, ResVReg, *GR.CurMF);
926 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
928 .
addUse(GR.getSPIRVTypeID(ResType))
930 .
addImm(
static_cast<int64_t
>(i));
931 Res |= MIB.constrainAllUses(
TII,
TRI, RBI);
936bool SPIRVInstructionSelector::selectFence(
MachineInstr &
I)
const {
939 Register MemSemReg = buildI32Constant(MemSem,
I);
942 Register ScopeReg = buildI32Constant(Scope,
I);
944 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
950bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
957 if (!isa<GIntrinsic>(
I)) {
962 ScopeReg = buildI32Constant(Scope,
I);
964 unsigned ScSem =
static_cast<uint32_t>(
968 MemSemEqReg = buildI32Constant(MemSemEq,
I);
972 MemSemEq == MemSemNeq ? MemSemEqReg : buildI32Constant(MemSemNeq,
I);
974 ScopeReg =
I.getOperand(5).getReg();
975 MemSemEqReg =
I.getOperand(6).getReg();
976 MemSemNeqReg =
I.getOperand(7).getReg();
981 SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
982 Register ACmpRes =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
985 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
987 .
addUse(GR.getSPIRVTypeID(SpvValTy))
995 Register CmpSuccReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
999 .
addUse(GR.getSPIRVTypeID(BoolTy))
1003 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1006 .
addUse(GR.getSPIRVTypeID(ResType))
1008 .
addUse(GR.getOrCreateUndef(
I, ResType,
TII))
1013 .
addUse(GR.getSPIRVTypeID(ResType))
1023 case SPIRV::StorageClass::Workgroup:
1024 case SPIRV::StorageClass::CrossWorkgroup:
1025 case SPIRV::StorageClass::Function:
1034 case SPIRV::StorageClass::DeviceOnlyINTEL:
1035 case SPIRV::StorageClass::HostOnlyINTEL:
1047bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
1052 auto UIs =
MRI->use_instructions(ResVReg);
1053 if (!UIs.empty() && ++UIs.begin() == UIs.end() &&
1054 (UIs.begin()->getOpcode() == SPIRV::OpConstantComposite ||
1055 UIs.begin()->getOpcode() == SPIRV::OpVariable ||
1057 Register NewReg =
I.getOperand(1).getReg();
1059 SPIRVType *SpvBaseTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
1060 ResType = GR.getOrCreateSPIRVPointerType(SpvBaseTy,
I,
TII,
1061 SPIRV::StorageClass::Generic);
1063 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1065 .
addUse(GR.getSPIRVTypeID(ResType))
1071 Register SrcPtr =
I.getOperand(1).getReg();
1072 SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);
1073 SPIRV::StorageClass::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtr);
1074 SPIRV::StorageClass::StorageClass DstSC = GR.getPointerStorageClass(ResVReg);
1082 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1085 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1088 Register Tmp =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1089 SPIRVType *GenericPtrTy = GR.getOrCreateSPIRVPointerType(
1090 SrcPtrTy,
I,
TII, SPIRV::StorageClass::Generic);
1095 .
addUse(GR.getSPIRVTypeID(GenericPtrTy))
1100 .
addUse(GR.getSPIRVTypeID(ResType))
1108 return selectUnOp(ResVReg, ResType,
I,
1109 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
1111 return selectUnOp(ResVReg, ResType,
I,
1112 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
1116 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
1123 return SPIRV::OpFOrdEqual;
1125 return SPIRV::OpFOrdGreaterThanEqual;
1127 return SPIRV::OpFOrdGreaterThan;
1129 return SPIRV::OpFOrdLessThanEqual;
1131 return SPIRV::OpFOrdLessThan;
1133 return SPIRV::OpFOrdNotEqual;
1135 return SPIRV::OpOrdered;
1137 return SPIRV::OpFUnordEqual;
1139 return SPIRV::OpFUnordGreaterThanEqual;
1141 return SPIRV::OpFUnordGreaterThan;
1143 return SPIRV::OpFUnordLessThanEqual;
1145 return SPIRV::OpFUnordLessThan;
1147 return SPIRV::OpFUnordNotEqual;
1149 return SPIRV::OpUnordered;
1159 return SPIRV::OpIEqual;
1161 return SPIRV::OpINotEqual;
1163 return SPIRV::OpSGreaterThanEqual;
1165 return SPIRV::OpSGreaterThan;
1167 return SPIRV::OpSLessThanEqual;
1169 return SPIRV::OpSLessThan;
1171 return SPIRV::OpUGreaterThanEqual;
1173 return SPIRV::OpUGreaterThan;
1175 return SPIRV::OpULessThanEqual;
1177 return SPIRV::OpULessThan;
1186 return SPIRV::OpPtrEqual;
1188 return SPIRV::OpPtrNotEqual;
1199 return SPIRV::OpLogicalEqual;
1201 return SPIRV::OpLogicalNotEqual;
1207bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
1210 unsigned OpAnyOrAll)
const {
1211 assert(
I.getNumOperands() == 3);
1212 assert(
I.getOperand(2).isReg());
1214 Register InputRegister =
I.getOperand(2).getReg();
1215 SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);
1220 bool IsBoolTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeBool);
1221 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
1222 if (IsBoolTy && !IsVectorTy) {
1223 assert(ResVReg ==
I.getOperand(0).getReg());
1224 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1225 TII.get(TargetOpcode::COPY))
1231 bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
1232 unsigned SpirvNotEqualId =
1233 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
1234 SPIRVType *SpvBoolScalarTy = GR.getOrCreateSPIRVBoolType(
I,
TII);
1239 NotEqualReg = IsBoolTy ? InputRegister
1240 :
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1242 SpvBoolTy = GR.getOrCreateSPIRVVectorType(SpvBoolTy, NumElts,
I,
TII);
1247 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
1249 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SpirvNotEqualId))
1251 .
addUse(GR.getSPIRVTypeID(SpvBoolTy))
1260 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(OpAnyOrAll))
1262 .
addUse(GR.getSPIRVTypeID(SpvBoolScalarTy))
1267bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
1270 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
1273bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
1276 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
1279bool SPIRVInstructionSelector::selectFmix(
Register ResVReg,
1283 assert(
I.getNumOperands() == 5);
1284 assert(
I.getOperand(2).isReg());
1285 assert(
I.getOperand(3).isReg());
1286 assert(
I.getOperand(4).isReg());
1289 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1291 .
addUse(GR.getSPIRVTypeID(ResType))
1292 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1294 .
addUse(
I.getOperand(2).getReg())
1295 .
addUse(
I.getOperand(3).getReg())
1296 .
addUse(
I.getOperand(4).getReg())
1300bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
1304 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
1306 .
addUse(GR.getSPIRVTypeID(ResType))
1307 .
addUse(
I.getOperand(1).getReg())
1311bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
1319 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
1321 Register OpReg =
I.getOperand(1).getReg();
1324 switch (
Def->getOpcode()) {
1325 case SPIRV::ASSIGN_TYPE:
1327 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
1328 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1329 Reg =
Def->getOperand(2).getReg();
1332 case SPIRV::OpUndef:
1333 Reg =
Def->getOperand(1).getReg();
1336 unsigned DestOpCode;
1337 if (
Reg.isValid()) {
1338 DestOpCode = SPIRV::OpConstantNull;
1340 DestOpCode = TargetOpcode::COPY;
1343 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
1344 .
addDef(
I.getOperand(0).getReg())
1351bool SPIRVInstructionSelector::selectConstVector(
Register ResVReg,
1361 SPIRVType *ConstTy = this->MRI->getVRegDef(MO.getReg());
1362 assert(ConstTy && ConstTy->getOpcode() == SPIRV::ASSIGN_TYPE &&
1363 ConstTy->getOperand(1).isReg());
1364 Register ConstReg = ConstTy->getOperand(1).getReg();
1365 const MachineInstr *Const = this->MRI->getVRegDef(ConstReg);
1367 return (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
1368 Const->getOpcode() == TargetOpcode::G_FCONSTANT);
1371 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1372 TII.get(SPIRV::OpConstantComposite))
1374 .
addUse(GR.getSPIRVTypeID(ResType));
1375 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
1376 MIB.
addUse(
I.getOperand(i).getReg());
1386 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1391 unsigned N = OpDef->
getOpcode() == TargetOpcode::G_CONSTANT
1399 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1404 return OpDef->
getOpcode() == TargetOpcode::G_CONSTANT ||
1405 OpDef->
getOpcode() == TargetOpcode::G_FCONSTANT;
1415bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
1419 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1420 N = GR.getScalarOrVectorComponentCount(ResType);
1421 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
1426 unsigned OpIdx =
I.getNumExplicitDefs();
1427 if (!
I.getOperand(OpIdx).isReg())
1431 Register OpReg =
I.getOperand(OpIdx).getReg();
1434 if (!IsConst &&
N < 2)
1436 "There must be at least two constituent operands in a vector");
1438 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1439 TII.get(IsConst ? SPIRV::OpConstantComposite
1440 : SPIRV::OpCompositeConstruct))
1442 .
addUse(GR.getSPIRVTypeID(ResType));
1443 for (
unsigned i = 0; i <
N; ++i)
1448bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
1452 Register Cmp0 =
I.getOperand(2).getReg();
1453 Register Cmp1 =
I.getOperand(3).getReg();
1454 assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
1455 GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
1456 "CMP operands should have the same type");
1457 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
1459 .
addUse(GR.getSPIRVTypeID(ResType))
1465bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
1468 auto Pred =
I.getOperand(1).getPredicate();
1471 Register CmpOperand =
I.getOperand(2).getReg();
1472 if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
1474 else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
1478 return selectCmp(ResVReg, ResType, CmpOpc,
I);
1484 assert(
I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
1485 "Expected G_FCONSTANT");
1486 const ConstantFP *FPImm =
I.getOperand(1).getFPImm();
1493 assert(
I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1494 "Expected G_CONSTANT");
1495 addNumImm(
I.getOperand(1).getCImm()->getValue(), MIB);
1503 ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32,
I,
TII);
1505 auto ConstInt = ConstantInt::get(LLVMTy, Val);
1506 Register NewReg = GR.find(ConstInt, GR.CurMF);
1509 GR.add(ConstInt, GR.CurMF, NewReg);
1513 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1515 .
addUse(GR.getSPIRVTypeID(SpvI32Ty));
1517 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1519 .
addUse(GR.getSPIRVTypeID(SpvI32Ty))
1527bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
1531 return selectCmp(ResVReg, ResType, CmpOp,
I);
1537 bool ZeroAsNull = STI.isOpenCLEnv();
1538 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1539 return GR.getOrCreateConstVector(0UL,
I, ResType,
TII, ZeroAsNull);
1540 return GR.getOrCreateConstInt(0,
I, ResType,
TII, ZeroAsNull);
1560 bool ZeroAsNull = STI.isOpenCLEnv();
1562 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1563 return GR.getOrCreateConstVector(VZero,
I, ResType,
TII, ZeroAsNull);
1564 return GR.getOrCreateConstFP(VZero,
I, ResType,
TII, ZeroAsNull);
1570 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1573 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1578bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
1581 bool IsSigned)
const {
1583 Register ZeroReg = buildZerosVal(ResType,
I);
1584 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
1586 GR.isScalarOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool);
1588 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectSIVCond;
1589 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1591 .
addUse(GR.getSPIRVTypeID(ResType))
1592 .
addUse(
I.getOperand(1).getReg())
1598bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
1601 unsigned Opcode)
const {
1602 Register SrcReg =
I.getOperand(1).getReg();
1605 if (GR.isScalarOrVectorOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
1606 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1608 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1610 TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts,
I,
TII);
1612 SrcReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1613 selectSelect(SrcReg, TmpType,
I,
false);
1615 return selectUnOpWithSrc(ResVReg, ResType,
I, SrcReg, Opcode);
1618bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
1621 Register SrcReg =
I.getOperand(1).getReg();
1622 if (GR.isScalarOrVectorOfType(SrcReg, SPIRV::OpTypeBool))
1623 return selectSelect(ResVReg, ResType,
I, IsSigned);
1625 SPIRVType *SrcType = GR.getSPIRVTypeForVReg(SrcReg);
1626 if (SrcType == ResType)
1627 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1628 TII.get(TargetOpcode::COPY))
1633 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1634 return selectUnOp(ResVReg, ResType,
I, Opcode);
1637bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
1643 Register BitIntReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1644 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
1645 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
1647 Register One = buildOnesVal(
false, IntTy,
I);
1651 .
addUse(GR.getSPIRVTypeID(IntTy))
1655 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpINotEqual))
1657 .
addUse(GR.getSPIRVTypeID(BoolTy))
1663bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
1666 Register IntReg =
I.getOperand(1).getReg();
1667 const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
1668 if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool))
1669 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
1670 if (ArgType == ResType)
1671 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1672 TII.get(TargetOpcode::COPY))
1676 bool IsSigned = GR.isScalarOrVectorSigned(ResType);
1677 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1678 return selectUnOp(ResVReg, ResType,
I, Opcode);
1681bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
1685 unsigned TyOpcode = ResType->
getOpcode();
1686 assert(TyOpcode != SPIRV::OpTypePointer ||
Imm.isZero());
1688 if ((TyOpcode == SPIRV::OpTypePointer || TyOpcode == SPIRV::OpTypeEvent) &&
1690 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1692 .
addUse(GR.getSPIRVTypeID(ResType))
1694 if (TyOpcode == SPIRV::OpTypeInt) {
1695 assert(
Imm.getBitWidth() <= 64 &&
"Unsupported integer width!");
1699 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
1704 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1706 .
addUse(GR.getSPIRVTypeID(ResType));
1713bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
1716 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1718 .
addUse(GR.getSPIRVTypeID(ResType))
1725 if (TypeInst->
getOpcode() != SPIRV::ASSIGN_TYPE)
1729 return ImmInst->
getOpcode() == TargetOpcode::G_CONSTANT;
1739bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
1743 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
1745 .
addUse(GR.getSPIRVTypeID(ResType))
1747 .
addUse(
I.getOperand(3).getReg())
1749 .
addUse(
I.getOperand(2).getReg());
1750 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
1755bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
1759 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1761 .
addUse(GR.getSPIRVTypeID(ResType))
1762 .
addUse(
I.getOperand(2).getReg());
1763 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
1768bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
1772 return selectInsertVal(ResVReg, ResType,
I);
1774 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
1776 .
addUse(GR.getSPIRVTypeID(ResType))
1777 .
addUse(
I.getOperand(2).getReg())
1778 .
addUse(
I.getOperand(3).getReg())
1779 .
addUse(
I.getOperand(4).getReg())
1783bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
1787 return selectExtractVal(ResVReg, ResType,
I);
1789 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
1791 .
addUse(GR.getSPIRVTypeID(ResType))
1792 .
addUse(
I.getOperand(2).getReg())
1793 .
addUse(
I.getOperand(3).getReg())
1797bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
1800 const bool IsGEPInBounds =
I.getOperand(2).getImm();
1805 const unsigned Opcode = STI.isVulkanEnv()
1806 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
1807 : SPIRV::OpAccessChain)
1808 : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
1809 : SPIRV::OpPtrAccessChain);
1811 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1813 .
addUse(GR.getSPIRVTypeID(ResType))
1815 .
addUse(
I.getOperand(3).getReg());
1817 const unsigned StartingIndex =
1818 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
1821 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
1822 Res.addUse(
I.getOperand(i).getReg());
1823 return Res.constrainAllUses(
TII,
TRI, RBI);
1827bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
1830 unsigned Lim =
I.getNumExplicitOperands();
1831 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
1832 Register OpReg =
I.getOperand(i).getReg();
1834 SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
1836 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
1843 Register WrapReg = GR.find(OpDefine, MF);
1849 WrapReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1850 GR.add(OpDefine, MF, WrapReg);
1854 GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF);
1858 .
addUse(GR.getSPIRVTypeID(OpType))
1868bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
1874 case Intrinsic::spv_load:
1875 return selectLoad(ResVReg, ResType,
I);
1876 case Intrinsic::spv_store:
1877 return selectStore(
I);
1878 case Intrinsic::spv_extractv:
1879 return selectExtractVal(ResVReg, ResType,
I);
1880 case Intrinsic::spv_insertv:
1881 return selectInsertVal(ResVReg, ResType,
I);
1882 case Intrinsic::spv_extractelt:
1883 return selectExtractElt(ResVReg, ResType,
I);
1884 case Intrinsic::spv_insertelt:
1885 return selectInsertElt(ResVReg, ResType,
I);
1886 case Intrinsic::spv_gep:
1887 return selectGEP(ResVReg, ResType,
I);
1888 case Intrinsic::spv_unref_global:
1889 case Intrinsic::spv_init_global: {
1892 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
1895 return selectGlobalValue(
MI->getOperand(0).getReg(), *
MI,
Init);
1897 case Intrinsic::spv_undef: {
1898 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1900 .
addUse(GR.getSPIRVTypeID(ResType));
1903 case Intrinsic::spv_const_composite: {
1905 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
1907 unsigned Opcode = SPIRV::OpConstantNull;
1910 Opcode = SPIRV::OpConstantComposite;
1911 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
1914 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
1916 .
addUse(GR.getSPIRVTypeID(ResType));
1919 for (
Register OpReg : CompositeArgs)
1924 case Intrinsic::spv_assign_name: {
1925 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
1926 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
1927 for (
unsigned i =
I.getNumExplicitDefs() + 2;
1928 i <
I.getNumExplicitOperands(); ++i) {
1929 MIB.
addImm(
I.getOperand(i).getImm());
1933 case Intrinsic::spv_switch: {
1934 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
1935 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
1936 if (
I.getOperand(i).isReg())
1937 MIB.
addReg(
I.getOperand(i).getReg());
1938 else if (
I.getOperand(i).isCImm())
1939 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
1940 else if (
I.getOperand(i).isMBB())
1941 MIB.
addMBB(
I.getOperand(i).getMBB());
1947 case Intrinsic::spv_cmpxchg:
1948 return selectAtomicCmpXchg(ResVReg, ResType,
I);
1949 case Intrinsic::spv_unreachable:
1950 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable));
1952 case Intrinsic::spv_alloca:
1953 return selectFrameIndex(ResVReg, ResType,
I);
1954 case Intrinsic::spv_alloca_array:
1955 return selectAllocaArray(ResVReg, ResType,
I);
1956 case Intrinsic::spv_assume:
1957 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
1958 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
1959 .
addUse(
I.getOperand(1).getReg());
1961 case Intrinsic::spv_expect:
1962 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
1963 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
1965 .
addUse(GR.getSPIRVTypeID(ResType))
1966 .
addUse(
I.getOperand(2).getReg())
1967 .
addUse(
I.getOperand(3).getReg());
1969 case Intrinsic::spv_thread_id:
1970 return selectSpvThreadId(ResVReg, ResType,
I);
1971 case Intrinsic::spv_all:
1972 return selectAll(ResVReg, ResType,
I);
1973 case Intrinsic::spv_any:
1974 return selectAny(ResVReg, ResType,
I);
1975 case Intrinsic::spv_lerp:
1976 return selectFmix(ResVReg, ResType,
I);
1977 case Intrinsic::spv_lifetime_start:
1978 case Intrinsic::spv_lifetime_end: {
1979 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
1980 : SPIRV::OpLifetimeStop;
1981 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
1982 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
1983 unsigned PonteeOpType = GR.getPointeeTypeOp(PtrReg);
1984 bool IsNonvoidPtr = PonteeOpType != 0 && PonteeOpType != SPIRV::OpTypeVoid;
1985 if (
Size == -1 || IsNonvoidPtr)
1990 std::string DiagMsg;
1993 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
2000bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
2007 TII.get(SPIRV::OpVariableLengthArrayINTEL))
2009 .
addUse(GR.getSPIRVTypeID(ResType))
2010 .
addUse(
I.getOperand(2).getReg())
2014bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
2022 bool IsHeader =
false;
2024 for (; It != E && It !=
I; ++It) {
2025 Opcode = It->getOpcode();
2026 if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
2028 }
else if (IsHeader &&
2029 !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
2034 return BuildMI(*
MBB, It, It->getDebugLoc(),
TII.get(SPIRV::OpVariable))
2036 .
addUse(GR.getSPIRVTypeID(ResType))
2041bool SPIRVInstructionSelector::selectBranch(
MachineInstr &
I)
const {
2048 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
2049 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2052 .
addMBB(
I.getOperand(0).getMBB())
2056 .
addMBB(
I.getOperand(0).getMBB())
2060bool SPIRVInstructionSelector::selectBranchCond(
MachineInstr &
I)
const {
2073 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
2080 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2081 .
addUse(
I.getOperand(0).getReg())
2082 .
addMBB(
I.getOperand(1).getMBB())
2087bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
2090 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
2092 .
addUse(GR.getSPIRVTypeID(ResType));
2093 const unsigned NumOps =
I.getNumOperands();
2094 for (
unsigned i = 1; i < NumOps; i += 2) {
2095 MIB.
addUse(
I.getOperand(i + 0).getReg());
2096 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
2101bool SPIRVInstructionSelector::selectGlobalValue(
2106 Type *GVType = GR.getDeducedGlobalValueType(GV);
2111 SPIRV::AccessQualifier::ReadWrite,
false);
2112 PointerBaseType = GR.getOrCreateSPIRVArrayType(
2115 PointerBaseType = GR.getOrCreateSPIRVType(
2116 GVType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2118 SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(
2119 PointerBaseType,
I,
TII,
2122 std::string GlobalIdent;
2124 unsigned &
ID = UnnamedGlobalIDs[GV];
2126 ID = UnnamedGlobalIDs.size();
2127 GlobalIdent =
"__unnamed_" +
Twine(
ID).
str();
2142 if (isa<Function>(GV)) {
2145 Register NewReg = GR.find(ConstVal, GR.CurMF);
2148 GR.add(ConstVal, GR.CurMF, NewReg);
2150 STI.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)
2151 ? dyn_cast<Function>(GV)
2159 MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass);
2162 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
2164 .
addUse(GR.getSPIRVTypeID(ResType))
2170 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2172 .
addUse(GR.getSPIRVTypeID(ResType))
2175 assert(NewReg != ResVReg);
2176 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
2181 auto GlobalVar = cast<GlobalVariable>(GV);
2184 bool HasInit =
GlobalVar->hasInitializer() &&
2185 !isa<UndefValue>(
GlobalVar->getInitializer());
2188 if (HasInit && !
Init)
2192 SPIRV::StorageClass::StorageClass Storage =
2195 Storage != SPIRV::StorageClass::Function;
2196 SPIRV::LinkageType::LinkageType LnkType =
2198 ? SPIRV::LinkageType::Import
2200 STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
2201 ? SPIRV::LinkageType::LinkOnceODR
2202 : SPIRV::LinkageType::Export);
2204 Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
2206 HasLnkTy, LnkType, MIRBuilder,
true);
2207 return Reg.isValid();
2210bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
2213 if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
2214 return selectExtInst(ResVReg, ResType,
I, CL::log10);
2226 Register VarReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2228 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2230 .
addUse(GR.getSPIRVTypeID(ResType))
2231 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
2233 .
add(
I.getOperand(1))
2238 ResType->
getOpcode() == SPIRV::OpTypeFloat);
2241 ResType->
getOpcode() == SPIRV::OpTypeVector
2245 GR.buildConstantFP(
APFloat(0.30103f), MIRBuilder, SpirvScalarType);
2248 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
2249 ? SPIRV::OpVectorTimesScalar
2253 .
addUse(GR.getSPIRVTypeID(ResType))
2261bool SPIRVInstructionSelector::selectSpvThreadId(
Register ResVReg,
2269 const SPIRVType *U32Type = GR.getOrCreateSPIRVIntegerType(32, MIRBuilder);
2271 GR.getOrCreateSPIRVVectorType(U32Type, 3, MIRBuilder);
2272 const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
2273 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
2277 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
2278 MIRBuilder.getMRI()->setType(NewRegister,
LLT::pointer(0, 32));
2279 GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());
2282 Register Variable = GR.buildGlobalVariable(
2283 NewRegister, PtrType,
2285 SPIRV::StorageClass::Input,
nullptr,
true,
true,
2286 SPIRV::LinkageType::Import, MIRBuilder,
false);
2290 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2291 MIRBuilder.getMRI()->setType(LoadedRegister,
LLT::pointer(0, 32));
2292 GR.assignSPIRVTypeToVReg(Vec3Ty, LoadedRegister, MIRBuilder.getMF());
2295 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
2297 .
addUse(GR.getSPIRVTypeID(Vec3Ty))
2302 assert(
I.getOperand(2).isReg());
2303 Register ThreadIdReg =
I.getOperand(2).getReg();
2309 assert(Const &&
Const->getOpcode() == TargetOpcode::G_CONSTANT);
2315 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2317 .
addUse(GR.getSPIRVTypeID(ResType))
2328 return new SPIRVInstructionSelector(
TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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)
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
const char LLVMTargetMachineRef TM
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 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 SPIRV::Scope::Scope getScope(SyncScope::ID Ord, SPIRVMachineModuleInfo *MMI)
static unsigned getBoolCmpOpcode(unsigned PredNum)
static unsigned getICmpOpcode(unsigned PredNum)
static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef)
static int64_t foldImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
static bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
static unsigned getPtrCmpOpcode(unsigned Pred)
static unsigned getArrayComponentCount(MachineRegisterInfo *MRI, const SPIRVType *ResType)
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.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
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.
MachineModuleInfo & getMMI() const
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.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
This class can be derived from and used by targets to hold private target-specific information for ea...
This class contains meta information specific to a module.
const Module * getModule() const
Ty & getObjFileInfo()
Keep track of various per-module pieces of information for backends that would like to do so.
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 ...
LLVMContext & getContext() const
Get the global data context.
Analysis providing profile information.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
SyncScope::ID SubGroupSSID
SPIRVMachineModuleInfo(const MachineModuleInfo &MMI)
SyncScope::ID AllSVMDevicesSSID
SyncScope::ID Work_ItemSSID
SyncScope::ID WorkGroupSSID
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)
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)