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;
410 auto GetCopyInfo = [&](uint16_t SrcEncoding, uint16_t DstEncoding)
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)) {
547 if (!
STI.is64Bit()) {
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:
1135 return (uint64_t)C0 < (uint64_t)C1;
1137 return (uint64_t)C0 >= (uint64_t)C1;
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) {
1635 if (!Reg.isVirtual())
1643 bool IsSigned =
false;
1644 bool IsEquality =
false;
1645 switch (
MI.getOpcode()) {
1681 MI.eraseFromParent();
1707 auto searchConst = [&](int64_t C1) ->
Register {
1709 auto DefC1 = std::find_if(++
II, E, [&](
const MachineInstr &
I) ->
bool {
1712 I.getOperand(0).getReg().isVirtual();
1715 return DefC1->getOperand(0).getReg();
1727 if (
isFromLoadImm(MRI, LHS, C0) && C0 != 0 && LHS.getReg().isVirtual() &&
1728 MRI.
hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
1730 if (
Register RegZ = searchConst(C0 + 1)) {
1738 MI.eraseFromParent();
1748 if (
isFromLoadImm(MRI, RHS, C0) && C0 != 0 && RHS.getReg().isVirtual() &&
1751 if (
Register RegZ = searchConst(C0 - 1)) {
1759 MI.eraseFromParent();
1769 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1771 int NumOp =
MI.getNumExplicitOperands();
1772 return MI.getOperand(NumOp - 1).getMBB();
1776 int64_t BrOffset)
const {
1777 unsigned XLen =
STI.getXLen();
1784 case RISCV::NDS_BBC:
1785 case RISCV::NDS_BBS:
1786 case RISCV::NDS_BEQC:
1787 case RISCV::NDS_BNEC:
1797 case RISCV::CV_BEQIMM:
1798 case RISCV::CV_BNEIMM:
1799 case RISCV::QC_BEQI:
1800 case RISCV::QC_BNEI:
1801 case RISCV::QC_BGEI:
1802 case RISCV::QC_BLTI:
1803 case RISCV::QC_BLTUI:
1804 case RISCV::QC_BGEUI:
1805 case RISCV::QC_E_BEQI:
1806 case RISCV::QC_E_BNEI:
1807 case RISCV::QC_E_BGEI:
1808 case RISCV::QC_E_BLTI:
1809 case RISCV::QC_E_BLTUI:
1810 case RISCV::QC_E_BGEUI:
1813 case RISCV::PseudoBR:
1815 case RISCV::PseudoJump:
1822 const PseudoSourceValue *PSV = MMO->getPseudoValue();
1823 return PSV && PSV->isJumpTable();
1831 if (!
Reg.isVirtual())
1839 return MO.getIndex();
1848 if (!
Reg.isVirtual())
1855 switch (
MI->getOpcode()) {
1891 if (
MI.getOpcode() != RISCV::PseudoBRIND &&
1892 MI.getOpcode() != RISCV::PseudoBRINDX7)
1896 if (!Reg.isVirtual())
1907 switch (Def->getOpcode()) {
1938 case RISCV::ADD:
return RISCV::PseudoCCADD;
1939 case RISCV::SUB:
return RISCV::PseudoCCSUB;
1940 case RISCV::SLL:
return RISCV::PseudoCCSLL;
1941 case RISCV::SRL:
return RISCV::PseudoCCSRL;
1942 case RISCV::SRA:
return RISCV::PseudoCCSRA;
1943 case RISCV::AND:
return RISCV::PseudoCCAND;
1944 case RISCV::OR:
return RISCV::PseudoCCOR;
1945 case RISCV::XOR:
return RISCV::PseudoCCXOR;
1946 case RISCV::MAX:
return RISCV::PseudoCCMAX;
1947 case RISCV::MAXU:
return RISCV::PseudoCCMAXU;
1948 case RISCV::MIN:
return RISCV::PseudoCCMIN;
1949 case RISCV::MINU:
return RISCV::PseudoCCMINU;
1950 case RISCV::MUL:
return RISCV::PseudoCCMUL;
1951 case RISCV::LUI:
return RISCV::PseudoCCLUI;
1952 case RISCV::QC_LI:
return RISCV::PseudoCCQC_LI;
1953 case RISCV::QC_E_LI:
return RISCV::PseudoCCQC_E_LI;
1955 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
1956 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
1957 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
1958 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
1959 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
1960 case RISCV::ORI:
return RISCV::PseudoCCORI;
1961 case RISCV::XORI:
return RISCV::PseudoCCXORI;
1963 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
1964 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
1965 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
1966 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
1967 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
1969 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
1970 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
1971 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
1972 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
1974 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
1975 case RISCV::ORN:
return RISCV::PseudoCCORN;
1976 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
1978 case RISCV::NDS_BFOS:
return RISCV::PseudoCCNDS_BFOS;
1979 case RISCV::NDS_BFOZ:
return RISCV::PseudoCCNDS_BFOZ;
1983 return RISCV::INSTRUCTION_LIST_END;
1992 if (!
Reg.isVirtual())
2000 if (!STI.hasShortForwardBranchIMinMax() &&
2001 (
MI->getOpcode() == RISCV::MAX ||
MI->getOpcode() == RISCV::MIN ||
2002 MI->getOpcode() == RISCV::MINU ||
MI->getOpcode() == RISCV::MAXU))
2005 if (!STI.hasShortForwardBranchIMul() &&
MI->getOpcode() == RISCV::MUL)
2012 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
2013 MI->getOperand(1).getReg() == RISCV::X0)
2018 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2031 bool DontMoveAcrossStores =
true;
2032 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2040 bool PreferFalse)
const {
2041 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
2042 "Unknown select instruction");
2043 if (!
STI.hasShortForwardBranchIALU())
2049 bool Invert = !
DefMI;
2057 Register DestReg =
MI.getOperand(0).getReg();
2063 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
2070 NewMI.
add(FalseReg);
2078 unsigned BCCOpcode =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
2084 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 2));
2085 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 1));
2095 if (
DefMI->getParent() !=
MI.getParent())
2099 DefMI->eraseFromParent();
2104 if (
MI.isMetaInstruction())
2107 unsigned Opcode =
MI.getOpcode();
2109 if (Opcode == TargetOpcode::INLINEASM ||
2110 Opcode == TargetOpcode::INLINEASM_BR) {
2112 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
2117 if (
STI.hasStdExtZca()) {
2118 if (
unsigned Size = getCompressedSize(
MI,
STI))
2125 if (Opcode == TargetOpcode::BUNDLE)
2126 return getInstBundleSize(
MI);
2128 if (
MI.getParent() &&
MI.getParent()->getParent()) {
2129 if (
unsigned Size = getCompressedSize(
MI,
STI))
2134 case RISCV::PseudoMV_FPR16INX:
2135 case RISCV::PseudoMV_FPR32INX:
2136 case RISCV::PseudoClearGPR:
2138 return STI.hasStdExtZca() ? 2 : 4;
2140 case RISCV::PseudoCCMOVGPRNoX0:
2141 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2144 case RISCV::PseudoCCMOVGPR:
2145 case RISCV::PseudoCCADD:
2146 case RISCV::PseudoCCSUB:
2147 case RISCV::PseudoCCSLL:
2148 case RISCV::PseudoCCSRL:
2149 case RISCV::PseudoCCSRA:
2150 case RISCV::PseudoCCAND:
2151 case RISCV::PseudoCCOR:
2152 case RISCV::PseudoCCXOR:
2153 case RISCV::PseudoCCADDI:
2154 case RISCV::PseudoCCANDI:
2155 case RISCV::PseudoCCORI:
2156 case RISCV::PseudoCCXORI:
2157 case RISCV::PseudoCCLUI:
2158 case RISCV::PseudoCCSLLI:
2159 case RISCV::PseudoCCSRLI:
2160 case RISCV::PseudoCCSRAI:
2161 case RISCV::PseudoCCADDW:
2162 case RISCV::PseudoCCSUBW:
2163 case RISCV::PseudoCCSLLW:
2164 case RISCV::PseudoCCSRLW:
2165 case RISCV::PseudoCCSRAW:
2166 case RISCV::PseudoCCADDIW:
2167 case RISCV::PseudoCCSLLIW:
2168 case RISCV::PseudoCCSRLIW:
2169 case RISCV::PseudoCCSRAIW:
2170 case RISCV::PseudoCCANDN:
2171 case RISCV::PseudoCCORN:
2172 case RISCV::PseudoCCXNOR:
2173 case RISCV::PseudoCCMAX:
2174 case RISCV::PseudoCCMIN:
2175 case RISCV::PseudoCCMAXU:
2176 case RISCV::PseudoCCMINU:
2177 case RISCV::PseudoCCMUL:
2178 case RISCV::PseudoCCLB:
2179 case RISCV::PseudoCCLH:
2180 case RISCV::PseudoCCLW:
2181 case RISCV::PseudoCCLHU:
2182 case RISCV::PseudoCCLBU:
2183 case RISCV::PseudoCCLWU:
2184 case RISCV::PseudoCCLD:
2185 case RISCV::PseudoCCQC_LI:
2186 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2189 case RISCV::PseudoCCQC_E_LI:
2190 case RISCV::PseudoCCQC_E_LB:
2191 case RISCV::PseudoCCQC_E_LH:
2192 case RISCV::PseudoCCQC_E_LW:
2193 case RISCV::PseudoCCQC_E_LHU:
2194 case RISCV::PseudoCCQC_E_LBU:
2195 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2198 case TargetOpcode::STACKMAP:
2201 case TargetOpcode::PATCHPOINT:
2204 case TargetOpcode::STATEPOINT: {
2208 return std::max(NumBytes, 8U);
2210 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2211 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2212 case TargetOpcode::PATCHABLE_TAIL_CALL: {
2215 if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
2216 F.hasFnAttribute(
"patchable-function-entry")) {
2218 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
2220 return (
STI.hasStdExtZca() ? 2 : 4) * Num;
2224 return STI.is64Bit() ? 68 : 44;
2227 return get(Opcode).getSize();
2232 const unsigned Opcode =
MI.getOpcode();
2236 case RISCV::FSGNJ_D:
2237 case RISCV::FSGNJ_S:
2238 case RISCV::FSGNJ_H:
2239 case RISCV::FSGNJ_D_INX:
2240 case RISCV::FSGNJ_D_IN32X:
2241 case RISCV::FSGNJ_S_INX:
2242 case RISCV::FSGNJ_H_INX:
2244 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2245 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
2249 return (
MI.getOperand(1).isReg() &&
2250 MI.getOperand(1).getReg() == RISCV::X0) ||
2251 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
2253 return MI.isAsCheapAsAMove();
2256std::optional<DestSourcePair>
2260 switch (
MI.getOpcode()) {
2266 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2267 MI.getOperand(2).isReg())
2269 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2270 MI.getOperand(1).isReg())
2275 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
2276 MI.getOperand(2).getImm() == 0)
2280 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2281 MI.getOperand(1).isReg())
2285 case RISCV::SH1ADD_UW:
2287 case RISCV::SH2ADD_UW:
2289 case RISCV::SH3ADD_UW:
2290 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2291 MI.getOperand(2).isReg())
2294 case RISCV::FSGNJ_D:
2295 case RISCV::FSGNJ_S:
2296 case RISCV::FSGNJ_H:
2297 case RISCV::FSGNJ_D_INX:
2298 case RISCV::FSGNJ_D_IN32X:
2299 case RISCV::FSGNJ_S_INX:
2300 case RISCV::FSGNJ_H_INX:
2302 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2303 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
2307 return std::nullopt;
2315 const auto &SchedModel =
STI.getSchedModel();
2316 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
2328 RISCV::getNamedOperandIdx(Root.
getOpcode(), RISCV::OpName::frm);
2332 return RISCV::getNamedOperandIdx(
MI->getOpcode(),
2333 RISCV::OpName::frm) < 0;
2335 "New instructions require FRM whereas the old one does not have it");
2342 for (
auto *NewMI : InsInstrs) {
2344 if (
static_cast<unsigned>(RISCV::getNamedOperandIdx(
2345 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
2387bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
2388 bool Invert)
const {
2389#define OPCODE_LMUL_CASE(OPC) \
2390 case RISCV::OPC##_M1: \
2391 case RISCV::OPC##_M2: \
2392 case RISCV::OPC##_M4: \
2393 case RISCV::OPC##_M8: \
2394 case RISCV::OPC##_MF2: \
2395 case RISCV::OPC##_MF4: \
2396 case RISCV::OPC##_MF8
2398#define OPCODE_LMUL_MASK_CASE(OPC) \
2399 case RISCV::OPC##_M1_MASK: \
2400 case RISCV::OPC##_M2_MASK: \
2401 case RISCV::OPC##_M4_MASK: \
2402 case RISCV::OPC##_M8_MASK: \
2403 case RISCV::OPC##_MF2_MASK: \
2404 case RISCV::OPC##_MF4_MASK: \
2405 case RISCV::OPC##_MF8_MASK
2410 Opcode = *InvOpcode;
2427#undef OPCODE_LMUL_MASK_CASE
2428#undef OPCODE_LMUL_CASE
2431bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
2444 auto checkImmOperand = [&](
unsigned OpIdx) {
2448 auto checkRegOperand = [&](
unsigned OpIdx) {
2456 if (!checkRegOperand(1))
2471 bool SeenMI2 =
false;
2472 for (
auto End =
MBB->
rend(), It = It1; It != End; ++It) {
2481 if (It->modifiesRegister(RISCV::V0,
TRI)) {
2482 Register SrcReg = It->getOperand(1).getReg();
2500 if (MI1VReg != SrcReg)
2509 assert(SeenMI2 &&
"Prev is expected to appear before Root");
2520 const MachineOperand &Op1 = Root.
getOperand(OpIdx);
2521 const MachineOperand &Op2 = Prev.
getOperand(OpIdx);
2549bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
2550 bool &Commuted)
const {
2554 "Expect the present of passthrough operand.");
2560 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
2561 areRVVInstsReassociable(Inst, *MI2);
2565 return areRVVInstsReassociable(Inst, *MI1) &&
2566 (isVectorAssociativeAndCommutative(*MI1) ||
2567 isVectorAssociativeAndCommutative(*MI1,
true)) &&
2574 if (!isVectorAssociativeAndCommutative(Inst) &&
2575 !isVectorAssociativeAndCommutative(Inst,
true))
2601 for (
unsigned I = 0;
I < 5; ++
I)
2607 bool &Commuted)
const {
2608 if (isVectorAssociativeAndCommutative(Inst) ||
2609 isVectorAssociativeAndCommutative(Inst,
true))
2610 return hasReassociableVectorSibling(Inst, Commuted);
2616 unsigned OperandIdx = Commuted ? 2 : 1;
2620 int16_t InstFrmOpIdx =
2621 RISCV::getNamedOperandIdx(Inst.
getOpcode(), RISCV::OpName::frm);
2622 int16_t SiblingFrmOpIdx =
2623 RISCV::getNamedOperandIdx(Sibling.
getOpcode(), RISCV::OpName::frm);
2625 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
2630 bool Invert)
const {
2631 if (isVectorAssociativeAndCommutative(Inst, Invert))
2639 Opc = *InverseOpcode;
2684std::optional<unsigned>
2686#define RVV_OPC_LMUL_CASE(OPC, INV) \
2687 case RISCV::OPC##_M1: \
2688 return RISCV::INV##_M1; \
2689 case RISCV::OPC##_M2: \
2690 return RISCV::INV##_M2; \
2691 case RISCV::OPC##_M4: \
2692 return RISCV::INV##_M4; \
2693 case RISCV::OPC##_M8: \
2694 return RISCV::INV##_M8; \
2695 case RISCV::OPC##_MF2: \
2696 return RISCV::INV##_MF2; \
2697 case RISCV::OPC##_MF4: \
2698 return RISCV::INV##_MF4; \
2699 case RISCV::OPC##_MF8: \
2700 return RISCV::INV##_MF8
2702#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
2703 case RISCV::OPC##_M1_MASK: \
2704 return RISCV::INV##_M1_MASK; \
2705 case RISCV::OPC##_M2_MASK: \
2706 return RISCV::INV##_M2_MASK; \
2707 case RISCV::OPC##_M4_MASK: \
2708 return RISCV::INV##_M4_MASK; \
2709 case RISCV::OPC##_M8_MASK: \
2710 return RISCV::INV##_M8_MASK; \
2711 case RISCV::OPC##_MF2_MASK: \
2712 return RISCV::INV##_MF2_MASK; \
2713 case RISCV::OPC##_MF4_MASK: \
2714 return RISCV::INV##_MF4_MASK; \
2715 case RISCV::OPC##_MF8_MASK: \
2716 return RISCV::INV##_MF8_MASK
2720 return std::nullopt;
2722 return RISCV::FSUB_H;
2724 return RISCV::FSUB_S;
2726 return RISCV::FSUB_D;
2728 return RISCV::FADD_H;
2730 return RISCV::FADD_S;
2732 return RISCV::FADD_D;
2749#undef RVV_OPC_LMUL_MASK_CASE
2750#undef RVV_OPC_LMUL_CASE
2755 bool DoRegPressureReduce) {
2782 bool DoRegPressureReduce) {
2789 DoRegPressureReduce)) {
2795 DoRegPressureReduce)) {
2805 bool DoRegPressureReduce) {
2813 unsigned CombineOpc) {
2820 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2834 unsigned OuterShiftAmt) {
2840 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2867 case RISCV::SH1ADD_UW:
2869 case RISCV::SH2ADD_UW:
2871 case RISCV::SH3ADD_UW:
2917 bool DoRegPressureReduce)
const {
2926 DoRegPressureReduce);
2934 return RISCV::FMADD_H;
2936 return RISCV::FMADD_S;
2938 return RISCV::FMADD_D;
2983 bool Mul1IsKill = Mul1.
isKill();
2984 bool Mul2IsKill = Mul2.
isKill();
2985 bool AddendIsKill = Addend.
isKill();
2994 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
3019 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
3026 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
3029 switch (InnerShiftAmt - OuterShiftAmt) {
3033 InnerOpc = RISCV::ADD;
3036 InnerOpc = RISCV::SH1ADD;
3039 InnerOpc = RISCV::SH2ADD;
3042 InnerOpc = RISCV::SH3ADD;
3060 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
3077 DelInstrs, InstrIdxForVirtReg);
3104 for (
const auto &[Index, Operand] :
enumerate(
Desc.operands())) {
3106 unsigned OpType = Operand.OperandType;
3112 ErrInfo =
"Expected an immediate operand.";
3121#define CASE_OPERAND_UIMM(NUM) \
3122 case RISCVOp::OPERAND_UIMM##NUM: \
3123 Ok = isUInt<NUM>(Imm); \
3125#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX) \
3126 case RISCVOp::OPERAND_UIMM##BITS##_LSB##SUFFIX: { \
3127 constexpr size_t NumZeros = sizeof(#SUFFIX) - 1; \
3128 Ok = isShiftedUInt<BITS - NumZeros, NumZeros>(Imm); \
3131#define CASE_OPERAND_SIMM(NUM) \
3132 case RISCVOp::OPERAND_SIMM##NUM: \
3133 Ok = isInt<NUM>(Imm); \
3162 Ok =
Imm >= 1 &&
Imm <= 16;
3171 Ok =
Imm >= 1 &&
Imm <= 32;
3174 Ok =
Imm >= 1 &&
Imm <= 64;
3177 Ok =
Imm ==
STI.getXLen();
3213 Ok =
Imm >= -15 &&
Imm <= 16;
3241 Ok = Ok &&
Imm != 0;
3247 Ok =
Imm >= 0 &&
Imm <= 10;
3250 Ok =
Imm >= 0 &&
Imm <= 7;
3253 Ok =
Imm >= 1 &&
Imm <= 10;
3256 Ok =
Imm >= 2 &&
Imm <= 14;
3265 Ok =
Imm >= 0 &&
Imm <= 48 &&
Imm % 16 == 0;
3310 ErrInfo =
"Invalid immediate";
3319 ErrInfo =
"Expected a non-register operand.";
3323 ErrInfo =
"Invalid immediate";
3332 ErrInfo =
"Expected a non-register operand.";
3336 ErrInfo =
"Invalid immediate";
3344 ErrInfo =
"Expected a non-register operand.";
3348 ErrInfo =
"Invalid immediate";
3357 ErrInfo =
"Invalid immediate";
3360 }
else if (!MO.
isReg()) {
3361 ErrInfo =
"Expected a register or immediate operand.";
3367 ErrInfo =
"Expected a register or immediate operand.";
3374 const uint64_t TSFlags =
Desc.TSFlags;
3377 if (!
Op.isImm() && !
Op.isReg()) {
3378 ErrInfo =
"Invalid operand type for VL operand";
3381 if (
Op.isReg() &&
Op.getReg().isValid()) {
3384 if (!RISCV::GPRNoX0RegClass.hasSubClassEq(RC)) {
3385 ErrInfo =
"Invalid register class for VL operand";
3390 ErrInfo =
"VL operand w/o SEW operand?";
3396 if (!
MI.getOperand(OpIdx).isImm()) {
3397 ErrInfo =
"SEW value expected to be an immediate";
3400 uint64_t Log2SEW =
MI.getOperand(OpIdx).getImm();
3402 ErrInfo =
"Unexpected SEW value";
3405 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3407 ErrInfo =
"Unexpected SEW value";
3413 if (!
MI.getOperand(OpIdx).isImm()) {
3414 ErrInfo =
"Policy operand expected to be an immediate";
3417 uint64_t Policy =
MI.getOperand(OpIdx).getImm();
3419 ErrInfo =
"Invalid Policy Value";
3423 ErrInfo =
"policy operand w/o VL operand?";
3431 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
3432 ErrInfo =
"policy operand w/o tied operand?";
3439 !
MI.readsRegister(RISCV::FRM,
nullptr)) {
3440 ErrInfo =
"dynamic rounding mode should read FRM";
3462 case RISCV::LD_RV32:
3472 case RISCV::SD_RV32:
3488 int64_t NewOffset = OldOffset + Disp;
3510 "Addressing mode not supported for folding");
3583 case RISCV::LD_RV32:
3586 case RISCV::SD_RV32:
3593 OffsetIsScalable =
false;
3609 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
3617 if (MO1->getAddrSpace() != MO2->getAddrSpace())
3620 auto Base1 = MO1->getValue();
3621 auto Base2 = MO2->getValue();
3622 if (!Base1 || !Base2)
3630 return Base1 == Base2;
3636 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
3637 unsigned NumBytes)
const {
3640 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
3645 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
3651 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
3657 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
3707 int64_t OffsetA = 0, OffsetB = 0;
3713 int LowOffset = std::min(OffsetA, OffsetB);
3714 int HighOffset = std::max(OffsetA, OffsetB);
3715 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3717 LowOffset + (
int)LowWidth.
getValue() <= HighOffset)
3724std::pair<unsigned, unsigned>
3727 return std::make_pair(TF & Mask, TF & ~Mask);
3733 static const std::pair<unsigned, const char *> TargetFlags[] = {
3734 {MO_CALL,
"riscv-call"},
3735 {MO_LO,
"riscv-lo"},
3736 {MO_HI,
"riscv-hi"},
3737 {MO_PCREL_LO,
"riscv-pcrel-lo"},
3738 {MO_PCREL_HI,
"riscv-pcrel-hi"},
3739 {MO_GOT_HI,
"riscv-got-hi"},
3740 {MO_TPREL_LO,
"riscv-tprel-lo"},
3741 {MO_TPREL_HI,
"riscv-tprel-hi"},
3742 {MO_TPREL_ADD,
"riscv-tprel-add"},
3743 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
3744 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
3745 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
3746 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
3747 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
3748 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"},
3749 {MO_QC_ACCESS,
"riscv-qc-access"},
3758 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
3771 unsigned &Flags)
const {
3791 return F.getFnAttribute(
"fentry-call").getValueAsBool() ||
3792 F.hasFnAttribute(
"patchable-function-entry");
3797 return MI.readsRegister(RegNo,
TRI) ||
3798 MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
3803 return MI.modifiesRegister(RegNo,
TRI) ||
3804 MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
3808 if (!
MBB.back().isReturn())
3854 if (
C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
3855 C.isAvailableInsideSeq(
Reg,
TRI)) {
3873 if (
C.back().isReturn() &&
3874 !
C.isAvailableAcrossAndOutOfSeq(TailExpandUseReg, RegInfo)) {
3876 LLVM_DEBUG(
dbgs() <<
"Cannot be outlined between: " <<
C.front() <<
"and "
3878 LLVM_DEBUG(
dbgs() <<
"Because the tail-call register is live across "
3879 "the proposed outlined function call\n");
3885 if (
C.back().isReturn()) {
3887 "The candidate who uses return instruction must be outlined "
3894 if (!
C.isAvailableInsideSeq(RISCV::X5, RegInfo))
3898 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo))
3908std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3911 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3912 unsigned MinRepeats)
const {
3920 if (RepeatedSequenceLocs.size() < MinRepeats)
3921 return std::nullopt;
3925 unsigned InstrSizeCExt =
3927 unsigned CallOverhead = 0, FrameOverhead = 0;
3930 unsigned CFICount = 0;
3931 for (
auto &
I : Candidate) {
3932 if (
I.isCFIInstruction())
3943 std::vector<MCCFIInstruction> CFIInstructions =
3944 C.getMF()->getFrameInstructions();
3946 if (CFICount > 0 && CFICount != CFIInstructions.size())
3947 return std::nullopt;
3955 CallOverhead = 4 + InstrSizeCExt;
3962 FrameOverhead = InstrSizeCExt;
3968 return std::nullopt;
3972 for (
auto &
C : RepeatedSequenceLocs) {
3974 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo)) {
3976 unsigned CandCallOverhead = 8;
3981 unsigned CandCallOverhead = InstrSizeCExt + 8 + InstrSizeCExt;
3986 for (
auto &
C : RepeatedSequenceLocs)
3987 C.setCallInfo(MOCI, CallOverhead);
3990 unsigned SequenceSize = 0;
3991 for (
auto &
MI : Candidate)
3994 return std::make_unique<outliner::OutlinedFunction>(
3995 RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
4001 unsigned Flags)
const {
4005 MBB->getParent()->getSubtarget().getRegisterInfo();
4006 const auto &
F =
MI.getMF()->getFunction();
4011 if (
MI.isCFIInstruction())
4019 for (
const auto &MO :
MI.operands()) {
4024 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
4025 F.hasSection() ||
F.getSectionPrefix()))
4042 MBB.addLiveIn(RISCV::X5);
4061 .addGlobalAddress(M.getNamedValue(MF.
getName()),
4068 assert(SaveReg &&
"Cannot find an available register to save/restore X5.");
4079 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4095 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4103 bool AllowSideEffects)
const {
4108 if (
TRI.isGeneralPurposeRegister(MF, Reg)) {
4110 }
else if (RISCV::FPR32RegClass.
contains(Reg)) {
4112 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
4114 }
else if (RISCV::FPR128RegClass.
contains(Reg)) {
4116 }
else if (RISCV::VRRegClass.
contains(Reg)) {
4120 "buildClearRegister is not implemented for " +
TRI.getRegAsmName(Reg));
4130 return std::nullopt;
4134 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
4135 MI.getOperand(2).isImm())
4136 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
4138 return std::nullopt;
4146 std::string GenericComment =
4148 if (!GenericComment.empty())
4149 return GenericComment;
4152 if (OpIdx >=
Desc.getNumOperands())
4153 return std::string();
4155 std::string Comment;
4162 switch (OpInfo.OperandType) {
4165 unsigned Imm =
Op.getImm();
4170 unsigned Imm =
Op.getImm();
4175 unsigned Imm =
Op.getImm();
4181 unsigned Log2SEW =
Op.getImm();
4182 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
4188 unsigned Policy =
Op.getImm();
4190 "Invalid Policy Value");
4196 if (
Op.isImm() &&
Op.getImm() == -1)
4218#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
4219 RISCV::Pseudo##OP##_##LMUL
4221#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
4222 RISCV::Pseudo##OP##_##LMUL##_MASK
4224#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
4225 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
4226 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
4228#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
4229 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
4230 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
4231 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
4232 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
4233 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
4234 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
4236#define CASE_RVV_OPCODE_UNMASK(OP) \
4237 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4238 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
4240#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
4241 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
4242 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
4243 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
4244 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
4245 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
4246 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
4248#define CASE_RVV_OPCODE_MASK(OP) \
4249 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
4250 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
4252#define CASE_RVV_OPCODE_WIDEN(OP) \
4253 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4254 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
4256#define CASE_RVV_OPCODE(OP) \
4257 CASE_RVV_OPCODE_UNMASK(OP): \
4258 case CASE_RVV_OPCODE_MASK(OP)
4262#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
4263 RISCV::PseudoV##OP##_##TYPE##_##LMUL
4265#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
4266 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
4267 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
4268 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
4269 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
4270 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
4271 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
4272 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
4275#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
4276 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
4278#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
4279 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
4280 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
4281 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
4282 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
4284#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
4285 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
4286 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
4288#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
4289 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
4290 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
4292#define CASE_VFMA_OPCODE_VV(OP) \
4293 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
4294 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VV, E16): \
4295 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
4296 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
4298#define CASE_VFMA_SPLATS(OP) \
4299 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
4300 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VFPR16, E16): \
4301 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
4302 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
4306 unsigned &SrcOpIdx1,
4307 unsigned &SrcOpIdx2)
const {
4309 if (!
Desc.isCommutable())
4312 switch (
MI.getOpcode()) {
4313 case RISCV::TH_MVEQZ:
4314 case RISCV::TH_MVNEZ:
4318 if (
MI.getOperand(2).getReg() == RISCV::X0)
4321 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4322 case RISCV::QC_SELECTIEQ:
4323 case RISCV::QC_SELECTINE:
4324 case RISCV::QC_SELECTIIEQ:
4325 case RISCV::QC_SELECTIINE:
4326 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4327 case RISCV::QC_MVEQ:
4328 case RISCV::QC_MVNE:
4329 case RISCV::QC_MVLT:
4330 case RISCV::QC_MVGE:
4331 case RISCV::QC_MVLTU:
4332 case RISCV::QC_MVGEU:
4333 case RISCV::QC_MVEQI:
4334 case RISCV::QC_MVNEI:
4335 case RISCV::QC_MVLTI:
4336 case RISCV::QC_MVGEI:
4337 case RISCV::QC_MVLTUI:
4338 case RISCV::QC_MVGEUI:
4339 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 4);
4340 case RISCV::TH_MULA:
4341 case RISCV::TH_MULAW:
4342 case RISCV::TH_MULAH:
4343 case RISCV::TH_MULS:
4344 case RISCV::TH_MULSW:
4345 case RISCV::TH_MULSH:
4347 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4348 case RISCV::PseudoCCMOVGPRNoX0:
4349 case RISCV::PseudoCCMOVGPR:
4351 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4392 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4419 unsigned CommutableOpIdx1 = 1;
4420 unsigned CommutableOpIdx2 = 3;
4421 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4442 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
4444 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
4448 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
4449 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
4455 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
4456 SrcOpIdx2 == CommuteAnyOperandIndex) {
4459 unsigned CommutableOpIdx1 = SrcOpIdx1;
4460 if (SrcOpIdx1 == SrcOpIdx2) {
4463 CommutableOpIdx1 = 1;
4464 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
4466 CommutableOpIdx1 = SrcOpIdx2;
4471 unsigned CommutableOpIdx2;
4472 if (CommutableOpIdx1 != 1) {
4474 CommutableOpIdx2 = 1;
4476 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
4481 if (Op1Reg !=
MI.getOperand(2).getReg())
4482 CommutableOpIdx2 = 2;
4484 CommutableOpIdx2 = 3;
4489 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4502#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
4503 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
4504 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
4507#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
4508 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
4509 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
4510 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
4511 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
4512 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
4513 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
4514 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
4517#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
4518 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
4519 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
4522#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
4523 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
4524 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
4525 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
4526 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
4528#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
4529 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
4530 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
4532#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
4533 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
4534 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
4536#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
4537 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
4538 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VV, E16) \
4539 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
4540 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
4542#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
4543 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
4544 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VFPR16, E16) \
4545 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
4546 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
4552 unsigned OpIdx2)
const {
4555 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
4559 switch (
MI.getOpcode()) {
4560 case RISCV::TH_MVEQZ:
4561 case RISCV::TH_MVNEZ: {
4562 auto &WorkingMI = cloneIfNew(
MI);
4563 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
4564 : RISCV::TH_MVEQZ));
4568 case RISCV::QC_SELECTIEQ:
4569 case RISCV::QC_SELECTINE:
4570 case RISCV::QC_SELECTIIEQ:
4571 case RISCV::QC_SELECTIINE:
4573 case RISCV::QC_MVEQ:
4574 case RISCV::QC_MVNE:
4575 case RISCV::QC_MVLT:
4576 case RISCV::QC_MVGE:
4577 case RISCV::QC_MVLTU:
4578 case RISCV::QC_MVGEU:
4579 case RISCV::QC_MVEQI:
4580 case RISCV::QC_MVNEI:
4581 case RISCV::QC_MVLTI:
4582 case RISCV::QC_MVGEI:
4583 case RISCV::QC_MVLTUI:
4584 case RISCV::QC_MVGEUI: {
4585 auto &WorkingMI = cloneIfNew(
MI);
4590 case RISCV::PseudoCCMOVGPRNoX0:
4591 case RISCV::PseudoCCMOVGPR: {
4593 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
4595 auto &WorkingMI = cloneIfNew(
MI);
4596 WorkingMI.getOperand(
MI.getNumExplicitOperands() - 3).setImm(BCC);
4620 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4621 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
4623 switch (
MI.getOpcode()) {
4646 auto &WorkingMI = cloneIfNew(
MI);
4647 WorkingMI.setDesc(
get(
Opc));
4657 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4660 if (OpIdx1 == 3 || OpIdx2 == 3) {
4662 switch (
MI.getOpcode()) {
4673 auto &WorkingMI = cloneIfNew(
MI);
4674 WorkingMI.setDesc(
get(
Opc));
4686#undef CASE_VMA_CHANGE_OPCODE_COMMON
4687#undef CASE_VMA_CHANGE_OPCODE_LMULS
4688#undef CASE_VFMA_CHANGE_OPCODE_COMMON
4689#undef CASE_VFMA_CHANGE_OPCODE_LMULS_M1
4690#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF2
4691#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF4
4692#undef CASE_VFMA_CHANGE_OPCODE_VV
4693#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
4695#undef CASE_RVV_OPCODE_UNMASK_LMUL
4696#undef CASE_RVV_OPCODE_MASK_LMUL
4697#undef CASE_RVV_OPCODE_LMUL
4698#undef CASE_RVV_OPCODE_UNMASK_WIDEN
4699#undef CASE_RVV_OPCODE_UNMASK
4700#undef CASE_RVV_OPCODE_MASK_WIDEN
4701#undef CASE_RVV_OPCODE_MASK
4702#undef CASE_RVV_OPCODE_WIDEN
4703#undef CASE_RVV_OPCODE
4705#undef CASE_VMA_OPCODE_COMMON
4706#undef CASE_VMA_OPCODE_LMULS
4707#undef CASE_VFMA_OPCODE_COMMON
4708#undef CASE_VFMA_OPCODE_LMULS_M1
4709#undef CASE_VFMA_OPCODE_LMULS_MF2
4710#undef CASE_VFMA_OPCODE_LMULS_MF4
4711#undef CASE_VFMA_OPCODE_VV
4712#undef CASE_VFMA_SPLATS
4715 switch (
MI.getOpcode()) {
4723 if (
MI.getOperand(1).getReg() == RISCV::X0)
4724 commuteInstruction(
MI);
4726 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4727 MI.getOperand(2).ChangeToImmediate(0);
4728 MI.setDesc(
get(RISCV::ADDI));
4732 if (
MI.getOpcode() == RISCV::XOR &&
4733 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4734 MI.getOperand(1).setReg(RISCV::X0);
4735 MI.getOperand(2).ChangeToImmediate(0);
4736 MI.setDesc(
get(RISCV::ADDI));
4743 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4744 MI.setDesc(
get(RISCV::ADDI));
4750 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4751 MI.getOperand(2).ChangeToImmediate(0);
4752 MI.setDesc(
get(RISCV::ADDI));
4758 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4759 MI.getOperand(2).ChangeToImmediate(0);
4760 MI.setDesc(
get(RISCV::ADDIW));
4767 if (
MI.getOperand(1).getReg() == RISCV::X0)
4768 commuteInstruction(
MI);
4770 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4771 MI.getOperand(2).ChangeToImmediate(0);
4772 MI.setDesc(
get(RISCV::ADDIW));
4777 case RISCV::SH1ADD_UW:
4779 case RISCV::SH2ADD_UW:
4781 case RISCV::SH3ADD_UW:
4783 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4784 MI.removeOperand(1);
4786 MI.setDesc(
get(RISCV::ADDI));
4790 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4791 MI.removeOperand(2);
4792 unsigned Opc =
MI.getOpcode();
4793 if (
Opc == RISCV::SH1ADD_UW ||
Opc == RISCV::SH2ADD_UW ||
4794 Opc == RISCV::SH3ADD_UW) {
4796 MI.setDesc(
get(RISCV::SLLI_UW));
4800 MI.setDesc(
get(RISCV::SLLI));
4814 if (
MI.getOperand(1).getReg() == RISCV::X0 ||
4815 MI.getOperand(2).getReg() == RISCV::X0) {
4816 MI.getOperand(1).setReg(RISCV::X0);
4817 MI.getOperand(2).ChangeToImmediate(0);
4818 MI.setDesc(
get(RISCV::ADDI));
4824 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4825 MI.getOperand(2).setImm(0);
4826 MI.setDesc(
get(RISCV::ADDI));
4834 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4835 MI.getOperand(2).ChangeToImmediate(0);
4836 MI.setDesc(
get(RISCV::ADDI));
4840 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4841 MI.getOperand(2).ChangeToImmediate(0);
4842 MI.setDesc(
get(RISCV::ADDI));
4850 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4851 MI.getOperand(2).ChangeToImmediate(0);
4852 MI.setDesc(
get(RISCV::ADDI));
4862 case RISCV::SLLI_UW:
4864 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4865 MI.getOperand(2).setImm(0);
4866 MI.setDesc(
get(RISCV::ADDI));
4874 if (
MI.getOperand(1).getReg() == RISCV::X0 &&
4875 MI.getOperand(2).getReg() == RISCV::X0) {
4876 MI.getOperand(2).ChangeToImmediate(0);
4877 MI.setDesc(
get(RISCV::ADDI));
4881 if (
MI.getOpcode() == RISCV::ADD_UW &&
4882 MI.getOperand(1).getReg() == RISCV::X0) {
4883 MI.removeOperand(1);
4885 MI.setDesc(
get(RISCV::ADDI));
4891 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4892 MI.getOperand(2).setImm(
MI.getOperand(2).getImm() != 0);
4893 MI.setDesc(
get(RISCV::ADDI));
4899 case RISCV::ZEXT_H_RV32:
4900 case RISCV::ZEXT_H_RV64:
4903 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4905 MI.setDesc(
get(RISCV::ADDI));
4914 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4915 MI.getOperand(2).ChangeToImmediate(0);
4916 MI.setDesc(
get(RISCV::ADDI));
4923 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4925 MI.removeOperand(0);
4926 MI.insert(
MI.operands_begin() + 1, {MO0});
4931 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4933 MI.removeOperand(0);
4934 MI.insert(
MI.operands_begin() + 1, {MO0});
4935 MI.setDesc(
get(RISCV::BNE));
4940 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4942 MI.removeOperand(0);
4943 MI.insert(
MI.operands_begin() + 1, {MO0});
4944 MI.setDesc(
get(RISCV::BEQ));
4952#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
4953 RISCV::PseudoV##OP##_##LMUL##_TIED
4955#define CASE_WIDEOP_OPCODE_LMULS(OP) \
4956 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
4957 case CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
4958 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
4959 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
4960 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
4961 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
4963#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
4964 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
4965 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
4968#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4969 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
4970 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
4971 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
4972 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
4973 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
4974 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
4977#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
4978 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
4980#define CASE_FP_WIDEOP_OPCODE_LMULS(OP) \
4981 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4982 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4983 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
4984 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4985 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
4986 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4987 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
4988 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
4989 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
4991#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
4992 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
4993 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
4996#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4997 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4998 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4999 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
5000 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
5001 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
5002 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
5003 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
5004 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
5005 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
5007#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP) \
5008 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
5009 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
5010 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
5011 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
5012 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16)
5014#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP) \
5015 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
5016 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
5017 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
5018 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
5019 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16)
5026 switch (
MI.getOpcode()) {
5034 MI.getNumExplicitOperands() == 7 &&
5035 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
5042 switch (
MI.getOpcode()) {
5054 .
add(
MI.getOperand(0))
5056 .
add(
MI.getOperand(1))
5057 .
add(
MI.getOperand(2))
5058 .
add(
MI.getOperand(3))
5059 .
add(
MI.getOperand(4))
5060 .
add(
MI.getOperand(5))
5061 .
add(
MI.getOperand(6));
5070 MI.getNumExplicitOperands() == 6);
5077 switch (
MI.getOpcode()) {
5089 .
add(
MI.getOperand(0))
5091 .
add(
MI.getOperand(1))
5092 .
add(
MI.getOperand(2))
5093 .
add(
MI.getOperand(3))
5094 .
add(
MI.getOperand(4))
5095 .
add(
MI.getOperand(5));
5102 unsigned NumOps =
MI.getNumOperands();
5105 if (
Op.isReg() &&
Op.isKill())
5113 if (
MI.getOperand(0).isEarlyClobber()) {
5127#undef CASE_WIDEOP_OPCODE_COMMON
5128#undef CASE_WIDEOP_OPCODE_LMULS
5129#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
5130#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
5131#undef CASE_FP_WIDEOP_OPCODE_COMMON
5132#undef CASE_FP_WIDEOP_OPCODE_LMULS
5133#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
5134#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
5143 if (ShiftAmount == 0)
5149 }
else if (
int ShXAmount, ShiftAmount;
5151 (ShXAmount =
isShifted359(Amount, ShiftAmount)) != 0) {
5154 switch (ShXAmount) {
5156 Opc = RISCV::SH1ADD;
5159 Opc = RISCV::SH2ADD;
5162 Opc = RISCV::SH3ADD;
5198 }
else if (
STI.hasStdExtZmmul()) {
5208 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
5209 if (Amount & (1U << ShiftAmount)) {
5213 .
addImm(ShiftAmount - PrevShiftAmount)
5215 if (Amount >> (ShiftAmount + 1)) {
5229 PrevShiftAmount = ShiftAmount;
5232 assert(Acc &&
"Expected valid accumulator");
5242 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
5250 ?
STI.getTailDupAggressiveThreshold()
5257 unsigned Opcode =
MI.getOpcode();
5258 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
5267 return MI.isCopy() &&
MI.getOperand(0).getReg().isPhysical() &&
5269 TRI->getMinimalPhysRegClass(
MI.getOperand(0).getReg()));
5272std::optional<std::pair<unsigned, unsigned>>
5276 return std::nullopt;
5277 case RISCV::PseudoVSPILL2_M1:
5278 case RISCV::PseudoVRELOAD2_M1:
5279 return std::make_pair(2u, 1u);
5280 case RISCV::PseudoVSPILL2_M2:
5281 case RISCV::PseudoVRELOAD2_M2:
5282 return std::make_pair(2u, 2u);
5283 case RISCV::PseudoVSPILL2_M4:
5284 case RISCV::PseudoVRELOAD2_M4:
5285 return std::make_pair(2u, 4u);
5286 case RISCV::PseudoVSPILL3_M1:
5287 case RISCV::PseudoVRELOAD3_M1:
5288 return std::make_pair(3u, 1u);
5289 case RISCV::PseudoVSPILL3_M2:
5290 case RISCV::PseudoVRELOAD3_M2:
5291 return std::make_pair(3u, 2u);
5292 case RISCV::PseudoVSPILL4_M1:
5293 case RISCV::PseudoVRELOAD4_M1:
5294 return std::make_pair(4u, 1u);
5295 case RISCV::PseudoVSPILL4_M2:
5296 case RISCV::PseudoVRELOAD4_M2:
5297 return std::make_pair(4u, 2u);
5298 case RISCV::PseudoVSPILL5_M1:
5299 case RISCV::PseudoVRELOAD5_M1:
5300 return std::make_pair(5u, 1u);
5301 case RISCV::PseudoVSPILL6_M1:
5302 case RISCV::PseudoVRELOAD6_M1:
5303 return std::make_pair(6u, 1u);
5304 case RISCV::PseudoVSPILL7_M1:
5305 case RISCV::PseudoVRELOAD7_M1:
5306 return std::make_pair(7u, 1u);
5307 case RISCV::PseudoVSPILL8_M1:
5308 case RISCV::PseudoVRELOAD8_M1:
5309 return std::make_pair(8u, 1u);
5314 int16_t MI1FrmOpIdx =
5315 RISCV::getNamedOperandIdx(MI1.
getOpcode(), RISCV::OpName::frm);
5316 int16_t MI2FrmOpIdx =
5317 RISCV::getNamedOperandIdx(MI2.
getOpcode(), RISCV::OpName::frm);
5318 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
5325std::optional<unsigned>
5329 return std::nullopt;
5332 case RISCV::VSLL_VX:
5333 case RISCV::VSRL_VX:
5334 case RISCV::VSRA_VX:
5336 case RISCV::VSSRL_VX:
5337 case RISCV::VSSRA_VX:
5339 case RISCV::VROL_VX:
5340 case RISCV::VROR_VX:
5345 case RISCV::VNSRL_WX:
5346 case RISCV::VNSRA_WX:
5348 case RISCV::VNCLIPU_WX:
5349 case RISCV::VNCLIP_WX:
5351 case RISCV::VWSLL_VX:
5356 case RISCV::VADD_VX:
5357 case RISCV::VSUB_VX:
5358 case RISCV::VRSUB_VX:
5360 case RISCV::VWADDU_VX:
5361 case RISCV::VWSUBU_VX:
5362 case RISCV::VWADD_VX:
5363 case RISCV::VWSUB_VX:
5364 case RISCV::VWADDU_WX:
5365 case RISCV::VWSUBU_WX:
5366 case RISCV::VWADD_WX:
5367 case RISCV::VWSUB_WX:
5369 case RISCV::VADC_VXM:
5370 case RISCV::VADC_VIM:
5371 case RISCV::VMADC_VXM:
5372 case RISCV::VMADC_VIM:
5373 case RISCV::VMADC_VX:
5374 case RISCV::VSBC_VXM:
5375 case RISCV::VMSBC_VXM:
5376 case RISCV::VMSBC_VX:
5378 case RISCV::VAND_VX:
5380 case RISCV::VXOR_VX:
5382 case RISCV::VMSEQ_VX:
5383 case RISCV::VMSNE_VX:
5384 case RISCV::VMSLTU_VX:
5385 case RISCV::VMSLT_VX:
5386 case RISCV::VMSLEU_VX:
5387 case RISCV::VMSLE_VX:
5388 case RISCV::VMSGTU_VX:
5389 case RISCV::VMSGT_VX:
5391 case RISCV::VMINU_VX:
5392 case RISCV::VMIN_VX:
5393 case RISCV::VMAXU_VX:
5394 case RISCV::VMAX_VX:
5396 case RISCV::VMUL_VX:
5397 case RISCV::VMULH_VX:
5398 case RISCV::VMULHU_VX:
5399 case RISCV::VMULHSU_VX:
5401 case RISCV::VDIVU_VX:
5402 case RISCV::VDIV_VX:
5403 case RISCV::VREMU_VX:
5404 case RISCV::VREM_VX:
5406 case RISCV::VWMUL_VX:
5407 case RISCV::VWMULU_VX:
5408 case RISCV::VWMULSU_VX:
5410 case RISCV::VMACC_VX:
5411 case RISCV::VNMSAC_VX:
5412 case RISCV::VMADD_VX:
5413 case RISCV::VNMSUB_VX:
5415 case RISCV::VWMACCU_VX:
5416 case RISCV::VWMACC_VX:
5417 case RISCV::VWMACCSU_VX:
5418 case RISCV::VWMACCUS_VX:
5420 case RISCV::VMERGE_VXM:
5422 case RISCV::VMV_V_X:
5424 case RISCV::VSADDU_VX:
5425 case RISCV::VSADD_VX:
5426 case RISCV::VSSUBU_VX:
5427 case RISCV::VSSUB_VX:
5429 case RISCV::VAADDU_VX:
5430 case RISCV::VAADD_VX:
5431 case RISCV::VASUBU_VX:
5432 case RISCV::VASUB_VX:
5434 case RISCV::VSMUL_VX:
5436 case RISCV::VMV_S_X:
5438 case RISCV::VANDN_VX:
5439 return 1U << Log2SEW;
5445 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
5448 return RVV->BaseInstr;
5458 unsigned Scaled = Log2SEW + (DestEEW - 1);
5472 return std::nullopt;
5479 if (LHS.isReg() && RHS.isReg() && LHS.getReg().isVirtual() &&
5480 LHS.getReg() == RHS.getReg())
5484 if (LHS.isImm() && LHS.getImm() == 0)
5490 if (!LHSImm || !RHSImm)
5492 return LHSImm <= RHSImm;
5504 : LHS(LHS), RHS(RHS),
Cond(
Cond.begin(),
Cond.end()) {}
5506 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
5516 std::optional<bool> createTripCountGreaterCondition(
5517 int TC, MachineBasicBlock &
MBB,
5518 SmallVectorImpl<MachineOperand> &CondParam)
override {
5526 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
5528 void adjustTripCount(
int TripCountAdjust)
override {}
5532std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
5540 if (
TBB == LoopBB && FBB == LoopBB)
5547 assert((
TBB == LoopBB || FBB == LoopBB) &&
5548 "The Loop must be a single-basic-block loop");
5559 if (!Reg.isVirtual())
5566 if (LHS && LHS->isPHI())
5568 if (RHS && RHS->isPHI())
5571 return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS,
Cond);
5577 Opc = RVVMCOpcode ? RVVMCOpcode :
Opc;
5594 case RISCV::FDIV_H_INX:
5595 case RISCV::FDIV_S_INX:
5596 case RISCV::FDIV_D_INX:
5597 case RISCV::FDIV_D_IN32X:
5598 case RISCV::FSQRT_H:
5599 case RISCV::FSQRT_S:
5600 case RISCV::FSQRT_D:
5601 case RISCV::FSQRT_H_INX:
5602 case RISCV::FSQRT_S_INX:
5603 case RISCV::FSQRT_D_INX:
5604 case RISCV::FSQRT_D_IN32X:
5606 case RISCV::VDIV_VV:
5607 case RISCV::VDIV_VX:
5608 case RISCV::VDIVU_VV:
5609 case RISCV::VDIVU_VX:
5610 case RISCV::VREM_VV:
5611 case RISCV::VREM_VX:
5612 case RISCV::VREMU_VV:
5613 case RISCV::VREMU_VX:
5615 case RISCV::VFDIV_VV:
5616 case RISCV::VFDIV_VF:
5617 case RISCV::VFRDIV_VF:
5618 case RISCV::VFSQRT_V:
5619 case RISCV::VFRSQRT7_V:
5625 if (
MI->getOpcode() != TargetOpcode::COPY)
5630 Register DstReg =
MI->getOperand(0).getReg();
5633 :
TRI->getMinimalPhysRegClass(DstReg);
5643 auto [RCLMul, RCFractional] =
5645 return (!RCFractional && LMul == RCLMul) || (RCFractional && LMul == 1);
5649 if (
MI.memoperands_empty())
5664 if (MO.getReg().isPhysical())
5667 if (MO.getReg().isPhysical())
5669 bool SawStore =
false;
5672 if (
II->definesRegister(PhysReg,
nullptr))
5675 if (
II->definesRegister(PhysReg,
nullptr) ||
5676 II->readsRegister(PhysReg,
nullptr))
5678 II->isSafeToMove(SawStore);
MachineInstrBuilder MachineInstrBuilder & DefMI
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
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#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.
uint64_t IntrinsicInst * II
static std::optional< int64_t > getEffectiveImm(const MachineRegisterInfo &MRI, const MachineOperand &MO)
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 bool forwardCopyWillClobberTuple(unsigned DstReg, unsigned SrcReg, unsigned NumRegs)
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)
static int getJumpTableIndexFromLoadAddr(const MachineRegisterInfo &MRI, Register Reg)
#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)
#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)
static bool isJumpTableLoad(const MachineInstr &MI)
#define CASE_RVV_OPCODE_LMUL(OP, LMUL)
static int getJumpTableIndexFromBase(const MachineRegisterInfo &MRI, Register Reg)
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.
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...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const 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.
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 LLVM_READONLY 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 LLVM_READONLY 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
int getJumpTableIndex(const MachineInstr &MI) 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
bool hasCFProtectionBranch() 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.
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 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 isVLKnownLE(const MachineRegisterInfo &MRI, const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
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
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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)
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
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.