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;
188 bool IsSigned)
const;
190 bool IsSigned,
unsigned Opcode)
const;
192 bool IsSigned)
const;
232 GL::GLSLExtInst GLInst)
const;
245 const SPIRVType *ResType =
nullptr)
const;
258#define GET_GLOBALISEL_IMPL
259#include "SPIRVGenGlobalISel.inc"
260#undef GET_GLOBALISEL_IMPL
266 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
268#include
"SPIRVGenGlobalISel.inc"
271#include
"SPIRVGenGlobalISel.inc"
282 GR.setCurrentFunc(MF);
283 InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
292 assert(
I.getParent() &&
"Instruction should be in a basic block!");
293 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
298 if (Opcode == SPIRV::ASSIGN_TYPE) {
299 Register DstReg =
I.getOperand(0).getReg();
300 Register SrcReg =
I.getOperand(1).getReg();
301 auto *
Def =
MRI->getVRegDef(SrcReg);
303 if (
MRI->getType(DstReg).isPointer())
305 bool Res = selectImpl(
I, *CoverageInfo);
306 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
310 MRI->replaceRegWith(SrcReg, DstReg);
311 I.removeFromParent();
313 }
else if (
I.getNumDefs() == 1) {
320 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
321 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
327 bool HasDefs =
I.getNumDefs() > 0;
329 SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) :
nullptr;
330 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
331 if (spvSelect(ResVReg, ResType,
I)) {
333 for (
unsigned i = 0; i <
I.getNumDefs(); ++i)
335 I.removeFromParent();
341bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
344 const unsigned Opcode =
I.getOpcode();
346 return selectImpl(
I, *CoverageInfo);
348 case TargetOpcode::G_CONSTANT:
349 return selectConst(ResVReg, ResType,
I.getOperand(1).getCImm()->getValue(),
351 case TargetOpcode::G_GLOBAL_VALUE:
352 return selectGlobalValue(ResVReg,
I);
353 case TargetOpcode::G_IMPLICIT_DEF:
354 return selectOpUndef(ResVReg, ResType,
I);
355 case TargetOpcode::G_FREEZE:
356 return selectFreeze(ResVReg, ResType,
I);
358 case TargetOpcode::G_INTRINSIC:
359 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
360 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
361 return selectIntrinsic(ResVReg, ResType,
I);
362 case TargetOpcode::G_BITREVERSE:
363 return selectBitreverse(ResVReg, ResType,
I);
365 case TargetOpcode::G_BUILD_VECTOR:
366 return selectConstVector(ResVReg, ResType,
I);
367 case TargetOpcode::G_SPLAT_VECTOR:
368 return selectSplatVector(ResVReg, ResType,
I);
370 case TargetOpcode::G_SHUFFLE_VECTOR: {
372 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
374 .
addUse(GR.getSPIRVTypeID(ResType))
375 .
addUse(
I.getOperand(1).getReg())
376 .
addUse(
I.getOperand(2).getReg());
377 for (
auto V :
I.getOperand(3).getShuffleMask())
381 case TargetOpcode::G_MEMMOVE:
382 case TargetOpcode::G_MEMCPY:
383 case TargetOpcode::G_MEMSET:
384 return selectMemOperation(ResVReg,
I);
386 case TargetOpcode::G_ICMP:
387 return selectICmp(ResVReg, ResType,
I);
388 case TargetOpcode::G_FCMP:
389 return selectFCmp(ResVReg, ResType,
I);
391 case TargetOpcode::G_FRAME_INDEX:
392 return selectFrameIndex(ResVReg, ResType,
I);
394 case TargetOpcode::G_LOAD:
395 return selectLoad(ResVReg, ResType,
I);
396 case TargetOpcode::G_STORE:
397 return selectStore(
I);
399 case TargetOpcode::G_BR:
400 return selectBranch(
I);
401 case TargetOpcode::G_BRCOND:
402 return selectBranchCond(
I);
404 case TargetOpcode::G_PHI:
405 return selectPhi(ResVReg, ResType,
I);
407 case TargetOpcode::G_FPTOSI:
408 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
409 case TargetOpcode::G_FPTOUI:
410 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
412 case TargetOpcode::G_SITOFP:
413 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
414 case TargetOpcode::G_UITOFP:
415 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
417 case TargetOpcode::G_CTPOP:
418 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
419 case TargetOpcode::G_SMIN:
420 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
421 case TargetOpcode::G_UMIN:
422 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
424 case TargetOpcode::G_SMAX:
425 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
426 case TargetOpcode::G_UMAX:
427 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
429 case TargetOpcode::G_FMA:
430 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
432 case TargetOpcode::G_FPOW:
433 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
434 case TargetOpcode::G_FPOWI:
435 return selectExtInst(ResVReg, ResType,
I, CL::pown);
437 case TargetOpcode::G_FEXP:
438 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
439 case TargetOpcode::G_FEXP2:
440 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
442 case TargetOpcode::G_FLOG:
443 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
444 case TargetOpcode::G_FLOG2:
445 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
446 case TargetOpcode::G_FLOG10:
447 return selectLog10(ResVReg, ResType,
I);
449 case TargetOpcode::G_FABS:
450 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
451 case TargetOpcode::G_ABS:
452 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
454 case TargetOpcode::G_FMINNUM:
455 case TargetOpcode::G_FMINIMUM:
456 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::NMin);
457 case TargetOpcode::G_FMAXNUM:
458 case TargetOpcode::G_FMAXIMUM:
459 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::NMax);
461 case TargetOpcode::G_FCOPYSIGN:
462 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
464 case TargetOpcode::G_FCEIL:
465 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
466 case TargetOpcode::G_FFLOOR:
467 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
469 case TargetOpcode::G_FCOS:
470 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
471 case TargetOpcode::G_FSIN:
472 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
473 case TargetOpcode::G_FTAN:
474 return selectExtInst(ResVReg, ResType,
I, CL::tan, GL::Tan);
475 case TargetOpcode::G_FACOS:
476 return selectExtInst(ResVReg, ResType,
I, CL::acos, GL::Acos);
477 case TargetOpcode::G_FASIN:
478 return selectExtInst(ResVReg, ResType,
I, CL::asin, GL::Asin);
479 case TargetOpcode::G_FATAN:
480 return selectExtInst(ResVReg, ResType,
I, CL::atan, GL::Atan);
481 case TargetOpcode::G_FCOSH:
482 return selectExtInst(ResVReg, ResType,
I, CL::cosh, GL::Cosh);
483 case TargetOpcode::G_FSINH:
484 return selectExtInst(ResVReg, ResType,
I, CL::sinh, GL::Sinh);
485 case TargetOpcode::G_FTANH:
486 return selectExtInst(ResVReg, ResType,
I, CL::tanh, GL::Tanh);
488 case TargetOpcode::G_FSQRT:
489 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
491 case TargetOpcode::G_CTTZ:
492 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
493 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
494 case TargetOpcode::G_CTLZ:
495 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
496 return selectExtInst(ResVReg, ResType,
I, CL::clz);
498 case TargetOpcode::G_INTRINSIC_ROUND:
499 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
500 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
501 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
502 case TargetOpcode::G_INTRINSIC_TRUNC:
503 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
504 case TargetOpcode::G_FRINT:
505 case TargetOpcode::G_FNEARBYINT:
506 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
508 case TargetOpcode::G_SMULH:
509 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
510 case TargetOpcode::G_UMULH:
511 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
513 case TargetOpcode::G_SADDSAT:
514 return selectExtInst(ResVReg, ResType,
I, CL::s_add_sat);
515 case TargetOpcode::G_UADDSAT:
516 return selectExtInst(ResVReg, ResType,
I, CL::u_add_sat);
517 case TargetOpcode::G_SSUBSAT:
518 return selectExtInst(ResVReg, ResType,
I, CL::s_sub_sat);
519 case TargetOpcode::G_USUBSAT:
520 return selectExtInst(ResVReg, ResType,
I, CL::u_sub_sat);
522 case TargetOpcode::G_SEXT:
523 return selectExt(ResVReg, ResType,
I,
true);
524 case TargetOpcode::G_ANYEXT:
525 case TargetOpcode::G_ZEXT:
526 return selectExt(ResVReg, ResType,
I,
false);
527 case TargetOpcode::G_TRUNC:
528 return selectTrunc(ResVReg, ResType,
I);
529 case TargetOpcode::G_FPTRUNC:
530 case TargetOpcode::G_FPEXT:
531 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
533 case TargetOpcode::G_PTRTOINT:
534 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
535 case TargetOpcode::G_INTTOPTR:
536 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
537 case TargetOpcode::G_BITCAST:
538 return selectBitcast(ResVReg, ResType,
I);
539 case TargetOpcode::G_ADDRSPACE_CAST:
540 return selectAddrSpaceCast(ResVReg, ResType,
I);
541 case TargetOpcode::G_PTR_ADD: {
546 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
550 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
551 (*II).getOpcode() == TargetOpcode::COPY ||
552 (*II).getOpcode() == SPIRV::OpVariable) &&
554 Register Idx = buildZerosVal(GR.getOrCreateSPIRVIntegerType(32,
I,
TII),
I);
556 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
558 .
addUse(GR.getSPIRVTypeID(ResType))
560 SPIRV::Opcode::InBoundsPtrAccessChain))
563 .
addUse(
I.getOperand(2).getReg());
567 case TargetOpcode::G_ATOMICRMW_OR:
568 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
569 case TargetOpcode::G_ATOMICRMW_ADD:
570 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
571 case TargetOpcode::G_ATOMICRMW_AND:
572 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
573 case TargetOpcode::G_ATOMICRMW_MAX:
574 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
575 case TargetOpcode::G_ATOMICRMW_MIN:
576 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
577 case TargetOpcode::G_ATOMICRMW_SUB:
578 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
579 case TargetOpcode::G_ATOMICRMW_XOR:
580 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
581 case TargetOpcode::G_ATOMICRMW_UMAX:
582 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
583 case TargetOpcode::G_ATOMICRMW_UMIN:
584 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
585 case TargetOpcode::G_ATOMICRMW_XCHG:
586 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
587 case TargetOpcode::G_ATOMIC_CMPXCHG:
588 return selectAtomicCmpXchg(ResVReg, ResType,
I);
590 case TargetOpcode::G_ATOMICRMW_FADD:
591 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT);
592 case TargetOpcode::G_ATOMICRMW_FSUB:
594 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFAddEXT,
596 case TargetOpcode::G_ATOMICRMW_FMIN:
597 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMinEXT);
598 case TargetOpcode::G_ATOMICRMW_FMAX:
599 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicFMaxEXT);
601 case TargetOpcode::G_FENCE:
602 return selectFence(
I);
604 case TargetOpcode::G_STACKSAVE:
605 return selectStackSave(ResVReg, ResType,
I);
606 case TargetOpcode::G_STACKRESTORE:
607 return selectStackRestore(
I);
609 case TargetOpcode::G_UNMERGE_VALUES:
617bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
620 CL::OpenCLExtInst CLInst)
const {
621 return selectExtInst(ResVReg, ResType,
I,
622 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
625bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
628 CL::OpenCLExtInst CLInst,
629 GL::GLSLExtInst GLInst)
const {
630 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
631 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
632 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
635bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
640 for (
const auto &Ex : Insts) {
641 SPIRV::InstructionSet::InstructionSet Set = Ex.first;
643 if (STI.canUseExtInstSet(Set)) {
645 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
647 .
addUse(GR.getSPIRVTypeID(ResType))
650 const unsigned NumOps =
I.getNumOperands();
651 for (
unsigned i = 1; i < NumOps; ++i)
652 MIB.add(
I.getOperand(i));
653 return MIB.constrainAllUses(
TII,
TRI, RBI);
659bool SPIRVInstructionSelector::selectUnOpWithSrc(
Register ResVReg,
663 unsigned Opcode)
const {
664 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
666 .
addUse(GR.getSPIRVTypeID(ResType))
671bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
674 unsigned Opcode)
const {
675 if (STI.isOpenCLEnv() &&
I.getOperand(1).isReg()) {
676 Register SrcReg =
I.getOperand(1).getReg();
679 MRI->def_instr_begin(SrcReg);
680 DefIt !=
MRI->def_instr_end(); DefIt = std::next(DefIt)) {
681 if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
689 case SPIRV::OpConvertPtrToU:
690 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertPtrToU);
692 case SPIRV::OpConvertUToPtr:
693 SpecOpcode =
static_cast<uint32_t>(SPIRV::Opcode::ConvertUToPtr);
697 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
698 TII.get(SPIRV::OpSpecConstantOp))
700 .
addUse(GR.getSPIRVTypeID(ResType))
706 return selectUnOpWithSrc(ResVReg, ResType,
I,
I.getOperand(1).getReg(),
710bool SPIRVInstructionSelector::selectBitcast(
Register ResVReg,
713 Register OpReg =
I.getOperand(1).getReg();
714 SPIRVType *OpType = OpReg.
isValid() ? GR.getSPIRVTypeForVReg(OpReg) :
nullptr;
715 if (!GR.isBitcastCompatible(ResType, OpType))
717 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
723 return SPIRV::Scope::Invocation;
725 return SPIRV::Scope::Device;
727 return SPIRV::Scope::Workgroup;
729 return SPIRV::Scope::CrossDevice;
731 return SPIRV::Scope::Subgroup;
740 return SPIRV::Scope::Device;
746 if (
MemOp->isVolatile())
747 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
748 if (
MemOp->isNonTemporal())
749 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
750 if (
MemOp->getAlign().value())
751 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
753 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
755 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
762 if (Flags & MachineMemOperand::Flags::MOVolatile)
763 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
764 if (Flags & MachineMemOperand::Flags::MONonTemporal)
765 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
767 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
771bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
774 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
776 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
778 .
addUse(GR.getSPIRVTypeID(ResType))
780 if (!
I.getNumMemOperands()) {
781 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
783 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
788 return MIB.constrainAllUses(
TII,
TRI, RBI);
791bool SPIRVInstructionSelector::selectStore(
MachineInstr &
I)
const {
792 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
793 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
796 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
799 if (!
I.getNumMemOperands()) {
800 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
802 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
807 return MIB.constrainAllUses(
TII,
TRI, RBI);
810bool SPIRVInstructionSelector::selectStackSave(
Register ResVReg,
813 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
815 "llvm.stacksave intrinsic: this instruction requires the following "
816 "SPIR-V extension: SPV_INTEL_variable_length_array",
819 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSaveMemoryINTEL))
821 .
addUse(GR.getSPIRVTypeID(ResType))
825bool SPIRVInstructionSelector::selectStackRestore(
MachineInstr &
I)
const {
826 if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
828 "llvm.stackrestore intrinsic: this instruction requires the following "
829 "SPIR-V extension: SPV_INTEL_variable_length_array",
831 if (!
I.getOperand(0).isReg())
834 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpRestoreMemoryINTEL))
835 .
addUse(
I.getOperand(0).getReg())
839bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
842 Register SrcReg =
I.getOperand(1).getReg();
843 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
844 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
847 SPIRVType *ValTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
848 SPIRVType *ArrTy = GR.getOrCreateSPIRVArrayType(ValTy, Num,
I,
TII);
850 SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType(
851 ArrTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
861 GR.add(GV, GR.CurMF, VarReg);
864 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
866 .
addUse(GR.getSPIRVTypeID(VarTy))
867 .
addImm(SPIRV::StorageClass::UniformConstant)
870 SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
871 ValTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
873 selectUnOpWithSrc(SrcReg, SourceTy,
I, VarReg, SPIRV::OpBitcast);
875 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
876 .
addUse(
I.getOperand(0).getReg())
878 .
addUse(
I.getOperand(2).getReg());
879 if (
I.getNumMemOperands())
882 if (ResVReg.
isValid() && ResVReg != MIB->getOperand(0).getReg())
883 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY), ResVReg)
884 .
addUse(MIB->getOperand(0).getReg());
888bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
892 unsigned NegateOpcode)
const {
897 Register ScopeReg = buildI32Constant(Scope,
I);
905 Register MemSemReg = buildI32Constant(MemSem ,
I);
908 Register ValueReg =
I.getOperand(2).getReg();
909 if (NegateOpcode != 0) {
911 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
912 Result |= selectUnOpWithSrc(TmpReg, ResType,
I, ValueReg, NegateOpcode);
918 .
addUse(GR.getSPIRVTypeID(ResType))
927bool SPIRVInstructionSelector::selectUnmergeValues(
MachineInstr &
I)
const {
928 unsigned ArgI =
I.getNumOperands() - 1;
930 I.getOperand(ArgI).isReg() ?
I.getOperand(ArgI).getReg() :
Register(0);
932 SrcReg.
isValid() ? GR.getSPIRVTypeForVReg(SrcReg) :
nullptr;
933 if (!DefType || DefType->
getOpcode() != SPIRV::OpTypeVector)
935 "cannot select G_UNMERGE_VALUES with a non-vector argument");
941 for (
unsigned i = 0; i <
I.getNumDefs(); ++i) {
942 Register ResVReg =
I.getOperand(i).getReg();
943 SPIRVType *ResType = GR.getSPIRVTypeForVReg(ResVReg);
946 ResType = ScalarType;
947 MRI->setRegClass(ResVReg, &SPIRV::IDRegClass);
948 MRI->setType(ResVReg,
LLT::scalar(GR.getScalarOrVectorBitWidth(ResType)));
949 GR.assignSPIRVTypeToVReg(ResType, ResVReg, *GR.CurMF);
952 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
954 .
addUse(GR.getSPIRVTypeID(ResType))
956 .
addImm(
static_cast<int64_t
>(i));
957 Res |= MIB.constrainAllUses(
TII,
TRI, RBI);
962bool SPIRVInstructionSelector::selectFence(
MachineInstr &
I)
const {
965 Register MemSemReg = buildI32Constant(MemSem,
I);
968 Register ScopeReg = buildI32Constant(Scope,
I);
970 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
976bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
983 if (!isa<GIntrinsic>(
I)) {
988 ScopeReg = buildI32Constant(Scope,
I);
990 unsigned ScSem =
static_cast<uint32_t>(
994 MemSemEqReg = buildI32Constant(MemSemEq,
I);
998 MemSemEq == MemSemNeq ? MemSemEqReg : buildI32Constant(MemSemNeq,
I);
1000 ScopeReg =
I.getOperand(5).getReg();
1001 MemSemEqReg =
I.getOperand(6).getReg();
1002 MemSemNeqReg =
I.getOperand(7).getReg();
1006 Register Val =
I.getOperand(4).getReg();
1007 SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
1008 Register ACmpRes =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1011 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
1013 .
addUse(GR.getSPIRVTypeID(SpvValTy))
1021 Register CmpSuccReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1025 .
addUse(GR.getSPIRVTypeID(BoolTy))
1029 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1032 .
addUse(GR.getSPIRVTypeID(ResType))
1034 .
addUse(GR.getOrCreateUndef(
I, ResType,
TII))
1039 .
addUse(GR.getSPIRVTypeID(ResType))
1049 case SPIRV::StorageClass::Workgroup:
1050 case SPIRV::StorageClass::CrossWorkgroup:
1051 case SPIRV::StorageClass::Function:
1060 case SPIRV::StorageClass::DeviceOnlyINTEL:
1061 case SPIRV::StorageClass::HostOnlyINTEL:
1073bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
1078 auto UIs =
MRI->use_instructions(ResVReg);
1079 if (!UIs.empty() && ++UIs.begin() == UIs.end() &&
1080 (UIs.begin()->getOpcode() == SPIRV::OpConstantComposite ||
1081 UIs.begin()->getOpcode() == SPIRV::OpVariable ||
1083 Register NewReg =
I.getOperand(1).getReg();
1085 SPIRVType *SpvBaseTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
1086 ResType = GR.getOrCreateSPIRVPointerType(SpvBaseTy,
I,
TII,
1087 SPIRV::StorageClass::Generic);
1089 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
1091 .
addUse(GR.getSPIRVTypeID(ResType))
1097 Register SrcPtr =
I.getOperand(1).getReg();
1098 SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);
1099 SPIRV::StorageClass::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtr);
1100 SPIRV::StorageClass::StorageClass DstSC = GR.getPointerStorageClass(ResVReg);
1104 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1105 TII.get(TargetOpcode::COPY))
1112 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1115 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1118 Register Tmp =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1119 SPIRVType *GenericPtrTy = GR.getOrCreateSPIRVPointerType(
1120 GR.getPointeeType(SrcPtrTy),
I,
TII, SPIRV::StorageClass::Generic);
1125 .
addUse(GR.getSPIRVTypeID(GenericPtrTy))
1130 .
addUse(GR.getSPIRVTypeID(ResType))
1138 return selectUnOp(ResVReg, ResType,
I,
1139 SPIRV::OpPtrCastToCrossWorkgroupINTEL);
1141 return selectUnOp(ResVReg, ResType,
I,
1142 SPIRV::OpCrossWorkgroupCastToPtrINTEL);
1144 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
1146 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
1156 return SPIRV::OpFOrdEqual;
1158 return SPIRV::OpFOrdGreaterThanEqual;
1160 return SPIRV::OpFOrdGreaterThan;
1162 return SPIRV::OpFOrdLessThanEqual;
1164 return SPIRV::OpFOrdLessThan;
1166 return SPIRV::OpFOrdNotEqual;
1168 return SPIRV::OpOrdered;
1170 return SPIRV::OpFUnordEqual;
1172 return SPIRV::OpFUnordGreaterThanEqual;
1174 return SPIRV::OpFUnordGreaterThan;
1176 return SPIRV::OpFUnordLessThanEqual;
1178 return SPIRV::OpFUnordLessThan;
1180 return SPIRV::OpFUnordNotEqual;
1182 return SPIRV::OpUnordered;
1192 return SPIRV::OpIEqual;
1194 return SPIRV::OpINotEqual;
1196 return SPIRV::OpSGreaterThanEqual;
1198 return SPIRV::OpSGreaterThan;
1200 return SPIRV::OpSLessThanEqual;
1202 return SPIRV::OpSLessThan;
1204 return SPIRV::OpUGreaterThanEqual;
1206 return SPIRV::OpUGreaterThan;
1208 return SPIRV::OpULessThanEqual;
1210 return SPIRV::OpULessThan;
1219 return SPIRV::OpPtrEqual;
1221 return SPIRV::OpPtrNotEqual;
1232 return SPIRV::OpLogicalEqual;
1234 return SPIRV::OpLogicalNotEqual;
1240bool SPIRVInstructionSelector::selectAnyOrAll(
Register ResVReg,
1243 unsigned OpAnyOrAll)
const {
1244 assert(
I.getNumOperands() == 3);
1245 assert(
I.getOperand(2).isReg());
1247 Register InputRegister =
I.getOperand(2).getReg();
1248 SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);
1253 bool IsBoolTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeBool);
1254 bool IsVectorTy = InputType->
getOpcode() == SPIRV::OpTypeVector;
1255 if (IsBoolTy && !IsVectorTy) {
1256 assert(ResVReg ==
I.getOperand(0).getReg());
1257 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1258 TII.get(TargetOpcode::COPY))
1264 bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
1265 unsigned SpirvNotEqualId =
1266 IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
1267 SPIRVType *SpvBoolScalarTy = GR.getOrCreateSPIRVBoolType(
I,
TII);
1272 NotEqualReg = IsBoolTy ? InputRegister
1273 :
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1275 SpvBoolTy = GR.getOrCreateSPIRVVectorType(SpvBoolTy, NumElts,
I,
TII);
1280 IsFloatTy ? buildZerosValF(InputType,
I) : buildZerosVal(InputType,
I);
1282 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SpirvNotEqualId))
1284 .
addUse(GR.getSPIRVTypeID(SpvBoolTy))
1293 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(OpAnyOrAll))
1295 .
addUse(GR.getSPIRVTypeID(SpvBoolScalarTy))
1300bool SPIRVInstructionSelector::selectAll(
Register ResVReg,
1303 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAll);
1306bool SPIRVInstructionSelector::selectAny(
Register ResVReg,
1309 return selectAnyOrAll(ResVReg, ResType,
I, SPIRV::OpAny);
1312bool SPIRVInstructionSelector::selectFmix(
Register ResVReg,
1316 assert(
I.getNumOperands() == 5);
1317 assert(
I.getOperand(2).isReg());
1318 assert(
I.getOperand(3).isReg());
1319 assert(
I.getOperand(4).isReg());
1322 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1324 .
addUse(GR.getSPIRVTypeID(ResType))
1325 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1327 .
addUse(
I.getOperand(2).getReg())
1328 .
addUse(
I.getOperand(3).getReg())
1329 .
addUse(
I.getOperand(4).getReg())
1333bool SPIRVInstructionSelector::selectRsqrt(
Register ResVReg,
1337 assert(
I.getNumOperands() == 3);
1338 assert(
I.getOperand(2).isReg());
1341 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1343 .
addUse(GR.getSPIRVTypeID(ResType))
1344 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1346 .
addUse(
I.getOperand(2).getReg())
1350bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
1354 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
1356 .
addUse(GR.getSPIRVTypeID(ResType))
1357 .
addUse(
I.getOperand(1).getReg())
1361bool SPIRVInstructionSelector::selectFreeze(
Register ResVReg,
1369 if (!
I.getOperand(0).isReg() || !
I.getOperand(1).isReg())
1371 Register OpReg =
I.getOperand(1).getReg();
1374 switch (
Def->getOpcode()) {
1375 case SPIRV::ASSIGN_TYPE:
1377 MRI->getVRegDef(
Def->getOperand(1).getReg())) {
1378 if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1379 Reg =
Def->getOperand(2).getReg();
1382 case SPIRV::OpUndef:
1383 Reg =
Def->getOperand(1).getReg();
1386 unsigned DestOpCode;
1387 if (
Reg.isValid()) {
1388 DestOpCode = SPIRV::OpConstantNull;
1390 DestOpCode = TargetOpcode::COPY;
1393 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(DestOpCode))
1394 .
addDef(
I.getOperand(0).getReg())
1401bool SPIRVInstructionSelector::selectConstVector(
Register ResVReg,
1411 SPIRVType *ConstTy = this->MRI->getVRegDef(MO.getReg());
1412 assert(ConstTy && ConstTy->getOpcode() == SPIRV::ASSIGN_TYPE &&
1413 ConstTy->getOperand(1).isReg());
1414 Register ConstReg = ConstTy->getOperand(1).getReg();
1415 const MachineInstr *Const = this->MRI->getVRegDef(ConstReg);
1417 return (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
1418 Const->getOpcode() == TargetOpcode::G_FCONSTANT);
1421 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1422 TII.get(SPIRV::OpConstantComposite))
1424 .
addUse(GR.getSPIRVTypeID(ResType));
1425 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
1426 MIB.
addUse(
I.getOperand(i).getReg());
1436 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1441 unsigned N = OpDef->
getOpcode() == TargetOpcode::G_CONSTANT
1450 if (OpDef->
getOpcode() == SPIRV::ASSIGN_TYPE &&
1462 case TargetOpcode::G_CONSTANT:
1463 case TargetOpcode::G_FCONSTANT:
1465 case TargetOpcode::G_INTRINSIC:
1466 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1467 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
1468 return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
1469 Intrinsic::spv_const_composite;
1470 case TargetOpcode::G_BUILD_VECTOR:
1471 case TargetOpcode::G_SPLAT_VECTOR: {
1495bool SPIRVInstructionSelector::selectSplatVector(
Register ResVReg,
1499 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1500 N = GR.getScalarOrVectorComponentCount(ResType);
1501 else if (ResType->
getOpcode() == SPIRV::OpTypeArray)
1506 unsigned OpIdx =
I.getNumExplicitDefs();
1507 if (!
I.getOperand(OpIdx).isReg())
1511 Register OpReg =
I.getOperand(OpIdx).getReg();
1514 if (!IsConst &&
N < 2)
1516 "There must be at least two constituent operands in a vector");
1518 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1519 TII.get(IsConst ? SPIRV::OpConstantComposite
1520 : SPIRV::OpCompositeConstruct))
1522 .
addUse(GR.getSPIRVTypeID(ResType));
1523 for (
unsigned i = 0; i <
N; ++i)
1528bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
1532 Register Cmp0 =
I.getOperand(2).getReg();
1533 Register Cmp1 =
I.getOperand(3).getReg();
1534 assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
1535 GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
1536 "CMP operands should have the same type");
1537 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
1539 .
addUse(GR.getSPIRVTypeID(ResType))
1545bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
1548 auto Pred =
I.getOperand(1).getPredicate();
1551 Register CmpOperand =
I.getOperand(2).getReg();
1552 if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
1554 else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
1558 return selectCmp(ResVReg, ResType, CmpOpc,
I);
1564 assert(
I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
1565 "Expected G_FCONSTANT");
1566 const ConstantFP *FPImm =
I.getOperand(1).getFPImm();
1573 assert(
I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1574 "Expected G_CONSTANT");
1575 addNumImm(
I.getOperand(1).getCImm()->getValue(), MIB);
1583 ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32,
I,
TII);
1585 auto ConstInt = ConstantInt::get(LLVMTy, Val);
1586 Register NewReg = GR.find(ConstInt, GR.CurMF);
1589 GR.add(ConstInt, GR.CurMF, NewReg);
1593 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1595 .
addUse(GR.getSPIRVTypeID(SpvI32Ty));
1597 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1599 .
addUse(GR.getSPIRVTypeID(SpvI32Ty))
1607bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
1611 return selectCmp(ResVReg, ResType, CmpOp,
I);
1617 bool ZeroAsNull = STI.isOpenCLEnv();
1618 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1619 return GR.getOrCreateConstVector(0UL,
I, ResType,
TII, ZeroAsNull);
1620 return GR.getOrCreateConstInt(0,
I, ResType,
TII, ZeroAsNull);
1640 bool ZeroAsNull = STI.isOpenCLEnv();
1642 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1643 return GR.getOrCreateConstVector(VZero,
I, ResType,
TII, ZeroAsNull);
1644 return GR.getOrCreateConstFP(VZero,
I, ResType,
TII, ZeroAsNull);
1650 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1653 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1658bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
1661 bool IsSigned)
const {
1663 Register ZeroReg = buildZerosVal(ResType,
I);
1664 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
1666 GR.isScalarOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool);
1668 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectSIVCond;
1669 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1671 .
addUse(GR.getSPIRVTypeID(ResType))
1672 .
addUse(
I.getOperand(1).getReg())
1678bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
1681 unsigned Opcode)
const {
1682 Register SrcReg =
I.getOperand(1).getReg();
1685 if (GR.isScalarOrVectorOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
1686 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1688 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1690 TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts,
I,
TII);
1692 SrcReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1693 selectSelect(SrcReg, TmpType,
I,
false);
1695 return selectUnOpWithSrc(ResVReg, ResType,
I, SrcReg, Opcode);
1698bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
1701 Register SrcReg =
I.getOperand(1).getReg();
1702 if (GR.isScalarOrVectorOfType(SrcReg, SPIRV::OpTypeBool))
1703 return selectSelect(ResVReg, ResType,
I, IsSigned);
1705 SPIRVType *SrcType = GR.getSPIRVTypeForVReg(SrcReg);
1706 if (SrcType == ResType)
1707 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1708 TII.get(TargetOpcode::COPY))
1713 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1714 return selectUnOp(ResVReg, ResType,
I, Opcode);
1717bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
1723 Register BitIntReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1724 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
1725 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
1727 Register One = buildOnesVal(
false, IntTy,
I);
1731 .
addUse(GR.getSPIRVTypeID(IntTy))
1735 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpINotEqual))
1737 .
addUse(GR.getSPIRVTypeID(BoolTy))
1743bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
1746 Register IntReg =
I.getOperand(1).getReg();
1747 const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
1748 if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool))
1749 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
1750 if (ArgType == ResType)
1751 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
1752 TII.get(TargetOpcode::COPY))
1756 bool IsSigned = GR.isScalarOrVectorSigned(ResType);
1757 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1758 return selectUnOp(ResVReg, ResType,
I, Opcode);
1761bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
1765 unsigned TyOpcode = ResType->
getOpcode();
1766 assert(TyOpcode != SPIRV::OpTypePointer ||
Imm.isZero());
1768 if ((TyOpcode == SPIRV::OpTypePointer || TyOpcode == SPIRV::OpTypeEvent) &&
1770 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1772 .
addUse(GR.getSPIRVTypeID(ResType))
1774 if (TyOpcode == SPIRV::OpTypeInt) {
1775 assert(
Imm.getBitWidth() <= 64 &&
"Unsupported integer width!");
1779 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
1784 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1786 .
addUse(GR.getSPIRVTypeID(ResType));
1793bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
1796 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1798 .
addUse(GR.getSPIRVTypeID(ResType))
1805 if (TypeInst->
getOpcode() == SPIRV::ASSIGN_TYPE) {
1808 return ImmInst->
getOpcode() == TargetOpcode::G_CONSTANT;
1810 return TypeInst->
getOpcode() == SPIRV::OpConstantI;
1815 if (TypeInst->
getOpcode() == SPIRV::OpConstantI)
1822bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
1826 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
1828 .
addUse(GR.getSPIRVTypeID(ResType))
1830 .
addUse(
I.getOperand(3).getReg())
1832 .
addUse(
I.getOperand(2).getReg());
1833 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
1838bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
1842 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1844 .
addUse(GR.getSPIRVTypeID(ResType))
1845 .
addUse(
I.getOperand(2).getReg());
1846 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
1851bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
1855 return selectInsertVal(ResVReg, ResType,
I);
1857 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
1859 .
addUse(GR.getSPIRVTypeID(ResType))
1860 .
addUse(
I.getOperand(2).getReg())
1861 .
addUse(
I.getOperand(3).getReg())
1862 .
addUse(
I.getOperand(4).getReg())
1866bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
1870 return selectExtractVal(ResVReg, ResType,
I);
1872 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
1874 .
addUse(GR.getSPIRVTypeID(ResType))
1875 .
addUse(
I.getOperand(2).getReg())
1876 .
addUse(
I.getOperand(3).getReg())
1880bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
1883 const bool IsGEPInBounds =
I.getOperand(2).getImm();
1888 const unsigned Opcode = STI.isVulkanEnv()
1889 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
1890 : SPIRV::OpAccessChain)
1891 : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
1892 : SPIRV::OpPtrAccessChain);
1894 auto Res =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode))
1896 .
addUse(GR.getSPIRVTypeID(ResType))
1898 .
addUse(
I.getOperand(3).getReg());
1900 const unsigned StartingIndex =
1901 (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
1904 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
1905 Res.addUse(
I.getOperand(i).getReg());
1906 return Res.constrainAllUses(
TII,
TRI, RBI);
1910bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
1913 unsigned Lim =
I.getNumExplicitOperands();
1914 for (
unsigned i =
I.getNumExplicitDefs() + 1; i < Lim; ++i) {
1915 Register OpReg =
I.getOperand(i).getReg();
1917 SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
1919 if (!OpDefine || !OpType ||
isConstReg(
MRI, OpDefine, Visited) ||
1920 OpDefine->
getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
1921 GR.isAggregateType(OpType)) {
1928 Register WrapReg = GR.find(OpDefine, MF);
1934 WrapReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1935 GR.add(OpDefine, MF, WrapReg);
1939 GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF);
1943 .
addUse(GR.getSPIRVTypeID(OpType))
1953bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
1959 case Intrinsic::spv_load:
1960 return selectLoad(ResVReg, ResType,
I);
1961 case Intrinsic::spv_store:
1962 return selectStore(
I);
1963 case Intrinsic::spv_extractv:
1964 return selectExtractVal(ResVReg, ResType,
I);
1965 case Intrinsic::spv_insertv:
1966 return selectInsertVal(ResVReg, ResType,
I);
1967 case Intrinsic::spv_extractelt:
1968 return selectExtractElt(ResVReg, ResType,
I);
1969 case Intrinsic::spv_insertelt:
1970 return selectInsertElt(ResVReg, ResType,
I);
1971 case Intrinsic::spv_gep:
1972 return selectGEP(ResVReg, ResType,
I);
1973 case Intrinsic::spv_unref_global:
1974 case Intrinsic::spv_init_global: {
1977 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
1980 return selectGlobalValue(
MI->getOperand(0).getReg(), *
MI,
Init);
1982 case Intrinsic::spv_undef: {
1983 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1985 .
addUse(GR.getSPIRVTypeID(ResType));
1988 case Intrinsic::spv_const_composite: {
1990 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
1992 unsigned Opcode = SPIRV::OpConstantNull;
1995 Opcode = SPIRV::OpConstantComposite;
1996 if (!wrapIntoSpecConstantOp(
I, CompositeArgs))
1999 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(Opcode))
2001 .
addUse(GR.getSPIRVTypeID(ResType));
2004 for (
Register OpReg : CompositeArgs)
2009 case Intrinsic::spv_assign_name: {
2010 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
2011 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
2012 for (
unsigned i =
I.getNumExplicitDefs() + 2;
2013 i <
I.getNumExplicitOperands(); ++i) {
2014 MIB.
addImm(
I.getOperand(i).getImm());
2018 case Intrinsic::spv_switch: {
2019 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
2020 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
2021 if (
I.getOperand(i).isReg())
2022 MIB.
addReg(
I.getOperand(i).getReg());
2023 else if (
I.getOperand(i).isCImm())
2024 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
2025 else if (
I.getOperand(i).isMBB())
2026 MIB.
addMBB(
I.getOperand(i).getMBB());
2032 case Intrinsic::spv_cmpxchg:
2033 return selectAtomicCmpXchg(ResVReg, ResType,
I);
2034 case Intrinsic::spv_unreachable:
2035 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable));
2037 case Intrinsic::spv_alloca:
2038 return selectFrameIndex(ResVReg, ResType,
I);
2039 case Intrinsic::spv_alloca_array:
2040 return selectAllocaArray(ResVReg, ResType,
I);
2041 case Intrinsic::spv_assume:
2042 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
2043 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
2044 .
addUse(
I.getOperand(1).getReg());
2046 case Intrinsic::spv_expect:
2047 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
2048 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
2050 .
addUse(GR.getSPIRVTypeID(ResType))
2051 .
addUse(
I.getOperand(2).getReg())
2052 .
addUse(
I.getOperand(3).getReg());
2054 case Intrinsic::spv_thread_id:
2055 return selectSpvThreadId(ResVReg, ResType,
I);
2056 case Intrinsic::spv_all:
2057 return selectAll(ResVReg, ResType,
I);
2058 case Intrinsic::spv_any:
2059 return selectAny(ResVReg, ResType,
I);
2060 case Intrinsic::spv_lerp:
2061 return selectFmix(ResVReg, ResType,
I);
2062 case Intrinsic::spv_rsqrt:
2063 return selectRsqrt(ResVReg, ResType,
I);
2064 case Intrinsic::spv_lifetime_start:
2065 case Intrinsic::spv_lifetime_end: {
2066 unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
2067 : SPIRV::OpLifetimeStop;
2068 int64_t
Size =
I.getOperand(
I.getNumExplicitDefs() + 1).getImm();
2069 Register PtrReg =
I.getOperand(
I.getNumExplicitDefs() + 2).getReg();
2070 unsigned PonteeOpType = GR.getPointeeTypeOp(PtrReg);
2071 bool IsNonvoidPtr = PonteeOpType != 0 && PonteeOpType != SPIRV::OpTypeVoid;
2072 if (
Size == -1 || IsNonvoidPtr)
2077 std::string DiagMsg;
2080 DiagMsg =
"Intrinsic selection not implemented: " + DiagMsg;
2087bool SPIRVInstructionSelector::selectAllocaArray(
Register ResVReg,
2094 TII.get(SPIRV::OpVariableLengthArrayINTEL))
2096 .
addUse(GR.getSPIRVTypeID(ResType))
2097 .
addUse(
I.getOperand(2).getReg())
2101bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
2109 bool IsHeader =
false;
2111 for (; It != E && It !=
I; ++It) {
2112 Opcode = It->getOpcode();
2113 if (Opcode == SPIRV::OpFunction || Opcode == SPIRV::OpFunctionParameter) {
2115 }
else if (IsHeader &&
2116 !(Opcode == SPIRV::ASSIGN_TYPE || Opcode == SPIRV::OpLabel)) {
2121 return BuildMI(*
MBB, It, It->getDebugLoc(),
TII.get(SPIRV::OpVariable))
2123 .
addUse(GR.getSPIRVTypeID(ResType))
2128bool SPIRVInstructionSelector::selectBranch(
MachineInstr &
I)
const {
2135 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
2136 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2139 .
addMBB(
I.getOperand(0).getMBB())
2143 .
addMBB(
I.getOperand(0).getMBB())
2147bool SPIRVInstructionSelector::selectBranchCond(
MachineInstr &
I)
const {
2160 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
2167 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
2168 .
addUse(
I.getOperand(0).getReg())
2169 .
addMBB(
I.getOperand(1).getMBB())
2174bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
2177 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
2179 .
addUse(GR.getSPIRVTypeID(ResType));
2180 const unsigned NumOps =
I.getNumOperands();
2181 for (
unsigned i = 1; i < NumOps; i += 2) {
2182 MIB.
addUse(
I.getOperand(i + 0).getReg());
2183 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
2188bool SPIRVInstructionSelector::selectGlobalValue(
2193 Type *GVType = GR.getDeducedGlobalValueType(GV);
2198 SPIRV::AccessQualifier::ReadWrite,
false);
2199 PointerBaseType = GR.getOrCreateSPIRVArrayType(
2202 PointerBaseType = GR.getOrCreateSPIRVType(
2203 GVType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
2205 SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(
2206 PointerBaseType,
I,
TII,
2209 std::string GlobalIdent;
2211 unsigned &
ID = UnnamedGlobalIDs[GV];
2213 ID = UnnamedGlobalIDs.size();
2214 GlobalIdent =
"__unnamed_" +
Twine(
ID).
str();
2229 if (isa<Function>(GV)) {
2232 Register NewReg = GR.find(ConstVal, GR.CurMF);
2235 GR.add(ConstVal, GR.CurMF, NewReg);
2237 STI.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)
2238 ? dyn_cast<Function>(GV)
2246 MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass);
2249 TII.get(SPIRV::OpConstantFunctionPointerINTEL))
2251 .
addUse(GR.getSPIRVTypeID(ResType))
2257 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
2259 .
addUse(GR.getSPIRVTypeID(ResType))
2262 assert(NewReg != ResVReg);
2263 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
2268 auto GlobalVar = cast<GlobalVariable>(GV);
2271 bool HasInit =
GlobalVar->hasInitializer() &&
2272 !isa<UndefValue>(
GlobalVar->getInitializer());
2275 if (HasInit && !
Init)
2279 SPIRV::StorageClass::StorageClass Storage =
2282 Storage != SPIRV::StorageClass::Function;
2283 SPIRV::LinkageType::LinkageType LnkType =
2285 ? SPIRV::LinkageType::Import
2287 STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
2288 ? SPIRV::LinkageType::LinkOnceODR
2289 : SPIRV::LinkageType::Export);
2291 Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
2293 HasLnkTy, LnkType, MIRBuilder,
true);
2294 return Reg.isValid();
2297bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
2300 if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
2301 return selectExtInst(ResVReg, ResType,
I, CL::log10);
2313 Register VarReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2315 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
2317 .
addUse(GR.getSPIRVTypeID(ResType))
2318 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
2320 .
add(
I.getOperand(1))
2325 ResType->
getOpcode() == SPIRV::OpTypeFloat);
2328 ResType->
getOpcode() == SPIRV::OpTypeVector
2332 GR.buildConstantFP(
APFloat(0.30103f), MIRBuilder, SpirvScalarType);
2335 auto Opcode = ResType->
getOpcode() == SPIRV::OpTypeVector
2336 ? SPIRV::OpVectorTimesScalar
2340 .
addUse(GR.getSPIRVTypeID(ResType))
2348bool SPIRVInstructionSelector::selectSpvThreadId(
Register ResVReg,
2356 const SPIRVType *U32Type = GR.getOrCreateSPIRVIntegerType(32, MIRBuilder);
2358 GR.getOrCreateSPIRVVectorType(U32Type, 3, MIRBuilder);
2359 const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
2360 Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);
2364 MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
2365 MIRBuilder.getMRI()->setType(NewRegister,
LLT::pointer(0, 32));
2366 GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());
2369 Register Variable = GR.buildGlobalVariable(
2370 NewRegister, PtrType,
2372 SPIRV::StorageClass::Input,
nullptr,
true,
true,
2373 SPIRV::LinkageType::Import, MIRBuilder,
false);
2377 Register LoadedRegister =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
2378 MIRBuilder.getMRI()->setType(LoadedRegister,
LLT::pointer(0, 32));
2379 GR.assignSPIRVTypeToVReg(Vec3Ty, LoadedRegister, MIRBuilder.getMF());
2382 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
2384 .
addUse(GR.getSPIRVTypeID(Vec3Ty))
2389 assert(
I.getOperand(2).isReg());
2390 Register ThreadIdReg =
I.getOperand(2).getReg();
2396 assert(Const &&
Const->getOpcode() == TargetOpcode::G_CONSTANT);
2402 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
2404 .
addUse(GR.getSPIRVTypeID(ResType))
2415 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
uint64_t IntrinsicInst * II
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, SmallPtrSet< SPIRVType *, 4 > &Visited)
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.
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.
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
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)
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)