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);
678bool RISCVInstructionSelector::select(MachineInstr &
MI) {
679 MachineIRBuilder MIB(
MI);
681 preISelLower(
MI, MIB);
682 const unsigned Opc =
MI.getOpcode();
684 if (!
MI.isPreISelOpcode() ||
Opc == TargetOpcode::G_PHI) {
685 if (
Opc == TargetOpcode::PHI ||
Opc == TargetOpcode::G_PHI) {
686 const Register DefReg =
MI.getOperand(0).getReg();
687 const LLT DefTy =
MRI->getType(DefReg);
690 MRI->getRegClassOrRegBank(DefReg);
692 const TargetRegisterClass *DefRC =
701 DefRC = getRegClassForTypeOnBank(DefTy, RB);
708 MI.setDesc(
TII.get(TargetOpcode::PHI));
719 if (selectImpl(
MI, *CoverageInfo))
723 case TargetOpcode::G_ANYEXT:
724 case TargetOpcode::G_PTRTOINT:
725 case TargetOpcode::G_INTTOPTR:
726 case TargetOpcode::G_TRUNC:
727 case TargetOpcode::G_FREEZE:
729 case TargetOpcode::G_CONSTANT: {
731 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
733 if (!materializeImm(DstReg, Imm, MIB))
736 MI.eraseFromParent();
739 case TargetOpcode::G_FCONSTANT: {
742 const APFloat &FPimm =
MI.getOperand(1).getFPImm()->getValueAPF();
743 unsigned Size =
MRI->getType(DstReg).getSizeInBits();
749 GPRReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
751 if (!materializeImm(GPRReg,
Imm.getSExtValue(), MIB))
755 unsigned Opcode =
Size == 64 ? RISCV::FMV_D_X
756 :
Size == 32 ? RISCV::FMV_W_X
758 auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
759 if (!FMV.constrainAllUses(
TII,
TRI, RBI))
764 "Unexpected size or subtarget");
768 MachineInstrBuilder FCVT =
769 MIB.buildInstr(RISCV::FCVT_D_W, {DstReg}, {
Register(RISCV::X0)})
774 MI.eraseFromParent();
779 Register GPRRegHigh =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
780 Register GPRRegLow =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
782 if (!materializeImm(GPRRegHigh,
Imm.extractBits(32, 32).getSExtValue(),
785 if (!materializeImm(GPRRegLow,
Imm.trunc(32).getSExtValue(), MIB))
787 MachineInstrBuilder PairF64 = MIB.buildInstr(
788 RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
793 MI.eraseFromParent();
796 case TargetOpcode::G_GLOBAL_VALUE: {
797 auto *GV =
MI.getOperand(1).getGlobal();
798 if (GV->isThreadLocal()) {
803 return selectAddr(
MI, MIB, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
805 case TargetOpcode::G_JUMP_TABLE:
806 case TargetOpcode::G_CONSTANT_POOL:
807 return selectAddr(
MI, MIB,
MRI);
808 case TargetOpcode::G_BRCOND: {
814 .addMBB(
MI.getOperand(1).getMBB());
815 MI.eraseFromParent();
818 case TargetOpcode::G_BRINDIRECT:
819 MI.setDesc(
TII.get(RISCV::PseudoBRIND));
822 case TargetOpcode::G_SELECT:
823 return selectSelect(
MI, MIB);
824 case TargetOpcode::G_FCMP:
825 return selectFPCompare(
MI, MIB);
826 case TargetOpcode::G_FENCE: {
831 emitFence(FenceOrdering, FenceSSID, MIB);
832 MI.eraseFromParent();
835 case TargetOpcode::G_IMPLICIT_DEF:
836 return selectImplicitDef(
MI, MIB);
837 case TargetOpcode::G_UNMERGE_VALUES:
844bool RISCVInstructionSelector::selectUnmergeValues(
845 MachineInstr &
MI, MachineIRBuilder &MIB)
const {
846 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
848 if (!Subtarget->hasStdExtZfa())
852 if (
MI.getNumOperands() != 3)
857 if (!isRegInFprb(Src) || !isRegInGprb(
Lo) || !isRegInGprb(
Hi))
860 MachineInstr *ExtractLo = MIB.
buildInstr(RISCV::FMV_X_W_FPR64, {
Lo}, {Src});
864 MachineInstr *ExtractHi = MIB.
buildInstr(RISCV::FMVH_X_D, {
Hi}, {Src});
868 MI.eraseFromParent();
872bool RISCVInstructionSelector::replacePtrWithInt(MachineOperand &
Op,
873 MachineIRBuilder &MIB) {
875 assert(
MRI->getType(PtrReg).isPointer() &&
"Operand is not a pointer!");
879 MRI->setRegBank(PtrToInt.getReg(0), RBI.
getRegBank(RISCV::GPRBRegBankID));
880 Op.setReg(PtrToInt.getReg(0));
881 return select(*PtrToInt);
884void RISCVInstructionSelector::preISelLower(MachineInstr &
MI,
885 MachineIRBuilder &MIB) {
886 switch (
MI.getOpcode()) {
887 case TargetOpcode::G_PTR_ADD: {
891 replacePtrWithInt(
MI.getOperand(1), MIB);
892 MI.setDesc(
TII.get(TargetOpcode::G_ADD));
893 MRI->setType(DstReg, sXLen);
896 case TargetOpcode::G_PTRMASK: {
899 replacePtrWithInt(
MI.getOperand(1), MIB);
900 MI.setDesc(
TII.get(TargetOpcode::G_AND));
901 MRI->setType(DstReg, sXLen);
907void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
908 const MachineInstr &
MI,
910 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
911 "Expected G_CONSTANT");
912 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
916void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
917 const MachineInstr &
MI,
919 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
920 "Expected G_CONSTANT");
921 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
925void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
926 const MachineInstr &
MI,
928 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
929 "Expected G_CONSTANT");
930 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
934void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
935 const MachineInstr &
MI,
937 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
938 "Expected G_CONSTANT");
939 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
943void RISCVInstructionSelector::renderFrameIndex(MachineInstrBuilder &MIB,
944 const MachineInstr &
MI,
946 assert(
MI.getOpcode() == TargetOpcode::G_FRAME_INDEX &&
OpIdx == -1 &&
947 "Expected G_FRAME_INDEX");
948 MIB.
add(
MI.getOperand(1));
951void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
952 const MachineInstr &
MI,
954 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
955 "Expected G_CONSTANT");
956 uint64_t
C =
MI.getOperand(1).getCImm()->getZExtValue();
960void RISCVInstructionSelector::renderXLenSubTrailingOnes(
961 MachineInstrBuilder &MIB,
const MachineInstr &
MI,
int OpIdx)
const {
962 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
963 "Expected G_CONSTANT");
964 uint64_t
C =
MI.getOperand(1).getCImm()->getZExtValue();
968void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
969 const MachineInstr &
MI,
971 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
972 "Expected G_CONSTANT");
973 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
974 int64_t Adj =
Imm < 0 ? -2048 : 2047;
978void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
979 const MachineInstr &
MI,
981 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
982 "Expected G_CONSTANT");
983 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
987const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank(
988 LLT Ty,
const RegisterBank &RB)
const {
989 if (RB.
getID() == RISCV::GPRBRegBankID) {
991 return &RISCV::GPRRegClass;
994 if (RB.
getID() == RISCV::FPRBRegBankID) {
996 return &RISCV::FPR16RegClass;
998 return &RISCV::FPR32RegClass;
1000 return &RISCV::FPR64RegClass;
1003 if (RB.
getID() == RISCV::VRBRegBankID) {
1005 return &RISCV::VRRegClass;
1008 return &RISCV::VRM2RegClass;
1011 return &RISCV::VRM4RegClass;
1014 return &RISCV::VRM8RegClass;
1020bool RISCVInstructionSelector::isRegInGprb(
Register Reg)
const {
1024bool RISCVInstructionSelector::isRegInFprb(
Register Reg)
const {
1028bool RISCVInstructionSelector::selectCopy(MachineInstr &
MI)
const {
1034 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1037 "Register class not available for LLT, register bank combination");
1048 MI.setDesc(
TII.get(RISCV::COPY));
1052bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &
MI,
1053 MachineIRBuilder &MIB)
const {
1054 assert(
MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1056 const Register DstReg =
MI.getOperand(0).getReg();
1057 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(
1061 "Register class not available for LLT, register bank combination");
1067 MI.setDesc(
TII.get(TargetOpcode::IMPLICIT_DEF));
1071bool RISCVInstructionSelector::materializeImm(
Register DstReg, int64_t Imm,
1072 MachineIRBuilder &MIB)
const {
1080 unsigned NumInsts = Seq.
size();
1083 for (
unsigned i = 0; i < NumInsts; i++) {
1085 ?
MRI->createVirtualRegister(&RISCV::GPRRegClass)
1087 const RISCVMatInt::Inst &
I = Seq[i];
1090 switch (
I.getOpndKind()) {
1099 {SrcReg, Register(RISCV::X0)});
1119bool RISCVInstructionSelector::selectAddr(MachineInstr &
MI,
1120 MachineIRBuilder &MIB,
bool IsLocal,
1121 bool IsExternWeak)
const {
1122 assert((
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1123 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
1124 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
1125 "Unexpected opcode");
1127 const MachineOperand &DispMO =
MI.getOperand(1);
1130 const LLT DefTy =
MRI->getType(DefReg);
1137 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
1141 MI.setDesc(
TII.get(RISCV::PseudoLLA));
1149 MachineFunction &MF = *
MI.getParent()->getParent();
1163 MI.eraseFromParent();
1170 "Unsupported code model for lowering",
MI);
1177 Register AddrHiDest =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1178 MachineInstr *AddrHi = MIB.
buildInstr(RISCV::LUI, {AddrHiDest}, {})
1190 MI.eraseFromParent();
1203 MachineFunction &MF = *
MI.getParent()->getParent();
1217 MI.eraseFromParent();
1224 MI.setDesc(
TII.get(RISCV::PseudoLLA));
1231bool RISCVInstructionSelector::selectSelect(MachineInstr &
MI,
1232 MachineIRBuilder &MIB)
const {
1239 Register DstReg = SelectMI.getReg(0);
1241 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
1243 unsigned Size =
MRI->getType(DstReg).getSizeInBits();
1244 Opc =
Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
1245 : RISCV::Select_FPR64_Using_CC_GPR;
1253 .
addReg(SelectMI.getTrueReg())
1254 .
addReg(SelectMI.getFalseReg());
1255 MI.eraseFromParent();
1266 return Size == 16 ? RISCV::FLT_H :
Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
1268 return Size == 16 ? RISCV::FLE_H :
Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
1270 return Size == 16 ? RISCV::FEQ_H :
Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
1283 assert(!isLegalFCmpPredicate(Pred) &&
"Predicate already legal?");
1286 if (isLegalFCmpPredicate(InvPred)) {
1294 if (isLegalFCmpPredicate(InvPred)) {
1299 if (isLegalFCmpPredicate(InvPred)) {
1311bool RISCVInstructionSelector::selectFPCompare(MachineInstr &
MI,
1312 MachineIRBuilder &MIB)
const {
1320 unsigned Size =
MRI->getType(
LHS).getSizeInBits();
1325 bool NeedInvert =
false;
1329 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1331 if (!
Cmp.constrainAllUses(
TII,
TRI, RBI))
1337 {&RISCV::GPRRegClass}, {
LHS,
RHS});
1338 if (!Cmp1.constrainAllUses(
TII,
TRI, RBI))
1341 {&RISCV::GPRRegClass}, {
RHS,
LHS});
1342 if (!Cmp2.constrainAllUses(
TII,
TRI, RBI))
1345 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1347 MIB.
buildInstr(RISCV::OR, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1348 if (!
Or.constrainAllUses(
TII,
TRI, RBI))
1355 {&RISCV::GPRRegClass}, {
LHS,
LHS});
1356 if (!Cmp1.constrainAllUses(
TII,
TRI, RBI))
1359 {&RISCV::GPRRegClass}, {
RHS,
RHS});
1360 if (!Cmp2.constrainAllUses(
TII,
TRI, RBI))
1363 TmpReg =
MRI->createVirtualRegister(&RISCV::GPRRegClass);
1365 MIB.
buildInstr(RISCV::AND, {TmpReg}, {Cmp1.getReg(0), Cmp2.getReg(0)});
1366 if (!
And.constrainAllUses(
TII,
TRI, RBI))
1373 auto Xor = MIB.
buildInstr(RISCV::XORI, {DstReg}, {TmpReg}).addImm(1);
1374 if (!
Xor.constrainAllUses(
TII,
TRI, RBI))
1378 MI.eraseFromParent();
1382void RISCVInstructionSelector::emitFence(
AtomicOrdering FenceOrdering,
1384 MachineIRBuilder &MIB)
const {
1385 if (STI.hasStdExtZtso()) {
1388 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
1398 MIB.
buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1406 MIB.
buildInstr(TargetOpcode::MEMBARRIER, {}, {});
1412 unsigned Pred, Succ;
1413 switch (FenceOrdering) {
1416 case AtomicOrdering::AcquireRelease:
1420 case AtomicOrdering::Acquire:
1425 case AtomicOrdering::Release:
1430 case AtomicOrdering::SequentiallyConsistent:
1440InstructionSelector *
1444 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 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.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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).
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.
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.
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.
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.