41#define GEN_CHECK_COMPRESS_INSTR
42#include "RISCVGenCompressInstEmitter.inc"
44#define GET_INSTRINFO_CTOR_DTOR
45#include "RISCVGenInstrInfo.inc"
47#define DEBUG_TYPE "riscv-instr-info"
49 "Number of registers within vector register groups spilled");
51 "Number of registers within vector register groups reloaded");
55 cl::desc(
"Prefer whole register move for vector registers."));
58 "riscv-force-machine-combiner-strategy",
cl::Hidden,
59 cl::desc(
"Force machine combiner to use a specific strategy for machine "
60 "trace metrics evaluation."),
65 "MinInstrCount strategy.")));
69 cl::desc(
"Enable RegSave strategy in machine outliner (save X5 to a "
70 "temporary register when X5 is live across outlined calls)."));
76#define GET_RISCVVPseudosTable_IMPL
77#include "RISCVGenSearchableTables.inc"
83#define GET_RISCVMaskedPseudosTable_IMPL
84#include "RISCVGenSearchableTables.inc"
90 RISCV::ADJCALLSTACKUP),
93#define GET_INSTRINFO_HELPERS
94#include "RISCVGenInstrInfo.inc"
97 if (
STI.hasStdExtZca())
106 int &FrameIndex)
const {
116 case RISCV::VL1RE8_V:
117 case RISCV::VL1RE16_V:
118 case RISCV::VL1RE32_V:
119 case RISCV::VL1RE64_V:
122 case RISCV::VL2RE8_V:
123 case RISCV::VL2RE16_V:
124 case RISCV::VL2RE32_V:
125 case RISCV::VL2RE64_V:
128 case RISCV::VL4RE8_V:
129 case RISCV::VL4RE16_V:
130 case RISCV::VL4RE32_V:
131 case RISCV::VL4RE64_V:
134 case RISCV::VL8RE8_V:
135 case RISCV::VL8RE16_V:
136 case RISCV::VL8RE32_V:
137 case RISCV::VL8RE64_V:
145 switch (
MI.getOpcode()) {
169 case RISCV::VL1RE8_V:
170 case RISCV::VL2RE8_V:
171 case RISCV::VL4RE8_V:
172 case RISCV::VL8RE8_V:
173 if (!
MI.getOperand(1).isFI())
175 FrameIndex =
MI.getOperand(1).getIndex();
178 return MI.getOperand(0).getReg();
181 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
182 MI.getOperand(2).getImm() == 0) {
183 FrameIndex =
MI.getOperand(1).getIndex();
184 return MI.getOperand(0).getReg();
191 int &FrameIndex)
const {
199 switch (
MI.getOpcode()) {
224 if (!
MI.getOperand(1).isFI())
226 FrameIndex =
MI.getOperand(1).getIndex();
229 return MI.getOperand(0).getReg();
232 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
233 MI.getOperand(2).getImm() == 0) {
234 FrameIndex =
MI.getOperand(1).getIndex();
235 return MI.getOperand(0).getReg();
245 case RISCV::VFMV_V_F:
248 case RISCV::VFMV_S_F:
250 return MI.getOperand(1).isUndef();
258 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
269 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
270 "Unexpected COPY instruction.");
274 bool FoundDef =
false;
275 bool FirstVSetVLI =
false;
276 unsigned FirstSEW = 0;
279 if (
MBBI->isMetaInstruction())
282 if (RISCVInstrInfo::isVectorConfigInstr(*
MBBI)) {
292 unsigned FirstVType =
MBBI->getOperand(2).getImm();
297 if (FirstLMul != LMul)
302 if (!RISCVInstrInfo::isVLPreservingConfig(*
MBBI))
308 unsigned VType =
MBBI->getOperand(2).getImm();
326 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
328 }
else if (
MBBI->getNumDefs()) {
331 if (
MBBI->modifiesRegister(RISCV::VL,
nullptr))
337 if (!MO.isReg() || !MO.isDef())
339 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
354 if (MO.getReg() != SrcReg)
395 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
396 uint16_t DstEncoding =
TRI->getEncodingValue(DstReg);
398 assert(!Fractional &&
"It is impossible be fractional lmul here.");
399 unsigned NumRegs = NF * LMulVal;
405 SrcEncoding += NumRegs - 1;
406 DstEncoding += NumRegs - 1;
412 unsigned,
unsigned> {
420 uint16_t Diff = DstEncoding - SrcEncoding;
421 if (
I + 8 <= NumRegs && Diff >= 8 && SrcEncoding % 8 == 7 &&
422 DstEncoding % 8 == 7)
424 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
425 if (
I + 4 <= NumRegs && Diff >= 4 && SrcEncoding % 4 == 3 &&
426 DstEncoding % 4 == 3)
428 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
429 if (
I + 2 <= NumRegs && Diff >= 2 && SrcEncoding % 2 == 1 &&
430 DstEncoding % 2 == 1)
432 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
435 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
440 if (
I + 8 <= NumRegs && SrcEncoding % 8 == 0 && DstEncoding % 8 == 0)
442 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
443 if (
I + 4 <= NumRegs && SrcEncoding % 4 == 0 && DstEncoding % 4 == 0)
445 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
446 if (
I + 2 <= NumRegs && SrcEncoding % 2 == 0 && DstEncoding % 2 == 0)
448 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
451 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
454 while (
I != NumRegs) {
459 auto [LMulCopied, RegClass,
Opc, VVOpc, VIOpc] =
460 GetCopyInfo(SrcEncoding, DstEncoding);
464 if (LMul == LMulCopied &&
467 if (DefMBBI->getOpcode() == VIOpc)
474 RegClass, ReversedCopy ? (SrcEncoding - NumCopied + 1) : SrcEncoding);
476 RegClass, ReversedCopy ? (DstEncoding - NumCopied + 1) : DstEncoding);
484 MIB = MIB.add(DefMBBI->getOperand(2));
492 MIB.addImm(Log2SEW ? Log2SEW : 3);
504 SrcEncoding += (ReversedCopy ? -NumCopied : NumCopied);
505 DstEncoding += (ReversedCopy ? -NumCopied : NumCopied);
514 bool RenamableDest,
bool RenamableSrc)
const {
518 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
526 if (SrcReg == RISCV::DUMMY_REG_PAIR_WITH_X0 &&
527 RISCV::GPRRegClass.
contains(DstReg)) {
534 if (RISCV::GPRF16RegClass.
contains(DstReg, SrcReg)) {
540 if (RISCV::GPRF32RegClass.
contains(DstReg, SrcReg)) {
546 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
548 if (
STI.hasStdExtZdinx()) {
557 if (
STI.hasStdExtP()) {
566 MCRegister EvenReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even);
567 MCRegister OddReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd);
569 if (OddReg == RISCV::DUMMY_REG_PAIR_WITH_X0)
571 assert(DstReg != RISCV::X0_Pair &&
"Cannot write to X0_Pair");
575 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
576 .
addReg(EvenReg, KillFlag)
579 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
586 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
587 RISCV::GPRRegClass.
contains(DstReg)) {
589 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
594 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
596 if (
STI.hasStdExtZfh()) {
597 Opc = RISCV::FSGNJ_H;
600 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
601 "Unexpected extensions");
603 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
604 &RISCV::FPR32RegClass);
605 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
606 &RISCV::FPR32RegClass);
607 Opc = RISCV::FSGNJ_S;
611 .
addReg(SrcReg, KillFlag);
615 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
618 .
addReg(SrcReg, KillFlag);
622 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
625 .
addReg(SrcReg, KillFlag);
629 if (RISCV::FPR32RegClass.
contains(DstReg) &&
630 RISCV::GPRRegClass.
contains(SrcReg)) {
632 .
addReg(SrcReg, KillFlag);
636 if (RISCV::GPRRegClass.
contains(DstReg) &&
637 RISCV::FPR32RegClass.
contains(SrcReg)) {
639 .
addReg(SrcReg, KillFlag);
643 if (RISCV::FPR64RegClass.
contains(DstReg) &&
644 RISCV::GPRRegClass.
contains(SrcReg)) {
645 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
647 .
addReg(SrcReg, KillFlag);
651 if (RISCV::GPRRegClass.
contains(DstReg) &&
652 RISCV::FPR64RegClass.
contains(SrcReg)) {
653 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
655 .
addReg(SrcReg, KillFlag);
661 TRI->getCommonMinimalPhysRegClass(SrcReg, DstReg);
672 Register SrcReg,
bool IsKill,
int FI,
681 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
682 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::SW
684 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
685 Opcode = RISCV::SH_INX;
686 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
687 Opcode = RISCV::SW_INX;
688 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
689 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
690 Alignment >=
STI.getZilsdAlign()) {
691 Opcode = RISCV::SD_RV32;
693 Opcode = RISCV::PseudoRV32ZdinxSD;
695 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
697 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
699 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
701 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
702 Opcode = RISCV::VS1R_V;
703 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
704 Opcode = RISCV::VS2R_V;
705 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
706 Opcode = RISCV::VS4R_V;
707 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
708 Opcode = RISCV::VS8R_V;
709 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
710 Opcode = RISCV::PseudoVSPILL2_M1;
711 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
712 Opcode = RISCV::PseudoVSPILL2_M2;
713 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
714 Opcode = RISCV::PseudoVSPILL2_M4;
715 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
716 Opcode = RISCV::PseudoVSPILL3_M1;
717 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
718 Opcode = RISCV::PseudoVSPILL3_M2;
719 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
720 Opcode = RISCV::PseudoVSPILL4_M1;
721 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
722 Opcode = RISCV::PseudoVSPILL4_M2;
723 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
724 Opcode = RISCV::PseudoVSPILL5_M1;
725 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
726 Opcode = RISCV::PseudoVSPILL6_M1;
727 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
728 Opcode = RISCV::PseudoVSPILL7_M1;
729 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
730 Opcode = RISCV::PseudoVSPILL8_M1;
773 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
774 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::LW
776 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
777 Opcode = RISCV::LH_INX;
778 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
779 Opcode = RISCV::LW_INX;
780 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
781 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
782 Alignment >=
STI.getZilsdAlign()) {
783 Opcode = RISCV::LD_RV32;
785 Opcode = RISCV::PseudoRV32ZdinxLD;
787 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
789 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
791 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
793 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
794 Opcode = RISCV::VL1RE8_V;
795 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
796 Opcode = RISCV::VL2RE8_V;
797 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
798 Opcode = RISCV::VL4RE8_V;
799 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
800 Opcode = RISCV::VL8RE8_V;
801 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
802 Opcode = RISCV::PseudoVRELOAD2_M1;
803 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
804 Opcode = RISCV::PseudoVRELOAD2_M2;
805 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
806 Opcode = RISCV::PseudoVRELOAD2_M4;
807 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
808 Opcode = RISCV::PseudoVRELOAD3_M1;
809 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
810 Opcode = RISCV::PseudoVRELOAD3_M2;
811 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
812 Opcode = RISCV::PseudoVRELOAD4_M1;
813 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
814 Opcode = RISCV::PseudoVRELOAD4_M2;
815 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
816 Opcode = RISCV::PseudoVRELOAD5_M1;
817 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
818 Opcode = RISCV::PseudoVRELOAD6_M1;
819 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
820 Opcode = RISCV::PseudoVRELOAD7_M1;
821 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
822 Opcode = RISCV::PseudoVRELOAD8_M1;
860 if (
Ops.size() != 1 ||
Ops[0] != 1)
863 switch (
MI.getOpcode()) {
865 if (RISCVInstrInfo::isSEXT_W(
MI))
867 if (RISCVInstrInfo::isZEXT_W(
MI))
869 if (RISCVInstrInfo::isZEXT_B(
MI))
876 case RISCV::ZEXT_H_RV32:
877 case RISCV::ZEXT_H_RV64:
884 case RISCV::VMV_X_S: {
887 if (ST.getXLen() < (1U << Log2SEW))
902 case RISCV::VFMV_F_S: {
930 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(*LoadOpc),
939 return RISCV::PseudoCCLB;
941 return RISCV::PseudoCCLBU;
943 return RISCV::PseudoCCLH;
945 return RISCV::PseudoCCLHU;
947 return RISCV::PseudoCCLW;
949 return RISCV::PseudoCCLWU;
951 return RISCV::PseudoCCLD;
953 return RISCV::PseudoCCQC_E_LB;
954 case RISCV::QC_E_LBU:
955 return RISCV::PseudoCCQC_E_LBU;
957 return RISCV::PseudoCCQC_E_LH;
958 case RISCV::QC_E_LHU:
959 return RISCV::PseudoCCQC_E_LHU;
961 return RISCV::PseudoCCQC_E_LW;
973 if (
MI.getOpcode() != RISCV::PseudoCCMOVGPR)
978 if (!
STI.hasShortForwardBranchILoad() || !PredOpc)
982 if (
Ops.size() != 1 || (
Ops[0] != 1 &&
Ops[0] != 2))
985 bool Invert =
Ops[0] == 2;
994 MI.getDebugLoc(),
get(PredOpc), DestReg);
1005 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
1011 NewMI.
add({
MI.getOperand(
MI.getNumExplicitOperands() - 2),
1012 MI.getOperand(
MI.getNumExplicitOperands() - 1)});
1021 bool DstIsDead)
const {
1037 bool SrcRenamable =
false;
1041 bool LastItem = ++Num == Seq.
size();
1046 switch (Inst.getOpndKind()) {
1056 .
addReg(SrcReg, SrcRegState)
1063 .
addReg(SrcReg, SrcRegState)
1064 .
addReg(SrcReg, SrcRegState)
1070 .
addReg(SrcReg, SrcRegState)
1078 SrcRenamable = DstRenamable;
1088 case RISCV::CV_BEQIMM:
1089 case RISCV::QC_BEQI:
1090 case RISCV::QC_E_BEQI:
1091 case RISCV::NDS_BBC:
1092 case RISCV::NDS_BEQC:
1096 case RISCV::QC_BNEI:
1097 case RISCV::QC_E_BNEI:
1098 case RISCV::CV_BNEIMM:
1099 case RISCV::NDS_BBS:
1100 case RISCV::NDS_BNEC:
1103 case RISCV::QC_BLTI:
1104 case RISCV::QC_E_BLTI:
1107 case RISCV::QC_BGEI:
1108 case RISCV::QC_E_BGEI:
1111 case RISCV::QC_BLTUI:
1112 case RISCV::QC_E_BLTUI:
1115 case RISCV::QC_BGEUI:
1116 case RISCV::QC_E_BGEUI:
1148 "Unknown conditional branch");
1159 case RISCV::QC_MVEQ:
1160 return RISCV::QC_MVNE;
1161 case RISCV::QC_MVNE:
1162 return RISCV::QC_MVEQ;
1163 case RISCV::QC_MVLT:
1164 return RISCV::QC_MVGE;
1165 case RISCV::QC_MVGE:
1166 return RISCV::QC_MVLT;
1167 case RISCV::QC_MVLTU:
1168 return RISCV::QC_MVGEU;
1169 case RISCV::QC_MVGEU:
1170 return RISCV::QC_MVLTU;
1171 case RISCV::QC_MVEQI:
1172 return RISCV::QC_MVNEI;
1173 case RISCV::QC_MVNEI:
1174 return RISCV::QC_MVEQI;
1175 case RISCV::QC_MVLTI:
1176 return RISCV::QC_MVGEI;
1177 case RISCV::QC_MVGEI:
1178 return RISCV::QC_MVLTI;
1179 case RISCV::QC_MVLTUI:
1180 return RISCV::QC_MVGEUI;
1181 case RISCV::QC_MVGEUI:
1182 return RISCV::QC_MVLTUI;
1187 switch (SelectOpc) {
1206 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
1216 case RISCV::Select_GPR_Using_CC_SImm5_CV:
1221 return RISCV::CV_BEQIMM;
1223 return RISCV::CV_BNEIMM;
1226 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
1231 return RISCV::QC_BEQI;
1233 return RISCV::QC_BNEI;
1235 return RISCV::QC_BLTI;
1237 return RISCV::QC_BGEI;
1240 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
1245 return RISCV::QC_BLTUI;
1247 return RISCV::QC_BGEUI;
1250 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
1255 return RISCV::QC_E_BEQI;
1257 return RISCV::QC_E_BNEI;
1259 return RISCV::QC_E_BLTI;
1261 return RISCV::QC_E_BGEI;
1264 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
1269 return RISCV::QC_E_BLTUI;
1271 return RISCV::QC_E_BGEUI;
1274 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
1279 return RISCV::NDS_BBC;
1281 return RISCV::NDS_BBS;
1284 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
1289 return RISCV::NDS_BEQC;
1291 return RISCV::NDS_BNEC;
1337 case RISCV::CV_BEQIMM:
1338 return RISCV::CV_BNEIMM;
1339 case RISCV::CV_BNEIMM:
1340 return RISCV::CV_BEQIMM;
1341 case RISCV::QC_BEQI:
1342 return RISCV::QC_BNEI;
1343 case RISCV::QC_BNEI:
1344 return RISCV::QC_BEQI;
1345 case RISCV::QC_BLTI:
1346 return RISCV::QC_BGEI;
1347 case RISCV::QC_BGEI:
1348 return RISCV::QC_BLTI;
1349 case RISCV::QC_BLTUI:
1350 return RISCV::QC_BGEUI;
1351 case RISCV::QC_BGEUI:
1352 return RISCV::QC_BLTUI;
1353 case RISCV::QC_E_BEQI:
1354 return RISCV::QC_E_BNEI;
1355 case RISCV::QC_E_BNEI:
1356 return RISCV::QC_E_BEQI;
1357 case RISCV::QC_E_BLTI:
1358 return RISCV::QC_E_BGEI;
1359 case RISCV::QC_E_BGEI:
1360 return RISCV::QC_E_BLTI;
1361 case RISCV::QC_E_BLTUI:
1362 return RISCV::QC_E_BGEUI;
1363 case RISCV::QC_E_BGEUI:
1364 return RISCV::QC_E_BLTUI;
1365 case RISCV::NDS_BBC:
1366 return RISCV::NDS_BBS;
1367 case RISCV::NDS_BBS:
1368 return RISCV::NDS_BBC;
1369 case RISCV::NDS_BEQC:
1370 return RISCV::NDS_BNEC;
1371 case RISCV::NDS_BNEC:
1372 return RISCV::NDS_BEQC;
1380 bool AllowModify)
const {
1381 TBB = FBB =
nullptr;
1386 if (
I ==
MBB.end() || !isUnpredicatedTerminator(*
I))
1392 int NumTerminators = 0;
1393 for (
auto J =
I.getReverse(); J !=
MBB.rend() && isUnpredicatedTerminator(*J);
1396 if (J->getDesc().isUnconditionalBranch() ||
1397 J->getDesc().isIndirectBranch()) {
1404 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.end()) {
1405 while (std::next(FirstUncondOrIndirectBr) !=
MBB.end()) {
1406 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
1409 I = FirstUncondOrIndirectBr;
1413 if (
I->getDesc().isIndirectBranch())
1417 if (
I->isPreISelOpcode())
1421 if (NumTerminators > 2)
1425 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
1431 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
1437 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
1438 I->getDesc().isUnconditionalBranch()) {
1449 int *BytesRemoved)
const {
1456 if (!
I->getDesc().isUnconditionalBranch() &&
1457 !
I->getDesc().isConditionalBranch())
1463 I->eraseFromParent();
1467 if (
I ==
MBB.begin())
1470 if (!
I->getDesc().isConditionalBranch())
1476 I->eraseFromParent();
1489 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1491 "RISC-V branch conditions have two components!");
1525 assert(RS &&
"RegScavenger required for long branching");
1527 "new block should be inserted for expanding unconditional branch");
1530 "restore block should be inserted for restoring clobbered registers");
1539 "Branch offsets outside of the signed 32-bit range not supported");
1545 auto II =
MBB.end();
1551 RS->enterBasicBlockEnd(
MBB);
1558 RC = &RISCV::GPRX7RegClass;
1560 RS->scavengeRegisterBackwards(*RC,
MI.getIterator(),
1564 RS->setRegUsed(TmpGPR);
1569 TmpGPR =
STI.hasStdExtE() ? RISCV::X9 : RISCV::X27;
1575 if (FrameIndex == -1)
1580 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1583 MI.getOperand(1).setMBB(&RestoreBB);
1587 TRI->eliminateFrameIndex(RestoreBB.
back(),
1597 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1607 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1608 MI->getOperand(1).getReg() == RISCV::X0) {
1609 Imm =
MI->getOperand(2).getImm();
1614 if (
MI->getOpcode() == RISCV::BSETI &&
MI->getOperand(1).isReg() &&
1615 MI->getOperand(1).getReg() == RISCV::X0 &&
1616 MI->getOperand(2).getImm() == 11) {
1630 if (Reg == RISCV::X0) {
1638 bool IsSigned =
false;
1639 bool IsEquality =
false;
1640 switch (
MI.getOpcode()) {
1676 MI.eraseFromParent();
1702 auto searchConst = [&](int64_t C1) ->
Register {
1704 auto DefC1 = std::find_if(++
II, E, [&](
const MachineInstr &
I) ->
bool {
1707 I.getOperand(0).getReg().isVirtual();
1710 return DefC1->getOperand(0).getReg();
1722 if (
isFromLoadImm(MRI, LHS, C0) && C0 != 0 && LHS.getReg().isVirtual() &&
1723 MRI.
hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
1725 if (
Register RegZ = searchConst(C0 + 1)) {
1733 MI.eraseFromParent();
1743 if (
isFromLoadImm(MRI, RHS, C0) && C0 != 0 && RHS.getReg().isVirtual() &&
1746 if (
Register RegZ = searchConst(C0 - 1)) {
1754 MI.eraseFromParent();
1764 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1766 int NumOp =
MI.getNumExplicitOperands();
1767 return MI.getOperand(NumOp - 1).getMBB();
1771 int64_t BrOffset)
const {
1772 unsigned XLen =
STI.getXLen();
1779 case RISCV::NDS_BBC:
1780 case RISCV::NDS_BBS:
1781 case RISCV::NDS_BEQC:
1782 case RISCV::NDS_BNEC:
1792 case RISCV::CV_BEQIMM:
1793 case RISCV::CV_BNEIMM:
1794 case RISCV::QC_BEQI:
1795 case RISCV::QC_BNEI:
1796 case RISCV::QC_BGEI:
1797 case RISCV::QC_BLTI:
1798 case RISCV::QC_BLTUI:
1799 case RISCV::QC_BGEUI:
1800 case RISCV::QC_E_BEQI:
1801 case RISCV::QC_E_BNEI:
1802 case RISCV::QC_E_BGEI:
1803 case RISCV::QC_E_BLTI:
1804 case RISCV::QC_E_BLTUI:
1805 case RISCV::QC_E_BGEUI:
1808 case RISCV::PseudoBR:
1810 case RISCV::PseudoJump:
1821 case RISCV::ADD:
return RISCV::PseudoCCADD;
1822 case RISCV::SUB:
return RISCV::PseudoCCSUB;
1823 case RISCV::SLL:
return RISCV::PseudoCCSLL;
1824 case RISCV::SRL:
return RISCV::PseudoCCSRL;
1825 case RISCV::SRA:
return RISCV::PseudoCCSRA;
1826 case RISCV::AND:
return RISCV::PseudoCCAND;
1827 case RISCV::OR:
return RISCV::PseudoCCOR;
1828 case RISCV::XOR:
return RISCV::PseudoCCXOR;
1829 case RISCV::MAX:
return RISCV::PseudoCCMAX;
1830 case RISCV::MAXU:
return RISCV::PseudoCCMAXU;
1831 case RISCV::MIN:
return RISCV::PseudoCCMIN;
1832 case RISCV::MINU:
return RISCV::PseudoCCMINU;
1833 case RISCV::MUL:
return RISCV::PseudoCCMUL;
1834 case RISCV::LUI:
return RISCV::PseudoCCLUI;
1835 case RISCV::QC_LI:
return RISCV::PseudoCCQC_LI;
1836 case RISCV::QC_E_LI:
return RISCV::PseudoCCQC_E_LI;
1838 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
1839 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
1840 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
1841 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
1842 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
1843 case RISCV::ORI:
return RISCV::PseudoCCORI;
1844 case RISCV::XORI:
return RISCV::PseudoCCXORI;
1846 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
1847 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
1848 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
1849 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
1850 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
1852 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
1853 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
1854 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
1855 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
1857 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
1858 case RISCV::ORN:
return RISCV::PseudoCCORN;
1859 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
1861 case RISCV::NDS_BFOS:
return RISCV::PseudoCCNDS_BFOS;
1862 case RISCV::NDS_BFOZ:
return RISCV::PseudoCCNDS_BFOZ;
1866 return RISCV::INSTRUCTION_LIST_END;
1875 if (!
Reg.isVirtual())
1883 if (!STI.hasShortForwardBranchIMinMax() &&
1884 (
MI->getOpcode() == RISCV::MAX ||
MI->getOpcode() == RISCV::MIN ||
1885 MI->getOpcode() == RISCV::MINU ||
MI->getOpcode() == RISCV::MAXU))
1888 if (!STI.hasShortForwardBranchIMul() &&
MI->getOpcode() == RISCV::MUL)
1895 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1896 MI->getOperand(1).getReg() == RISCV::X0)
1901 if (MO.isFI() || MO.isCPI() || MO.isJTI())
1914 bool DontMoveAcrossStores =
true;
1915 if (!
MI->isSafeToMove(DontMoveAcrossStores))
1923 bool PreferFalse)
const {
1924 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1925 "Unknown select instruction");
1926 if (!
STI.hasShortForwardBranchIALU())
1932 bool Invert = !
DefMI;
1940 Register DestReg =
MI.getOperand(0).getReg();
1946 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
1953 NewMI.
add(FalseReg);
1961 unsigned BCCOpcode =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
1967 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 2));
1968 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 1));
1978 if (
DefMI->getParent() !=
MI.getParent())
1982 DefMI->eraseFromParent();
1987 if (
MI.isMetaInstruction())
1990 unsigned Opcode =
MI.getOpcode();
1992 if (Opcode == TargetOpcode::INLINEASM ||
1993 Opcode == TargetOpcode::INLINEASM_BR) {
1995 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
2000 if (
STI.hasStdExtZca()) {
2001 if (isCompressibleInst(
MI,
STI))
2008 if (Opcode == TargetOpcode::BUNDLE)
2009 return getInstBundleSize(
MI);
2011 if (
MI.getParent() &&
MI.getParent()->getParent()) {
2012 if (isCompressibleInst(
MI,
STI))
2017 case RISCV::PseudoMV_FPR16INX:
2018 case RISCV::PseudoMV_FPR32INX:
2019 case RISCV::PseudoClearGPR:
2021 return STI.hasStdExtZca() ? 2 : 4;
2023 case RISCV::PseudoCCMOVGPRNoX0:
2024 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2027 case RISCV::PseudoCCMOVGPR:
2028 case RISCV::PseudoCCADD:
2029 case RISCV::PseudoCCSUB:
2030 case RISCV::PseudoCCSLL:
2031 case RISCV::PseudoCCSRL:
2032 case RISCV::PseudoCCSRA:
2033 case RISCV::PseudoCCAND:
2034 case RISCV::PseudoCCOR:
2035 case RISCV::PseudoCCXOR:
2036 case RISCV::PseudoCCADDI:
2037 case RISCV::PseudoCCANDI:
2038 case RISCV::PseudoCCORI:
2039 case RISCV::PseudoCCXORI:
2040 case RISCV::PseudoCCLUI:
2041 case RISCV::PseudoCCSLLI:
2042 case RISCV::PseudoCCSRLI:
2043 case RISCV::PseudoCCSRAI:
2044 case RISCV::PseudoCCADDW:
2045 case RISCV::PseudoCCSUBW:
2046 case RISCV::PseudoCCSLLW:
2047 case RISCV::PseudoCCSRLW:
2048 case RISCV::PseudoCCSRAW:
2049 case RISCV::PseudoCCADDIW:
2050 case RISCV::PseudoCCSLLIW:
2051 case RISCV::PseudoCCSRLIW:
2052 case RISCV::PseudoCCSRAIW:
2053 case RISCV::PseudoCCANDN:
2054 case RISCV::PseudoCCORN:
2055 case RISCV::PseudoCCXNOR:
2056 case RISCV::PseudoCCMAX:
2057 case RISCV::PseudoCCMIN:
2058 case RISCV::PseudoCCMAXU:
2059 case RISCV::PseudoCCMINU:
2060 case RISCV::PseudoCCMUL:
2061 case RISCV::PseudoCCLB:
2062 case RISCV::PseudoCCLH:
2063 case RISCV::PseudoCCLW:
2064 case RISCV::PseudoCCLHU:
2065 case RISCV::PseudoCCLBU:
2066 case RISCV::PseudoCCLWU:
2067 case RISCV::PseudoCCLD:
2068 case RISCV::PseudoCCQC_LI:
2069 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2072 case RISCV::PseudoCCQC_E_LI:
2073 case RISCV::PseudoCCQC_E_LB:
2074 case RISCV::PseudoCCQC_E_LH:
2075 case RISCV::PseudoCCQC_E_LW:
2076 case RISCV::PseudoCCQC_E_LHU:
2077 case RISCV::PseudoCCQC_E_LBU:
2078 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2081 case TargetOpcode::STACKMAP:
2084 case TargetOpcode::PATCHPOINT:
2087 case TargetOpcode::STATEPOINT: {
2091 return std::max(NumBytes, 8U);
2093 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2094 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2095 case TargetOpcode::PATCHABLE_TAIL_CALL: {
2098 if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
2099 F.hasFnAttribute(
"patchable-function-entry")) {
2101 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
2103 return (
STI.hasStdExtZca() ? 2 : 4) * Num;
2107 return STI.is64Bit() ? 68 : 44;
2110 return get(Opcode).getSize();
2115 const unsigned Opcode =
MI.getOpcode();
2119 case RISCV::FSGNJ_D:
2120 case RISCV::FSGNJ_S:
2121 case RISCV::FSGNJ_H:
2122 case RISCV::FSGNJ_D_INX:
2123 case RISCV::FSGNJ_D_IN32X:
2124 case RISCV::FSGNJ_S_INX:
2125 case RISCV::FSGNJ_H_INX:
2127 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2128 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
2132 return (
MI.getOperand(1).isReg() &&
2133 MI.getOperand(1).getReg() == RISCV::X0) ||
2134 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
2136 return MI.isAsCheapAsAMove();
2139std::optional<DestSourcePair>
2143 switch (
MI.getOpcode()) {
2149 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2150 MI.getOperand(2).isReg())
2152 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2153 MI.getOperand(1).isReg())
2158 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
2159 MI.getOperand(2).getImm() == 0)
2163 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2164 MI.getOperand(1).isReg())
2168 case RISCV::SH1ADD_UW:
2170 case RISCV::SH2ADD_UW:
2172 case RISCV::SH3ADD_UW:
2173 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2174 MI.getOperand(2).isReg())
2177 case RISCV::FSGNJ_D:
2178 case RISCV::FSGNJ_S:
2179 case RISCV::FSGNJ_H:
2180 case RISCV::FSGNJ_D_INX:
2181 case RISCV::FSGNJ_D_IN32X:
2182 case RISCV::FSGNJ_S_INX:
2183 case RISCV::FSGNJ_H_INX:
2185 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2186 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
2190 return std::nullopt;
2198 const auto &SchedModel =
STI.getSchedModel();
2199 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
2211 RISCV::getNamedOperandIdx(Root.
getOpcode(), RISCV::OpName::frm);
2215 return RISCV::getNamedOperandIdx(
MI->getOpcode(),
2216 RISCV::OpName::frm) < 0;
2218 "New instructions require FRM whereas the old one does not have it");
2225 for (
auto *NewMI : InsInstrs) {
2227 if (
static_cast<unsigned>(RISCV::getNamedOperandIdx(
2228 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
2270bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
2271 bool Invert)
const {
2272#define OPCODE_LMUL_CASE(OPC) \
2273 case RISCV::OPC##_M1: \
2274 case RISCV::OPC##_M2: \
2275 case RISCV::OPC##_M4: \
2276 case RISCV::OPC##_M8: \
2277 case RISCV::OPC##_MF2: \
2278 case RISCV::OPC##_MF4: \
2279 case RISCV::OPC##_MF8
2281#define OPCODE_LMUL_MASK_CASE(OPC) \
2282 case RISCV::OPC##_M1_MASK: \
2283 case RISCV::OPC##_M2_MASK: \
2284 case RISCV::OPC##_M4_MASK: \
2285 case RISCV::OPC##_M8_MASK: \
2286 case RISCV::OPC##_MF2_MASK: \
2287 case RISCV::OPC##_MF4_MASK: \
2288 case RISCV::OPC##_MF8_MASK
2293 Opcode = *InvOpcode;
2310#undef OPCODE_LMUL_MASK_CASE
2311#undef OPCODE_LMUL_CASE
2314bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
2325 const uint64_t TSFlags =
Desc.TSFlags;
2327 auto checkImmOperand = [&](
unsigned OpIdx) {
2331 auto checkRegOperand = [&](
unsigned OpIdx) {
2339 if (!checkRegOperand(1))
2354 bool SeenMI2 =
false;
2355 for (
auto End =
MBB->
rend(), It = It1; It != End; ++It) {
2364 if (It->modifiesRegister(RISCV::V0,
TRI)) {
2365 Register SrcReg = It->getOperand(1).getReg();
2383 if (MI1VReg != SrcReg)
2392 assert(SeenMI2 &&
"Prev is expected to appear before Root");
2432bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
2433 bool &Commuted)
const {
2437 "Expect the present of passthrough operand.");
2443 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
2444 areRVVInstsReassociable(Inst, *MI2);
2448 return areRVVInstsReassociable(Inst, *MI1) &&
2449 (isVectorAssociativeAndCommutative(*MI1) ||
2450 isVectorAssociativeAndCommutative(*MI1,
true)) &&
2457 if (!isVectorAssociativeAndCommutative(Inst) &&
2458 !isVectorAssociativeAndCommutative(Inst,
true))
2484 for (
unsigned I = 0;
I < 5; ++
I)
2490 bool &Commuted)
const {
2491 if (isVectorAssociativeAndCommutative(Inst) ||
2492 isVectorAssociativeAndCommutative(Inst,
true))
2493 return hasReassociableVectorSibling(Inst, Commuted);
2499 unsigned OperandIdx = Commuted ? 2 : 1;
2503 int16_t InstFrmOpIdx =
2504 RISCV::getNamedOperandIdx(Inst.
getOpcode(), RISCV::OpName::frm);
2505 int16_t SiblingFrmOpIdx =
2506 RISCV::getNamedOperandIdx(Sibling.
getOpcode(), RISCV::OpName::frm);
2508 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
2513 bool Invert)
const {
2514 if (isVectorAssociativeAndCommutative(Inst, Invert))
2522 Opc = *InverseOpcode;
2567std::optional<unsigned>
2569#define RVV_OPC_LMUL_CASE(OPC, INV) \
2570 case RISCV::OPC##_M1: \
2571 return RISCV::INV##_M1; \
2572 case RISCV::OPC##_M2: \
2573 return RISCV::INV##_M2; \
2574 case RISCV::OPC##_M4: \
2575 return RISCV::INV##_M4; \
2576 case RISCV::OPC##_M8: \
2577 return RISCV::INV##_M8; \
2578 case RISCV::OPC##_MF2: \
2579 return RISCV::INV##_MF2; \
2580 case RISCV::OPC##_MF4: \
2581 return RISCV::INV##_MF4; \
2582 case RISCV::OPC##_MF8: \
2583 return RISCV::INV##_MF8
2585#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
2586 case RISCV::OPC##_M1_MASK: \
2587 return RISCV::INV##_M1_MASK; \
2588 case RISCV::OPC##_M2_MASK: \
2589 return RISCV::INV##_M2_MASK; \
2590 case RISCV::OPC##_M4_MASK: \
2591 return RISCV::INV##_M4_MASK; \
2592 case RISCV::OPC##_M8_MASK: \
2593 return RISCV::INV##_M8_MASK; \
2594 case RISCV::OPC##_MF2_MASK: \
2595 return RISCV::INV##_MF2_MASK; \
2596 case RISCV::OPC##_MF4_MASK: \
2597 return RISCV::INV##_MF4_MASK; \
2598 case RISCV::OPC##_MF8_MASK: \
2599 return RISCV::INV##_MF8_MASK
2603 return std::nullopt;
2605 return RISCV::FSUB_H;
2607 return RISCV::FSUB_S;
2609 return RISCV::FSUB_D;
2611 return RISCV::FADD_H;
2613 return RISCV::FADD_S;
2615 return RISCV::FADD_D;
2632#undef RVV_OPC_LMUL_MASK_CASE
2633#undef RVV_OPC_LMUL_CASE
2638 bool DoRegPressureReduce) {
2665 bool DoRegPressureReduce) {
2672 DoRegPressureReduce)) {
2678 DoRegPressureReduce)) {
2688 bool DoRegPressureReduce) {
2696 unsigned CombineOpc) {
2703 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2717 unsigned OuterShiftAmt) {
2723 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2750 case RISCV::SH1ADD_UW:
2752 case RISCV::SH2ADD_UW:
2754 case RISCV::SH3ADD_UW:
2800 bool DoRegPressureReduce)
const {
2809 DoRegPressureReduce);
2817 return RISCV::FMADD_H;
2819 return RISCV::FMADD_S;
2821 return RISCV::FMADD_D;
2866 bool Mul1IsKill = Mul1.
isKill();
2867 bool Mul2IsKill = Mul2.
isKill();
2868 bool AddendIsKill = Addend.
isKill();
2877 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
2902 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
2909 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
2912 switch (InnerShiftAmt - OuterShiftAmt) {
2916 InnerOpc = RISCV::ADD;
2919 InnerOpc = RISCV::SH1ADD;
2922 InnerOpc = RISCV::SH2ADD;
2925 InnerOpc = RISCV::SH3ADD;
2943 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
2960 DelInstrs, InstrIdxForVirtReg);
2987 for (
const auto &[Index, Operand] :
enumerate(
Desc.operands())) {
2989 unsigned OpType = Operand.OperandType;
2995 ErrInfo =
"Expected an immediate operand.";
2998 int64_t Imm = MO.
getImm();
3004#define CASE_OPERAND_UIMM(NUM) \
3005 case RISCVOp::OPERAND_UIMM##NUM: \
3006 Ok = isUInt<NUM>(Imm); \
3008#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX) \
3009 case RISCVOp::OPERAND_UIMM##BITS##_LSB##SUFFIX: { \
3010 constexpr size_t NumZeros = sizeof(#SUFFIX) - 1; \
3011 Ok = isShiftedUInt<BITS - NumZeros, NumZeros>(Imm); \
3014#define CASE_OPERAND_SIMM(NUM) \
3015 case RISCVOp::OPERAND_SIMM##NUM: \
3016 Ok = isInt<NUM>(Imm); \
3050 Ok = Imm >= 1 && Imm <= 32;
3053 Ok = Imm >= 1 && Imm <= 64;
3056 Ok = Imm ==
STI.getXLen();
3080 Ok = (
isUInt<5>(Imm) && Imm != 0) || Imm == -1;
3092 Ok = Imm >= -15 && Imm <= 16;
3120 Ok = Ok && Imm != 0;
3123 Ok = (
isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
3126 Ok = Imm >= 0 && Imm <= 10;
3129 Ok = Imm >= 0 && Imm <= 7;
3132 Ok = Imm >= 1 && Imm <= 10;
3135 Ok = Imm >= 2 && Imm <= 14;
3144 Ok = Imm >= 0 && Imm <= 48 && Imm % 16 == 0;
3185 Ok = Imm == 1 || Imm == 2 || Imm == 4;
3189 ErrInfo =
"Invalid immediate";
3198 ErrInfo =
"Expected a non-register operand.";
3202 ErrInfo =
"Invalid immediate";
3211 ErrInfo =
"Expected a non-register operand.";
3215 ErrInfo =
"Invalid immediate";
3223 ErrInfo =
"Expected a non-register operand.";
3227 ErrInfo =
"Invalid immediate";
3233 int64_t Imm = MO.
getImm();
3236 ErrInfo =
"Invalid immediate";
3239 }
else if (!MO.
isReg()) {
3240 ErrInfo =
"Expected a register or immediate operand.";
3246 ErrInfo =
"Expected a register or immediate operand.";
3256 if (!
Op.isImm() && !
Op.isReg()) {
3257 ErrInfo =
"Invalid operand type for VL operand";
3260 if (
Op.isReg() &&
Op.getReg().isValid()) {
3263 if (!RISCV::GPRNoX0RegClass.hasSubClassEq(RC)) {
3264 ErrInfo =
"Invalid register class for VL operand";
3269 ErrInfo =
"VL operand w/o SEW operand?";
3275 if (!
MI.getOperand(
OpIdx).isImm()) {
3276 ErrInfo =
"SEW value expected to be an immediate";
3281 ErrInfo =
"Unexpected SEW value";
3284 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3286 ErrInfo =
"Unexpected SEW value";
3292 if (!
MI.getOperand(
OpIdx).isImm()) {
3293 ErrInfo =
"Policy operand expected to be an immediate";
3298 ErrInfo =
"Invalid Policy Value";
3302 ErrInfo =
"policy operand w/o VL operand?";
3310 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
3311 ErrInfo =
"policy operand w/o tied operand?";
3318 !
MI.readsRegister(RISCV::FRM,
nullptr)) {
3319 ErrInfo =
"dynamic rounding mode should read FRM";
3341 case RISCV::LD_RV32:
3351 case RISCV::SD_RV32:
3367 int64_t NewOffset = OldOffset + Disp;
3389 "Addressing mode not supported for folding");
3462 case RISCV::LD_RV32:
3465 case RISCV::SD_RV32:
3472 OffsetIsScalable =
false;
3488 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
3496 if (MO1->getAddrSpace() != MO2->getAddrSpace())
3499 auto Base1 = MO1->getValue();
3500 auto Base2 = MO2->getValue();
3501 if (!Base1 || !Base2)
3509 return Base1 == Base2;
3515 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
3516 unsigned NumBytes)
const {
3519 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
3524 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
3530 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
3536 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
3586 int64_t OffsetA = 0, OffsetB = 0;
3592 int LowOffset = std::min(OffsetA, OffsetB);
3593 int HighOffset = std::max(OffsetA, OffsetB);
3594 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3596 LowOffset + (
int)LowWidth.
getValue() <= HighOffset)
3603std::pair<unsigned, unsigned>
3606 return std::make_pair(TF & Mask, TF & ~Mask);
3612 static const std::pair<unsigned, const char *> TargetFlags[] = {
3613 {MO_CALL,
"riscv-call"},
3614 {MO_LO,
"riscv-lo"},
3615 {MO_HI,
"riscv-hi"},
3616 {MO_PCREL_LO,
"riscv-pcrel-lo"},
3617 {MO_PCREL_HI,
"riscv-pcrel-hi"},
3618 {MO_GOT_HI,
"riscv-got-hi"},
3619 {MO_TPREL_LO,
"riscv-tprel-lo"},
3620 {MO_TPREL_HI,
"riscv-tprel-hi"},
3621 {MO_TPREL_ADD,
"riscv-tprel-add"},
3622 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
3623 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
3624 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
3625 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
3626 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
3627 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"},
3628 {MO_QC_ACCESS,
"riscv-qc-access"},
3637 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
3650 unsigned &Flags)
const {
3670 return F.getFnAttribute(
"fentry-call").getValueAsBool() ||
3671 F.hasFnAttribute(
"patchable-function-entry");
3676 return MI.readsRegister(RegNo,
TRI) ||
3677 MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
3682 return MI.modifiesRegister(RegNo,
TRI) ||
3683 MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
3687 if (!
MBB.back().isReturn())
3726 if (
C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
3727 C.isAvailableInsideSeq(
Reg,
TRI)) {
3741 if (
C.back().isReturn() &&
3742 !
C.isAvailableAcrossAndOutOfSeq(TailExpandUseReg, RegInfo)) {
3744 LLVM_DEBUG(
dbgs() <<
"Cannot be outlined between: " <<
C.front() <<
"and "
3746 LLVM_DEBUG(
dbgs() <<
"Because the tail-call register is live across "
3747 "the proposed outlined function call\n");
3753 if (
C.back().isReturn()) {
3755 "The candidate who uses return instruction must be outlined "
3762 if (!
C.isAvailableInsideSeq(RISCV::X5, RegInfo))
3766 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo))
3776std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3779 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3780 unsigned MinRepeats)
const {
3788 if (RepeatedSequenceLocs.size() < MinRepeats)
3789 return std::nullopt;
3793 unsigned InstrSizeCExt =
3795 unsigned CallOverhead = 0, FrameOverhead = 0;
3798 unsigned CFICount = 0;
3799 for (
auto &
I : Candidate) {
3800 if (
I.isCFIInstruction())
3811 std::vector<MCCFIInstruction> CFIInstructions =
3812 C.getMF()->getFrameInstructions();
3814 if (CFICount > 0 && CFICount != CFIInstructions.size())
3815 return std::nullopt;
3823 CallOverhead = 4 + InstrSizeCExt;
3830 FrameOverhead = InstrSizeCExt;
3836 return std::nullopt;
3840 for (
auto &
C : RepeatedSequenceLocs) {
3842 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo)) {
3844 unsigned CandCallOverhead = 8;
3849 unsigned CandCallOverhead = InstrSizeCExt + 8 + InstrSizeCExt;
3854 for (
auto &
C : RepeatedSequenceLocs)
3855 C.setCallInfo(MOCI, CallOverhead);
3858 unsigned SequenceSize = 0;
3859 for (
auto &
MI : Candidate)
3862 return std::make_unique<outliner::OutlinedFunction>(
3863 RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
3869 unsigned Flags)
const {
3873 MBB->getParent()->getSubtarget().getRegisterInfo();
3874 const auto &
F =
MI.getMF()->getFunction();
3879 if (
MI.isCFIInstruction())
3887 for (
const auto &MO :
MI.operands()) {
3892 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
3893 F.hasSection() ||
F.getSectionPrefix()))
3910 MBB.addLiveIn(RISCV::X5);
3925 .addGlobalAddress(M.getNamedValue(MF.
getName()),
3932 assert(SaveReg &&
"Cannot find an available register to save/restore X5.");
3943 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
3959 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
3967 bool AllowSideEffects)
const {
3972 if (
TRI.isGeneralPurposeRegister(MF, Reg)) {
3974 }
else if (RISCV::FPR32RegClass.
contains(Reg)) {
3976 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
3978 }
else if (RISCV::FPR128RegClass.
contains(Reg)) {
3982 "buildClearRegister is not implemented for vector registers");
3992 return std::nullopt;
3996 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
3997 MI.getOperand(2).isImm())
3998 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
4000 return std::nullopt;
4008 std::string GenericComment =
4010 if (!GenericComment.empty())
4011 return GenericComment;
4015 return std::string();
4017 std::string Comment;
4024 switch (OpInfo.OperandType) {
4027 unsigned Imm =
Op.getImm();
4032 unsigned Imm =
Op.getImm();
4037 unsigned Imm =
Op.getImm();
4043 unsigned Log2SEW =
Op.getImm();
4044 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
4050 unsigned Policy =
Op.getImm();
4052 "Invalid Policy Value");
4058 if (
Op.isImm() &&
Op.getImm() == -1)
4080#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
4081 RISCV::Pseudo##OP##_##LMUL
4083#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
4084 RISCV::Pseudo##OP##_##LMUL##_MASK
4086#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
4087 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
4088 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
4090#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
4091 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
4092 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
4093 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
4094 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
4095 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
4096 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
4098#define CASE_RVV_OPCODE_UNMASK(OP) \
4099 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4100 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
4102#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
4103 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
4104 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
4105 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
4106 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
4107 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
4108 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
4110#define CASE_RVV_OPCODE_MASK(OP) \
4111 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
4112 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
4114#define CASE_RVV_OPCODE_WIDEN(OP) \
4115 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4116 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
4118#define CASE_RVV_OPCODE(OP) \
4119 CASE_RVV_OPCODE_UNMASK(OP): \
4120 case CASE_RVV_OPCODE_MASK(OP)
4124#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
4125 RISCV::PseudoV##OP##_##TYPE##_##LMUL
4127#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
4128 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
4129 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
4130 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
4131 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
4132 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
4133 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
4134 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
4137#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
4138 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
4140#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
4141 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
4142 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
4143 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
4144 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
4146#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
4147 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
4148 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
4150#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
4151 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
4152 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
4154#define CASE_VFMA_OPCODE_VV(OP) \
4155 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
4156 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VV, E16): \
4157 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
4158 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
4160#define CASE_VFMA_SPLATS(OP) \
4161 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
4162 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VFPR16, E16): \
4163 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
4164 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
4168 unsigned &SrcOpIdx1,
4169 unsigned &SrcOpIdx2)
const {
4171 if (!
Desc.isCommutable())
4174 switch (
MI.getOpcode()) {
4175 case RISCV::TH_MVEQZ:
4176 case RISCV::TH_MVNEZ:
4180 if (
MI.getOperand(2).getReg() == RISCV::X0)
4183 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4184 case RISCV::QC_SELECTIEQ:
4185 case RISCV::QC_SELECTINE:
4186 case RISCV::QC_SELECTIIEQ:
4187 case RISCV::QC_SELECTIINE:
4188 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4189 case RISCV::QC_MVEQ:
4190 case RISCV::QC_MVNE:
4191 case RISCV::QC_MVLT:
4192 case RISCV::QC_MVGE:
4193 case RISCV::QC_MVLTU:
4194 case RISCV::QC_MVGEU:
4195 case RISCV::QC_MVEQI:
4196 case RISCV::QC_MVNEI:
4197 case RISCV::QC_MVLTI:
4198 case RISCV::QC_MVGEI:
4199 case RISCV::QC_MVLTUI:
4200 case RISCV::QC_MVGEUI:
4201 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 4);
4202 case RISCV::TH_MULA:
4203 case RISCV::TH_MULAW:
4204 case RISCV::TH_MULAH:
4205 case RISCV::TH_MULS:
4206 case RISCV::TH_MULSW:
4207 case RISCV::TH_MULSH:
4209 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4210 case RISCV::PseudoCCMOVGPRNoX0:
4211 case RISCV::PseudoCCMOVGPR:
4213 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4254 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4281 unsigned CommutableOpIdx1 = 1;
4282 unsigned CommutableOpIdx2 = 3;
4283 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4304 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
4306 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
4310 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
4311 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
4317 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
4318 SrcOpIdx2 == CommuteAnyOperandIndex) {
4321 unsigned CommutableOpIdx1 = SrcOpIdx1;
4322 if (SrcOpIdx1 == SrcOpIdx2) {
4325 CommutableOpIdx1 = 1;
4326 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
4328 CommutableOpIdx1 = SrcOpIdx2;
4333 unsigned CommutableOpIdx2;
4334 if (CommutableOpIdx1 != 1) {
4336 CommutableOpIdx2 = 1;
4338 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
4343 if (Op1Reg !=
MI.getOperand(2).getReg())
4344 CommutableOpIdx2 = 2;
4346 CommutableOpIdx2 = 3;
4351 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4364#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
4365 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
4366 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
4369#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
4370 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
4371 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
4372 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
4373 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
4374 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
4375 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
4376 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
4379#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
4380 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
4381 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
4384#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
4385 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
4386 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
4387 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
4388 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
4390#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
4391 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
4392 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
4394#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
4395 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
4396 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
4398#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
4399 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
4400 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VV, E16) \
4401 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
4402 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
4404#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
4405 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
4406 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VFPR16, E16) \
4407 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
4408 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
4414 unsigned OpIdx2)
const {
4417 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
4421 switch (
MI.getOpcode()) {
4422 case RISCV::TH_MVEQZ:
4423 case RISCV::TH_MVNEZ: {
4424 auto &WorkingMI = cloneIfNew(
MI);
4425 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
4426 : RISCV::TH_MVEQZ));
4430 case RISCV::QC_SELECTIEQ:
4431 case RISCV::QC_SELECTINE:
4432 case RISCV::QC_SELECTIIEQ:
4433 case RISCV::QC_SELECTIINE:
4435 case RISCV::QC_MVEQ:
4436 case RISCV::QC_MVNE:
4437 case RISCV::QC_MVLT:
4438 case RISCV::QC_MVGE:
4439 case RISCV::QC_MVLTU:
4440 case RISCV::QC_MVGEU:
4441 case RISCV::QC_MVEQI:
4442 case RISCV::QC_MVNEI:
4443 case RISCV::QC_MVLTI:
4444 case RISCV::QC_MVGEI:
4445 case RISCV::QC_MVLTUI:
4446 case RISCV::QC_MVGEUI: {
4447 auto &WorkingMI = cloneIfNew(
MI);
4452 case RISCV::PseudoCCMOVGPRNoX0:
4453 case RISCV::PseudoCCMOVGPR: {
4455 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
4457 auto &WorkingMI = cloneIfNew(
MI);
4458 WorkingMI.getOperand(
MI.getNumExplicitOperands() - 3).setImm(BCC);
4482 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4483 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
4485 switch (
MI.getOpcode()) {
4508 auto &WorkingMI = cloneIfNew(
MI);
4509 WorkingMI.setDesc(
get(
Opc));
4519 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4522 if (OpIdx1 == 3 || OpIdx2 == 3) {
4524 switch (
MI.getOpcode()) {
4535 auto &WorkingMI = cloneIfNew(
MI);
4536 WorkingMI.setDesc(
get(
Opc));
4548#undef CASE_VMA_CHANGE_OPCODE_COMMON
4549#undef CASE_VMA_CHANGE_OPCODE_LMULS
4550#undef CASE_VFMA_CHANGE_OPCODE_COMMON
4551#undef CASE_VFMA_CHANGE_OPCODE_LMULS_M1
4552#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF2
4553#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF4
4554#undef CASE_VFMA_CHANGE_OPCODE_VV
4555#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
4557#undef CASE_RVV_OPCODE_UNMASK_LMUL
4558#undef CASE_RVV_OPCODE_MASK_LMUL
4559#undef CASE_RVV_OPCODE_LMUL
4560#undef CASE_RVV_OPCODE_UNMASK_WIDEN
4561#undef CASE_RVV_OPCODE_UNMASK
4562#undef CASE_RVV_OPCODE_MASK_WIDEN
4563#undef CASE_RVV_OPCODE_MASK
4564#undef CASE_RVV_OPCODE_WIDEN
4565#undef CASE_RVV_OPCODE
4567#undef CASE_VMA_OPCODE_COMMON
4568#undef CASE_VMA_OPCODE_LMULS
4569#undef CASE_VFMA_OPCODE_COMMON
4570#undef CASE_VFMA_OPCODE_LMULS_M1
4571#undef CASE_VFMA_OPCODE_LMULS_MF2
4572#undef CASE_VFMA_OPCODE_LMULS_MF4
4573#undef CASE_VFMA_OPCODE_VV
4574#undef CASE_VFMA_SPLATS
4577 switch (
MI.getOpcode()) {
4585 if (
MI.getOperand(1).getReg() == RISCV::X0)
4586 commuteInstruction(
MI);
4588 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4589 MI.getOperand(2).ChangeToImmediate(0);
4590 MI.setDesc(
get(RISCV::ADDI));
4594 if (
MI.getOpcode() == RISCV::XOR &&
4595 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4596 MI.getOperand(1).setReg(RISCV::X0);
4597 MI.getOperand(2).ChangeToImmediate(0);
4598 MI.setDesc(
get(RISCV::ADDI));
4605 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4606 MI.setDesc(
get(RISCV::ADDI));
4612 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4613 MI.getOperand(2).ChangeToImmediate(0);
4614 MI.setDesc(
get(RISCV::ADDI));
4620 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4621 MI.getOperand(2).ChangeToImmediate(0);
4622 MI.setDesc(
get(RISCV::ADDIW));
4629 if (
MI.getOperand(1).getReg() == RISCV::X0)
4630 commuteInstruction(
MI);
4632 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4633 MI.getOperand(2).ChangeToImmediate(0);
4634 MI.setDesc(
get(RISCV::ADDIW));
4639 case RISCV::SH1ADD_UW:
4641 case RISCV::SH2ADD_UW:
4643 case RISCV::SH3ADD_UW:
4645 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4646 MI.removeOperand(1);
4648 MI.setDesc(
get(RISCV::ADDI));
4652 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4653 MI.removeOperand(2);
4654 unsigned Opc =
MI.getOpcode();
4655 if (
Opc == RISCV::SH1ADD_UW ||
Opc == RISCV::SH2ADD_UW ||
4656 Opc == RISCV::SH3ADD_UW) {
4658 MI.setDesc(
get(RISCV::SLLI_UW));
4662 MI.setDesc(
get(RISCV::SLLI));
4676 if (
MI.getOperand(1).getReg() == RISCV::X0 ||
4677 MI.getOperand(2).getReg() == RISCV::X0) {
4678 MI.getOperand(1).setReg(RISCV::X0);
4679 MI.getOperand(2).ChangeToImmediate(0);
4680 MI.setDesc(
get(RISCV::ADDI));
4686 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4687 MI.getOperand(2).setImm(0);
4688 MI.setDesc(
get(RISCV::ADDI));
4696 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4697 MI.getOperand(2).ChangeToImmediate(0);
4698 MI.setDesc(
get(RISCV::ADDI));
4702 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4703 MI.getOperand(2).ChangeToImmediate(0);
4704 MI.setDesc(
get(RISCV::ADDI));
4712 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4713 MI.getOperand(2).ChangeToImmediate(0);
4714 MI.setDesc(
get(RISCV::ADDI));
4724 case RISCV::SLLI_UW:
4726 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4727 MI.getOperand(2).setImm(0);
4728 MI.setDesc(
get(RISCV::ADDI));
4736 if (
MI.getOperand(1).getReg() == RISCV::X0 &&
4737 MI.getOperand(2).getReg() == RISCV::X0) {
4738 MI.getOperand(2).ChangeToImmediate(0);
4739 MI.setDesc(
get(RISCV::ADDI));
4743 if (
MI.getOpcode() == RISCV::ADD_UW &&
4744 MI.getOperand(1).getReg() == RISCV::X0) {
4745 MI.removeOperand(1);
4747 MI.setDesc(
get(RISCV::ADDI));
4753 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4754 MI.getOperand(2).setImm(
MI.getOperand(2).getImm() != 0);
4755 MI.setDesc(
get(RISCV::ADDI));
4761 case RISCV::ZEXT_H_RV32:
4762 case RISCV::ZEXT_H_RV64:
4765 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4767 MI.setDesc(
get(RISCV::ADDI));
4776 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4777 MI.getOperand(2).ChangeToImmediate(0);
4778 MI.setDesc(
get(RISCV::ADDI));
4785 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4787 MI.removeOperand(0);
4788 MI.insert(
MI.operands_begin() + 1, {MO0});
4793 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4795 MI.removeOperand(0);
4796 MI.insert(
MI.operands_begin() + 1, {MO0});
4797 MI.setDesc(
get(RISCV::BNE));
4802 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4804 MI.removeOperand(0);
4805 MI.insert(
MI.operands_begin() + 1, {MO0});
4806 MI.setDesc(
get(RISCV::BEQ));
4814#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
4815 RISCV::PseudoV##OP##_##LMUL##_TIED
4817#define CASE_WIDEOP_OPCODE_LMULS(OP) \
4818 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
4819 case CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
4820 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
4821 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
4822 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
4823 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
4825#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
4826 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
4827 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
4830#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4831 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
4832 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
4833 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
4834 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
4835 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
4836 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
4839#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
4840 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
4842#define CASE_FP_WIDEOP_OPCODE_LMULS(OP) \
4843 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4844 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4845 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
4846 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4847 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
4848 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4849 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
4850 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
4851 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
4853#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
4854 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
4855 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
4858#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4859 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4860 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4861 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
4862 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
4863 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
4864 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
4865 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
4866 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
4867 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
4869#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP) \
4870 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4871 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4872 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4873 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4874 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16)
4876#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP) \
4877 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4878 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4879 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
4880 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
4881 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16)
4888 switch (
MI.getOpcode()) {
4896 MI.getNumExplicitOperands() == 7 &&
4897 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
4904 switch (
MI.getOpcode()) {
4916 .
add(
MI.getOperand(0))
4918 .
add(
MI.getOperand(1))
4919 .
add(
MI.getOperand(2))
4920 .
add(
MI.getOperand(3))
4921 .
add(
MI.getOperand(4))
4922 .
add(
MI.getOperand(5))
4923 .
add(
MI.getOperand(6));
4932 MI.getNumExplicitOperands() == 6);
4939 switch (
MI.getOpcode()) {
4951 .
add(
MI.getOperand(0))
4953 .
add(
MI.getOperand(1))
4954 .
add(
MI.getOperand(2))
4955 .
add(
MI.getOperand(3))
4956 .
add(
MI.getOperand(4))
4957 .
add(
MI.getOperand(5));
4964 unsigned NumOps =
MI.getNumOperands();
4967 if (
Op.isReg() &&
Op.isKill())
4975 if (
MI.getOperand(0).isEarlyClobber()) {
4989#undef CASE_WIDEOP_OPCODE_COMMON
4990#undef CASE_WIDEOP_OPCODE_LMULS
4991#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
4992#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
4993#undef CASE_FP_WIDEOP_OPCODE_COMMON
4994#undef CASE_FP_WIDEOP_OPCODE_LMULS
4995#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
4996#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
5005 if (ShiftAmount == 0)
5011 }
else if (
int ShXAmount, ShiftAmount;
5013 (ShXAmount =
isShifted359(Amount, ShiftAmount)) != 0) {
5016 switch (ShXAmount) {
5018 Opc = RISCV::SH1ADD;
5021 Opc = RISCV::SH2ADD;
5024 Opc = RISCV::SH3ADD;
5060 }
else if (
STI.hasStdExtZmmul()) {
5070 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
5071 if (Amount & (1U << ShiftAmount)) {
5075 .
addImm(ShiftAmount - PrevShiftAmount)
5077 if (Amount >> (ShiftAmount + 1)) {
5091 PrevShiftAmount = ShiftAmount;
5094 assert(Acc &&
"Expected valid accumulator");
5104 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
5112 ?
STI.getTailDupAggressiveThreshold()
5119 unsigned Opcode =
MI.getOpcode();
5120 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
5129 return MI.isCopy() &&
MI.getOperand(0).getReg().isPhysical() &&
5131 TRI->getMinimalPhysRegClass(
MI.getOperand(0).getReg()));
5134std::optional<std::pair<unsigned, unsigned>>
5138 return std::nullopt;
5139 case RISCV::PseudoVSPILL2_M1:
5140 case RISCV::PseudoVRELOAD2_M1:
5141 return std::make_pair(2u, 1u);
5142 case RISCV::PseudoVSPILL2_M2:
5143 case RISCV::PseudoVRELOAD2_M2:
5144 return std::make_pair(2u, 2u);
5145 case RISCV::PseudoVSPILL2_M4:
5146 case RISCV::PseudoVRELOAD2_M4:
5147 return std::make_pair(2u, 4u);
5148 case RISCV::PseudoVSPILL3_M1:
5149 case RISCV::PseudoVRELOAD3_M1:
5150 return std::make_pair(3u, 1u);
5151 case RISCV::PseudoVSPILL3_M2:
5152 case RISCV::PseudoVRELOAD3_M2:
5153 return std::make_pair(3u, 2u);
5154 case RISCV::PseudoVSPILL4_M1:
5155 case RISCV::PseudoVRELOAD4_M1:
5156 return std::make_pair(4u, 1u);
5157 case RISCV::PseudoVSPILL4_M2:
5158 case RISCV::PseudoVRELOAD4_M2:
5159 return std::make_pair(4u, 2u);
5160 case RISCV::PseudoVSPILL5_M1:
5161 case RISCV::PseudoVRELOAD5_M1:
5162 return std::make_pair(5u, 1u);
5163 case RISCV::PseudoVSPILL6_M1:
5164 case RISCV::PseudoVRELOAD6_M1:
5165 return std::make_pair(6u, 1u);
5166 case RISCV::PseudoVSPILL7_M1:
5167 case RISCV::PseudoVRELOAD7_M1:
5168 return std::make_pair(7u, 1u);
5169 case RISCV::PseudoVSPILL8_M1:
5170 case RISCV::PseudoVRELOAD8_M1:
5171 return std::make_pair(8u, 1u);
5176 int16_t MI1FrmOpIdx =
5177 RISCV::getNamedOperandIdx(MI1.
getOpcode(), RISCV::OpName::frm);
5178 int16_t MI2FrmOpIdx =
5179 RISCV::getNamedOperandIdx(MI2.
getOpcode(), RISCV::OpName::frm);
5180 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
5187std::optional<unsigned>
5191 return std::nullopt;
5194 case RISCV::VSLL_VX:
5195 case RISCV::VSRL_VX:
5196 case RISCV::VSRA_VX:
5198 case RISCV::VSSRL_VX:
5199 case RISCV::VSSRA_VX:
5201 case RISCV::VROL_VX:
5202 case RISCV::VROR_VX:
5207 case RISCV::VNSRL_WX:
5208 case RISCV::VNSRA_WX:
5210 case RISCV::VNCLIPU_WX:
5211 case RISCV::VNCLIP_WX:
5213 case RISCV::VWSLL_VX:
5218 case RISCV::VADD_VX:
5219 case RISCV::VSUB_VX:
5220 case RISCV::VRSUB_VX:
5222 case RISCV::VWADDU_VX:
5223 case RISCV::VWSUBU_VX:
5224 case RISCV::VWADD_VX:
5225 case RISCV::VWSUB_VX:
5226 case RISCV::VWADDU_WX:
5227 case RISCV::VWSUBU_WX:
5228 case RISCV::VWADD_WX:
5229 case RISCV::VWSUB_WX:
5231 case RISCV::VADC_VXM:
5232 case RISCV::VADC_VIM:
5233 case RISCV::VMADC_VXM:
5234 case RISCV::VMADC_VIM:
5235 case RISCV::VMADC_VX:
5236 case RISCV::VSBC_VXM:
5237 case RISCV::VMSBC_VXM:
5238 case RISCV::VMSBC_VX:
5240 case RISCV::VAND_VX:
5242 case RISCV::VXOR_VX:
5244 case RISCV::VMSEQ_VX:
5245 case RISCV::VMSNE_VX:
5246 case RISCV::VMSLTU_VX:
5247 case RISCV::VMSLT_VX:
5248 case RISCV::VMSLEU_VX:
5249 case RISCV::VMSLE_VX:
5250 case RISCV::VMSGTU_VX:
5251 case RISCV::VMSGT_VX:
5253 case RISCV::VMINU_VX:
5254 case RISCV::VMIN_VX:
5255 case RISCV::VMAXU_VX:
5256 case RISCV::VMAX_VX:
5258 case RISCV::VMUL_VX:
5259 case RISCV::VMULH_VX:
5260 case RISCV::VMULHU_VX:
5261 case RISCV::VMULHSU_VX:
5263 case RISCV::VDIVU_VX:
5264 case RISCV::VDIV_VX:
5265 case RISCV::VREMU_VX:
5266 case RISCV::VREM_VX:
5268 case RISCV::VWMUL_VX:
5269 case RISCV::VWMULU_VX:
5270 case RISCV::VWMULSU_VX:
5272 case RISCV::VMACC_VX:
5273 case RISCV::VNMSAC_VX:
5274 case RISCV::VMADD_VX:
5275 case RISCV::VNMSUB_VX:
5277 case RISCV::VWMACCU_VX:
5278 case RISCV::VWMACC_VX:
5279 case RISCV::VWMACCSU_VX:
5280 case RISCV::VWMACCUS_VX:
5282 case RISCV::VMERGE_VXM:
5284 case RISCV::VMV_V_X:
5286 case RISCV::VSADDU_VX:
5287 case RISCV::VSADD_VX:
5288 case RISCV::VSSUBU_VX:
5289 case RISCV::VSSUB_VX:
5291 case RISCV::VAADDU_VX:
5292 case RISCV::VAADD_VX:
5293 case RISCV::VASUBU_VX:
5294 case RISCV::VASUB_VX:
5296 case RISCV::VSMUL_VX:
5298 case RISCV::VMV_S_X:
5300 case RISCV::VANDN_VX:
5301 return 1U << Log2SEW;
5307 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
5310 return RVV->BaseInstr;
5320 unsigned Scaled = Log2SEW + (DestEEW - 1);
5334 return std::nullopt;
5339 assert((LHS.isImm() || LHS.getParent()->getMF()->getRegInfo().isSSA()) &&
5340 (RHS.isImm() || RHS.getParent()->getMF()->getRegInfo().isSSA()));
5341 if (LHS.isReg() && RHS.isReg() && LHS.getReg().isVirtual() &&
5342 LHS.getReg() == RHS.getReg())
5346 if (LHS.isImm() && LHS.getImm() == 0)
5352 if (!LHSImm || !RHSImm)
5354 return LHSImm <= RHSImm;
5366 : LHS(LHS), RHS(RHS),
Cond(
Cond.begin(),
Cond.end()) {}
5368 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
5378 std::optional<bool> createTripCountGreaterCondition(
5379 int TC, MachineBasicBlock &
MBB,
5380 SmallVectorImpl<MachineOperand> &CondParam)
override {
5388 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
5390 void adjustTripCount(
int TripCountAdjust)
override {}
5394std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
5402 if (
TBB == LoopBB && FBB == LoopBB)
5409 assert((
TBB == LoopBB || FBB == LoopBB) &&
5410 "The Loop must be a single-basic-block loop");
5421 if (!Reg.isVirtual())
5428 if (LHS && LHS->isPHI())
5430 if (RHS && RHS->isPHI())
5433 return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS,
Cond);
5439 Opc = RVVMCOpcode ? RVVMCOpcode :
Opc;
5456 case RISCV::FDIV_H_INX:
5457 case RISCV::FDIV_S_INX:
5458 case RISCV::FDIV_D_INX:
5459 case RISCV::FDIV_D_IN32X:
5460 case RISCV::FSQRT_H:
5461 case RISCV::FSQRT_S:
5462 case RISCV::FSQRT_D:
5463 case RISCV::FSQRT_H_INX:
5464 case RISCV::FSQRT_S_INX:
5465 case RISCV::FSQRT_D_INX:
5466 case RISCV::FSQRT_D_IN32X:
5468 case RISCV::VDIV_VV:
5469 case RISCV::VDIV_VX:
5470 case RISCV::VDIVU_VV:
5471 case RISCV::VDIVU_VX:
5472 case RISCV::VREM_VV:
5473 case RISCV::VREM_VX:
5474 case RISCV::VREMU_VV:
5475 case RISCV::VREMU_VX:
5477 case RISCV::VFDIV_VV:
5478 case RISCV::VFDIV_VF:
5479 case RISCV::VFRDIV_VF:
5480 case RISCV::VFSQRT_V:
5481 case RISCV::VFRSQRT7_V:
5487 if (
MI->getOpcode() != TargetOpcode::COPY)
5492 Register DstReg =
MI->getOperand(0).getReg();
5495 :
TRI->getMinimalPhysRegClass(DstReg);
5505 auto [RCLMul, RCFractional] =
5507 return (!RCFractional && LMul == RCLMul) || (RCFractional && LMul == 1);
5511 if (
MI.memoperands_empty())
5526 if (MO.getReg().isPhysical())
5529 if (MO.getReg().isPhysical())
5531 bool SawStore =
false;
5534 if (
II->definesRegister(PhysReg,
nullptr))
5537 if (
II->definesRegister(PhysReg,
nullptr) ||
5538 II->readsRegister(PhysReg,
nullptr))
5540 if (
II->mayStore()) {
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
SmallVector< int16_t, MAX_SRC_OPERANDS_NUM > OperandIndices
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static bool cannotInsertTailCall(const MachineBasicBlock &MBB)
#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)
#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP)
#define CASE_FP_WIDEOP_OPCODE_LMULS(OP)
#define CASE_OPERAND_SIMM(NUM)
static std::optional< unsigned > getLMULForRVVWholeLoadStore(unsigned Opcode)
#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP)
static unsigned getFPFusedMultiplyOpcode(unsigned RootOpc, unsigned Pattern)
std::optional< unsigned > getFoldedOpcode(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, const RISCVSubtarget &ST)
#define RVV_OPC_LMUL_CASE(OPC, INV)
#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP)
static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs)
static unsigned getAddendOperandIdx(unsigned Pattern)
#define CASE_RVV_OPCODE_UNMASK(OP)
#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP)
static cl::opt< bool > PreferWholeRegisterMove("riscv-prefer-whole-register-move", cl::init(false), cl::Hidden, cl::desc("Prefer whole register move for vector registers."))
#define CASE_VFMA_SPLATS(OP)
unsigned getPredicatedOpcode(unsigned Opcode)
#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP)
#define CASE_WIDEOP_OPCODE_LMULS(OP)
static bool isMIReadsReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
#define OPCODE_LMUL_MASK_CASE(OPC)
#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX)
static bool isFSUB(unsigned Opc)
#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)
#define CASE_RVV_OPCODE(OP)
static std::optional< int64_t > getEffectiveImm(const MachineOperand &MO)
#define CASE_VFMA_OPCODE_VV(OP)
static cl::opt< bool > OutlinerEnableRegSave("riscv-outliner-regsave", cl::init(true), cl::Hidden, cl::desc("Enable RegSave strategy in machine outliner (save X5 to a " "temporary register when X5 is live across outlined calls)."))
MachineOutlinerConstructionID
#define CASE_RVV_OPCODE_WIDEN(OP)
static unsigned getLoadPredicatedOpcode(unsigned Opcode)
static unsigned getSHXADDUWShiftAmount(unsigned Opc)
#define CASE_VMA_OPCODE_LMULS(OP, TYPE)
static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI, const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI, MachineBasicBlock::const_iterator &DefMBBI, RISCVVType::VLMUL LMul)
static bool isFMUL(unsigned Opc)
static unsigned getInverseXqcicmOpcode(unsigned Opcode)
static bool getFPPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
#define OPCODE_LMUL_CASE(OPC)
#define CASE_OPERAND_UIMM(NUM)
static Register findRegisterToSaveX5To(outliner::Candidate &C, const TargetRegisterInfo &TRI)
static bool canCombineShiftIntoShXAdd(const MachineBasicBlock &MBB, const MachineOperand &MO, unsigned OuterShiftAmt)
Utility routine that checks if.
static bool isCandidatePatchable(const MachineBasicBlock &MBB)
static bool isFADD(unsigned Opc)
static void genShXAddAddShift(MachineInstr &Root, unsigned AddOpIdx, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
static bool isLoadImm(const MachineInstr *MI, int64_t &Imm)
static bool isMIModifiesReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
#define CASE_RVV_OPCODE_LMUL(OP, LMUL)
static bool canCombineFPFusedMultiply(const MachineInstr &Root, const MachineOperand &MO, bool DoRegPressureReduce)
static bool getSHXADDPatterns(const MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getFPFusedMultiplyPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
static cl::opt< MachineTraceStrategy > ForceMachineCombinerStrategy("riscv-force-machine-combiner-strategy", cl::Hidden, cl::desc("Force machine combiner to use a specific strategy for machine " "trace metrics evaluation."), cl::init(MachineTraceStrategy::TS_NumStrategies), cl::values(clEnumValN(MachineTraceStrategy::TS_Local, "local", "Local strategy."), clEnumValN(MachineTraceStrategy::TS_MinInstrCount, "min-instr", "MinInstrCount strategy.")))
static unsigned getSHXADDShiftAmount(unsigned Opc)
#define CASE_RVV_OPCODE_MASK(OP)
#define RVV_OPC_LMUL_MASK_CASE(OPC, INV)
static MachineInstr * canFoldAsPredicatedOp(Register Reg, const MachineRegisterInfo &MRI, const TargetInstrInfo *TII, const RISCVSubtarget &STI)
Identify instructions that can be folded into a CCMOV instruction, and return the defining instructio...
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
bool empty() const
Check if the array is empty.
static LLVM_ABI DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
Attempts to merge LocA and LocB into a single location; see DebugLoc::getMergedLocation for more deta...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LiveInterval - This class represents the liveness of a register, or stack slot.
LiveInterval & getInterval(Register Reg)
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
const Segment * getSegmentContaining(SlotIndex Idx) const
Return the segment that contains the specified index, or null if there is none.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
This holds information about one operand of a machine instruction, indicating the register class for ...
const uint8_t TSFlags
Configurable target specific flags.
Wrapper class representing physical registers. Should be passed by value.
const FeatureBitset & getFeatureBits() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineInstrBundleIterator< const MachineInstr, true > const_reverse_iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setStackID(int ObjectIdx, uint8_t ID)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
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 & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isReturn(QueryType Type=AnyInBundle) const
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
filtered_mop_range all_defs()
Returns an iterator range over all operands that are (explicit or implicit) register defs.
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
LLVM_ABI bool isSafeToMove(bool &SawStore) const
Return true if it is safe to move this instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
A description of a memory reference used in the backend.
bool isNonTemporal() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
MI-level patchpoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSafeToMove(const MachineInstr &From, const MachineBasicBlock::iterator &To)
Return true if moving From down to To won't cause any physical register reads or writes to be clobber...
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg) const override
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags, bool DstRenamable=false, bool DstIsDead=false) const
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
void mulImm(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const
Generate code to multiply the value in DestReg by Amt - handles all the common optimizations for this...
static bool isPairableLdStInstOpc(unsigned Opc)
Return true if pairing the given load or store may be paired with another.
RISCVInstrInfo(const RISCVSubtarget &STI)
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &dl, int *BytesAdded=nullptr) const override
bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const override
static bool isLdStSafeToPair(const MachineInstr &LdSt, const TargetRegisterInfo *TRI)
void copyPhysRegVector(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RegClass) const
bool isReMaterializableImpl(const MachineInstr &MI) const override
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
bool isVRegCopy(const MachineInstr *MI, unsigned LMul=0) const
Return true if MI is a COPY to a vector register of a specific LMul, or any kind of vector registers ...
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, LocationSize &Width, const TargetRegisterInfo *TRI) const
unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override
void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const override
const RISCVSubtarget & STI
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
std::optional< unsigned > getInverseOpcode(unsigned Opcode) const override
bool simplifyInstruction(MachineInstr &MI) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MBBI, unsigned Flags) const override
MachineTraceStrategy getMachineCombinerTraceStrategy() const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MCInst getNop() const override
bool analyzeCandidate(outliner::Candidate &C) const
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
bool requiresNTLHint(const MachineInstr &MI) const
Return true if the instruction requires an NTL hint to be emitted.
void finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc)
void buildClearRegister(Register Reg, MachineBasicBlock &MBB, MachineBasicBlock::iterator Iter, DebugLoc &DL, bool AllowSideEffects=true) const override
bool isAssociativeAndCommutative(const MachineInstr &Inst, bool Invert) const override
CombinerObjective getCombinerObjective(unsigned Pattern) const override
bool isHighLatencyDef(int Opc) const override
static bool evaluateCondBranch(RISCVCC::CondCode CC, int64_t C0, int64_t C1)
Return the result of the evaluation of C0 CC C1, where CC is a RISCVCC::CondCode.
bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const override
bool optimizeCondBranch(MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
static bool isFromLoadImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, int64_t &Imm)
Return true if the operand is a load immediate instruction and sets Imm to the immediate value.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
int getBranchRelaxationScratchFrameIndex() const
const RISCVRegisterInfo * getRegisterInfo() const override
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const
Returns true iff the routine could find two commutable operands in the given machine instruction.
virtual bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const
Return true when \P Inst has reassociable operands in the same \P MBB.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const
Optional target hook that returns true if MBB is safe to outline from, and returns any target-specifi...
virtual void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const
The returned array encodes the operand index for each parameter because the operands may be commuted;...
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const
Return true when \P Inst has reassociable sibling.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getZero()
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
self_iterator getIterator()
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
CondCode getInverseBranchCondition(CondCode)
unsigned getInverseBranchOpcode(unsigned BCC)
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static bool isValidRoundingMode(unsigned Mode)
static StringRef roundingModeToString(RoundingMode RndMode)
static unsigned getVecPolicyOpNum(const MCInstrDesc &Desc)
static bool usesMaskPolicy(uint64_t TSFlags)
static bool hasRoundModeOp(uint64_t TSFlags)
static unsigned getVLOpNum(const MCInstrDesc &Desc)
static bool hasVLOp(uint64_t TSFlags)
static MCRegister getTailExpandUseRegNo(const FeatureBitset &FeatureBits)
static int getFRMOpNum(const MCInstrDesc &Desc)
static int getVXRMOpNum(const MCInstrDesc &Desc)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool usesVXRM(uint64_t TSFlags)
static bool isRVVWideningReduction(uint64_t TSFlags)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
static bool hasSEWOp(uint64_t TSFlags)
static bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
SmallVector< Inst, 8 > InstSeq
@ OPERAND_UIMMLOG2XLEN_NONZERO
@ OPERAND_SIMM12_LSB00000
@ OPERAND_FIRST_RISCV_IMM
@ OPERAND_UIMM10_LSB00_NONZERO
@ OPERAND_SIMM10_LSB0000_NONZERO
@ OPERAND_ATOMIC_ORDERING
static unsigned getNF(uint8_t TSFlags)
static RISCVVType::VLMUL getLMul(uint8_t TSFlags)
static bool isTailAgnostic(unsigned VType)
LLVM_ABI void printXSfmmVType(unsigned VType, raw_ostream &OS)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static bool isValidSEW(unsigned SEW)
static bool isValidVType(unsigned VType)
LLVM_ABI void printVType(unsigned VType, raw_ostream &OS)
static bool isValidXSfmmVType(unsigned VTypeI)
static unsigned getSEW(unsigned VType)
static VLMUL getVLMUL(unsigned VType)
static bool isValidRoundingMode(unsigned Mode)
static StringRef roundingModeToString(RoundingMode RndMode)
bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2)
bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
bool isValidYBNDSWImm(int64_t Imm)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW)
std::optional< unsigned > getVectorLowDemandedScalarBits(unsigned Opcode, unsigned Log2SEW)
std::optional< std::pair< unsigned, unsigned > > isRVVSpillForZvlsseg(unsigned Opcode)
static constexpr unsigned RVVBitsPerBlock
bool isRVVSpill(const MachineInstr &MI)
static constexpr unsigned RVVBytesPerBlock
static constexpr int64_t VLMaxSentinel
bool isVectorCopy(const TargetRegisterInfo *TRI, const MachineInstr &MI)
Return true if MI is a copy that will be lowered to one or more vmvNr.vs.
static bool isValidSMTVTypeMode(unsigned Mode)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
MachineTraceStrategy
Strategies for selecting traces.
@ TS_MinInstrCount
Select the trace through a block that has the fewest instructions.
@ TS_Local
Select the trace that contains only the current basic block.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static const MachineMemOperand::Flags MONontemporalBit1
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.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isValidAtomicOrdering(Int I)
constexpr RegState getKillRegState(bool B)
static const MachineMemOperand::Flags MONontemporalBit0
constexpr RegState getDeadRegState(bool B)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned M1(unsigned Val)
constexpr bool has_single_bit(T Value) noexcept
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)
constexpr RegState getRenamableRegState(bool B)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
int isShifted359(T Value, int &Shift)
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...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
This represents a simple continuous liveness interval for a value.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static bool isRVVRegClass(const TargetRegisterClass *RC)
Used to describe a register and immediate addition.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.