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
57 static constexpr unsigned MaxRecursionDepth = 6;
60 const unsigned Depth = 0)
const;
90 bool IsExternWeak =
false)
const;
99 unsigned &CurOp,
bool IsMasked,
100 bool IsStridedOrIndexed,
101 LLT *IndexVT =
nullptr)
const;
107 unsigned ShiftWidth)
const;
108 ComplexRendererFns selectShiftMaskXLen(
MachineOperand &Root)
const {
109 return selectShiftMask(Root, STI.
getXLen());
111 ComplexRendererFns selectShiftMask32(
MachineOperand &Root)
const {
112 return selectShiftMask(Root, 32);
116 ComplexRendererFns selectAddrRegImmLsb00000(
MachineOperand &Root)
const;
121 struct ConstAddrPlan {
122 enum { X0, LUI, InstSeq } Kind = X0;
127 ComplexRendererFns computeConstAddr(int64_t CVal,
bool IsPrefetch,
132 const ConstAddrPlan &Plan,
135 ComplexRendererFns selectSExtBits(
MachineOperand &Root,
unsigned Bits)
const;
136 template <
unsigned Bits>
138 return selectSExtBits(Root, Bits);
141 ComplexRendererFns selectZExtBits(
MachineOperand &Root,
unsigned Bits)
const;
142 template <
unsigned Bits>
144 return selectZExtBits(Root, Bits);
147 ComplexRendererFns selectSHXADDOp(
MachineOperand &Root,
unsigned ShAmt)
const;
148 template <
unsigned ShAmt>
150 return selectSHXADDOp(Root, ShAmt);
154 unsigned ShAmt)
const;
155 template <
unsigned ShAmt>
156 ComplexRendererFns selectSHXADD_UWOp(
MachineOperand &Root)
const {
157 return selectSHXADD_UWOp(Root, ShAmt);
161 ComplexRendererFns renderAddiPair(
Register BaseReg, int64_t AddiImm,
162 int64_t OffsetImm)
const;
196#define GET_GLOBALISEL_PREDICATES_DECL
197#include "RISCVGenGlobalISel.inc"
198#undef GET_GLOBALISEL_PREDICATES_DECL
200#define GET_GLOBALISEL_TEMPORARIES_DECL
201#include "RISCVGenGlobalISel.inc"
202#undef GET_GLOBALISEL_TEMPORARIES_DECL
207#define GET_GLOBALISEL_IMPL
208#include "RISCVGenGlobalISel.inc"
209#undef GET_GLOBALISEL_IMPL
211RISCVInstructionSelector::RISCVInstructionSelector(
214 : STI(STI),
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI),
218#include
"RISCVGenGlobalISel.inc"
221#include
"RISCVGenGlobalISel.inc"
227bool RISCVInstructionSelector::hasAllNBitUsers(
const MachineInstr &
MI,
229 const unsigned Depth)
const {
231 assert((
MI.getOpcode() == TargetOpcode::G_ADD ||
232 MI.getOpcode() == TargetOpcode::G_SUB ||
233 MI.getOpcode() == TargetOpcode::G_MUL ||
234 MI.getOpcode() == TargetOpcode::G_SHL ||
235 MI.getOpcode() == TargetOpcode::G_LSHR ||
236 MI.getOpcode() == TargetOpcode::G_AND ||
237 MI.getOpcode() == TargetOpcode::G_OR ||
238 MI.getOpcode() == TargetOpcode::G_XOR ||
239 MI.getOpcode() == TargetOpcode::G_SEXT_INREG ||
Depth != 0) &&
240 "Unexpected opcode");
242 if (
Depth >= RISCVInstructionSelector::MaxRecursionDepth)
245 auto DestReg =
MI.getOperand(0).getReg();
247 assert(UserOp.getParent() &&
"UserOp must have a parent");
248 const MachineInstr &UserMI = *UserOp.getParent();
249 unsigned OpIdx = UserOp.getOperandNo();
257 case RISCV::FCVT_D_W:
258 case RISCV::FCVT_S_W:
301InstructionSelector::ComplexRendererFns
302RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,
303 unsigned ShiftWidth)
const {
307 using namespace llvm::MIPatternMatch;
313 ShAmtReg = ZExtSrcReg;
332 APInt ShMask(AndMask.
getBitWidth(), ShiftWidth - 1);
333 if (ShMask.isSubsetOf(AndMask)) {
334 ShAmtReg = AndSrcReg;
338 KnownBits
Known = VT->getKnownBits(AndSrcReg);
339 if (ShMask.isSubsetOf(AndMask |
Known.Zero))
340 ShAmtReg = AndSrcReg;
347 if (
Imm != 0 &&
Imm.urem(ShiftWidth) == 0)
352 if (
Imm != 0 &&
Imm.urem(ShiftWidth) == 0) {
356 unsigned NegOpc =
Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
357 return {{[=](MachineInstrBuilder &MIB) {
358 MachineIRBuilder(*MIB.getInstr())
359 .buildInstr(NegOpc, {ShAmtReg}, {
Register(RISCV::X0),
Reg});
360 MIB.addReg(ShAmtReg);
363 if (
Imm.urem(ShiftWidth) == ShiftWidth - 1) {
367 return {{[=](MachineInstrBuilder &MIB) {
368 MachineIRBuilder(*MIB.getInstr())
369 .buildInstr(RISCV::XORI, {ShAmtReg}, {
Reg})
371 MIB.addReg(ShAmtReg);
376 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
379InstructionSelector::ComplexRendererFns
380RISCVInstructionSelector::selectSExtBits(MachineOperand &Root,
381 unsigned Bits)
const {
389 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SrcReg); }}};
393 if ((
Size - VT->computeNumSignBits(RootReg)) < Bits)
394 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
399InstructionSelector::ComplexRendererFns
400RISCVInstructionSelector::selectZExtBits(MachineOperand &Root,
401 unsigned Bits)
const {
409 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
414 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RegX); }}};
418 return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
423InstructionSelector::ComplexRendererFns
424RISCVInstructionSelector::selectSHXADDOp(MachineOperand &Root,
425 unsigned ShAmt)
const {
426 using namespace llvm::MIPatternMatch;
432 const unsigned XLen = STI.
getXLen();
447 assert(
Mask.getBitWidth() == XLen &&
"Unexpected mask size!");
448 assert(C2 > 0 && C2 < XLen &&
"Unexpected shift amount!");
454 if (
Mask.isShiftedMask()) {
455 unsigned Leading = XLen -
Mask.getActiveBits();
456 unsigned Trailing =
Mask.countr_zero();
459 if (*LeftShift && Leading == 0 && C2 < Trailing && Trailing == ShAmt) {
461 return {{[=](MachineInstrBuilder &MIB) {
462 MachineIRBuilder(*MIB.getInstr())
463 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
464 .addImm(Trailing - C2);
471 if (!*LeftShift && Leading == C2 && Trailing == ShAmt) {
473 return {{[=](MachineInstrBuilder &MIB) {
474 MachineIRBuilder(*MIB.getInstr())
475 .buildInstr(RISCV::SRLI, {DstReg}, {RegY})
476 .addImm(Leading + Trailing);
496 unsigned Leading = XLen -
Mask.getActiveBits();
497 unsigned Trailing =
Mask.countr_zero();
502 *
LeftShift && Leading == 32 && Trailing > 0 && (Trailing + C2) == ShAmt;
507 (Trailing - C2) == ShAmt;
511 return {{[=](MachineInstrBuilder &MIB) {
512 MachineIRBuilder(*MIB.getInstr())
513 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
523InstructionSelector::ComplexRendererFns
524RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
525 unsigned ShAmt)
const {
526 using namespace llvm::MIPatternMatch;
541 assert(C2 > 0 && C2 <
Mask.getBitWidth() &&
"Unexpected shift amount!");
544 if (
Mask.isShiftedMask()) {
545 unsigned Leading =
Mask.countl_zero();
546 unsigned Trailing =
Mask.countr_zero();
547 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
549 return {{[=](MachineInstrBuilder &MIB) {
550 MachineIRBuilder(*MIB.getInstr())
551 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
562InstructionSelector::ComplexRendererFns
563RISCVInstructionSelector::renderVLOp(MachineOperand &Root)
const {
564 assert(Root.
isReg() &&
"Expected operand to be a Register");
565 std::optional<ValueAndVReg>
C;
567 if (
C->Value.isAllOnes())
571 return {{[=](MachineInstrBuilder &MIB) {
576 uint64_t ZExtC =
C->Value.getZExtValue();
577 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
580 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.
getReg()); }}};
583InstructionSelector::ComplexRendererFns
584RISCVInstructionSelector::renderAddiPair(
Register BaseReg, int64_t AddiImm,
585 int64_t OffsetImm)
const {
586 return {{[=](MachineInstrBuilder &MIB) {
589 BuildMI(*MIB->getParent(), *MIB.getInstr(), MIB->getDebugLoc(),
590 TII.get(RISCV::ADDI), Tmp)
596 [=](MachineInstrBuilder &MIB) { MIB.addImm(OffsetImm); }}};
599InstructionSelector::ComplexRendererFns
600RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root)
const {
610 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); },
611 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
623 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(BaseFI); },
624 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
627 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
628 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
633 if (RHSC >= -4096 && RHSC <= 4094) {
634 int64_t Adj = RHSC < 0 ? -2048 : 2047;
635 return renderAddiPair(BaseReg, Adj, RHSC - Adj);
639 if (
auto Fns = computeConstAddr(RHSC,
false, BaseReg))
648 if (
auto Fns = computeConstAddr(CVal,
false,
Register()))
652 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
653 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
656InstructionSelector::ComplexRendererFns
657RISCVInstructionSelector::selectBrindRegImm(MachineOperand &Root)
const {
670 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
671 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
674 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
675 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
678InstructionSelector::ComplexRendererFns
679RISCVInstructionSelector::selectAddrRegImmLsb00000(MachineOperand &Root)
const {
689 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); },
690 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
700 if ((RHSC & 0b11111) != 0) {
701 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
702 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
708 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(BaseFI); },
709 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
711 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
712 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
716 if ((-2049 >= RHSC && RHSC >= -4096) || (4063 >= RHSC && RHSC >= 2017)) {
717 int64_t Adj = RHSC < 0 ? -2048 : 2016;
718 return renderAddiPair(BaseReg, RHSC - Adj, Adj);
723 if (
auto Fns = computeConstAddr(RHSC,
true, BaseReg))
732 if (
auto Fns = computeConstAddr(CVal,
true,
Register()))
736 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
737 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
746 case CmpInst::Predicate::ICMP_EQ:
748 case CmpInst::Predicate::ICMP_NE:
750 case CmpInst::Predicate::ICMP_ULT:
752 case CmpInst::Predicate::ICMP_SLT:
754 case CmpInst::Predicate::ICMP_UGE:
756 case CmpInst::Predicate::ICMP_SGE:
822 CC = getRISCVCCFromICmp(
Pred);
829 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
834 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
836 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
838 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
840 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
849 unsigned GenericOpc,
unsigned OpSize) {
850 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
854 return IsStore ? RISCV::SB : RISCV::LBU;
856 return IsStore ? RISCV::SH : RISCV::LH;
858 return IsStore ? RISCV::SW : RISCV::LW;
862 if (!STI.
is64Bit() && STI.hasStdExtZilsd())
863 return IsStore ? RISCV::SD_RV32 : RISCV::LD_RV32;
864 return IsStore ? RISCV::SD : RISCV::LD;
870void RISCVInstructionSelector::addVectorLoadStoreOperands(
871 MachineInstr &
I, SmallVectorImpl<Register> &SrcOps,
unsigned &CurOp,
872 bool IsMasked,
bool IsStridedOrIndexed, LLT *IndexVT)
const {
874 auto PtrReg =
I.getOperand(CurOp++).getReg();
878 if (IsStridedOrIndexed) {
879 auto StrideReg =
I.getOperand(CurOp++).getReg();
887 auto MaskReg =
I.getOperand(CurOp++).getReg();
892bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
893 MachineInstr &
I)
const {
900 case Intrinsic::riscv_vlm:
901 case Intrinsic::riscv_vle:
902 case Intrinsic::riscv_vle_mask:
903 case Intrinsic::riscv_vlse:
904 case Intrinsic::riscv_vlse_mask: {
905 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
906 IntrinID == Intrinsic::riscv_vlse_mask;
907 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
908 IntrinID == Intrinsic::riscv_vlse_mask;
913 const Register DstReg =
I.getOperand(0).getReg();
916 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
921 if (HasPassthruOperand) {
922 auto PassthruReg =
I.getOperand(CurOp++).getReg();
928 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked, IsStrided);
931 const RISCV::VLEPseudo *
P =
932 RISCV::getVLEPseudo(IsMasked, IsStrided,
false, Log2SEW,
933 static_cast<unsigned>(LMUL));
935 MachineInstrBuilder PseudoMI =
936 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(
P->Pseudo), DstReg);
941 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
942 for (
auto &RenderFn : *VLOpFn)
951 Policy =
I.getOperand(CurOp++).getImm();
961 case Intrinsic::riscv_vloxei:
962 case Intrinsic::riscv_vloxei_mask:
963 case Intrinsic::riscv_vluxei:
964 case Intrinsic::riscv_vluxei_mask: {
965 bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
966 IntrinID == Intrinsic::riscv_vluxei_mask;
967 bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
968 IntrinID == Intrinsic::riscv_vloxei_mask;
973 const Register DstReg =
I.getOperand(0).getReg();
976 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
981 if (HasPassthruOperand) {
982 auto PassthruReg =
I.getOperand(CurOp++).getReg();
989 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked,
true, &IndexVT);
995 if (IndexLog2EEW == 6 && !
Subtarget->is64Bit()) {
997 "values when XLEN=32");
999 const RISCV::VLX_VSXPseudo *
P = RISCV::getVLXPseudo(
1000 IsMasked, IsOrdered, IndexLog2EEW,
static_cast<unsigned>(LMUL),
1001 static_cast<unsigned>(IndexLMUL));
1003 MachineInstrBuilder PseudoMI =
1004 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(
P->Pseudo), DstReg);
1009 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1010 for (
auto &RenderFn : *VLOpFn)
1014 PseudoMI.
addImm(Log2SEW);
1019 Policy =
I.getOperand(CurOp++).getImm();
1025 I.eraseFromParent();
1029 case Intrinsic::riscv_vsm:
1030 case Intrinsic::riscv_vse:
1031 case Intrinsic::riscv_vse_mask:
1032 case Intrinsic::riscv_vsse:
1033 case Intrinsic::riscv_vsse_mask: {
1034 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
1035 IntrinID == Intrinsic::riscv_vsse_mask;
1036 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
1037 IntrinID == Intrinsic::riscv_vsse_mask;
1046 auto PassthruReg =
I.getOperand(CurOp++).getReg();
1049 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked, IsStrided);
1052 const RISCV::VSEPseudo *
P = RISCV::getVSEPseudo(
1053 IsMasked, IsStrided, Log2SEW,
static_cast<unsigned>(LMUL));
1055 MachineInstrBuilder PseudoMI =
1061 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1062 for (
auto &RenderFn : *VLOpFn)
1066 PseudoMI.
addImm(Log2SEW);
1071 I.eraseFromParent();
1075 case Intrinsic::riscv_vsoxei:
1076 case Intrinsic::riscv_vsoxei_mask:
1077 case Intrinsic::riscv_vsuxei:
1078 case Intrinsic::riscv_vsuxei_mask: {
1079 bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
1080 IntrinID == Intrinsic::riscv_vsuxei_mask;
1081 bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
1082 IntrinID == Intrinsic::riscv_vsoxei_mask;
1091 auto PassthruReg =
I.getOperand(CurOp++).getReg();
1095 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked,
true, &IndexVT);
1101 if (IndexLog2EEW == 6 && !
Subtarget->is64Bit()) {
1103 "values when XLEN=32");
1105 const RISCV::VLX_VSXPseudo *
P = RISCV::getVSXPseudo(
1106 IsMasked, IsOrdered, IndexLog2EEW,
static_cast<unsigned>(LMUL),
1107 static_cast<unsigned>(IndexLMUL));
1109 MachineInstrBuilder PseudoMI =
1115 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1116 for (
auto &RenderFn : *VLOpFn)
1120 PseudoMI.
addImm(Log2SEW);
1125 I.eraseFromParent();
1132bool RISCVInstructionSelector::selectIntrinsic(MachineInstr &
I)
const {
1139 case Intrinsic::riscv_vsetvli:
1140 case Intrinsic::riscv_vsetvlimax: {
1142 bool VLMax = IntrinID == Intrinsic::riscv_vsetvlimax;
1144 unsigned Offset = VLMax ? 2 : 3;
1152 Register DstReg =
I.getOperand(0).getReg();
1155 unsigned Opcode = RISCV::PseudoVSETVLI;
1159 Register AVLReg =
I.getOperand(2).getReg();
1161 uint64_t AVL = AVLConst->Value.getZExtValue();
1162 if (
auto VLEN =
Subtarget->getRealVLen()) {
1174 Opcode = RISCV::PseudoVSETVLIX0;
1176 Register AVLReg =
I.getOperand(2).getReg();
1181 uint64_t AVL = AVLConst->Value.getZExtValue();
1183 MachineInstr *PseudoMI =
1185 TII.get(RISCV::PseudoVSETIVLI), DstReg)
1188 I.eraseFromParent();
1195 MachineInstr *PseudoMI =
1196 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode), DstReg)
1199 I.eraseFromParent();
1206bool RISCVInstructionSelector::selectExtractSubvector(MachineInstr &
MI)
const {
1207 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR);
1215 unsigned Idx =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
1221 std::tie(SubRegIdx, Idx) =
1223 SrcMVT, DstMVT, Idx, &
TRI);
1238 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
TII.get(TargetOpcode::COPY),
1240 .
addReg(SrcReg, {}, SubRegIdx);
1242 MI.eraseFromParent();
1246bool RISCVInstructionSelector::selectInsertSubVector(MachineInstr &
MI)
const {
1247 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR);
1251 Register SubVecReg =
MI.getOperand(2).getReg();
1259 unsigned Idx =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
1262 std::tie(SubRegIdx, Idx) =
1264 VecMVT, SubVecMVT, Idx, &
TRI);
1280 if (SubRegIdx == RISCV::NoSubRegister) {
1283 "Unexpected subvector insert");
1284 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
TII.get(TargetOpcode::COPY),
1287 MI.eraseFromParent();
1293 MachineInstr *Ins =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1294 TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1299 MI.eraseFromParent();
1304bool RISCVInstructionSelector::select(MachineInstr &
MI) {
1306 const unsigned Opc =
MI.getOpcode();
1308 if (!
MI.isPreISelOpcode() ||
Opc == TargetOpcode::G_PHI) {
1309 if (
Opc == TargetOpcode::PHI ||
Opc == TargetOpcode::G_PHI) {
1310 const Register DefReg =
MI.getOperand(0).getReg();
1325 DefRC =
TRI.getRegClassForTypeOnBank(DefTy, RB, STI.
is64Bit());
1332 MI.setDesc(
TII.get(TargetOpcode::PHI));
1343 if (selectImpl(
MI, *CoverageInfo))
1347 case TargetOpcode::G_ANYEXT:
1348 case TargetOpcode::G_PTRTOINT:
1349 case TargetOpcode::G_INTTOPTR:
1350 case TargetOpcode::G_TRUNC:
1351 case TargetOpcode::G_FREEZE:
1353 case TargetOpcode::G_CONSTANT: {
1355 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
1357 if (!materializeImm(DstReg,
Imm,
MI))
1360 MI.eraseFromParent();
1363 case TargetOpcode::G_ZEXT:
1364 case TargetOpcode::G_SEXT: {
1365 bool IsSigned =
Opc != TargetOpcode::G_ZEXT;
1375 RISCV::GPRBRegBankID &&
1376 "Unexpected ext regbank");
1379 if (IsSigned && SrcSize == 32) {
1380 MI.setDesc(
TII.get(RISCV::ADDIW));
1387 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
1388 MI.setDesc(
TII.get(RISCV::ADD_UW));
1395 if (SrcSize == 16 &&
1396 (STI.hasStdExtZbb() || (!IsSigned && STI.hasStdExtZbkb()))) {
1397 MI.setDesc(
TII.get(IsSigned ? RISCV::SEXT_H
1398 : STI.
is64Bit() ? RISCV::ZEXT_H_RV64
1399 : RISCV::ZEXT_H_RV32));
1406 MachineInstr *ShiftLeft =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1407 TII.get(RISCV::SLLI), ShiftLeftReg)
1411 MachineInstr *ShiftRight =
1413 TII.get(IsSigned ? RISCV::SRAI : RISCV::SRLI), DstReg)
1417 MI.eraseFromParent();
1420 case TargetOpcode::G_FCONSTANT: {
1423 const APFloat &FPimm =
MI.getOperand(1).getFPImm()->getValueAPF();
1432 if (!materializeImm(GPRReg,
Imm.getSExtValue(),
MI))
1436 unsigned Opcode =
Size == 64 ? RISCV::FMV_D_X
1437 :
Size == 32 ? RISCV::FMV_W_X
1439 MachineInstr *FMV =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1440 TII.get(Opcode), DstReg)
1446 "Unexpected size or subtarget");
1450 MachineInstr *FCVT =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1451 TII.get(RISCV::FCVT_D_W), DstReg)
1456 MI.eraseFromParent();
1464 if (!materializeImm(GPRRegHigh,
Imm.extractBits(32, 32).getSExtValue(),
1467 if (!materializeImm(GPRRegLow,
Imm.trunc(32).getSExtValue(),
MI))
1469 MachineInstr *PairF64 =
1471 TII.get(RISCV::BuildPairF64Pseudo), DstReg)
1477 MI.eraseFromParent();
1480 case TargetOpcode::G_GLOBAL_VALUE: {
1481 auto *GV =
MI.getOperand(1).getGlobal();
1482 if (GV->isThreadLocal()) {
1487 return selectAddr(
MI, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1489 case TargetOpcode::G_JUMP_TABLE:
1490 case TargetOpcode::G_CONSTANT_POOL:
1491 return selectAddr(
MI);
1492 case TargetOpcode::G_BRCOND: {
1497 MachineInstr *Bcc =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1501 .
addMBB(
MI.getOperand(1).getMBB());
1502 MI.eraseFromParent();
1506 case TargetOpcode::G_SELECT:
1507 return selectSelect(
MI);
1508 case TargetOpcode::G_FCMP:
1509 return selectFPCompare(
MI);
1510 case TargetOpcode::G_FENCE: {
1515 emitFence(FenceOrdering, FenceSSID,
MI);
1516 MI.eraseFromParent();
1519 case TargetOpcode::G_IMPLICIT_DEF:
1520 return selectImplicitDef(
MI);
1521 case TargetOpcode::G_UNMERGE_VALUES:
1523 case TargetOpcode::G_MERGE_VALUES:
1525 case TargetOpcode::G_LOAD:
1526 case TargetOpcode::G_STORE: {
1533 if (RB.
getID() != RISCV::GPRBRegBankID)
1540 "Load/Store pointer operand isn't a GPR");
1541 assert(PtrTy.
isPointer() &&
"Load/Store pointer operand isn't a pointer");
1557 const unsigned NewOpc =
1559 if (NewOpc ==
MI.getOpcode())
1563 auto AddrModeFns = selectAddrRegImm(
MI.getOperand(1));
1568 MachineInstrBuilder NewInst =
1576 for (
auto &Fn : *AddrModeFns)
1578 MI.eraseFromParent();
1583 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1584 return selectIntrinsicWithSideEffects(
MI);
1585 case TargetOpcode::G_INTRINSIC:
1586 return selectIntrinsic(
MI);
1587 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1588 return selectExtractSubvector(
MI);
1589 case TargetOpcode::G_INSERT_SUBVECTOR:
1590 return selectInsertSubVector(
MI);
1596bool RISCVInstructionSelector::selectUnmergeValues(MachineInstr &
MI)
const {
1597 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1600 if (
MI.getNumOperands() != 3)
1609 isRegInGprb(
Lo) && isRegInGprb(
Hi)) {
1621 auto ExtractHalf = [&](
Register Dst,
unsigned SubIdx) {
1623 MachineInstr &
C = *
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1624 TII.get(TargetOpcode::COPY), Dst)
1625 .
addReg(Src, {}, SubIdx);
1628 ExtractHalf(
Lo, RISCV::sub_gpr_even);
1629 ExtractHalf(
Hi, RISCV::sub_gpr_odd);
1630 MI.eraseFromParent();
1637 if (!isRegInFprb(Src) || !isRegInGprb(
Lo) || !isRegInGprb(
Hi))
1640 MachineInstr *ExtractLo =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1641 TII.get(RISCV::FMV_X_W_FPR64),
Lo)
1645 MachineInstr *ExtractHi =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1646 TII.get(RISCV::FMVH_X_D),
Hi)
1650 MI.eraseFromParent();
1654bool RISCVInstructionSelector::selectMergeValues(MachineInstr &
MI)
const {
1655 assert(
MI.getOpcode() == TargetOpcode::G_MERGE_VALUES);
1657 if (
MI.getNumOperands() != 3)
1666 isRegInGprb(
Lo) && isRegInGprb(
Hi)) {
1672 MachineInstr &Seq = *
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1673 TII.get(TargetOpcode::REG_SEQUENCE), Dst)
1675 .
addImm(RISCV::sub_gpr_even)
1677 .
addImm(RISCV::sub_gpr_odd);
1678 MI.eraseFromParent();
1685bool RISCVInstructionSelector::replacePtrWithInt(MachineInstr &
MI,
1687 MachineOperand &
Op =
MI.getOperand(OpIdx);
1694 MachineInstr *PtrToInt =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1695 TII.get(TargetOpcode::G_PTRTOINT), IntReg)
1698 return select(*PtrToInt);
1701void RISCVInstructionSelector::preISelLower(MachineInstr &
MI) {
1702 switch (
MI.getOpcode()) {
1703 case TargetOpcode::G_PTR_ADD: {
1707 replacePtrWithInt(
MI, 1);
1708 MI.setDesc(
TII.get(TargetOpcode::G_ADD));
1712 case TargetOpcode::G_PTRMASK: {
1715 replacePtrWithInt(
MI, 1);
1716 MI.setDesc(
TII.get(TargetOpcode::G_AND));
1723void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1724 const MachineInstr &
MI,
1726 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1727 "Expected G_CONSTANT");
1728 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1732void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1733 const MachineInstr &
MI,
1735 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1736 "Expected G_CONSTANT");
1737 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1741void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1742 const MachineInstr &
MI,
1744 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1745 "Expected G_CONSTANT");
1746 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1750void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1751 const MachineInstr &
MI,
1753 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1754 "Expected G_CONSTANT");
1755 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1759void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1760 const MachineInstr &
MI,
1762 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1763 "Expected G_CONSTANT");
1764 uint64_t C =
MI.getOperand(1).getCImm()->getZExtValue();
1768void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1769 MachineInstrBuilder &MIB,
const MachineInstr &
MI,
int OpIdx)
const {
1770 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1771 "Expected G_CONSTANT");
1772 uint64_t C =
MI.getOperand(1).getCImm()->getZExtValue();
1776void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1777 const MachineInstr &
MI,
1779 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1780 "Expected G_CONSTANT");
1781 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
1782 int64_t Adj =
Imm < 0 ? -2048 : 2047;
1786void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1787 const MachineInstr &
MI,
1789 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1790 "Expected G_CONSTANT");
1791 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1795bool RISCVInstructionSelector::isRegInGprb(
Register Reg)
const {
1799bool RISCVInstructionSelector::isRegInFprb(
Register Reg)
const {
1807bool RISCVInstructionSelector::isWorthFoldingAdd(
Register AddResult)
const {
1825bool RISCVInstructionSelector::selectCopy(MachineInstr &
MI)
const {
1832 TRI.getConstrainedRegClassForReg(DstReg, *
MRI);
1835 "Register class not available for LLT, register bank combination");
1846 MI.setDesc(
TII.get(RISCV::COPY));
1850bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &
MI)
const {
1851 assert(
MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1853 const Register DstReg =
MI.getOperand(0).getReg();
1858 "Register class not available for LLT, register bank combination");
1864 MI.setDesc(
TII.get(TargetOpcode::IMPLICIT_DEF));
1868bool RISCVInstructionSelector::materializeImm(
Register DstReg, int64_t
Imm,
1869 MachineInstr &
MI)
const {
1879 return materializeInstSeq(DstReg, Seq,
MI);
1882bool RISCVInstructionSelector::materializeInstSeq(
1884 assert(!Seq.
empty() &&
"materializeInstSeq requires a non-empty sequence");
1888 unsigned NumInsts = Seq.
size();
1891 for (
unsigned i = 0; i < NumInsts; i++) {
1895 const RISCVMatInt::Inst &
I = Seq[i];
1898 switch (
I.getOpndKind()) {
1928InstructionSelector::ComplexRendererFns
1929RISCVInstructionSelector::computeConstAddr(int64_t CVal,
bool IsPrefetch,
1936 auto emit = [&](ConstAddrPlan Plan) -> ComplexRendererFns {
1937 return {{[=](MachineInstrBuilder &MIB) {
1938 MIB.
addReg(materializeConstBase(MIB, Plan, OrigBase));
1940 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Plan.Lo12); }}};
1943 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1944 return std::nullopt;
1948 Plan.Kind = ConstAddrPlan::LUI;
1949 Plan.Hi20 = (
Hi >> 12) & 0xfffff;
1951 return emit(std::move(Plan));
1957 if (Seq.
back().getOpcode() != RISCV::ADDI)
1958 return std::nullopt;
1959 Lo12 = Seq.
back().getImm();
1960 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1961 return std::nullopt;
1964 return std::nullopt;
1966 Plan.Kind = ConstAddrPlan::InstSeq;
1967 Plan.Seq = std::move(Seq);
1969 return emit(std::move(Plan));
1973RISCVInstructionSelector::materializeConstBase(MachineInstrBuilder &MIB,
1974 const ConstAddrPlan &Plan,
1978 MachineInstr &InsertPt = *MIB.
getInstr();
1981 switch (Plan.Kind) {
1982 case ConstAddrPlan::X0:
1984 case ConstAddrPlan::LUI: {
1986 MachineInstr *LUI =
BuildMI(
MBB, InsertPt,
DL,
TII.get(RISCV::LUI), HiReg)
1991 case ConstAddrPlan::InstSeq: {
1993 materializeInstSeq(HiReg, Plan.Seq, InsertPt);
2000 if (OrigBase.
isValid() && HiReg != RISCV::X0) {
2008 return OrigBase.
isValid() ? OrigBase : HiReg;
2011bool RISCVInstructionSelector::selectAddr(MachineInstr &
MI,
bool IsLocal,
2012 bool IsExternWeak)
const {
2013 assert((
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
2014 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
2015 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
2016 "Unexpected opcode");
2018 const MachineOperand &DispMO =
MI.getOperand(1);
2028 if (IsLocal && !
Subtarget->allowTaggedGlobals()) {
2032 MI.setDesc(
TII.get(RISCV::PseudoLLA));
2049 TII.get(RISCV::PseudoLGA), DefReg)
2055 MI.eraseFromParent();
2062 "Unsupported code model for lowering",
MI);
2070 MachineInstr *AddrHi =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
2071 TII.get(RISCV::LUI), AddrHiDest)
2077 TII.get(RISCV::ADDI), DefReg)
2083 MI.eraseFromParent();
2104 TII.get(RISCV::PseudoLGA), DefReg)
2110 MI.eraseFromParent();
2117 MI.setDesc(
TII.get(RISCV::PseudoLLA));
2125bool RISCVInstructionSelector::selectSelect(MachineInstr &
MI)
const {
2132 Register DstReg = SelectMI.getReg(0);
2134 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
2137 Opc =
Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
2138 : RISCV::Select_FPR64_Using_CC_GPR;
2147 .
addReg(SelectMI.getTrueReg())
2148 .
addReg(SelectMI.getFalseReg());
2149 MI.eraseFromParent();
2161 return Size == 16 ? RISCV::FLT_H :
Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
2163 return Size == 16 ? RISCV::FLE_H :
Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
2165 return Size == 16 ? RISCV::FEQ_H :
Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
2178 assert(!isLegalFCmpPredicate(
Pred) &&
"Predicate already legal?");
2181 if (isLegalFCmpPredicate(InvPred)) {
2189 if (isLegalFCmpPredicate(InvPred)) {
2194 if (isLegalFCmpPredicate(InvPred)) {
2206bool RISCVInstructionSelector::selectFPCompare(MachineInstr &
MI)
const {
2219 bool NeedInvert =
false;
2234 MachineInstr *Cmp1 =
2242 MachineInstr *Cmp2 =
2252 TII.get(RISCV::OR), TmpReg)
2272 MachineInstr *Cmp1 =
2280 MachineInstr *Cmp2 =
2288 TII.get(RISCV::AND), TmpReg)
2299 TII.get(RISCV::XORI), DstReg)
2305 MI.eraseFromParent();
2309void RISCVInstructionSelector::emitFence(
AtomicOrdering FenceOrdering,
2311 MachineInstr &
MI)
const {
2315 if (STI.hasStdExtZtso()) {
2318 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
2342 unsigned Pred, Succ;
2343 switch (FenceOrdering) {
2346 case AtomicOrdering::AcquireRelease:
2350 case AtomicOrdering::Acquire:
2355 case AtomicOrdering::Release:
2360 case AtomicOrdering::SequentiallyConsistent:
2370InstructionSelector *
2374 return new RISCVInstructionSelector(TM,
Subtarget, RBI);
const AArch64Subtarget & Subtarget
#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 selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
static StringRef getName(Value *V)
static bool isWorthFoldingAdd(SDValue Add)
static unsigned selectRegImmLoadStoreOp(const RISCVSubtarget &STI, unsigned GenericOpc, unsigned OpSize)
Select the RISC-V regimm opcode for the G_LOAD or G_STORE operation GenericOpc on STI,...
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)
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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.
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,...
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.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
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
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addDisp(const MachineOperand &Disp, int64_t off, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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.
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,...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI void setRegBank(Register Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Analysis providing profile information.
This class provides the information for the target register banks.
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
static unsigned getRegClassIDForVecVT(MVT VT)
static RISCVVType::VLMUL getLMUL(MVT VT)
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.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
bool isPositionIndependent() const
CodeModel::Model getCodeModel() const
Returns the code model.
#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.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
operand_type_match m_Pred()
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
UnaryOp_match< SrcTy, TargetOpcode::G_INTTOPTR > m_GIntToPtr(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
SpecificImmMatch m_SpecificImm(int64_t RequestedValue)
Matches an immediate operand equal to RequestedValue.
AllOnesConstantMatch m_AllOnes()
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
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_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
GFrameIndexMatch m_GFrameIndex(int &FI)
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)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
SrcImmOp_match< SrcTy, AnyImmMatch, TargetOpcode::G_SEXT_INREG > m_GSExtInReg(const SrcTy &Src)
Matches a G_SEXT_INREG, binding its source and immediate width.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
SmallVector< Inst, 8 > InstSeq
static unsigned decodeVSEW(unsigned VSEW)
LLVM_ABI unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
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.
@ User
could "use" a pointer
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Known
Known to have no common set bits.
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 void 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.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
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 raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
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.