40#define GEN_CHECK_COMPRESS_INSTR
41#include "RISCVGenCompressInstEmitter.inc"
43#define GET_INSTRINFO_CTOR_DTOR
44#include "RISCVGenInstrInfo.inc"
46#define DEBUG_TYPE "riscv-instr-info"
48 "Number of registers within vector register groups spilled");
50 "Number of registers within vector register groups reloaded");
54 cl::desc(
"Prefer whole register move for vector registers."));
57 "riscv-force-machine-combiner-strategy",
cl::Hidden,
58 cl::desc(
"Force machine combiner to use a specific strategy for machine "
59 "trace metrics evaluation."),
64 "MinInstrCount strategy.")));
68 cl::desc(
"Enable RegSave strategy in machine outliner (save X5 to a "
69 "temporary register when X5 is live across outlined calls)."));
75#define GET_RISCVVPseudosTable_IMPL
76#include "RISCVGenSearchableTables.inc"
82#define GET_RISCVMaskedPseudosTable_IMPL
83#include "RISCVGenSearchableTables.inc"
89 RISCV::ADJCALLSTACKUP),
92#define GET_INSTRINFO_HELPERS
93#include "RISCVGenInstrInfo.inc"
96 if (
STI.hasStdExtZca())
105 int &FrameIndex)
const {
115 case RISCV::VL1RE8_V:
116 case RISCV::VL1RE16_V:
117 case RISCV::VL1RE32_V:
118 case RISCV::VL1RE64_V:
121 case RISCV::VL2RE8_V:
122 case RISCV::VL2RE16_V:
123 case RISCV::VL2RE32_V:
124 case RISCV::VL2RE64_V:
127 case RISCV::VL4RE8_V:
128 case RISCV::VL4RE16_V:
129 case RISCV::VL4RE32_V:
130 case RISCV::VL4RE64_V:
133 case RISCV::VL8RE8_V:
134 case RISCV::VL8RE16_V:
135 case RISCV::VL8RE32_V:
136 case RISCV::VL8RE64_V:
144 switch (
MI.getOpcode()) {
168 case RISCV::VL1RE8_V:
169 case RISCV::VL2RE8_V:
170 case RISCV::VL4RE8_V:
171 case RISCV::VL8RE8_V:
172 if (!
MI.getOperand(1).isFI())
174 FrameIndex =
MI.getOperand(1).getIndex();
177 return MI.getOperand(0).getReg();
180 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
181 MI.getOperand(2).getImm() == 0) {
182 FrameIndex =
MI.getOperand(1).getIndex();
183 return MI.getOperand(0).getReg();
190 int &FrameIndex)
const {
198 switch (
MI.getOpcode()) {
223 if (!
MI.getOperand(1).isFI())
225 FrameIndex =
MI.getOperand(1).getIndex();
228 return MI.getOperand(0).getReg();
231 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
232 MI.getOperand(2).getImm() == 0) {
233 FrameIndex =
MI.getOperand(1).getIndex();
234 return MI.getOperand(0).getReg();
244 case RISCV::VFMV_V_F:
247 case RISCV::VFMV_S_F:
249 return MI.getOperand(1).isUndef();
257 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
268 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
269 "Unexpected COPY instruction.");
273 bool FoundDef =
false;
274 bool FirstVSetVLI =
false;
275 unsigned FirstSEW = 0;
278 if (
MBBI->isMetaInstruction())
281 if (RISCVInstrInfo::isVectorConfigInstr(*
MBBI)) {
291 unsigned FirstVType =
MBBI->getOperand(2).getImm();
296 if (FirstLMul != LMul)
301 if (!RISCVInstrInfo::isVLPreservingConfig(*
MBBI))
307 unsigned VType =
MBBI->getOperand(2).getImm();
325 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
327 }
else if (
MBBI->getNumDefs()) {
330 if (
MBBI->modifiesRegister(RISCV::VL,
nullptr))
336 if (!MO.isReg() || !MO.isDef())
338 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
353 if (MO.getReg() != SrcReg)
394 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
395 uint16_t DstEncoding =
TRI->getEncodingValue(DstReg);
397 assert(!Fractional &&
"It is impossible be fractional lmul here.");
398 unsigned NumRegs = NF * LMulVal;
404 SrcEncoding += NumRegs - 1;
405 DstEncoding += NumRegs - 1;
409 auto GetCopyInfo = [&](uint16_t SrcEncoding, uint16_t DstEncoding)
411 unsigned,
unsigned> {
419 uint16_t Diff = DstEncoding - SrcEncoding;
420 if (
I + 8 <= NumRegs && Diff >= 8 && SrcEncoding % 8 == 7 &&
421 DstEncoding % 8 == 7)
423 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
424 if (
I + 4 <= NumRegs && Diff >= 4 && SrcEncoding % 4 == 3 &&
425 DstEncoding % 4 == 3)
427 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
428 if (
I + 2 <= NumRegs && Diff >= 2 && SrcEncoding % 2 == 1 &&
429 DstEncoding % 2 == 1)
431 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
434 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
439 if (
I + 8 <= NumRegs && SrcEncoding % 8 == 0 && DstEncoding % 8 == 0)
441 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
442 if (
I + 4 <= NumRegs && SrcEncoding % 4 == 0 && DstEncoding % 4 == 0)
444 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
445 if (
I + 2 <= NumRegs && SrcEncoding % 2 == 0 && DstEncoding % 2 == 0)
447 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
450 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
453 while (
I != NumRegs) {
458 auto [LMulCopied, RegClass,
Opc, VVOpc, VIOpc] =
459 GetCopyInfo(SrcEncoding, DstEncoding);
463 if (LMul == LMulCopied &&
466 if (DefMBBI->getOpcode() == VIOpc)
473 RegClass, ReversedCopy ? (SrcEncoding - NumCopied + 1) : SrcEncoding);
475 RegClass, ReversedCopy ? (DstEncoding - NumCopied + 1) : DstEncoding);
483 MIB = MIB.add(DefMBBI->getOperand(2));
491 MIB.addImm(Log2SEW ? Log2SEW : 3);
503 SrcEncoding += (ReversedCopy ? -NumCopied : NumCopied);
504 DstEncoding += (ReversedCopy ? -NumCopied : NumCopied);
513 bool RenamableDest,
bool RenamableSrc)
const {
517 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
525 if (SrcReg == RISCV::DUMMY_REG_PAIR_WITH_X0 &&
526 RISCV::GPRRegClass.
contains(DstReg)) {
533 if (RISCV::GPRF16RegClass.
contains(DstReg, SrcReg)) {
539 if (RISCV::GPRF32RegClass.
contains(DstReg, SrcReg)) {
545 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
546 if (!
STI.is64Bit()) {
547 if (
STI.hasStdExtZdinx()) {
556 if (
STI.hasStdExtP()) {
565 MCRegister EvenReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even);
566 MCRegister OddReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd);
568 if (OddReg == RISCV::DUMMY_REG_PAIR_WITH_X0)
570 assert(DstReg != RISCV::X0_Pair &&
"Cannot write to X0_Pair");
574 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
575 .
addReg(EvenReg, KillFlag)
578 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
585 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
586 RISCV::GPRRegClass.
contains(DstReg)) {
588 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
593 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
595 if (
STI.hasStdExtZfh()) {
596 Opc = RISCV::FSGNJ_H;
599 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
600 "Unexpected extensions");
602 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
603 &RISCV::FPR32RegClass);
604 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
605 &RISCV::FPR32RegClass);
606 Opc = RISCV::FSGNJ_S;
610 .
addReg(SrcReg, KillFlag);
614 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
617 .
addReg(SrcReg, KillFlag);
621 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
624 .
addReg(SrcReg, KillFlag);
628 if (RISCV::FPR32RegClass.
contains(DstReg) &&
629 RISCV::GPRRegClass.
contains(SrcReg)) {
631 .
addReg(SrcReg, KillFlag);
635 if (RISCV::GPRRegClass.
contains(DstReg) &&
636 RISCV::FPR32RegClass.
contains(SrcReg)) {
638 .
addReg(SrcReg, KillFlag);
642 if (RISCV::FPR64RegClass.
contains(DstReg) &&
643 RISCV::GPRRegClass.
contains(SrcReg)) {
644 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
646 .
addReg(SrcReg, KillFlag);
650 if (RISCV::GPRRegClass.
contains(DstReg) &&
651 RISCV::FPR64RegClass.
contains(SrcReg)) {
652 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
654 .
addReg(SrcReg, KillFlag);
660 TRI->getCommonMinimalPhysRegClass(SrcReg, DstReg);
671 Register SrcReg,
bool IsKill,
int FI,
680 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
681 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::SW
683 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
684 Opcode = RISCV::SH_INX;
685 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
686 Opcode = RISCV::SW_INX;
687 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
688 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
689 Alignment >=
STI.getZilsdAlign()) {
690 Opcode = RISCV::SD_RV32;
692 Opcode = RISCV::PseudoRV32ZdinxSD;
694 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
696 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
698 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
700 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
701 Opcode = RISCV::VS1R_V;
702 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
703 Opcode = RISCV::VS2R_V;
704 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
705 Opcode = RISCV::VS4R_V;
706 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
707 Opcode = RISCV::VS8R_V;
708 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
709 Opcode = RISCV::PseudoVSPILL2_M1;
710 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
711 Opcode = RISCV::PseudoVSPILL2_M2;
712 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
713 Opcode = RISCV::PseudoVSPILL2_M4;
714 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
715 Opcode = RISCV::PseudoVSPILL3_M1;
716 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
717 Opcode = RISCV::PseudoVSPILL3_M2;
718 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
719 Opcode = RISCV::PseudoVSPILL4_M1;
720 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
721 Opcode = RISCV::PseudoVSPILL4_M2;
722 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
723 Opcode = RISCV::PseudoVSPILL5_M1;
724 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
725 Opcode = RISCV::PseudoVSPILL6_M1;
726 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
727 Opcode = RISCV::PseudoVSPILL7_M1;
728 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
729 Opcode = RISCV::PseudoVSPILL8_M1;
772 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
773 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::LW
775 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
776 Opcode = RISCV::LH_INX;
777 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
778 Opcode = RISCV::LW_INX;
779 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
780 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
781 Alignment >=
STI.getZilsdAlign()) {
782 Opcode = RISCV::LD_RV32;
784 Opcode = RISCV::PseudoRV32ZdinxLD;
786 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
788 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
790 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
792 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
793 Opcode = RISCV::VL1RE8_V;
794 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
795 Opcode = RISCV::VL2RE8_V;
796 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
797 Opcode = RISCV::VL4RE8_V;
798 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
799 Opcode = RISCV::VL8RE8_V;
800 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
801 Opcode = RISCV::PseudoVRELOAD2_M1;
802 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
803 Opcode = RISCV::PseudoVRELOAD2_M2;
804 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
805 Opcode = RISCV::PseudoVRELOAD2_M4;
806 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
807 Opcode = RISCV::PseudoVRELOAD3_M1;
808 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
809 Opcode = RISCV::PseudoVRELOAD3_M2;
810 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
811 Opcode = RISCV::PseudoVRELOAD4_M1;
812 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
813 Opcode = RISCV::PseudoVRELOAD4_M2;
814 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
815 Opcode = RISCV::PseudoVRELOAD5_M1;
816 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
817 Opcode = RISCV::PseudoVRELOAD6_M1;
818 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
819 Opcode = RISCV::PseudoVRELOAD7_M1;
820 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
821 Opcode = RISCV::PseudoVRELOAD8_M1;
859 if (
Ops.size() != 1 ||
Ops[0] != 1)
862 switch (
MI.getOpcode()) {
864 if (RISCVInstrInfo::isSEXT_W(
MI))
866 if (RISCVInstrInfo::isZEXT_W(
MI))
868 if (RISCVInstrInfo::isZEXT_B(
MI))
875 case RISCV::ZEXT_H_RV32:
876 case RISCV::ZEXT_H_RV64:
883 case RISCV::VMV_X_S: {
886 if (ST.getXLen() < (1U << Log2SEW))
901 case RISCV::VFMV_F_S: {
929 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(*LoadOpc),
938 return RISCV::PseudoCCLB;
940 return RISCV::PseudoCCLBU;
942 return RISCV::PseudoCCLH;
944 return RISCV::PseudoCCLHU;
946 return RISCV::PseudoCCLW;
948 return RISCV::PseudoCCLWU;
950 return RISCV::PseudoCCLD;
952 return RISCV::PseudoCCQC_E_LB;
953 case RISCV::QC_E_LBU:
954 return RISCV::PseudoCCQC_E_LBU;
956 return RISCV::PseudoCCQC_E_LH;
957 case RISCV::QC_E_LHU:
958 return RISCV::PseudoCCQC_E_LHU;
960 return RISCV::PseudoCCQC_E_LW;
972 if (
MI.getOpcode() != RISCV::PseudoCCMOVGPR)
977 if (!
STI.hasShortForwardBranchILoad() || !PredOpc)
981 if (
Ops.size() != 1 || (
Ops[0] != 1 &&
Ops[0] != 2))
984 bool Invert =
Ops[0] == 2;
993 MI.getDebugLoc(),
get(PredOpc), DestReg);
1004 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
1010 NewMI.
add({
MI.getOperand(
MI.getNumExplicitOperands() - 2),
1011 MI.getOperand(
MI.getNumExplicitOperands() - 1)});
1020 bool DstIsDead)
const {
1036 bool SrcRenamable =
false;
1040 bool LastItem = ++Num == Seq.
size();
1045 switch (Inst.getOpndKind()) {
1048 .
addDef(DstReg, DstRegState)
1054 .
addDef(DstReg, DstRegState)
1055 .
addReg(SrcReg, SrcRegState)
1061 .
addDef(DstReg, DstRegState)
1062 .
addReg(SrcReg, SrcRegState)
1063 .
addReg(SrcReg, SrcRegState)
1068 .
addDef(DstReg, DstRegState)
1069 .
addReg(SrcReg, SrcRegState)
1077 SrcRenamable = DstRenamable;
1087 case RISCV::CV_BEQIMM:
1088 case RISCV::QC_BEQI:
1089 case RISCV::QC_E_BEQI:
1090 case RISCV::NDS_BBC:
1091 case RISCV::NDS_BEQC:
1095 case RISCV::QC_BNEI:
1096 case RISCV::QC_E_BNEI:
1097 case RISCV::CV_BNEIMM:
1098 case RISCV::NDS_BBS:
1099 case RISCV::NDS_BNEC:
1102 case RISCV::QC_BLTI:
1103 case RISCV::QC_E_BLTI:
1106 case RISCV::QC_BGEI:
1107 case RISCV::QC_E_BGEI:
1110 case RISCV::QC_BLTUI:
1111 case RISCV::QC_E_BLTUI:
1114 case RISCV::QC_BGEUI:
1115 case RISCV::QC_E_BGEUI:
1134 return (uint64_t)C0 < (uint64_t)C1;
1136 return (uint64_t)C0 >= (uint64_t)C1;
1147 "Unknown conditional branch");
1158 case RISCV::QC_MVEQ:
1159 return RISCV::QC_MVNE;
1160 case RISCV::QC_MVNE:
1161 return RISCV::QC_MVEQ;
1162 case RISCV::QC_MVLT:
1163 return RISCV::QC_MVGE;
1164 case RISCV::QC_MVGE:
1165 return RISCV::QC_MVLT;
1166 case RISCV::QC_MVLTU:
1167 return RISCV::QC_MVGEU;
1168 case RISCV::QC_MVGEU:
1169 return RISCV::QC_MVLTU;
1170 case RISCV::QC_MVEQI:
1171 return RISCV::QC_MVNEI;
1172 case RISCV::QC_MVNEI:
1173 return RISCV::QC_MVEQI;
1174 case RISCV::QC_MVLTI:
1175 return RISCV::QC_MVGEI;
1176 case RISCV::QC_MVGEI:
1177 return RISCV::QC_MVLTI;
1178 case RISCV::QC_MVLTUI:
1179 return RISCV::QC_MVGEUI;
1180 case RISCV::QC_MVGEUI:
1181 return RISCV::QC_MVLTUI;
1186 switch (SelectOpc) {
1205 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
1215 case RISCV::Select_GPR_Using_CC_SImm5_CV:
1220 return RISCV::CV_BEQIMM;
1222 return RISCV::CV_BNEIMM;
1225 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
1230 return RISCV::QC_BEQI;
1232 return RISCV::QC_BNEI;
1234 return RISCV::QC_BLTI;
1236 return RISCV::QC_BGEI;
1239 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
1244 return RISCV::QC_BLTUI;
1246 return RISCV::QC_BGEUI;
1249 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
1254 return RISCV::QC_E_BEQI;
1256 return RISCV::QC_E_BNEI;
1258 return RISCV::QC_E_BLTI;
1260 return RISCV::QC_E_BGEI;
1263 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
1268 return RISCV::QC_E_BLTUI;
1270 return RISCV::QC_E_BGEUI;
1273 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
1278 return RISCV::NDS_BBC;
1280 return RISCV::NDS_BBS;
1283 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
1288 return RISCV::NDS_BEQC;
1290 return RISCV::NDS_BNEC;
1336 case RISCV::CV_BEQIMM:
1337 return RISCV::CV_BNEIMM;
1338 case RISCV::CV_BNEIMM:
1339 return RISCV::CV_BEQIMM;
1340 case RISCV::QC_BEQI:
1341 return RISCV::QC_BNEI;
1342 case RISCV::QC_BNEI:
1343 return RISCV::QC_BEQI;
1344 case RISCV::QC_BLTI:
1345 return RISCV::QC_BGEI;
1346 case RISCV::QC_BGEI:
1347 return RISCV::QC_BLTI;
1348 case RISCV::QC_BLTUI:
1349 return RISCV::QC_BGEUI;
1350 case RISCV::QC_BGEUI:
1351 return RISCV::QC_BLTUI;
1352 case RISCV::QC_E_BEQI:
1353 return RISCV::QC_E_BNEI;
1354 case RISCV::QC_E_BNEI:
1355 return RISCV::QC_E_BEQI;
1356 case RISCV::QC_E_BLTI:
1357 return RISCV::QC_E_BGEI;
1358 case RISCV::QC_E_BGEI:
1359 return RISCV::QC_E_BLTI;
1360 case RISCV::QC_E_BLTUI:
1361 return RISCV::QC_E_BGEUI;
1362 case RISCV::QC_E_BGEUI:
1363 return RISCV::QC_E_BLTUI;
1364 case RISCV::NDS_BBC:
1365 return RISCV::NDS_BBS;
1366 case RISCV::NDS_BBS:
1367 return RISCV::NDS_BBC;
1368 case RISCV::NDS_BEQC:
1369 return RISCV::NDS_BNEC;
1370 case RISCV::NDS_BNEC:
1371 return RISCV::NDS_BEQC;
1379 bool AllowModify)
const {
1380 TBB = FBB =
nullptr;
1385 if (
I ==
MBB.end() || !isUnpredicatedTerminator(*
I))
1391 int NumTerminators = 0;
1392 for (
auto J =
I.getReverse(); J !=
MBB.rend() && isUnpredicatedTerminator(*J);
1395 if (J->getDesc().isUnconditionalBranch() ||
1396 J->getDesc().isIndirectBranch()) {
1403 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.end()) {
1404 while (std::next(FirstUncondOrIndirectBr) !=
MBB.end()) {
1405 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
1408 I = FirstUncondOrIndirectBr;
1412 if (
I->getDesc().isIndirectBranch())
1416 if (
I->isPreISelOpcode())
1420 if (NumTerminators > 2)
1424 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
1430 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
1436 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
1437 I->getDesc().isUnconditionalBranch()) {
1448 int *BytesRemoved)
const {
1455 if (!
I->getDesc().isUnconditionalBranch() &&
1456 !
I->getDesc().isConditionalBranch())
1462 I->eraseFromParent();
1466 if (
I ==
MBB.begin())
1469 if (!
I->getDesc().isConditionalBranch())
1475 I->eraseFromParent();
1488 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1490 "RISC-V branch conditions have two components!");
1524 assert(RS &&
"RegScavenger required for long branching");
1526 "new block should be inserted for expanding unconditional branch");
1529 "restore block should be inserted for restoring clobbered registers");
1538 "Branch offsets outside of the signed 32-bit range not supported");
1544 auto II =
MBB.end();
1550 RS->enterBasicBlockEnd(
MBB);
1557 RC = &RISCV::GPRX7RegClass;
1559 RS->scavengeRegisterBackwards(*RC,
MI.getIterator(),
1563 RS->setRegUsed(TmpGPR);
1568 TmpGPR =
STI.hasStdExtE() ? RISCV::X9 : RISCV::X27;
1574 if (FrameIndex == -1)
1579 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1582 MI.getOperand(1).setMBB(&RestoreBB);
1586 TRI->eliminateFrameIndex(RestoreBB.
back(),
1596 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1606 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1607 MI->getOperand(1).getReg() == RISCV::X0) {
1608 Imm =
MI->getOperand(2).getImm();
1613 if (
MI->getOpcode() == RISCV::BSETI &&
MI->getOperand(1).isReg() &&
1614 MI->getOperand(1).getReg() == RISCV::X0 &&
1615 MI->getOperand(2).getImm() == 11) {
1629 if (Reg == RISCV::X0) {
1634 if (!Reg.isVirtual())
1642 bool IsSigned =
false;
1643 bool IsEquality =
false;
1644 switch (
MI.getOpcode()) {
1680 MI.eraseFromParent();
1706 auto searchConst = [&](int64_t C1) ->
Register {
1708 auto DefC1 = std::find_if(++
II, E, [&](
const MachineInstr &
I) ->
bool {
1711 I.getOperand(0).getReg().isVirtual();
1714 return DefC1->getOperand(0).getReg();
1726 if (
isFromLoadImm(MRI, LHS, C0) && C0 != 0 && LHS.getReg().isVirtual() &&
1727 MRI.
hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
1729 if (
Register RegZ = searchConst(C0 + 1)) {
1737 MI.eraseFromParent();
1747 if (
isFromLoadImm(MRI, RHS, C0) && C0 != 0 && RHS.getReg().isVirtual() &&
1750 if (
Register RegZ = searchConst(C0 - 1)) {
1758 MI.eraseFromParent();
1768 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1770 int NumOp =
MI.getNumExplicitOperands();
1771 return MI.getOperand(NumOp - 1).getMBB();
1775 int64_t BrOffset)
const {
1776 unsigned XLen =
STI.getXLen();
1783 case RISCV::NDS_BBC:
1784 case RISCV::NDS_BBS:
1785 case RISCV::NDS_BEQC:
1786 case RISCV::NDS_BNEC:
1796 case RISCV::CV_BEQIMM:
1797 case RISCV::CV_BNEIMM:
1798 case RISCV::QC_BEQI:
1799 case RISCV::QC_BNEI:
1800 case RISCV::QC_BGEI:
1801 case RISCV::QC_BLTI:
1802 case RISCV::QC_BLTUI:
1803 case RISCV::QC_BGEUI:
1804 case RISCV::QC_E_BEQI:
1805 case RISCV::QC_E_BNEI:
1806 case RISCV::QC_E_BGEI:
1807 case RISCV::QC_E_BLTI:
1808 case RISCV::QC_E_BLTUI:
1809 case RISCV::QC_E_BGEUI:
1812 case RISCV::PseudoBR:
1814 case RISCV::PseudoJump:
1821 const PseudoSourceValue *PSV = MMO->getPseudoValue();
1822 return PSV && PSV->isJumpTable();
1830 if (!
Reg.isVirtual())
1838 return MO.getIndex();
1847 if (!
Reg.isVirtual())
1854 switch (
MI->getOpcode()) {
1890 if (
MI.getOpcode() != RISCV::PseudoBRIND &&
1891 MI.getOpcode() != RISCV::PseudoBRINDX7)
1895 if (!Reg.isVirtual())
1906 switch (Def->getOpcode()) {
1946 case RISCV::ADD:
return RISCV::PseudoCCADD;
1947 case RISCV::SUB:
return RISCV::PseudoCCSUB;
1948 case RISCV::SLL:
return RISCV::PseudoCCSLL;
1949 case RISCV::SRL:
return RISCV::PseudoCCSRL;
1950 case RISCV::SRA:
return RISCV::PseudoCCSRA;
1951 case RISCV::AND:
return RISCV::PseudoCCAND;
1952 case RISCV::OR:
return RISCV::PseudoCCOR;
1953 case RISCV::XOR:
return RISCV::PseudoCCXOR;
1954 case RISCV::MAX:
return RISCV::PseudoCCMAX;
1955 case RISCV::MAXU:
return RISCV::PseudoCCMAXU;
1956 case RISCV::MIN:
return RISCV::PseudoCCMIN;
1957 case RISCV::MINU:
return RISCV::PseudoCCMINU;
1958 case RISCV::MUL:
return RISCV::PseudoCCMUL;
1959 case RISCV::LUI:
return RISCV::PseudoCCLUI;
1960 case RISCV::QC_LI:
return RISCV::PseudoCCQC_LI;
1961 case RISCV::QC_E_LI:
return RISCV::PseudoCCQC_E_LI;
1963 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
1964 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
1965 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
1966 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
1967 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
1968 case RISCV::ORI:
return RISCV::PseudoCCORI;
1969 case RISCV::XORI:
return RISCV::PseudoCCXORI;
1971 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
1972 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
1973 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
1974 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
1975 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
1977 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
1978 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
1979 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
1980 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
1982 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
1983 case RISCV::ORN:
return RISCV::PseudoCCORN;
1984 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
1986 case RISCV::NDS_BFOS:
return RISCV::PseudoCCNDS_BFOS;
1987 case RISCV::NDS_BFOZ:
return RISCV::PseudoCCNDS_BFOZ;
1991 return RISCV::INSTRUCTION_LIST_END;
2000 if (!
Reg.isVirtual())
2008 if (!STI.hasShortForwardBranchIMinMax() &&
2009 (
MI->getOpcode() == RISCV::MAX ||
MI->getOpcode() == RISCV::MIN ||
2010 MI->getOpcode() == RISCV::MINU ||
MI->getOpcode() == RISCV::MAXU))
2013 if (!STI.hasShortForwardBranchIMul() &&
MI->getOpcode() == RISCV::MUL)
2020 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
2021 MI->getOperand(1).getReg() == RISCV::X0)
2026 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2039 bool DontMoveAcrossStores =
true;
2040 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2048 bool PreferFalse)
const {
2049 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
2050 "Unknown select instruction");
2051 if (!
STI.hasShortForwardBranchIALU())
2057 bool Invert = !
DefMI;
2065 Register DestReg =
MI.getOperand(0).getReg();
2071 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
2078 NewMI.
add(FalseReg);
2086 unsigned BCCOpcode =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
2092 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 2));
2093 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 1));
2103 if (
DefMI->getParent() !=
MI.getParent())
2107 DefMI->eraseFromParent();
2112 if (
MI.isMetaInstruction())
2115 unsigned Opcode =
MI.getOpcode();
2117 if (Opcode == TargetOpcode::INLINEASM ||
2118 Opcode == TargetOpcode::INLINEASM_BR) {
2120 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
2125 if (
STI.hasStdExtZca()) {
2126 if (
unsigned Size = getCompressedSize(
MI,
STI))
2133 if (Opcode == TargetOpcode::BUNDLE)
2134 return getInstBundleSize(
MI);
2136 if (
MI.getParent() &&
MI.getParent()->getParent()) {
2137 if (
unsigned Size = getCompressedSize(
MI,
STI))
2142 case RISCV::PseudoMV_FPR16INX:
2143 case RISCV::PseudoMV_FPR32INX:
2144 case RISCV::PseudoClearGPR:
2146 return STI.hasStdExtZca() ? 2 : 4;
2148 case RISCV::PseudoCCMOVGPRNoX0:
2149 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2152 case RISCV::PseudoCCMOVGPR:
2153 case RISCV::PseudoCCADD:
2154 case RISCV::PseudoCCSUB:
2155 case RISCV::PseudoCCSLL:
2156 case RISCV::PseudoCCSRL:
2157 case RISCV::PseudoCCSRA:
2158 case RISCV::PseudoCCAND:
2159 case RISCV::PseudoCCOR:
2160 case RISCV::PseudoCCXOR:
2161 case RISCV::PseudoCCADDI:
2162 case RISCV::PseudoCCANDI:
2163 case RISCV::PseudoCCORI:
2164 case RISCV::PseudoCCXORI:
2165 case RISCV::PseudoCCLUI:
2166 case RISCV::PseudoCCSLLI:
2167 case RISCV::PseudoCCSRLI:
2168 case RISCV::PseudoCCSRAI:
2169 case RISCV::PseudoCCADDW:
2170 case RISCV::PseudoCCSUBW:
2171 case RISCV::PseudoCCSLLW:
2172 case RISCV::PseudoCCSRLW:
2173 case RISCV::PseudoCCSRAW:
2174 case RISCV::PseudoCCADDIW:
2175 case RISCV::PseudoCCSLLIW:
2176 case RISCV::PseudoCCSRLIW:
2177 case RISCV::PseudoCCSRAIW:
2178 case RISCV::PseudoCCANDN:
2179 case RISCV::PseudoCCORN:
2180 case RISCV::PseudoCCXNOR:
2181 case RISCV::PseudoCCMAX:
2182 case RISCV::PseudoCCMIN:
2183 case RISCV::PseudoCCMAXU:
2184 case RISCV::PseudoCCMINU:
2185 case RISCV::PseudoCCMUL:
2186 case RISCV::PseudoCCLB:
2187 case RISCV::PseudoCCLH:
2188 case RISCV::PseudoCCLW:
2189 case RISCV::PseudoCCLHU:
2190 case RISCV::PseudoCCLBU:
2191 case RISCV::PseudoCCLWU:
2192 case RISCV::PseudoCCLD:
2193 case RISCV::PseudoCCQC_LI:
2194 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2197 case RISCV::PseudoCCQC_E_LI:
2198 case RISCV::PseudoCCQC_E_LB:
2199 case RISCV::PseudoCCQC_E_LH:
2200 case RISCV::PseudoCCQC_E_LW:
2201 case RISCV::PseudoCCQC_E_LHU:
2202 case RISCV::PseudoCCQC_E_LBU:
2203 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2206 case TargetOpcode::STACKMAP:
2209 case TargetOpcode::PATCHPOINT:
2212 case TargetOpcode::STATEPOINT: {
2216 return std::max(NumBytes, 8U);
2218 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2219 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2220 case TargetOpcode::PATCHABLE_TAIL_CALL: {
2223 if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
2224 F.hasFnAttribute(
"patchable-function-entry")) {
2226 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
2228 return (
STI.hasStdExtZca() ? 2 : 4) * Num;
2232 return STI.is64Bit() ? 68 : 44;
2235 return get(Opcode).getSize();
2240 const unsigned Opcode =
MI.getOpcode();
2244 case RISCV::FSGNJ_D:
2245 case RISCV::FSGNJ_S:
2246 case RISCV::FSGNJ_H:
2247 case RISCV::FSGNJ_D_INX:
2248 case RISCV::FSGNJ_D_IN32X:
2249 case RISCV::FSGNJ_S_INX:
2250 case RISCV::FSGNJ_H_INX:
2252 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2253 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
2257 return (
MI.getOperand(1).isReg() &&
2258 MI.getOperand(1).getReg() == RISCV::X0) ||
2259 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
2261 return MI.isAsCheapAsAMove();
2264std::optional<DestSourcePair>
2268 switch (
MI.getOpcode()) {
2274 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2275 MI.getOperand(2).isReg())
2277 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2278 MI.getOperand(1).isReg())
2283 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
2284 MI.getOperand(2).getImm() == 0)
2288 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2289 MI.getOperand(1).isReg())
2293 case RISCV::SH1ADD_UW:
2295 case RISCV::SH2ADD_UW:
2297 case RISCV::SH3ADD_UW:
2298 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2299 MI.getOperand(2).isReg())
2302 case RISCV::FSGNJ_D:
2303 case RISCV::FSGNJ_S:
2304 case RISCV::FSGNJ_H:
2305 case RISCV::FSGNJ_D_INX:
2306 case RISCV::FSGNJ_D_IN32X:
2307 case RISCV::FSGNJ_S_INX:
2308 case RISCV::FSGNJ_H_INX:
2310 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2311 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
2315 return std::nullopt;
2323 const auto &SchedModel =
STI.getSchedModel();
2324 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
2336 RISCV::getNamedOperandIdx(Root.
getOpcode(), RISCV::OpName::frm);
2340 return RISCV::getNamedOperandIdx(
MI->getOpcode(),
2341 RISCV::OpName::frm) < 0;
2343 "New instructions require FRM whereas the old one does not have it");
2350 for (
auto *NewMI : InsInstrs) {
2352 if (
static_cast<unsigned>(RISCV::getNamedOperandIdx(
2353 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
2395bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
2396 bool Invert)
const {
2397#define OPCODE_LMUL_CASE(OPC) \
2398 case RISCV::OPC##_M1: \
2399 case RISCV::OPC##_M2: \
2400 case RISCV::OPC##_M4: \
2401 case RISCV::OPC##_M8: \
2402 case RISCV::OPC##_MF2: \
2403 case RISCV::OPC##_MF4: \
2404 case RISCV::OPC##_MF8
2406#define OPCODE_LMUL_MASK_CASE(OPC) \
2407 case RISCV::OPC##_M1_MASK: \
2408 case RISCV::OPC##_M2_MASK: \
2409 case RISCV::OPC##_M4_MASK: \
2410 case RISCV::OPC##_M8_MASK: \
2411 case RISCV::OPC##_MF2_MASK: \
2412 case RISCV::OPC##_MF4_MASK: \
2413 case RISCV::OPC##_MF8_MASK
2418 Opcode = *InvOpcode;
2435#undef OPCODE_LMUL_MASK_CASE
2436#undef OPCODE_LMUL_CASE
2439bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
2452 auto checkImmOperand = [&](
unsigned OpIdx) {
2456 auto checkRegOperand = [&](
unsigned OpIdx) {
2464 if (!checkRegOperand(1))
2479 bool SeenMI2 =
false;
2480 for (
auto End =
MBB->
rend(), It = It1; It != End; ++It) {
2489 if (It->modifiesRegister(RISCV::V0,
TRI)) {
2490 Register SrcReg = It->getOperand(1).getReg();
2508 if (MI1VReg != SrcReg)
2517 assert(SeenMI2 &&
"Prev is expected to appear before Root");
2528 const MachineOperand &Op1 = Root.
getOperand(OpIdx);
2529 const MachineOperand &Op2 = Prev.
getOperand(OpIdx);
2557bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
2558 bool &Commuted)
const {
2562 "Expect the present of passthrough operand.");
2568 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
2569 areRVVInstsReassociable(Inst, *MI2);
2573 return areRVVInstsReassociable(Inst, *MI1) &&
2574 (isVectorAssociativeAndCommutative(*MI1) ||
2575 isVectorAssociativeAndCommutative(*MI1,
true)) &&
2582 if (!isVectorAssociativeAndCommutative(Inst) &&
2583 !isVectorAssociativeAndCommutative(Inst,
true))
2609 for (
unsigned I = 0;
I < 5; ++
I)
2615 bool &Commuted)
const {
2616 if (isVectorAssociativeAndCommutative(Inst) ||
2617 isVectorAssociativeAndCommutative(Inst,
true))
2618 return hasReassociableVectorSibling(Inst, Commuted);
2624 unsigned OperandIdx = Commuted ? 2 : 1;
2628 int16_t InstFrmOpIdx =
2629 RISCV::getNamedOperandIdx(Inst.
getOpcode(), RISCV::OpName::frm);
2630 int16_t SiblingFrmOpIdx =
2631 RISCV::getNamedOperandIdx(Sibling.
getOpcode(), RISCV::OpName::frm);
2633 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
2638 bool Invert)
const {
2639 if (isVectorAssociativeAndCommutative(Inst, Invert))
2647 Opc = *InverseOpcode;
2692std::optional<unsigned>
2694#define RVV_OPC_LMUL_CASE(OPC, INV) \
2695 case RISCV::OPC##_M1: \
2696 return RISCV::INV##_M1; \
2697 case RISCV::OPC##_M2: \
2698 return RISCV::INV##_M2; \
2699 case RISCV::OPC##_M4: \
2700 return RISCV::INV##_M4; \
2701 case RISCV::OPC##_M8: \
2702 return RISCV::INV##_M8; \
2703 case RISCV::OPC##_MF2: \
2704 return RISCV::INV##_MF2; \
2705 case RISCV::OPC##_MF4: \
2706 return RISCV::INV##_MF4; \
2707 case RISCV::OPC##_MF8: \
2708 return RISCV::INV##_MF8
2710#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
2711 case RISCV::OPC##_M1_MASK: \
2712 return RISCV::INV##_M1_MASK; \
2713 case RISCV::OPC##_M2_MASK: \
2714 return RISCV::INV##_M2_MASK; \
2715 case RISCV::OPC##_M4_MASK: \
2716 return RISCV::INV##_M4_MASK; \
2717 case RISCV::OPC##_M8_MASK: \
2718 return RISCV::INV##_M8_MASK; \
2719 case RISCV::OPC##_MF2_MASK: \
2720 return RISCV::INV##_MF2_MASK; \
2721 case RISCV::OPC##_MF4_MASK: \
2722 return RISCV::INV##_MF4_MASK; \
2723 case RISCV::OPC##_MF8_MASK: \
2724 return RISCV::INV##_MF8_MASK
2728 return std::nullopt;
2730 return RISCV::FSUB_H;
2732 return RISCV::FSUB_S;
2734 return RISCV::FSUB_D;
2736 return RISCV::FADD_H;
2738 return RISCV::FADD_S;
2740 return RISCV::FADD_D;
2757#undef RVV_OPC_LMUL_MASK_CASE
2758#undef RVV_OPC_LMUL_CASE
2763 bool DoRegPressureReduce) {
2790 bool DoRegPressureReduce) {
2797 DoRegPressureReduce)) {
2803 DoRegPressureReduce)) {
2813 bool DoRegPressureReduce) {
2821 unsigned CombineOpc) {
2828 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2842 unsigned OuterShiftAmt) {
2848 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2875 case RISCV::SH1ADD_UW:
2877 case RISCV::SH2ADD_UW:
2879 case RISCV::SH3ADD_UW:
2925 bool DoRegPressureReduce)
const {
2934 DoRegPressureReduce);
2942 return RISCV::FMADD_H;
2944 return RISCV::FMADD_S;
2946 return RISCV::FMADD_D;
2991 bool Mul1IsKill = Mul1.
isKill();
2992 bool Mul2IsKill = Mul2.
isKill();
2993 bool AddendIsKill = Addend.
isKill();
3002 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
3027 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
3034 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
3037 switch (InnerShiftAmt - OuterShiftAmt) {
3041 InnerOpc = RISCV::ADD;
3044 InnerOpc = RISCV::SH1ADD;
3047 InnerOpc = RISCV::SH2ADD;
3050 InnerOpc = RISCV::SH3ADD;
3068 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
3085 DelInstrs, InstrIdxForVirtReg);
3112 for (
const auto &[Index, Operand] :
enumerate(
Desc.operands())) {
3114 unsigned OpType = Operand.OperandType;
3120 ErrInfo =
"Expected an immediate operand.";
3129#define CASE_OPERAND_UIMM(NUM) \
3130 case RISCVOp::OPERAND_UIMM##NUM: \
3131 Ok = isUInt<NUM>(Imm); \
3133#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX) \
3134 case RISCVOp::OPERAND_UIMM##BITS##_LSB##SUFFIX: { \
3135 constexpr size_t NumZeros = sizeof(#SUFFIX) - 1; \
3136 Ok = isShiftedUInt<BITS - NumZeros, NumZeros>(Imm); \
3139#define CASE_OPERAND_SIMM(NUM) \
3140 case RISCVOp::OPERAND_SIMM##NUM: \
3141 Ok = isInt<NUM>(Imm); \
3170 Ok =
Imm >= 1 &&
Imm <= 16;
3179 Ok =
Imm >= 1 &&
Imm <= 32;
3182 Ok =
Imm >= 1 &&
Imm <= 64;
3218 Ok =
Imm >= -15 &&
Imm <= 16;
3246 Ok = Ok &&
Imm != 0;
3252 Ok =
Imm >= 0 &&
Imm <= 10;
3255 Ok =
Imm >= 0 &&
Imm <= 7;
3258 Ok =
Imm >= 1 &&
Imm <= 10;
3261 Ok =
Imm >= 2 &&
Imm <= 14;
3270 Ok =
Imm >= 0 &&
Imm <= 48 &&
Imm % 16 == 0;
3315 ErrInfo =
"Invalid immediate";
3324 ErrInfo =
"Expected a non-register operand.";
3328 ErrInfo =
"Invalid immediate";
3337 ErrInfo =
"Expected a non-register operand.";
3341 ErrInfo =
"Invalid immediate";
3349 ErrInfo =
"Expected a non-register operand.";
3353 ErrInfo =
"Invalid immediate";
3362 ErrInfo =
"Invalid immediate";
3365 }
else if (!MO.
isReg()) {
3366 ErrInfo =
"Expected a register or immediate operand.";
3372 ErrInfo =
"Expected a register or immediate operand.";
3379 const uint64_t TSFlags =
Desc.TSFlags;
3382 if (!
Op.isImm() && !
Op.isReg()) {
3383 ErrInfo =
"Invalid operand type for VL operand";
3386 if (
Op.isReg() &&
Op.getReg().isValid()) {
3389 if (!RISCV::GPRNoX0RegClass.hasSubClassEq(RC)) {
3390 ErrInfo =
"Invalid register class for VL operand";
3395 ErrInfo =
"VL operand w/o SEW operand?";
3401 if (!
MI.getOperand(OpIdx).isImm()) {
3402 ErrInfo =
"SEW value expected to be an immediate";
3405 uint64_t Log2SEW =
MI.getOperand(OpIdx).getImm();
3407 ErrInfo =
"Unexpected SEW value";
3410 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3412 ErrInfo =
"Unexpected SEW value";
3418 if (!
MI.getOperand(OpIdx).isImm()) {
3419 ErrInfo =
"Policy operand expected to be an immediate";
3422 uint64_t Policy =
MI.getOperand(OpIdx).getImm();
3424 ErrInfo =
"Invalid Policy Value";
3428 ErrInfo =
"policy operand w/o VL operand?";
3436 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
3437 ErrInfo =
"policy operand w/o tied operand?";
3444 !
MI.readsRegister(RISCV::FRM,
nullptr)) {
3445 ErrInfo =
"dynamic rounding mode should read FRM";
3467 case RISCV::LD_RV32:
3477 case RISCV::SD_RV32:
3493 int64_t NewOffset = OldOffset + Disp;
3515 "Addressing mode not supported for folding");
3588 case RISCV::LD_RV32:
3591 case RISCV::SD_RV32:
3598 OffsetIsScalable =
false;
3614 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
3622 if (MO1->getAddrSpace() != MO2->getAddrSpace())
3625 auto Base1 = MO1->getValue();
3626 auto Base2 = MO2->getValue();
3627 if (!Base1 || !Base2)
3635 return Base1 == Base2;
3641 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
3642 unsigned NumBytes)
const {
3645 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
3650 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
3656 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
3662 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
3712 int64_t OffsetA = 0, OffsetB = 0;
3718 int LowOffset = std::min(OffsetA, OffsetB);
3719 int HighOffset = std::max(OffsetA, OffsetB);
3720 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3722 LowOffset + (
int)LowWidth.
getValue() <= HighOffset)
3729std::pair<unsigned, unsigned>
3732 return std::make_pair(TF & Mask, TF & ~Mask);
3738 static const std::pair<unsigned, const char *> TargetFlags[] = {
3739 {MO_CALL,
"riscv-call"},
3740 {MO_LO,
"riscv-lo"},
3741 {MO_HI,
"riscv-hi"},
3742 {MO_PCREL_LO,
"riscv-pcrel-lo"},
3743 {MO_PCREL_HI,
"riscv-pcrel-hi"},
3744 {MO_GOT_HI,
"riscv-got-hi"},
3745 {MO_TPREL_LO,
"riscv-tprel-lo"},
3746 {MO_TPREL_HI,
"riscv-tprel-hi"},
3747 {MO_TPREL_ADD,
"riscv-tprel-add"},
3748 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
3749 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
3750 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
3751 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
3752 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
3753 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"},
3754 {MO_QC_ACCESS,
"riscv-qc-access"},
3763 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
3776 unsigned &Flags)
const {
3796 return F.getFnAttribute(
"fentry-call").getValueAsBool() ||
3797 F.hasFnAttribute(
"patchable-function-entry");
3802 return MI.readsRegister(RegNo,
TRI) ||
3803 MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
3808 return MI.modifiesRegister(RegNo,
TRI) ||
3809 MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
3813 if (!
MBB.back().isReturn())
3859 if (
C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
3860 C.isAvailableInsideSeq(
Reg,
TRI)) {
3878 if (
C.back().isReturn() &&
3879 !
C.isAvailableAcrossAndOutOfSeq(TailExpandUseReg, RegInfo)) {
3881 LLVM_DEBUG(
dbgs() <<
"Cannot be outlined between: " <<
C.front() <<
"and "
3883 LLVM_DEBUG(
dbgs() <<
"Because the tail-call register is live across "
3884 "the proposed outlined function call\n");
3890 if (
C.back().isReturn()) {
3892 "The candidate who uses return instruction must be outlined "
3899 if (!
C.isAvailableInsideSeq(RISCV::X5, RegInfo))
3903 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo))
3913std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3916 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3917 unsigned MinRepeats)
const {
3925 if (RepeatedSequenceLocs.size() < MinRepeats)
3926 return std::nullopt;
3930 unsigned InstrSizeCExt =
3932 unsigned CallOverhead = 0, FrameOverhead = 0;
3935 unsigned CFICount = 0;
3936 for (
auto &
I : Candidate) {
3937 if (
I.isCFIInstruction())
3948 std::vector<MCCFIInstruction> CFIInstructions =
3949 C.getMF()->getFrameInstructions();
3951 if (CFICount > 0 && CFICount != CFIInstructions.size())
3952 return std::nullopt;
3960 CallOverhead = 4 + InstrSizeCExt;
3967 FrameOverhead = InstrSizeCExt;
3973 return std::nullopt;
3977 for (
auto &
C : RepeatedSequenceLocs) {
3979 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo)) {
3981 unsigned CandCallOverhead = 8;
3986 unsigned CandCallOverhead = InstrSizeCExt + 8 + InstrSizeCExt;
3991 for (
auto &
C : RepeatedSequenceLocs)
3992 C.setCallInfo(MOCI, CallOverhead);
3995 unsigned SequenceSize = 0;
3996 for (
auto &
MI : Candidate)
3999 return std::make_unique<outliner::OutlinedFunction>(
4000 RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
4006 unsigned Flags)
const {
4010 MBB->getParent()->getSubtarget().getRegisterInfo();
4011 const auto &
F =
MI.getMF()->getFunction();
4016 if (
MI.isCFIInstruction())
4024 for (
const auto &MO :
MI.operands()) {
4029 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
4030 F.hasSection() ||
F.getSectionPrefix()))
4047 MBB.addLiveIn(RISCV::X5);
4065 .addGlobalAddress(M.getNamedValue(MF.
getName()),
4072 assert(SaveReg &&
"Cannot find an available register to save/restore X5.");
4083 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4099 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4107 bool AllowSideEffects)
const {
4112 if (
TRI.isGeneralPurposeRegister(MF, Reg)) {
4114 }
else if (RISCV::FPR32RegClass.
contains(Reg)) {
4116 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
4118 }
else if (RISCV::FPR128RegClass.
contains(Reg)) {
4120 }
else if (RISCV::VRRegClass.
contains(Reg)) {
4124 "buildClearRegister is not implemented for " +
TRI.getRegAsmName(Reg));
4134 return std::nullopt;
4138 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
4139 MI.getOperand(2).isImm())
4140 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
4142 return std::nullopt;
4150 std::string GenericComment =
4152 if (!GenericComment.empty())
4153 return GenericComment;
4156 if (OpIdx >=
Desc.getNumOperands())
4157 return std::string();
4159 std::string Comment;
4166 switch (OpInfo.OperandType) {
4169 unsigned Imm =
Op.getImm();
4174 unsigned Imm =
Op.getImm();
4179 unsigned Imm =
Op.getImm();
4185 unsigned Log2SEW =
Op.getImm();
4186 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
4192 unsigned Policy =
Op.getImm();
4194 "Invalid Policy Value");
4200 if (
Op.isImm() &&
Op.getImm() == -1)
4222#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
4223 RISCV::Pseudo##OP##_##LMUL
4225#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
4226 RISCV::Pseudo##OP##_##LMUL##_MASK
4228#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
4229 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
4230 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
4232#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
4233 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
4234 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
4235 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
4236 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
4237 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
4238 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
4240#define CASE_RVV_OPCODE_UNMASK(OP) \
4241 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4242 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
4244#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
4245 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
4246 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
4247 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
4248 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
4249 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
4250 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
4252#define CASE_RVV_OPCODE_MASK(OP) \
4253 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
4254 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
4256#define CASE_RVV_OPCODE_WIDEN(OP) \
4257 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4258 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
4260#define CASE_RVV_OPCODE(OP) \
4261 CASE_RVV_OPCODE_UNMASK(OP): \
4262 case CASE_RVV_OPCODE_MASK(OP)
4266#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
4267 RISCV::PseudoV##OP##_##TYPE##_##LMUL
4269#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
4270 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
4271 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
4272 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
4273 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
4274 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
4275 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
4276 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
4279#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
4280 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
4282#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
4283 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
4284 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
4285 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
4286 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
4288#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
4289 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
4290 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
4292#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
4293 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
4294 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
4296#define CASE_VFMA_OPCODE_VV(OP) \
4297 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
4298 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VV, E16): \
4299 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
4300 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
4302#define CASE_VFMA_SPLATS(OP) \
4303 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
4304 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VFPR16, E16): \
4305 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
4306 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
4310 unsigned &SrcOpIdx1,
4311 unsigned &SrcOpIdx2)
const {
4313 if (!
Desc.isCommutable())
4316 switch (
MI.getOpcode()) {
4317 case RISCV::TH_MVEQZ:
4318 case RISCV::TH_MVNEZ:
4322 if (
MI.getOperand(2).getReg() == RISCV::X0)
4325 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4326 case RISCV::QC_SELECTIEQ:
4327 case RISCV::QC_SELECTINE:
4328 case RISCV::QC_SELECTIIEQ:
4329 case RISCV::QC_SELECTIINE:
4330 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4331 case RISCV::QC_MVEQ:
4332 case RISCV::QC_MVNE:
4333 case RISCV::QC_MVLT:
4334 case RISCV::QC_MVGE:
4335 case RISCV::QC_MVLTU:
4336 case RISCV::QC_MVGEU:
4337 case RISCV::QC_MVEQI:
4338 case RISCV::QC_MVNEI:
4339 case RISCV::QC_MVLTI:
4340 case RISCV::QC_MVGEI:
4341 case RISCV::QC_MVLTUI:
4342 case RISCV::QC_MVGEUI:
4343 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 4);
4344 case RISCV::TH_MULA:
4345 case RISCV::TH_MULAW:
4346 case RISCV::TH_MULAH:
4347 case RISCV::TH_MULS:
4348 case RISCV::TH_MULSW:
4349 case RISCV::TH_MULSH:
4351 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4352 case RISCV::PseudoCCMOVGPRNoX0:
4353 case RISCV::PseudoCCMOVGPR:
4355 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4396 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4423 unsigned CommutableOpIdx1 = 1;
4424 unsigned CommutableOpIdx2 = 3;
4425 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4446 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
4448 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
4452 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
4453 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
4459 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
4460 SrcOpIdx2 == CommuteAnyOperandIndex) {
4463 unsigned CommutableOpIdx1 = SrcOpIdx1;
4464 if (SrcOpIdx1 == SrcOpIdx2) {
4467 CommutableOpIdx1 = 1;
4468 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
4470 CommutableOpIdx1 = SrcOpIdx2;
4475 unsigned CommutableOpIdx2;
4476 if (CommutableOpIdx1 != 1) {
4478 CommutableOpIdx2 = 1;
4480 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
4485 if (Op1Reg !=
MI.getOperand(2).getReg())
4486 CommutableOpIdx2 = 2;
4488 CommutableOpIdx2 = 3;
4493 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4506#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
4507 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
4508 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
4511#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
4512 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
4513 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
4514 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
4515 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
4516 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
4517 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
4518 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
4521#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
4522 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
4523 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
4526#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
4527 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
4528 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
4529 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
4530 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
4532#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
4533 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
4534 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
4536#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
4537 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
4538 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
4540#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
4541 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
4542 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VV, E16) \
4543 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
4544 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
4546#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
4547 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
4548 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VFPR16, E16) \
4549 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
4550 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
4556 unsigned OpIdx2)
const {
4559 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
4563 switch (
MI.getOpcode()) {
4564 case RISCV::TH_MVEQZ:
4565 case RISCV::TH_MVNEZ: {
4566 auto &WorkingMI = cloneIfNew(
MI);
4567 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
4568 : RISCV::TH_MVEQZ));
4572 case RISCV::QC_SELECTIEQ:
4573 case RISCV::QC_SELECTINE:
4574 case RISCV::QC_SELECTIIEQ:
4575 case RISCV::QC_SELECTIINE:
4577 case RISCV::QC_MVEQ:
4578 case RISCV::QC_MVNE:
4579 case RISCV::QC_MVLT:
4580 case RISCV::QC_MVGE:
4581 case RISCV::QC_MVLTU:
4582 case RISCV::QC_MVGEU:
4583 case RISCV::QC_MVEQI:
4584 case RISCV::QC_MVNEI:
4585 case RISCV::QC_MVLTI:
4586 case RISCV::QC_MVGEI:
4587 case RISCV::QC_MVLTUI:
4588 case RISCV::QC_MVGEUI: {
4589 auto &WorkingMI = cloneIfNew(
MI);
4594 case RISCV::PseudoCCMOVGPRNoX0:
4595 case RISCV::PseudoCCMOVGPR: {
4597 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
4599 auto &WorkingMI = cloneIfNew(
MI);
4600 WorkingMI.getOperand(
MI.getNumExplicitOperands() - 3).setImm(BCC);
4624 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4625 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
4627 switch (
MI.getOpcode()) {
4650 auto &WorkingMI = cloneIfNew(
MI);
4651 WorkingMI.setDesc(
get(
Opc));
4661 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4664 if (OpIdx1 == 3 || OpIdx2 == 3) {
4666 switch (
MI.getOpcode()) {
4677 auto &WorkingMI = cloneIfNew(
MI);
4678 WorkingMI.setDesc(
get(
Opc));
4690#undef CASE_VMA_CHANGE_OPCODE_COMMON
4691#undef CASE_VMA_CHANGE_OPCODE_LMULS
4692#undef CASE_VFMA_CHANGE_OPCODE_COMMON
4693#undef CASE_VFMA_CHANGE_OPCODE_LMULS_M1
4694#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF2
4695#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF4
4696#undef CASE_VFMA_CHANGE_OPCODE_VV
4697#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
4699#undef CASE_RVV_OPCODE_UNMASK_LMUL
4700#undef CASE_RVV_OPCODE_MASK_LMUL
4701#undef CASE_RVV_OPCODE_LMUL
4702#undef CASE_RVV_OPCODE_UNMASK_WIDEN
4703#undef CASE_RVV_OPCODE_UNMASK
4704#undef CASE_RVV_OPCODE_MASK_WIDEN
4705#undef CASE_RVV_OPCODE_MASK
4706#undef CASE_RVV_OPCODE_WIDEN
4707#undef CASE_RVV_OPCODE
4709#undef CASE_VMA_OPCODE_COMMON
4710#undef CASE_VMA_OPCODE_LMULS
4711#undef CASE_VFMA_OPCODE_COMMON
4712#undef CASE_VFMA_OPCODE_LMULS_M1
4713#undef CASE_VFMA_OPCODE_LMULS_MF2
4714#undef CASE_VFMA_OPCODE_LMULS_MF4
4715#undef CASE_VFMA_OPCODE_VV
4716#undef CASE_VFMA_SPLATS
4719 switch (
MI.getOpcode()) {
4727 if (
MI.getOperand(1).getReg() == RISCV::X0)
4728 commuteInstruction(
MI);
4730 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4731 MI.getOperand(2).ChangeToImmediate(0);
4732 MI.setDesc(
get(RISCV::ADDI));
4736 if (
MI.getOpcode() == RISCV::XOR &&
4737 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4738 MI.getOperand(1).setReg(RISCV::X0);
4739 MI.getOperand(2).ChangeToImmediate(0);
4740 MI.setDesc(
get(RISCV::ADDI));
4747 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4748 MI.setDesc(
get(RISCV::ADDI));
4754 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4755 MI.getOperand(2).ChangeToImmediate(0);
4756 MI.setDesc(
get(RISCV::ADDI));
4762 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4763 MI.getOperand(2).ChangeToImmediate(0);
4764 MI.setDesc(
get(RISCV::ADDIW));
4771 if (
MI.getOperand(1).getReg() == RISCV::X0)
4772 commuteInstruction(
MI);
4774 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4775 MI.getOperand(2).ChangeToImmediate(0);
4776 MI.setDesc(
get(RISCV::ADDIW));
4781 case RISCV::SH1ADD_UW:
4783 case RISCV::SH2ADD_UW:
4785 case RISCV::SH3ADD_UW:
4787 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4788 MI.removeOperand(1);
4790 MI.setDesc(
get(RISCV::ADDI));
4794 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4795 MI.removeOperand(2);
4796 unsigned Opc =
MI.getOpcode();
4797 if (
Opc == RISCV::SH1ADD_UW ||
Opc == RISCV::SH2ADD_UW ||
4798 Opc == RISCV::SH3ADD_UW) {
4800 MI.setDesc(
get(RISCV::SLLI_UW));
4804 MI.setDesc(
get(RISCV::SLLI));
4818 if (
MI.getOperand(1).getReg() == RISCV::X0 ||
4819 MI.getOperand(2).getReg() == RISCV::X0) {
4820 MI.getOperand(1).setReg(RISCV::X0);
4821 MI.getOperand(2).ChangeToImmediate(0);
4822 MI.setDesc(
get(RISCV::ADDI));
4828 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4829 MI.getOperand(2).setImm(0);
4830 MI.setDesc(
get(RISCV::ADDI));
4838 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4839 MI.getOperand(2).ChangeToImmediate(0);
4840 MI.setDesc(
get(RISCV::ADDI));
4844 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4845 MI.getOperand(2).ChangeToImmediate(0);
4846 MI.setDesc(
get(RISCV::ADDI));
4854 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4855 MI.getOperand(2).ChangeToImmediate(0);
4856 MI.setDesc(
get(RISCV::ADDI));
4866 case RISCV::SLLI_UW:
4868 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4869 MI.getOperand(2).setImm(0);
4870 MI.setDesc(
get(RISCV::ADDI));
4878 if (
MI.getOperand(1).getReg() == RISCV::X0 &&
4879 MI.getOperand(2).getReg() == RISCV::X0) {
4880 MI.getOperand(2).ChangeToImmediate(0);
4881 MI.setDesc(
get(RISCV::ADDI));
4885 if (
MI.getOpcode() == RISCV::ADD_UW &&
4886 MI.getOperand(1).getReg() == RISCV::X0) {
4887 MI.removeOperand(1);
4889 MI.setDesc(
get(RISCV::ADDI));
4895 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4896 MI.getOperand(2).setImm(
MI.getOperand(2).getImm() != 0);
4897 MI.setDesc(
get(RISCV::ADDI));
4903 case RISCV::ZEXT_H_RV32:
4904 case RISCV::ZEXT_H_RV64:
4907 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4909 MI.setDesc(
get(RISCV::ADDI));
4918 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4919 MI.getOperand(2).ChangeToImmediate(0);
4920 MI.setDesc(
get(RISCV::ADDI));
4927 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4929 MI.removeOperand(0);
4930 MI.insert(
MI.operands_begin() + 1, {MO0});
4935 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4937 MI.removeOperand(0);
4938 MI.insert(
MI.operands_begin() + 1, {MO0});
4939 MI.setDesc(
get(RISCV::BNE));
4944 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4946 MI.removeOperand(0);
4947 MI.insert(
MI.operands_begin() + 1, {MO0});
4948 MI.setDesc(
get(RISCV::BEQ));
4956#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
4957 RISCV::PseudoV##OP##_##LMUL##_TIED
4959#define CASE_WIDEOP_OPCODE_LMULS(OP) \
4960 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
4961 case CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
4962 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
4963 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
4964 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
4965 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
4967#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
4968 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
4969 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
4972#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4973 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
4974 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
4975 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
4976 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
4977 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
4978 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
4981#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
4982 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
4984#define CASE_FP_WIDEOP_OPCODE_LMULS(OP) \
4985 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4986 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4987 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
4988 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4989 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
4990 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4991 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
4992 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
4993 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
4995#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
4996 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
4997 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
5000#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
5001 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
5002 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
5003 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
5004 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
5005 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
5006 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
5007 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
5008 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
5009 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
5011#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP) \
5012 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
5013 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
5014 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
5015 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
5016 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16)
5018#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP) \
5019 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
5020 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
5021 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
5022 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
5023 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16)
5029 switch (
MI.getOpcode()) {
5037 MI.getNumExplicitOperands() == 7 &&
5038 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
5045 switch (
MI.getOpcode()) {
5057 .
add(
MI.getOperand(0))
5059 .
add(
MI.getOperand(1))
5060 .
add(
MI.getOperand(2))
5061 .
add(
MI.getOperand(3))
5062 .
add(
MI.getOperand(4))
5063 .
add(
MI.getOperand(5))
5064 .
add(
MI.getOperand(6));
5073 MI.getNumExplicitOperands() == 6);
5080 switch (
MI.getOpcode()) {
5092 .
add(
MI.getOperand(0))
5094 .
add(
MI.getOperand(1))
5095 .
add(
MI.getOperand(2))
5096 .
add(
MI.getOperand(3))
5097 .
add(
MI.getOperand(4))
5098 .
add(
MI.getOperand(5));
5107 if (
MI.getOperand(0).isEarlyClobber()) {
5121#undef CASE_WIDEOP_OPCODE_COMMON
5122#undef CASE_WIDEOP_OPCODE_LMULS
5123#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
5124#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
5125#undef CASE_FP_WIDEOP_OPCODE_COMMON
5126#undef CASE_FP_WIDEOP_OPCODE_LMULS
5127#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
5128#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
5137 if (ShiftAmount == 0)
5143 }
else if (
int ShXAmount, ShiftAmount;
5145 (ShXAmount =
isShifted359(Amount, ShiftAmount)) != 0) {
5148 switch (ShXAmount) {
5150 Opc = RISCV::SH1ADD;
5153 Opc = RISCV::SH2ADD;
5156 Opc = RISCV::SH3ADD;
5192 }
else if (
STI.hasStdExtZmmul()) {
5202 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
5203 if (Amount & (1U << ShiftAmount)) {
5207 .
addImm(ShiftAmount - PrevShiftAmount)
5209 if (Amount >> (ShiftAmount + 1)) {
5223 PrevShiftAmount = ShiftAmount;
5226 assert(Acc &&
"Expected valid accumulator");
5236 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
5244 ?
STI.getTailDupAggressiveThreshold()
5251 unsigned Opcode =
MI.getOpcode();
5252 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
5261 return MI.isCopy() &&
MI.getOperand(0).getReg().isPhysical() &&
5263 TRI->getMinimalPhysRegClass(
MI.getOperand(0).getReg()));
5266std::optional<std::pair<unsigned, unsigned>>
5270 return std::nullopt;
5271 case RISCV::PseudoVSPILL2_M1:
5272 case RISCV::PseudoVRELOAD2_M1:
5273 return std::make_pair(2u, 1u);
5274 case RISCV::PseudoVSPILL2_M2:
5275 case RISCV::PseudoVRELOAD2_M2:
5276 return std::make_pair(2u, 2u);
5277 case RISCV::PseudoVSPILL2_M4:
5278 case RISCV::PseudoVRELOAD2_M4:
5279 return std::make_pair(2u, 4u);
5280 case RISCV::PseudoVSPILL3_M1:
5281 case RISCV::PseudoVRELOAD3_M1:
5282 return std::make_pair(3u, 1u);
5283 case RISCV::PseudoVSPILL3_M2:
5284 case RISCV::PseudoVRELOAD3_M2:
5285 return std::make_pair(3u, 2u);
5286 case RISCV::PseudoVSPILL4_M1:
5287 case RISCV::PseudoVRELOAD4_M1:
5288 return std::make_pair(4u, 1u);
5289 case RISCV::PseudoVSPILL4_M2:
5290 case RISCV::PseudoVRELOAD4_M2:
5291 return std::make_pair(4u, 2u);
5292 case RISCV::PseudoVSPILL5_M1:
5293 case RISCV::PseudoVRELOAD5_M1:
5294 return std::make_pair(5u, 1u);
5295 case RISCV::PseudoVSPILL6_M1:
5296 case RISCV::PseudoVRELOAD6_M1:
5297 return std::make_pair(6u, 1u);
5298 case RISCV::PseudoVSPILL7_M1:
5299 case RISCV::PseudoVRELOAD7_M1:
5300 return std::make_pair(7u, 1u);
5301 case RISCV::PseudoVSPILL8_M1:
5302 case RISCV::PseudoVRELOAD8_M1:
5303 return std::make_pair(8u, 1u);
5308 int16_t MI1FrmOpIdx =
5309 RISCV::getNamedOperandIdx(MI1.
getOpcode(), RISCV::OpName::frm);
5310 int16_t MI2FrmOpIdx =
5311 RISCV::getNamedOperandIdx(MI2.
getOpcode(), RISCV::OpName::frm);
5312 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
5319std::optional<unsigned>
5323 return std::nullopt;
5326 case RISCV::VSLL_VX:
5327 case RISCV::VSRL_VX:
5328 case RISCV::VSRA_VX:
5330 case RISCV::VSSRL_VX:
5331 case RISCV::VSSRA_VX:
5333 case RISCV::VROL_VX:
5334 case RISCV::VROR_VX:
5339 case RISCV::VNSRL_WX:
5340 case RISCV::VNSRA_WX:
5342 case RISCV::VNCLIPU_WX:
5343 case RISCV::VNCLIP_WX:
5345 case RISCV::VWSLL_VX:
5350 case RISCV::VADD_VX:
5351 case RISCV::VSUB_VX:
5352 case RISCV::VRSUB_VX:
5354 case RISCV::VWADDU_VX:
5355 case RISCV::VWSUBU_VX:
5356 case RISCV::VWADD_VX:
5357 case RISCV::VWSUB_VX:
5358 case RISCV::VWADDU_WX:
5359 case RISCV::VWSUBU_WX:
5360 case RISCV::VWADD_WX:
5361 case RISCV::VWSUB_WX:
5363 case RISCV::VADC_VXM:
5364 case RISCV::VADC_VIM:
5365 case RISCV::VMADC_VXM:
5366 case RISCV::VMADC_VIM:
5367 case RISCV::VMADC_VX:
5368 case RISCV::VSBC_VXM:
5369 case RISCV::VMSBC_VXM:
5370 case RISCV::VMSBC_VX:
5372 case RISCV::VAND_VX:
5374 case RISCV::VXOR_VX:
5376 case RISCV::VMSEQ_VX:
5377 case RISCV::VMSNE_VX:
5378 case RISCV::VMSLTU_VX:
5379 case RISCV::VMSLT_VX:
5380 case RISCV::VMSLEU_VX:
5381 case RISCV::VMSLE_VX:
5382 case RISCV::VMSGTU_VX:
5383 case RISCV::VMSGT_VX:
5385 case RISCV::VMINU_VX:
5386 case RISCV::VMIN_VX:
5387 case RISCV::VMAXU_VX:
5388 case RISCV::VMAX_VX:
5390 case RISCV::VMUL_VX:
5391 case RISCV::VMULH_VX:
5392 case RISCV::VMULHU_VX:
5393 case RISCV::VMULHSU_VX:
5395 case RISCV::VDIVU_VX:
5396 case RISCV::VDIV_VX:
5397 case RISCV::VREMU_VX:
5398 case RISCV::VREM_VX:
5400 case RISCV::VWMUL_VX:
5401 case RISCV::VWMULU_VX:
5402 case RISCV::VWMULSU_VX:
5404 case RISCV::VMACC_VX:
5405 case RISCV::VNMSAC_VX:
5406 case RISCV::VMADD_VX:
5407 case RISCV::VNMSUB_VX:
5409 case RISCV::VWMACCU_VX:
5410 case RISCV::VWMACC_VX:
5411 case RISCV::VWMACCSU_VX:
5412 case RISCV::VWMACCUS_VX:
5414 case RISCV::VMERGE_VXM:
5416 case RISCV::VMV_V_X:
5418 case RISCV::VSADDU_VX:
5419 case RISCV::VSADD_VX:
5420 case RISCV::VSSUBU_VX:
5421 case RISCV::VSSUB_VX:
5423 case RISCV::VAADDU_VX:
5424 case RISCV::VAADD_VX:
5425 case RISCV::VASUBU_VX:
5426 case RISCV::VASUB_VX:
5428 case RISCV::VSMUL_VX:
5430 case RISCV::VMV_S_X:
5432 case RISCV::VANDN_VX:
5433 return 1U << Log2SEW;
5439 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
5442 return RVV->BaseInstr;
5452 unsigned Scaled = Log2SEW + (DestEEW - 1);
5466 return std::nullopt;
5473 if (LHS.isReg() && RHS.isReg() && LHS.getReg().isVirtual() &&
5474 LHS.getReg() == RHS.getReg())
5478 if (LHS.isImm() && LHS.getImm() == 0)
5484 if (!LHSImm || !RHSImm)
5486 return LHSImm <= RHSImm;
5498 : LHS(LHS), RHS(RHS),
Cond(
Cond.begin(),
Cond.end()) {}
5500 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
5510 std::optional<bool> createTripCountGreaterCondition(
5511 int TC, MachineBasicBlock &
MBB,
5512 SmallVectorImpl<MachineOperand> &CondParam)
override {
5520 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
5522 void adjustTripCount(
int TripCountAdjust)
override {}
5526std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
5534 if (
TBB == LoopBB && FBB == LoopBB)
5541 assert((
TBB == LoopBB || FBB == LoopBB) &&
5542 "The Loop must be a single-basic-block loop");
5553 if (!Reg.isVirtual())
5560 if (LHS && LHS->isPHI())
5562 if (RHS && RHS->isPHI())
5565 return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS,
Cond);
5571 Opc = RVVMCOpcode ? RVVMCOpcode :
Opc;
5588 case RISCV::FDIV_H_INX:
5589 case RISCV::FDIV_S_INX:
5590 case RISCV::FDIV_D_INX:
5591 case RISCV::FDIV_D_IN32X:
5592 case RISCV::FSQRT_H:
5593 case RISCV::FSQRT_S:
5594 case RISCV::FSQRT_D:
5595 case RISCV::FSQRT_H_INX:
5596 case RISCV::FSQRT_S_INX:
5597 case RISCV::FSQRT_D_INX:
5598 case RISCV::FSQRT_D_IN32X:
5600 case RISCV::VDIV_VV:
5601 case RISCV::VDIV_VX:
5602 case RISCV::VDIVU_VV:
5603 case RISCV::VDIVU_VX:
5604 case RISCV::VREM_VV:
5605 case RISCV::VREM_VX:
5606 case RISCV::VREMU_VV:
5607 case RISCV::VREMU_VX:
5609 case RISCV::VFDIV_VV:
5610 case RISCV::VFDIV_VF:
5611 case RISCV::VFRDIV_VF:
5612 case RISCV::VFSQRT_V:
5613 case RISCV::VFRSQRT7_V:
5619 if (
MI->getOpcode() != TargetOpcode::COPY)
5624 Register DstReg =
MI->getOperand(0).getReg();
5627 :
TRI->getMinimalPhysRegClass(DstReg);
5637 auto [RCLMul, RCFractional] =
5639 return (!RCFractional && LMul == RCLMul) || (RCFractional && LMul == 1);
5643 if (
MI.memoperands_empty())
5658 if (MO.getReg().isPhysical())
5661 if (MO.getReg().isPhysical())
5663 bool SawStore =
false;
5666 if (
II->definesRegister(PhysReg,
nullptr))
5669 if (
II->definesRegister(PhysReg,
nullptr) ||
5670 II->readsRegister(PhysReg,
nullptr))
5672 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 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.
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 & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & 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...
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.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
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.
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.