25#include "llvm/IR/IntrinsicsRISCV.h"
28#define DEBUG_TYPE "riscv-isel"
33#define GET_GLOBALISEL_PREDICATE_BITSET
34#include "RISCVGenGlobalISel.inc"
35#undef GET_GLOBALISEL_PREDICATE_BITSET
60 static constexpr unsigned MaxRecursionDepth = 6;
63 const unsigned Depth = 0)
const;
89 bool IsExternWeak =
false)
const;
97 unsigned ShiftWidth)
const;
98 ComplexRendererFns selectShiftMaskXLen(
MachineOperand &Root)
const {
99 return selectShiftMask(Root, STI.
getXLen());
101 ComplexRendererFns selectShiftMask32(
MachineOperand &Root)
const {
102 return selectShiftMask(Root, 32);
106 ComplexRendererFns selectSExtBits(
MachineOperand &Root,
unsigned Bits)
const;
107 template <
unsigned Bits>
109 return selectSExtBits(Root, Bits);
112 ComplexRendererFns selectZExtBits(
MachineOperand &Root,
unsigned Bits)
const;
113 template <
unsigned Bits>
115 return selectZExtBits(Root, Bits);
118 ComplexRendererFns selectSHXADDOp(
MachineOperand &Root,
unsigned ShAmt)
const;
119 template <
unsigned ShAmt>
121 return selectSHXADDOp(Root, ShAmt);
125 unsigned ShAmt)
const;
126 template <
unsigned ShAmt>
127 ComplexRendererFns selectSHXADD_UWOp(
MachineOperand &Root)
const {
128 return selectSHXADD_UWOp(Root, ShAmt);
168#define GET_GLOBALISEL_PREDICATES_DECL
169#include "RISCVGenGlobalISel.inc"
170#undef GET_GLOBALISEL_PREDICATES_DECL
172#define GET_GLOBALISEL_TEMPORARIES_DECL
173#include "RISCVGenGlobalISel.inc"
174#undef GET_GLOBALISEL_TEMPORARIES_DECL
179#define GET_GLOBALISEL_IMPL
180#include "RISCVGenGlobalISel.inc"
181#undef GET_GLOBALISEL_IMPL
183RISCVInstructionSelector::RISCVInstructionSelector(
186 : STI(STI),
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI),
190#include
"RISCVGenGlobalISel.inc"
193#include
"RISCVGenGlobalISel.inc"
199bool RISCVInstructionSelector::hasAllNBitUsers(
const MachineInstr &
MI,
201 const unsigned Depth)
const {
203 assert((
MI.getOpcode() == TargetOpcode::G_ADD ||
204 MI.getOpcode() == TargetOpcode::G_SUB ||
205 MI.getOpcode() == TargetOpcode::G_MUL ||
206 MI.getOpcode() == TargetOpcode::G_SHL ||
207 MI.getOpcode() == TargetOpcode::G_LSHR ||
208 MI.getOpcode() == TargetOpcode::G_AND ||
209 MI.getOpcode() == TargetOpcode::G_OR ||
210 MI.getOpcode() == TargetOpcode::G_XOR ||
211 MI.getOpcode() == TargetOpcode::G_SEXT_INREG ||
Depth != 0) &&
212 "Unexpected opcode");
214 if (
Depth >= RISCVInstructionSelector::MaxRecursionDepth)
217 auto DestReg =
MI.getOperand(0).getReg();
218 for (
auto &UserOp :
MRI->use_nodbg_operands(DestReg)) {
219 assert(UserOp.getParent() &&
"UserOp must have a parent");
220 const MachineInstr &UserMI = *UserOp.getParent();
229 case RISCV::FCVT_D_W:
230 case RISCV::FCVT_S_W:
273InstructionSelector::ComplexRendererFns
274RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
275 unsigned ShiftWidth)
const {
279 using namespace llvm::MIPatternMatch;
285 ShAmtReg = ZExtSrcReg;
304 APInt ShMask(AndMask.
getBitWidth(), ShiftWidth - 1);
305 if (ShMask.isSubsetOf(AndMask)) {
306 ShAmtReg = AndSrcReg;
310 KnownBits Known = VT->getKnownBits(AndSrcReg);
311 if (ShMask.isSubsetOf(AndMask | Known.
Zero))
312 ShAmtReg = AndSrcReg;
319 if (Imm != 0 &&
Imm.urem(ShiftWidth) == 0)
324 if (Imm != 0 &&
Imm.urem(ShiftWidth) == 0) {
327 ShAmtReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
328 unsigned NegOpc = Subtarget->
is64Bit() ? RISCV::SUBW : RISCV::SUB;
329 return {{[=](MachineInstrBuilder &MIB) {
330 MachineIRBuilder(*MIB.getInstr())
331 .buildInstr(NegOpc, {ShAmtReg}, {
Register(RISCV::X0),
Reg});
332 MIB.addReg(ShAmtReg);
335 if (
Imm.urem(ShiftWidth) == ShiftWidth - 1) {
338 ShAmtReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
339 return {{[=](MachineInstrBuilder &MIB) {
340 MachineIRBuilder(*MIB.getInstr())
341 .buildInstr(RISCV::XORI, {ShAmtReg}, {
Reg})
343 MIB.addReg(ShAmtReg);
348 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
351InstructionSelector::ComplexRendererFns
352RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
353 unsigned Bits)
const {
357 MachineInstr *RootDef =
MRI->getVRegDef(RootReg);
359 if (RootDef->
getOpcode() == TargetOpcode::G_SEXT_INREG &&
362 {[=](MachineInstrBuilder &MIB) { MIB.add(RootDef->
getOperand(1)); }}};
365 unsigned Size =
MRI->getType(RootReg).getScalarSizeInBits();
366 if ((
Size - VT->computeNumSignBits(RootReg)) < Bits)
367 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
372InstructionSelector::ComplexRendererFns
373RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
374 unsigned Bits)
const {
382 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
386 MRI->getType(RegX).getScalarSizeInBits() == Bits)
387 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
389 unsigned Size =
MRI->getType(RootReg).getScalarSizeInBits();
391 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
396InstructionSelector::ComplexRendererFns
397RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
398 unsigned ShAmt)
const {
399 using namespace llvm::MIPatternMatch;
405 const unsigned XLen = STI.
getXLen();
424 if (
Mask.isShiftedMask()) {
425 unsigned Leading = XLen -
Mask.getActiveBits();
426 unsigned Trailing =
Mask.countr_zero();
429 if (*LeftShift && Leading == 0 && C2.
ult(Trailing) && Trailing == ShAmt) {
430 Register DstReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
431 return {{[=](MachineInstrBuilder &MIB) {
432 MachineIRBuilder(*MIB.getInstr())
433 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
441 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
442 Register DstReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
443 return {{[=](MachineInstrBuilder &MIB) {
444 MachineIRBuilder(*MIB.getInstr())
445 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
446 .addImm(Leading + Trailing);
467 unsigned Leading = XLen -
Mask.getActiveBits();
468 unsigned Trailing =
Mask.countr_zero();
481 Register DstReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
482 return {{[=](MachineInstrBuilder &MIB) {
483 MachineIRBuilder(*MIB.getInstr())
484 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
494InstructionSelector::ComplexRendererFns
495RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
496 unsigned ShAmt)
const {
497 using namespace llvm::MIPatternMatch;
514 if (
Mask.isShiftedMask()) {
515 unsigned Leading =
Mask.countl_zero();
516 unsigned Trailing =
Mask.countr_zero();
517 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
518 Register DstReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
519 return {{[=](MachineInstrBuilder &MIB) {
520 MachineIRBuilder(*MIB.getInstr())
521 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
532InstructionSelector::ComplexRendererFns
533RISCVInstructionSelector::renderVLOp(MachineOperand &Root)
const {
534 assert(Root.
isReg() &&
"Expected operand to be a Register");
535 MachineInstr *RootDef =
MRI->getVRegDef(Root.
getReg());
537 if (RootDef->
getOpcode() == TargetOpcode::G_CONSTANT) {
539 if (
C->getValue().isAllOnes())
543 return {{[=](MachineInstrBuilder &MIB) {
548 uint64_t ZExtC =
C->getZExtValue();
549 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
552 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.
getReg()); }}};
555InstructionSelector::ComplexRendererFns
556RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root)
const {
560 MachineInstr *RootDef =
MRI->getVRegDef(Root.
getReg());
561 if (RootDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX) {
563 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->
getOperand(1)); },
564 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
568 if (isBaseWithConstantOffset(Root, *
MRI)) {
571 MachineInstr *LHSDef =
MRI->getVRegDef(
LHS.getReg());
572 MachineInstr *RHSDef =
MRI->getVRegDef(
RHS.getReg());
576 if (LHSDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX)
578 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->
getOperand(1)); },
579 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
582 return {{[=](MachineInstrBuilder &MIB) { MIB.add(
LHS); },
583 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
589 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.
getReg()); },
590 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
599 case CmpInst::Predicate::ICMP_EQ:
601 case CmpInst::Predicate::ICMP_NE:
603 case CmpInst::Predicate::ICMP_ULT:
605 case CmpInst::Predicate::ICMP_SLT:
607 case CmpInst::Predicate::ICMP_UGE:
609 case CmpInst::Predicate::ICMP_SGE:
675 CC = getRISCVCCFromICmp(Pred);
682 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
687 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
689 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
691 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
693 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
701 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
705 return IsStore ? RISCV::SB : RISCV::LBU;
707 return IsStore ? RISCV::SH : RISCV::LH;
709 return IsStore ? RISCV::SW : RISCV::LW;
711 return IsStore ? RISCV::SD : RISCV::LD;
717bool RISCVInstructionSelector::select(MachineInstr &
MI) {
718 MachineIRBuilder MIB(
MI);
720 preISelLower(
MI, MIB);
721 const unsigned Opc =
MI.getOpcode();
723 if (!
MI.isPreISelOpcode() ||
Opc == TargetOpcode::G_PHI) {
724 if (
Opc == TargetOpcode::PHI ||
Opc == TargetOpcode::G_PHI) {
725 const Register DefReg =
MI.getOperand(0).getReg();
726 const LLT DefTy =
MRI->getType(DefReg);
729 MRI->getRegClassOrRegBank(DefReg);
731 const TargetRegisterClass *DefRC =
740 DefRC = getRegClassForTypeOnBank(DefTy, RB);
747 MI.setDesc(
TII.get(TargetOpcode::PHI));
758 if (selectImpl(
MI, *CoverageInfo))
762 case TargetOpcode::G_ANYEXT:
763 case TargetOpcode::G_PTRTOINT:
764 case TargetOpcode::G_INTTOPTR:
765 case TargetOpcode::G_TRUNC:
766 case TargetOpcode::G_FREEZE:
768 case TargetOpcode::G_CONSTANT: {
770 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
772 if (!materializeImm(DstReg, Imm, MIB))
775 MI.eraseFromParent();
778 case TargetOpcode::G_ZEXT:
779 case TargetOpcode::G_SEXT: {
780 bool IsSigned =
Opc != TargetOpcode::G_ZEXT;
783 LLT SrcTy =
MRI->getType(SrcReg);
790 RISCV::GPRBRegBankID &&
791 "Unexpected ext regbank");
794 if (IsSigned && SrcSize == 32) {
795 MI.setDesc(
TII.get(RISCV::ADDIW));
801 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
802 MI.setDesc(
TII.get(RISCV::ADD_UW));
808 if (SrcSize == 16 && STI.hasStdExtZbb()) {
809 MI.setDesc(
TII.get(IsSigned ? RISCV::SEXT_H
810 : STI.isRV64() ? RISCV::ZEXT_H_RV64
811 : RISCV::ZEXT_H_RV32));
816 if (!IsSigned && SrcSize == 16 && STI.hasStdExtZbkb()) {
817 MI.setDesc(
TII.get(STI.
is64Bit() ? RISCV::PACKW : RISCV::PACK));
824 MIB.buildInstr(RISCV::SLLI, {&RISCV::GPRRegClass}, {SrcReg})
825 .addImm(STI.
getXLen() - SrcSize);
827 auto ShiftRight = MIB.buildInstr(IsSigned ? RISCV::SRAI : RISCV::SRLI,
828 {DstReg}, {ShiftLeft})
829 .addImm(STI.
getXLen() - SrcSize);
831 MI.eraseFromParent();
834 case TargetOpcode::G_FCONSTANT: {
837 const APFloat &FPimm =
MI.getOperand(1).getFPImm()->getValueAPF();
838 unsigned Size =
MRI->getType(DstReg).getSizeInBits();
844 GPRReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
846 if (!materializeImm(GPRReg,
Imm.getSExtValue(), MIB))
850 unsigned Opcode =
Size == 64 ? RISCV::FMV_D_X
851 :
Size == 32 ? RISCV::FMV_W_X
853 auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
854 if (!FMV.constrainAllUses(
TII,
TRI, RBI))
859 "Unexpected size or subtarget");
863 MachineInstrBuilder FCVT =
864 MIB.buildInstr(RISCV::FCVT_D_W, {DstReg}, {
Register(RISCV::X0)})
869 MI.eraseFromParent();
874 Register GPRRegHigh =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
875 Register GPRRegLow =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
877 if (!materializeImm(GPRRegHigh,
Imm.extractBits(32, 32).getSExtValue(),
880 if (!materializeImm(GPRRegLow,
Imm.trunc(32).getSExtValue(), MIB))
882 MachineInstrBuilder PairF64 = MIB.buildInstr(
883 RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
888 MI.eraseFromParent();
891 case TargetOpcode::G_GLOBAL_VALUE: {
892 auto *GV =
MI.getOperand(1).getGlobal();
893 if (GV->isThreadLocal()) {
898 return selectAddr(
MI, MIB, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
900 case TargetOpcode::G_JUMP_TABLE:
901 case TargetOpcode::G_CONSTANT_POOL:
902 return selectAddr(
MI, MIB,
MRI);
903 case TargetOpcode::G_BRCOND: {
909 .addMBB(
MI.getOperand(1).getMBB());
910 MI.eraseFromParent();
913 case TargetOpcode::G_BRINDIRECT:
914 MI.setDesc(
TII.get(RISCV::PseudoBRIND));
917 case TargetOpcode::G_SELECT:
918 return selectSelect(
MI, MIB);
919 case TargetOpcode::G_FCMP:
920 return selectFPCompare(
MI, MIB);
921 case TargetOpcode::G_FENCE: {
926 emitFence(FenceOrdering, FenceSSID, MIB);
927 MI.eraseFromParent();
930 case TargetOpcode::G_IMPLICIT_DEF:
931 return selectImplicitDef(
MI, MIB);
932 case TargetOpcode::G_UNMERGE_VALUES:
934 case TargetOpcode::G_LOAD:
935 case TargetOpcode::G_STORE: {
939 LLT PtrTy =
MRI->getType(PtrReg);
942 if (RB.
getID() != RISCV::GPRBRegBankID)
949 "Load/Store pointer operand isn't a GPR");
950 assert(PtrTy.
isPointer() &&
"Load/Store pointer operand isn't a pointer");
966 if (NewOpc ==
MI.getOpcode())
970 auto AddrModeFns = selectAddrRegImm(
MI.getOperand(1));
975 auto NewInst = MIB.buildInstr(NewOpc, {}, {},
MI.getFlags());
977 NewInst.addUse(ValReg);
979 NewInst.addDef(ValReg);
980 NewInst.cloneMemRefs(
MI);
981 for (
auto &Fn : *AddrModeFns)
983 MI.eraseFromParent();
992bool RISCVInstructionSelector::selectUnmergeValues(
993 MachineInstr &
MI, MachineIRBuilder &MIB)
const {
994 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
996 if (!Subtarget->hasStdExtZfa())
1000 if (
MI.getNumOperands() != 3)
1005 if (!isRegInFprb(Src) || !isRegInGprb(
Lo) || !isRegInGprb(
Hi))
1008 MachineInstr *ExtractLo = MIB.
buildInstr(RISCV::FMV_X_W_FPR64, {
Lo}, {Src});
1012 MachineInstr *ExtractHi = MIB.
buildInstr(RISCV::FMVH_X_D, {
Hi}, {Src});
1016 MI.eraseFromParent();
1020bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &
Op,
1021 MachineIRBuilder &MIB) {
1023 assert(
MRI->getType(PtrReg).isPointer() &&
"Operand is not a pointer!");
1027 MRI->setRegBank(PtrToInt.getReg(0), RBI.
getRegBank(RISCV::GPRBRegBankID));
1028 Op.setReg(PtrToInt.getReg(0));
1029 return select(*PtrToInt);
1032void RISCVInstructionSelector::preISelLower(MachineInstr &
MI,
1033 MachineIRBuilder &MIB) {
1034 switch (
MI.getOpcode()) {
1035 case TargetOpcode::G_PTR_ADD: {
1039 replacePtrWithInt(
MI.getOperand(1), MIB);
1040 MI.setDesc(
TII.get(TargetOpcode::G_ADD));
1041 MRI->setType(DstReg, sXLen);
1044 case TargetOpcode::G_PTRMASK: {
1047 replacePtrWithInt(
MI.getOperand(1), MIB);
1048 MI.setDesc(
TII.get(TargetOpcode::G_AND));
1049 MRI->setType(DstReg, sXLen);
1055void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1056 const MachineInstr &
MI,
1058 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1059 "Expected G_CONSTANT");
1060 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1064void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1065 const MachineInstr &
MI,
1067 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1068 "Expected G_CONSTANT");
1069 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1073void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1074 const MachineInstr &
MI,
1076 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1077 "Expected G_CONSTANT");
1078 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1082void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1083 const MachineInstr &
MI,
1085 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1086 "Expected G_CONSTANT");
1087 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1091void RISCVInstructionSelector::renderFrameIndex(MachineInstrBuilder &MIB,
1092 const MachineInstr &
MI,
1094 assert(
MI.getOpcode() == TargetOpcode::G_FRAME_INDEX &&
OpIdx == -1 &&
1095 "Expected G_FRAME_INDEX");
1096 MIB.
add(
MI.getOperand(1));
1099void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1100 const MachineInstr &
MI,
1102 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1103 "Expected G_CONSTANT");
1104 uint64_t
C =
MI.getOperand(1).getCImm()->getZExtValue();
1108void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1109 MachineInstrBuilder &MIB,
const MachineInstr &
MI,
int OpIdx)
const {
1110 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1111 "Expected G_CONSTANT");
1112 uint64_t
C =
MI.getOperand(1).getCImm()->getZExtValue();
1116void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1117 const MachineInstr &
MI,
1119 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1120 "Expected G_CONSTANT");
1121 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
1122 int64_t Adj =
Imm < 0 ? -2048 : 2047;
1126void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1127 const MachineInstr &
MI,
1129 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
1130 "Expected G_CONSTANT");
1131 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1135const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
1136 LLT Ty,
const RegisterBank &RB)
const {
1137 if (RB.
getID() == RISCV::GPRBRegBankID) {
1139 return &RISCV::GPRRegClass;
1142 if (RB.
getID() == RISCV::FPRBRegBankID) {
1144 return &RISCV::FPR16RegClass;
1146 return &RISCV::FPR32RegClass;
1148 return &RISCV::FPR64RegClass;
1151 if (RB.
getID() == RISCV::VRBRegBankID) {
1153 return &RISCV::VRRegClass;
1156 return &RISCV::VRM2RegClass;
1159 return &RISCV::VRM4RegClass;
1162 return &RISCV::VRM8RegClass;
1168bool RISCVInstructionSelector::isRegInGprb(
Register Reg)
const {
1172bool RISCVInstructionSelector::isRegInFprb(
Register Reg)
const {
1176bool RISCVInstructionSelector::selectCopy(MachineInstr &
MI)
const {
1182 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1185 "Register class not available for LLT, register bank combination");
1196 MI.setDesc(
TII.get(RISCV::COPY));
1200bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &
MI,
1201 MachineIRBuilder &MIB)
const {
1202 assert(
MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1204 const Register DstReg =
MI.getOperand(0).getReg();
1205 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1209 "Register class not available for LLT, register bank combination");
1215 MI.setDesc(
TII.get(TargetOpcode::IMPLICIT_DEF));
1219bool RISCVInstructionSelector::materializeImm(
Register DstReg, int64_t Imm,
1220 MachineIRBuilder &MIB)
const {
1228 unsigned NumInsts = Seq.
size();
1231 for (
unsigned i = 0; i < NumInsts; i++) {
1233 ?
MRI->createVirtualRegister(&RISCV::GPRRegClass)
1235 const RISCVMatInt::Inst &
I = Seq[i];
1238 switch (
I.getOpndKind()) {
1247 {SrcReg, Register(RISCV::X0)});
1267bool RISCVInstructionSelector::selectAddr(MachineInstr &
MI,
1268 MachineIRBuilder &MIB,
bool IsLocal,
1269 bool IsExternWeak)
const {
1270 assert((
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1271 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1272 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1273 "Unexpected opcode");
1275 const MachineOperand &DispMO =
MI.getOperand(1);
1278 const LLT DefTy =
MRI->getType(DefReg);
1285 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1289 MI.setDesc(
TII.get(RISCV::PseudoLLA));
1297 MachineFunction &MF = *
MI.getParent()->getParent();
1311 MI.eraseFromParent();
1318 "Unsupported code model for lowering",
MI);
1325 Register AddrHiDest =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1326 MachineInstr *AddrHi = MIB.
buildInstr(RISCV::LUI, {AddrHiDest}, {})
1338 MI.eraseFromParent();
1351 MachineFunction &MF = *
MI.getParent()->getParent();
1365 MI.eraseFromParent();
1372 MI.setDesc(
TII.get(RISCV::PseudoLLA));
1379bool RISCVInstructionSelector::selectSelect(MachineInstr &
MI,
1380 MachineIRBuilder &MIB)
const {
1387 Register DstReg = SelectMI.getReg(0);
1389 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1391 unsigned Size =
MRI->getType(DstReg).getSizeInBits();
1392 Opc =
Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1393 : RISCV::Select_FPR64_Using_CC_GPR;
1401 .
addReg(SelectMI.getTrueReg())
1402 .
addReg(SelectMI.getFalseReg());
1403 MI.eraseFromParent();
1414 return Size == 16 ? RISCV::FLT_H :
Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1416 return Size == 16 ? RISCV::FLE_H :
Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1418 return Size == 16 ? RISCV::FEQ_H :
Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1431 assert(!isLegalFCmpPredicate(Pred) &&
"Predicate already legal?");
1434 if (isLegalFCmpPredicate(InvPred)) {
1442 if (isLegalFCmpPredicate(InvPred)) {
1447 if (isLegalFCmpPredicate(InvPred)) {
1459bool RISCVInstructionSelector::selectFPCompare(MachineInstr &
MI,
1460 MachineIRBuilder &MIB)
const {
1468 unsigned Size =
MRI->getType(
LHS).getSizeInBits();
1473 bool NeedInvert =
false;
1477 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1479 if (!
Cmp.constrainAllUses(
TII,
TRI, RBI))
1485 {&RISCV::GPRRegClass}, {
LHS,
RHS});
1486 if (!Cmp1.constrainAllUses(
TII,
TRI, RBI))
1489 {&RISCV::GPRRegClass}, {
RHS,
LHS});
1490 if (!Cmp2.constrainAllUses(
TII,
TRI, RBI))
1493 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1495 MIB.
buildInstr(RISCV::OR, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1496 if (!
Or.constrainAllUses(
TII,
TRI, RBI))
1503 {&RISCV::GPRRegClass}, {
LHS,
LHS});
1504 if (!Cmp1.constrainAllUses(
TII,
TRI, RBI))
1507 {&RISCV::GPRRegClass}, {
RHS,
RHS});
1508 if (!Cmp2.constrainAllUses(
TII,
TRI, RBI))
1511 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1513 MIB.
buildInstr(RISCV::AND, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1514 if (!
And.constrainAllUses(
TII,
TRI, RBI))
1521 auto Xor = MIB.
buildInstr(RISCV::XORI, {DstReg}, {TmpReg}).addImm(1);
1522 if (!
Xor.constrainAllUses(
TII,
TRI, RBI))
1526 MI.eraseFromParent();
1530void RISCVInstructionSelector::emitFence(
AtomicOrdering FenceOrdering,
1532 MachineIRBuilder &MIB)
const {
1533 if (STI.hasStdExtZtso()) {
1536 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1546 MIB.
buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1554 MIB.
buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1560 unsigned Pred, Succ;
1561 switch (FenceOrdering) {
1564 case AtomicOrdering::AcquireRelease:
1568 case AtomicOrdering::Acquire:
1573 case AtomicOrdering::Release:
1578 case AtomicOrdering::SequentiallyConsistent:
1588InstructionSelector *
1592 return new RISCVInstructionSelector(TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
static bool hasAllWUsers(const MachineInstr &OrigMI, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI)
static bool hasAllNBitUsers(const MachineInstr &OrigMI, const LoongArchSubtarget &ST, const MachineRegisterInfo &MRI, unsigned OrigBits)
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
static StringRef getName(Value *V)
static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize)
Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the G...
static unsigned selectZalasrLoadStoreOp(unsigned GenericOpc, unsigned OpSize)
Select the RISC-V Zalasr opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the G...
static unsigned getFCmpOpcode(CmpInst::Predicate Pred, unsigned Size)
static bool legalizeFCmpPredicate(Register &LHS, Register &RHS, CmpInst::Predicate &Pred, bool &NeedInvert)
static void getOperandsForBranch(Register CondReg, RISCVCC::CondCode &CC, Register &LHS, Register &RHS, MachineRegisterInfo &MRI)
const SmallVectorImpl< MachineOperand > & Cond
This file declares the targeting of the RegisterBankInfo class for RISC-V.
APInt bitcastToAPInt() const
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
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
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater 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_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
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
This is an important base class in LLVM.
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSizeInBits() const
Returns the size in bits of the memory access.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr unsigned getAddressSpace() const
TypeSize getValue() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_PTRTOINT instruction.
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 & addMemOperand(MachineMemOperand *MMO) const
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 getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
const MachineOperand & getOperand(unsigned i) const
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Analysis providing profile information.
This class provides the information for the target register banks.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
bool isPositionIndependent() const
CodeModel::Model getCodeModel() const
Returns the code model.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
operand_type_match m_Reg()
operand_type_match m_Pred()
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
SpecificConstantMatch m_SpecificICst(APInt RequestedValue)
Matches a constant equal to RequestedValue.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
SmallVector< Inst, 8 > InstSeq
static constexpr int64_t VLMaxSentinel
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
This is an optimization pass for GlobalISel generic memory operations.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
InstructionSelector * createRISCVInstructionSelector(const RISCVTargetMachine &TM, const RISCVSubtarget &Subtarget, const RISCVRegisterBankInfo &RBI)
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
@ Or
Bitwise or logical OR of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.