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");
56#define GET_RISCVVPseudosTable_IMPL
57#include "RISCVGenSearchableTables.inc"
63#define GET_RISCVMaskedPseudosTable_IMPL
64#include "RISCVGenSearchableTables.inc"
70 RISCV::ADJCALLSTACKUP),
73#define GET_INSTRINFO_HELPERS
74#include "RISCVGenInstrInfo.inc"
77 if (
STI.hasStdExtZca())
86 int &FrameIndex)
const {
97 case RISCV::VL1RE16_V:
98 case RISCV::VL1RE32_V:
99 case RISCV::VL1RE64_V:
102 case RISCV::VL2RE8_V:
103 case RISCV::VL2RE16_V:
104 case RISCV::VL2RE32_V:
105 case RISCV::VL2RE64_V:
108 case RISCV::VL4RE8_V:
109 case RISCV::VL4RE16_V:
110 case RISCV::VL4RE32_V:
111 case RISCV::VL4RE64_V:
114 case RISCV::VL8RE8_V:
115 case RISCV::VL8RE16_V:
116 case RISCV::VL8RE32_V:
117 case RISCV::VL8RE64_V:
125 switch (
MI.getOpcode()) {
149 case RISCV::VL1RE8_V:
150 case RISCV::VL2RE8_V:
151 case RISCV::VL4RE8_V:
152 case RISCV::VL8RE8_V:
153 if (!
MI.getOperand(1).isFI())
155 FrameIndex =
MI.getOperand(1).getIndex();
158 return MI.getOperand(0).getReg();
161 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
162 MI.getOperand(2).getImm() == 0) {
163 FrameIndex =
MI.getOperand(1).getIndex();
164 return MI.getOperand(0).getReg();
171 int &FrameIndex)
const {
179 switch (
MI.getOpcode()) {
204 if (!
MI.getOperand(1).isFI())
206 FrameIndex =
MI.getOperand(1).getIndex();
209 return MI.getOperand(0).getReg();
212 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
213 MI.getOperand(2).getImm() == 0) {
214 FrameIndex =
MI.getOperand(1).getIndex();
215 return MI.getOperand(0).getReg();
225 case RISCV::VFMV_V_F:
228 case RISCV::VFMV_S_F:
230 return MI.getOperand(1).isUndef();
238 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
246 if (STI.
getCLOpts().prefer_whole_register_move)
249 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
250 "Unexpected COPY instruction.");
254 bool FoundDef =
false;
255 bool FirstVSetVLI =
false;
256 unsigned FirstSEW = 0;
259 if (
MBBI->isMetaInstruction())
262 if (RISCVInstrInfo::isVectorConfigInstr(*
MBBI)) {
272 unsigned FirstVType =
MBBI->getOperand(2).getImm();
277 if (FirstLMul != LMul)
282 if (!RISCVInstrInfo::isVLPreservingConfig(*
MBBI))
288 unsigned VType =
MBBI->getOperand(2).getImm();
306 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
308 }
else if (
MBBI->getNumDefs()) {
311 if (
MBBI->modifiesRegister(RISCV::VL,
nullptr))
317 if (!MO.isReg() || !MO.isDef())
319 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
334 if (MO.getReg() != SrcReg)
375 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
376 uint16_t DstEncoding =
TRI->getEncodingValue(DstReg);
378 assert(!Fractional &&
"It is impossible be fractional lmul here.");
379 unsigned NumRegs = NF * LMulVal;
385 SrcEncoding += NumRegs - 1;
386 DstEncoding += NumRegs - 1;
390 auto GetCopyInfo = [&](uint16_t SrcEncoding, uint16_t DstEncoding)
392 unsigned,
unsigned> {
400 uint16_t Diff = DstEncoding - SrcEncoding;
401 if (
I + 8 <= NumRegs && Diff >= 8 && SrcEncoding % 8 == 7 &&
402 DstEncoding % 8 == 7)
404 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
405 if (
I + 4 <= NumRegs && Diff >= 4 && SrcEncoding % 4 == 3 &&
406 DstEncoding % 4 == 3)
408 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
409 if (
I + 2 <= NumRegs && Diff >= 2 && SrcEncoding % 2 == 1 &&
410 DstEncoding % 2 == 1)
412 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
415 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
420 if (
I + 8 <= NumRegs && SrcEncoding % 8 == 0 && DstEncoding % 8 == 0)
422 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
423 if (
I + 4 <= NumRegs && SrcEncoding % 4 == 0 && DstEncoding % 4 == 0)
425 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
426 if (
I + 2 <= NumRegs && SrcEncoding % 2 == 0 && DstEncoding % 2 == 0)
428 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
431 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
434 while (
I != NumRegs) {
439 auto [LMulCopied, RegClass,
Opc, VVOpc, VIOpc] =
440 GetCopyInfo(SrcEncoding, DstEncoding);
444 if (LMul == LMulCopied &&
447 if (DefMBBI->getOpcode() == VIOpc)
454 RegClass, ReversedCopy ? (SrcEncoding - NumCopied + 1) : SrcEncoding);
456 RegClass, ReversedCopy ? (DstEncoding - NumCopied + 1) : DstEncoding);
464 MIB = MIB.add(DefMBBI->getOperand(2));
472 MIB.addImm(Log2SEW ? Log2SEW : 3);
484 SrcEncoding += (ReversedCopy ? -NumCopied : NumCopied);
485 DstEncoding += (ReversedCopy ? -NumCopied : NumCopied);
494 bool RenamableDest,
bool RenamableSrc)
const {
498 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
506 if (SrcReg == RISCV::DUMMY_REG_PAIR_WITH_X0 &&
507 RISCV::GPRRegClass.
contains(DstReg)) {
514 if (RISCV::GPRF16RegClass.
contains(DstReg, SrcReg)) {
520 if (RISCV::GPRF32RegClass.
contains(DstReg, SrcReg)) {
526 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
527 if (!
STI.is64Bit()) {
528 if (
STI.hasStdExtZdinx()) {
537 if (
STI.hasStdExtP()) {
546 MCRegister EvenReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even);
547 MCRegister OddReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd);
549 if (OddReg == RISCV::DUMMY_REG_PAIR_WITH_X0)
551 assert(DstReg != RISCV::X0_Pair &&
"Cannot write to X0_Pair");
555 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
556 .
addReg(EvenReg, KillFlag)
559 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
566 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
567 RISCV::GPRRegClass.
contains(DstReg)) {
569 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
574 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
576 if (
STI.hasStdExtZfh()) {
577 Opc = RISCV::FSGNJ_H;
580 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
581 "Unexpected extensions");
583 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
584 &RISCV::FPR32RegClass);
585 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
586 &RISCV::FPR32RegClass);
587 Opc = RISCV::FSGNJ_S;
591 .
addReg(SrcReg, KillFlag);
595 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
598 .
addReg(SrcReg, KillFlag);
602 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
605 .
addReg(SrcReg, KillFlag);
609 if (RISCV::FPR32RegClass.
contains(DstReg) &&
610 RISCV::GPRRegClass.
contains(SrcReg)) {
612 .
addReg(SrcReg, KillFlag);
616 if (RISCV::GPRRegClass.
contains(DstReg) &&
617 RISCV::FPR32RegClass.
contains(SrcReg)) {
619 .
addReg(SrcReg, KillFlag);
623 if (RISCV::FPR64RegClass.
contains(DstReg) &&
624 RISCV::GPRRegClass.
contains(SrcReg)) {
625 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
627 .
addReg(SrcReg, KillFlag);
631 if (RISCV::GPRRegClass.
contains(DstReg) &&
632 RISCV::FPR64RegClass.
contains(SrcReg)) {
633 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
635 .
addReg(SrcReg, KillFlag);
641 TRI->getCommonMinimalPhysRegClass(SrcReg, DstReg);
652 Register SrcReg,
bool IsKill,
int FI,
661 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
662 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::SW
664 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
665 Opcode = RISCV::SH_INX;
666 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
667 Opcode = RISCV::SW_INX;
668 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
669 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
670 Alignment >=
STI.getZilsdAlign()) {
671 Opcode = RISCV::SD_RV32;
673 Opcode = RISCV::PseudoRV32ZdinxSD;
675 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
677 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
679 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
681 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
682 Opcode = RISCV::VS1R_V;
683 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
684 Opcode = RISCV::VS2R_V;
685 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
686 Opcode = RISCV::VS4R_V;
687 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
688 Opcode = RISCV::VS8R_V;
689 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
690 Opcode = RISCV::PseudoVSPILL2_M1;
691 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
692 Opcode = RISCV::PseudoVSPILL2_M2;
693 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
694 Opcode = RISCV::PseudoVSPILL2_M4;
695 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
696 Opcode = RISCV::PseudoVSPILL3_M1;
697 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
698 Opcode = RISCV::PseudoVSPILL3_M2;
699 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
700 Opcode = RISCV::PseudoVSPILL4_M1;
701 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
702 Opcode = RISCV::PseudoVSPILL4_M2;
703 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
704 Opcode = RISCV::PseudoVSPILL5_M1;
705 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
706 Opcode = RISCV::PseudoVSPILL6_M1;
707 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
708 Opcode = RISCV::PseudoVSPILL7_M1;
709 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
710 Opcode = RISCV::PseudoVSPILL8_M1;
753 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
754 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::LW
756 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
757 Opcode = RISCV::LH_INX;
758 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
759 Opcode = RISCV::LW_INX;
760 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
761 if (!
STI.is64Bit() &&
STI.hasStdExtZilsd() &&
762 Alignment >=
STI.getZilsdAlign()) {
763 Opcode = RISCV::LD_RV32;
765 Opcode = RISCV::PseudoRV32ZdinxLD;
767 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
769 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
771 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
773 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
774 Opcode = RISCV::VL1RE8_V;
775 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
776 Opcode = RISCV::VL2RE8_V;
777 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
778 Opcode = RISCV::VL4RE8_V;
779 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
780 Opcode = RISCV::VL8RE8_V;
781 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
782 Opcode = RISCV::PseudoVRELOAD2_M1;
783 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
784 Opcode = RISCV::PseudoVRELOAD2_M2;
785 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
786 Opcode = RISCV::PseudoVRELOAD2_M4;
787 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
788 Opcode = RISCV::PseudoVRELOAD3_M1;
789 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
790 Opcode = RISCV::PseudoVRELOAD3_M2;
791 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
792 Opcode = RISCV::PseudoVRELOAD4_M1;
793 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
794 Opcode = RISCV::PseudoVRELOAD4_M2;
795 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
796 Opcode = RISCV::PseudoVRELOAD5_M1;
797 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
798 Opcode = RISCV::PseudoVRELOAD6_M1;
799 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
800 Opcode = RISCV::PseudoVRELOAD7_M1;
801 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
802 Opcode = RISCV::PseudoVRELOAD8_M1;
840 if (
Ops.size() != 1 ||
Ops[0] != 1)
843 switch (
MI.getOpcode()) {
845 if (RISCVInstrInfo::isSEXT_W(
MI))
847 if (RISCVInstrInfo::isZEXT_W(
MI))
849 if (RISCVInstrInfo::isZEXT_B(
MI))
856 case RISCV::ZEXT_H_RV32:
857 case RISCV::ZEXT_H_RV64:
864 case RISCV::VMV_X_S: {
867 if (ST.getXLen() < (1U << Log2SEW))
882 case RISCV::VFMV_F_S: {
910 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(*LoadOpc),
919 return RISCV::PseudoCCLB;
921 return RISCV::PseudoCCLBU;
923 return RISCV::PseudoCCLH;
925 return RISCV::PseudoCCLHU;
927 return RISCV::PseudoCCLW;
929 return RISCV::PseudoCCLWU;
931 return RISCV::PseudoCCLD;
933 return RISCV::PseudoCCQC_E_LB;
934 case RISCV::QC_E_LBU:
935 return RISCV::PseudoCCQC_E_LBU;
937 return RISCV::PseudoCCQC_E_LH;
938 case RISCV::QC_E_LHU:
939 return RISCV::PseudoCCQC_E_LHU;
941 return RISCV::PseudoCCQC_E_LW;
953 if (
MI.getOpcode() != RISCV::PseudoCCMOVGPR)
958 if (!
STI.hasShortForwardBranchILoad() || !PredOpc)
962 if (
Ops.size() != 1 || (
Ops[0] != 1 &&
Ops[0] != 2))
965 bool Invert =
Ops[0] == 2;
974 MI.getDebugLoc(),
get(PredOpc), DestReg);
985 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
991 NewMI.
add({
MI.getOperand(
MI.getNumExplicitOperands() - 2),
992 MI.getOperand(
MI.getNumExplicitOperands() - 1)});
1001 bool DstIsDead)
const {
1017 bool SrcRenamable =
false;
1021 bool LastItem = ++Num == Seq.
size();
1026 switch (Inst.getOpndKind()) {
1029 .
addDef(DstReg, DstRegState)
1035 .
addDef(DstReg, DstRegState)
1036 .
addReg(SrcReg, SrcRegState)
1042 .
addDef(DstReg, DstRegState)
1043 .
addReg(SrcReg, SrcRegState)
1044 .
addReg(SrcReg, SrcRegState)
1049 .
addDef(DstReg, DstRegState)
1050 .
addReg(SrcReg, SrcRegState)
1058 SrcRenamable = DstRenamable;
1068 case RISCV::CV_BEQIMM:
1069 case RISCV::QC_BEQI:
1070 case RISCV::QC_E_BEQI:
1071 case RISCV::NDS_BBC:
1072 case RISCV::NDS_BEQC:
1076 case RISCV::QC_BNEI:
1077 case RISCV::QC_E_BNEI:
1078 case RISCV::CV_BNEIMM:
1079 case RISCV::NDS_BBS:
1080 case RISCV::NDS_BNEC:
1083 case RISCV::QC_BLTI:
1084 case RISCV::QC_E_BLTI:
1087 case RISCV::QC_BGEI:
1088 case RISCV::QC_E_BGEI:
1091 case RISCV::QC_BLTUI:
1092 case RISCV::QC_E_BLTUI:
1095 case RISCV::QC_BGEUI:
1096 case RISCV::QC_E_BGEUI:
1115 return (uint64_t)C0 < (uint64_t)C1;
1117 return (uint64_t)C0 >= (uint64_t)C1;
1128 "Unknown conditional branch");
1139 case RISCV::QC_MVEQ:
1140 return RISCV::QC_MVNE;
1141 case RISCV::QC_MVNE:
1142 return RISCV::QC_MVEQ;
1143 case RISCV::QC_MVLT:
1144 return RISCV::QC_MVGE;
1145 case RISCV::QC_MVGE:
1146 return RISCV::QC_MVLT;
1147 case RISCV::QC_MVLTU:
1148 return RISCV::QC_MVGEU;
1149 case RISCV::QC_MVGEU:
1150 return RISCV::QC_MVLTU;
1151 case RISCV::QC_MVEQI:
1152 return RISCV::QC_MVNEI;
1153 case RISCV::QC_MVNEI:
1154 return RISCV::QC_MVEQI;
1155 case RISCV::QC_MVLTI:
1156 return RISCV::QC_MVGEI;
1157 case RISCV::QC_MVGEI:
1158 return RISCV::QC_MVLTI;
1159 case RISCV::QC_MVLTUI:
1160 return RISCV::QC_MVGEUI;
1161 case RISCV::QC_MVGEUI:
1162 return RISCV::QC_MVLTUI;
1167 switch (SelectOpc) {
1186 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
1196 case RISCV::Select_GPR_Using_CC_SImm5_CV:
1201 return RISCV::CV_BEQIMM;
1203 return RISCV::CV_BNEIMM;
1206 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
1211 return RISCV::QC_BEQI;
1213 return RISCV::QC_BNEI;
1215 return RISCV::QC_BLTI;
1217 return RISCV::QC_BGEI;
1220 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
1225 return RISCV::QC_BLTUI;
1227 return RISCV::QC_BGEUI;
1230 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
1235 return RISCV::QC_E_BEQI;
1237 return RISCV::QC_E_BNEI;
1239 return RISCV::QC_E_BLTI;
1241 return RISCV::QC_E_BGEI;
1244 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
1249 return RISCV::QC_E_BLTUI;
1251 return RISCV::QC_E_BGEUI;
1254 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
1259 return RISCV::NDS_BBC;
1261 return RISCV::NDS_BBS;
1264 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
1269 return RISCV::NDS_BEQC;
1271 return RISCV::NDS_BNEC;
1317 case RISCV::CV_BEQIMM:
1318 return RISCV::CV_BNEIMM;
1319 case RISCV::CV_BNEIMM:
1320 return RISCV::CV_BEQIMM;
1321 case RISCV::QC_BEQI:
1322 return RISCV::QC_BNEI;
1323 case RISCV::QC_BNEI:
1324 return RISCV::QC_BEQI;
1325 case RISCV::QC_BLTI:
1326 return RISCV::QC_BGEI;
1327 case RISCV::QC_BGEI:
1328 return RISCV::QC_BLTI;
1329 case RISCV::QC_BLTUI:
1330 return RISCV::QC_BGEUI;
1331 case RISCV::QC_BGEUI:
1332 return RISCV::QC_BLTUI;
1333 case RISCV::QC_E_BEQI:
1334 return RISCV::QC_E_BNEI;
1335 case RISCV::QC_E_BNEI:
1336 return RISCV::QC_E_BEQI;
1337 case RISCV::QC_E_BLTI:
1338 return RISCV::QC_E_BGEI;
1339 case RISCV::QC_E_BGEI:
1340 return RISCV::QC_E_BLTI;
1341 case RISCV::QC_E_BLTUI:
1342 return RISCV::QC_E_BGEUI;
1343 case RISCV::QC_E_BGEUI:
1344 return RISCV::QC_E_BLTUI;
1345 case RISCV::NDS_BBC:
1346 return RISCV::NDS_BBS;
1347 case RISCV::NDS_BBS:
1348 return RISCV::NDS_BBC;
1349 case RISCV::NDS_BEQC:
1350 return RISCV::NDS_BNEC;
1351 case RISCV::NDS_BNEC:
1352 return RISCV::NDS_BEQC;
1360 bool AllowModify)
const {
1361 TBB = FBB =
nullptr;
1366 if (
I ==
MBB.end() || !isUnpredicatedTerminator(*
I))
1372 int NumTerminators = 0;
1373 for (
auto J =
I.getReverse(); J !=
MBB.rend() && isUnpredicatedTerminator(*J);
1376 if (J->getDesc().isUnconditionalBranch() ||
1377 J->getDesc().isIndirectBranch()) {
1384 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.end()) {
1385 while (std::next(FirstUncondOrIndirectBr) !=
MBB.end()) {
1386 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
1389 I = FirstUncondOrIndirectBr;
1393 if (
I->getDesc().isIndirectBranch())
1397 if (
I->isPreISelOpcode())
1401 if (NumTerminators > 2)
1405 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
1411 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
1417 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
1418 I->getDesc().isUnconditionalBranch()) {
1429 int *BytesRemoved)
const {
1436 if (!
I->getDesc().isUnconditionalBranch() &&
1437 !
I->getDesc().isConditionalBranch())
1443 I->eraseFromParent();
1447 if (
I ==
MBB.begin())
1450 if (!
I->getDesc().isConditionalBranch())
1456 I->eraseFromParent();
1469 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1471 "RISC-V branch conditions have two components!");
1505 assert(RS &&
"RegScavenger required for long branching");
1507 "new block should be inserted for expanding unconditional branch");
1510 "restore block should be inserted for restoring clobbered registers");
1519 "Branch offsets outside of the signed 32-bit range not supported");
1525 auto II =
MBB.end();
1531 RS->enterBasicBlockEnd(
MBB);
1538 RC = &RISCV::GPRX7RegClass;
1540 RS->scavengeRegisterBackwards(*RC,
MI.getIterator(),
1544 RS->setRegUsed(TmpGPR);
1549 TmpGPR =
STI.hasStdExtE() ? RISCV::X9 : RISCV::X27;
1555 if (FrameIndex == -1)
1560 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1563 MI.getOperand(1).setMBB(&RestoreBB);
1567 TRI->eliminateFrameIndex(RestoreBB.
back(),
1577 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1587 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1588 MI->getOperand(1).getReg() == RISCV::X0) {
1589 Imm =
MI->getOperand(2).getImm();
1594 if (
MI->getOpcode() == RISCV::BSETI &&
MI->getOperand(1).isReg() &&
1595 MI->getOperand(1).getReg() == RISCV::X0 &&
1596 MI->getOperand(2).getImm() == 11) {
1610 if (Reg == RISCV::X0) {
1615 if (!Reg.isVirtual())
1623 bool IsSigned =
false;
1624 bool IsEquality =
false;
1625 switch (
MI.getOpcode()) {
1661 MI.eraseFromParent();
1687 auto searchConst = [&](int64_t C1) ->
Register {
1689 auto DefC1 = std::find_if(++
II, E, [&](
const MachineInstr &
I) ->
bool {
1692 I.getOperand(0).getReg().isVirtual();
1695 return DefC1->getOperand(0).getReg();
1707 if (
isFromLoadImm(MRI, LHS, C0) && C0 != 0 && LHS.getReg().isVirtual() &&
1708 MRI.
hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
1710 if (
Register RegZ = searchConst(C0 + 1)) {
1718 MI.eraseFromParent();
1728 if (
isFromLoadImm(MRI, RHS, C0) && C0 != 0 && RHS.getReg().isVirtual() &&
1731 if (
Register RegZ = searchConst(C0 - 1)) {
1739 MI.eraseFromParent();
1749 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1751 int NumOp =
MI.getNumExplicitOperands();
1752 return MI.getOperand(NumOp - 1).getMBB();
1756 int64_t BrOffset)
const {
1757 unsigned XLen =
STI.getXLen();
1764 case RISCV::NDS_BBC:
1765 case RISCV::NDS_BBS:
1766 case RISCV::NDS_BEQC:
1767 case RISCV::NDS_BNEC:
1777 case RISCV::CV_BEQIMM:
1778 case RISCV::CV_BNEIMM:
1779 case RISCV::QC_BEQI:
1780 case RISCV::QC_BNEI:
1781 case RISCV::QC_BGEI:
1782 case RISCV::QC_BLTI:
1783 case RISCV::QC_BLTUI:
1784 case RISCV::QC_BGEUI:
1785 case RISCV::QC_E_BEQI:
1786 case RISCV::QC_E_BNEI:
1787 case RISCV::QC_E_BGEI:
1788 case RISCV::QC_E_BLTI:
1789 case RISCV::QC_E_BLTUI:
1790 case RISCV::QC_E_BGEUI:
1793 case RISCV::PseudoBR:
1795 case RISCV::PseudoJump:
1802 const PseudoSourceValue *PSV = MMO->getPseudoValue();
1803 return PSV && PSV->isJumpTable();
1811 if (!
Reg.isVirtual())
1819 return MO.getIndex();
1828 if (!
Reg.isVirtual())
1835 switch (
MI->getOpcode()) {
1871 if (
MI.getOpcode() != RISCV::PseudoBRIND &&
1872 MI.getOpcode() != RISCV::PseudoBRINDX7)
1876 if (!Reg.isVirtual())
1887 switch (Def->getOpcode()) {
1928 case RISCV::ADD:
return RISCV::PseudoCCADD;
1929 case RISCV::SUB:
return RISCV::PseudoCCSUB;
1930 case RISCV::SLL:
return RISCV::PseudoCCSLL;
1931 case RISCV::SRL:
return RISCV::PseudoCCSRL;
1932 case RISCV::SRA:
return RISCV::PseudoCCSRA;
1933 case RISCV::AND:
return RISCV::PseudoCCAND;
1934 case RISCV::OR:
return RISCV::PseudoCCOR;
1935 case RISCV::XOR:
return RISCV::PseudoCCXOR;
1936 case RISCV::MAX:
return RISCV::PseudoCCMAX;
1937 case RISCV::MAXU:
return RISCV::PseudoCCMAXU;
1938 case RISCV::MIN:
return RISCV::PseudoCCMIN;
1939 case RISCV::MINU:
return RISCV::PseudoCCMINU;
1940 case RISCV::MUL:
return RISCV::PseudoCCMUL;
1941 case RISCV::LUI:
return RISCV::PseudoCCLUI;
1942 case RISCV::QC_LI:
return RISCV::PseudoCCQC_LI;
1943 case RISCV::QC_E_LI:
return RISCV::PseudoCCQC_E_LI;
1945 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
1946 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
1947 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
1948 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
1949 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
1950 case RISCV::ORI:
return RISCV::PseudoCCORI;
1951 case RISCV::XORI:
return RISCV::PseudoCCXORI;
1953 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
1954 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
1955 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
1956 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
1957 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
1959 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
1960 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
1961 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
1962 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
1964 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
1965 case RISCV::ORN:
return RISCV::PseudoCCORN;
1966 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
1968 case RISCV::NDS_BFOS:
return RISCV::PseudoCCNDS_BFOS;
1969 case RISCV::NDS_BFOZ:
return RISCV::PseudoCCNDS_BFOZ;
1973 return RISCV::INSTRUCTION_LIST_END;
1982 if (!
Reg.isVirtual())
1990 if (!STI.hasShortForwardBranchIMinMax() &&
1991 (
MI->getOpcode() == RISCV::MAX ||
MI->getOpcode() == RISCV::MIN ||
1992 MI->getOpcode() == RISCV::MINU ||
MI->getOpcode() == RISCV::MAXU))
1995 if (!STI.hasShortForwardBranchIMul() &&
MI->getOpcode() == RISCV::MUL)
2002 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
2003 MI->getOperand(1).getReg() == RISCV::X0)
2008 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2021 bool DontMoveAcrossStores =
true;
2022 if (!
MI->isSafeToMove(DontMoveAcrossStores))
2030 bool PreferFalse)
const {
2031 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
2032 "Unknown select instruction");
2033 if (!
STI.hasShortForwardBranchIALU())
2039 bool Invert = !
DefMI;
2047 Register DestReg =
MI.getOperand(0).getReg();
2053 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
2060 NewMI.
add(FalseReg);
2068 unsigned BCCOpcode =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
2074 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 2));
2075 NewMI.
add(
MI.getOperand(
MI.getNumExplicitOperands() - 1));
2085 if (
DefMI->getParent() !=
MI.getParent())
2089 DefMI->eraseFromParent();
2094 if (
MI.isMetaInstruction())
2097 unsigned Opcode =
MI.getOpcode();
2099 if (Opcode == TargetOpcode::INLINEASM ||
2100 Opcode == TargetOpcode::INLINEASM_BR) {
2102 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
2107 if (
STI.hasStdExtZca()) {
2108 if (
unsigned Size = getCompressedSize(
MI,
STI))
2115 if (Opcode == TargetOpcode::BUNDLE)
2116 return getInstBundleSize(
MI);
2118 if (
MI.getParent() &&
MI.getParent()->getParent()) {
2119 if (
unsigned Size = getCompressedSize(
MI,
STI))
2124 case RISCV::PseudoMV_FPR16INX:
2125 case RISCV::PseudoMV_FPR32INX:
2126 case RISCV::PseudoClearGPR:
2128 return STI.hasStdExtZca() ? 2 : 4;
2130 case RISCV::PseudoCCMOVGPRNoX0:
2131 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2134 case RISCV::PseudoCCMOVGPR:
2135 case RISCV::PseudoCCADD:
2136 case RISCV::PseudoCCSUB:
2137 case RISCV::PseudoCCSLL:
2138 case RISCV::PseudoCCSRL:
2139 case RISCV::PseudoCCSRA:
2140 case RISCV::PseudoCCAND:
2141 case RISCV::PseudoCCOR:
2142 case RISCV::PseudoCCXOR:
2143 case RISCV::PseudoCCADDI:
2144 case RISCV::PseudoCCANDI:
2145 case RISCV::PseudoCCORI:
2146 case RISCV::PseudoCCXORI:
2147 case RISCV::PseudoCCLUI:
2148 case RISCV::PseudoCCSLLI:
2149 case RISCV::PseudoCCSRLI:
2150 case RISCV::PseudoCCSRAI:
2151 case RISCV::PseudoCCADDW:
2152 case RISCV::PseudoCCSUBW:
2153 case RISCV::PseudoCCSLLW:
2154 case RISCV::PseudoCCSRLW:
2155 case RISCV::PseudoCCSRAW:
2156 case RISCV::PseudoCCADDIW:
2157 case RISCV::PseudoCCSLLIW:
2158 case RISCV::PseudoCCSRLIW:
2159 case RISCV::PseudoCCSRAIW:
2160 case RISCV::PseudoCCANDN:
2161 case RISCV::PseudoCCORN:
2162 case RISCV::PseudoCCXNOR:
2163 case RISCV::PseudoCCMAX:
2164 case RISCV::PseudoCCMIN:
2165 case RISCV::PseudoCCMAXU:
2166 case RISCV::PseudoCCMINU:
2167 case RISCV::PseudoCCMUL:
2168 case RISCV::PseudoCCLB:
2169 case RISCV::PseudoCCLH:
2170 case RISCV::PseudoCCLW:
2171 case RISCV::PseudoCCLHU:
2172 case RISCV::PseudoCCLBU:
2173 case RISCV::PseudoCCLWU:
2174 case RISCV::PseudoCCLD:
2175 case RISCV::PseudoCCQC_LI:
2176 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2179 case RISCV::PseudoCCQC_E_LI:
2180 case RISCV::PseudoCCQC_E_LB:
2181 case RISCV::PseudoCCQC_E_LH:
2182 case RISCV::PseudoCCQC_E_LW:
2183 case RISCV::PseudoCCQC_E_LHU:
2184 case RISCV::PseudoCCQC_E_LBU:
2185 return get(
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm())
2188 case TargetOpcode::STACKMAP:
2191 case TargetOpcode::PATCHPOINT:
2194 case TargetOpcode::STATEPOINT: {
2198 return std::max(NumBytes, 8U);
2200 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
2201 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
2202 case TargetOpcode::PATCHABLE_TAIL_CALL: {
2205 if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
2206 F.hasFnAttribute(
"patchable-function-entry")) {
2208 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
2210 return (
STI.hasStdExtZca() ? 2 : 4) * Num;
2214 return STI.is64Bit() ? 68 : 44;
2217 return get(Opcode).getSize();
2222 const unsigned Opcode =
MI.getOpcode();
2226 case RISCV::FSGNJ_D:
2227 case RISCV::FSGNJ_S:
2228 case RISCV::FSGNJ_H:
2229 case RISCV::FSGNJ_D_INX:
2230 case RISCV::FSGNJ_D_IN32X:
2231 case RISCV::FSGNJ_S_INX:
2232 case RISCV::FSGNJ_H_INX:
2234 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2235 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
2239 return (
MI.getOperand(1).isReg() &&
2240 MI.getOperand(1).getReg() == RISCV::X0) ||
2241 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
2243 return MI.isAsCheapAsAMove();
2246std::optional<DestSourcePair>
2250 switch (
MI.getOpcode()) {
2256 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2257 MI.getOperand(2).isReg())
2259 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2260 MI.getOperand(1).isReg())
2265 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
2266 MI.getOperand(2).getImm() == 0)
2270 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2271 MI.getOperand(1).isReg())
2275 case RISCV::SH1ADD_UW:
2277 case RISCV::SH2ADD_UW:
2279 case RISCV::SH3ADD_UW:
2280 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2281 MI.getOperand(2).isReg())
2284 case RISCV::FSGNJ_D:
2285 case RISCV::FSGNJ_S:
2286 case RISCV::FSGNJ_H:
2287 case RISCV::FSGNJ_D_INX:
2288 case RISCV::FSGNJ_D_IN32X:
2289 case RISCV::FSGNJ_S_INX:
2290 case RISCV::FSGNJ_H_INX:
2292 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2293 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
2297 return std::nullopt;
2301 std::optional<MachineTraceStrategy> Forced =
2302 STI.getCLOpts().force_machine_combiner_strategy;
2307 const auto &SchedModel =
STI.getSchedModel();
2308 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
2320 RISCV::getNamedOperandIdx(Root.
getOpcode(), RISCV::OpName::frm);
2324 return RISCV::getNamedOperandIdx(
MI->getOpcode(),
2325 RISCV::OpName::frm) < 0;
2327 "New instructions require FRM whereas the old one does not have it");
2334 for (
auto *NewMI : InsInstrs) {
2336 if (
static_cast<unsigned>(RISCV::getNamedOperandIdx(
2337 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
2379bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
2380 bool Invert)
const {
2381#define OPCODE_LMUL_CASE(OPC) \
2382 case RISCV::OPC##_M1: \
2383 case RISCV::OPC##_M2: \
2384 case RISCV::OPC##_M4: \
2385 case RISCV::OPC##_M8: \
2386 case RISCV::OPC##_MF2: \
2387 case RISCV::OPC##_MF4: \
2388 case RISCV::OPC##_MF8
2390#define OPCODE_LMUL_MASK_CASE(OPC) \
2391 case RISCV::OPC##_M1_MASK: \
2392 case RISCV::OPC##_M2_MASK: \
2393 case RISCV::OPC##_M4_MASK: \
2394 case RISCV::OPC##_M8_MASK: \
2395 case RISCV::OPC##_MF2_MASK: \
2396 case RISCV::OPC##_MF4_MASK: \
2397 case RISCV::OPC##_MF8_MASK
2402 Opcode = *InvOpcode;
2419#undef OPCODE_LMUL_MASK_CASE
2420#undef OPCODE_LMUL_CASE
2423bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
2436 auto checkImmOperand = [&](
unsigned OpIdx) {
2440 auto checkRegOperand = [&](
unsigned OpIdx) {
2448 if (!checkRegOperand(1))
2463 bool SeenMI2 =
false;
2464 for (
auto End =
MBB->
rend(), It = It1; It != End; ++It) {
2473 if (It->modifiesRegister(RISCV::V0,
TRI)) {
2474 Register SrcReg = It->getOperand(1).getReg();
2492 if (MI1VReg != SrcReg)
2501 assert(SeenMI2 &&
"Prev is expected to appear before Root");
2512 const MachineOperand &Op1 = Root.
getOperand(OpIdx);
2513 const MachineOperand &Op2 = Prev.
getOperand(OpIdx);
2541bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
2542 bool &Commuted)
const {
2546 "Expect the present of passthrough operand.");
2552 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
2553 areRVVInstsReassociable(Inst, *MI2);
2557 return areRVVInstsReassociable(Inst, *MI1) &&
2558 (isVectorAssociativeAndCommutative(*MI1) ||
2559 isVectorAssociativeAndCommutative(*MI1,
true)) &&
2566 if (!isVectorAssociativeAndCommutative(Inst) &&
2567 !isVectorAssociativeAndCommutative(Inst,
true))
2593 for (
unsigned I = 0;
I < 5; ++
I)
2599 bool &Commuted)
const {
2600 if (isVectorAssociativeAndCommutative(Inst) ||
2601 isVectorAssociativeAndCommutative(Inst,
true))
2602 return hasReassociableVectorSibling(Inst, Commuted);
2608 unsigned OperandIdx = Commuted ? 2 : 1;
2612 int16_t InstFrmOpIdx =
2613 RISCV::getNamedOperandIdx(Inst.
getOpcode(), RISCV::OpName::frm);
2614 int16_t SiblingFrmOpIdx =
2615 RISCV::getNamedOperandIdx(Sibling.
getOpcode(), RISCV::OpName::frm);
2617 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
2622 bool Invert)
const {
2623 if (isVectorAssociativeAndCommutative(Inst, Invert))
2631 Opc = *InverseOpcode;
2676std::optional<unsigned>
2678#define RVV_OPC_LMUL_CASE(OPC, INV) \
2679 case RISCV::OPC##_M1: \
2680 return RISCV::INV##_M1; \
2681 case RISCV::OPC##_M2: \
2682 return RISCV::INV##_M2; \
2683 case RISCV::OPC##_M4: \
2684 return RISCV::INV##_M4; \
2685 case RISCV::OPC##_M8: \
2686 return RISCV::INV##_M8; \
2687 case RISCV::OPC##_MF2: \
2688 return RISCV::INV##_MF2; \
2689 case RISCV::OPC##_MF4: \
2690 return RISCV::INV##_MF4; \
2691 case RISCV::OPC##_MF8: \
2692 return RISCV::INV##_MF8
2694#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
2695 case RISCV::OPC##_M1_MASK: \
2696 return RISCV::INV##_M1_MASK; \
2697 case RISCV::OPC##_M2_MASK: \
2698 return RISCV::INV##_M2_MASK; \
2699 case RISCV::OPC##_M4_MASK: \
2700 return RISCV::INV##_M4_MASK; \
2701 case RISCV::OPC##_M8_MASK: \
2702 return RISCV::INV##_M8_MASK; \
2703 case RISCV::OPC##_MF2_MASK: \
2704 return RISCV::INV##_MF2_MASK; \
2705 case RISCV::OPC##_MF4_MASK: \
2706 return RISCV::INV##_MF4_MASK; \
2707 case RISCV::OPC##_MF8_MASK: \
2708 return RISCV::INV##_MF8_MASK
2712 return std::nullopt;
2714 return RISCV::FSUB_H;
2716 return RISCV::FSUB_S;
2718 return RISCV::FSUB_D;
2720 return RISCV::FADD_H;
2722 return RISCV::FADD_S;
2724 return RISCV::FADD_D;
2741#undef RVV_OPC_LMUL_MASK_CASE
2742#undef RVV_OPC_LMUL_CASE
2747 bool DoRegPressureReduce) {
2774 bool DoRegPressureReduce) {
2781 DoRegPressureReduce)) {
2787 DoRegPressureReduce)) {
2797 bool DoRegPressureReduce) {
2805 unsigned CombineOpc) {
2812 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2826 unsigned OuterShiftAmt) {
2832 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2859 case RISCV::SH1ADD_UW:
2861 case RISCV::SH2ADD_UW:
2863 case RISCV::SH3ADD_UW:
2909 bool DoRegPressureReduce)
const {
2918 DoRegPressureReduce);
2926 return RISCV::FMADD_H;
2928 return RISCV::FMADD_S;
2930 return RISCV::FMADD_D;
2975 bool Mul1IsKill = Mul1.
isKill();
2976 bool Mul2IsKill = Mul2.
isKill();
2977 bool AddendIsKill = Addend.
isKill();
2986 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
3011 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
3018 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
3021 switch (InnerShiftAmt - OuterShiftAmt) {
3025 InnerOpc = RISCV::ADD;
3028 InnerOpc = RISCV::SH1ADD;
3031 InnerOpc = RISCV::SH2ADD;
3034 InnerOpc = RISCV::SH3ADD;
3052 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
3069 DelInstrs, InstrIdxForVirtReg);
3096 for (
const auto &[Index, Operand] :
enumerate(
Desc.operands())) {
3098 unsigned OpType = Operand.OperandType;
3104 ErrInfo =
"Expected an immediate operand.";
3113#define CASE_OPERAND_UIMM(NUM) \
3114 case RISCVOp::OPERAND_UIMM##NUM: \
3115 Ok = isUInt<NUM>(Imm); \
3117#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX) \
3118 case RISCVOp::OPERAND_UIMM##BITS##_LSB##SUFFIX: { \
3119 constexpr size_t NumZeros = sizeof(#SUFFIX) - 1; \
3120 Ok = isShiftedUInt<BITS - NumZeros, NumZeros>(Imm); \
3123#define CASE_OPERAND_SIMM(NUM) \
3124 case RISCVOp::OPERAND_SIMM##NUM: \
3125 Ok = isInt<NUM>(Imm); \
3154 Ok =
Imm >= 1 &&
Imm <= 16;
3163 Ok =
Imm >= 1 &&
Imm <= 32;
3166 Ok =
Imm >= 1 &&
Imm <= 64;
3202 Ok =
Imm >= -15 &&
Imm <= 16;
3230 Ok = Ok &&
Imm != 0;
3236 Ok =
Imm >= 0 &&
Imm <= 10;
3239 Ok =
Imm >= 0 &&
Imm <= 7;
3242 Ok =
Imm >= 1 &&
Imm <= 10;
3245 Ok =
Imm >= 2 &&
Imm <= 14;
3254 Ok =
Imm >= 0 &&
Imm <= 48 &&
Imm % 16 == 0;
3299 ErrInfo =
"Invalid immediate";
3308 ErrInfo =
"Expected a non-register operand.";
3312 ErrInfo =
"Invalid immediate";
3321 ErrInfo =
"Expected a non-register operand.";
3325 ErrInfo =
"Invalid immediate";
3333 ErrInfo =
"Expected a non-register operand.";
3337 ErrInfo =
"Invalid immediate";
3346 ErrInfo =
"Invalid immediate";
3349 }
else if (!MO.
isReg()) {
3350 ErrInfo =
"Expected a register or immediate operand.";
3356 ErrInfo =
"Expected a register or immediate operand.";
3363 const uint64_t TSFlags =
Desc.TSFlags;
3366 if (!
Op.isImm() && !
Op.isReg()) {
3367 ErrInfo =
"Invalid operand type for VL operand";
3370 if (
Op.isReg() &&
Op.getReg().isValid()) {
3373 if (!RISCV::GPRNoX0RegClass.hasSubClassEq(RC)) {
3374 ErrInfo =
"Invalid register class for VL operand";
3379 ErrInfo =
"VL operand w/o SEW operand?";
3385 if (!
MI.getOperand(OpIdx).isImm()) {
3386 ErrInfo =
"SEW value expected to be an immediate";
3389 uint64_t Log2SEW =
MI.getOperand(OpIdx).getImm();
3391 ErrInfo =
"Unexpected SEW value";
3394 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3396 ErrInfo =
"Unexpected SEW value";
3402 if (!
MI.getOperand(OpIdx).isImm()) {
3403 ErrInfo =
"Policy operand expected to be an immediate";
3406 uint64_t Policy =
MI.getOperand(OpIdx).getImm();
3408 ErrInfo =
"Invalid Policy Value";
3412 ErrInfo =
"policy operand w/o VL operand?";
3420 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
3421 ErrInfo =
"policy operand w/o tied operand?";
3428 !
MI.readsRegister(RISCV::FRM,
nullptr)) {
3429 ErrInfo =
"dynamic rounding mode should read FRM";
3451 case RISCV::LD_RV32:
3461 case RISCV::SD_RV32:
3477 int64_t NewOffset = OldOffset + Disp;
3499 "Addressing mode not supported for folding");
3571 case RISCV::LD_RV32:
3574 case RISCV::SD_RV32:
3581 OffsetIsScalable =
false;
3597 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
3605 if (MO1->getAddrSpace() != MO2->getAddrSpace())
3608 auto Base1 = MO1->getValue();
3609 auto Base2 = MO2->getValue();
3610 if (!Base1 || !Base2)
3618 return Base1 == Base2;
3624 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
3625 unsigned NumBytes)
const {
3628 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
3633 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
3639 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
3645 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
3694 int64_t OffsetA = 0, OffsetB = 0;
3700 int LowOffset = std::min(OffsetA, OffsetB);
3701 int HighOffset = std::max(OffsetA, OffsetB);
3702 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3704 LowOffset + (
int)LowWidth.
getValue() <= HighOffset)
3711std::pair<unsigned, unsigned>
3714 return std::make_pair(TF & Mask, TF & ~Mask);
3720 static const std::pair<unsigned, const char *> TargetFlags[] = {
3721 {MO_CALL,
"riscv-call"},
3722 {MO_LO,
"riscv-lo"},
3723 {MO_HI,
"riscv-hi"},
3724 {MO_PCREL_LO,
"riscv-pcrel-lo"},
3725 {MO_PCREL_HI,
"riscv-pcrel-hi"},
3726 {MO_GOT_HI,
"riscv-got-hi"},
3727 {MO_TPREL_LO,
"riscv-tprel-lo"},
3728 {MO_TPREL_HI,
"riscv-tprel-hi"},
3729 {MO_TPREL_ADD,
"riscv-tprel-add"},
3730 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
3731 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
3732 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
3733 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
3734 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
3735 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"},
3736 {MO_QC_ACCESS,
"riscv-qc-access"},
3745 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
3758 unsigned &Flags)
const {
3778 return F.getFnAttribute(
"fentry-call").getValueAsBool() ||
3779 F.hasFnAttribute(
"patchable-function-entry");
3784 return MI.readsRegister(RegNo,
TRI) ||
3785 MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
3790 return MI.modifiesRegister(RegNo,
TRI) ||
3791 MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
3795 if (!
MBB.back().isReturn())
3841 if (
C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
3842 C.isAvailableInsideSeq(
Reg,
TRI)) {
3860 if (
C.back().isReturn() &&
3861 !
C.isAvailableAcrossAndOutOfSeq(TailExpandUseReg, RegInfo)) {
3863 LLVM_DEBUG(
dbgs() <<
"Cannot be outlined between: " <<
C.front() <<
"and "
3865 LLVM_DEBUG(
dbgs() <<
"Because the tail-call register is live across "
3866 "the proposed outlined function call\n");
3872 if (
C.back().isReturn()) {
3874 "The candidate who uses return instruction must be outlined "
3881 if (!
C.isAvailableInsideSeq(RISCV::X5, RegInfo))
3885 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo))
3895std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3898 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3899 unsigned MinRepeats)
const {
3907 if (RepeatedSequenceLocs.size() < MinRepeats)
3908 return std::nullopt;
3912 unsigned InstrSizeCExt =
3914 unsigned CallOverhead = 0, FrameOverhead = 0;
3917 unsigned CFICount = 0;
3918 for (
auto &
I : Candidate) {
3919 if (
I.isCFIInstruction())
3930 std::vector<MCCFIInstruction> CFIInstructions =
3931 C.getMF()->getFrameInstructions();
3933 if (CFICount > 0 && CFICount != CFIInstructions.size())
3934 return std::nullopt;
3942 CallOverhead = 4 + InstrSizeCExt;
3949 FrameOverhead = InstrSizeCExt;
3955 return std::nullopt;
3959 for (
auto &
C : RepeatedSequenceLocs) {
3961 if (
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, RegInfo)) {
3963 unsigned CandCallOverhead = 8;
3968 unsigned CandCallOverhead = InstrSizeCExt + 8 + InstrSizeCExt;
3973 for (
auto &
C : RepeatedSequenceLocs)
3974 C.setCallInfo(MOCI, CallOverhead);
3977 unsigned SequenceSize = 0;
3978 for (
auto &
MI : Candidate)
3981 return std::make_unique<outliner::OutlinedFunction>(
3982 RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
3988 unsigned Flags)
const {
3992 MBB->getParent()->getSubtarget().getRegisterInfo();
3993 const auto &
F =
MI.getMF()->getFunction();
3998 if (
MI.isCFIInstruction())
4006 for (
const auto &MO :
MI.operands()) {
4011 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
4012 F.hasSection() ||
F.getSectionPrefix()))
4029 MBB.addLiveIn(RISCV::X5);
4047 .addGlobalAddress(M.getNamedValue(MF.
getName()),
4054 assert(SaveReg &&
"Cannot find an available register to save/restore X5.");
4065 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4081 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
4089 bool AllowSideEffects)
const {
4094 if (
TRI.isGeneralPurposeRegister(MF, Reg)) {
4096 }
else if (RISCV::FPR32RegClass.
contains(Reg)) {
4098 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
4100 }
else if (RISCV::FPR128RegClass.
contains(Reg)) {
4102 }
else if (RISCV::VRRegClass.
contains(Reg)) {
4106 "buildClearRegister is not implemented for " +
TRI.getRegAsmName(Reg));
4116 return std::nullopt;
4120 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
4121 MI.getOperand(2).isImm())
4122 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
4124 return std::nullopt;
4130 unsigned OpIdx)
const {
4132 std::string GenericComment =
4134 if (!GenericComment.empty())
4135 return GenericComment;
4138 if (OpIdx >=
Desc.getNumOperands())
4139 return std::string();
4141 std::string Comment;
4148 switch (OpInfo.OperandType) {
4151 unsigned Imm =
Op.getImm();
4156 unsigned Imm =
Op.getImm();
4161 unsigned Imm =
Op.getImm();
4167 unsigned Log2SEW =
Op.getImm();
4168 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
4174 unsigned Policy =
Op.getImm();
4176 "Invalid Policy Value");
4182 if (
Op.isImm() &&
Op.getImm() == -1)
4204#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
4205 RISCV::Pseudo##OP##_##LMUL
4207#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
4208 RISCV::Pseudo##OP##_##LMUL##_MASK
4210#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
4211 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
4212 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
4214#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
4215 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
4216 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
4217 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
4218 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
4219 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
4220 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
4222#define CASE_RVV_OPCODE_UNMASK(OP) \
4223 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4224 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
4226#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
4227 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
4228 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
4229 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
4230 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
4231 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
4232 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
4234#define CASE_RVV_OPCODE_MASK(OP) \
4235 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
4236 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
4238#define CASE_RVV_OPCODE_WIDEN(OP) \
4239 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
4240 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
4242#define CASE_RVV_OPCODE(OP) \
4243 CASE_RVV_OPCODE_UNMASK(OP): \
4244 case CASE_RVV_OPCODE_MASK(OP)
4248#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
4249 RISCV::PseudoV##OP##_##TYPE##_##LMUL
4251#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
4252 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
4253 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
4254 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
4255 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
4256 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
4257 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
4258 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
4261#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
4262 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
4264#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
4265 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
4266 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
4267 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
4268 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
4270#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
4271 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
4272 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
4274#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
4275 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
4276 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
4278#define CASE_VFMA_OPCODE_VV(OP) \
4279 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
4280 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VV, E16): \
4281 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
4282 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
4284#define CASE_VFMA_SPLATS(OP) \
4285 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
4286 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VFPR16, E16): \
4287 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
4288 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
4292 unsigned &SrcOpIdx1,
4293 unsigned &SrcOpIdx2)
const {
4295 if (!
Desc.isCommutable())
4298 switch (
MI.getOpcode()) {
4299 case RISCV::TH_MVEQZ:
4300 case RISCV::TH_MVNEZ:
4304 if (
MI.getOperand(2).getReg() == RISCV::X0)
4307 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4308 case RISCV::QC_SELECTIEQ:
4309 case RISCV::QC_SELECTINE:
4310 case RISCV::QC_SELECTIIEQ:
4311 case RISCV::QC_SELECTIINE:
4312 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4313 case RISCV::QC_MVEQ:
4314 case RISCV::QC_MVNE:
4315 case RISCV::QC_MVLT:
4316 case RISCV::QC_MVGE:
4317 case RISCV::QC_MVLTU:
4318 case RISCV::QC_MVGEU:
4319 case RISCV::QC_MVEQI:
4320 case RISCV::QC_MVNEI:
4321 case RISCV::QC_MVLTI:
4322 case RISCV::QC_MVGEI:
4323 case RISCV::QC_MVLTUI:
4324 case RISCV::QC_MVGEUI:
4325 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 4);
4326 case RISCV::TH_MULA:
4327 case RISCV::TH_MULAW:
4328 case RISCV::TH_MULAH:
4329 case RISCV::TH_MULS:
4330 case RISCV::TH_MULSW:
4331 case RISCV::TH_MULSH:
4333 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4334 case RISCV::PseudoCCMOVGPRNoX0:
4335 case RISCV::PseudoCCMOVGPR:
4337 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
4378 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
4405 unsigned CommutableOpIdx1 = 1;
4406 unsigned CommutableOpIdx2 = 3;
4407 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4428 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
4430 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
4434 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
4435 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
4441 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
4442 SrcOpIdx2 == CommuteAnyOperandIndex) {
4445 unsigned CommutableOpIdx1 = SrcOpIdx1;
4446 if (SrcOpIdx1 == SrcOpIdx2) {
4449 CommutableOpIdx1 = 1;
4450 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
4452 CommutableOpIdx1 = SrcOpIdx2;
4457 unsigned CommutableOpIdx2;
4458 if (CommutableOpIdx1 != 1) {
4460 CommutableOpIdx2 = 1;
4462 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
4467 if (Op1Reg !=
MI.getOperand(2).getReg())
4468 CommutableOpIdx2 = 2;
4470 CommutableOpIdx2 = 3;
4475 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4488#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
4489 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
4490 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
4493#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
4494 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
4495 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
4496 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
4497 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
4498 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
4499 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
4500 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
4503#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
4504 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
4505 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
4508#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
4509 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
4510 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
4511 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
4512 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
4514#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
4515 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
4516 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
4518#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
4519 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
4520 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
4522#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
4523 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
4524 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VV, E16) \
4525 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
4526 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
4528#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
4529 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
4530 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VFPR16, E16) \
4531 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
4532 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
4538 unsigned OpIdx2)
const {
4541 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
4545 switch (
MI.getOpcode()) {
4546 case RISCV::TH_MVEQZ:
4547 case RISCV::TH_MVNEZ: {
4548 auto &WorkingMI = cloneIfNew(
MI);
4549 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
4550 : RISCV::TH_MVEQZ));
4554 case RISCV::QC_SELECTIEQ:
4555 case RISCV::QC_SELECTINE:
4556 case RISCV::QC_SELECTIIEQ:
4557 case RISCV::QC_SELECTIINE:
4559 case RISCV::QC_MVEQ:
4560 case RISCV::QC_MVNE:
4561 case RISCV::QC_MVLT:
4562 case RISCV::QC_MVGE:
4563 case RISCV::QC_MVLTU:
4564 case RISCV::QC_MVGEU:
4565 case RISCV::QC_MVEQI:
4566 case RISCV::QC_MVNEI:
4567 case RISCV::QC_MVLTI:
4568 case RISCV::QC_MVGEI:
4569 case RISCV::QC_MVLTUI:
4570 case RISCV::QC_MVGEUI: {
4571 auto &WorkingMI = cloneIfNew(
MI);
4576 case RISCV::PseudoCCMOVGPRNoX0:
4577 case RISCV::PseudoCCMOVGPR: {
4579 unsigned BCC =
MI.getOperand(
MI.getNumExplicitOperands() - 3).getImm();
4581 auto &WorkingMI = cloneIfNew(
MI);
4582 WorkingMI.getOperand(
MI.getNumExplicitOperands() - 3).setImm(BCC);
4606 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4607 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
4609 switch (
MI.getOpcode()) {
4632 auto &WorkingMI = cloneIfNew(
MI);
4633 WorkingMI.setDesc(
get(
Opc));
4643 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4646 if (OpIdx1 == 3 || OpIdx2 == 3) {
4648 switch (
MI.getOpcode()) {
4659 auto &WorkingMI = cloneIfNew(
MI);
4660 WorkingMI.setDesc(
get(
Opc));
4672#undef CASE_VMA_CHANGE_OPCODE_COMMON
4673#undef CASE_VMA_CHANGE_OPCODE_LMULS
4674#undef CASE_VFMA_CHANGE_OPCODE_COMMON
4675#undef CASE_VFMA_CHANGE_OPCODE_LMULS_M1
4676#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF2
4677#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF4
4678#undef CASE_VFMA_CHANGE_OPCODE_VV
4679#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
4681#undef CASE_RVV_OPCODE_UNMASK_LMUL
4682#undef CASE_RVV_OPCODE_MASK_LMUL
4683#undef CASE_RVV_OPCODE_LMUL
4684#undef CASE_RVV_OPCODE_UNMASK_WIDEN
4685#undef CASE_RVV_OPCODE_UNMASK
4686#undef CASE_RVV_OPCODE_MASK_WIDEN
4687#undef CASE_RVV_OPCODE_MASK
4688#undef CASE_RVV_OPCODE_WIDEN
4689#undef CASE_RVV_OPCODE
4691#undef CASE_VMA_OPCODE_COMMON
4692#undef CASE_VMA_OPCODE_LMULS
4693#undef CASE_VFMA_OPCODE_COMMON
4694#undef CASE_VFMA_OPCODE_LMULS_M1
4695#undef CASE_VFMA_OPCODE_LMULS_MF2
4696#undef CASE_VFMA_OPCODE_LMULS_MF4
4697#undef CASE_VFMA_OPCODE_VV
4698#undef CASE_VFMA_SPLATS
4701 switch (
MI.getOpcode()) {
4709 if (
MI.getOperand(1).getReg() == RISCV::X0)
4710 commuteInstruction(
MI);
4712 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4713 MI.getOperand(2).ChangeToImmediate(0);
4714 MI.setDesc(
get(RISCV::ADDI));
4718 if (
MI.getOpcode() == RISCV::XOR &&
4719 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4720 MI.getOperand(1).setReg(RISCV::X0);
4721 MI.getOperand(2).ChangeToImmediate(0);
4722 MI.setDesc(
get(RISCV::ADDI));
4729 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4730 MI.setDesc(
get(RISCV::ADDI));
4736 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4737 MI.getOperand(2).ChangeToImmediate(0);
4738 MI.setDesc(
get(RISCV::ADDI));
4744 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4745 MI.getOperand(2).ChangeToImmediate(0);
4746 MI.setDesc(
get(RISCV::ADDIW));
4753 if (
MI.getOperand(1).getReg() == RISCV::X0)
4754 commuteInstruction(
MI);
4756 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4757 MI.getOperand(2).ChangeToImmediate(0);
4758 MI.setDesc(
get(RISCV::ADDIW));
4763 case RISCV::SH1ADD_UW:
4765 case RISCV::SH2ADD_UW:
4767 case RISCV::SH3ADD_UW:
4769 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4770 MI.removeOperand(1);
4772 MI.setDesc(
get(RISCV::ADDI));
4776 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4777 MI.removeOperand(2);
4778 unsigned Opc =
MI.getOpcode();
4779 if (
Opc == RISCV::SH1ADD_UW ||
Opc == RISCV::SH2ADD_UW ||
4780 Opc == RISCV::SH3ADD_UW) {
4782 MI.setDesc(
get(RISCV::SLLI_UW));
4786 MI.setDesc(
get(RISCV::SLLI));
4800 if (
MI.getOperand(1).getReg() == RISCV::X0 ||
4801 MI.getOperand(2).getReg() == RISCV::X0) {
4802 MI.getOperand(1).setReg(RISCV::X0);
4803 MI.getOperand(2).ChangeToImmediate(0);
4804 MI.setDesc(
get(RISCV::ADDI));
4810 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4811 MI.getOperand(2).setImm(0);
4812 MI.setDesc(
get(RISCV::ADDI));
4820 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4821 MI.getOperand(2).ChangeToImmediate(0);
4822 MI.setDesc(
get(RISCV::ADDI));
4826 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4827 MI.getOperand(2).ChangeToImmediate(0);
4828 MI.setDesc(
get(RISCV::ADDI));
4836 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4837 MI.getOperand(2).ChangeToImmediate(0);
4838 MI.setDesc(
get(RISCV::ADDI));
4848 case RISCV::SLLI_UW:
4850 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4851 MI.getOperand(2).setImm(0);
4852 MI.setDesc(
get(RISCV::ADDI));
4860 if (
MI.getOperand(1).getReg() == RISCV::X0 &&
4861 MI.getOperand(2).getReg() == RISCV::X0) {
4862 MI.getOperand(2).ChangeToImmediate(0);
4863 MI.setDesc(
get(RISCV::ADDI));
4867 if (
MI.getOpcode() == RISCV::ADD_UW &&
4868 MI.getOperand(1).getReg() == RISCV::X0) {
4869 MI.removeOperand(1);
4871 MI.setDesc(
get(RISCV::ADDI));
4877 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4878 MI.getOperand(2).setImm(
MI.getOperand(2).getImm() != 0);
4879 MI.setDesc(
get(RISCV::ADDI));
4885 case RISCV::ZEXT_H_RV32:
4886 case RISCV::ZEXT_H_RV64:
4889 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4891 MI.setDesc(
get(RISCV::ADDI));
4900 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4901 MI.getOperand(2).ChangeToImmediate(0);
4902 MI.setDesc(
get(RISCV::ADDI));
4909 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4911 MI.removeOperand(0);
4912 MI.insert(
MI.operands_begin() + 1, {MO0});
4917 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4919 MI.removeOperand(0);
4920 MI.insert(
MI.operands_begin() + 1, {MO0});
4921 MI.setDesc(
get(RISCV::BNE));
4926 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4928 MI.removeOperand(0);
4929 MI.insert(
MI.operands_begin() + 1, {MO0});
4930 MI.setDesc(
get(RISCV::BEQ));
4938#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
4939 RISCV::PseudoV##OP##_##LMUL##_TIED
4941#define CASE_WIDEOP_OPCODE_LMULS(OP) \
4942 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
4943 case CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
4944 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
4945 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
4946 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
4947 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
4949#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
4950 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
4951 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
4954#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4955 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
4956 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
4957 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
4958 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
4959 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
4960 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
4963#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
4964 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
4966#define CASE_FP_WIDEOP_OPCODE_LMULS(OP) \
4967 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4968 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4969 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
4970 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4971 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
4972 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4973 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
4974 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
4975 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
4977#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
4978 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
4979 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
4982#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4983 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4984 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4985 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
4986 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
4987 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
4988 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
4989 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
4990 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
4991 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
4993#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP) \
4994 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4995 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4996 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4997 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4998 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16)
5000#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(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, M1, E16) \
5004 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
5005 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16)
5011 switch (
MI.getOpcode()) {
5019 MI.getNumExplicitOperands() == 7 &&
5020 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
5027 switch (
MI.getOpcode()) {
5039 .
add(
MI.getOperand(0))
5041 .
add(
MI.getOperand(1))
5042 .
add(
MI.getOperand(2))
5043 .
add(
MI.getOperand(3))
5044 .
add(
MI.getOperand(4))
5045 .
add(
MI.getOperand(5))
5046 .
add(
MI.getOperand(6));
5055 MI.getNumExplicitOperands() == 6);
5062 switch (
MI.getOpcode()) {
5074 .
add(
MI.getOperand(0))
5076 .
add(
MI.getOperand(1))
5077 .
add(
MI.getOperand(2))
5078 .
add(
MI.getOperand(3))
5079 .
add(
MI.getOperand(4))
5080 .
add(
MI.getOperand(5));
5089 if (
MI.getOperand(0).isEarlyClobber()) {
5095 if (S->
end == Idx.getRegSlot(
true))
5096 S->
end = Idx.getRegSlot();
5103#undef CASE_WIDEOP_OPCODE_COMMON
5104#undef CASE_WIDEOP_OPCODE_LMULS
5105#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
5106#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
5107#undef CASE_FP_WIDEOP_OPCODE_COMMON
5108#undef CASE_FP_WIDEOP_OPCODE_LMULS
5109#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
5110#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
5119 if (ShiftAmount == 0)
5125 }
else if (
int ShXAmount, ShiftAmount;
5127 (ShXAmount =
isShifted359(Amount, ShiftAmount)) != 0) {
5130 switch (ShXAmount) {
5132 Opc = RISCV::SH1ADD;
5135 Opc = RISCV::SH2ADD;
5138 Opc = RISCV::SH3ADD;
5174 }
else if (
STI.hasStdExtZmmul()) {
5184 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
5185 if (Amount & (1U << ShiftAmount)) {
5189 .
addImm(ShiftAmount - PrevShiftAmount)
5191 if (Amount >> (ShiftAmount + 1)) {
5205 PrevShiftAmount = ShiftAmount;
5208 assert(Acc &&
"Expected valid accumulator");
5218 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
5226 ?
STI.getTailDupAggressiveThreshold()
5233 unsigned Opcode =
MI.getOpcode();
5234 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
5243 return MI.isCopy() &&
MI.getOperand(0).getReg().isPhysical() &&
5245 TRI->getMinimalPhysRegClass(
MI.getOperand(0).getReg()));
5248std::optional<std::pair<unsigned, unsigned>>
5252 return std::nullopt;
5253 case RISCV::PseudoVSPILL2_M1:
5254 case RISCV::PseudoVRELOAD2_M1:
5255 return std::make_pair(2u, 1u);
5256 case RISCV::PseudoVSPILL2_M2:
5257 case RISCV::PseudoVRELOAD2_M2:
5258 return std::make_pair(2u, 2u);
5259 case RISCV::PseudoVSPILL2_M4:
5260 case RISCV::PseudoVRELOAD2_M4:
5261 return std::make_pair(2u, 4u);
5262 case RISCV::PseudoVSPILL3_M1:
5263 case RISCV::PseudoVRELOAD3_M1:
5264 return std::make_pair(3u, 1u);
5265 case RISCV::PseudoVSPILL3_M2:
5266 case RISCV::PseudoVRELOAD3_M2:
5267 return std::make_pair(3u, 2u);
5268 case RISCV::PseudoVSPILL4_M1:
5269 case RISCV::PseudoVRELOAD4_M1:
5270 return std::make_pair(4u, 1u);
5271 case RISCV::PseudoVSPILL4_M2:
5272 case RISCV::PseudoVRELOAD4_M2:
5273 return std::make_pair(4u, 2u);
5274 case RISCV::PseudoVSPILL5_M1:
5275 case RISCV::PseudoVRELOAD5_M1:
5276 return std::make_pair(5u, 1u);
5277 case RISCV::PseudoVSPILL6_M1:
5278 case RISCV::PseudoVRELOAD6_M1:
5279 return std::make_pair(6u, 1u);
5280 case RISCV::PseudoVSPILL7_M1:
5281 case RISCV::PseudoVRELOAD7_M1:
5282 return std::make_pair(7u, 1u);
5283 case RISCV::PseudoVSPILL8_M1:
5284 case RISCV::PseudoVRELOAD8_M1:
5285 return std::make_pair(8u, 1u);
5290 int16_t MI1FrmOpIdx =
5291 RISCV::getNamedOperandIdx(MI1.
getOpcode(), RISCV::OpName::frm);
5292 int16_t MI2FrmOpIdx =
5293 RISCV::getNamedOperandIdx(MI2.
getOpcode(), RISCV::OpName::frm);
5294 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
5301std::optional<unsigned>
5305 return std::nullopt;
5308 case RISCV::VSLL_VX:
5309 case RISCV::VSRL_VX:
5310 case RISCV::VSRA_VX:
5312 case RISCV::VSSRL_VX:
5313 case RISCV::VSSRA_VX:
5315 case RISCV::VROL_VX:
5316 case RISCV::VROR_VX:
5321 case RISCV::VNSRL_WX:
5322 case RISCV::VNSRA_WX:
5324 case RISCV::VNCLIPU_WX:
5325 case RISCV::VNCLIP_WX:
5327 case RISCV::VWSLL_VX:
5332 case RISCV::VADD_VX:
5333 case RISCV::VSUB_VX:
5334 case RISCV::VRSUB_VX:
5336 case RISCV::VWADDU_VX:
5337 case RISCV::VWSUBU_VX:
5338 case RISCV::VWADD_VX:
5339 case RISCV::VWSUB_VX:
5340 case RISCV::VWADDU_WX:
5341 case RISCV::VWSUBU_WX:
5342 case RISCV::VWADD_WX:
5343 case RISCV::VWSUB_WX:
5345 case RISCV::VADC_VXM:
5346 case RISCV::VADC_VIM:
5347 case RISCV::VMADC_VXM:
5348 case RISCV::VMADC_VIM:
5349 case RISCV::VMADC_VX:
5350 case RISCV::VSBC_VXM:
5351 case RISCV::VMSBC_VXM:
5352 case RISCV::VMSBC_VX:
5354 case RISCV::VAND_VX:
5356 case RISCV::VXOR_VX:
5358 case RISCV::VMSEQ_VX:
5359 case RISCV::VMSNE_VX:
5360 case RISCV::VMSLTU_VX:
5361 case RISCV::VMSLT_VX:
5362 case RISCV::VMSLEU_VX:
5363 case RISCV::VMSLE_VX:
5364 case RISCV::VMSGTU_VX:
5365 case RISCV::VMSGT_VX:
5367 case RISCV::VMINU_VX:
5368 case RISCV::VMIN_VX:
5369 case RISCV::VMAXU_VX:
5370 case RISCV::VMAX_VX:
5372 case RISCV::VMUL_VX:
5373 case RISCV::VMULH_VX:
5374 case RISCV::VMULHU_VX:
5375 case RISCV::VMULHSU_VX:
5377 case RISCV::VDIVU_VX:
5378 case RISCV::VDIV_VX:
5379 case RISCV::VREMU_VX:
5380 case RISCV::VREM_VX:
5382 case RISCV::VWMUL_VX:
5383 case RISCV::VWMULU_VX:
5384 case RISCV::VWMULSU_VX:
5386 case RISCV::VMACC_VX:
5387 case RISCV::VNMSAC_VX:
5388 case RISCV::VMADD_VX:
5389 case RISCV::VNMSUB_VX:
5391 case RISCV::VWMACCU_VX:
5392 case RISCV::VWMACC_VX:
5393 case RISCV::VWMACCSU_VX:
5394 case RISCV::VWMACCUS_VX:
5396 case RISCV::VMERGE_VXM:
5398 case RISCV::VMV_V_X:
5400 case RISCV::VSADDU_VX:
5401 case RISCV::VSADD_VX:
5402 case RISCV::VSSUBU_VX:
5403 case RISCV::VSSUB_VX:
5405 case RISCV::VAADDU_VX:
5406 case RISCV::VAADD_VX:
5407 case RISCV::VASUBU_VX:
5408 case RISCV::VASUB_VX:
5410 case RISCV::VSMUL_VX:
5412 case RISCV::VMV_S_X:
5414 case RISCV::VANDN_VX:
5415 return 1U << Log2SEW;
5421 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
5424 return RVV->BaseInstr;
5434 unsigned Scaled = Log2SEW + (DestEEW - 1);
5448 return std::nullopt;
5455 if (LHS.isReg() && RHS.isReg() && LHS.getReg().isVirtual() &&
5456 LHS.getReg() == RHS.getReg())
5460 if (LHS.isImm() && LHS.getImm() == 0)
5466 if (!LHSImm || !RHSImm)
5468 return LHSImm <= RHSImm;
5480 : LHS(LHS), RHS(RHS),
Cond(
Cond.begin(),
Cond.end()) {}
5482 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
5492 std::optional<bool> createTripCountGreaterCondition(
5493 int TC, MachineBasicBlock &
MBB,
5494 SmallVectorImpl<MachineOperand> &CondParam)
override {
5502 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
5504 void adjustTripCount(
int TripCountAdjust)
override {}
5508std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
5516 if (
TBB == LoopBB && FBB == LoopBB)
5523 assert((
TBB == LoopBB || FBB == LoopBB) &&
5524 "The Loop must be a single-basic-block loop");
5535 if (!Reg.isVirtual())
5542 if (LHS && LHS->isPHI())
5544 if (RHS && RHS->isPHI())
5547 return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS,
Cond);
5553 Opc = RVVMCOpcode ? RVVMCOpcode :
Opc;
5570 case RISCV::FDIV_H_INX:
5571 case RISCV::FDIV_S_INX:
5572 case RISCV::FDIV_D_INX:
5573 case RISCV::FDIV_D_IN32X:
5574 case RISCV::FSQRT_H:
5575 case RISCV::FSQRT_S:
5576 case RISCV::FSQRT_D:
5577 case RISCV::FSQRT_H_INX:
5578 case RISCV::FSQRT_S_INX:
5579 case RISCV::FSQRT_D_INX:
5580 case RISCV::FSQRT_D_IN32X:
5582 case RISCV::VDIV_VV:
5583 case RISCV::VDIV_VX:
5584 case RISCV::VDIVU_VV:
5585 case RISCV::VDIVU_VX:
5586 case RISCV::VREM_VV:
5587 case RISCV::VREM_VX:
5588 case RISCV::VREMU_VV:
5589 case RISCV::VREMU_VX:
5591 case RISCV::VFDIV_VV:
5592 case RISCV::VFDIV_VF:
5593 case RISCV::VFRDIV_VF:
5594 case RISCV::VFSQRT_V:
5595 case RISCV::VFRSQRT7_V:
5601 if (
MI->getOpcode() != TargetOpcode::COPY)
5606 Register DstReg =
MI->getOperand(0).getReg();
5609 :
TRI->getMinimalPhysRegClass(DstReg);
5619 auto [RCLMul, RCFractional] =
5621 return (!RCFractional && LMul == RCLMul) || (RCFractional && LMul == 1);
5625 if (
MI.memoperands_empty())
5640 if (MO.getReg().isPhysical())
5643 if (MO.getReg().isPhysical())
5645 bool SawStore =
false;
5648 if (
II->definesRegister(PhysReg,
nullptr))
5651 if (
II->definesRegister(PhysReg,
nullptr) ||
5652 II->readsRegister(PhysReg,
nullptr))
5654 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")
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static int getJumpTableIndexFromLoadAddr(const MachineRegisterInfo &MRI, Register Reg)
static bool isJumpTableLoad(const MachineInstr &MI)
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)
#define CASE_VFMA_SPLATS(OP)
unsigned getPredicatedOpcode(unsigned Opcode)
#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP)
#define CASE_WIDEOP_OPCODE_LMULS(OP)
static bool isMIReadsReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
#define OPCODE_LMUL_MASK_CASE(OPC)
#define CASE_OPERAND_UIMM_LSB_ZEROS(BITS, SUFFIX)
static bool isFSUB(unsigned Opc)
#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)
#define CASE_RVV_OPCODE(OP)
#define CASE_VFMA_OPCODE_VV(OP)
MachineOutlinerConstructionID
#define CASE_RVV_OPCODE_WIDEN(OP)
static unsigned getLoadPredicatedOpcode(unsigned Opcode)
static unsigned getSHXADDUWShiftAmount(unsigned Opc)
#define CASE_VMA_OPCODE_LMULS(OP, TYPE)
static bool isConvertibleToVMV_V_V(const RISCVSubtarget &STI, const MachineBasicBlock &MBB, MachineBasicBlock::const_iterator MBBI, MachineBasicBlock::const_iterator &DefMBBI, RISCVVType::VLMUL LMul)
static bool isFMUL(unsigned Opc)
static unsigned getInverseXqcicmOpcode(unsigned Opcode)
static bool getFPPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
#define OPCODE_LMUL_CASE(OPC)
#define CASE_OPERAND_UIMM(NUM)
static Register findRegisterToSaveX5To(outliner::Candidate &C, const TargetRegisterInfo &TRI)
static bool canCombineShiftIntoShXAdd(const MachineBasicBlock &MBB, const MachineOperand &MO, unsigned OuterShiftAmt)
Utility routine that checks if.
static bool isCandidatePatchable(const MachineBasicBlock &MBB)
static bool isFADD(unsigned Opc)
static void genShXAddAddShift(MachineInstr &Root, unsigned AddOpIdx, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
static bool isLoadImm(const MachineInstr *MI, int64_t &Imm)
static bool isMIModifiesReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
#define CASE_RVV_OPCODE_LMUL(OP, LMUL)
static 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 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
unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override
void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) 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 getMemOperandWithOffsetWidth(const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, LocationSize &Width) const
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.
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx) const override
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
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 RISCVOptions & getCLOpts() 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.
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 std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx) const
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.
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)
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.