30#include "llvm/IR/IntrinsicsSPIRV.h"
33#define DEBUG_TYPE "spirv-isel"
36namespace CL = SPIRV::OpenCLExtInst;
37namespace GL = SPIRV::GLSLExtInst;
40 std::vector<std::pair<SPIRV::InstructionSet::InstructionSet, uint32_t>>;
44#define GET_GLOBALISEL_PREDICATE_BITSET
45#include "SPIRVGenGlobalISel.inc"
46#undef GET_GLOBALISEL_PREDICATE_BITSET
67#define GET_GLOBALISEL_PREDICATES_DECL
68#include "SPIRVGenGlobalISel.inc"
69#undef GET_GLOBALISEL_PREDICATES_DECL
71#define GET_GLOBALISEL_TEMPORARIES_DECL
72#include "SPIRVGenGlobalISel.inc"
73#undef GET_GLOBALISEL_TEMPORARIES_DECL
134 bool IsSigned)
const;
136 bool IsSigned,
unsigned Opcode)
const;
138 bool IsSigned)
const;
174 GL::GLSLExtInst GLInst)
const;
182 const SPIRVType *ResType =
nullptr)
const;
191#define GET_GLOBALISEL_IMPL
192#include "SPIRVGenGlobalISel.inc"
193#undef GET_GLOBALISEL_IMPL
199 TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
201#include
"SPIRVGenGlobalISel.inc"
204#include
"SPIRVGenGlobalISel.inc"
214 GR.setCurrentFunc(MF);
215 InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI);
224 assert(
I.getParent() &&
"Instruction should be in a basic block!");
225 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
230 if (
Opcode == SPIRV::ASSIGN_TYPE) {
231 auto *
Def =
MRI->getVRegDef(
I.getOperand(1).getReg());
233 auto Res = selectImpl(
I, *CoverageInfo);
234 assert(Res ||
Def->getOpcode() == TargetOpcode::G_CONSTANT);
238 MRI->replaceRegWith(
I.getOperand(1).getReg(),
I.getOperand(0).getReg());
239 I.removeFromParent();
241 }
else if (
I.getNumDefs() == 1) {
248 if (
I.getNumOperands() !=
I.getNumExplicitOperands()) {
249 LLVM_DEBUG(
errs() <<
"Generic instr has unexpected implicit operands\n");
255 bool HasDefs =
I.getNumDefs() > 0;
257 SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) :
nullptr;
258 assert(!HasDefs || ResType ||
I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
259 if (spvSelect(ResVReg, ResType,
I)) {
262 I.removeFromParent();
268bool SPIRVInstructionSelector::spvSelect(
Register ResVReg,
272 I.getOpcode() == TargetOpcode::G_CONSTANT);
273 const unsigned Opcode =
I.getOpcode();
275 case TargetOpcode::G_CONSTANT:
276 return selectConst(ResVReg, ResType,
I.getOperand(1).getCImm()->getValue(),
278 case TargetOpcode::G_GLOBAL_VALUE:
279 return selectGlobalValue(ResVReg,
I);
280 case TargetOpcode::G_IMPLICIT_DEF:
281 return selectOpUndef(ResVReg, ResType,
I);
283 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
284 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
285 return selectIntrinsic(ResVReg, ResType,
I);
286 case TargetOpcode::G_BITREVERSE:
287 return selectBitreverse(ResVReg, ResType,
I);
289 case TargetOpcode::G_BUILD_VECTOR:
290 return selectConstVector(ResVReg, ResType,
I);
292 case TargetOpcode::G_SHUFFLE_VECTOR: {
294 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorShuffle))
296 .
addUse(GR.getSPIRVTypeID(ResType))
297 .
addUse(
I.getOperand(1).getReg())
298 .
addUse(
I.getOperand(2).getReg());
299 for (
auto V :
I.getOperand(3).getShuffleMask())
303 case TargetOpcode::G_MEMMOVE:
304 case TargetOpcode::G_MEMCPY:
305 case TargetOpcode::G_MEMSET:
306 return selectMemOperation(ResVReg,
I);
308 case TargetOpcode::G_ICMP:
309 return selectICmp(ResVReg, ResType,
I);
310 case TargetOpcode::G_FCMP:
311 return selectFCmp(ResVReg, ResType,
I);
313 case TargetOpcode::G_FRAME_INDEX:
314 return selectFrameIndex(ResVReg, ResType,
I);
316 case TargetOpcode::G_LOAD:
317 return selectLoad(ResVReg, ResType,
I);
318 case TargetOpcode::G_STORE:
319 return selectStore(
I);
321 case TargetOpcode::G_BR:
322 return selectBranch(
I);
323 case TargetOpcode::G_BRCOND:
324 return selectBranchCond(
I);
326 case TargetOpcode::G_PHI:
327 return selectPhi(ResVReg, ResType,
I);
329 case TargetOpcode::G_FPTOSI:
330 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToS);
331 case TargetOpcode::G_FPTOUI:
332 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertFToU);
334 case TargetOpcode::G_SITOFP:
335 return selectIToF(ResVReg, ResType,
I,
true, SPIRV::OpConvertSToF);
336 case TargetOpcode::G_UITOFP:
337 return selectIToF(ResVReg, ResType,
I,
false, SPIRV::OpConvertUToF);
339 case TargetOpcode::G_CTPOP:
340 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitCount);
341 case TargetOpcode::G_SMIN:
342 return selectExtInst(ResVReg, ResType,
I, CL::s_min, GL::SMin);
343 case TargetOpcode::G_UMIN:
344 return selectExtInst(ResVReg, ResType,
I, CL::u_min, GL::UMin);
346 case TargetOpcode::G_SMAX:
347 return selectExtInst(ResVReg, ResType,
I, CL::s_max, GL::SMax);
348 case TargetOpcode::G_UMAX:
349 return selectExtInst(ResVReg, ResType,
I, CL::u_max, GL::UMax);
351 case TargetOpcode::G_FMA:
352 return selectExtInst(ResVReg, ResType,
I, CL::fma, GL::Fma);
354 case TargetOpcode::G_FPOW:
355 return selectExtInst(ResVReg, ResType,
I, CL::pow, GL::Pow);
356 case TargetOpcode::G_FPOWI:
357 return selectExtInst(ResVReg, ResType,
I, CL::pown);
359 case TargetOpcode::G_FEXP:
360 return selectExtInst(ResVReg, ResType,
I, CL::exp, GL::Exp);
361 case TargetOpcode::G_FEXP2:
362 return selectExtInst(ResVReg, ResType,
I, CL::exp2, GL::Exp2);
364 case TargetOpcode::G_FLOG:
365 return selectExtInst(ResVReg, ResType,
I, CL::log, GL::Log);
366 case TargetOpcode::G_FLOG2:
367 return selectExtInst(ResVReg, ResType,
I, CL::log2, GL::Log2);
368 case TargetOpcode::G_FLOG10:
369 return selectLog10(ResVReg, ResType,
I);
371 case TargetOpcode::G_FABS:
372 return selectExtInst(ResVReg, ResType,
I, CL::fabs, GL::FAbs);
373 case TargetOpcode::G_ABS:
374 return selectExtInst(ResVReg, ResType,
I, CL::s_abs, GL::SAbs);
376 case TargetOpcode::G_FMINNUM:
377 case TargetOpcode::G_FMINIMUM:
378 return selectExtInst(ResVReg, ResType,
I, CL::fmin, GL::FMin);
379 case TargetOpcode::G_FMAXNUM:
380 case TargetOpcode::G_FMAXIMUM:
381 return selectExtInst(ResVReg, ResType,
I, CL::fmax, GL::FMax);
383 case TargetOpcode::G_FCOPYSIGN:
384 return selectExtInst(ResVReg, ResType,
I, CL::copysign);
386 case TargetOpcode::G_FCEIL:
387 return selectExtInst(ResVReg, ResType,
I, CL::ceil, GL::Ceil);
388 case TargetOpcode::G_FFLOOR:
389 return selectExtInst(ResVReg, ResType,
I, CL::floor, GL::Floor);
391 case TargetOpcode::G_FCOS:
392 return selectExtInst(ResVReg, ResType,
I, CL::cos, GL::Cos);
393 case TargetOpcode::G_FSIN:
394 return selectExtInst(ResVReg, ResType,
I, CL::sin, GL::Sin);
396 case TargetOpcode::G_FSQRT:
397 return selectExtInst(ResVReg, ResType,
I, CL::sqrt, GL::Sqrt);
399 case TargetOpcode::G_CTTZ:
400 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
401 return selectExtInst(ResVReg, ResType,
I, CL::ctz);
402 case TargetOpcode::G_CTLZ:
403 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
404 return selectExtInst(ResVReg, ResType,
I, CL::clz);
406 case TargetOpcode::G_INTRINSIC_ROUND:
407 return selectExtInst(ResVReg, ResType,
I, CL::round, GL::Round);
408 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
409 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
410 case TargetOpcode::G_INTRINSIC_TRUNC:
411 return selectExtInst(ResVReg, ResType,
I, CL::trunc, GL::Trunc);
412 case TargetOpcode::G_FRINT:
413 case TargetOpcode::G_FNEARBYINT:
414 return selectExtInst(ResVReg, ResType,
I, CL::rint, GL::RoundEven);
416 case TargetOpcode::G_SMULH:
417 return selectExtInst(ResVReg, ResType,
I, CL::s_mul_hi);
418 case TargetOpcode::G_UMULH:
419 return selectExtInst(ResVReg, ResType,
I, CL::u_mul_hi);
421 case TargetOpcode::G_SEXT:
422 return selectExt(ResVReg, ResType,
I,
true);
423 case TargetOpcode::G_ANYEXT:
424 case TargetOpcode::G_ZEXT:
425 return selectExt(ResVReg, ResType,
I,
false);
426 case TargetOpcode::G_TRUNC:
427 return selectTrunc(ResVReg, ResType,
I);
428 case TargetOpcode::G_FPTRUNC:
429 case TargetOpcode::G_FPEXT:
430 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpFConvert);
432 case TargetOpcode::G_PTRTOINT:
433 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertPtrToU);
434 case TargetOpcode::G_INTTOPTR:
435 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpConvertUToPtr);
436 case TargetOpcode::G_BITCAST:
437 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
438 case TargetOpcode::G_ADDRSPACE_CAST:
439 return selectAddrSpaceCast(ResVReg, ResType,
I);
440 case TargetOpcode::G_PTR_ADD: {
445 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
448 assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
449 (*II).getOpcode() == TargetOpcode::COPY ||
450 (*II).getOpcode() == SPIRV::OpVariable) &&
452 Register Idx = buildZerosVal(GR.getOrCreateSPIRVIntegerType(32,
I,
TII),
I);
454 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
456 .
addUse(GR.getSPIRVTypeID(ResType))
458 SPIRV::Opcode::InBoundsPtrAccessChain))
461 .
addUse(
I.getOperand(2).getReg());
465 case TargetOpcode::G_ATOMICRMW_OR:
466 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicOr);
467 case TargetOpcode::G_ATOMICRMW_ADD:
468 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicIAdd);
469 case TargetOpcode::G_ATOMICRMW_AND:
470 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicAnd);
471 case TargetOpcode::G_ATOMICRMW_MAX:
472 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMax);
473 case TargetOpcode::G_ATOMICRMW_MIN:
474 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicSMin);
475 case TargetOpcode::G_ATOMICRMW_SUB:
476 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicISub);
477 case TargetOpcode::G_ATOMICRMW_XOR:
478 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicXor);
479 case TargetOpcode::G_ATOMICRMW_UMAX:
480 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMax);
481 case TargetOpcode::G_ATOMICRMW_UMIN:
482 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicUMin);
483 case TargetOpcode::G_ATOMICRMW_XCHG:
484 return selectAtomicRMW(ResVReg, ResType,
I, SPIRV::OpAtomicExchange);
485 case TargetOpcode::G_ATOMIC_CMPXCHG:
486 return selectAtomicCmpXchg(ResVReg, ResType,
I);
488 case TargetOpcode::G_FENCE:
489 return selectFence(
I);
496bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
499 CL::OpenCLExtInst CLInst)
const {
500 return selectExtInst(ResVReg, ResType,
I,
501 {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
504bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
507 CL::OpenCLExtInst CLInst,
508 GL::GLSLExtInst GLInst)
const {
509 ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
510 {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
511 return selectExtInst(ResVReg, ResType,
I, ExtInsts);
514bool SPIRVInstructionSelector::selectExtInst(
Register ResVReg,
519 for (
const auto &Ex : Insts) {
520 SPIRV::InstructionSet::InstructionSet Set = Ex.first;
522 if (STI.canUseExtInstSet(Set)) {
524 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
526 .
addUse(GR.getSPIRVTypeID(ResType))
529 const unsigned NumOps =
I.getNumOperands();
530 for (
unsigned i = 1; i < NumOps; ++i)
531 MIB.add(
I.getOperand(i));
532 return MIB.constrainAllUses(
TII,
TRI, RBI);
538bool SPIRVInstructionSelector::selectUnOpWithSrc(
Register ResVReg,
545 .
addUse(GR.getSPIRVTypeID(ResType))
550bool SPIRVInstructionSelector::selectUnOp(
Register ResVReg,
554 return selectUnOpWithSrc(ResVReg, ResType,
I,
I.getOperand(1).getReg(),
561 return SPIRV::Scope::Invocation;
563 return SPIRV::Scope::Device;
572 if (
MemOp->isVolatile())
573 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
574 if (
MemOp->isNonTemporal())
575 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
576 if (
MemOp->getAlign().value())
577 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);
579 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
581 if (SpvMemOp &
static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
588 if (Flags & MachineMemOperand::Flags::MOVolatile)
589 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
590 if (Flags & MachineMemOperand::Flags::MONonTemporal)
591 SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
593 if (SpvMemOp !=
static_cast<uint32_t>(SPIRV::MemoryOperand::None))
597bool SPIRVInstructionSelector::selectLoad(
Register ResVReg,
600 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
602 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpLoad))
604 .
addUse(GR.getSPIRVTypeID(ResType))
606 if (!
I.getNumMemOperands()) {
607 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
609 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
614 return MIB.constrainAllUses(
TII,
TRI, RBI);
617bool SPIRVInstructionSelector::selectStore(
MachineInstr &
I)
const {
618 unsigned OpOffset = isa<GIntrinsic>(
I) ? 1 : 0;
619 Register StoreVal =
I.getOperand(0 + OpOffset).getReg();
622 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpStore))
625 if (!
I.getNumMemOperands()) {
626 assert(
I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
628 TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
633 return MIB.constrainAllUses(
TII,
TRI, RBI);
636bool SPIRVInstructionSelector::selectMemOperation(
Register ResVReg,
639 Register SrcReg =
I.getOperand(1).getReg();
640 if (
I.getOpcode() == TargetOpcode::G_MEMSET) {
641 assert(
I.getOperand(1).isReg() &&
I.getOperand(2).isReg());
644 SPIRVType *ValTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
645 SPIRVType *ArrTy = GR.getOrCreateSPIRVArrayType(ValTy, Num,
I,
TII);
647 SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType(
648 ArrTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
650 Type *LLVMArrTy = ArrayType::get(
655 GR.add(GV, GR.CurMF, VarReg);
658 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
660 .
addUse(GR.getSPIRVTypeID(VarTy))
661 .
addImm(SPIRV::StorageClass::UniformConstant)
664 SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
665 ValTy,
I,
TII, SPIRV::StorageClass::UniformConstant);
667 selectUnOpWithSrc(SrcReg, SourceTy,
I, VarReg, SPIRV::OpBitcast);
669 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCopyMemorySized))
670 .
addUse(
I.getOperand(0).getReg())
672 .
addUse(
I.getOperand(2).getReg());
673 if (
I.getNumMemOperands())
676 if (ResVReg.
isValid() && ResVReg != MIB->getOperand(0).getReg())
677 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY), ResVReg)
678 .
addUse(MIB->getOperand(0).getReg());
682bool SPIRVInstructionSelector::selectAtomicRMW(
Register ResVReg,
685 unsigned NewOpcode)
const {
689 Register ScopeReg = buildI32Constant(Scope,
I);
697 Register MemSemReg = buildI32Constant(MemSem ,
I);
699 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(NewOpcode))
701 .
addUse(GR.getSPIRVTypeID(ResType))
705 .
addUse(
I.getOperand(2).getReg())
709bool SPIRVInstructionSelector::selectFence(
MachineInstr &
I)
const {
712 Register MemSemReg = buildI32Constant(MemSem,
I);
715 Register ScopeReg = buildI32Constant(Scope,
I);
717 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpMemoryBarrier))
723bool SPIRVInstructionSelector::selectAtomicCmpXchg(
Register ResVReg,
730 if (!isa<GIntrinsic>(
I)) {
734 ScopeReg = buildI32Constant(Scope,
I);
736 unsigned ScSem =
static_cast<uint32_t>(
740 MemSemEqReg = buildI32Constant(MemSemEq,
I);
744 MemSemEq == MemSemNeq ? MemSemEqReg : buildI32Constant(MemSemNeq,
I);
746 ScopeReg =
I.getOperand(5).getReg();
747 MemSemEqReg =
I.getOperand(6).getReg();
748 MemSemNeqReg =
I.getOperand(7).getReg();
753 SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
754 Register ACmpRes =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
757 BuildMI(*
I.getParent(),
I,
DL,
TII.get(SPIRV::OpAtomicCompareExchange))
759 .
addUse(GR.getSPIRVTypeID(SpvValTy))
767 Register CmpSuccReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
771 .
addUse(GR.getSPIRVTypeID(BoolTy))
775 Register TmpReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
778 .
addUse(GR.getSPIRVTypeID(ResType))
785 .
addUse(GR.getSPIRVTypeID(ResType))
795 case SPIRV::StorageClass::Workgroup:
796 case SPIRV::StorageClass::CrossWorkgroup:
797 case SPIRV::StorageClass::Function:
809bool SPIRVInstructionSelector::selectAddrSpaceCast(
Register ResVReg,
814 auto UIs =
MRI->use_instructions(ResVReg);
815 if (!UIs.empty() && ++UIs.begin() == UIs.end() &&
816 (UIs.begin()->getOpcode() == SPIRV::OpConstantComposite ||
817 UIs.begin()->getOpcode() == SPIRV::OpVariable ||
819 Register NewReg =
I.getOperand(1).getReg();
821 SPIRVType *SpvBaseTy = GR.getOrCreateSPIRVIntegerType(8,
I,
TII);
822 ResType = GR.getOrCreateSPIRVPointerType(SpvBaseTy,
I,
TII,
823 SPIRV::StorageClass::Generic);
825 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSpecConstantOp))
827 .
addUse(GR.getSPIRVTypeID(ResType))
833 Register SrcPtr =
I.getOperand(1).getReg();
834 SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);
835 SPIRV::StorageClass::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtr);
836 SPIRV::StorageClass::StorageClass DstSC = GR.getPointerStorageClass(ResVReg);
840 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpPtrCastToGeneric);
843 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpGenericCastToPtr);
846 Register Tmp =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
847 SPIRVType *GenericPtrTy = GR.getOrCreateSPIRVPointerType(
848 SrcPtrTy,
I,
TII, SPIRV::StorageClass::Generic);
853 .
addUse(GR.getSPIRVTypeID(GenericPtrTy))
858 .
addUse(GR.getSPIRVTypeID(ResType))
864 return selectUnOp(ResVReg, ResType,
I, SPIRV::OpBitcast);
871 return SPIRV::OpFOrdEqual;
873 return SPIRV::OpFOrdGreaterThanEqual;
875 return SPIRV::OpFOrdGreaterThan;
877 return SPIRV::OpFOrdLessThanEqual;
879 return SPIRV::OpFOrdLessThan;
881 return SPIRV::OpFOrdNotEqual;
883 return SPIRV::OpOrdered;
885 return SPIRV::OpFUnordEqual;
887 return SPIRV::OpFUnordGreaterThanEqual;
889 return SPIRV::OpFUnordGreaterThan;
891 return SPIRV::OpFUnordLessThanEqual;
893 return SPIRV::OpFUnordLessThan;
895 return SPIRV::OpFUnordNotEqual;
897 return SPIRV::OpUnordered;
907 return SPIRV::OpIEqual;
909 return SPIRV::OpINotEqual;
911 return SPIRV::OpSGreaterThanEqual;
913 return SPIRV::OpSGreaterThan;
915 return SPIRV::OpSLessThanEqual;
917 return SPIRV::OpSLessThan;
919 return SPIRV::OpUGreaterThanEqual;
921 return SPIRV::OpUGreaterThan;
923 return SPIRV::OpULessThanEqual;
925 return SPIRV::OpULessThan;
934 return SPIRV::OpPtrEqual;
936 return SPIRV::OpPtrNotEqual;
947 return SPIRV::OpLogicalEqual;
949 return SPIRV::OpLogicalNotEqual;
955bool SPIRVInstructionSelector::selectBitreverse(
Register ResVReg,
959 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBitReverse))
961 .
addUse(GR.getSPIRVTypeID(ResType))
962 .
addUse(
I.getOperand(1).getReg())
966bool SPIRVInstructionSelector::selectConstVector(
Register ResVReg,
976 SPIRVType *ConstTy = this->MRI->getVRegDef(MO.getReg());
977 assert(ConstTy && ConstTy->getOpcode() == SPIRV::ASSIGN_TYPE &&
978 ConstTy->getOperand(1).isReg());
979 Register ConstReg = ConstTy->getOperand(1).getReg();
980 const MachineInstr *Const = this->MRI->getVRegDef(ConstReg);
982 return (Const->getOpcode() == TargetOpcode::G_CONSTANT ||
983 Const->getOpcode() == TargetOpcode::G_FCONSTANT);
986 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
987 TII.get(SPIRV::OpConstantComposite))
989 .
addUse(GR.getSPIRVTypeID(ResType));
990 for (
unsigned i =
I.getNumExplicitDefs(); i <
I.getNumExplicitOperands(); ++i)
991 MIB.
addUse(
I.getOperand(i).getReg());
995bool SPIRVInstructionSelector::selectCmp(
Register ResVReg,
999 Register Cmp0 =
I.getOperand(2).getReg();
1000 Register Cmp1 =
I.getOperand(3).getReg();
1001 assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
1002 GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
1003 "CMP operands should have the same type");
1004 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(CmpOpc))
1006 .
addUse(GR.getSPIRVTypeID(ResType))
1012bool SPIRVInstructionSelector::selectICmp(
Register ResVReg,
1015 auto Pred =
I.getOperand(1).getPredicate();
1018 Register CmpOperand =
I.getOperand(2).getReg();
1019 if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
1021 else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
1025 return selectCmp(ResVReg, ResType, CmpOpc,
I);
1031 assert(
I.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
1032 "Expected G_FCONSTANT");
1033 const ConstantFP *FPImm =
I.getOperand(1).getFPImm();
1040 assert(
I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1041 "Expected G_CONSTANT");
1042 addNumImm(
I.getOperand(1).getCImm()->getValue(), MIB);
1050 ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32,
I,
TII);
1053 Register NewReg = GR.find(ConstInt, GR.CurMF);
1056 GR.add(ConstInt, GR.CurMF, NewReg);
1060 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1062 .
addUse(GR.getSPIRVTypeID(SpvI32Ty));
1064 MI =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1066 .
addUse(GR.getSPIRVTypeID(SpvI32Ty))
1074bool SPIRVInstructionSelector::selectFCmp(
Register ResVReg,
1078 return selectCmp(ResVReg, ResType, CmpOp,
I);
1083 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1084 return GR.getOrCreateConsIntVector(0,
I, ResType,
TII);
1085 return GR.getOrCreateConstInt(0,
I, ResType,
TII);
1091 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1094 if (ResType->
getOpcode() == SPIRV::OpTypeVector)
1099bool SPIRVInstructionSelector::selectSelect(
Register ResVReg,
1102 bool IsSigned)
const {
1104 Register ZeroReg = buildZerosVal(ResType,
I);
1105 Register OneReg = buildOnesVal(IsSigned, ResType,
I);
1107 GR.isScalarOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool);
1109 IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectSIVCond;
1112 .
addUse(GR.getSPIRVTypeID(ResType))
1113 .
addUse(
I.getOperand(1).getReg())
1119bool SPIRVInstructionSelector::selectIToF(
Register ResVReg,
1123 Register SrcReg =
I.getOperand(1).getReg();
1126 if (GR.isScalarOrVectorOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
1127 unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
1129 if (ResType->
getOpcode() == SPIRV::OpTypeVector) {
1131 TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts,
I,
TII);
1133 SrcReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1134 selectSelect(SrcReg, TmpType,
I,
false);
1136 return selectUnOpWithSrc(ResVReg, ResType,
I, SrcReg,
Opcode);
1139bool SPIRVInstructionSelector::selectExt(
Register ResVReg,
1142 if (GR.isScalarOrVectorOfType(
I.getOperand(1).getReg(), SPIRV::OpTypeBool))
1143 return selectSelect(ResVReg, ResType,
I, IsSigned);
1144 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1145 return selectUnOp(ResVReg, ResType,
I,
Opcode);
1148bool SPIRVInstructionSelector::selectIntToBool(
Register IntReg,
1154 Register BitIntReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1155 bool IsVectorTy = IntTy->
getOpcode() == SPIRV::OpTypeVector;
1156 unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
1158 Register One = buildOnesVal(
false, IntTy,
I);
1162 .
addUse(GR.getSPIRVTypeID(IntTy))
1166 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpINotEqual))
1168 .
addUse(GR.getSPIRVTypeID(BoolTy))
1174bool SPIRVInstructionSelector::selectTrunc(
Register ResVReg,
1177 if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool)) {
1178 Register IntReg =
I.getOperand(1).getReg();
1179 const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
1180 return selectIntToBool(IntReg, ResVReg,
I, ArgType, ResType);
1182 bool IsSigned = GR.isScalarOrVectorSigned(ResType);
1183 unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
1184 return selectUnOp(ResVReg, ResType,
I,
Opcode);
1187bool SPIRVInstructionSelector::selectConst(
Register ResVReg,
1191 unsigned TyOpcode = ResType->
getOpcode();
1192 assert(TyOpcode != SPIRV::OpTypePointer ||
Imm.isZero());
1194 if ((TyOpcode == SPIRV::OpTypePointer || TyOpcode == SPIRV::OpTypeEvent) &&
1196 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1198 .
addUse(GR.getSPIRVTypeID(ResType))
1200 if (TyOpcode == SPIRV::OpTypeInt) {
1201 assert(
Imm.getBitWidth() <= 64 &&
"Unsupported integer width!");
1205 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
1210 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantI))
1212 .
addUse(GR.getSPIRVTypeID(ResType));
1219bool SPIRVInstructionSelector::selectOpUndef(
Register ResVReg,
1222 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1224 .
addUse(GR.getSPIRVTypeID(ResType))
1231 if (TypeInst->
getOpcode() != SPIRV::ASSIGN_TYPE)
1235 return ImmInst->
getOpcode() == TargetOpcode::G_CONSTANT;
1245bool SPIRVInstructionSelector::selectInsertVal(
Register ResVReg,
1249 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeInsert))
1251 .
addUse(GR.getSPIRVTypeID(ResType))
1253 .
addUse(
I.getOperand(3).getReg())
1255 .
addUse(
I.getOperand(2).getReg());
1256 for (
unsigned i = 4; i <
I.getNumOperands(); i++)
1261bool SPIRVInstructionSelector::selectExtractVal(
Register ResVReg,
1265 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpCompositeExtract))
1267 .
addUse(GR.getSPIRVTypeID(ResType))
1268 .
addUse(
I.getOperand(2).getReg());
1269 for (
unsigned i = 3; i <
I.getNumOperands(); i++)
1274bool SPIRVInstructionSelector::selectInsertElt(
Register ResVReg,
1278 return selectInsertVal(ResVReg, ResType,
I);
1280 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorInsertDynamic))
1282 .
addUse(GR.getSPIRVTypeID(ResType))
1283 .
addUse(
I.getOperand(2).getReg())
1284 .
addUse(
I.getOperand(3).getReg())
1285 .
addUse(
I.getOperand(4).getReg())
1289bool SPIRVInstructionSelector::selectExtractElt(
Register ResVReg,
1293 return selectExtractVal(ResVReg, ResType,
I);
1295 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVectorExtractDynamic))
1297 .
addUse(GR.getSPIRVTypeID(ResType))
1298 .
addUse(
I.getOperand(2).getReg())
1299 .
addUse(
I.getOperand(3).getReg())
1303bool SPIRVInstructionSelector::selectGEP(
Register ResVReg,
1306 const bool IsGEPInBounds =
I.getOperand(2).getImm();
1311 const unsigned Opcode = STI.isVulkanEnv()
1312 ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
1313 : SPIRV::OpAccessChain)
1314 : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
1315 : SPIRV::OpPtrAccessChain);
1319 .
addUse(GR.getSPIRVTypeID(ResType))
1321 .
addUse(
I.getOperand(3).getReg());
1323 const unsigned StartingIndex =
1324 (
Opcode == SPIRV::OpAccessChain ||
Opcode == SPIRV::OpInBoundsAccessChain)
1327 for (
unsigned i = StartingIndex; i <
I.getNumExplicitOperands(); ++i)
1328 Res.
addUse(
I.getOperand(i).getReg());
1332bool SPIRVInstructionSelector::selectIntrinsic(
Register ResVReg,
1337 case Intrinsic::spv_load:
1338 return selectLoad(ResVReg, ResType,
I);
1339 case Intrinsic::spv_store:
1340 return selectStore(
I);
1341 case Intrinsic::spv_extractv:
1342 return selectExtractVal(ResVReg, ResType,
I);
1343 case Intrinsic::spv_insertv:
1344 return selectInsertVal(ResVReg, ResType,
I);
1345 case Intrinsic::spv_extractelt:
1346 return selectExtractElt(ResVReg, ResType,
I);
1347 case Intrinsic::spv_insertelt:
1348 return selectInsertElt(ResVReg, ResType,
I);
1349 case Intrinsic::spv_gep:
1350 return selectGEP(ResVReg, ResType,
I);
1351 case Intrinsic::spv_unref_global:
1352 case Intrinsic::spv_init_global: {
1355 ?
MRI->getVRegDef(
I.getOperand(2).getReg())
1358 return selectGlobalValue(
MI->getOperand(0).getReg(), *
MI,
Init);
1360 case Intrinsic::spv_undef: {
1361 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUndef))
1363 .
addUse(GR.getSPIRVTypeID(ResType));
1366 case Intrinsic::spv_const_composite: {
1368 bool IsNull =
I.getNumExplicitDefs() + 1 ==
I.getNumExplicitOperands();
1370 IsNull ? SPIRV::OpConstantNull : SPIRV::OpConstantComposite;
1373 .
addUse(GR.getSPIRVTypeID(ResType));
1376 for (
unsigned i =
I.getNumExplicitDefs() + 1;
1377 i <
I.getNumExplicitOperands(); ++i) {
1378 MIB.
addUse(
I.getOperand(i).getReg());
1383 case Intrinsic::spv_assign_name: {
1384 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpName));
1385 MIB.
addUse(
I.getOperand(
I.getNumExplicitDefs() + 1).getReg());
1386 for (
unsigned i =
I.getNumExplicitDefs() + 2;
1387 i <
I.getNumExplicitOperands(); ++i) {
1388 MIB.
addImm(
I.getOperand(i).getImm());
1392 case Intrinsic::spv_switch: {
1393 auto MIB =
BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpSwitch));
1394 for (
unsigned i = 1; i <
I.getNumExplicitOperands(); ++i) {
1395 if (
I.getOperand(i).isReg())
1396 MIB.
addReg(
I.getOperand(i).getReg());
1397 else if (
I.getOperand(i).isCImm())
1398 addNumImm(
I.getOperand(i).getCImm()->getValue(), MIB);
1399 else if (
I.getOperand(i).isMBB())
1400 MIB.
addMBB(
I.getOperand(i).getMBB());
1406 case Intrinsic::spv_cmpxchg:
1407 return selectAtomicCmpXchg(ResVReg, ResType,
I);
1408 case Intrinsic::spv_unreachable:
1409 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpUnreachable));
1411 case Intrinsic::spv_alloca:
1412 return selectFrameIndex(ResVReg, ResType,
I);
1413 case Intrinsic::spv_assume:
1414 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
1415 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpAssumeTrueKHR))
1416 .
addUse(
I.getOperand(1).getReg());
1418 case Intrinsic::spv_expect:
1419 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
1420 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExpectKHR))
1422 .
addUse(GR.getSPIRVTypeID(ResType))
1423 .
addUse(
I.getOperand(2).getReg())
1424 .
addUse(
I.getOperand(3).getReg());
1432bool SPIRVInstructionSelector::selectFrameIndex(
Register ResVReg,
1435 return BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpVariable))
1437 .
addUse(GR.getSPIRVTypeID(ResType))
1442bool SPIRVInstructionSelector::selectBranch(
MachineInstr &
I)
const {
1449 if (PrevI !=
nullptr && PrevI->
getOpcode() == TargetOpcode::G_BRCOND) {
1450 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
1453 .
addMBB(
I.getOperand(0).getMBB())
1457 .
addMBB(
I.getOperand(0).getMBB())
1461bool SPIRVInstructionSelector::selectBranchCond(
MachineInstr &
I)
const {
1474 if (NextI !=
nullptr && NextI->
getOpcode() == SPIRV::OpBranchConditional)
1481 return BuildMI(
MBB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpBranchConditional))
1482 .
addUse(
I.getOperand(0).getReg())
1483 .
addMBB(
I.getOperand(1).getMBB())
1488bool SPIRVInstructionSelector::selectPhi(
Register ResVReg,
1491 auto MIB =
BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(SPIRV::OpPhi))
1493 .
addUse(GR.getSPIRVTypeID(ResType));
1494 const unsigned NumOps =
I.getNumOperands();
1495 for (
unsigned i = 1; i < NumOps; i += 2) {
1496 MIB.
addUse(
I.getOperand(i + 0).getReg());
1497 MIB.
addMBB(
I.getOperand(i + 1).getMBB());
1502bool SPIRVInstructionSelector::selectGlobalValue(
1512 SPIRV::AccessQualifier::ReadWrite,
false);
1513 PointerBaseType = GR.getOrCreateSPIRVArrayType(
1516 PointerBaseType = GR.getOrCreateSPIRVType(
1517 GVType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
false);
1519 SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(
1520 PointerBaseType,
I,
TII,
1527 if (isa<Function>(GV)) {
1530 Register NewReg = GR.find(ConstVal, GR.CurMF);
1533 GR.add(ConstVal, GR.CurMF, NewReg);
1534 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpConstantNull))
1536 .
addUse(GR.getSPIRVTypeID(ResType))
1539 assert(NewReg != ResVReg);
1540 return BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(TargetOpcode::COPY))
1545 auto GlobalVar = cast<GlobalVariable>(GV);
1548 bool HasInit =
GlobalVar->hasInitializer() &&
1549 !isa<UndefValue>(
GlobalVar->getInitializer());
1552 if (HasInit && !
Init)
1556 SPIRV::StorageClass::StorageClass Storage =
1559 Storage != SPIRV::StorageClass::Function;
1560 SPIRV::LinkageType::LinkageType LnkType =
1562 ? SPIRV::LinkageType::Import
1563 : SPIRV::LinkageType::Export;
1565 Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
1567 HasLnkTy, LnkType, MIRBuilder,
true);
1568 return Reg.isValid();
1571bool SPIRVInstructionSelector::selectLog10(
Register ResVReg,
1574 if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
1575 return selectExtInst(ResVReg, ResType,
I, CL::log10);
1587 Register VarReg =
MRI->createVirtualRegister(&SPIRV::IDRegClass);
1589 BuildMI(BB,
I,
I.getDebugLoc(),
TII.get(SPIRV::OpExtInst))
1591 .
addUse(GR.getSPIRVTypeID(ResType))
1592 .
addImm(
static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
1594 .
add(
I.getOperand(1))
1599 ResType->
getOpcode() == SPIRV::OpTypeFloat);
1602 ResType->
getOpcode() == SPIRV::OpTypeVector
1606 GR.buildConstantFP(
APFloat(0.30103f), MIRBuilder, SpirvScalarType);
1610 ? SPIRV::OpVectorTimesScalar
1614 .
addUse(GR.getSPIRVTypeID(ResType))
1627 return new SPIRVInstructionSelector(
TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
static unsigned getIntrinsicID(const SDNode *N)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file declares a class to represent arbitrary precision floating point values and provide a varie...
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
static SPIRV::Scope::Scope getScope(SyncScope::ID Ord)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static void addMemoryOperands(MachineMemOperand *MemOp, MachineInstrBuilder &MIB)
static unsigned getFCmpOpcode(unsigned PredNum)
bool isTypeFoldingSupported(unsigned Opcode)
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
static unsigned getBoolCmpOpcode(unsigned PredNum)
static unsigned getICmpOpcode(unsigned PredNum)
static int64_t foldImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
static bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)
static unsigned getPtrCmpOpcode(unsigned Pred)
static constexpr uint32_t Opcode
APInt bitcastToAPInt() const
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
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
This is an important base class in LLVM.
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
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).
Type * getValueType() const
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".
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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.
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.
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,...
Analysis providing profile information.
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
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
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ 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)
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
bool isSpvIntrinsic(MachineInstr &MI, Intrinsic::ID IntrinsicID)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
InstructionSelector * createSPIRVInstructionSelector(const SPIRVTargetMachine &TM, const SPIRVSubtarget &Subtarget, const RegisterBankInfo &RBI)
constexpr unsigned BitWidth
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)