41#define GEN_CHECK_COMPRESS_INSTR
42#include "RISCVGenCompressInstEmitter.inc"
44#define GET_INSTRINFO_CTOR_DTOR
45#define GET_INSTRINFO_NAMED_OPS
46#include "RISCVGenInstrInfo.inc"
48#define DEBUG_TYPE "riscv-instr-info"
50 "Number of registers within vector register groups spilled");
52 "Number of registers within vector register groups reloaded");
56 cl::desc(
"Prefer whole register move for vector registers."));
59 "riscv-force-machine-combiner-strategy",
cl::Hidden,
60 cl::desc(
"Force machine combiner to use a specific strategy for machine "
61 "trace metrics evaluation."),
66 "MinInstrCount strategy.")));
72#define GET_RISCVVPseudosTable_IMPL
73#include "RISCVGenSearchableTables.inc"
79#define GET_RISCVMaskedPseudosTable_IMPL
80#include "RISCVGenSearchableTables.inc"
86 RISCV::ADJCALLSTACKUP),
89#define GET_INSTRINFO_HELPERS
90#include "RISCVGenInstrInfo.inc"
93 if (
STI.hasStdExtZca())
102 int &FrameIndex)
const {
112 case RISCV::VL1RE8_V:
113 case RISCV::VL1RE16_V:
114 case RISCV::VL1RE32_V:
115 case RISCV::VL1RE64_V:
118 case RISCV::VL2RE8_V:
119 case RISCV::VL2RE16_V:
120 case RISCV::VL2RE32_V:
121 case RISCV::VL2RE64_V:
124 case RISCV::VL4RE8_V:
125 case RISCV::VL4RE16_V:
126 case RISCV::VL4RE32_V:
127 case RISCV::VL4RE64_V:
130 case RISCV::VL8RE8_V:
131 case RISCV::VL8RE16_V:
132 case RISCV::VL8RE32_V:
133 case RISCV::VL8RE64_V:
141 switch (
MI.getOpcode()) {
165 case RISCV::VL1RE8_V:
166 case RISCV::VL2RE8_V:
167 case RISCV::VL4RE8_V:
168 case RISCV::VL8RE8_V:
169 if (!
MI.getOperand(1).isFI())
171 FrameIndex =
MI.getOperand(1).getIndex();
174 return MI.getOperand(0).getReg();
177 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
178 MI.getOperand(2).getImm() == 0) {
179 FrameIndex =
MI.getOperand(1).getIndex();
180 return MI.getOperand(0).getReg();
187 int &FrameIndex)
const {
195 switch (
MI.getOpcode()) {
220 if (!
MI.getOperand(1).isFI())
222 FrameIndex =
MI.getOperand(1).getIndex();
225 return MI.getOperand(0).getReg();
228 if (
MI.getOperand(1).isFI() &&
MI.getOperand(2).isImm() &&
229 MI.getOperand(2).getImm() == 0) {
230 FrameIndex =
MI.getOperand(1).getIndex();
231 return MI.getOperand(0).getReg();
241 case RISCV::VFMV_V_F:
244 case RISCV::VFMV_S_F:
246 return MI.getOperand(1).isUndef();
254 return DstReg > SrcReg && (DstReg - SrcReg) < NumRegs;
265 assert(
MBBI->getOpcode() == TargetOpcode::COPY &&
266 "Unexpected COPY instruction.");
270 bool FoundDef =
false;
271 bool FirstVSetVLI =
false;
272 unsigned FirstSEW = 0;
275 if (
MBBI->isMetaInstruction())
278 if (RISCVInstrInfo::isVectorConfigInstr(*
MBBI)) {
288 unsigned FirstVType =
MBBI->getOperand(2).getImm();
293 if (FirstLMul != LMul)
298 if (!RISCVInstrInfo::isVLPreservingConfig(*
MBBI))
304 unsigned VType =
MBBI->getOperand(2).getImm();
322 }
else if (
MBBI->isInlineAsm() ||
MBBI->isCall()) {
324 }
else if (
MBBI->getNumDefs()) {
327 if (
MBBI->modifiesRegister(RISCV::VL,
nullptr))
333 if (!MO.isReg() || !MO.isDef())
335 if (!FoundDef &&
TRI->regsOverlap(MO.getReg(), SrcReg)) {
350 if (MO.getReg() != SrcReg)
391 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
392 uint16_t DstEncoding =
TRI->getEncodingValue(DstReg);
394 assert(!Fractional &&
"It is impossible be fractional lmul here.");
395 unsigned NumRegs = NF * LMulVal;
401 SrcEncoding += NumRegs - 1;
402 DstEncoding += NumRegs - 1;
408 unsigned,
unsigned> {
416 uint16_t Diff = DstEncoding - SrcEncoding;
417 if (
I + 8 <= NumRegs && Diff >= 8 && SrcEncoding % 8 == 7 &&
418 DstEncoding % 8 == 7)
420 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
421 if (
I + 4 <= NumRegs && Diff >= 4 && SrcEncoding % 4 == 3 &&
422 DstEncoding % 4 == 3)
424 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
425 if (
I + 2 <= NumRegs && Diff >= 2 && SrcEncoding % 2 == 1 &&
426 DstEncoding % 2 == 1)
428 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
431 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
436 if (
I + 8 <= NumRegs && SrcEncoding % 8 == 0 && DstEncoding % 8 == 0)
438 RISCV::PseudoVMV_V_V_M8, RISCV::PseudoVMV_V_I_M8};
439 if (
I + 4 <= NumRegs && SrcEncoding % 4 == 0 && DstEncoding % 4 == 0)
441 RISCV::PseudoVMV_V_V_M4, RISCV::PseudoVMV_V_I_M4};
442 if (
I + 2 <= NumRegs && SrcEncoding % 2 == 0 && DstEncoding % 2 == 0)
444 RISCV::PseudoVMV_V_V_M2, RISCV::PseudoVMV_V_I_M2};
447 RISCV::PseudoVMV_V_V_M1, RISCV::PseudoVMV_V_I_M1};
450 while (
I != NumRegs) {
455 auto [LMulCopied, RegClass,
Opc, VVOpc, VIOpc] =
456 GetCopyInfo(SrcEncoding, DstEncoding);
460 if (LMul == LMulCopied &&
463 if (DefMBBI->getOpcode() == VIOpc)
470 RegClass, ReversedCopy ? (SrcEncoding - NumCopied + 1) : SrcEncoding);
472 RegClass, ReversedCopy ? (DstEncoding - NumCopied + 1) : DstEncoding);
480 MIB = MIB.add(DefMBBI->getOperand(2));
488 MIB.addImm(Log2SEW ? Log2SEW : 3);
500 SrcEncoding += (ReversedCopy ? -NumCopied : NumCopied);
501 DstEncoding += (ReversedCopy ? -NumCopied : NumCopied);
510 bool RenamableDest,
bool RenamableSrc)
const {
514 if (RISCV::GPRRegClass.
contains(DstReg, SrcReg)) {
521 if (RISCV::GPRF16RegClass.
contains(DstReg, SrcReg)) {
527 if (RISCV::GPRF32RegClass.
contains(DstReg, SrcReg)) {
533 if (RISCV::GPRPairRegClass.
contains(DstReg, SrcReg)) {
534 if (
STI.isRV32() &&
STI.hasStdExtZdinx()) {
543 MCRegister EvenReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_even);
544 MCRegister OddReg =
TRI->getSubReg(SrcReg, RISCV::sub_gpr_odd);
546 if (OddReg == RISCV::DUMMY_REG_PAIR_WITH_X0)
548 assert(DstReg != RISCV::X0_Pair &&
"Cannot write to X0_Pair");
552 TRI->getSubReg(DstReg, RISCV::sub_gpr_even))
553 .
addReg(EvenReg, KillFlag)
556 TRI->getSubReg(DstReg, RISCV::sub_gpr_odd))
563 if (RISCV::VCSRRegClass.
contains(SrcReg) &&
564 RISCV::GPRRegClass.
contains(DstReg)) {
566 .
addImm(RISCVSysReg::lookupSysRegByName(
TRI->getName(SrcReg))->Encoding)
571 if (RISCV::FPR16RegClass.
contains(DstReg, SrcReg)) {
573 if (
STI.hasStdExtZfh()) {
574 Opc = RISCV::FSGNJ_H;
577 (
STI.hasStdExtZfhmin() ||
STI.hasStdExtZfbfmin()) &&
578 "Unexpected extensions");
580 DstReg =
TRI->getMatchingSuperReg(DstReg, RISCV::sub_16,
581 &RISCV::FPR32RegClass);
582 SrcReg =
TRI->getMatchingSuperReg(SrcReg, RISCV::sub_16,
583 &RISCV::FPR32RegClass);
584 Opc = RISCV::FSGNJ_S;
588 .
addReg(SrcReg, KillFlag);
592 if (RISCV::FPR32RegClass.
contains(DstReg, SrcReg)) {
595 .
addReg(SrcReg, KillFlag);
599 if (RISCV::FPR64RegClass.
contains(DstReg, SrcReg)) {
602 .
addReg(SrcReg, KillFlag);
606 if (RISCV::FPR32RegClass.
contains(DstReg) &&
607 RISCV::GPRRegClass.
contains(SrcReg)) {
609 .
addReg(SrcReg, KillFlag);
613 if (RISCV::GPRRegClass.
contains(DstReg) &&
614 RISCV::FPR32RegClass.
contains(SrcReg)) {
616 .
addReg(SrcReg, KillFlag);
620 if (RISCV::FPR64RegClass.
contains(DstReg) &&
621 RISCV::GPRRegClass.
contains(SrcReg)) {
622 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
624 .
addReg(SrcReg, KillFlag);
628 if (RISCV::GPRRegClass.
contains(DstReg) &&
629 RISCV::FPR64RegClass.
contains(SrcReg)) {
630 assert(
STI.getXLen() == 64 &&
"Unexpected GPR size");
632 .
addReg(SrcReg, KillFlag);
638 TRI->getCommonMinimalPhysRegClass(SrcReg, DstReg);
649 Register SrcReg,
bool IsKill,
int FI,
657 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
658 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::SW
660 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
661 Opcode = RISCV::SH_INX;
662 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
663 Opcode = RISCV::SW_INX;
664 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
665 Opcode = RISCV::PseudoRV32ZdinxSD;
666 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
668 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
670 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
672 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
673 Opcode = RISCV::VS1R_V;
674 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
675 Opcode = RISCV::VS2R_V;
676 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
677 Opcode = RISCV::VS4R_V;
678 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
679 Opcode = RISCV::VS8R_V;
680 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
681 Opcode = RISCV::PseudoVSPILL2_M1;
682 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
683 Opcode = RISCV::PseudoVSPILL2_M2;
684 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
685 Opcode = RISCV::PseudoVSPILL2_M4;
686 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
687 Opcode = RISCV::PseudoVSPILL3_M1;
688 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
689 Opcode = RISCV::PseudoVSPILL3_M2;
690 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
691 Opcode = RISCV::PseudoVSPILL4_M1;
692 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
693 Opcode = RISCV::PseudoVSPILL4_M2;
694 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
695 Opcode = RISCV::PseudoVSPILL5_M1;
696 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
697 Opcode = RISCV::PseudoVSPILL6_M1;
698 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
699 Opcode = RISCV::PseudoVSPILL7_M1;
700 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
701 Opcode = RISCV::PseudoVSPILL8_M1;
743 if (RISCV::GPRRegClass.hasSubClassEq(RC)) {
744 Opcode = RegInfo.getRegSizeInBits(RISCV::GPRRegClass) == 32 ? RISCV::LW
746 }
else if (RISCV::GPRF16RegClass.hasSubClassEq(RC)) {
747 Opcode = RISCV::LH_INX;
748 }
else if (RISCV::GPRF32RegClass.hasSubClassEq(RC)) {
749 Opcode = RISCV::LW_INX;
750 }
else if (RISCV::GPRPairRegClass.hasSubClassEq(RC)) {
751 Opcode = RISCV::PseudoRV32ZdinxLD;
752 }
else if (RISCV::FPR16RegClass.hasSubClassEq(RC)) {
754 }
else if (RISCV::FPR32RegClass.hasSubClassEq(RC)) {
756 }
else if (RISCV::FPR64RegClass.hasSubClassEq(RC)) {
758 }
else if (RISCV::VRRegClass.hasSubClassEq(RC)) {
759 Opcode = RISCV::VL1RE8_V;
760 }
else if (RISCV::VRM2RegClass.hasSubClassEq(RC)) {
761 Opcode = RISCV::VL2RE8_V;
762 }
else if (RISCV::VRM4RegClass.hasSubClassEq(RC)) {
763 Opcode = RISCV::VL4RE8_V;
764 }
else if (RISCV::VRM8RegClass.hasSubClassEq(RC)) {
765 Opcode = RISCV::VL8RE8_V;
766 }
else if (RISCV::VRN2M1RegClass.hasSubClassEq(RC))
767 Opcode = RISCV::PseudoVRELOAD2_M1;
768 else if (RISCV::VRN2M2RegClass.hasSubClassEq(RC))
769 Opcode = RISCV::PseudoVRELOAD2_M2;
770 else if (RISCV::VRN2M4RegClass.hasSubClassEq(RC))
771 Opcode = RISCV::PseudoVRELOAD2_M4;
772 else if (RISCV::VRN3M1RegClass.hasSubClassEq(RC))
773 Opcode = RISCV::PseudoVRELOAD3_M1;
774 else if (RISCV::VRN3M2RegClass.hasSubClassEq(RC))
775 Opcode = RISCV::PseudoVRELOAD3_M2;
776 else if (RISCV::VRN4M1RegClass.hasSubClassEq(RC))
777 Opcode = RISCV::PseudoVRELOAD4_M1;
778 else if (RISCV::VRN4M2RegClass.hasSubClassEq(RC))
779 Opcode = RISCV::PseudoVRELOAD4_M2;
780 else if (RISCV::VRN5M1RegClass.hasSubClassEq(RC))
781 Opcode = RISCV::PseudoVRELOAD5_M1;
782 else if (RISCV::VRN6M1RegClass.hasSubClassEq(RC))
783 Opcode = RISCV::PseudoVRELOAD6_M1;
784 else if (RISCV::VRN7M1RegClass.hasSubClassEq(RC))
785 Opcode = RISCV::PseudoVRELOAD7_M1;
786 else if (RISCV::VRN8M1RegClass.hasSubClassEq(RC))
787 Opcode = RISCV::PseudoVRELOAD8_M1;
825 if (
Ops.size() != 1 ||
Ops[0] != 1)
828 switch (
MI.getOpcode()) {
830 if (RISCVInstrInfo::isSEXT_W(
MI))
832 if (RISCVInstrInfo::isZEXT_W(
MI))
834 if (RISCVInstrInfo::isZEXT_B(
MI))
841 case RISCV::ZEXT_H_RV32:
842 case RISCV::ZEXT_H_RV64:
849 case RISCV::VMV_X_S: {
852 if (ST.getXLen() < (1U << Log2SEW))
867 case RISCV::VFMV_F_S: {
894 return BuildMI(*
MI.getParent(), InsertPt,
MI.getDebugLoc(),
get(*LoadOpc),
904 bool DstIsDead)
const {
920 bool SrcRenamable =
false;
924 bool LastItem = ++Num == Seq.
size();
929 switch (Inst.getOpndKind()) {
939 .
addReg(SrcReg, SrcRegState)
946 .
addReg(SrcReg, SrcRegState)
947 .
addReg(SrcReg, SrcRegState)
953 .
addReg(SrcReg, SrcRegState)
961 SrcRenamable = DstRenamable;
971 case RISCV::CV_BEQIMM:
973 case RISCV::QC_E_BEQI:
975 case RISCV::NDS_BEQC:
980 case RISCV::QC_E_BNEI:
981 case RISCV::CV_BNEIMM:
983 case RISCV::NDS_BNEC:
987 case RISCV::QC_E_BLTI:
991 case RISCV::QC_E_BGEI:
994 case RISCV::QC_BLTUI:
995 case RISCV::QC_E_BLTUI:
998 case RISCV::QC_BGEUI:
999 case RISCV::QC_E_BGEUI:
1031 "Unknown conditional branch");
1042 case RISCV::QC_MVEQ:
1043 return RISCV::QC_MVNE;
1044 case RISCV::QC_MVNE:
1045 return RISCV::QC_MVEQ;
1046 case RISCV::QC_MVLT:
1047 return RISCV::QC_MVGE;
1048 case RISCV::QC_MVGE:
1049 return RISCV::QC_MVLT;
1050 case RISCV::QC_MVLTU:
1051 return RISCV::QC_MVGEU;
1052 case RISCV::QC_MVGEU:
1053 return RISCV::QC_MVLTU;
1054 case RISCV::QC_MVEQI:
1055 return RISCV::QC_MVNEI;
1056 case RISCV::QC_MVNEI:
1057 return RISCV::QC_MVEQI;
1058 case RISCV::QC_MVLTI:
1059 return RISCV::QC_MVGEI;
1060 case RISCV::QC_MVGEI:
1061 return RISCV::QC_MVLTI;
1062 case RISCV::QC_MVLTUI:
1063 return RISCV::QC_MVGEUI;
1064 case RISCV::QC_MVGEUI:
1065 return RISCV::QC_MVLTUI;
1070 switch (SelectOpc) {
1089 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
1099 case RISCV::Select_GPR_Using_CC_SImm5_CV:
1104 return RISCV::CV_BEQIMM;
1106 return RISCV::CV_BNEIMM;
1109 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
1114 return RISCV::QC_BEQI;
1116 return RISCV::QC_BNEI;
1118 return RISCV::QC_BLTI;
1120 return RISCV::QC_BGEI;
1123 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
1128 return RISCV::QC_BLTUI;
1130 return RISCV::QC_BGEUI;
1133 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
1138 return RISCV::QC_E_BEQI;
1140 return RISCV::QC_E_BNEI;
1142 return RISCV::QC_E_BLTI;
1144 return RISCV::QC_E_BGEI;
1147 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
1152 return RISCV::QC_E_BLTUI;
1154 return RISCV::QC_E_BGEUI;
1157 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
1162 return RISCV::NDS_BBC;
1164 return RISCV::NDS_BBS;
1167 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
1172 return RISCV::NDS_BEQC;
1174 return RISCV::NDS_BNEC;
1203 bool AllowModify)
const {
1204 TBB = FBB =
nullptr;
1209 if (
I ==
MBB.end() || !isUnpredicatedTerminator(*
I))
1215 int NumTerminators = 0;
1216 for (
auto J =
I.getReverse(); J !=
MBB.rend() && isUnpredicatedTerminator(*J);
1219 if (J->getDesc().isUnconditionalBranch() ||
1220 J->getDesc().isIndirectBranch()) {
1227 if (AllowModify && FirstUncondOrIndirectBr !=
MBB.end()) {
1228 while (std::next(FirstUncondOrIndirectBr) !=
MBB.end()) {
1229 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
1232 I = FirstUncondOrIndirectBr;
1236 if (
I->getDesc().isIndirectBranch())
1240 if (
I->isPreISelOpcode())
1244 if (NumTerminators > 2)
1248 if (NumTerminators == 1 &&
I->getDesc().isUnconditionalBranch()) {
1254 if (NumTerminators == 1 &&
I->getDesc().isConditionalBranch()) {
1260 if (NumTerminators == 2 && std::prev(
I)->getDesc().isConditionalBranch() &&
1261 I->getDesc().isUnconditionalBranch()) {
1272 int *BytesRemoved)
const {
1279 if (!
I->getDesc().isUnconditionalBranch() &&
1280 !
I->getDesc().isConditionalBranch())
1286 I->eraseFromParent();
1290 if (
I ==
MBB.begin())
1293 if (!
I->getDesc().isConditionalBranch())
1299 I->eraseFromParent();
1312 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
1314 "RISC-V branch conditions have two components!");
1348 assert(RS &&
"RegScavenger required for long branching");
1350 "new block should be inserted for expanding unconditional branch");
1353 "restore block should be inserted for restoring clobbered registers");
1362 "Branch offsets outside of the signed 32-bit range not supported");
1367 Register ScratchReg =
MRI.createVirtualRegister(&RISCV::GPRJALRRegClass);
1368 auto II =
MBB.end();
1374 RS->enterBasicBlockEnd(
MBB);
1376 RS->scavengeRegisterBackwards(RISCV::GPRRegClass,
MI.getIterator(),
1380 RS->setRegUsed(TmpGPR);
1385 TmpGPR =
STI.hasStdExtE() ? RISCV::X9 : RISCV::X27;
1388 if (FrameIndex == -1)
1393 TRI->eliminateFrameIndex(std::prev(
MI.getIterator()),
1396 MI.getOperand(1).setMBB(&RestoreBB);
1400 TRI->eliminateFrameIndex(RestoreBB.
back(),
1404 MRI.replaceRegWith(ScratchReg, TmpGPR);
1405 MRI.clearVirtRegs();
1410 assert((
Cond.size() == 3) &&
"Invalid branch condition!");
1415 Cond[0].setImm(RISCV::BNE);
1418 Cond[0].setImm(RISCV::BNEI);
1421 Cond[0].setImm(RISCV::BEQ);
1424 Cond[0].setImm(RISCV::BEQI);
1427 Cond[0].setImm(RISCV::BGE);
1430 Cond[0].setImm(RISCV::BLT);
1433 Cond[0].setImm(RISCV::BGEU);
1436 Cond[0].setImm(RISCV::BLTU);
1438 case RISCV::CV_BEQIMM:
1439 Cond[0].setImm(RISCV::CV_BNEIMM);
1441 case RISCV::CV_BNEIMM:
1442 Cond[0].setImm(RISCV::CV_BEQIMM);
1444 case RISCV::QC_BEQI:
1445 Cond[0].setImm(RISCV::QC_BNEI);
1447 case RISCV::QC_BNEI:
1448 Cond[0].setImm(RISCV::QC_BEQI);
1450 case RISCV::QC_BGEI:
1451 Cond[0].setImm(RISCV::QC_BLTI);
1453 case RISCV::QC_BLTI:
1454 Cond[0].setImm(RISCV::QC_BGEI);
1456 case RISCV::QC_BGEUI:
1457 Cond[0].setImm(RISCV::QC_BLTUI);
1459 case RISCV::QC_BLTUI:
1460 Cond[0].setImm(RISCV::QC_BGEUI);
1462 case RISCV::QC_E_BEQI:
1463 Cond[0].setImm(RISCV::QC_E_BNEI);
1465 case RISCV::QC_E_BNEI:
1466 Cond[0].setImm(RISCV::QC_E_BEQI);
1468 case RISCV::QC_E_BGEI:
1469 Cond[0].setImm(RISCV::QC_E_BLTI);
1471 case RISCV::QC_E_BLTI:
1472 Cond[0].setImm(RISCV::QC_E_BGEI);
1474 case RISCV::QC_E_BGEUI:
1475 Cond[0].setImm(RISCV::QC_E_BLTUI);
1477 case RISCV::QC_E_BLTUI:
1478 Cond[0].setImm(RISCV::QC_E_BGEUI);
1480 case RISCV::NDS_BBC:
1481 Cond[0].setImm(RISCV::NDS_BBS);
1483 case RISCV::NDS_BBS:
1484 Cond[0].setImm(RISCV::NDS_BBC);
1486 case RISCV::NDS_BEQC:
1487 Cond[0].setImm(RISCV::NDS_BNEC);
1489 case RISCV::NDS_BNEC:
1490 Cond[0].setImm(RISCV::NDS_BEQC);
1500 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1501 MI->getOperand(1).getReg() == RISCV::X0) {
1502 Imm =
MI->getOperand(2).getImm();
1515 if (Reg == RISCV::X0) {
1519 return Reg.isVirtual() &&
isLoadImm(
MRI.getVRegDef(Reg), Imm);
1523 bool IsSigned =
false;
1524 bool IsEquality =
false;
1525 switch (
MI.getOpcode()) {
1561 MI.eraseFromParent();
1587 auto searchConst = [&](int64_t C1) ->
Register {
1589 auto DefC1 = std::find_if(++
II, E, [&](
const MachineInstr &
I) ->
bool {
1592 I.getOperand(0).getReg().isVirtual();
1595 return DefC1->getOperand(0).getReg();
1608 MRI.hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
1610 if (
Register RegZ = searchConst(C0 + 1)) {
1617 MRI.clearKillFlags(RegZ);
1618 MI.eraseFromParent();
1629 MRI.hasOneUse(RHS.getReg())) {
1631 if (
Register RegZ = searchConst(C0 - 1)) {
1638 MRI.clearKillFlags(RegZ);
1639 MI.eraseFromParent();
1649 assert(
MI.getDesc().isBranch() &&
"Unexpected opcode!");
1651 int NumOp =
MI.getNumExplicitOperands();
1652 return MI.getOperand(NumOp - 1).getMBB();
1656 int64_t BrOffset)
const {
1657 unsigned XLen =
STI.getXLen();
1664 case RISCV::NDS_BBC:
1665 case RISCV::NDS_BBS:
1666 case RISCV::NDS_BEQC:
1667 case RISCV::NDS_BNEC:
1677 case RISCV::CV_BEQIMM:
1678 case RISCV::CV_BNEIMM:
1679 case RISCV::QC_BEQI:
1680 case RISCV::QC_BNEI:
1681 case RISCV::QC_BGEI:
1682 case RISCV::QC_BLTI:
1683 case RISCV::QC_BLTUI:
1684 case RISCV::QC_BGEUI:
1685 case RISCV::QC_E_BEQI:
1686 case RISCV::QC_E_BNEI:
1687 case RISCV::QC_E_BGEI:
1688 case RISCV::QC_E_BLTI:
1689 case RISCV::QC_E_BLTUI:
1690 case RISCV::QC_E_BGEUI:
1693 case RISCV::PseudoBR:
1695 case RISCV::PseudoJump:
1706 case RISCV::ADD:
return RISCV::PseudoCCADD;
1707 case RISCV::SUB:
return RISCV::PseudoCCSUB;
1708 case RISCV::SLL:
return RISCV::PseudoCCSLL;
1709 case RISCV::SRL:
return RISCV::PseudoCCSRL;
1710 case RISCV::SRA:
return RISCV::PseudoCCSRA;
1711 case RISCV::AND:
return RISCV::PseudoCCAND;
1712 case RISCV::OR:
return RISCV::PseudoCCOR;
1713 case RISCV::XOR:
return RISCV::PseudoCCXOR;
1714 case RISCV::MAX:
return RISCV::PseudoCCMAX;
1715 case RISCV::MAXU:
return RISCV::PseudoCCMAXU;
1716 case RISCV::MIN:
return RISCV::PseudoCCMIN;
1717 case RISCV::MINU:
return RISCV::PseudoCCMINU;
1718 case RISCV::MUL:
return RISCV::PseudoCCMUL;
1719 case RISCV::LUI:
return RISCV::PseudoCCLUI;
1720 case RISCV::QC_LI:
return RISCV::PseudoCCQC_LI;
1721 case RISCV::QC_E_LI:
return RISCV::PseudoCCQC_E_LI;
1723 case RISCV::ADDI:
return RISCV::PseudoCCADDI;
1724 case RISCV::SLLI:
return RISCV::PseudoCCSLLI;
1725 case RISCV::SRLI:
return RISCV::PseudoCCSRLI;
1726 case RISCV::SRAI:
return RISCV::PseudoCCSRAI;
1727 case RISCV::ANDI:
return RISCV::PseudoCCANDI;
1728 case RISCV::ORI:
return RISCV::PseudoCCORI;
1729 case RISCV::XORI:
return RISCV::PseudoCCXORI;
1731 case RISCV::ADDW:
return RISCV::PseudoCCADDW;
1732 case RISCV::SUBW:
return RISCV::PseudoCCSUBW;
1733 case RISCV::SLLW:
return RISCV::PseudoCCSLLW;
1734 case RISCV::SRLW:
return RISCV::PseudoCCSRLW;
1735 case RISCV::SRAW:
return RISCV::PseudoCCSRAW;
1737 case RISCV::ADDIW:
return RISCV::PseudoCCADDIW;
1738 case RISCV::SLLIW:
return RISCV::PseudoCCSLLIW;
1739 case RISCV::SRLIW:
return RISCV::PseudoCCSRLIW;
1740 case RISCV::SRAIW:
return RISCV::PseudoCCSRAIW;
1742 case RISCV::ANDN:
return RISCV::PseudoCCANDN;
1743 case RISCV::ORN:
return RISCV::PseudoCCORN;
1744 case RISCV::XNOR:
return RISCV::PseudoCCXNOR;
1746 case RISCV::NDS_BFOS:
return RISCV::PseudoCCNDS_BFOS;
1747 case RISCV::NDS_BFOZ:
return RISCV::PseudoCCNDS_BFOZ;
1751 return RISCV::INSTRUCTION_LIST_END;
1760 if (!
Reg.isVirtual())
1762 if (!
MRI.hasOneNonDBGUse(
Reg))
1768 if (!STI.hasShortForwardBranchIMinMax() &&
1769 (
MI->getOpcode() == RISCV::MAX ||
MI->getOpcode() == RISCV::MIN ||
1770 MI->getOpcode() == RISCV::MINU ||
MI->getOpcode() == RISCV::MAXU))
1773 if (!STI.hasShortForwardBranchIMul() &&
MI->getOpcode() == RISCV::MUL)
1780 if (
MI->getOpcode() == RISCV::ADDI &&
MI->getOperand(1).isReg() &&
1781 MI->getOperand(1).getReg() == RISCV::X0)
1786 if (MO.isFI() || MO.isCPI() || MO.isJTI())
1796 if (MO.getReg().isPhysical() && !
MRI.isConstantPhysReg(MO.getReg()))
1799 bool DontMoveAcrossStores =
true;
1800 if (!
MI->isSafeToMove(DontMoveAcrossStores))
1807 unsigned &TrueOp,
unsigned &FalseOp,
1808 bool &Optimizable)
const {
1809 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1810 "Unknown select instruction");
1820 Cond.push_back(
MI.getOperand(1));
1821 Cond.push_back(
MI.getOperand(2));
1822 Cond.push_back(
MI.getOperand(3));
1824 Optimizable =
STI.hasShortForwardBranchOpt();
1831 bool PreferFalse)
const {
1832 assert(
MI.getOpcode() == RISCV::PseudoCCMOVGPR &&
1833 "Unknown select instruction");
1834 if (!
STI.hasShortForwardBranchOpt())
1840 bool Invert = !
DefMI;
1848 Register DestReg =
MI.getOperand(0).getReg();
1850 if (!
MRI.constrainRegClass(DestReg, PreviousClass))
1854 assert(PredOpc != RISCV::INSTRUCTION_LIST_END &&
"Unexpected opcode!");
1861 NewMI.
add(
MI.getOperand(1));
1862 NewMI.
add(
MI.getOperand(2));
1871 NewMI.
add(FalseReg);
1886 if (
DefMI->getParent() !=
MI.getParent())
1890 DefMI->eraseFromParent();
1895 if (
MI.isMetaInstruction())
1898 unsigned Opcode =
MI.getOpcode();
1900 if (Opcode == TargetOpcode::INLINEASM ||
1901 Opcode == TargetOpcode::INLINEASM_BR) {
1903 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(),
1907 if (!
MI.memoperands_empty()) {
1910 if (
STI.hasStdExtZca()) {
1911 if (isCompressibleInst(
MI,
STI))
1919 if (Opcode == TargetOpcode::BUNDLE)
1920 return getInstBundleLength(
MI);
1922 if (
MI.getParent() &&
MI.getParent()->getParent()) {
1923 if (isCompressibleInst(
MI,
STI))
1928 case RISCV::PseudoMV_FPR16INX:
1929 case RISCV::PseudoMV_FPR32INX:
1931 return STI.hasStdExtZca() ? 2 : 4;
1932 case TargetOpcode::STACKMAP:
1935 case TargetOpcode::PATCHPOINT:
1938 case TargetOpcode::STATEPOINT: {
1942 return std::max(NumBytes, 8U);
1944 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
1945 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
1946 case TargetOpcode::PATCHABLE_TAIL_CALL: {
1949 if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
1950 F.hasFnAttribute(
"patchable-function-entry")) {
1952 if (
F.getFnAttribute(
"patchable-function-entry")
1954 .getAsInteger(10, Num))
1955 return get(Opcode).getSize();
1958 return (
STI.hasStdExtZca() ? 2 : 4) * Num;
1962 return STI.is64Bit() ? 68 : 44;
1965 return get(Opcode).getSize();
1969unsigned RISCVInstrInfo::getInstBundleLength(
const MachineInstr &
MI)
const {
1973 while (++
I != E &&
I->isInsideBundle()) {
1974 assert(!
I->isBundle() &&
"No nested bundle!");
1981 const unsigned Opcode =
MI.getOpcode();
1985 case RISCV::FSGNJ_D:
1986 case RISCV::FSGNJ_S:
1987 case RISCV::FSGNJ_H:
1988 case RISCV::FSGNJ_D_INX:
1989 case RISCV::FSGNJ_D_IN32X:
1990 case RISCV::FSGNJ_S_INX:
1991 case RISCV::FSGNJ_H_INX:
1993 return MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
1994 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg();
1998 return (
MI.getOperand(1).isReg() &&
1999 MI.getOperand(1).getReg() == RISCV::X0) ||
2000 (
MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0);
2002 return MI.isAsCheapAsAMove();
2005std::optional<DestSourcePair>
2009 switch (
MI.getOpcode()) {
2015 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2016 MI.getOperand(2).isReg())
2018 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2019 MI.getOperand(1).isReg())
2024 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isImm() &&
2025 MI.getOperand(2).getImm() == 0)
2029 if (
MI.getOperand(2).isReg() &&
MI.getOperand(2).getReg() == RISCV::X0 &&
2030 MI.getOperand(1).isReg())
2034 case RISCV::SH1ADD_UW:
2036 case RISCV::SH2ADD_UW:
2038 case RISCV::SH3ADD_UW:
2039 if (
MI.getOperand(1).isReg() &&
MI.getOperand(1).getReg() == RISCV::X0 &&
2040 MI.getOperand(2).isReg())
2043 case RISCV::FSGNJ_D:
2044 case RISCV::FSGNJ_S:
2045 case RISCV::FSGNJ_H:
2046 case RISCV::FSGNJ_D_INX:
2047 case RISCV::FSGNJ_D_IN32X:
2048 case RISCV::FSGNJ_S_INX:
2049 case RISCV::FSGNJ_H_INX:
2051 if (
MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
2052 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg())
2056 return std::nullopt;
2064 const auto &SchedModel =
STI.getSchedModel();
2065 return (!SchedModel.hasInstrSchedModel() || SchedModel.isOutOfOrder())
2077 RISCV::getNamedOperandIdx(Root.
getOpcode(), RISCV::OpName::frm);
2081 return RISCV::getNamedOperandIdx(
MI->getOpcode(),
2082 RISCV::OpName::frm) < 0;
2084 "New instructions require FRM whereas the old one does not have it");
2091 for (
auto *NewMI : InsInstrs) {
2093 if (
static_cast<unsigned>(RISCV::getNamedOperandIdx(
2094 NewMI->getOpcode(), RISCV::OpName::frm)) != NewMI->getNumOperands())
2136bool RISCVInstrInfo::isVectorAssociativeAndCommutative(
const MachineInstr &Inst,
2137 bool Invert)
const {
2138#define OPCODE_LMUL_CASE(OPC) \
2139 case RISCV::OPC##_M1: \
2140 case RISCV::OPC##_M2: \
2141 case RISCV::OPC##_M4: \
2142 case RISCV::OPC##_M8: \
2143 case RISCV::OPC##_MF2: \
2144 case RISCV::OPC##_MF4: \
2145 case RISCV::OPC##_MF8
2147#define OPCODE_LMUL_MASK_CASE(OPC) \
2148 case RISCV::OPC##_M1_MASK: \
2149 case RISCV::OPC##_M2_MASK: \
2150 case RISCV::OPC##_M4_MASK: \
2151 case RISCV::OPC##_M8_MASK: \
2152 case RISCV::OPC##_MF2_MASK: \
2153 case RISCV::OPC##_MF4_MASK: \
2154 case RISCV::OPC##_MF8_MASK
2159 Opcode = *InvOpcode;
2176#undef OPCODE_LMUL_MASK_CASE
2177#undef OPCODE_LMUL_CASE
2180bool RISCVInstrInfo::areRVVInstsReassociable(
const MachineInstr &Root,
2187 const TargetRegisterInfo *
TRI =
MRI->getTargetRegisterInfo();
2191 const uint64_t TSFlags =
Desc.TSFlags;
2193 auto checkImmOperand = [&](
unsigned OpIdx) {
2197 auto checkRegOperand = [&](
unsigned OpIdx) {
2205 if (!checkRegOperand(1))
2220 bool SeenMI2 =
false;
2221 for (
auto End =
MBB->
rend(), It = It1; It != End; ++It) {
2230 if (It->modifiesRegister(RISCV::V0,
TRI)) {
2231 Register SrcReg = It->getOperand(1).getReg();
2249 if (MI1VReg != SrcReg)
2258 assert(SeenMI2 &&
"Prev is expected to appear before Root");
2297bool RISCVInstrInfo::hasReassociableVectorSibling(
const MachineInstr &Inst,
2298 bool &Commuted)
const {
2302 "Expect the present of passthrough operand.");
2308 Commuted = !areRVVInstsReassociable(Inst, *MI1) &&
2309 areRVVInstsReassociable(Inst, *MI2);
2313 return areRVVInstsReassociable(Inst, *MI1) &&
2314 (isVectorAssociativeAndCommutative(*MI1) ||
2315 isVectorAssociativeAndCommutative(*MI1,
true)) &&
2322 if (!isVectorAssociativeAndCommutative(Inst) &&
2323 !isVectorAssociativeAndCommutative(Inst,
true))
2335 MI1 =
MRI.getUniqueVRegDef(Op1.
getReg());
2337 MI2 =
MRI.getUniqueVRegDef(Op2.
getReg());
2349 for (
unsigned I = 0;
I < 5; ++
I)
2355 bool &Commuted)
const {
2356 if (isVectorAssociativeAndCommutative(Inst) ||
2357 isVectorAssociativeAndCommutative(Inst,
true))
2358 return hasReassociableVectorSibling(Inst, Commuted);
2364 unsigned OperandIdx = Commuted ? 2 : 1;
2368 int16_t InstFrmOpIdx =
2369 RISCV::getNamedOperandIdx(Inst.
getOpcode(), RISCV::OpName::frm);
2370 int16_t SiblingFrmOpIdx =
2371 RISCV::getNamedOperandIdx(Sibling.
getOpcode(), RISCV::OpName::frm);
2373 return (InstFrmOpIdx < 0 && SiblingFrmOpIdx < 0) ||
2378 bool Invert)
const {
2379 if (isVectorAssociativeAndCommutative(Inst, Invert))
2387 Opc = *InverseOpcode;
2432std::optional<unsigned>
2434#define RVV_OPC_LMUL_CASE(OPC, INV) \
2435 case RISCV::OPC##_M1: \
2436 return RISCV::INV##_M1; \
2437 case RISCV::OPC##_M2: \
2438 return RISCV::INV##_M2; \
2439 case RISCV::OPC##_M4: \
2440 return RISCV::INV##_M4; \
2441 case RISCV::OPC##_M8: \
2442 return RISCV::INV##_M8; \
2443 case RISCV::OPC##_MF2: \
2444 return RISCV::INV##_MF2; \
2445 case RISCV::OPC##_MF4: \
2446 return RISCV::INV##_MF4; \
2447 case RISCV::OPC##_MF8: \
2448 return RISCV::INV##_MF8
2450#define RVV_OPC_LMUL_MASK_CASE(OPC, INV) \
2451 case RISCV::OPC##_M1_MASK: \
2452 return RISCV::INV##_M1_MASK; \
2453 case RISCV::OPC##_M2_MASK: \
2454 return RISCV::INV##_M2_MASK; \
2455 case RISCV::OPC##_M4_MASK: \
2456 return RISCV::INV##_M4_MASK; \
2457 case RISCV::OPC##_M8_MASK: \
2458 return RISCV::INV##_M8_MASK; \
2459 case RISCV::OPC##_MF2_MASK: \
2460 return RISCV::INV##_MF2_MASK; \
2461 case RISCV::OPC##_MF4_MASK: \
2462 return RISCV::INV##_MF4_MASK; \
2463 case RISCV::OPC##_MF8_MASK: \
2464 return RISCV::INV##_MF8_MASK
2468 return std::nullopt;
2470 return RISCV::FSUB_H;
2472 return RISCV::FSUB_S;
2474 return RISCV::FSUB_D;
2476 return RISCV::FADD_H;
2478 return RISCV::FADD_S;
2480 return RISCV::FADD_D;
2497#undef RVV_OPC_LMUL_MASK_CASE
2498#undef RVV_OPC_LMUL_CASE
2503 bool DoRegPressureReduce) {
2519 if (DoRegPressureReduce && !
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2530 bool DoRegPressureReduce) {
2537 DoRegPressureReduce)) {
2543 DoRegPressureReduce)) {
2553 bool DoRegPressureReduce) {
2561 unsigned CombineOpc) {
2568 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
2571 if (!
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2582 unsigned OuterShiftAmt) {
2588 if (InnerShiftAmt < OuterShiftAmt || (InnerShiftAmt - OuterShiftAmt) > 3)
2615 case RISCV::SH1ADD_UW:
2617 case RISCV::SH2ADD_UW:
2619 case RISCV::SH3ADD_UW:
2665 bool DoRegPressureReduce)
const {
2674 DoRegPressureReduce);
2682 return RISCV::FMADD_H;
2684 return RISCV::FMADD_S;
2686 return RISCV::FMADD_D;
2731 bool Mul1IsKill = Mul1.
isKill();
2732 bool Mul2IsKill = Mul2.
isKill();
2733 bool AddendIsKill = Addend.
isKill();
2742 BuildMI(*MF, MergedLoc,
TII->get(FusedOpc), DstReg)
2767 assert(OuterShiftAmt != 0 &&
"Unexpected opcode");
2774 assert(InnerShiftAmt >= OuterShiftAmt &&
"Unexpected shift amount");
2777 switch (InnerShiftAmt - OuterShiftAmt) {
2781 InnerOpc = RISCV::ADD;
2784 InnerOpc = RISCV::SH1ADD;
2787 InnerOpc = RISCV::SH2ADD;
2790 InnerOpc = RISCV::SH3ADD;
2798 Register NewVR =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
2808 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
2825 DelInstrs, InstrIdxForVirtReg);
2852 for (
const auto &[Index, Operand] :
enumerate(
Desc.operands())) {
2853 unsigned OpType = Operand.OperandType;
2858 ErrInfo =
"Expected a non-register operand.";
2862 int64_t Imm = MO.
getImm();
2869#define CASE_OPERAND_UIMM(NUM) \
2870 case RISCVOp::OPERAND_UIMM##NUM: \
2871 Ok = isUInt<NUM>(Imm); \
2873#define CASE_OPERAND_SIMM(NUM) \
2874 case RISCVOp::OPERAND_SIMM##NUM: \
2875 Ok = isInt<NUM>(Imm); \
2907 Ok = (
isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32);
2949 Ok = (
isUInt<5>(Imm) && Imm != 0) || Imm == -1;
2960 Ok = (
isInt<5>(Imm) && Imm != -16) || Imm == 16;
2991 Ok = Ok && Imm != 0;
2995 (Imm >= 0xfffe0 && Imm <= 0xfffff);
2998 Ok = Imm >= 0 && Imm <= 10;
3001 Ok = Imm >= 0 && Imm <= 7;
3004 Ok = Imm >= 1 && Imm <= 10;
3007 Ok = Imm >= 2 && Imm <= 14;
3016 Ok = Imm >= 0 && Imm <= 48 && Imm % 16 == 0;
3049 ErrInfo =
"Invalid immediate";
3059 if (!
Op.isImm() && !
Op.isReg()) {
3060 ErrInfo =
"Invalid operand type for VL operand";
3063 if (
Op.isReg() &&
Op.getReg().isValid()) {
3065 auto *RC =
MRI.getRegClass(
Op.getReg());
3066 if (!RISCV::GPRRegClass.hasSubClassEq(RC)) {
3067 ErrInfo =
"Invalid register class for VL operand";
3072 ErrInfo =
"VL operand w/o SEW operand?";
3078 if (!
MI.getOperand(
OpIdx).isImm()) {
3079 ErrInfo =
"SEW value expected to be an immediate";
3084 ErrInfo =
"Unexpected SEW value";
3087 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3089 ErrInfo =
"Unexpected SEW value";
3095 if (!
MI.getOperand(
OpIdx).isImm()) {
3096 ErrInfo =
"Policy operand expected to be an immediate";
3101 ErrInfo =
"Invalid Policy Value";
3105 ErrInfo =
"policy operand w/o VL operand?";
3113 if (!
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
3114 ErrInfo =
"policy operand w/o tied operand?";
3121 !
MI.readsRegister(RISCV::FRM,
nullptr)) {
3122 ErrInfo =
"dynamic rounding mode should read FRM";
3144 case RISCV::LD_RV32:
3154 case RISCV::SD_RV32:
3170 int64_t NewOffset = OldOffset + Disp;
3192 "Addressing mode not supported for folding");
3266 case RISCV::LD_RV32:
3269 case RISCV::SD_RV32:
3276 OffsetIsScalable =
false;
3292 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
3300 if (MO1->getAddrSpace() != MO2->getAddrSpace())
3303 auto Base1 = MO1->getValue();
3304 auto Base2 = MO2->getValue();
3305 if (!Base1 || !Base2)
3313 return Base1 == Base2;
3319 int64_t Offset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
3320 unsigned NumBytes)
const {
3323 if (!BaseOps1.
empty() && !BaseOps2.
empty()) {
3328 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
3334 BaseOps1.
front()->getParent()->getMF()->getSubtarget().getCacheLineSize();
3340 return ClusterSize <= 4 && std::abs(Offset1 - Offset2) <
CacheLineSize;
3390 int64_t OffsetA = 0, OffsetB = 0;
3396 int LowOffset = std::min(OffsetA, OffsetB);
3397 int HighOffset = std::max(OffsetA, OffsetB);
3398 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3400 LowOffset + (
int)LowWidth.
getValue() <= HighOffset)
3407std::pair<unsigned, unsigned>
3410 return std::make_pair(TF & Mask, TF & ~Mask);
3416 static const std::pair<unsigned, const char *> TargetFlags[] = {
3417 {MO_CALL,
"riscv-call"},
3418 {MO_LO,
"riscv-lo"},
3419 {MO_HI,
"riscv-hi"},
3420 {MO_PCREL_LO,
"riscv-pcrel-lo"},
3421 {MO_PCREL_HI,
"riscv-pcrel-hi"},
3422 {MO_GOT_HI,
"riscv-got-hi"},
3423 {MO_TPREL_LO,
"riscv-tprel-lo"},
3424 {MO_TPREL_HI,
"riscv-tprel-hi"},
3425 {MO_TPREL_ADD,
"riscv-tprel-add"},
3426 {MO_TLS_GOT_HI,
"riscv-tls-got-hi"},
3427 {MO_TLS_GD_HI,
"riscv-tls-gd-hi"},
3428 {MO_TLSDESC_HI,
"riscv-tlsdesc-hi"},
3429 {MO_TLSDESC_LOAD_LO,
"riscv-tlsdesc-load-lo"},
3430 {MO_TLSDESC_ADD_LO,
"riscv-tlsdesc-add-lo"},
3431 {MO_TLSDESC_CALL,
"riscv-tlsdesc-call"}};
3439 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
3452 unsigned &Flags)
const {
3471 return F.getFnAttribute(
"fentry-call").getValueAsBool() ||
3472 F.hasFnAttribute(
"patchable-function-entry");
3477 return MI.readsRegister(RegNo,
TRI) ||
3478 MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
3483 return MI.modifiesRegister(RegNo,
TRI) ||
3484 MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
3488 if (!
MBB.back().isReturn())
3511 if (
C.back().isReturn()) {
3513 "The candidate who uses return instruction must be outlined "
3526 return !
C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *
TRI);
3529std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3532 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3533 unsigned MinRepeats)
const {
3539 if (RepeatedSequenceLocs.size() < MinRepeats)
3540 return std::nullopt;
3544 unsigned InstrSizeCExt =
3546 unsigned CallOverhead = 0, FrameOverhead = 0;
3549 unsigned CFICount = 0;
3550 for (
auto &
I : Candidate) {
3551 if (
I.isCFIInstruction())
3562 std::vector<MCCFIInstruction> CFIInstructions =
3563 C.getMF()->getFrameInstructions();
3565 if (CFICount > 0 && CFICount != CFIInstructions.size())
3566 return std::nullopt;
3574 CallOverhead = 4 + InstrSizeCExt;
3581 FrameOverhead = InstrSizeCExt;
3587 return std::nullopt;
3589 for (
auto &
C : RepeatedSequenceLocs)
3590 C.setCallInfo(MOCI, CallOverhead);
3592 unsigned SequenceSize = 0;
3593 for (
auto &
MI : Candidate)
3596 return std::make_unique<outliner::OutlinedFunction>(
3597 RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
3603 unsigned Flags)
const {
3607 MBB->getParent()->getSubtarget().getRegisterInfo();
3608 const auto &
F =
MI.getMF()->getFunction();
3613 if (
MI.isCFIInstruction())
3621 for (
const auto &MO :
MI.operands()) {
3626 (
MI.getMF()->getTarget().getFunctionSections() ||
F.hasComdat() ||
3627 F.hasSection() ||
F.getSectionPrefix()))
3644 MBB.addLiveIn(RISCV::X5);
3659 .addGlobalAddress(M.getNamedValue(MF.
getName()),
3667 .addGlobalAddress(M.getNamedValue(MF.
getName()), 0,
3678 return std::nullopt;
3682 if (
MI.getOpcode() == RISCV::ADDI &&
MI.getOperand(1).isReg() &&
3683 MI.getOperand(2).isImm())
3684 return RegImmPair{
MI.getOperand(1).getReg(),
MI.getOperand(2).getImm()};
3686 return std::nullopt;
3694 std::string GenericComment =
3696 if (!GenericComment.empty())
3697 return GenericComment;
3701 return std::string();
3705 return std::string();
3707 std::string Comment;
3714 switch (OpInfo.OperandType) {
3717 unsigned Imm =
Op.getImm();
3722 unsigned Imm =
Op.getImm();
3728 unsigned Log2SEW =
Op.getImm();
3729 unsigned SEW = Log2SEW ? 1 << Log2SEW : 8;
3735 unsigned Policy =
Op.getImm();
3737 "Invalid Policy Value");
3747#define CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL) \
3748 RISCV::Pseudo##OP##_##LMUL
3750#define CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL) \
3751 RISCV::Pseudo##OP##_##LMUL##_MASK
3753#define CASE_RVV_OPCODE_LMUL(OP, LMUL) \
3754 CASE_RVV_OPCODE_UNMASK_LMUL(OP, LMUL): \
3755 case CASE_RVV_OPCODE_MASK_LMUL(OP, LMUL)
3757#define CASE_RVV_OPCODE_UNMASK_WIDEN(OP) \
3758 CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF8): \
3759 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF4): \
3760 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, MF2): \
3761 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M1): \
3762 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M2): \
3763 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M4)
3765#define CASE_RVV_OPCODE_UNMASK(OP) \
3766 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
3767 case CASE_RVV_OPCODE_UNMASK_LMUL(OP, M8)
3769#define CASE_RVV_OPCODE_MASK_WIDEN(OP) \
3770 CASE_RVV_OPCODE_MASK_LMUL(OP, MF8): \
3771 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF4): \
3772 case CASE_RVV_OPCODE_MASK_LMUL(OP, MF2): \
3773 case CASE_RVV_OPCODE_MASK_LMUL(OP, M1): \
3774 case CASE_RVV_OPCODE_MASK_LMUL(OP, M2): \
3775 case CASE_RVV_OPCODE_MASK_LMUL(OP, M4)
3777#define CASE_RVV_OPCODE_MASK(OP) \
3778 CASE_RVV_OPCODE_MASK_WIDEN(OP): \
3779 case CASE_RVV_OPCODE_MASK_LMUL(OP, M8)
3781#define CASE_RVV_OPCODE_WIDEN(OP) \
3782 CASE_RVV_OPCODE_UNMASK_WIDEN(OP): \
3783 case CASE_RVV_OPCODE_MASK_WIDEN(OP)
3785#define CASE_RVV_OPCODE(OP) \
3786 CASE_RVV_OPCODE_UNMASK(OP): \
3787 case CASE_RVV_OPCODE_MASK(OP)
3791#define CASE_VMA_OPCODE_COMMON(OP, TYPE, LMUL) \
3792 RISCV::PseudoV##OP##_##TYPE##_##LMUL
3794#define CASE_VMA_OPCODE_LMULS(OP, TYPE) \
3795 CASE_VMA_OPCODE_COMMON(OP, TYPE, MF8): \
3796 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF4): \
3797 case CASE_VMA_OPCODE_COMMON(OP, TYPE, MF2): \
3798 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M1): \
3799 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M2): \
3800 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M4): \
3801 case CASE_VMA_OPCODE_COMMON(OP, TYPE, M8)
3804#define CASE_VFMA_OPCODE_COMMON(OP, TYPE, LMUL, SEW) \
3805 RISCV::PseudoV##OP##_##TYPE##_##LMUL##_##SEW
3807#define CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW) \
3808 CASE_VFMA_OPCODE_COMMON(OP, TYPE, M1, SEW): \
3809 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M2, SEW): \
3810 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M4, SEW): \
3811 case CASE_VFMA_OPCODE_COMMON(OP, TYPE, M8, SEW)
3813#define CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW) \
3814 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF2, SEW): \
3815 case CASE_VFMA_OPCODE_LMULS_M1(OP, TYPE, SEW)
3817#define CASE_VFMA_OPCODE_LMULS_MF4(OP, TYPE, SEW) \
3818 CASE_VFMA_OPCODE_COMMON(OP, TYPE, MF4, SEW): \
3819 case CASE_VFMA_OPCODE_LMULS_MF2(OP, TYPE, SEW)
3821#define CASE_VFMA_OPCODE_VV(OP) \
3822 CASE_VFMA_OPCODE_LMULS_MF4(OP, VV, E16): \
3823 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VV, E16): \
3824 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VV, E32): \
3825 case CASE_VFMA_OPCODE_LMULS_M1(OP, VV, E64)
3827#define CASE_VFMA_SPLATS(OP) \
3828 CASE_VFMA_OPCODE_LMULS_MF4(OP, VFPR16, E16): \
3829 case CASE_VFMA_OPCODE_LMULS_MF4(OP##_ALT, VFPR16, E16): \
3830 case CASE_VFMA_OPCODE_LMULS_MF2(OP, VFPR32, E32): \
3831 case CASE_VFMA_OPCODE_LMULS_M1(OP, VFPR64, E64)
3835 unsigned &SrcOpIdx1,
3836 unsigned &SrcOpIdx2)
const {
3838 if (!
Desc.isCommutable())
3841 switch (
MI.getOpcode()) {
3842 case RISCV::TH_MVEQZ:
3843 case RISCV::TH_MVNEZ:
3847 if (
MI.getOperand(2).getReg() == RISCV::X0)
3850 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
3851 case RISCV::QC_SELECTIEQ:
3852 case RISCV::QC_SELECTINE:
3853 case RISCV::QC_SELECTIIEQ:
3854 case RISCV::QC_SELECTIINE:
3855 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
3856 case RISCV::QC_MVEQ:
3857 case RISCV::QC_MVNE:
3858 case RISCV::QC_MVLT:
3859 case RISCV::QC_MVGE:
3860 case RISCV::QC_MVLTU:
3861 case RISCV::QC_MVGEU:
3862 case RISCV::QC_MVEQI:
3863 case RISCV::QC_MVNEI:
3864 case RISCV::QC_MVLTI:
3865 case RISCV::QC_MVGEI:
3866 case RISCV::QC_MVLTUI:
3867 case RISCV::QC_MVGEUI:
3868 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 4);
3869 case RISCV::TH_MULA:
3870 case RISCV::TH_MULAW:
3871 case RISCV::TH_MULAH:
3872 case RISCV::TH_MULS:
3873 case RISCV::TH_MULSW:
3874 case RISCV::TH_MULSH:
3876 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
3877 case RISCV::PseudoCCMOVGPRNoX0:
3878 case RISCV::PseudoCCMOVGPR:
3880 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
3907 return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
3934 unsigned CommutableOpIdx1 = 1;
3935 unsigned CommutableOpIdx2 = 3;
3936 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
3957 if (SrcOpIdx1 != CommuteAnyOperandIndex && SrcOpIdx1 > 3)
3959 if (SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx2 > 3)
3963 if (SrcOpIdx1 != CommuteAnyOperandIndex &&
3964 SrcOpIdx2 != CommuteAnyOperandIndex && SrcOpIdx1 != 1 && SrcOpIdx2 != 1)
3970 if (SrcOpIdx1 == CommuteAnyOperandIndex ||
3971 SrcOpIdx2 == CommuteAnyOperandIndex) {
3974 unsigned CommutableOpIdx1 = SrcOpIdx1;
3975 if (SrcOpIdx1 == SrcOpIdx2) {
3978 CommutableOpIdx1 = 1;
3979 }
else if (SrcOpIdx1 == CommuteAnyOperandIndex) {
3981 CommutableOpIdx1 = SrcOpIdx2;
3986 unsigned CommutableOpIdx2;
3987 if (CommutableOpIdx1 != 1) {
3989 CommutableOpIdx2 = 1;
3991 Register Op1Reg =
MI.getOperand(CommutableOpIdx1).getReg();
3996 if (Op1Reg !=
MI.getOperand(2).getReg())
3997 CommutableOpIdx2 = 2;
3999 CommutableOpIdx2 = 3;
4004 if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, CommutableOpIdx1,
4017#define CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL) \
4018 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL: \
4019 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL; \
4022#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE) \
4023 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF8) \
4024 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4) \
4025 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2) \
4026 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1) \
4027 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2) \
4028 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4) \
4029 CASE_VMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8)
4032#define CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, LMUL, SEW) \
4033 case RISCV::PseudoV##OLDOP##_##TYPE##_##LMUL##_##SEW: \
4034 Opc = RISCV::PseudoV##NEWOP##_##TYPE##_##LMUL##_##SEW; \
4037#define CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW) \
4038 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M1, SEW) \
4039 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M2, SEW) \
4040 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M4, SEW) \
4041 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, M8, SEW)
4043#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW) \
4044 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF2, SEW) \
4045 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, TYPE, SEW)
4047#define CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, TYPE, SEW) \
4048 CASE_VFMA_CHANGE_OPCODE_COMMON(OLDOP, NEWOP, TYPE, MF4, SEW) \
4049 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, TYPE, SEW)
4051#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP) \
4052 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VV, E16) \
4053 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VV, E16) \
4054 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VV, E32) \
4055 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VV, E64)
4057#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP) \
4058 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP, NEWOP, VFPR16, E16) \
4059 CASE_VFMA_CHANGE_OPCODE_LMULS_MF4(OLDOP##_ALT, NEWOP##_ALT, VFPR16, E16) \
4060 CASE_VFMA_CHANGE_OPCODE_LMULS_MF2(OLDOP, NEWOP, VFPR32, E32) \
4061 CASE_VFMA_CHANGE_OPCODE_LMULS_M1(OLDOP, NEWOP, VFPR64, E64)
4067 unsigned OpIdx2)
const {
4070 return *
MI.getParent()->getParent()->CloneMachineInstr(&
MI);
4074 switch (
MI.getOpcode()) {
4075 case RISCV::TH_MVEQZ:
4076 case RISCV::TH_MVNEZ: {
4077 auto &WorkingMI = cloneIfNew(
MI);
4078 WorkingMI.setDesc(
get(
MI.getOpcode() == RISCV::TH_MVEQZ ? RISCV::TH_MVNEZ
4079 : RISCV::TH_MVEQZ));
4083 case RISCV::QC_SELECTIEQ:
4084 case RISCV::QC_SELECTINE:
4085 case RISCV::QC_SELECTIIEQ:
4086 case RISCV::QC_SELECTIINE:
4088 case RISCV::QC_MVEQ:
4089 case RISCV::QC_MVNE:
4090 case RISCV::QC_MVLT:
4091 case RISCV::QC_MVGE:
4092 case RISCV::QC_MVLTU:
4093 case RISCV::QC_MVGEU:
4094 case RISCV::QC_MVEQI:
4095 case RISCV::QC_MVNEI:
4096 case RISCV::QC_MVLTI:
4097 case RISCV::QC_MVGEI:
4098 case RISCV::QC_MVLTUI:
4099 case RISCV::QC_MVGEUI: {
4100 auto &WorkingMI = cloneIfNew(
MI);
4105 case RISCV::PseudoCCMOVGPRNoX0:
4106 case RISCV::PseudoCCMOVGPR: {
4110 auto &WorkingMI = cloneIfNew(
MI);
4111 WorkingMI.getOperand(3).setImm(CC);
4135 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4136 assert((OpIdx1 == 3 || OpIdx2 == 3) &&
"Unexpected opcode index");
4138 switch (
MI.getOpcode()) {
4161 auto &WorkingMI = cloneIfNew(
MI);
4162 WorkingMI.setDesc(
get(
Opc));
4172 assert((OpIdx1 == 1 || OpIdx2 == 1) &&
"Unexpected opcode index");
4175 if (OpIdx1 == 3 || OpIdx2 == 3) {
4177 switch (
MI.getOpcode()) {
4188 auto &WorkingMI = cloneIfNew(
MI);
4189 WorkingMI.setDesc(
get(
Opc));
4201#undef CASE_VMA_CHANGE_OPCODE_COMMON
4202#undef CASE_VMA_CHANGE_OPCODE_LMULS
4203#undef CASE_VFMA_CHANGE_OPCODE_COMMON
4204#undef CASE_VFMA_CHANGE_OPCODE_LMULS_M1
4205#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF2
4206#undef CASE_VFMA_CHANGE_OPCODE_LMULS_MF4
4207#undef CASE_VFMA_CHANGE_OPCODE_VV
4208#undef CASE_VFMA_CHANGE_OPCODE_SPLATS
4210#undef CASE_RVV_OPCODE_UNMASK_LMUL
4211#undef CASE_RVV_OPCODE_MASK_LMUL
4212#undef CASE_RVV_OPCODE_LMUL
4213#undef CASE_RVV_OPCODE_UNMASK_WIDEN
4214#undef CASE_RVV_OPCODE_UNMASK
4215#undef CASE_RVV_OPCODE_MASK_WIDEN
4216#undef CASE_RVV_OPCODE_MASK
4217#undef CASE_RVV_OPCODE_WIDEN
4218#undef CASE_RVV_OPCODE
4220#undef CASE_VMA_OPCODE_COMMON
4221#undef CASE_VMA_OPCODE_LMULS
4222#undef CASE_VFMA_OPCODE_COMMON
4223#undef CASE_VFMA_OPCODE_LMULS_M1
4224#undef CASE_VFMA_OPCODE_LMULS_MF2
4225#undef CASE_VFMA_OPCODE_LMULS_MF4
4226#undef CASE_VFMA_OPCODE_VV
4227#undef CASE_VFMA_SPLATS
4230 switch (
MI.getOpcode()) {
4238 if (
MI.getOperand(1).getReg() == RISCV::X0)
4239 commuteInstruction(
MI);
4241 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4242 MI.getOperand(2).ChangeToImmediate(0);
4243 MI.setDesc(
get(RISCV::ADDI));
4247 if (
MI.getOpcode() == RISCV::XOR &&
4248 MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4249 MI.getOperand(1).setReg(RISCV::X0);
4250 MI.getOperand(2).ChangeToImmediate(0);
4251 MI.setDesc(
get(RISCV::ADDI));
4258 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4259 MI.setDesc(
get(RISCV::ADDI));
4265 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4266 MI.getOperand(2).ChangeToImmediate(0);
4267 MI.setDesc(
get(RISCV::ADDI));
4273 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4274 MI.getOperand(2).ChangeToImmediate(0);
4275 MI.setDesc(
get(RISCV::ADDIW));
4282 if (
MI.getOperand(1).getReg() == RISCV::X0)
4283 commuteInstruction(
MI);
4285 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4286 MI.getOperand(2).ChangeToImmediate(0);
4287 MI.setDesc(
get(RISCV::ADDIW));
4292 case RISCV::SH1ADD_UW:
4294 case RISCV::SH2ADD_UW:
4296 case RISCV::SH3ADD_UW:
4298 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4299 MI.removeOperand(1);
4301 MI.setDesc(
get(RISCV::ADDI));
4305 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4306 MI.removeOperand(2);
4307 unsigned Opc =
MI.getOpcode();
4308 if (
Opc == RISCV::SH1ADD_UW ||
Opc == RISCV::SH2ADD_UW ||
4309 Opc == RISCV::SH3ADD_UW) {
4311 MI.setDesc(
get(RISCV::SLLI_UW));
4315 MI.setDesc(
get(RISCV::SLLI));
4329 if (
MI.getOperand(1).getReg() == RISCV::X0 ||
4330 MI.getOperand(2).getReg() == RISCV::X0) {
4331 MI.getOperand(1).setReg(RISCV::X0);
4332 MI.getOperand(2).ChangeToImmediate(0);
4333 MI.setDesc(
get(RISCV::ADDI));
4339 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4340 MI.getOperand(2).setImm(0);
4341 MI.setDesc(
get(RISCV::ADDI));
4349 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4350 MI.getOperand(2).ChangeToImmediate(0);
4351 MI.setDesc(
get(RISCV::ADDI));
4355 if (
MI.getOperand(2).getReg() == RISCV::X0) {
4356 MI.getOperand(2).ChangeToImmediate(0);
4357 MI.setDesc(
get(RISCV::ADDI));
4365 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4366 MI.getOperand(2).ChangeToImmediate(0);
4367 MI.setDesc(
get(RISCV::ADDI));
4377 case RISCV::SLLI_UW:
4379 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4380 MI.getOperand(2).setImm(0);
4381 MI.setDesc(
get(RISCV::ADDI));
4389 if (
MI.getOperand(1).getReg() == RISCV::X0 &&
4390 MI.getOperand(2).getReg() == RISCV::X0) {
4391 MI.getOperand(2).ChangeToImmediate(0);
4392 MI.setDesc(
get(RISCV::ADDI));
4396 if (
MI.getOpcode() == RISCV::ADD_UW &&
4397 MI.getOperand(1).getReg() == RISCV::X0) {
4398 MI.removeOperand(1);
4400 MI.setDesc(
get(RISCV::ADDI));
4406 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4407 MI.getOperand(2).setImm(
MI.getOperand(2).getImm() != 0);
4408 MI.setDesc(
get(RISCV::ADDI));
4414 case RISCV::ZEXT_H_RV32:
4415 case RISCV::ZEXT_H_RV64:
4418 if (
MI.getOperand(1).getReg() == RISCV::X0) {
4420 MI.setDesc(
get(RISCV::ADDI));
4429 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
4430 MI.getOperand(2).ChangeToImmediate(0);
4431 MI.setDesc(
get(RISCV::ADDI));
4438 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4440 MI.removeOperand(0);
4441 MI.insert(
MI.operands_begin() + 1, {MO0});
4446 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4448 MI.removeOperand(0);
4449 MI.insert(
MI.operands_begin() + 1, {MO0});
4450 MI.setDesc(
get(RISCV::BNE));
4455 if (
MI.getOperand(0).getReg() == RISCV::X0) {
4457 MI.removeOperand(0);
4458 MI.insert(
MI.operands_begin() + 1, {MO0});
4459 MI.setDesc(
get(RISCV::BEQ));
4467#define CASE_WIDEOP_OPCODE_COMMON(OP, LMUL) \
4468 RISCV::PseudoV##OP##_##LMUL##_TIED
4470#define CASE_WIDEOP_OPCODE_LMULS(OP) \
4471 CASE_WIDEOP_OPCODE_COMMON(OP, MF8): \
4472 case CASE_WIDEOP_OPCODE_COMMON(OP, MF4): \
4473 case CASE_WIDEOP_OPCODE_COMMON(OP, MF2): \
4474 case CASE_WIDEOP_OPCODE_COMMON(OP, M1): \
4475 case CASE_WIDEOP_OPCODE_COMMON(OP, M2): \
4476 case CASE_WIDEOP_OPCODE_COMMON(OP, M4)
4478#define CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL) \
4479 case RISCV::PseudoV##OP##_##LMUL##_TIED: \
4480 NewOpc = RISCV::PseudoV##OP##_##LMUL; \
4483#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4484 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF8) \
4485 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4) \
4486 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2) \
4487 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1) \
4488 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2) \
4489 CASE_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4)
4492#define CASE_FP_WIDEOP_OPCODE_COMMON(OP, LMUL, SEW) \
4493 RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED
4495#define CASE_FP_WIDEOP_OPCODE_LMULS(OP) \
4496 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4497 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4498 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E32): \
4499 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4500 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E32): \
4501 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4502 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E32): \
4503 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16): \
4504 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E32) \
4506#define CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, LMUL, SEW) \
4507 case RISCV::PseudoV##OP##_##LMUL##_##SEW##_TIED: \
4508 NewOpc = RISCV::PseudoV##OP##_##LMUL##_##SEW; \
4511#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP) \
4512 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4513 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4514 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E32) \
4515 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
4516 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E32) \
4517 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
4518 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E32) \
4519 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16) \
4520 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E32) \
4522#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP) \
4523 CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF4, E16): \
4524 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, MF2, E16): \
4525 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M1, E16): \
4526 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M2, E16): \
4527 case CASE_FP_WIDEOP_OPCODE_COMMON(OP, M4, E16)
4529#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP) \
4530 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF4, E16) \
4531 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, MF2, E16) \
4532 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M1, E16) \
4533 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M2, E16) \
4534 CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON(OP, M4, E16)
4541 switch (
MI.getOpcode()) {
4549 MI.getNumExplicitOperands() == 7 &&
4550 "Expect 7 explicit operands rd, rs2, rs1, rm, vl, sew, policy");
4557 switch (
MI.getOpcode()) {
4569 .
add(
MI.getOperand(0))
4571 .
add(
MI.getOperand(1))
4572 .
add(
MI.getOperand(2))
4573 .
add(
MI.getOperand(3))
4574 .
add(
MI.getOperand(4))
4575 .
add(
MI.getOperand(5))
4576 .
add(
MI.getOperand(6));
4585 MI.getNumExplicitOperands() == 6);
4592 switch (
MI.getOpcode()) {
4604 .
add(
MI.getOperand(0))
4606 .
add(
MI.getOperand(1))
4607 .
add(
MI.getOperand(2))
4608 .
add(
MI.getOperand(3))
4609 .
add(
MI.getOperand(4))
4610 .
add(
MI.getOperand(5));
4617 unsigned NumOps =
MI.getNumOperands();
4620 if (
Op.isReg() &&
Op.isKill())
4628 if (
MI.getOperand(0).isEarlyClobber()) {
4642#undef CASE_WIDEOP_OPCODE_COMMON
4643#undef CASE_WIDEOP_OPCODE_LMULS
4644#undef CASE_WIDEOP_CHANGE_OPCODE_COMMON
4645#undef CASE_WIDEOP_CHANGE_OPCODE_LMULS
4646#undef CASE_FP_WIDEOP_OPCODE_COMMON
4647#undef CASE_FP_WIDEOP_OPCODE_LMULS
4648#undef CASE_FP_WIDEOP_CHANGE_OPCODE_COMMON
4649#undef CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS
4658 if (ShiftAmount == 0)
4664 }
else if (
int ShXAmount, ShiftAmount;
4666 (ShXAmount =
isShifted359(Amount, ShiftAmount)) != 0) {
4669 switch (ShXAmount) {
4671 Opc = RISCV::SH1ADD;
4674 Opc = RISCV::SH2ADD;
4677 Opc = RISCV::SH3ADD;
4692 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
4703 Register ScaledRegister =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
4713 }
else if (
STI.hasStdExtZmmul()) {
4714 Register N =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
4723 for (
uint32_t ShiftAmount = 0; Amount >> ShiftAmount; ShiftAmount++) {
4724 if (Amount & (1U << ShiftAmount)) {
4728 .
addImm(ShiftAmount - PrevShiftAmount)
4730 if (Amount >> (ShiftAmount + 1)) {
4733 Acc =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
4744 PrevShiftAmount = ShiftAmount;
4747 assert(Acc &&
"Expected valid accumulator");
4757 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
4765 ?
STI.getTailDupAggressiveThreshold()
4772 unsigned Opcode =
MI.getOpcode();
4773 if (!RISCVVPseudosTable::getPseudoInfo(Opcode) &&
4779std::optional<std::pair<unsigned, unsigned>>
4783 return std::nullopt;
4784 case RISCV::PseudoVSPILL2_M1:
4785 case RISCV::PseudoVRELOAD2_M1:
4786 return std::make_pair(2u, 1u);
4787 case RISCV::PseudoVSPILL2_M2:
4788 case RISCV::PseudoVRELOAD2_M2:
4789 return std::make_pair(2u, 2u);
4790 case RISCV::PseudoVSPILL2_M4:
4791 case RISCV::PseudoVRELOAD2_M4:
4792 return std::make_pair(2u, 4u);
4793 case RISCV::PseudoVSPILL3_M1:
4794 case RISCV::PseudoVRELOAD3_M1:
4795 return std::make_pair(3u, 1u);
4796 case RISCV::PseudoVSPILL3_M2:
4797 case RISCV::PseudoVRELOAD3_M2:
4798 return std::make_pair(3u, 2u);
4799 case RISCV::PseudoVSPILL4_M1:
4800 case RISCV::PseudoVRELOAD4_M1:
4801 return std::make_pair(4u, 1u);
4802 case RISCV::PseudoVSPILL4_M2:
4803 case RISCV::PseudoVRELOAD4_M2:
4804 return std::make_pair(4u, 2u);
4805 case RISCV::PseudoVSPILL5_M1:
4806 case RISCV::PseudoVRELOAD5_M1:
4807 return std::make_pair(5u, 1u);
4808 case RISCV::PseudoVSPILL6_M1:
4809 case RISCV::PseudoVRELOAD6_M1:
4810 return std::make_pair(6u, 1u);
4811 case RISCV::PseudoVSPILL7_M1:
4812 case RISCV::PseudoVRELOAD7_M1:
4813 return std::make_pair(7u, 1u);
4814 case RISCV::PseudoVSPILL8_M1:
4815 case RISCV::PseudoVRELOAD8_M1:
4816 return std::make_pair(8u, 1u);
4821 int16_t MI1FrmOpIdx =
4822 RISCV::getNamedOperandIdx(MI1.
getOpcode(), RISCV::OpName::frm);
4823 int16_t MI2FrmOpIdx =
4824 RISCV::getNamedOperandIdx(MI2.
getOpcode(), RISCV::OpName::frm);
4825 if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0)
4832std::optional<unsigned>
4836 return std::nullopt;
4839 case RISCV::VSLL_VX:
4840 case RISCV::VSRL_VX:
4841 case RISCV::VSRA_VX:
4843 case RISCV::VSSRL_VX:
4844 case RISCV::VSSRA_VX:
4846 case RISCV::VROL_VX:
4847 case RISCV::VROR_VX:
4852 case RISCV::VNSRL_WX:
4853 case RISCV::VNSRA_WX:
4855 case RISCV::VNCLIPU_WX:
4856 case RISCV::VNCLIP_WX:
4858 case RISCV::VWSLL_VX:
4863 case RISCV::VADD_VX:
4864 case RISCV::VSUB_VX:
4865 case RISCV::VRSUB_VX:
4867 case RISCV::VWADDU_VX:
4868 case RISCV::VWSUBU_VX:
4869 case RISCV::VWADD_VX:
4870 case RISCV::VWSUB_VX:
4871 case RISCV::VWADDU_WX:
4872 case RISCV::VWSUBU_WX:
4873 case RISCV::VWADD_WX:
4874 case RISCV::VWSUB_WX:
4876 case RISCV::VADC_VXM:
4877 case RISCV::VADC_VIM:
4878 case RISCV::VMADC_VXM:
4879 case RISCV::VMADC_VIM:
4880 case RISCV::VMADC_VX:
4881 case RISCV::VSBC_VXM:
4882 case RISCV::VMSBC_VXM:
4883 case RISCV::VMSBC_VX:
4885 case RISCV::VAND_VX:
4887 case RISCV::VXOR_VX:
4889 case RISCV::VMSEQ_VX:
4890 case RISCV::VMSNE_VX:
4891 case RISCV::VMSLTU_VX:
4892 case RISCV::VMSLT_VX:
4893 case RISCV::VMSLEU_VX:
4894 case RISCV::VMSLE_VX:
4895 case RISCV::VMSGTU_VX:
4896 case RISCV::VMSGT_VX:
4898 case RISCV::VMINU_VX:
4899 case RISCV::VMIN_VX:
4900 case RISCV::VMAXU_VX:
4901 case RISCV::VMAX_VX:
4903 case RISCV::VMUL_VX:
4904 case RISCV::VMULH_VX:
4905 case RISCV::VMULHU_VX:
4906 case RISCV::VMULHSU_VX:
4908 case RISCV::VDIVU_VX:
4909 case RISCV::VDIV_VX:
4910 case RISCV::VREMU_VX:
4911 case RISCV::VREM_VX:
4913 case RISCV::VWMUL_VX:
4914 case RISCV::VWMULU_VX:
4915 case RISCV::VWMULSU_VX:
4917 case RISCV::VMACC_VX:
4918 case RISCV::VNMSAC_VX:
4919 case RISCV::VMADD_VX:
4920 case RISCV::VNMSUB_VX:
4922 case RISCV::VWMACCU_VX:
4923 case RISCV::VWMACC_VX:
4924 case RISCV::VWMACCSU_VX:
4925 case RISCV::VWMACCUS_VX:
4927 case RISCV::VMERGE_VXM:
4929 case RISCV::VMV_V_X:
4931 case RISCV::VSADDU_VX:
4932 case RISCV::VSADD_VX:
4933 case RISCV::VSSUBU_VX:
4934 case RISCV::VSSUB_VX:
4936 case RISCV::VAADDU_VX:
4937 case RISCV::VAADD_VX:
4938 case RISCV::VASUBU_VX:
4939 case RISCV::VASUB_VX:
4941 case RISCV::VSMUL_VX:
4943 case RISCV::VMV_S_X:
4945 case RISCV::VANDN_VX:
4946 return 1U << Log2SEW;
4952 RISCVVPseudosTable::getPseudoInfo(RVVPseudoOpcode);
4955 return RVV->BaseInstr;
4965 unsigned Scaled = Log2SEW + (DestEEW - 1);
4979 return std::nullopt;
4984 assert((LHS.isImm() || LHS.getParent()->getMF()->getRegInfo().isSSA()) &&
4985 (RHS.isImm() || RHS.getParent()->getMF()->getRegInfo().isSSA()));
4986 if (LHS.isReg() && RHS.isReg() && LHS.getReg().isVirtual() &&
4987 LHS.getReg() == RHS.getReg())
4991 if (LHS.isImm() && LHS.getImm() == 0)
4997 if (!LHSImm || !RHSImm)
4999 return LHSImm <= RHSImm;
5011 : LHS(LHS), RHS(RHS),
Cond(
Cond.begin(),
Cond.end()) {}
5013 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
5023 std::optional<bool> createTripCountGreaterCondition(
5024 int TC, MachineBasicBlock &
MBB,
5025 SmallVectorImpl<MachineOperand> &CondParam)
override {
5033 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
5035 void adjustTripCount(
int TripCountAdjust)
override {}
5039std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
5047 if (
TBB == LoopBB && FBB == LoopBB)
5054 assert((
TBB == LoopBB || FBB == LoopBB) &&
5055 "The Loop must be a single-basic-block loop");
5066 if (!Reg.isVirtual())
5068 return MRI.getVRegDef(Reg);
5073 if (LHS && LHS->isPHI())
5075 if (RHS && RHS->isPHI())
5078 return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS,
Cond);
5084 Opc = RVVMCOpcode ? RVVMCOpcode :
Opc;
5101 case RISCV::FDIV_H_INX:
5102 case RISCV::FDIV_S_INX:
5103 case RISCV::FDIV_D_INX:
5104 case RISCV::FDIV_D_IN32X:
5105 case RISCV::FSQRT_H:
5106 case RISCV::FSQRT_S:
5107 case RISCV::FSQRT_D:
5108 case RISCV::FSQRT_H_INX:
5109 case RISCV::FSQRT_S_INX:
5110 case RISCV::FSQRT_D_INX:
5111 case RISCV::FSQRT_D_IN32X:
5113 case RISCV::VDIV_VV:
5114 case RISCV::VDIV_VX:
5115 case RISCV::VDIVU_VV:
5116 case RISCV::VDIVU_VX:
5117 case RISCV::VREM_VV:
5118 case RISCV::VREM_VX:
5119 case RISCV::VREMU_VV:
5120 case RISCV::VREMU_VX:
5122 case RISCV::VFDIV_VV:
5123 case RISCV::VFDIV_VF:
5124 case RISCV::VFRDIV_VF:
5125 case RISCV::VFSQRT_V:
5126 case RISCV::VFRSQRT7_V:
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
SmallVector< int16_t, MAX_SRC_OPERANDS_NUM > OperandIndices
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static bool cannotInsertTailCall(const MachineBasicBlock &MBB)
#define CASE_VFMA_CHANGE_OPCODE_SPLATS(OLDOP, NEWOP)
#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS_ALT(OP)
#define CASE_FP_WIDEOP_OPCODE_LMULS(OP)
#define CASE_OPERAND_SIMM(NUM)
static std::optional< unsigned > getLMULForRVVWholeLoadStore(unsigned Opcode)
#define CASE_VFMA_CHANGE_OPCODE_VV(OLDOP, NEWOP)
static bool analyzeCandidate(outliner::Candidate &C)
static unsigned getFPFusedMultiplyOpcode(unsigned RootOpc, unsigned Pattern)
std::optional< unsigned > getFoldedOpcode(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, const RISCVSubtarget &ST)
#define RVV_OPC_LMUL_CASE(OPC, INV)
#define CASE_FP_WIDEOP_CHANGE_OPCODE_LMULS(OP)
static void combineFPFusedMultiply(MachineInstr &Root, MachineInstr &Prev, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs)
static unsigned getAddendOperandIdx(unsigned Pattern)
#define CASE_RVV_OPCODE_UNMASK(OP)
#define CASE_WIDEOP_CHANGE_OPCODE_LMULS(OP)
static cl::opt< bool > PreferWholeRegisterMove("riscv-prefer-whole-register-move", cl::init(false), cl::Hidden, cl::desc("Prefer whole register move for vector registers."))
#define CASE_VFMA_SPLATS(OP)
unsigned getPredicatedOpcode(unsigned Opcode)
#define CASE_FP_WIDEOP_OPCODE_LMULS_ALT(OP)
#define CASE_WIDEOP_OPCODE_LMULS(OP)
static bool isMIReadsReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
#define OPCODE_LMUL_MASK_CASE(OPC)
static bool isFSUB(unsigned Opc)
#define CASE_VMA_CHANGE_OPCODE_LMULS(OLDOP, NEWOP, TYPE)
#define CASE_RVV_OPCODE(OP)
static std::optional< int64_t > getEffectiveImm(const MachineOperand &MO)
#define CASE_VFMA_OPCODE_VV(OP)
MachineOutlinerConstructionID
#define CASE_RVV_OPCODE_WIDEN(OP)
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 bool canCombineShiftIntoShXAdd(const MachineBasicBlock &MBB, const MachineOperand &MO, unsigned OuterShiftAmt)
Utility routine that checks if.
static bool isCandidatePatchable(const MachineBasicBlock &MBB)
static bool isFADD(unsigned Opc)
static void genShXAddAddShift(MachineInstr &Root, unsigned AddOpIdx, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
static bool isLoadImm(const MachineInstr *MI, int64_t &Imm)
static bool isMIModifiesReg(const MachineInstr &MI, const TargetRegisterInfo *TRI, MCRegister RegNo)
static bool canCombineFPFusedMultiply(const MachineInstr &Root, const MachineOperand &MO, bool DoRegPressureReduce)
static bool getSHXADDPatterns(const MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getFPFusedMultiplyPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce)
static cl::opt< MachineTraceStrategy > ForceMachineCombinerStrategy("riscv-force-machine-combiner-strategy", cl::Hidden, cl::desc("Force machine combiner to use a specific strategy for machine " "trace metrics evaluation."), cl::init(MachineTraceStrategy::TS_NumStrategies), cl::values(clEnumValN(MachineTraceStrategy::TS_Local, "local", "Local strategy."), clEnumValN(MachineTraceStrategy::TS_MinInstrCount, "min-instr", "MinInstrCount strategy.")))
static unsigned getSHXADDShiftAmount(unsigned Opc)
#define CASE_RVV_OPCODE_MASK(OP)
#define RVV_OPC_LMUL_MASK_CASE(OPC, INV)
static MachineInstr * canFoldAsPredicatedOp(Register Reg, const MachineRegisterInfo &MRI, const TargetInstrInfo *TII, const RISCVSubtarget &STI)
Identify instructions that can be folded into a CCMOV instruction, and return the defining instructio...
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
static LLVM_ABI DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
Attempts to merge LocA and LocB into a single location; see DebugLoc::getMergedLocation for more deta...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LiveInterval - This class represents the liveness of a register, or stack slot.
LiveInterval & getInterval(Register Reg)
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
const Segment * getSegmentContaining(SlotIndex Idx) const
Return the segment that contains the specified index, or null if there is none.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
This holds information about one operand of a machine instruction, indicating the register class for ...
Wrapper class representing physical registers. Should be passed by value.
const FeatureBitset & getFeatureBits() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineInstrBundleIterator< const MachineInstr, true > const_reverse_iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setStackID(int ObjectIdx, uint8_t ID)
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
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
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
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.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
A description of a memory reference used in the backend.
bool isNonTemporal() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
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
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg) const override
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags, bool DstRenamable=false, bool DstIsDead=false) const
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
void mulImm(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const
Generate code to multiply the value in DestReg by Amt - handles all the common optimizations for this...
static bool isPairableLdStInstOpc(unsigned Opc)
Return true if pairing the given load or store may be paired with another.
RISCVInstrInfo(const RISCVSubtarget &STI)
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 canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, LocationSize &Width, const TargetRegisterInfo *TRI) const
unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override
void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const override
const RISCVSubtarget & STI
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
std::optional< unsigned > getInverseOpcode(unsigned Opcode) const override
bool simplifyInstruction(MachineInstr &MI) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MBBI, unsigned Flags) const override
MachineTraceStrategy getMachineCombinerTraceStrategy() const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MCInst getNop() const override
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
void finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc)
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
bool analyzeSelect(const MachineInstr &MI, SmallVectorImpl< MachineOperand > &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const override
static bool isFromLoadImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, int64_t &Imm)
Return true if the operand is a load immediate instruction and sets Imm to the immediate value.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
int getBranchRelaxationScratchFrameIndex() const
const RISCVRegisterInfo * getRegisterInfo() const override
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
StringRef - Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const
Returns true iff the routine could find two commutable operands in the given machine instruction.
virtual bool hasReassociableOperands(const MachineInstr &Inst, const MachineBasicBlock *MBB) const
Return true when \P Inst has reassociable operands in the same \P MBB.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const
Optional target hook that returns true if MBB is safe to outline from, and returns any target-specifi...
virtual void getReassociateOperandIndices(const MachineInstr &Root, unsigned Pattern, std::array< unsigned, 5 > &OperandIndices) const
The returned array encodes the operand index for each parameter because the operands may be commuted;...
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const
Return true when \P Inst has reassociable sibling.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
const uint8_t TSFlags
Configurable target specific flags.
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)
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
CondCode getInverseBranchCondition(CondCode)
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static bool isValidRoundingMode(unsigned Mode)
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 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
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)
LLVM_ABI void printVType(unsigned VType, raw_ostream &OS)
static bool isValidXSfmmVType(unsigned VTypeI)
static unsigned getSEW(unsigned VType)
static VLMUL getVLMUL(unsigned VType)
bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2)
bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS)
Given two VL operands, do we know that LHS <= RHS?
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
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
MachineTraceStrategy
Strategies for selecting traces.
@ TS_MinInstrCount
Select the trace through a block that has the fewest instructions.
@ TS_Local
Select the trace that contains only the current basic block.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
static const MachineMemOperand::Flags MONontemporalBit0
unsigned getDeadRegState(bool B)
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)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
int isShifted359(T Value, int &Shift)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
unsigned getKillRegState(bool B)
unsigned getRenamableRegState(bool B)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
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.