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);
497 unsigned Leading = XLen -
Mask.getActiveBits();
498 unsigned Trailing =
Mask.countr_zero();
503 *
LeftShift && Leading == 32 && Trailing > 0 && (Trailing + C2) == ShAmt;
508 (Trailing - C2) == ShAmt;
512 return {{[=](MachineInstrBuilder &MIB) {
513 MachineIRBuilder(*MIB.getInstr())
514 .buildInstr(RISCV::SRLIW, {DstReg}, {RegY})
524InstructionSelector::ComplexRendererFns
525RISCVInstructionSelector::selectSHXADD_UWOp(MachineOperand &Root,
526 unsigned ShAmt)
const {
527 using namespace llvm::MIPatternMatch;
543 assert(C2 > 0 && C2 <
Mask.getBitWidth() &&
"Unexpected shift amount!");
546 if (
Mask.isShiftedMask()) {
547 unsigned Leading =
Mask.countl_zero();
548 unsigned Trailing =
Mask.countr_zero();
549 if (Leading == 32 - ShAmt && C2 == Trailing && Trailing > ShAmt) {
551 return {{[=](MachineInstrBuilder &MIB) {
552 MachineIRBuilder(*MIB.getInstr())
553 .buildInstr(RISCV::SLLI, {DstReg}, {RegX})
564InstructionSelector::ComplexRendererFns
565RISCVInstructionSelector::renderVLOp(MachineOperand &Root)
const {
566 assert(Root.
isReg() &&
"Expected operand to be a Register");
567 std::optional<ValueAndVReg>
C;
569 if (
C->Value.isAllOnes())
573 return {{[=](MachineInstrBuilder &MIB) {
578 uint64_t ZExtC =
C->Value.getZExtValue();
579 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(ZExtC); }}};
582 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.
getReg()); }}};
585InstructionSelector::ComplexRendererFns
586RISCVInstructionSelector::renderAddiPair(
Register BaseReg, int64_t AddiImm,
587 int64_t OffsetImm)
const {
588 return {{[=](MachineInstrBuilder &MIB) {
591 BuildMI(*MIB->getParent(), *MIB.getInstr(), MIB->getDebugLoc(),
592 TII.get(RISCV::ADDI), Tmp)
598 [=](MachineInstrBuilder &MIB) { MIB.addImm(OffsetImm); }}};
601InstructionSelector::ComplexRendererFns
602RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root)
const {
612 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); },
613 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
625 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(BaseFI); },
626 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
629 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
630 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
635 if (RHSC >= -4096 && RHSC <= 4094) {
636 int64_t Adj = RHSC < 0 ? -2048 : 2047;
637 return renderAddiPair(BaseReg, Adj, RHSC - Adj);
641 if (
auto Fns = computeConstAddr(RHSC,
false, BaseReg))
650 if (
auto Fns = computeConstAddr(CVal,
false,
Register()))
654 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
655 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
658InstructionSelector::ComplexRendererFns
659RISCVInstructionSelector::selectBrindRegImm(MachineOperand &Root)
const {
672 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
673 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
676 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
677 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
680InstructionSelector::ComplexRendererFns
681RISCVInstructionSelector::selectAddrRegImmLsb00000(MachineOperand &Root)
const {
691 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); },
692 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
702 if ((RHSC & 0b11111) != 0) {
703 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
704 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
710 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(BaseFI); },
711 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
713 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(BaseReg); },
714 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); }}};
718 if ((-2049 >= RHSC && RHSC >= -4096) || (4063 >= RHSC && RHSC >= 2017)) {
719 int64_t Adj = RHSC < 0 ? -2048 : 2016;
720 return renderAddiPair(BaseReg, RHSC - Adj, Adj);
725 if (
auto Fns = computeConstAddr(RHSC,
true, BaseReg))
734 if (
auto Fns = computeConstAddr(CVal,
true,
Register()))
738 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(RootReg); },
739 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
748 case CmpInst::Predicate::ICMP_EQ:
750 case CmpInst::Predicate::ICMP_NE:
752 case CmpInst::Predicate::ICMP_ULT:
754 case CmpInst::Predicate::ICMP_SLT:
756 case CmpInst::Predicate::ICMP_UGE:
758 case CmpInst::Predicate::ICMP_SGE:
824 CC = getRISCVCCFromICmp(Pred);
831 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
836 return IsStore ? RISCV::SB_RL : RISCV::LB_AQ;
838 return IsStore ? RISCV::SH_RL : RISCV::LH_AQ;
840 return IsStore ? RISCV::SW_RL : RISCV::LW_AQ;
842 return IsStore ? RISCV::SD_RL : RISCV::LD_AQ;
851 unsigned GenericOpc,
unsigned OpSize) {
852 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
856 return IsStore ? RISCV::SB : RISCV::LBU;
858 return IsStore ? RISCV::SH : RISCV::LH;
860 return IsStore ? RISCV::SW : RISCV::LW;
864 if (!STI.
is64Bit() && STI.hasStdExtZilsd())
865 return IsStore ? RISCV::SD_RV32 : RISCV::LD_RV32;
866 return IsStore ? RISCV::SD : RISCV::LD;
872void RISCVInstructionSelector::addVectorLoadStoreOperands(
873 MachineInstr &
I, SmallVectorImpl<Register> &SrcOps,
unsigned &CurOp,
874 bool IsMasked,
bool IsStridedOrIndexed, LLT *IndexVT)
const {
876 auto PtrReg =
I.getOperand(CurOp++).getReg();
880 if (IsStridedOrIndexed) {
881 auto StrideReg =
I.getOperand(CurOp++).getReg();
884 *IndexVT = MRI->
getType(StrideReg);
889 auto MaskReg =
I.getOperand(CurOp++).getReg();
894bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
895 MachineInstr &
I)
const {
902 case Intrinsic::riscv_vlm:
903 case Intrinsic::riscv_vle:
904 case Intrinsic::riscv_vle_mask:
905 case Intrinsic::riscv_vlse:
906 case Intrinsic::riscv_vlse_mask: {
907 bool IsMasked = IntrinID == Intrinsic::riscv_vle_mask ||
908 IntrinID == Intrinsic::riscv_vlse_mask;
909 bool IsStrided = IntrinID == Intrinsic::riscv_vlse ||
910 IntrinID == Intrinsic::riscv_vlse_mask;
911 LLT VT = MRI->
getType(
I.getOperand(0).getReg());
915 const Register DstReg =
I.getOperand(0).getReg();
918 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
923 if (HasPassthruOperand) {
924 auto PassthruReg =
I.getOperand(CurOp++).getReg();
930 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked, IsStrided);
933 const RISCV::VLEPseudo *
P =
934 RISCV::getVLEPseudo(IsMasked, IsStrided,
false, Log2SEW,
935 static_cast<unsigned>(LMUL));
937 MachineInstrBuilder PseudoMI =
938 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(
P->Pseudo), DstReg);
943 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
944 for (
auto &RenderFn : *VLOpFn)
953 Policy =
I.getOperand(CurOp++).getImm();
963 case Intrinsic::riscv_vloxei:
964 case Intrinsic::riscv_vloxei_mask:
965 case Intrinsic::riscv_vluxei:
966 case Intrinsic::riscv_vluxei_mask: {
967 bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
968 IntrinID == Intrinsic::riscv_vluxei_mask;
969 bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
970 IntrinID == Intrinsic::riscv_vloxei_mask;
971 LLT VT = MRI->
getType(
I.getOperand(0).getReg());
975 const Register DstReg =
I.getOperand(0).getReg();
978 bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
983 if (HasPassthruOperand) {
984 auto PassthruReg =
I.getOperand(CurOp++).getReg();
991 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked,
true, &IndexVT);
997 if (IndexLog2EEW == 6 && !Subtarget->
is64Bit()) {
999 "values when XLEN=32");
1001 const RISCV::VLX_VSXPseudo *
P = RISCV::getVLXPseudo(
1002 IsMasked, IsOrdered, IndexLog2EEW,
static_cast<unsigned>(LMUL),
1003 static_cast<unsigned>(IndexLMUL));
1005 MachineInstrBuilder PseudoMI =
1006 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(
P->Pseudo), DstReg);
1011 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1012 for (
auto &RenderFn : *VLOpFn)
1016 PseudoMI.
addImm(Log2SEW);
1021 Policy =
I.getOperand(CurOp++).getImm();
1027 I.eraseFromParent();
1031 case Intrinsic::riscv_vsm:
1032 case Intrinsic::riscv_vse:
1033 case Intrinsic::riscv_vse_mask:
1034 case Intrinsic::riscv_vsse:
1035 case Intrinsic::riscv_vsse_mask: {
1036 bool IsMasked = IntrinID == Intrinsic::riscv_vse_mask ||
1037 IntrinID == Intrinsic::riscv_vsse_mask;
1038 bool IsStrided = IntrinID == Intrinsic::riscv_vsse ||
1039 IntrinID == Intrinsic::riscv_vsse_mask;
1040 LLT VT = MRI->
getType(
I.getOperand(1).getReg());
1048 auto PassthruReg =
I.getOperand(CurOp++).getReg();
1051 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked, IsStrided);
1054 const RISCV::VSEPseudo *
P = RISCV::getVSEPseudo(
1055 IsMasked, IsStrided, Log2SEW,
static_cast<unsigned>(LMUL));
1057 MachineInstrBuilder PseudoMI =
1063 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1064 for (
auto &RenderFn : *VLOpFn)
1068 PseudoMI.
addImm(Log2SEW);
1073 I.eraseFromParent();
1077 case Intrinsic::riscv_vsoxei:
1078 case Intrinsic::riscv_vsoxei_mask:
1079 case Intrinsic::riscv_vsuxei:
1080 case Intrinsic::riscv_vsuxei_mask: {
1081 bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
1082 IntrinID == Intrinsic::riscv_vsuxei_mask;
1083 bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
1084 IntrinID == Intrinsic::riscv_vsoxei_mask;
1085 LLT VT = MRI->
getType(
I.getOperand(1).getReg());
1093 auto PassthruReg =
I.getOperand(CurOp++).getReg();
1097 addVectorLoadStoreOperands(
I, SrcOps, CurOp, IsMasked,
true, &IndexVT);
1103 if (IndexLog2EEW == 6 && !Subtarget->
is64Bit()) {
1105 "values when XLEN=32");
1107 const RISCV::VLX_VSXPseudo *
P = RISCV::getVSXPseudo(
1108 IsMasked, IsOrdered, IndexLog2EEW,
static_cast<unsigned>(LMUL),
1109 static_cast<unsigned>(IndexLMUL));
1111 MachineInstrBuilder PseudoMI =
1117 auto VLOpFn = renderVLOp(
I.getOperand(CurOp++));
1118 for (
auto &RenderFn : *VLOpFn)
1122 PseudoMI.
addImm(Log2SEW);
1127 I.eraseFromParent();
1134bool RISCVInstructionSelector::selectIntrinsic(MachineInstr &
I)
const {
1141 case Intrinsic::riscv_vsetvli:
1142 case Intrinsic::riscv_vsetvlimax: {
1144 bool VLMax = IntrinID == Intrinsic::riscv_vsetvlimax;
1146 unsigned Offset = VLMax ? 2 : 3;
1154 Register DstReg =
I.getOperand(0).getReg();
1157 unsigned Opcode = RISCV::PseudoVSETVLI;
1161 Register AVLReg =
I.getOperand(2).getReg();
1163 uint64_t AVL = AVLConst->Value.getZExtValue();
1176 Opcode = RISCV::PseudoVSETVLIX0;
1178 Register AVLReg =
I.getOperand(2).getReg();
1183 uint64_t AVL = AVLConst->Value.getZExtValue();
1185 MachineInstr *PseudoMI =
1187 TII.get(RISCV::PseudoVSETIVLI), DstReg)
1190 I.eraseFromParent();
1197 MachineInstr *PseudoMI =
1198 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcode), DstReg)
1201 I.eraseFromParent();
1208bool RISCVInstructionSelector::selectExtractSubvector(MachineInstr &
MI)
const {
1209 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR);
1214 LLT DstTy = MRI->
getType(DstReg);
1215 LLT SrcTy = MRI->
getType(SrcReg);
1217 unsigned Idx =
static_cast<unsigned>(
MI.getOperand(2).
getImm());
1223 std::tie(SubRegIdx, Idx) =
1225 SrcMVT, DstMVT, Idx, &
TRI);
1240 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
TII.get(TargetOpcode::COPY),
1242 .
addReg(SrcReg, {}, SubRegIdx);
1244 MI.eraseFromParent();
1248bool RISCVInstructionSelector::selectInsertSubVector(MachineInstr &
MI)
const {
1249 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR);
1253 Register SubVecReg =
MI.getOperand(2).getReg();
1255 LLT VecTy = MRI->
getType(VecReg);
1256 LLT SubVecTy = MRI->
getType(SubVecReg);
1261 unsigned Idx =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
1264 std::tie(SubRegIdx, Idx) =
1266 VecMVT, SubVecMVT, Idx, &
TRI);
1282 if (SubRegIdx == RISCV::NoSubRegister) {
1285 "Unexpected subvector insert");
1286 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
TII.get(TargetOpcode::COPY),
1289 MI.eraseFromParent();
1295 MachineInstr *Ins =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1296 TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1301 MI.eraseFromParent();
1306bool RISCVInstructionSelector::select(MachineInstr &
MI) {
1308 const unsigned Opc =
MI.getOpcode();
1310 if (!
MI.isPreISelOpcode() ||
Opc == TargetOpcode::G_PHI) {
1311 if (
Opc == TargetOpcode::PHI ||
Opc == TargetOpcode::G_PHI) {
1312 const Register DefReg =
MI.getOperand(0).getReg();
1313 const LLT DefTy = MRI->
getType(DefReg);
1327 DefRC =
TRI.getRegClassForTypeOnBank(DefTy, RB, STI.
is64Bit());
1334 MI.setDesc(
TII.get(TargetOpcode::PHI));
1345 if (selectImpl(
MI, *CoverageInfo))
1349 case TargetOpcode::G_ANYEXT:
1350 case TargetOpcode::G_PTRTOINT:
1351 case TargetOpcode::G_INTTOPTR:
1352 case TargetOpcode::G_TRUNC:
1353 case TargetOpcode::G_FREEZE:
1355 case TargetOpcode::G_CONSTANT: {
1357 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
1359 if (!materializeImm(DstReg,
Imm,
MI))
1362 MI.eraseFromParent();
1365 case TargetOpcode::G_ZEXT:
1366 case TargetOpcode::G_SEXT: {
1367 bool IsSigned =
Opc != TargetOpcode::G_ZEXT;
1370 LLT SrcTy = MRI->
getType(SrcReg);
1377 RISCV::GPRBRegBankID &&
1378 "Unexpected ext regbank");
1381 if (IsSigned && SrcSize == 32) {
1382 MI.setDesc(
TII.get(RISCV::ADDIW));
1389 if (!IsSigned && SrcSize == 32 && STI.hasStdExtZba()) {
1390 MI.setDesc(
TII.get(RISCV::ADD_UW));
1397 if (SrcSize == 16 &&
1398 (STI.hasStdExtZbb() || (!IsSigned && STI.hasStdExtZbkb()))) {
1399 MI.setDesc(
TII.get(IsSigned ? RISCV::SEXT_H
1400 : STI.
is64Bit() ? RISCV::ZEXT_H_RV64
1401 : RISCV::ZEXT_H_RV32));
1408 MachineInstr *ShiftLeft =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1409 TII.get(RISCV::SLLI), ShiftLeftReg)
1413 MachineInstr *ShiftRight =
1415 TII.get(IsSigned ? RISCV::SRAI : RISCV::SRLI), DstReg)
1419 MI.eraseFromParent();
1422 case TargetOpcode::G_FCONSTANT: {
1425 const APFloat &FPimm =
MI.getOperand(1).getFPImm()->getValueAPF();
1434 if (!materializeImm(GPRReg,
Imm.getSExtValue(),
MI))
1438 unsigned Opcode =
Size == 64 ? RISCV::FMV_D_X
1439 :
Size == 32 ? RISCV::FMV_W_X
1441 MachineInstr *FMV =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1442 TII.get(Opcode), DstReg)
1448 "Unexpected size or subtarget");
1452 MachineInstr *FCVT =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1453 TII.get(RISCV::FCVT_D_W), DstReg)
1458 MI.eraseFromParent();
1466 if (!materializeImm(GPRRegHigh,
Imm.extractBits(32, 32).getSExtValue(),
1469 if (!materializeImm(GPRRegLow,
Imm.trunc(32).getSExtValue(),
MI))
1471 MachineInstr *PairF64 =
1473 TII.get(RISCV::BuildPairF64Pseudo), DstReg)
1479 MI.eraseFromParent();
1482 case TargetOpcode::G_GLOBAL_VALUE: {
1483 auto *GV =
MI.getOperand(1).getGlobal();
1484 if (GV->isThreadLocal()) {
1489 return selectAddr(
MI, GV->isDSOLocal(), GV->hasExternalWeakLinkage());
1491 case TargetOpcode::G_JUMP_TABLE:
1492 case TargetOpcode::G_CONSTANT_POOL:
1493 return selectAddr(
MI);
1494 case TargetOpcode::G_BRCOND: {
1499 MachineInstr *Bcc =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1503 .
addMBB(
MI.getOperand(1).getMBB());
1504 MI.eraseFromParent();
1508 case TargetOpcode::G_SELECT:
1509 return selectSelect(
MI);
1510 case TargetOpcode::G_FCMP:
1511 return selectFPCompare(
MI);
1512 case TargetOpcode::G_FENCE: {
1517 emitFence(FenceOrdering, FenceSSID,
MI);
1518 MI.eraseFromParent();
1521 case TargetOpcode::G_IMPLICIT_DEF:
1522 return selectImplicitDef(
MI);
1523 case TargetOpcode::G_UNMERGE_VALUES:
1525 case TargetOpcode::G_MERGE_VALUES:
1527 case TargetOpcode::G_LOAD:
1528 case TargetOpcode::G_STORE: {
1532 LLT PtrTy = MRI->
getType(PtrReg);
1534 const RegisterBank &RB = *RBI.
getRegBank(ValReg, *MRI,
TRI);
1535 if (RB.
getID() != RISCV::GPRBRegBankID)
1539 const RegisterBank &PtrRB = *RBI.
getRegBank(PtrReg, *MRI,
TRI);
1542 "Load/Store pointer operand isn't a GPR");
1543 assert(PtrTy.
isPointer() &&
"Load/Store pointer operand isn't a pointer");
1559 const unsigned NewOpc =
1561 if (NewOpc ==
MI.getOpcode())
1565 auto AddrModeFns = selectAddrRegImm(
MI.getOperand(1));
1570 MachineInstrBuilder NewInst =
1578 for (
auto &Fn : *AddrModeFns)
1580 MI.eraseFromParent();
1585 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
1586 return selectIntrinsicWithSideEffects(
MI);
1587 case TargetOpcode::G_INTRINSIC:
1588 return selectIntrinsic(
MI);
1589 case TargetOpcode::G_EXTRACT_SUBVECTOR:
1590 return selectExtractSubvector(
MI);
1591 case TargetOpcode::G_INSERT_SUBVECTOR:
1592 return selectInsertSubVector(
MI);
1598bool RISCVInstructionSelector::selectUnmergeValues(MachineInstr &
MI)
const {
1599 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
1602 if (
MI.getNumOperands() != 3)
1609 if (!Subtarget->
is64Bit() && Subtarget->hasStdExtZilsd() &&
1611 isRegInGprb(
Lo) && isRegInGprb(
Hi)) {
1623 auto ExtractHalf = [&](
Register Dst,
unsigned SubIdx) {
1625 MachineInstr &
C = *
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1626 TII.get(TargetOpcode::COPY), Dst)
1627 .
addReg(Src, {}, SubIdx);
1630 ExtractHalf(
Lo, RISCV::sub_gpr_even);
1631 ExtractHalf(
Hi, RISCV::sub_gpr_odd);
1632 MI.eraseFromParent();
1636 if (!Subtarget->hasStdExtZfa())
1639 if (!isRegInFprb(Src) || !isRegInGprb(
Lo) || !isRegInGprb(
Hi))
1642 MachineInstr *ExtractLo =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1643 TII.get(RISCV::FMV_X_W_FPR64),
Lo)
1647 MachineInstr *ExtractHi =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1648 TII.get(RISCV::FMVH_X_D),
Hi)
1652 MI.eraseFromParent();
1656bool RISCVInstructionSelector::selectMergeValues(MachineInstr &
MI)
const {
1657 assert(
MI.getOpcode() == TargetOpcode::G_MERGE_VALUES);
1659 if (
MI.getNumOperands() != 3)
1666 if (!Subtarget->
is64Bit() && Subtarget->hasStdExtZilsd() &&
1668 isRegInGprb(
Lo) && isRegInGprb(
Hi)) {
1674 MachineInstr &Seq = *
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1675 TII.get(TargetOpcode::REG_SEQUENCE), Dst)
1677 .
addImm(RISCV::sub_gpr_even)
1679 .
addImm(RISCV::sub_gpr_odd);
1680 MI.eraseFromParent();
1687bool RISCVInstructionSelector::replacePtrWithInt(MachineInstr &
MI,
1689 MachineOperand &
Op =
MI.getOperand(OpIdx);
1696 MachineInstr *PtrToInt =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
1697 TII.get(TargetOpcode::G_PTRTOINT), IntReg)
1700 return select(*PtrToInt);
1703void RISCVInstructionSelector::preISelLower(MachineInstr &
MI) {
1704 switch (
MI.getOpcode()) {
1705 case TargetOpcode::G_PTR_ADD: {
1709 replacePtrWithInt(
MI, 1);
1710 MI.setDesc(
TII.get(TargetOpcode::G_ADD));
1714 case TargetOpcode::G_PTRMASK: {
1717 replacePtrWithInt(
MI, 1);
1718 MI.setDesc(
TII.get(TargetOpcode::G_AND));
1725void RISCVInstructionSelector::renderNegImm(MachineInstrBuilder &MIB,
1726 const MachineInstr &
MI,
1728 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1729 "Expected G_CONSTANT");
1730 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1734void RISCVInstructionSelector::renderImmSubFromXLen(MachineInstrBuilder &MIB,
1735 const MachineInstr &
MI,
1737 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1738 "Expected G_CONSTANT");
1739 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1743void RISCVInstructionSelector::renderImmSubFrom32(MachineInstrBuilder &MIB,
1744 const MachineInstr &
MI,
1746 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1747 "Expected G_CONSTANT");
1748 uint64_t CstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1752void RISCVInstructionSelector::renderImmPlus1(MachineInstrBuilder &MIB,
1753 const MachineInstr &
MI,
1755 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1756 "Expected G_CONSTANT");
1757 int64_t CstVal =
MI.getOperand(1).getCImm()->getSExtValue();
1761void RISCVInstructionSelector::renderTrailingZeros(MachineInstrBuilder &MIB,
1762 const MachineInstr &
MI,
1764 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1765 "Expected G_CONSTANT");
1766 uint64_t C =
MI.getOperand(1).getCImm()->getZExtValue();
1770void RISCVInstructionSelector::renderXLenSubTrailingOnes(
1771 MachineInstrBuilder &MIB,
const MachineInstr &
MI,
int OpIdx)
const {
1772 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1773 "Expected G_CONSTANT");
1774 uint64_t C =
MI.getOperand(1).getCImm()->getZExtValue();
1778void RISCVInstructionSelector::renderAddiPairImmSmall(MachineInstrBuilder &MIB,
1779 const MachineInstr &
MI,
1781 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1782 "Expected G_CONSTANT");
1783 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue();
1784 int64_t Adj =
Imm < 0 ? -2048 : 2047;
1788void RISCVInstructionSelector::renderAddiPairImmLarge(MachineInstrBuilder &MIB,
1789 const MachineInstr &
MI,
1791 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
1792 "Expected G_CONSTANT");
1793 int64_t
Imm =
MI.getOperand(1).getCImm()->getSExtValue() < 0 ? -2048 : 2047;
1797bool RISCVInstructionSelector::isRegInGprb(
Register Reg)
const {
1801bool RISCVInstructionSelector::isRegInFprb(
Register Reg)
const {
1809bool RISCVInstructionSelector::isWorthFoldingAdd(
Register AddResult)
const {
1820 LLT Ty = MRI->
getType(
User.getOperand(0).getReg());
1827bool RISCVInstructionSelector::selectCopy(MachineInstr &
MI)
const {
1834 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
1837 "Register class not available for LLT, register bank combination");
1848 MI.setDesc(
TII.get(RISCV::COPY));
1852bool RISCVInstructionSelector::selectImplicitDef(MachineInstr &
MI)
const {
1853 assert(
MI.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
1855 const Register DstReg =
MI.getOperand(0).getReg();
1860 "Register class not available for LLT, register bank combination");
1866 MI.setDesc(
TII.get(TargetOpcode::IMPLICIT_DEF));
1870bool RISCVInstructionSelector::materializeImm(
Register DstReg, int64_t
Imm,
1871 MachineInstr &
MI)
const {
1881 return materializeInstSeq(DstReg, Seq,
MI);
1884bool RISCVInstructionSelector::materializeInstSeq(
1886 assert(!Seq.
empty() &&
"materializeInstSeq requires a non-empty sequence");
1890 unsigned NumInsts = Seq.
size();
1893 for (
unsigned i = 0; i < NumInsts; i++) {
1897 const RISCVMatInt::Inst &
I = Seq[i];
1900 switch (
I.getOpndKind()) {
1930InstructionSelector::ComplexRendererFns
1931RISCVInstructionSelector::computeConstAddr(int64_t CVal,
bool IsPrefetch,
1938 auto emit = [&](ConstAddrPlan Plan) -> ComplexRendererFns {
1939 return {{[=](MachineInstrBuilder &MIB) {
1940 MIB.
addReg(materializeConstBase(MIB, Plan, OrigBase));
1942 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Plan.Lo12); }}};
1945 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1946 return std::nullopt;
1950 Plan.Kind = ConstAddrPlan::LUI;
1951 Plan.Hi20 = (
Hi >> 12) & 0xfffff;
1953 return emit(std::move(Plan));
1959 if (Seq.
back().getOpcode() != RISCV::ADDI)
1960 return std::nullopt;
1961 Lo12 = Seq.
back().getImm();
1962 if (IsPrefetch && (Lo12 & 0b11111) != 0)
1963 return std::nullopt;
1966 return std::nullopt;
1968 Plan.Kind = ConstAddrPlan::InstSeq;
1969 Plan.Seq = std::move(Seq);
1971 return emit(std::move(Plan));
1975RISCVInstructionSelector::materializeConstBase(MachineInstrBuilder &MIB,
1976 const ConstAddrPlan &Plan,
1980 MachineInstr &InsertPt = *MIB.
getInstr();
1983 switch (Plan.Kind) {
1984 case ConstAddrPlan::X0:
1986 case ConstAddrPlan::LUI: {
1988 MachineInstr *LUI =
BuildMI(
MBB, InsertPt,
DL,
TII.get(RISCV::LUI), HiReg)
1993 case ConstAddrPlan::InstSeq: {
1995 materializeInstSeq(HiReg, Plan.Seq, InsertPt);
2002 if (OrigBase.
isValid() && HiReg != RISCV::X0) {
2010 return OrigBase.
isValid() ? OrigBase : HiReg;
2013bool RISCVInstructionSelector::selectAddr(MachineInstr &
MI,
bool IsLocal,
2014 bool IsExternWeak)
const {
2015 assert((
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
2016 MI.getOpcode() == TargetOpcode::G_JUMP_TABLE ||
2017 MI.getOpcode() == TargetOpcode::G_CONSTANT_POOL) &&
2018 "Unexpected opcode");
2020 const MachineOperand &DispMO =
MI.getOperand(1);
2023 const LLT DefTy = MRI->
getType(DefReg);
2030 if (IsLocal && !Subtarget->allowTaggedGlobals()) {
2034 MI.setDesc(
TII.get(RISCV::PseudoLLA));
2051 TII.get(RISCV::PseudoLGA), DefReg)
2057 MI.eraseFromParent();
2064 "Unsupported code model for lowering",
MI);
2072 MachineInstr *AddrHi =
BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(),
2073 TII.get(RISCV::LUI), AddrHiDest)
2079 TII.get(RISCV::ADDI), DefReg)
2085 MI.eraseFromParent();
2106 TII.get(RISCV::PseudoLGA), DefReg)
2112 MI.eraseFromParent();
2119 MI.setDesc(
TII.get(RISCV::PseudoLLA));
2127bool RISCVInstructionSelector::selectSelect(MachineInstr &
MI)
const {
2134 Register DstReg = SelectMI.getReg(0);
2136 unsigned Opc = RISCV::Select_GPR_Using_CC_GPR;
2139 Opc =
Size == 32 ? RISCV::Select_FPR32_Using_CC_GPR
2140 : RISCV::Select_FPR64_Using_CC_GPR;
2149 .
addReg(SelectMI.getTrueReg())
2150 .
addReg(SelectMI.getFalseReg());
2151 MI.eraseFromParent();
2163 return Size == 16 ? RISCV::FLT_H :
Size == 32 ? RISCV::FLT_S : RISCV::FLT_D;
2165 return Size == 16 ? RISCV::FLE_H :
Size == 32 ? RISCV::FLE_S : RISCV::FLE_D;
2167 return Size == 16 ? RISCV::FEQ_H :
Size == 32 ? RISCV::FEQ_S : RISCV::FEQ_D;
2180 assert(!isLegalFCmpPredicate(Pred) &&
"Predicate already legal?");
2183 if (isLegalFCmpPredicate(InvPred)) {
2191 if (isLegalFCmpPredicate(InvPred)) {
2196 if (isLegalFCmpPredicate(InvPred)) {
2208bool RISCVInstructionSelector::selectFPCompare(MachineInstr &
MI)
const {
2221 bool NeedInvert =
false;
2236 MachineInstr *Cmp1 =
2244 MachineInstr *Cmp2 =
2254 TII.get(RISCV::OR), TmpReg)
2274 MachineInstr *Cmp1 =
2282 MachineInstr *Cmp2 =
2290 TII.get(RISCV::AND), TmpReg)
2301 TII.get(RISCV::XORI), DstReg)
2307 MI.eraseFromParent();
2311void RISCVInstructionSelector::emitFence(
AtomicOrdering FenceOrdering,
2313 MachineInstr &
MI)
const {
2317 if (STI.hasStdExtZtso()) {
2320 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
2344 unsigned Pred, Succ;
2345 switch (FenceOrdering) {
2348 case AtomicOrdering::AcquireRelease:
2352 case AtomicOrdering::Acquire:
2357 case AtomicOrdering::Release:
2362 case AtomicOrdering::SequentiallyConsistent:
2372InstructionSelector *
2376 return new RISCVInstructionSelector(TM, Subtarget, RBI);
#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)
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.
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.
std::optional< unsigned > getRealVLen() const
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)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
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)
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.